def test_label(): from Gnumed.business.gmPerson import cPatient from Gnumed.business.gmPersonSearch import ask_for_patient #while ask_for_patient() is not None: pat_min = 1 pat_max = 100 try: pat_min = int(sys.argv[2]) pat_max = int(sys.argv[3]) except: pass cPatient(aPK_obj=pat_min) f = io.open('x-auto_inf_labels.txt', mode='w', encoding='utf8') f.write('--------------------------------\n') f.write('12345678901234567890123456789012\n') f.write('--------------------------------\n') for pat_id in range(pat_min, pat_max): try: exp_area = cExportArea(pat_id) pat = cPatient(aPK_obj=pat_id) except: continue f.write(exp_area._compute_autorun_inf_label(pat) + '\n') f.close() return
def __PID2dto(HL7=None): pat_lname = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__lastname) pat_fname = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__firstname) pat_mname = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__middlename) if pat_mname is not None: pat_fname += ' ' pat_fname += pat_mname _log.debug('patient data from PID segment: first=%s (middle=%s) last=%s', pat_fname, pat_mname, pat_lname) dto = gmPerson.cDTO_person() dto.firstnames = pat_fname dto.lastnames = pat_lname dto.gender = HL7_GENDERS[HL7.extract_field('PID', segment_num = 1, field_num = PID_field__gender)] hl7_dob = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__dob) if hl7_dob is not None: tmp = time.strptime(hl7_dob, '%Y%m%d') dto.dob = pyDT.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tzinfo = gmDateTime.gmCurrentLocalTimezone) idents = dto.get_candidate_identities() if len(idents) == 0: _log.warning('no match candidate, not auto-importing') _log.debug(dto) return [] if len(idents) > 1: _log.warning('more than one match candidate, not auto-importing') _log.debug(dto) return idents return [gmPerson.cPatient(idents[0].ID)]
def __PID2dto(HL7=None): pat_lname = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__lastname) pat_fname = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__firstname) pat_mname = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__name, component_num = PID_component__middlename) if pat_mname is not None: pat_fname += u' ' pat_fname += pat_mname _log.debug(u'patient data from PID segment: first=%s (middle=%s) last=%s', pat_fname, pat_mname, pat_lname) dto = gmPerson.cDTO_person() dto.firstnames = pat_fname dto.lastnames = pat_lname dto.gender = HL7_GENDERS[HL7.extract_field('PID', segment_num = 1, field_num = PID_field__gender)] hl7_dob = HL7.extract_field('PID', segment_num = 1, field_num = PID_field__dob) if hl7_dob is not None: tmp = time.strptime(hl7_dob, '%Y%m%d') dto.dob = pyDT.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tzinfo = gmDateTime.gmCurrentLocalTimezone) idents = dto.get_candidate_identities() if len(idents) == 0: _log.warning('no match candidate, not auto-importing') _log.debug(dto) return [] if len(idents) > 1: _log.warning('more than one match candidate, not auto-importing') _log.debug(dto) return idents return [gmPerson.cPatient(idents[0].ID)]
def get_patients(self, search_term=None, a_locale=None, dto=None): identities = self.get_identities(search_term, a_locale, dto) if identities is None: return None return [ gmPerson.cPatient(aPK_obj=ident['pk_identity']) for ident in identities ]
def test_clin_calc(): from Gnumed.business.gmPraxis import gmCurrentPraxisBranch praxis = gmCurrentPraxisBranch() from Gnumed.business.gmPerson import cPatient pat = cPatient(aPK_obj = 12) calc = cClinicalCalculator(patient = pat) #result = calc.eGFR_MDRD_short #result = calc.eGFR_Schwartz result = calc.eGFR #result = calc.body_surface_area #result = calc.get_EDC(lmp = gmDateTime.pydt_now_here()) #result = calc.body_mass_index #result = calc.eGFRs print('%s' % result.format(with_formula = True, with_warnings = True, with_variables = True, with_sub_results = True))
def test_get_useful_filename(): pk = 12 from Gnumed.business.gmPerson import cPatient pat = cPatient(pk) doc_folder = cDocumentFolder(aPKey=pk) for doc in doc_folder.documents: for part in doc.parts: print( part.get_useful_filename(patient=pat, make_unique=True, directory=None, include_gnumed_tag=False, date_before_type=True, name_first=False))
def test_get_useful_filename(): pk = 12 from Gnumed.business.gmPerson import cPatient pat = cPatient(pk) doc_folder = cDocumentFolder(aPKey = pk) for doc in doc_folder.documents: for part in doc.parts: print(part.get_useful_filename ( patient = pat, make_unique = True, directory = None, include_gnumed_tag = False, date_before_type = True, name_first = False ))
def dump_items_to_disk(self, base_dir=None, items=None): if items is None: items = self.items if len(items) == 0: return None if base_dir is None: from Gnumed.business.gmPerson import cPatient pat = cPatient(aPK_obj=self.__pk_identity) base_dir = gmTools.mk_sandbox_dir(prefix=u'exp-%s-' % pat.dirname) _log.debug('dumping export items to: %s', base_dir) gmTools.mkdir(base_dir) for item in items: item.save_to_file(directory=base_dir) return base_dir
def get_tooltip(data): if data is None: return None patient = gmPerson.cPatient(data['pk_patient']) return data.format ( patient = patient, with_summary = True, with_codes = True, with_episodes = True, with_encounters = True, with_medications = False, with_hospital_stays = False, with_procedures = False, with_family_history = False, with_documents = False, with_tests = False, with_vaccinations = False )
def test_part_metainfo_formatter(): #-------------------------------- def desc_printer(worker_result): status, desc = worker_result print('printer callback:') print(status) print(desc) print('<hit key> for next') return #-------------------------------- pk = 12 from Gnumed.business.gmPerson import cPatient pat = cPatient(pk) doc_folder = cDocumentFolder(aPKey = pk) for doc in doc_folder.documents: for part in doc.parts: part.format_metainfo(callback = desc_printer) input('waiting ...')
def _create_data(self): issue_name = self.GetValue().strip() if issue_name == '': gmDispatcher.send(signal = 'statustext', msg = _('Cannot create health issue without name.'), beep = True) _log.debug('cannot create health issue without name') return if self.use_current_patient: pat = gmPerson.gmCurrentPatient() else: pat = gmPerson.cPatient(aPK_obj = self.__patient_id) emr = pat.emr issue = emr.add_health_issue(issue_name = issue_name) if issue is None: self.data = {} else: self.SetText ( value = issue_name, data = issue['pk_health_issue'] )
def _create_data(self): epi_name = self.GetValue().strip() if epi_name == '': gmDispatcher.send(signal = 'statustext', msg = _('Cannot create episode without name.'), beep = True) _log.debug('cannot create episode without name') return if self.use_current_patient: pat = gmPerson.gmCurrentPatient() else: pat = gmPerson.cPatient(aPK_obj = self.__patient_id) emr = pat.emr epi = emr.add_episode(episode_name = epi_name, is_open = self.__is_open_for_create_data) if epi is None: self.data = {} else: self.SetText ( value = epi_name, data = epi['pk_episode'] )
def set_active_patient(patient=None, forced_reload=False): # already active ? if isinstance(patient, gmPerson.gmCurrentPatient): return True if isinstance(patient, gmPerson.cPatient): if patient['is_deleted']: _log.error('patient is disabled, will not use as active patient: %s', patient) return False elif isinstance(patient, gmPerson.cPerson): if patient['is_deleted']: _log.error('patient is disabled, will not use as active patient: %s', patient) return False patient = patient.as_patient elif patient == -1: pass else: # maybe integer ? success, pk = gmTools.input2int(initial = patient, minval = 1) if not success: raise ValueError('<patient> must be either -1, >0, or a cPatient, cPerson or gmCurrentPatient instance, is: %s' % patient) # but also valid patient ID ? try: patient = gmPerson.cPatient(aPK_obj = pk) except Exception: _log.exception('error changing active patient to [%s]' % patient) return False if not _verify_staff_chart_access(patient = patient): return False success = gmPerson.set_active_patient(patient = patient, forced_reload = forced_reload) if not success: return False wx.CallAfter(_do_after_setting_active_patient, patient) return True
def set_active_patient(patient=None, forced_reload=False): # already active ? if isinstance(patient, gmPerson.gmCurrentPatient): return True if isinstance(patient, gmPerson.cPatient): if patient['is_deleted']: _log.error('patient is disabled, will not use as active patient: %s', patient) return False elif isinstance(patient, gmPerson.cPerson): if patient['is_deleted']: _log.error('patient is disabled, will not use as active patient: %s', patient) return False patient = patient.as_patient elif patient == -1: pass else: # maybe integer ? success, pk = gmTools.input2int(initial = patient, minval = 1) if not success: raise ValueError('<patient> must be either -1, >0, or a cPatient, cPerson or gmCurrentPatient instance, is: %s' % patient) # but also valid patient ID ? try: patient = gmPerson.cPatient(aPK_obj = pk) except: _log.exception('error changing active patient to [%s]' % patient) return False if not _verify_staff_chart_access(patient = patient): return False success = gmPerson.set_active_patient(patient = patient, forced_reload = forced_reload) if not success: return False wx.CallAfter(_do_after_setting_active_patient, patient) return True
def export(self, base_dir=None, items=None, with_metadata=True): if items is None: items_found = self.items if len(items) == 0: return None from Gnumed.business.gmPerson import cPatient pat = cPatient(aPK_obj = self.__pk_identity) if base_dir is None: base_dir = gmTools.mk_sandbox_dir(prefix = u'exp-%s-' % pat.dirname) _log.debug('base dir: %s', base_dir) doc_dir = os.path.join(base_dir, r'documents') gmTools.mkdir(doc_dir) mugshot = pat.document_folder.latest_mugshot if mugshot is None: mugshot_url = u'documents/no-such-file.png' mugshot_alt = _('no patient photograph available') mugshot_title = u'' else: mugshot_url = mugshot.export_to_file(directory = doc_dir) mugshot_alt =_('patient photograph from %s') % gmDateTime.pydt_strftime(mugshot['date_generated'], '%B %Y') mugshot_title = gmDateTime.pydt_strftime(mugshot['date_generated'], '%B %Y') # index.html idx_fname = os.path.join(base_dir, u'index.html') idx_file = io.open(idx_fname, mode = u'wt', encoding = u'utf8') # header browse_dicomdir = u'' existing_files = os.listdir(base_dir) if u'DICOMDIR' in existing_files: browse_dicomdir = u' <li><a href="./DICOMDIR">browse DICOMDIR</a></li>' idx_file.write(_html_start % { u'html_title_header': _('Patient data for'), u'html_title_patient': gmTools.html_escape_string(pat['description_gender'] + u', ' + _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')), u'title': _('Patient data export'), u'pat_name': gmTools.html_escape_string(pat['description_gender']), u'pat_dob': gmTools.html_escape_string(_(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')), u'mugshot_url': mugshot_url, u'mugshot_alt': mugshot_alt, u'mugshot_title': mugshot_title, u'docs_title': _(u'Documents'), u'browse_root': _(u'browse storage medium'), u'browse_docs': _(u'browse documents area'), u'browse_dicomdir': browse_dicomdir }) # middle for item in items: item_path = item.export_to_file(directory = doc_dir) item_fname = os.path.split(item_path)[1] idx_file.write(_html_list_item % ( item_fname, gmTools.html_escape_string(item['description']) )) # footer _cfg = gmCfg2.gmCfgData() idx_file.write(_html_end % ( gmTools.html_escape_string(gmDateTime.pydt_strftime(format = '%Y %B %d', encoding = u'utf8')), gmTools.html_escape_string(_cfg.get(option = u'client_version')) )) idx_file.close() # autorun.inf autorun_fname = os.path.join(base_dir, u'autorun.inf') autorun_file = io.open(autorun_fname, mode = u'wt', encoding = u'utf8') autorun_file.write(_autorun_inf % ( (pat['description_gender'] + u', ' + _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')).strip(), _('Browse patient data') )) autorun_file.close() # cd.inf cd_inf_fname = os.path.join(base_dir, u'cd.inf') cd_inf_file = io.open(cd_inf_fname, mode = u'wt', encoding = u'utf8') cd_inf_file.write(_cd_inf % ( pat['lastnames'], pat['firstnames'], gmTools.coalesce(pat['gender'], u'?'), pat.get_formatted_dob('%Y-%m-%d'), gmDateTime.pydt_strftime(format = '%Y-%m-%d', encoding = u'utf8'), pat.ID, _cfg.get(option = u'client_version'), u' / '.join([ u'%s = %s (%s)' % (g['tag'], g['label'], g['l10n_label']) for g in pat.gender_list ]) )) cd_inf_file.close() # README readme_fname = os.path.join(base_dir, u'README') readme_file = io.open(readme_fname, mode = u'wt', encoding = u'utf8') readme_file.write(_README % ( pat['description_gender'] + u', ' + _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d') )) readme_file.close() # patient demographics as GDT/XML/VCF pat.export_as_gdt(filename = os.path.join(base_dir, u'patient.gdt')) pat.export_as_xml_linuxmednews(filename = os.path.join(base_dir, u'patient.xml')) pat.export_as_vcard(filename = os.path.join(base_dir, u'patient.vcf')) return base_dir
def print_generic_document(parent=None, jobtype:str=None, episode=None): """Call LibreOffice Writer with a generated (fake) ODT file. Once Writer is closed, the ODT is imported if different from its initial content. Note: The file passed to LO _must_ reside in a directory the parents of which are all R-X by the user or else LO will throw up its arms in despair and fall back to the user's home dir upon saving. So, /tmp/user/$UID/some-file.odt will *not* work (because .../user/... is "drwx--x--x root.root") while /home/$USER/some/dir/some-file.odt does. """ sandbox = os.path.join(gmTools.gmPaths().user_tmp_dir, 'libreoffice') gmTools.mkdir(sandbox) fpath = gmTools.get_unique_filename(suffix = '.txt', tmp_dir = sandbox) doc_file = open(fpath, mode = 'wt') doc_file.write(__ODT_FILE_PREAMBLE) doc_file.write(_('Today: %s') % gmDateTime.pydt_now_here().strftime('%c')) doc_file.write('\n\n') prax = gmPraxis.gmCurrentPraxisBranch() doc_file.write('Praxis:\n') doc_file.write(prax.format()) doc_file.write('\n') doc_file.write('Praxis branch:\n') doc_file.write('\n'.join(prax.org_unit.format ( with_address = True, with_org = True, with_comms = True ))) doc_file.write('\n\n') pat = gmPerson.gmCurrentPatient(gmPerson.cPatient(12)) if pat.connected: doc_file.write('Patient:\n') doc_file.write(pat.get_description_gender()) doc_file.write('\n\n') for adr in pat.get_addresses(): doc_file.write(adr.format(single_line = False, verbose = True, show_type = True)) doc_file.write('\n\n') for chan in pat.get_comm_channels(): doc_file.werite(chan.format()) doc_file.write('\n\n') doc_file.write('Provider:\n') doc_file.write('\n'.join(gmStaff.gmCurrentProvider().get_staff().format())) doc_file.write('\n\n-----------------------------------------------------------------------------\n\n') doc_file.close() # convert txt -> odt success, ret_code, stdout = gmShellAPI.run_process ( cmd_line = [ 'lowriter', '--convert-to', 'odt', '--outdir', os.path.split(fpath)[0], fpath ], verbose = True ) if success: fpath = gmTools.fname_stem_with_path(fpath) + '.odt' else: _log.warning('cannot convert .txt to .odt') md5_before = gmTools.file2md5(fpath) gmShellAPI.run_process(cmd_line = ['lowriter', fpath], verbose = True) md5_after = gmTools.file2md5(fpath) if md5_before == md5_after: gmDispatcher.send(signal = 'statustext', msg = _('Document not modified. Discarding.'), beep = False) return if not pat.connected: shutil.move(fpath, gmTools.gmPaths().user_work_dir) gmDispatcher.send(signal = 'statustext', msg = _('No patient. Moved file into %s') % gmTools.gmPaths().user_work_dir, beep = False) return pat.export_area.add_file ( filename = fpath, hint = _('Generic letter, written at %s') % gmDateTime.pydt_now_here().strftime('%Y %b %d %H:%M') ) gmDispatcher.send(signal = 'display_widget', name = 'gmExportAreaPlugin')
def export(self, base_dir=None, items=None, expand_compressed=False): if items is None: items = self.items if len(items) == 0: return None media_base_dir = base_dir from Gnumed.business.gmPerson import cPatient pat = cPatient(aPK_obj=self.__pk_identity) if media_base_dir is None: media_base_dir = gmTools.mk_sandbox_dir(prefix='exp-%s-' % pat.subdir_name) _log.debug('patient media base dir: %s', media_base_dir) doc_dir = os.path.join(media_base_dir, r'documents') if os.path.isdir(doc_dir): index_existing_docs = True else: index_existing_docs = False gmTools.mkdir(doc_dir) _html_start_data = { 'html_title_header': _('Patient data for'), 'html_title_patient': gmTools.html_escape_string( pat.get_description_gender(with_nickname=False) + ', ' + _('born') + ' ' + pat.get_formatted_dob('%Y %B %d')), 'title': _('Patient data export'), 'pat_name': gmTools.html_escape_string( pat.get_description_gender(with_nickname=False)), 'pat_dob': gmTools.html_escape_string( _('born') + ' ' + pat.get_formatted_dob('%Y %B %d')), 'mugshot_url': 'documents/no-such-file.png', 'mugshot_alt': _('no patient photograph available'), 'mugshot_title': '', 'docs_title': _('Documents'), 'browse_root': _('browse storage medium'), 'browse_docs': _('browse documents area'), 'browse_dicomdir': '', 'run_dicom_viewer': '' } mugshot = pat.document_folder.latest_mugshot if mugshot is not None: _html_start_data['mugshot_url'] = mugshot.save_to_file( directory=doc_dir, adjust_extension=True) _html_start_data['mugshot_alt'] = _( 'patient photograph from %s') % gmDateTime.pydt_strftime( mugshot['date_generated'], '%B %Y') _html_start_data['mugshot_title'] = gmDateTime.pydt_strftime( mugshot['date_generated'], '%B %Y') if 'DICOMDIR' in os.listdir(media_base_dir): _html_start_data[ 'browse_dicomdir'] = '<li><a href="./DICOMDIR">%s</a></li>' % _( 'show DICOMDIR file') # copy DWV into target dir dwv_src_dir = os.path.join(gmTools.gmPaths().local_base_dir, 'dwv4export') if not os.path.isdir(dwv_src_dir): dwv_src_dir = os.path.join( gmTools.gmPaths().system_app_data_dir, 'dwv4export') if os.path.isdir(dwv_src_dir): dwv_target_dir = os.path.join(media_base_dir, 'dwv') gmTools.rmdir(dwv_target_dir) try: shutil.copytree(dwv_src_dir, dwv_target_dir) _html_start_data[ 'run_dicom_viewer'] = '<li><a href="./dwv/viewers/mobile-local/index.html">%s</a></li>' % _( 'run Radiology Images (DICOM) Viewer') except (shutil.Error, OSError): _log.exception('cannot include DWV, skipping') # index.html # - header idx_fname = os.path.join(media_base_dir, 'index.html') idx_file = io.open(idx_fname, mode='wt', encoding='utf8') idx_file.write(_html_start % _html_start_data) # - middle (side effect ! -> exports items into files ...) existing_docs = os.listdir( doc_dir ) # get them now, or else we will include the to-be-exported items # - export items for item in items: item_path = item.save_to_file(directory=doc_dir) item_fname = os.path.split(item_path)[1] idx_file.write( _html_list_item % (item_fname, gmTools.html_escape_string(item['description']))) # - preexisting documents for doc_fname in existing_docs: idx_file.write( _html_list_item % (doc_fname, gmTools.html_escape_string(_('other: %s') % doc_fname))) # - footer _cfg = gmCfg2.gmCfgData() from Gnumed.business.gmPraxis import gmCurrentPraxisBranch prax = gmCurrentPraxisBranch() lines = [] adr = prax.branch.org_unit.address if adr is not None: lines.extend(adr.format()) for comm in prax.branch.org_unit.comm_channels: if comm['is_confidential'] is True: continue lines.append('%s: %s' % (comm['l10n_comm_type'], comm['url'])) adr = '' if len(lines) > 0: adr = gmTools.html_escape_string('\n'.join(lines), replace_eol=True, keep_visual_eol=True) _html_end_data = { 'branch': gmTools.html_escape_string(prax['branch']), 'praxis': gmTools.html_escape_string(prax['praxis']), 'date': gmTools.html_escape_string( gmDateTime.pydt_strftime(gmDateTime.pydt_now_here(), format='%Y %B %d')), 'gm_ver': gmTools.html_escape_string(_cfg.get(option='client_version')), #'gm_ver': 'git HEAD', # for testing 'adr': adr } idx_file.write(_html_end % _html_end_data) idx_file.close() # start.html (just a copy of index.html, really ;-) start_fname = os.path.join(media_base_dir, 'start.html') try: shutil.copy2(idx_fname, start_fname) except Exception: _log.exception('cannot copy %s to %s', idx_fname, start_fname) # autorun.inf autorun_dict = {} autorun_dict['label'] = self._compute_autorun_inf_label(pat) autorun_dict['action'] = _('Browse patient data') autorun_dict['icon'] = '' media_icon_kwd = '$$gnumed_patient_media_export_icon' media_icon_kwd_exp = gmKeywordExpansion.get_expansion( keyword=media_icon_kwd, textual_only=False, binary_only=True) icon_tmp_file = media_icon_kwd_exp.save_to_file( target_mime='image/x-icon', target_extension='.ico', ignore_conversion_problems=True) if icon_tmp_file is None: _log.debug('cannot retrieve <%s>', media_icon_kwd) else: media_icon_fname = os.path.join(media_base_dir, 'gnumed.ico') try: shutil.move(icon_tmp_file, media_icon_fname) autorun_dict['icon'] = 'icon=gnumed.ico' except Exception: _log.exception('cannot move %s to %s', icon_tmp_file, media_icon_fname) autorun_fname = os.path.join(media_base_dir, 'autorun.inf') autorun_file = io.open(autorun_fname, mode='wt', encoding='cp1252', errors='replace') autorun_file.write(_autorun_inf % autorun_dict) autorun_file.close() # cd.inf cd_inf_fname = os.path.join(media_base_dir, 'cd.inf') cd_inf_file = io.open(cd_inf_fname, mode='wt', encoding='utf8') cd_inf_file.write( _cd_inf % (pat['lastnames'], pat['firstnames'], gmTools.coalesce(pat['gender'], '?'), pat.get_formatted_dob('%Y-%m-%d'), gmDateTime.pydt_strftime(gmDateTime.pydt_now_here(), format='%Y-%m-%d'), pat.ID, _cfg.get(option='client_version'), ' / '.join([ '%s = %s (%s)' % (g['tag'], g['label'], g['l10n_label']) for g in pat.gender_list ]))) cd_inf_file.close() # README readme_fname = os.path.join(media_base_dir, 'README') readme_file = io.open(readme_fname, mode='wt', encoding='utf8') readme_file.write( _README % (pat.get_description_gender(with_nickname=False) + ', ' + _('born') + ' ' + pat.get_formatted_dob('%Y %B %d'))) readme_file.close() # patient demographics as GDT/XML/VCF pat.export_as_gdt(filename=os.path.join(media_base_dir, 'patient.gdt')) pat.export_as_xml_linuxmednews( filename=os.path.join(media_base_dir, 'patient.xml')) pat.export_as_vcard( filename=os.path.join(media_base_dir, 'patient.vcf')) # praxis VCF shutil.move(prax.vcf, os.path.join(media_base_dir, 'praxis.vcf')) return media_base_dir
def process_staged_single_PID_hl7_file(staged_item): log_name = gmTools.get_unique_filename ( prefix = u'gm-staged_hl7_import-', suffix = u'.log' ) import_logger = logging.FileHandler(log_name) import_logger.setLevel(logging.DEBUG) root_logger = logging.getLogger('') root_logger.addHandler(import_logger) _log.debug('log file: %s', log_name) if not staged_item.lock(): _log.error('cannot lock staged data for HL7 import') root_logger.removeHandler(import_logger) return False, log_name _log.debug('reference ID of staged HL7 data: %s', staged_item['external_data_id']) filename = staged_item.export_to_file() _log.debug('unstaged HL7 data into: %s', filename) if staged_item['pk_identity_disambiguated'] is None: emr = None else: emr = gmPerson.cPatient(staged_item['pk_identity_disambiguated']).emr success = False try: success = __import_single_PID_hl7_file(filename, emr = emr) if success: delete_incoming_data(pk_incoming_data = staged_item['pk_incoming_data_unmatched']) staged_item.unlock() root_logger.removeHandler(import_logger) return True, log_name _log.error('error when importing single-PID/single-MSH file') except Exception: _log.exception('error when importing single-PID/single-MSH file') if not success: staged_item['comment'] = _('failed import: %s\n') % gmDateTime.pydt_strftime() staged_item['comment'] += u'\n' staged_item['comment'] += (u'-' * 80) staged_item['comment'] += u'\n\n' log = io.open(log_name, mode = 'rt', encoding = 'utf8') staged_item['comment'] += log.read() log.close() staged_item['comment'] += u'\n' staged_item['comment'] += (u'-' * 80) staged_item['comment'] += u'\n\n' staged_item['comment'] += format_hl7_file ( filename, skip_empty_fields = True, eol = u'\n ', return_filename = False ) staged_item.save() staged_item.unlock() root_logger.removeHandler(import_logger) return success, log_name
def refresh(self, encounter=None, msg=None): if msg is not None: self._LBL_instructions.SetLabel(msg) if encounter is not None: self.__encounter = encounter if self.__encounter is None: return True # getting the patient via the encounter allows us to act # on any encounter regardless of the currently active patient pat = gmPerson.cPatient(aPK_obj = self.__encounter['pk_patient']) self._LBL_patient.SetLabel(pat.get_description_gender().strip()) curr_pat = gmPerson.gmCurrentPatient() if curr_pat.connected: if curr_pat.ID == self.__encounter['pk_patient']: self._LBL_patient.SetForegroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOWTEXT)) else: self._LBL_patient.SetForegroundColour('red') self._PRW_encounter_type.SetText(self.__encounter['l10n_type'], data = self.__encounter['pk_type']) self._PRW_location.Enable(True) self._PRW_location.display_as_disabled(False) branch = self.__encounter.praxis_branch if branch is None: # None or old entry because praxis has been re-configured unit = self.__encounter.org_unit if unit is None: # None self._PRW_location.SetText(u'', data = None) else: # old entry self._PRW_location.Enable(False) self._PRW_location.display_as_disabled(True) self._PRW_location.SetText(_('old praxis branch: %s (%s)') % (unit['unit'], unit['organization']), data = None) else: self._PRW_location.SetText(self.__encounter['praxis_branch'], data = branch['pk_praxis_branch']) fts = gmDateTime.cFuzzyTimestamp ( timestamp = self.__encounter['started'], accuracy = gmDateTime.acc_minutes ) self._PRW_start.SetText(fts.format_accurately(), data=fts) fts = gmDateTime.cFuzzyTimestamp ( timestamp = self.__encounter['last_affirmed'], accuracy = gmDateTime.acc_minutes ) self._PRW_end.SetText(fts.format_accurately(), data=fts) # RFE self._TCTRL_rfe.SetValue(gmTools.coalesce(self.__encounter['reason_for_encounter'], '')) val, data = self._PRW_rfe_codes.generic_linked_codes2item_dict(self.__encounter.generic_codes_rfe) self._PRW_rfe_codes.SetText(val, data) # AOE self._TCTRL_aoe.SetValue(gmTools.coalesce(self.__encounter['assessment_of_encounter'], '')) val, data = self._PRW_aoe_codes.generic_linked_codes2item_dict(self.__encounter.generic_codes_aoe) self._PRW_aoe_codes.SetText(val, data) # last affirmed if self.__encounter['last_affirmed'] == self.__encounter['started']: self._PRW_end.SetFocus() else: self._TCTRL_aoe.SetFocus() return True
#============================================================ # main #------------------------------------------------------------ if __name__ == '__main__': if len(sys.argv) < 2: sys.exit() if sys.argv[1] != "test": sys.exit() gmI18N.activate_locale() gmI18N.install_domain('gnumed') from Gnumed.business import gmPraxis praxis = gmPraxis.gmCurrentPraxisBranch(branch = gmPraxis.get_praxis_branches()[0]) from Gnumed.business import gmPerson # 14 / 20 / 138 / 58 / 20 / 5 pat = gmPerson.gmCurrentPatient(gmPerson.cPatient(aPK_obj = 14)) fname = '~/gnumed/gm2tl-%s.timeline' % pat.subdir_name print (create_timeline_file ( patient = pat, filename = os.path.expanduser(fname), include_documents = True, include_vaccinations = True, include_encounters = True ))
def __import_single_PID_hl7_file(filename, emr=None): """Assumes single-PID/single-MSH HL7 file.""" _log.debug('importing single-PID single-MSH HL7 data from [%s]', filename) # read the file MSH_file = io.open(filename, mode = 'rt', encoding = 'utf8') HL7 = pyhl7.parse(MSH_file.read(1024 * 1024 * 5)) # 5 MB max MSH_file.close() # sanity checks if len(HL7.segments('MSH')) != 1: _log.error('more than one MSH segment') return False if len(HL7.segments('PID')) != 1: _log.error('more than one PID segment') return False # ensure lab is in database hl7_lab = HL7.extract_field('MSH', field_num = MSH_field__sending_lab) gm_lab = __find_or_create_lab(hl7_lab) # ensure test types exist conn = gmPG2.get_connection(readonly = False) __ensure_hl7_test_types_exist_in_gnumed(link_obj = conn, hl7_data = HL7, pk_test_org = gm_lab['pk_test_org']) # find patient if emr is None: #PID = HL7.segment('PID') pats = __PID2dto(HL7 = HL7) if len(pats) == 0: conn.rollback() return False if len(pats) > 1: conn.rollback() return False emr = pats[0].emr # import values: loop over segments when_list = {} current_result = None previous_segment = None had_errors = False msh_seen = False pid_seen = False last_obr = None obr = {} for seg_idx in range(len(HL7)): seg = HL7[seg_idx] seg_type = seg[0][0] _log.debug('processing line #%s = segment of type <%s>', seg_idx, seg_type) if seg_type == u'MSH': msh_seen = True if seg_type == u'PID': if not msh_seen: conn.rollback() _log.error('PID segment before MSH segment') return False pid_seen = True if seg_type in [u'MSH', u'PID']: _log.info('segment already handled') previous_segment = seg_type obr = {} current_result = None continue if seg_type in [u'ORC']: _log.info('currently ignoring %s segments', seg_type) previous_segment = seg_type obr = {} current_result = None continue if seg_type == u'OBR': previous_segment = seg_type last_obr = seg current_result = None obr['abbrev'] = (u'%s' % seg[OBR_field__service_name][0]).strip() try: obr['name'] = (u'%s' % seg[OBR_field__service_name][1]).strip() except IndexError: obr['name'] = obr['abbrev'] for field_name in [OBR_field__ts_ended, OBR_field__ts_started, OBR_field__ts_specimen_received, OBR_field__ts_requested]: obr['clin_when'] = seg[field_name][0].strip() if obr['clin_when'] != u'': break continue if seg_type == u'OBX': current_result = None # determine value val_alpha = seg[OBX_field__value][0].strip() is_num, val_num = gmTools.input2decimal(initial = val_alpha) if is_num: val_alpha = None else: val_num = None val_alpha = val_alpha.replace('\.br\\', u'\n') # determine test type unit = seg[OBX_field__unit][0].strip() if unit == u'': if is_num: unit = u'1/1' else: unit = None test_type = __find_or_create_test_type ( loinc = u'%s' % seg[OBX_field__type][0][OBX_component__loinc-1], name = u'%s' % seg[OBX_field__type][0][OBX_component__name-1], pk_lab = gm_lab['pk_test_org'], unit = unit ) # eventually, episode should be read from lab_request epi = emr.add_episode ( link_obj = conn, episode_name = u'administrative', is_open = False, allow_dupes = False ) current_result = emr.add_test_result ( link_obj = conn, episode = epi['pk_episode'], type = test_type['pk_test_type'], intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'], val_num = val_num, val_alpha = val_alpha, unit = unit ) # handle range information et al ref_range = seg[OBX_field__range][0].strip() if ref_range != u'': current_result.reference_range = ref_range flag = seg[OBX_field__abnormal_flag][0].strip() if flag != u'': current_result['abnormality_indicator'] = flag current_result['status'] = seg[OBX_field__status][0].strip() current_result['val_grouping'] = seg[OBX_field__subid][0].strip() current_result['source_data'] = u'' if last_obr is not None: current_result['source_data'] += unicode(last_obr) current_result['source_data'] += u'\n' current_result['source_data'] += unicode(seg) clin_when = seg[OBX_field__timestamp][0].strip() if clin_when == u'': _log.warning('no <Observation timestamp> in OBX, trying OBR timestamp') clin_when = obr['clin_when'] try: clin_when = __hl7dt2pydt(clin_when) except ValueError: _log.exception('clin_when from OBX or OBR not useable, assuming <today>') if clin_when is not None: current_result['clin_when'] = clin_when current_result.save(conn = conn) when_list[gmDateTime.pydt_strftime(current_result['clin_when'], '%Y %b %d')] = 1 previous_segment = seg_type continue if seg_type == u'NTE': note = seg[NET_field__note][0].strip().replace('\.br\\', u'\n') if note == u'': _log.debug('empty NTE segment') previous_segment = seg_type # maybe not ? (HL7 providers happen to use empty NTE segments to "structure" raw HL7 |-) continue # if this is an NTE following an OBR (IOW an order-related # comment): make this a test result all of its own :-) if previous_segment == u'OBR': _log.debug('NTE following OBR: general note, using OBR timestamp [%s]', obr['clin_when']) current_result = None name = obr['name'] if name == u'': name = _('Comment') # FIXME: please suggest a LOINC for "order comment" test_type = __find_or_create_test_type(name = name, pk_lab = gm_lab['pk_test_org'], abbrev = obr['abbrev']) # eventually, episode should be read from lab_request epi = emr.add_episode ( link_obj = conn, episode_name = u'administrative', is_open = False, allow_dupes = False ) nte_result = emr.add_test_result ( link_obj = conn, episode = epi['pk_episode'], type = test_type['pk_test_type'], intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'], val_alpha = note ) #nte_result['val_grouping'] = seg[OBX_field__subid][0].strip() nte_result['source_data'] = unicode(seg) try: nte_result['clin_when'] = __hl7dt2pydt(obr['clin_when']) except ValueError: _log.exception('no .clin_when from OBR for NTE pseudo-OBX available') nte_result.save(conn = conn) continue if (previous_segment == u'OBX') and (current_result is not None): current_result['source_data'] += u'\n' current_result['source_data'] += unicode(seg) current_result['note_test_org'] = gmTools.coalesce ( current_result['note_test_org'], note, u'%%s\n%s' % note ) current_result.save(conn = conn) previous_segment = seg_type continue _log.error(u'unexpected NTE segment') had_errors = True break _log.error('unknown segment, aborting') _log.debug('line: %s', seg) had_errors = True break if had_errors: conn.rollback() return False conn.commit() # record import in chart try: no_results = len(HL7.segments('OBX')) except KeyError: no_results = u'?' soap = _( 'Imported HL7 file [%s]:\n' ' lab "%s" (%s@%s), %s results (%s)' ) % ( filename, hl7_lab, gm_lab['unit'], gm_lab['organization'], no_results, u' / '.join(when_list.keys()) ) epi = emr.add_episode ( episode_name = u'administrative', is_open = False, allow_dupes = False ) emr.add_clin_narrative ( note = soap, soap_cat = None, episode = epi ) # keep copy of HL7 data in document archive folder = gmPerson.cPatient(emr.pk_patient).document_folder hl7_docs = folder.get_documents ( doc_type = u'HL7 data', episodes = [epi['pk_episode']], order_by = u'ORDER BY clin_when DESC' ) if len(hl7_docs) > 0: # there should only ever be one unless the user manually creates more, # also, it should always be the latest since "ORDER BY clin_when DESC" hl7_doc = hl7_docs[0] else: hl7_doc = folder.add_document ( document_type = u'HL7 data', encounter = emr.active_encounter['pk_encounter'], episode = epi['pk_episode'] ) hl7_doc['comment'] = _('list of imported HL7 data files') hl7_doc['clin_when'] = gmDateTime.pydt_now_here() hl7_doc.save() part = hl7_doc.add_part(file = filename) part['obj_comment'] = _('Result dates: %s') % u' / '.join(when_list.keys()) part.save() hl7_doc.set_reviewed(technically_abnormal = False, clinically_relevant = False) return True
def get_patients(self, search_term = None, a_locale = None, dto = None): identities = self.get_identities(search_term, a_locale, dto) if identities is None: return None return [ gmPerson.cPatient(aPK_obj=ident['pk_identity']) for ident in identities ]
def __import_single_PID_hl7_file(filename, emr=None): """Assumes single-PID/single-MSH HL7 file.""" _log.debug('importing single-PID single-MSH HL7 data from [%s]', filename) # read the file MSH_file = io.open(filename, mode = 'rt', encoding = 'utf8', newline = '') HL7 = pyhl7.parse(MSH_file.read(1024 * 1024 * 5)) # 5 MB max MSH_file.close() # sanity checks if len(HL7.segments('MSH')) != 1: _log.error('more than one MSH segment') return False if len(HL7.segments('PID')) != 1: _log.error('more than one PID segment') return False # ensure lab is in database hl7_lab = HL7.extract_field('MSH', field_num = MSH_field__sending_lab) gm_lab = __find_or_create_lab(hl7_lab) # ensure test types exist conn = gmPG2.get_connection(readonly = False) __ensure_hl7_test_types_exist_in_gnumed(link_obj = conn, hl7_data = HL7, pk_test_org = gm_lab['pk_test_org']) # find patient if emr is None: #PID = HL7.segment('PID') pats = __PID2dto(HL7 = HL7) if len(pats) == 0: conn.rollback() return False if len(pats) > 1: conn.rollback() return False emr = pats[0].emr # import values: loop over segments when_list = {} current_result = None previous_segment = None had_errors = False msh_seen = False pid_seen = False last_obr = None obr = {} for seg_idx in range(len(HL7)): seg = HL7[seg_idx] seg_type = seg[0][0] _log.debug('processing line #%s = segment of type <%s>', seg_idx, seg_type) if seg_type == 'MSH': msh_seen = True if seg_type == 'PID': if not msh_seen: conn.rollback() _log.error('PID segment before MSH segment') return False pid_seen = True if seg_type in ['MSH', 'PID']: _log.info('segment already handled') previous_segment = seg_type obr = {} current_result = None continue if seg_type in ['ORC']: _log.info('currently ignoring %s segments', seg_type) previous_segment = seg_type obr = {} current_result = None continue if seg_type == 'OBR': previous_segment = seg_type last_obr = seg current_result = None obr['abbrev'] = ('%s' % seg[OBR_field__service_name][0]).strip() try: obr['name'] = ('%s' % seg[OBR_field__service_name][1]).strip() except IndexError: obr['name'] = obr['abbrev'] for field_name in [OBR_field__ts_ended, OBR_field__ts_started, OBR_field__ts_specimen_received, OBR_field__ts_requested]: obr['clin_when'] = seg[field_name][0].strip() if obr['clin_when'] != '': break continue if seg_type == 'OBX': current_result = None # determine value val_alpha = seg[OBX_field__value][0].strip() is_num, val_num = gmTools.input2decimal(initial = val_alpha) if is_num: val_alpha = None else: val_num = None val_alpha = val_alpha.replace('\.br\\', '\n') # determine test type unit = seg[OBX_field__unit][0].strip() if unit == '': if is_num: unit = '1/1' else: unit = None test_type = __find_or_create_test_type ( loinc = '%s' % seg[OBX_field__type][0][OBX_component__loinc-1], name = '%s' % seg[OBX_field__type][0][OBX_component__name-1], pk_lab = gm_lab['pk_test_org'], unit = unit, link_obj = conn ) # eventually, episode should be read from lab_request epi = emr.add_episode ( link_obj = conn, episode_name = 'administrative', is_open = False, allow_dupes = False ) current_result = emr.add_test_result ( link_obj = conn, episode = epi['pk_episode'], type = test_type['pk_test_type'], intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'], val_num = val_num, val_alpha = val_alpha, unit = unit ) # handle range information et al ref_range = seg[OBX_field__range][0].strip() if ref_range != '': current_result.reference_range = ref_range flag = seg[OBX_field__abnormal_flag][0].strip() if flag != '': current_result['abnormality_indicator'] = flag current_result['status'] = seg[OBX_field__status][0].strip() current_result['val_grouping'] = seg[OBX_field__subid][0].strip() current_result['source_data'] = '' if last_obr is not None: current_result['source_data'] += str(last_obr) current_result['source_data'] += '\n' current_result['source_data'] += str(seg) clin_when = seg[OBX_field__timestamp][0].strip() if clin_when == '': _log.warning('no <Observation timestamp> in OBX, trying OBR timestamp') clin_when = obr['clin_when'] try: clin_when = __hl7dt2pydt(clin_when) except ValueError: _log.exception('clin_when from OBX or OBR not useable, assuming <today>') if clin_when is not None: current_result['clin_when'] = clin_when current_result.save(conn = conn) when_list[gmDateTime.pydt_strftime(current_result['clin_when'], '%Y %b %d')] = 1 previous_segment = seg_type continue if seg_type == 'NTE': note = seg[NET_field__note][0].strip().replace('\.br\\', '\n') if note == '': _log.debug('empty NTE segment') previous_segment = seg_type # maybe not ? (HL7 providers happen to use empty NTE segments to "structure" raw HL7 |-) continue # if this is an NTE following an OBR (IOW an order-related # comment): make this a test result all of its own :-) if previous_segment == 'OBR': _log.debug('NTE following OBR: general note, using OBR timestamp [%s]', obr['clin_when']) current_result = None name = obr['name'] if name == '': name = _('Comment') # FIXME: please suggest a LOINC for "order comment" test_type = __find_or_create_test_type(name = name, pk_lab = gm_lab['pk_test_org'], abbrev = obr['abbrev'], link_obj = conn) # eventually, episode should be read from lab_request epi = emr.add_episode ( link_obj = conn, episode_name = 'administrative', is_open = False, allow_dupes = False ) nte_result = emr.add_test_result ( link_obj = conn, episode = epi['pk_episode'], type = test_type['pk_test_type'], intended_reviewer = gmStaff.gmCurrentProvider()['pk_staff'], val_alpha = note ) #nte_result['val_grouping'] = seg[OBX_field__subid][0].strip() nte_result['source_data'] = str(seg) try: nte_result['clin_when'] = __hl7dt2pydt(obr['clin_when']) except ValueError: _log.exception('no .clin_when from OBR for NTE pseudo-OBX available') nte_result.save(conn = conn) continue if (previous_segment == 'OBX') and (current_result is not None): current_result['source_data'] += '\n' current_result['source_data'] += str(seg) current_result['note_test_org'] = gmTools.coalesce ( current_result['note_test_org'], note, '%%s\n%s' % note ) current_result.save(conn = conn) previous_segment = seg_type continue _log.error('unexpected NTE segment') had_errors = True break _log.error('unknown segment, aborting') _log.debug('line: %s', seg) had_errors = True break if had_errors: conn.rollback() return False conn.commit() # record import in chart try: no_results = len(HL7.segments('OBX')) except KeyError: no_results = '?' soap = _( 'Imported HL7 file [%s]:\n' ' lab "%s" (%s@%s), %s results (%s)' ) % ( filename, hl7_lab, gm_lab['unit'], gm_lab['organization'], no_results, ' / '.join(list(when_list)) ) epi = emr.add_episode ( episode_name = 'administrative', is_open = False, allow_dupes = False ) emr.add_clin_narrative ( note = soap, soap_cat = None, episode = epi ) # keep copy of HL7 data in document archive folder = gmPerson.cPatient(emr.pk_patient).document_folder hl7_docs = folder.get_documents ( doc_type = 'HL7 data', pk_episodes = [epi['pk_episode']], order_by = 'ORDER BY clin_when DESC' ) if len(hl7_docs) > 0: # there should only ever be one unless the user manually creates more, # also, it should always be the latest since "ORDER BY clin_when DESC" hl7_doc = hl7_docs[0] else: hl7_doc = folder.add_document ( document_type = 'HL7 data', encounter = emr.active_encounter['pk_encounter'], episode = epi['pk_episode'] ) hl7_doc['comment'] = _('list of imported HL7 data files') hl7_doc['pk_org_unit'] = gmPraxis.gmCurrentPraxisBranch()['pk_org_unit'] hl7_doc['clin_when'] = gmDateTime.pydt_now_here() hl7_doc.save() part = hl7_doc.add_part(file = filename) part['obj_comment'] = _('Result dates: %s') % ' / '.join(list(when_list)) part.save() hl7_doc.set_reviewed(technically_abnormal = False, clinically_relevant = False) return True
def process_staged_single_PID_hl7_file(staged_item): log_name = gmTools.get_unique_filename ( prefix = 'gm-staged_hl7_import-', suffix = '.log' ) import_logger = logging.FileHandler(log_name) import_logger.setLevel(logging.DEBUG) root_logger = logging.getLogger('') root_logger.addHandler(import_logger) _log.debug('log file: %s', log_name) if not staged_item.lock(): _log.error('cannot lock staged data for HL7 import') root_logger.removeHandler(import_logger) return False, log_name _log.debug('reference ID of staged HL7 data: %s', staged_item['external_data_id']) filename = staged_item.save_to_file() _log.debug('unstaged HL7 data into: %s', filename) if staged_item['pk_identity_disambiguated'] is None: emr = None else: emr = gmPerson.cPatient(staged_item['pk_identity_disambiguated']).emr success = False try: success = __import_single_PID_hl7_file(filename, emr = emr) if success: gmIncomingData.delete_incoming_data(pk_incoming_data = staged_item['pk_incoming_data_unmatched']) staged_item.unlock() root_logger.removeHandler(import_logger) return True, log_name _log.error('error when importing single-PID/single-MSH file') except Exception: _log.exception('error when importing single-PID/single-MSH file') if not success: staged_item['comment'] = _('failed import: %s\n') % gmDateTime.pydt_strftime(gmDateTime.pydt_now_here()) staged_item['comment'] += '\n' staged_item['comment'] += ('-' * 80) staged_item['comment'] += '\n\n' log = io.open(log_name, mode = 'rt', encoding = 'utf8') staged_item['comment'] += log.read() log.close() staged_item['comment'] += '\n' staged_item['comment'] += ('-' * 80) staged_item['comment'] += '\n\n' staged_item['comment'] += format_hl7_file ( filename, skip_empty_fields = True, eol = '\n ', return_filename = False ) staged_item.save() staged_item.unlock() root_logger.removeHandler(import_logger) return success, log_name
def refresh(self, encounter=None, msg=None): if msg is not None: self._LBL_instructions.SetLabel(msg) if encounter is not None: self.__encounter = encounter if self.__encounter is None: return True # getting the patient via the encounter allows us to act # on any encounter regardless of the currently active patient pat = gmPerson.cPatient(aPK_obj=self.__encounter['pk_patient']) self._LBL_patient.SetLabel(pat.get_description_gender().strip()) curr_pat = gmPerson.gmCurrentPatient() if curr_pat.connected: if curr_pat.ID == self.__encounter['pk_patient']: self._LBL_patient.SetForegroundColour( wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)) else: self._LBL_patient.SetForegroundColour('red') self._PRW_encounter_type.SetText(self.__encounter['l10n_type'], data=self.__encounter['pk_type']) self._PRW_location.Enable(True) branch = self.__encounter.praxis_branch if branch is None: # None or old entry because praxis has been re-configured unit = self.__encounter.org_unit if unit is None: # None self._PRW_location.SetText('', data=None) else: # old entry self._PRW_location.Enable(False) self._PRW_location.SetText( _('old praxis branch: %s (%s)') % (unit['unit'], unit['organization']), data=None) else: self._PRW_location.SetText(self.__encounter['praxis_branch'], data=branch['pk_praxis_branch']) fts = gmDateTime.cFuzzyTimestamp(timestamp=self.__encounter['started'], accuracy=gmDateTime.acc_minutes) self._PRW_start.SetText(fts.format_accurately(), data=fts) fts = gmDateTime.cFuzzyTimestamp( timestamp=self.__encounter['last_affirmed'], accuracy=gmDateTime.acc_minutes) self._PRW_end.SetText(fts.format_accurately(), data=fts) # RFE self._TCTRL_rfe.SetValue( gmTools.coalesce(self.__encounter['reason_for_encounter'], '')) val, data = self._PRW_rfe_codes.generic_linked_codes2item_dict( self.__encounter.generic_codes_rfe) self._PRW_rfe_codes.SetText(val, data) # AOE self._TCTRL_aoe.SetValue( gmTools.coalesce(self.__encounter['assessment_of_encounter'], '')) val, data = self._PRW_aoe_codes.generic_linked_codes2item_dict( self.__encounter.generic_codes_aoe) self._PRW_aoe_codes.SetText(val, data) # last affirmed if self.__encounter['last_affirmed'] == self.__encounter['started']: self._PRW_end.SetFocus() else: self._TCTRL_aoe.SetFocus() return True
def export(self, base_dir=None, items=None, expand_compressed=False): if items is None: items = self.items if len(items) == 0: return None media_base_dir = base_dir from Gnumed.business.gmPerson import cPatient pat = cPatient(aPK_obj=self.__pk_identity) if media_base_dir is None: media_base_dir = gmTools.mk_sandbox_dir(prefix=u'exp-%s-' % pat.dirname) _log.debug('patient media base dir: %s', media_base_dir) doc_dir = os.path.join(media_base_dir, r'documents') if os.path.isdir(doc_dir): index_existing_docs = True else: index_existing_docs = False gmTools.mkdir(doc_dir) _html_start_data = { u'html_title_header': _('Patient data for'), u'html_title_patient': gmTools.html_escape_string( pat.get_description_gender(with_nickname=False) + u', ' + _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')), u'title': _('Patient data export'), u'pat_name': gmTools.html_escape_string( pat.get_description_gender(with_nickname=False)), u'pat_dob': gmTools.html_escape_string( _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')), u'mugshot_url': u'documents/no-such-file.png', u'mugshot_alt': _('no patient photograph available'), u'mugshot_title': u'', u'docs_title': _(u'Documents'), u'browse_root': _(u'browse storage medium'), u'browse_docs': _(u'browse documents area'), u'browse_dicomdir': u'', u'run_dicom_viewer': u'' } mugshot = pat.document_folder.latest_mugshot if mugshot is not None: _html_start_data['mugshot_url'] = mugshot.save_to_file( directory=doc_dir, adjust_extension=True) _html_start_data['mugshot_alt'] = _( 'patient photograph from %s') % gmDateTime.pydt_strftime( mugshot['date_generated'], '%B %Y') _html_start_data['mugshot_title'] = gmDateTime.pydt_strftime( mugshot['date_generated'], '%B %Y') if u'DICOMDIR' in os.listdir(media_base_dir): _html_start_data[ u'browse_dicomdir'] = u'<li><a href="./DICOMDIR">%s</a></li>' % _( u'show DICOMDIR file') # copy DWV into target dir dwv_target_dir = os.path.join(media_base_dir, u'dwv') gmTools.rmdir(dwv_target_dir) dwv_src_dir = os.path.join(gmTools.gmPaths().local_base_dir, u'dwv4export') if not os.path.isdir(dwv_src_dir): dwv_src_dir = os.path.join( gmTools.gmPaths().system_app_data_dir, u'dwv4export') try: shutil.copytree(dwv_src_dir, dwv_target_dir) _html_start_data[ u'run_dicom_viewer'] = u'<li><a href="./dwv/viewers/mobile-local/index.html">%s</a></li>' % _( u'run Radiology Images (DICOM) Viewer') except shutil.Error, OSError: _log.exception('cannot include DWV, skipping')
target_year = end.year + 1 end = end.replace(year = target_year) timeline.write(xml_end % ( format_pydt(start), format_pydt(end) )) timeline.close() return timeline_fname #============================================================ # main #------------------------------------------------------------ if __name__ == '__main__': if len(sys.argv) < 2: sys.exit() if sys.argv[1] != "test": sys.exit() from Gnumed.pycommon import gmI18N gmI18N.activate_locale() gmI18N.install_domain('gnumed') from Gnumed.business import gmPerson # 14 / 20 / 138 / 58 / 20 / 5 pat = gmPerson.gmCurrentPatient(gmPerson.cPatient(aPK_obj = 12)) fname = u'~/tmp/gm2tl-%s.timeline' % pat.get_dirname() print create_timeline_file(patient = pat, filename = os.path.expanduser(fname))
def export(self, base_dir=None, items=None, with_metadata=True, expand_compressed=False): if items is None: items = self.items if len(items) == 0: return None from Gnumed.business.gmPerson import cPatient pat = cPatient(aPK_obj=self.__pk_identity) if base_dir is None: base_dir = gmTools.mk_sandbox_dir(prefix=u'exp-%s-' % pat.dirname) _log.debug('base dir: %s', base_dir) doc_dir = os.path.join(base_dir, r'documents') gmTools.mkdir(doc_dir) _html_start_data = { u'html_title_header': _('Patient data for'), u'html_title_patient': gmTools.html_escape_string( pat.get_description_gender(with_nickname=False) + u', ' + _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')), u'title': _('Patient data export'), u'pat_name': gmTools.html_escape_string( pat.get_description_gender(with_nickname=False)), u'pat_dob': gmTools.html_escape_string( _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')), u'mugshot_url': u'documents/no-such-file.png', u'mugshot_alt': _('no patient photograph available'), u'mugshot_title': u'', u'docs_title': _(u'Documents'), u'browse_root': _(u'browse storage medium'), u'browse_docs': _(u'browse documents area'), u'browse_dicomdir': u'' } mugshot = pat.document_folder.latest_mugshot if mugshot is not None: _html_start_data['mugshot_url'] = mugshot.export_to_file( directory=doc_dir) _html_start_data['mugshot_alt'] = _( 'patient photograph from %s') % gmDateTime.pydt_strftime( mugshot['date_generated'], '%B %Y') _html_start_data['mugshot_title'] = gmDateTime.pydt_strftime( mugshot['date_generated'], '%B %Y') # index.html idx_fname = os.path.join(base_dir, u'index.html') idx_file = io.open(idx_fname, mode=u'wt', encoding=u'utf8') # header existing_files = os.listdir(base_dir) if u'DICOMDIR' in existing_files: _html_start_data[ u'browse_dicomdir'] = u' <li><a href="./DICOMDIR">browse DICOMDIR</a></li>' idx_file.write(_html_start % _html_start_data) # middle for item in items: item_path = item.export_to_file(directory=doc_dir) item_fname = os.path.split(item_path)[1] idx_file.write( _html_list_item % (item_fname, gmTools.html_escape_string(item['description']))) # footer _cfg = gmCfg2.gmCfgData() from Gnumed.business.gmPraxis import gmCurrentPraxisBranch prax = gmCurrentPraxisBranch() lines = [] adr = prax.branch.org_unit.address if adr is not None: lines.extend(adr.format()) for comm in prax.branch.org_unit.comm_channels: if comm['is_confidential'] is True: continue lines.append(u'%s: %s' % (comm['l10n_comm_type'], comm['url'])) adr = u'' if len(lines) > 0: adr = gmTools.html_escape_string(u'\n'.join(lines), replace_eol=True, keep_visual_eol=True) _html_end_data = { 'branch': gmTools.html_escape_string(prax['branch']), 'praxis': gmTools.html_escape_string(prax['praxis']), 'date': gmTools.html_escape_string( gmDateTime.pydt_strftime(gmDateTime.pydt_now_here(), format='%Y %B %d', encoding=u'utf8')), 'gm_ver': gmTools.html_escape_string(_cfg.get(option=u'client_version')), #'gm_ver': 'git HEAD', # for testing 'adr': adr } idx_file.write(_html_end % _html_end_data) idx_file.close() # autorun.inf autorun_fname = os.path.join(base_dir, u'autorun.inf') autorun_file = io.open(autorun_fname, mode=u'wt', encoding=u'utf8') autorun_file.write( _autorun_inf % ((pat.get_description_gender(with_nickname=False) + u', ' + _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d')).strip(), _('Browse patient data'))) autorun_file.close() # cd.inf cd_inf_fname = os.path.join(base_dir, u'cd.inf') cd_inf_file = io.open(cd_inf_fname, mode=u'wt', encoding=u'utf8') cd_inf_file.write( _cd_inf % (pat['lastnames'], pat['firstnames'], gmTools.coalesce(pat['gender'], u'?'), pat.get_formatted_dob('%Y-%m-%d'), gmDateTime.pydt_strftime(gmDateTime.pydt_now_here(), format='%Y-%m-%d', encoding=u'utf8'), pat.ID, _cfg.get(option=u'client_version'), u' / '.join([ u'%s = %s (%s)' % (g['tag'], g['label'], g['l10n_label']) for g in pat.gender_list ]))) cd_inf_file.close() # README readme_fname = os.path.join(base_dir, u'README') readme_file = io.open(readme_fname, mode=u'wt', encoding=u'utf8') readme_file.write( _README % (pat.get_description_gender(with_nickname=False) + u', ' + _(u'born') + u' ' + pat.get_formatted_dob('%Y %B %d'))) readme_file.close() # patient demographics as GDT/XML/VCF pat.export_as_gdt(filename=os.path.join(base_dir, u'patient.gdt')) pat.export_as_xml_linuxmednews( filename=os.path.join(base_dir, u'patient.xml')) pat.export_as_vcard(filename=os.path.join(base_dir, u'patient.vcf')) # praxis VCF shutil.move(prax.vcf, os.path.join(base_dir, u'praxis.vcf')) return base_dir