| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf8 -*-
2 """Medication handling code.
3
4 license: GPL
5 """
6 #============================================================
7 __version__ = "$Revision: 1.21 $"
8 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
9
10 import sys, logging, csv, codecs, os, re as regex, subprocess
11
12
13 if __name__ == '__main__':
14 sys.path.insert(0, '../../')
15 from Gnumed.pycommon import gmBusinessDBObject, gmPG2, gmShellAPI, gmTools
16 from Gnumed.pycommon import gmDispatcher, gmDateTime, gmHooks
17 from Gnumed.business import gmATC, gmAllergy
18
19
20 _log = logging.getLogger('gm.meds')
21 _log.info(__version__)
22
23 #============================================================
25 """Always relates to the active patient."""
26 gmHooks.run_hook_script(hook = u'after_substance_intake_modified')
27
28 gmDispatcher.connect(_on_substance_intake_modified, u'substance_intake_mod_db')
29
30 #============================================================
32
33 if search_term is None:
34 return u'http://www.dosing.de'
35
36 terms = []
37 names = []
38
39 if isinstance(search_term, cBrandedDrug):
40 if search_term['atc_code'] is not None:
41 terms.append(search_term['atc_code'])
42
43 elif isinstance(search_term, cSubstanceIntakeEntry):
44 names.append(search_term['substance'])
45 if search_term['atc_brand'] is not None:
46 terms.append(search_term['atc_brand'])
47 if search_term['atc_substance'] is not None:
48 terms.append(search_term['atc_substance'])
49
50 elif search_term is not None:
51 names.append(u'%s' % search_term)
52 terms.extend(gmATC.text2atc(text = u'%s' % search_term, fuzzy = True))
53
54 for name in names:
55 if name.endswith('e'):
56 terms.append(name[:-1])
57 else:
58 terms.append(name)
59
60 #url_template = u'http://www.google.de/#q=site%%3Adosing.de+%s'
61 #url = url_template % u'+OR+'.join(terms)
62
63 url_template = u'http://www.google.de/search?hl=de&source=hp&q=site%%3Adosing.de+%s&btnG=Google-Suche'
64 url = url_template % u'+OR+'.join(terms)
65
66 _log.debug(u'renal insufficiency URL: %s', url)
67
68 return url
69 #============================================================
70 # this should be in gmCoding.py
71 -def create_data_source(long_name=None, short_name=None, version=None, source=None, language=None):
72
73 args = {
74 'lname': long_name,
75 'sname': short_name,
76 'ver': version,
77 'src': source,
78 'lang': language
79 }
80
81 cmd = u"""select pk from ref.data_source where name_long = %(lname)s and name_short = %(sname)s and version = %(ver)s"""
82 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
83 if len(rows) > 0:
84 return rows[0]['pk']
85
86 cmd = u"""
87 INSERT INTO ref.data_source (name_long, name_short, version, source, lang)
88 VALUES (
89 %(lname)s,
90 %(sname)s,
91 %(ver)s,
92 %(src)s,
93 %(lang)s
94 )
95 returning pk
96 """
97 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
98
99 return rows[0]['pk']
100 #============================================================
101 # wishlist:
102 # - --conf-file= for glwin.exe
103 # - wirkstoff: Konzentration auch in Multiprodukten
104 # - wirkstoff: ATC auch in Multiprodukten
105 # - Suche nach ATC per CLI
106
108 """Iterator over a Gelbe Liste/MMI v8.2 CSV file."""
109
110 version = u'Gelbe Liste/MMI v8.2 CSV file interface'
111 default_transfer_file_windows = r"c:\rezept.txt"
112 #default_encoding = 'cp1252'
113 default_encoding = 'cp1250'
114 csv_fieldnames = [
115 u'name',
116 u'packungsgroesse', # obsolete, use "packungsmenge"
117 u'darreichungsform',
118 u'packungstyp',
119 u'festbetrag',
120 u'avp',
121 u'hersteller',
122 u'rezepttext',
123 u'pzn',
124 u'status_vertrieb',
125 u'status_rezeptpflicht',
126 u'status_fachinfo',
127 u'btm',
128 u'atc',
129 u'anzahl_packungen',
130 u'zuzahlung_pro_packung',
131 u'einheit',
132 u'schedule_morgens',
133 u'schedule_mittags',
134 u'schedule_abends',
135 u'schedule_nachts',
136 u'status_dauermedikament',
137 u'status_hausliste',
138 u'status_negativliste',
139 u'ik_nummer',
140 u'status_rabattvertrag',
141 u'wirkstoffe',
142 u'wirkstoffmenge',
143 u'wirkstoffeinheit',
144 u'wirkstoffmenge_bezug',
145 u'wirkstoffmenge_bezugseinheit',
146 u'status_import',
147 u'status_lifestyle',
148 u'status_ausnahmeliste',
149 u'packungsmenge',
150 u'apothekenpflicht',
151 u'status_billigere_packung',
152 u'rezepttyp',
153 u'besonderes_arzneimittel', # Abstimmungsverfahren SGB-V
154 u't_rezept_pflicht', # Thalidomid-Rezept
155 u'erstattbares_medizinprodukt',
156 u'hilfsmittel',
157 u'hzv_rabattkennung',
158 u'hzv_preis'
159 ]
160 boolean_fields = [
161 u'status_rezeptpflicht',
162 u'status_fachinfo',
163 u'btm',
164 u'status_dauermedikament',
165 u'status_hausliste',
166 u'status_negativliste',
167 u'status_rabattvertrag',
168 u'status_import',
169 u'status_lifestyle',
170 u'status_ausnahmeliste',
171 u'apothekenpflicht',
172 u'status_billigere_packung',
173 u'besonderes_arzneimittel', # Abstimmungsverfahren SGB-V
174 u't_rezept_pflicht',
175 u'erstattbares_medizinprodukt',
176 u'hilfsmittel'
177 ]
178 #--------------------------------------------------------
180
181 _log.info(cGelbeListeCSVFile.version)
182
183 self.filename = filename
184 if filename is None:
185 self.filename = cGelbeListeCSVFile.default_transfer_file_windows
186
187 _log.debug('reading Gelbe Liste/MMI drug data from [%s]', self.filename)
188
189 self.csv_file = codecs.open(filename = filename, mode = 'rUb', encoding = cGelbeListeCSVFile.default_encoding)
190
191 self.csv_lines = gmTools.unicode_csv_reader (
192 self.csv_file,
193 fieldnames = cGelbeListeCSVFile.csv_fieldnames,
194 delimiter = ';',
195 quotechar = '"',
196 dict = True
197 )
198 #--------------------------------------------------------
201 #--------------------------------------------------------
203 line = self.csv_lines.next()
204
205 for field in cGelbeListeCSVFile.boolean_fields:
206 line[field] = (line[field].strip() == u'T')
207
208 # split field "Wirkstoff" by ";"
209 if line['wirkstoffe'].strip() == u'':
210 line['wirkstoffe'] = []
211 else:
212 line['wirkstoffe'] = [ wirkstoff.strip() for wirkstoff in line['wirkstoffe'].split(u';') ]
213
214 return line
215 #--------------------------------------------------------
223 #============================================================
225
226 #--------------------------------------------------------
230 #--------------------------------------------------------
233 #--------------------------------------------------------
236 #--------------------------------------------------------
239 #--------------------------------------------------------
242 #--------------------------------------------------------
245 #--------------------------------------------------------
248 #--------------------------------------------------------
251 #============================================================
253
254 version = u'FreeDiams v0.4.2 interface'
255 default_encoding = 'utf8'
256 default_dob_format = '%Y/%m/%d'
257
258 map_gender2mf = {
259 'm': u'M',
260 'f': u'F',
261 'tf': u'H',
262 'tm': u'H',
263 'h': u'H'
264 }
265 #--------------------------------------------------------
267 cDrugDataSourceInterface.__init__(self)
268 _log.info(cFreeDiamsInterface.version)
269
270 paths = gmTools.gmPaths()
271 self.__gm2fd_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'gm2freediams.xml')
272 self.__fd2gm_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'freediams2gm.xml')
273 self.__fd4gm_config_file = os.path.join(paths.home_dir, '.gnumed', 'freediams4gm.conf')
274
275 self.path_to_binary = None
276 self.__detect_binary()
277 #--------------------------------------------------------
279 # ~/.freediams/config.ini: [License] -> AcceptedVersion=....
280
281 if not self.__detect_binary():
282 return False
283
284 freediams = subprocess.Popen (
285 args = u'--version', # --version or -version or -v
286 executable = self.path_to_binary,
287 stdout = subprocess.PIPE,
288 stderr = subprocess.PIPE,
289 # close_fds = True, # Windows can't do that in conjunction with stdout/stderr = ... :-(
290 universal_newlines = True
291 )
292 data, errors = freediams.communicate()
293 ver = regex.search('FreeDiams\s\d.\d.\d', data).group().split()[1]
294 _log.debug('FreeDiams %s', ver)
295
296 return version
297 #--------------------------------------------------------
299 return create_data_source (
300 long_name = u'"FreeDiams" Drug Database Frontend',
301 short_name = u'FreeDiams',
302 version = self.get_data_source_version(),
303 source = u'http://ericmaeker.fr/FreeMedForms/di-manual/index.html',
304 language = u'fr' # actually to be multi-locale
305 )
306 #--------------------------------------------------------
308 """http://ericmaeker.fr/FreeMedForms/di-manual/en/html/ligne_commandes.html"""
309
310 if not self.__detect_binary():
311 return False
312
313 self.__create_gm2fd_file()
314 open(self.__fd2gm_filename, 'wb').close()
315
316 args = u'--exchange-in="%s"' % (self.__gm2fd_filename)
317
318 cmd = r'%s %s' % (self.path_to_binary, args)
319
320 # if self.patient is not None:
321 # names = self.patient.get_active_name()
322 # args += u' --patientname="%(lastnames)s, %(firstnames)s"' % names
323 # args += u' --patientsurname="%(lastnames)s"' % names
324 # args += u' --gender=%s' % cFreeDiamsInterface.map_gender2mf[self.patient['gender']]
325 # if self.patient['dob'] is not None:
326 # args += u' --dateofbirth=%s' % self.patient['dob'].strftime(cFreeDiamsInterface.default_dob_format)
327
328 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = blocking):
329 _log.error('problem switching to the FreeDiams drug database')
330 return False
331
332 return True
333 #--------------------------------------------------------
335 self.switch_to_frontend()
336 #--------------------------------------------------------
338 """FreeDiams ONLY use CIS.
339
340 CIS stands for Unique Speciality Identifier (eg bisoprolol 5 mg, gel).
341 CIS is AFSSAPS specific, but pharmacist can retreive drug name with the CIS.
342 AFSSAPS is the French FDA.
343
344 CIP stands for Unique Presentation Identifier (eg 30 pills plaq)
345 CIP if you want to specify the packaging of the drug (30 pills
346 thermoformed tablet...) -- actually not really usefull for french
347 doctors.
348 """
349 self.switch_to_frontend()
350 # .external_code_type: u'FR-CIS'
351 # .external_cod: the CIS value
352 #--------------------------------------------------------
354 self.switch_to_frontend()
355 #--------------------------------------------------------
359 #--------------------------------------------------------
360 # internal helpers
361 #--------------------------------------------------------
363
364 if self.path_to_binary is not None:
365 return True
366
367 found, cmd = gmShellAPI.find_first_binary(binaries = [
368 r'/usr/bin/freediams',
369 r'freediams',
370 r'/Applications/FreeDiams.app/Contents/MacOs/FreeDiams',
371 r'c:\programs\freediams\freediams.exe',
372 r'freediams.exe'
373 ])
374
375 if found:
376 self.path_to_binary = cmd
377 return True
378
379 try:
380 self.custom_path_to_binary
381 except AttributeError:
382 _log.error('cannot find FreeDiams binary, no custom path set')
383 return False
384
385 found, cmd = gmShellAPI.detect_external_binary(binary = self.custom_path_to_binary)
386 if found:
387 self.path_to_binary = cmd
388 return True
389
390 _log.error('cannot find FreeDiams binary')
391 return False
392 #--------------------------------------------------------
394
395 xml_file = codecs.open(self.__gm2fd_filename, 'wb', 'utf8')
396 if self.patient is None:
397 xml_file.close()
398 return
399
400 name = self.patient.get_active_name()
401 if self.patient['dob'] is None:
402 dob = u''
403 else:
404 dob = self.patient['dob'].strftime(cFreeDiamsInterface.default_dob_format)
405
406 emr = self.patient.get_emr()
407 allgs = emr.get_allergies() # leave out sensitivities ?
408 atcs = [ a['atc_code'] for a in allgs if a['atc_code'] is not None ]
409 inns = [ a['allergene'] for a in allgs ]
410 # this is rather fragile: FreeDiams won't know what type of UID this is
411 # (but it will assume it is of the type of the drug database in use)
412 uids = [ a['substance_code'] for a in allgs if a['substance_code'] is not None ]
413
414 # Eric says the order of same-level nodes does not matter.
415 xml = u"""<?xml version="1.0" encoding="UTF-8"?>
416
417 <FreeDiams_In version="0.4.2">
418 <EMR name="GNUmed" uid="unused"/>
419 <ConfigFile value="%s"/>
420 <OutFile value="%s" format="html_xml"/>
421 <Ui editmode="select-only" blockPatientDatas="1"/>
422 <Patient>
423 <Identity name="%s" surname="%s" uid="%s" dob="%s" gender="%s"/>
424 <ATCAllergies value="%s"/>
425 <InnAllergies value="%s"/>
426 <DrugsUidAllergies value="%s"/>
427 </Patient>
428 </FreeDiams_In>
429
430 <!--
431 <InnIntolerances value=""/>
432 <ATCIntolerances value="B05B"/>
433 <DrugsUidIntolerances value="68586203;62869109"/>
434 # FIXME: search by LOINC code and add (as soon as supported by FreeDiams ...)
435 <Creatinine value="12" unit="mg/l or mmol/l"/>
436 <Weight value="70" unit="kg or pd" />
437 <Height value="170" unit="cm or "/>
438 <ICD10 value="J11.0;A22;Z23"/>
439 -->
440 """ % (
441 self.__fd4gm_config_file,
442 self.__fd2gm_filename,
443 name['firstnames'], name['lastnames'], self.patient.ID, dob, cFreeDiamsInterface.map_gender2mf[self.patient['gender']],
444 u';'.join(atcs),
445 u';'.join(inns),
446 u';'.join(uids)
447 )
448
449 xml_file = codecs.open(self.__gm2fd_filename, 'wb', 'utf8')
450 xml_file.write(xml)
451 xml_file.close()
452 #--------------------------------------------------------
454
455 # fixed_xml = codecs.open(gmTools.get_unique_filename(suffix = '.xml', 'w', 'utf-8')
456 # for line in self.__fd2gm_filename:
457
458 # fd2gm = codecs.open(self.__fd2gm_filename, 'rU', 'utf-8')
459
460 from xml.etree import ElementTree as etree
461
462 fd2gm_xml = etree.ElementTree()
463 fd2gm_xml.parse(self.__fd2gm_filename)
464
465 print fd2gm_xml
466
467 #============================================================
469 """Support v8.2 CSV file interface only."""
470
471 version = u'Gelbe Liste/MMI v8.2 interface'
472 default_encoding = 'cp1250'
473 bdt_line_template = u'%03d6210#%s\r\n' # Medikament verordnet auf Kassenrezept
474 bdt_line_base_length = 8
475 #--------------------------------------------------------
477
478 cDrugDataSourceInterface.__init__(self)
479
480 _log.info(u'%s (native Windows)', cGelbeListeWindowsInterface.version)
481
482 self.path_to_binary = r'C:\Programme\MMI PHARMINDEX\glwin.exe'
483 self.args = r'-KEEPBACKGROUND -PRESCRIPTIONFILE %s -CLOSETOTRAY'
484
485 paths = gmTools.gmPaths()
486
487 self.default_csv_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'rezept.txt')
488 self.default_csv_filename_arg = os.path.join(paths.home_dir, '.gnumed', 'tmp')
489 self.interactions_filename = os.path.join(paths.home_dir, '.gnumed', 'tmp', 'gm2mmi.bdt')
490 self.data_date_filename = r'C:\Programme\MMI PHARMINDEX\datadate.txt'
491
492 self.__data_date = None
493 self.__online_update_date = None
494
495 # use adjusted config.dat
496 #--------------------------------------------------------
498
499 if self.__data_date is not None:
500 if not force_reload:
501 return {
502 'data': self.__data_date,
503 'online_update': self.__online_update_date
504 }
505
506 open(self.data_date_filename, 'wb').close()
507
508 cmd = u'%s -DATADATE' % self.path_to_binary
509 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = True):
510 _log.error('problem querying the MMI drug database for version information')
511 self.__data_date = None
512 self.__online_update_date = None
513 return {
514 'data': u'?',
515 'online_update': u'?'
516 }
517
518 try:
519 version_file = open(self.data_date_filename, 'rU')
520 except StandardError:
521 _log.error('problem querying the MMI drug database for version information')
522 _log.exception('cannot open MMI drug database version file [%s]', self.data_date_filename)
523 self.__data_date = None
524 self.__online_update_date = None
525 return {
526 'data': u'?',
527 'online_update': u'?'
528 }
529
530 self.__data_date = version_file.readline()[:10]
531 self.__online_update_date = version_file.readline()[:10]
532 version_file.close()
533
534 return {
535 'data': self.__data_date,
536 'online_update': self.__online_update_date
537 }
538 #--------------------------------------------------------
540 versions = self.get_data_source_version()
541
542 return create_data_source (
543 long_name = u'Medikamentendatenbank "mmi PHARMINDEX" (Gelbe Liste)',
544 short_name = u'GL/MMI',
545 version = u'Daten: %s, Preise (Onlineupdate): %s' % (versions['data'], versions['online_update']),
546 source = u'Medizinische Medien Informations GmbH, Am Forsthaus Gravenbruch 7, 63263 Neu-Isenburg',
547 language = u'de'
548 )
549 #--------------------------------------------------------
551
552 # must make sure csv file exists
553 open(self.default_csv_filename, 'wb').close()
554
555 if cmd is None:
556 cmd = (u'%s %s' % (self.path_to_binary, self.args)) % self.default_csv_filename_arg
557
558 if not gmShellAPI.run_command_in_shell(command = cmd, blocking = blocking):
559 _log.error('problem switching to the MMI drug database')
560 # apparently on the first call MMI does not
561 # consistently return 0 on success
562 # return False
563
564 return True
565 #--------------------------------------------------------
567
568 # better to clean up interactions file
569 open(self.interactions_filename, 'wb').close()
570
571 if not self.switch_to_frontend(blocking = True):
572 return None
573
574 return cGelbeListeCSVFile(filename = self.default_csv_filename)
575 #--------------------------------------------------------
577
578 selected_drugs = self.select_drugs()
579 if selected_drugs is None:
580 return None
581
582 new_substances = []
583
584 for drug in selected_drugs:
585 atc = None # hopefully MMI eventually supports atc-per-substance in a drug...
586 if len(drug['wirkstoffe']) == 1:
587 atc = drug['atc']
588 for wirkstoff in drug['wirkstoffe']:
589 new_substances.append(create_used_substance(substance = wirkstoff, atc = atc))
590
591 selected_drugs.close()
592
593 return new_substances
594 #--------------------------------------------------------
596
597 selected_drugs = self.select_drugs()
598 if selected_drugs is None:
599 return None
600
601 data_src_pk = self.create_data_source_entry()
602
603 new_drugs = []
604 new_substances = []
605
606 for entry in selected_drugs:
607
608 _log.debug('importing drug: %s %s', entry['name'], entry['darreichungsform'])
609
610 if entry[u'hilfsmittel']:
611 _log.debug('skipping Hilfsmittel')
612 continue
613
614 if entry[u'erstattbares_medizinprodukt']:
615 _log.debug('skipping sonstiges Medizinprodukt')
616 continue
617
618 # create branded drug (or get it if it already exists)
619 drug = create_branded_drug(brand_name = entry['name'], preparation = entry['darreichungsform'])
620 if drug is None:
621 drug = get_drug_by_brand(brand_name = entry['name'], preparation = entry['darreichungsform'])
622 new_drugs.append(drug)
623
624 # update fields
625 drug['is_fake'] = False
626 drug['atc_code'] = entry['atc']
627 drug['external_code_type'] = u'DE-PZN'
628 drug['external_code'] = entry['pzn']
629 drug['fk_data_source'] = data_src_pk
630 drug.save()
631
632 # add components to brand
633 atc = None # hopefully MMI eventually supports atc-per-substance in a drug...
634 if len(entry['wirkstoffe']) == 1:
635 atc = entry['atc']
636 for wirkstoff in entry['wirkstoffe']:
637 drug.add_component(substance = wirkstoff, atc = atc)
638
639 # create as consumable substances, too
640 atc = None # hopefully MMI eventually supports atc-per-substance in a drug...
641 if len(entry['wirkstoffe']) == 1:
642 atc = entry['atc']
643 for wirkstoff in entry['wirkstoffe']:
644 new_substances.append(create_used_substance(substance = wirkstoff, atc = atc))
645
646 return new_drugs, new_substances
647 #--------------------------------------------------------
649 """For this to work the BDT interaction check must be configured in the MMI."""
650
651 if drug_ids_list is None:
652 if substances is None:
653 return
654 if len(substances) < 2:
655 return
656 drug_ids_list = [ (s.external_code_type, s.external_code) for s in substances ]
657 drug_ids_list = [ code_value for code_type, code_value in drug_ids_list if (code_value is not None) and (code_type == u'DE-PZN')]
658
659 else:
660 if len(drug_ids_list) < 2:
661 return
662
663 if drug_ids_list < 2:
664 return
665
666 bdt_file = codecs.open(filename = self.interactions_filename, mode = 'wb', encoding = cGelbeListeWindowsInterface.default_encoding)
667
668 for pzn in drug_ids_list:
669 pzn = pzn.strip()
670 lng = cGelbeListeWindowsInterface.bdt_line_base_length + len(pzn)
671 bdt_file.write(cGelbeListeWindowsInterface.bdt_line_template % (lng, pzn))
672
673 bdt_file.close()
674
675 self.switch_to_frontend(blocking = False)
676 #--------------------------------------------------------
678
679 cmd = None
680
681 if substance.external_code_type == u'DE-PZN':
682 cmd = u'%s -PZN %s' % (self.path_to_binary, substance.external_code)
683
684 if cmd is None:
685 name = gmTools.coalesce (
686 substance['brand'],
687 substance['substance']
688 )
689 cmd = u'%s -NAME %s' % (self.path_to_binary, name)
690
691 # better to clean up interactions file
692 open(self.interactions_filename, 'wb').close()
693
694 self.switch_to_frontend(cmd = cmd)
695 #============================================================
697
699 cGelbeListeWindowsInterface.__init__(self)
700
701 _log.info(u'%s (WINE extension)', cGelbeListeWindowsInterface.version)
702
703 # FIXME: if -CLOSETOTRAY is used GNUmed cannot detect the end of MMI
704 self.path_to_binary = r'wine "C:\Programme\MMI PHARMINDEX\glwin.exe"'
705 self.args = r'"-PRESCRIPTIONFILE %s -KEEPBACKGROUND"'
706
707 paths = gmTools.gmPaths()
708
709 self.default_csv_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'windows', 'temp', 'mmi2gm.csv')
710 self.default_csv_filename_arg = r'c:\windows\temp\mmi2gm.csv'
711 self.interactions_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'windows', 'temp', 'gm2mmi.bdt')
712 self.data_date_filename = os.path.join(paths.home_dir, '.wine', 'drive_c', 'Programme', 'MMI PHARMINDEX', 'datadate.txt')
713 #============================================================
715 """empirical CSV interface"""
716
719
721
722 try:
723 csv_file = open(filename, 'rb') # FIXME: encoding ?
724 except:
725 _log.exception('cannot access [%s]', filename)
726 csv_file = None
727
728 field_names = u'PZN Handelsname Form Abpackungsmenge Einheit Preis1 Hersteller Preis2 rezeptpflichtig Festbetrag Packungszahl Packungsgr\xf6\xdfe'.split()
729
730 if csv_file is None:
731 return False
732
733 csv_lines = csv.DictReader (
734 csv_file,
735 fieldnames = field_names,
736 delimiter = ';'
737 )
738
739 for line in csv_lines:
740 print "--------------------------------------------------------------------"[:31]
741 for key in field_names:
742 tmp = ('%s ' % key)[:30]
743 print '%s: %s' % (tmp, line[key])
744
745 csv_file.close()
746
747 # narr = u'%sx %s %s %s (\u2258 %s %s) von %s (%s)' % (
748 # line['Packungszahl'].strip(),
749 # line['Handelsname'].strip(),
750 # line['Form'].strip(),
751 # line[u'Packungsgr\xf6\xdfe'].strip(),
752 # line['Abpackungsmenge'].strip(),
753 # line['Einheit'].strip(),
754 # line['Hersteller'].strip(),
755 # line['PZN'].strip()
756 # )
757 #============================================================
758 drug_data_source_interfaces = {
759 'Deutschland: Gelbe Liste/MMI (Windows)': cGelbeListeWindowsInterface,
760 'Deutschland: Gelbe Liste/MMI (WINE)': cGelbeListeWineInterface,
761 'FreeDiams (France, US, Canada)': cFreeDiamsInterface
762 }
763 #============================================================
764 # substances in use across all patients
765 #------------------------------------------------------------
767 cmd = u'select * from clin.consumed_substance order by description'
768 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
769 return rows
770 #------------------------------------------------------------
772 cmd = u'select * from clin.consumed_substance WHERE pk = %(pk)s'
773 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'pk': pk}}])
774 if len(rows) == 0:
775 return None
776 return rows[0]
777 #------------------------------------------------------------
779
780 substance = substance.strip()
781
782 if atc is not None:
783 atc = atc.strip()
784
785 args = {'desc': substance, 'atc': atc}
786
787 cmd = u'select pk, atc_code, description from clin.consumed_substance where description = %(desc)s'
788 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}])
789
790 if len(rows) == 0:
791 cmd = u'insert into clin.consumed_substance (description, atc_code) values (%(desc)s, gm.nullify_empty_string(%(atc)s)) returning pk, atc_code, description'
792 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
793
794 gmATC.propagate_atc(substance = substance, atc = atc)
795
796 row = rows[0]
797 # unfortunately not a real dict so no setting stuff by keyword
798 #row['atc_code'] = args['atc']
799 row[1] = args['atc']
800 return row
801 #------------------------------------------------------------
803 args = {'pk': substance}
804 cmd = u"""
805 delete from clin.consumed_substance
806 where
807 pk = %(pk)s and not exists (
808 select 1 from clin.substance_intake
809 where fk_substance = %(pk)s
810 )"""
811 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
812 #============================================================
814 """Represents a substance currently taken by a patient."""
815
816 _cmd_fetch_payload = u"select * from clin.v_pat_substance_intake where pk_substance_intake = %s"
817 _cmds_store_payload = [
818 u"""update clin.substance_intake set
819 clin_when = %(started)s,
820 discontinued = %(discontinued)s,
821 discontinue_reason = gm.nullify_empty_string(%(discontinue_reason)s),
822 strength = gm.nullify_empty_string(%(strength)s),
823 preparation = %(preparation)s,
824 schedule = gm.nullify_empty_string(%(schedule)s),
825 aim = gm.nullify_empty_string(%(aim)s),
826 narrative = gm.nullify_empty_string(%(notes)s),
827 intake_is_approved_of = %(intake_is_approved_of)s,
828
829 -- is_long_term = %(is_long_term)s,
830 is_long_term = (
831 case
832 when (
833 (%(is_long_term)s is False)
834 and
835 (%(duration)s is NULL)
836 ) is True then null
837 else %(is_long_term)s
838 end
839 )::boolean,
840 duration = (
841 case
842 when %(is_long_term)s is True then null
843 else %(duration)s
844 end
845 )::interval,
846
847 fk_brand = %(pk_brand)s,
848 fk_substance = %(pk_substance)s,
849 fk_episode = %(pk_episode)s
850 where
851 pk = %(pk_substance_intake)s and
852 xmin = %(xmin_substance_intake)s
853 returning
854 xmin as xmin_substance_intake
855 """
856 ]
857 _updatable_fields = [
858 u'started',
859 u'discontinued',
860 u'discontinue_reason',
861 u'preparation',
862 u'strength',
863 u'intake_is_approved_of',
864 u'schedule',
865 u'duration',
866 u'aim',
867 u'is_long_term',
868 u'notes',
869 u'pk_brand',
870 u'pk_substance',
871 u'pk_episode'
872 ]
873 #--------------------------------------------------------
875
876 if self._payload[self._idx['duration']] is None:
877 duration = gmTools.bool2subst (
878 self._payload[self._idx['is_long_term']],
879 _('long-term'),
880 _('short-term'),
881 _('?short-term')
882 )
883 else:
884 duration = gmDateTime.format_interval (
885 self._payload[self._idx['duration']],
886 accuracy_wanted = gmDateTime.acc_days
887 )
888
889 line = u'%s%s (%s %s): %s %s %s (%s)' % (
890 u' ' * left_margin,
891 self._payload[self._idx['started']].strftime(date_format),
892 gmTools.u_right_arrow,
893 duration,
894 self._payload[self._idx['substance']],
895 gmTools.coalesce(self._payload[self._idx['strength']], u''),
896 self._payload[self._idx['preparation']],
897 gmTools.bool2subst(self._payload[self._idx['is_currently_active']], _('ongoing'), _('inactive'), _('?ongoing'))
898 )
899
900 return line
901 #--------------------------------------------------------
903 allg = gmAllergy.create_allergy (
904 allergene = self._payload[self._idx['substance']],
905 allg_type = allergy_type,
906 episode_id = self._payload[self._idx['pk_episode']],
907 encounter_id = encounter_id
908 )
909 allg['substance'] = gmTools.coalesce (
910 self._payload[self._idx['brand']],
911 self._payload[self._idx['substance']]
912 )
913 allg['reaction'] = self._payload[self._idx['discontinue_reason']]
914 allg['atc_code'] = gmTools.coalesce(self._payload[self._idx['atc_substance']], self._payload[self._idx['atc_brand']])
915 if self._payload[self._idx['external_code_brand']] is not None:
916 allg['substance_code'] = u'%s::::%s' % (self._payload[self._idx['external_code_type_brand']], self._payload[self._idx['external_code_brand']])
917 allg['allergene'] = self._payload[self._idx['substance']]
918 comps = [ c['description'] for c in self.containing_drug.components ]
919 if len(comps) == 0:
920 allg['generics'] = self._payload[self._idx['substance']]
921 else:
922 allg['generics'] = u'; '.join(comps)
923
924 allg.save()
925 return allg
926 #--------------------------------------------------------
927 # properties
928 #--------------------------------------------------------
930
931 try: self.__ddd
932 except AttributeError: self.__ddd = None
933
934 if self.__ddd is not None:
935 return self.__ddd
936
937 if self._payload[self._idx['atc_substance']] is not None:
938 ddd = gmATC.atc2ddd(atc = self._payload[self._idx['atc_substance']])
939 if len(ddd) != 0:
940 self.__ddd = ddd[0]
941 else:
942 if self._payload[self._idx['atc_brand']] is not None:
943 ddd = gmATC.atc2ddd(atc = self._payload[self._idx['atc_brand']])
944 if len(ddd) != 0:
945 self.__ddd = ddd[0]
946
947 return self.__ddd
948
949 ddd = property(_get_ddd, lambda x:x)
950 #--------------------------------------------------------
952 drug = self.containing_drug
953
954 if drug is None:
955 return None
956
957 return drug.external_code
958
959 external_code = property(_get_external_code, lambda x:x)
960 #--------------------------------------------------------
962 drug = self.containing_drug
963
964 if drug is None:
965 return None
966
967 return drug.external_code_type
968
969 external_code_type = property(_get_external_code_type, lambda x:x)
970 #--------------------------------------------------------
972 if self._payload[self._idx['pk_brand']] is None:
973 return None
974
975 return cBrandedDrug(aPK_obj = self._payload[self._idx['pk_brand']])
976
977 containing_drug = property(_get_containing_drug, lambda x:x)
978 #--------------------------------------------------------
980 tests = [
981 # lead, trail
982 ' 1-1-1-1 ',
983 # leading dose
984 '1-1-1-1',
985 '22-1-1-1',
986 '1/3-1-1-1',
987 '/4-1-1-1'
988 ]
989 pattern = "^(\d\d|/\d|\d/\d|\d)[\s-]{1,5}\d{0,2}[\s-]{1,5}\d{0,2}[\s-]{1,5}\d{0,2}$"
990 for test in tests:
991 print test.strip(), ":", regex.match(pattern, test.strip())
992 #------------------------------------------------------------
993 -def create_substance_intake(substance=None, atc=None, encounter=None, episode=None, preparation=None):
994
995 args = {
996 'enc': encounter,
997 'epi': episode,
998 'prep': preparation,
999 'subst': create_used_substance(substance = substance, atc = atc)['pk']
1000 }
1001
1002 cmd = u"""
1003 insert into clin.substance_intake (
1004 fk_encounter,
1005 fk_episode,
1006 fk_substance,
1007 preparation,
1008 intake_is_approved_of
1009 ) values (
1010 %(enc)s,
1011 %(epi)s,
1012 %(subst)s,
1013 gm.nullify_empty_string(%(prep)s),
1014 False
1015 )
1016 returning pk
1017 """
1018 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
1019 return cSubstanceIntakeEntry(aPK_obj = rows[0][0])
1020 #------------------------------------------------------------
1022 cmd = u'delete from clin.substance_intake where pk = %(pk)s'
1023 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': substance}}])
1024 #------------------------------------------------------------
1026
1027 tex = u'\n{\\small\n'
1028 tex += u'\\noindent %s\n' % _('Additional notes')
1029 tex += u'\n'
1030 tex += u'\\noindent \\begin{tabular}{|l|l|l|l|}\n'
1031 tex += u'\\hline\n'
1032 tex += u'%s & %s & %s & \\\\ \n' % (_('Substance'), _('Strength'), _('Brand'))
1033 tex += u'\\hline\n'
1034 tex += u'%s\n'
1035 tex += u'\n'
1036 tex += u'\\end{tabular}\n'
1037 tex += u'}\n'
1038
1039 current_meds = emr.get_current_substance_intake (
1040 include_inactive = False,
1041 include_unapproved = False,
1042 order_by = u'brand, substance'
1043 )
1044
1045 # create lines
1046 lines = []
1047 for med in current_meds:
1048
1049 lines.append(u'%s & %s & %s %s & {\\scriptsize %s} \\\\ \n \\hline \n' % (
1050 med['substance'],
1051 gmTools.coalesce(med['strength'], u''),
1052 gmTools.coalesce(med['brand'], u''),
1053 med['preparation'],
1054 gmTools.coalesce(med['notes'], u'')
1055 ))
1056
1057 return tex % u' \n'.join(lines)
1058
1059 #------------------------------------------------------------
1061
1062 tex = u'\\noindent %s {\\tiny (%s)\\par}\n' % (_('Medication list'), _('ordered by brand'))
1063 tex += u'\n'
1064 tex += u'\\noindent \\begin{tabular}{|l|l|}\n'
1065 tex += u'\\hline\n'
1066 tex += u'%s & %s \\\\ \n' % (_('Drug'), _('Regimen'))
1067 tex += u'\\hline\n'
1068 tex += u'\n'
1069 tex += u'\\hline\n'
1070 tex += u'%s\n'
1071 tex += u'\n'
1072 tex += u'\\end{tabular}\n'
1073
1074 current_meds = emr.get_current_substance_intake (
1075 include_inactive = False,
1076 include_unapproved = False,
1077 order_by = u'brand, substance'
1078 )
1079
1080 # aggregate data
1081 line_data = {}
1082 for med in current_meds:
1083 identifier = gmTools.coalesce(med['brand'], med['substance'])
1084
1085 try:
1086 line_data[identifier]
1087 except KeyError:
1088 line_data[identifier] = {'brand': u'', 'preparation': u'', 'schedule': u'', 'aims': [], 'strengths': []}
1089
1090 line_data[identifier]['brand'] = identifier
1091 if med['strength'] is not None:
1092 line_data[identifier]['strengths'].append(med['strength'].strip())
1093 line_data[identifier]['preparation'] = med['preparation']
1094 line_data[identifier]['schedule'] = gmTools.coalesce(med['schedule'], u'')
1095 if med['aim'] not in line_data[identifier]['aims']:
1096 line_data[identifier]['aims'].append(med['aim'])
1097
1098 # create lines
1099 already_seen = []
1100 lines = []
1101 line1_template = u'%s %s & %s \\\\'
1102 line2_template = u' & {\\scriptsize %s\\par} \\\\'
1103
1104 for med in current_meds:
1105 identifier = gmTools.coalesce(med['brand'], med['substance'])
1106
1107 if identifier in already_seen:
1108 continue
1109
1110 already_seen.append(identifier)
1111
1112 lines.append (line1_template % (
1113 line_data[identifier]['brand'],
1114 line_data[identifier]['preparation'],
1115 line_data[identifier]['schedule']
1116 ))
1117
1118 strengths = u'/'.join(line_data[identifier]['strengths'])
1119 if strengths == u'':
1120 template = u' & {\\scriptsize %s\\par} \\\\'
1121 for aim in line_data[identifier]['aims']:
1122 lines.append(template % aim)
1123 else:
1124 if len(line_data[identifier]['aims']) == 0:
1125 template = u'%s & \\\\'
1126 lines.append(template % strengths)
1127 else:
1128 template = u'%s & {\\scriptsize %s\\par} \\\\'
1129 lines.append(template % (strengths, line_data[identifier]['aims'][0]))
1130 template = u' & {\\scriptsize %s\\par} \\\\'
1131 for aim in line_data[identifier]['aims'][1:]:
1132 lines.append(template % aim)
1133
1134 lines.append(u'\\hline')
1135
1136 return tex % u' \n'.join(lines)
1137 #============================================================
1139 """Represents a drug as marketed by a manufacturer."""
1140
1141 _cmd_fetch_payload = u"select *, xmin from ref.branded_drug where pk = %s"
1142 _cmds_store_payload = [
1143 u"""update ref.branded_drug set
1144 description = %(description)s,
1145 preparation = %(preparation)s,
1146 atc_code = gm.nullify_empty_string(%(atc_code)s),
1147 external_code = gm.nullify_empty_string(%(external_code)s),
1148 external_code_type = gm.nullify_empty_string(%(external_code_type)s),
1149 is_fake = %(is_fake)s,
1150 fk_data_source = %(fk_data_source)s
1151 where
1152 pk = %(pk)s and
1153 xmin = %(xmin)s
1154 returning
1155 xmin
1156 """
1157 ]
1158 _updatable_fields = [
1159 u'description',
1160 u'preparation',
1161 u'atc_code',
1162 u'is_fake',
1163 u'external_code',
1164 u'external_code_type',
1165 u'fk_data_source'
1166 ]
1167 #--------------------------------------------------------
1169 if self._payload[self._idx['external_code']] is None:
1170 return None
1171
1172 return self._payload[self._idx['external_code']]
1173
1174 external_code = property(_get_external_code, lambda x:x)
1175 #--------------------------------------------------------
1177
1178 # FIXME: maybe evaluate fk_data_source ?
1179 if self._payload[self._idx['external_code_type']] is None:
1180 return None
1181
1182 return self._payload[self._idx['external_code_type']]
1183
1184 external_code_type = property(_get_external_code_type, lambda x:x)
1185 #--------------------------------------------------------
1187 cmd = u'select * from ref.substance_in_brand where fk_brand = %(brand)s'
1188 args = {'brand': self._payload[self._idx['pk']]}
1189 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1190 return rows
1191
1192 components = property(_get_components, lambda x:x)
1193 #--------------------------------------------------------
1195 cmd = u'SELECT EXISTS (SELECT 1 FROM clin.vaccine WHERE fk_brand = %(fk_brand)s)'
1196 args = {'fk_brand': self._payload[self._idx['pk']]}
1197 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1198 return rows[0][0]
1199
1200 is_vaccine = property(_get_is_vaccine, lambda x:x)
1201 #--------------------------------------------------------
1203
1204 # normalize atc
1205 atc = gmATC.propagate_atc(substance = substance, atc = atc)
1206
1207 args = {
1208 'brand': self.pk_obj,
1209 'desc': substance,
1210 'atc': atc
1211 }
1212
1213 # already exists ?
1214 cmd = u"""
1215 SELECT pk
1216 FROM ref.substance_in_brand
1217 WHERE
1218 fk_brand = %(brand)s
1219 AND
1220 ((description = %(desc)s) OR ((atc_code = %(atc)s) IS TRUE))
1221 """
1222 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1223 if len(rows) > 0:
1224 return
1225
1226 # create it
1227 cmd = u"""
1228 INSERT INTO ref.substance_in_brand (fk_brand, description, atc_code)
1229 VALUES (%(brand)s, %(desc)s, %(atc)s)
1230 """
1231 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
1232 #------------------------------------------------------------
1235 #------------------------------------------------------------
1237 cmd = u'SELECT * FROM ref.v_substance_in_brand ORDER BY brand, substance'
1238 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
1239 return rows
1240 #------------------------------------------------------------
1242
1243 cmd = u'SELECT pk FROM ref.branded_drug ORDER BY description'
1244 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
1245
1246 return [ cBrandedDrug(aPK_obj = r['pk']) for r in rows ]
1247 #------------------------------------------------------------
1249 args = {'brand': brand_name, 'prep': preparation}
1250
1251 cmd = u'SELECT pk FROM ref.branded_drug WHERE description = %(brand)s AND preparation = %(prep)s'
1252 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
1253
1254 if len(rows) == 0:
1255 return None
1256
1257 return cBrandedDrug(aPK_obj = rows[0]['pk'])
1258 #------------------------------------------------------------
1260
1261 if preparation is None:
1262 preparation = _('units')
1263
1264 if preparation.strip() == u'':
1265 preparation = _('units')
1266
1267 drug = get_drug_by_brand(brand_name = brand_name, preparation = preparation)
1268
1269 if drug is not None:
1270 if return_existing:
1271 return drug
1272 return None
1273
1274 cmd = u'insert into ref.branded_drug (description, preparation) values (%(brand)s, %(prep)s) returning pk'
1275 args = {'brand': brand_name, 'prep': preparation}
1276 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True, get_col_idx = False)
1277
1278 return cBrandedDrug(aPK_obj = rows[0]['pk'])
1279 #------------------------------------------------------------
1281 cmd = u'delete from ref.branded_drug where pk = %(pk)s'
1282 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': brand}}])
1283 #------------------------------------------------------------
1285 cmd = u'delete from ref.substance_in_brand where fk_brand = %(brand)s and pk = %(comp)s'
1286 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'brand': brand, 'comp': component}}])
1287 #============================================================
1288 # main
1289 #------------------------------------------------------------
1290 if __name__ == "__main__":
1291
1292 if len(sys.argv) < 2:
1293 sys.exit()
1294
1295 if sys.argv[1] != 'test':
1296 sys.exit()
1297
1298 from Gnumed.pycommon import gmLog2
1299 from Gnumed.pycommon import gmI18N
1300 from Gnumed.business import gmPerson
1301
1302 gmI18N.activate_locale()
1303 # gmDateTime.init()
1304 #--------------------------------------------------------
1306 mmi = cGelbeListeWineInterface()
1307 print mmi
1308 print "interface definition:", mmi.version
1309 print "database versions: ", mmi.get_data_source_version()
1310 #--------------------------------------------------------
1312 mmi_file = cGelbeListeCSVFile(filename = sys.argv[2])
1313 for drug in mmi_file:
1314 print "-------------"
1315 print '"%s" (ATC: %s / PZN: %s)' % (drug['name'], drug['atc'], drug['pzn'])
1316 for stoff in drug['wirkstoffe']:
1317 print " Wirkstoff:", stoff
1318 print drug
1319 mmi_file.close()
1320 #--------------------------------------------------------
1324 #--------------------------------------------------------
1326 mmi = cGelbeListeWineInterface()
1327 mmi_file = mmi.select_drugs()
1328 for drug in mmi_file:
1329 print "-------------"
1330 print '"%s" (ATC: %s / PZN: %s)' % (drug['name'], drug['atc'], drug['pzn'])
1331 for stoff in drug['wirkstoffe']:
1332 print " Wirkstoff:", stoff
1333 print drug
1334 mmi_file.close()
1335 #--------------------------------------------------------
1339 #--------------------------------------------------------
1341 mmi = cGelbeListeInterface()
1342 print mmi
1343 print "interface definition:", mmi.version
1344 # Metoprolol + Hct vs Citalopram
1345 diclofenac = '7587712'
1346 phenprocoumon = '4421744'
1347 mmi.check_drug_interactions(drug_ids_list = [diclofenac, phenprocoumon])
1348 #--------------------------------------------------------
1349 # FreeDiams
1350 #--------------------------------------------------------
1352 gmPerson.set_active_patient(patient = gmPerson.cIdentity(aPK_obj = 12))
1353 fd = cFreeDiamsInterface()
1354 fd.patient = gmPerson.gmCurrentPatient()
1355 fd.switch_to_frontend(blocking = True)
1356 fd.import_fd2gm_file()
1357 #--------------------------------------------------------
1358 # generic
1359 #--------------------------------------------------------
1361 drug = create_substance_intake (
1362 substance = u'Whiskey',
1363 atc = u'no ATC available',
1364 encounter = 1,
1365 episode = 1,
1366 preparation = 'a nice glass'
1367 )
1368 print drug
1369 #--------------------------------------------------------
1374 #--------------------------------------------------------
1375 #test_MMI_interface()
1376 #test_MMI_file()
1377 #test_mmi_switch_to()
1378 #test_mmi_select_drugs()
1379 #test_mmi_import_substances()
1380 #test_mmi_import_drugs()
1381 test_fd_switch_to()
1382 #test_interaction_check()
1383 #test_create_substance_intake()
1384 #test_show_components()
1385 #============================================================
1386
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu Sep 9 04:07:33 2010 | http://epydoc.sourceforge.net |