Exemple #1
0
    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
Exemple #2
0
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)]
Exemple #3
0
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)]
Exemple #4
0
 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
     ]
Exemple #5
0
	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))
Exemple #6
0
 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))
Exemple #7
0
	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))
Exemple #8
0
	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
				))
Exemple #9
0
    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
Exemple #10
0
	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
		)
Exemple #11
0
	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
		)
Exemple #12
0
	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 ...')
Exemple #13
0
	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']
			)
Exemple #14
0
	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']
			)
Exemple #15
0
	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']
			)
Exemple #16
0
	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
Exemple #18
0
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
Exemple #19
0
	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
Exemple #20
0
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')
Exemple #21
0
    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
Exemple #22
0
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
Exemple #23
0
	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
Exemple #24
0
#============================================================
# 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
	))
Exemple #25
0
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
Exemple #26
0
	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 ]
Exemple #27
0
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
Exemple #28
0
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
Exemple #29
0
    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
Exemple #30
0
    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')
Exemple #31
0
	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))
Exemple #32
0
    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