def get_EDC(self, lmp=None, nullipara=True): result = cClinicalResult(_('unknown EDC')) result.formula_name = u'EDC (Mittendorf 1990)' result.formula_source = u'Mittendorf, R. et al., "The length of uncomplicated human gestation," OB/GYN, Vol. 75, No., 6 June, 1990, pp. 907-932.' if lmp is None: result.message = _('EDC: unknown LMP') return result result.variables['LMP'] = lmp result.variables['nullipara'] = nullipara if nullipara: result.variables['parity_offset'] = 15 # days else: result.variables['parity_offset'] = 10 # days now = gmDateTime.pydt_now_here() if lmp > now: result.warnings.append(_(u'LMP in the future')) if self.__patient is None: result.warnings.append(_(u'cannot run sanity checks, no patient')) else: if self.__patient['dob'] is None: result.warnings.append(_(u'cannot run sanity checks, no DOB')) else: years, months, days, hours, minutes, seconds = gmDateTime.calculate_apparent_age( start=self.__patient['dob']) # 5 years -- Myth ? # http://www.mirror.co.uk/news/uk-news/top-10-crazy-amazing-and-world-789842 if years < 10: result.warnings.append( _(u'patient less than 10 years old')) if self.__patient['gender'] in [None, u'm']: result.warnings.append( _(u'atypical gender for pregnancy: %s') % self.__patient.gender_string) if self.__patient['deceased'] is not None: result.warnings.append(_(u'patient already passed away')) if lmp.month > 3: edc_month = lmp.month - 3 edc_year = lmp.year + 1 else: edc_month = lmp.month + 9 edc_year = lmp.year result.numeric_value = gmDateTime.pydt_replace( dt=lmp, year=edc_year, month=edc_month, strict=False) + pydt.timedelta( days=result.variables['parity_offset']) result.message = _('EDC: %s') % gmDateTime.pydt_strftime( result.numeric_value, format='%Y %b %d') result.date_valid = now _log.debug(u'%s' % result) return result
def _get_egfr(self): # < 18 ? Schwartz = self.eGFR_Schwartz if Schwartz.numeric_value is not None: return Schwartz # this logic is based on "KVH aktuell 2/2014 Seite 10-15" # expect normal GFR CKD = self.eGFR_CKD_EPI if CKD.numeric_value is not None: if CKD.numeric_value > self.d(60): return CKD # CKD at or below 60 if self.__patient['dob'] is None: return CKD # no method will work, so return CKD anyway CG = self.eGFR_Cockcroft_Gault MDRD = self.eGFR_MDRD_short age = None if age is None: try: age = CKD.variables['age@crea'] except KeyError: _log.warning('CKD-EPI: no age@crea') if age is None: try: age = CG.variables['age@crea'] except KeyError: _log.warning('CG: no age@crea') if age is None: try: age = MDRD.variables['age@crea'] except KeyError: _log.warning('MDRD: no age@crea') if age is None: age = gmDateTime.calculate_apparent_age( start=self.__patient['dob'])[0] # geriatric ? if age > self.d(65): if CG.numeric_value is not None: return CG # non-geriatric or CG not computable if MDRD.numeric_value is None: if (CKD.numeric_value is not None) or (CG.numeric_value is None): return CKD return CG if MDRD.numeric_value > self.d(60): if CKD.numeric_value is not None: # probably normal after all (>60) -> use CKD-EPI return CKD return MDRD
def _get_egfr(self): # < 18 ? Schwartz = self.eGFR_Schwartz if Schwartz.numeric_value is not None: return Schwartz # this logic is based on "KVH aktuell 2/2014 Seite 10-15" # expect normal GFR CKD = self.eGFR_CKD_EPI if CKD.numeric_value is not None: if CKD.numeric_value > self.d(60): return CKD # CKD at or below 60 if self.__patient['dob'] is None: return CKD # no method will work, so return CKD anyway CG = self.eGFR_Cockcroft_Gault MDRD = self.eGFR_MDRD_short age = None if age is None: try: age = CKD.variables['age@crea'] except KeyError: _log.warning('CKD-EPI: no age@crea') if age is None: try: age = CG.variables['age@crea'] except KeyError: _log.warning('CG: no age@crea') if age is None: try: age = MDRD.variables['age@crea'] except KeyError: _log.warning('MDRD: no age@crea') if age is None: age = gmDateTime.calculate_apparent_age(start = self.__patient['dob'])[0] # geriatric ? if age > self.d(65): if CG.numeric_value is not None: return CG # non-geriatric or CG not computable if MDRD.numeric_value is None: if (CKD.numeric_value is not None) or (CG.numeric_value is None): return CKD return CG if MDRD.numeric_value > self.d(60): if CKD.numeric_value is not None: # probably normal after all (>60) -> use CKD-EPI return CKD return MDRD
def get_EDC(self, lmp=None, nullipara=True): result = cClinicalResult(_('unknown EDC')) result.formula_name = 'EDC (Mittendorf 1990)' result.formula_source = 'Mittendorf, R. et al., "The length of uncomplicated human gestation," OB/GYN, Vol. 75, No., 6 June, 1990, pp. 907-932.' if lmp is None: result.message = _('EDC: unknown LMP') return result result.variables['LMP'] = lmp result.variables['nullipara'] = nullipara if nullipara: result.variables['parity_offset'] = 15 # days else: result.variables['parity_offset'] = 10 # days now = gmDateTime.pydt_now_here() if lmp > now: result.warnings.append(_('LMP in the future')) if self.__patient is None: result.warnings.append(_('cannot run sanity checks, no patient')) else: if self.__patient['dob'] is None: result.warnings.append(_('cannot run sanity checks, no DOB')) else: years, months, days, hours, minutes, seconds = gmDateTime.calculate_apparent_age(start = self.__patient['dob']) # 5 years -- Myth ? # http://www.mirror.co.uk/news/uk-news/top-10-crazy-amazing-and-world-789842 if years < 10: result.warnings.append(_('patient less than 10 years old')) if self.__patient['gender'] in [None, 'm']: result.warnings.append(_('atypical gender for pregnancy: %s') % self.__patient.gender_string) if self.__patient['deceased'] is not None: result.warnings.append(_('patient already passed away')) if lmp.month > 3: edc_month = lmp.month - 3 edc_year = lmp.year + 1 else: edc_month = lmp.month + 9 edc_year = lmp.year result.numeric_value = gmDateTime.pydt_replace(dt = lmp, year = edc_year, month = edc_month, strict = False) + pydt.timedelta(days = result.variables['parity_offset']) result.message = _('EDC: %s') % gmDateTime.pydt_strftime ( result.numeric_value, format = '%Y %b %d' ) result.date_valid = now _log.debug('%s' % result) return result
def _get_gfr_cockcroft_gault(self): try: return self.__cache['cockcroft_gault'] except KeyError: pass result = cClinicalResult(_('unknown Cockcroft-Gault')) result.formula_name = u'eGFR from Cockcroft-Gault' result.formula_source = u'8/2014: http://en.wikipedia.org/Renal_function' result.hints.append(_('best @ age >65')) if self.__patient is None: result.message = _('Cockcroft-Gault: no patient') return result if self.__patient['dob'] is None: result.message = _('Cockcroft-Gault: no DOB (no age)') return result # 1) gender from Gnumed.business.gmPerson import map_gender2mf result.variables['gender'] = self.__patient['gender'] result.variables['gender_mf'] = map_gender2mf[self.__patient['gender']] if result.variables['gender_mf'] not in ['m', 'f']: result.message = _('Cockcroft-Gault: neither male nor female') return result # 2) creatinine result.variables[ 'serum_crea'] = self.__patient.emr.get_most_recent_results( loinc=gmLOINC.LOINC_creatinine_quantity, no_of_results=1) if result.variables['serum_crea'] is None: result.message = _( 'Cockcroft-Gault: serum creatinine value not found (LOINC: %s)' ) % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _('Cockcroft-Gault: creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d( result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in [u'mg/dl', u'mg/dL']: result.variables['unit_multiplier'] = self.d(72) if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d('1') else: #result.variables['gender_mf'] == 'f' result.variables['gender_multiplier'] = self.d('0.85') elif result.variables['serum_crea']['val_unit'] in [ u'µmol/L', u'µmol/l' ]: result.variables['unit_multiplier'] = self.d(1) if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d('1.23') else: #result.variables['gender_mf'] == 'f' result.variables['gender_multiplier'] = self.d('1.04') else: result.message = _( 'Cockcroft-Gault: unknown serum creatinine unit (%s)' ) % result.variables['serum_crea']['val_unit'] return result # 3) age (at creatinine evaluation) result.variables['dob'] = self.__patient['dob'] result.variables['age@crea'] = self.d( gmDateTime.calculate_apparent_age( start=result.variables['dob'], end=result.variables['serum_crea']['clin_when'])[0]) if (result.variables['age@crea'] < 18): result.message = _( 'Cockcroft-Gault: formula does not apply at age [%s] (17 < age)' ) % result.variables['age@crea'] return result result.variables[ 'weight'] = self.__patient.emr.get_most_recent_results( loinc=gmLOINC.LOINC_weight, no_of_results=1) if result.variables['weight'] is None: result.message = _('Cockcroft-Gault: weight not found') return result if result.variables['weight']['val_num'] is None: result.message = _('Cockcroft-Gault: weight not numeric') return result if result.variables['weight']['val_unit'] == u'kg': result.variables['weight_kg'] = self.d( result.variables['weight']['val_num']) elif result.variables['weight']['val_unit'] == u'g': result.variables['weight_kg'] = self.d( result.variables['weight']['val_num'] / self.d(1000)) else: result.message = _('Cockcroft-Gault: weight not in kg or g') return result # calculate result.numeric_value = (( (140 - result.variables['age@crea']) * result.variables['weight_kg'] * result.variables['gender_multiplier']) \ / \ (result.variables['unit_multiplier'] * result.variables['serum_crea_val']) ) result.unit = u'ml/min' #/1.73m² result.message = _('eGFR(CG): %.1f %s (%s)') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime( result.variables['serum_crea']['clin_when'], format='%Y %b %d')) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['cockroft_gault'] = result _log.debug(u'%s' % result) return result
def _get_gfr_ckd_epi(self): try: return self.__cache['CKD-EPI'] except KeyError: pass result = cClinicalResult(_('unknown CKD-EPI')) result.formula_name = u'eGFR from CKD-EPI' result.formula_source = u'8/2014: http://en.wikipedia.org/Renal_function' result.hints.append(_('best @ GFR > 60 ml/min')) if self.__patient is None: result.message = _('CKD-EPI: no patient') return result if self.__patient['dob'] is None: result.message = _('CKD-EPI: no DOB (no age)') return result # 1) gender from Gnumed.business.gmPerson import map_gender2mf result.variables['gender'] = self.__patient['gender'] result.variables['gender_mf'] = map_gender2mf[self.__patient['gender']] if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d(1) result.variables['k:gender_divisor'] = self.d('0.9') result.variables['a:gender_power'] = self.d('-0.411') elif result.variables['gender_mf'] == 'f': result.variables['gender_multiplier'] = self.d('1.018') result.variables['k:gender_divisor'] = self.d('0.7') result.variables['a:gender_power'] = self.d('-0.329') else: result.message = _('CKD-EPI: neither male nor female') return result # 2) creatinine result.variables[ 'serum_crea'] = self.__patient.emr.get_most_recent_results( loinc=gmLOINC.LOINC_creatinine_quantity, no_of_results=1) if result.variables['serum_crea'] is None: result.message = _( 'CKD-EPI: serum creatinine value not found (LOINC: %s)' ) % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _('CKD-EPI: creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d( result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in [u'mg/dl', u'mg/dL']: result.variables['serum_crea_val'] = self.d( result.variables['serum_crea']['val_num']) elif result.variables['serum_crea']['val_unit'] in [ u'µmol/L', u'µmol/l' ]: result.variables['serum_crea_val'] = self.d( result.variables['serum_crea']['val_num']) / self.d('88.4') else: result.message = _('CKD-EPI: unknown serum creatinine unit (%s)' ) % result.variables['serum_crea']['val_unit'] return result # 3) age (at creatinine evaluation) result.variables['dob'] = self.__patient['dob'] result.variables['age@crea'] = self.d( gmDateTime.calculate_apparent_age( start=result.variables['dob'], end=result.variables['serum_crea']['clin_when'])[0]) # if (result.variables['age@crea'] > 84) or (result.variables['age@crea'] < 18): # result.message = _('CKD-EPI: formula does not apply at age [%s] (17 < age < 85)') % result.variables['age@crea'] # return result # 4) ethnicity result.variables['ethnicity_multiplier'] = self.d(1) # non-black result.warnings.append( _('ethnicity: GNUmed does not know patient ethnicity, ignoring correction factor of 1.519 for "black"' )) # calculate result.numeric_value = ( self.d(141) * \ pow(min((result.variables['serum_crea_val'] / result.variables['k:gender_divisor']), self.d(1)), result.variables['a:gender_power']) * \ pow(max((result.variables['serum_crea_val'] / result.variables['k:gender_divisor']), self.d(1)), self.d('-1.209')) * \ pow(self.d('0.993'), result.variables['age@crea']) * \ result.variables['gender_multiplier'] * \ result.variables['ethnicity_multiplier'] ) result.unit = u'ml/min/1.73m²' result.message = _('eGFR(CKD-EPI): %.1f %s (%s)') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime( result.variables['serum_crea']['clin_when'], format='%Y %b %d')) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['CKD-EPI'] = result _log.debug(u'%s' % result) return result
def _get_gfr_mdrd_short(self): try: return self.__cache['MDRD_short'] except KeyError: pass result = cClinicalResult(_('unknown MDRD (4 vars/IDMS)')) result.formula_name = u'eGFR from 4-variables IDMS-MDRD' result.formula_source = u'1/2013: http://en.wikipedia.org/Renal_function / http://www.ganfyd.org/index.php?title=Estimated_glomerular_filtration_rate (NHS)' result.hints.append(_('best @ 30 < GFR < 60 ml/min')) if self.__patient is None: result.message = _('MDRD (4 vars/IDMS): no patient') return result if self.__patient['dob'] is None: result.message = _('MDRD (4 vars/IDMS): no DOB (no age)') return result # 1) gender from Gnumed.business.gmPerson import map_gender2mf result.variables['gender'] = self.__patient['gender'] result.variables['gender_mf'] = map_gender2mf[self.__patient['gender']] if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d(1) elif result.variables['gender_mf'] == 'f': result.variables['gender_multiplier'] = self.d('0.742') else: result.message = _('MDRD (4 vars/IDMS): neither male nor female') return result # 2) creatinine result.variables[ 'serum_crea'] = self.__patient.emr.get_most_recent_results( loinc=gmLOINC.LOINC_creatinine_quantity, no_of_results=1) if result.variables['serum_crea'] is None: result.message = _( 'MDRD (4 vars/IDMS): serum creatinine value not found (LOINC: %s)' ) % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _( 'MDRD (4 vars/IDMS): creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d( result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in [u'mg/dl', u'mg/dL']: result.variables['unit_multiplier'] = self.d(175) # older: 186 elif result.variables['serum_crea']['val_unit'] in [ u'µmol/L', u'µmol/l' ]: result.variables['unit_multiplier'] = self.d(30849) # older: 32788 else: result.message = _( 'MDRD (4 vars/IDMS): unknown serum creatinine unit (%s)' ) % result.variables['serum_crea']['val_unit'] return result # 3) age (at creatinine evaluation) result.variables['dob'] = self.__patient['dob'] result.variables['age@crea'] = self.d( gmDateTime.calculate_apparent_age( start=result.variables['dob'], end=result.variables['serum_crea']['clin_when'])[0]) if (result.variables['age@crea'] > 84) or (result.variables['age@crea'] < 18): result.message = _( 'MDRD (4 vars/IDMS): formula does not apply at age [%s] (17 < age < 85)' ) % result.variables['age@crea'] return result # 4) ethnicity result.variables['ethnicity_multiplier'] = self.d(1) # non-black result.warnings.append( _('ethnicity: GNUmed does not know patient ethnicity, ignoring correction factor' )) # calculate result.numeric_value = result.variables['unit_multiplier'] * \ pow(result.variables['serum_crea_val'], self.d('-1.154')) * \ pow(result.variables['age@crea'], self.d('-0.203')) * \ result.variables['ethnicity_multiplier'] * \ result.variables['gender_multiplier'] result.unit = u'ml/min/1.73m²' BSA = self.body_surface_area result.sub_results.append(BSA) if BSA.numeric_value is None: result.warnings.append( _(u'NOT corrected for non-average body surface (average = 1.73m²)' )) else: result.variables['BSA'] = BSA.numeric_value result_numeric_value = result.numeric_value / BSA.numeric_value result.message = _('eGFR(MDRD): %.1f %s (%s) [4-vars, IDMS]') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime( result.variables['serum_crea']['clin_when'], format='%Y %b %d')) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['MDRD_short'] = result _log.debug(u'%s' % result) return result
def __update_age_label(self): # no patient if not self.curr_pat.connected: self._LBL_age.SetLabel(_('<Age>')) self._LBL_age.SetToolTip(_('no patient selected')) return # gender is always known tt = _('Gender: %s (%s) - %s\n') % (self.curr_pat.gender_symbol, gmTools.coalesce( self.curr_pat['gender'], '?'), self.curr_pat.gender_string) # dob is not known if self.curr_pat['dob'] is None: age = '%s %s' % (self.curr_pat.gender_symbol, self.curr_pat.get_formatted_dob()) self._LBL_age.SetLabel(age) self._LBL_age.SetToolTip(tt) return tt += _('Born: %s\n') % self.curr_pat.get_formatted_dob( format='%d %b %Y') # patient is dead if self.curr_pat['deceased'] is not None: tt += _('Died: %s\n') % gmDateTime.pydt_strftime( self.curr_pat['deceased'], '%d %b %Y') tt += _('At age: %s\n') % self.curr_pat['medical_age'] age = '%s %s - %s (%s)' % ( self.curr_pat.gender_symbol, self.curr_pat.get_formatted_dob(format='%d %b %Y'), gmDateTime.pydt_strftime( self.curr_pat['deceased'], '%d %b %Y'), self.curr_pat['medical_age']) if self.curr_pat['dob_is_estimated']: tt += _(' (date of birth and age are estimated)\n') self._LBL_age.SetLabel(age) self._LBL_age.SetToolTip(tt) return # patient alive now = gmDateTime.pydt_now_here() # patient birthday ? if self.curr_pat.get_formatted_dob( format='%m-%d', honor_estimation=False) == now.strftime('%m-%d'): template = _('%(sex)s %(dob)s (%(age)s today !)') tt += _("\nToday is the patient's birthday !\n\n") tt += _('Age: %s\n') % self.curr_pat['medical_age'] else: tt += _('Age: %s, birthday:\n') % self.curr_pat['medical_age'] if self.curr_pat.current_birthday_passed is True: template = '%(sex)s %(dob)s%(l_arr)s (%(age)s)' tt += ' ' + _('last: %s ago (this year)' ) % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=self.curr_pat.birthday_this_year, end=now)) + '\n' tt += ' ' + _( 'next: in %s (next year)' ) % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=now, end=self.curr_pat.birthday_next_year)) + '\n' elif self.curr_pat.current_birthday_passed is False: template = '%(sex)s %(r_arr)s%(dob)s (%(age)s)' tt += ' ' + _( 'next: in %s (this year)' ) % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=now, end=self.curr_pat.birthday_this_year)) + '\n' tt += ' ' + _('last: %s ago (last year)' ) % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=self.curr_pat.birthday_last_year, end=now)) + '\n' else: # None, unknown template = '%(sex)s %(dob)s (%(age)s)' # FIXME: if the age is below, say, 2 hours we should fire # a timer here that updates the age in increments of 1 minute ... :-) age = template % { 'sex': self.curr_pat.gender_symbol, 'dob': self.curr_pat.get_formatted_dob(format='%d %b %Y'), 'age': self.curr_pat['medical_age'], 'r_arr': gmTools.u_arrow2right, 'l_arr': gmTools.u_left_arrow } # Easter Egg ;-) if self.curr_pat['lastnames'] == 'Leibner': if self.curr_pat['firstnames'] == 'Steffi': if self.curr_pat['preferred'] == 'Wildfang': age = '%s %s' % (gmTools.u_black_heart, age) if self.curr_pat['dob_is_estimated']: tt += _(' (date of birth and age are estimated)\n') self._LBL_age.SetLabel(age) self._LBL_age.SetToolTip(tt)
def __update_age_label(self): # no patient if not self.curr_pat.connected: self._LBL_age.SetLabel(_('<Age>')) self._LBL_age.SetToolTipString(_('no patient selected')) return # gender is always known tt = _(u'Gender: %s (%s) - %s\n') % ( self.curr_pat.gender_symbol, gmTools.coalesce(self.curr_pat[u'gender'], u'?'), self.curr_pat.gender_string ) # dob is not known if self.curr_pat['dob'] is None: age = u'%s %s' % ( self.curr_pat.gender_symbol, self.curr_pat.get_formatted_dob() ) self._LBL_age.SetLabel(age) self._LBL_age.SetToolTipString(tt) return tt += _('Born: %s\n') % self.curr_pat.get_formatted_dob(format = '%d %b %Y', encoding = gmI18N.get_encoding()) # patient is dead if self.curr_pat['deceased'] is not None: tt += _('Died: %s\n') % gmDateTime.pydt_strftime(self.curr_pat['deceased'], '%d %b %Y') tt += _('At age: %s\n') % self.curr_pat['medical_age'] age = u'%s %s - %s (%s)' % ( self.curr_pat.gender_symbol, self.curr_pat.get_formatted_dob(format = '%d %b %Y', encoding = gmI18N.get_encoding()), gmDateTime.pydt_strftime(self.curr_pat['deceased'], '%d %b %Y'), self.curr_pat['medical_age'] ) if self.curr_pat['dob_is_estimated']: tt += _(' (date of birth and age are estimated)\n') self._LBL_age.SetLabel(age) self._LBL_age.SetToolTipString(tt) return # patient alive now = gmDateTime.pydt_now_here() # patient birthday ? if self.curr_pat.get_formatted_dob(format = '%m-%d') == now.strftime('%m-%d'): template = _('%(sex)s %(dob)s (%(age)s today !)') tt += _("\nToday is the patient's birthday !\n\n") else: if self.curr_pat.current_birthday_passed(): template = u'%(sex)s %(dob)s%(l_arr)s (%(age)s)' tt += _(u'Birthday: %s ago\n') % gmDateTime.format_apparent_age_medically ( age = gmDateTime.calculate_apparent_age(start = self.curr_pat.birthday_this_year, end = now) ) else: template = u'%(sex)s %(r_arr)s%(dob)s (%(age)s)' tt += _(u'Birthday: in %s\n') % gmDateTime.format_apparent_age_medically ( age = gmDateTime.calculate_apparent_age(start = now, end = self.curr_pat.birthday_this_year) ) tt += _('Age: %s\n') % self.curr_pat['medical_age'] # FIXME: if the age is below, say, 2 hours we should fire # a timer here that updates the age in increments of 1 minute ... :-) age = template % { u'sex': self.curr_pat.gender_symbol, u'dob': self.curr_pat.get_formatted_dob(format = '%d %b %Y', encoding = gmI18N.get_encoding()), u'age': self.curr_pat['medical_age'], u'r_arr': gmTools.u_right_arrow, u'l_arr': gmTools.u_left_arrow } # Easter Egg ;-) if self.curr_pat['lastnames'] == u'Leibner': if self.curr_pat['firstnames'] == u'Steffi': if self.curr_pat['preferred'] == u'Wildfang': age = u'%s %s' % (gmTools.u_black_heart, age) if self.curr_pat['dob_is_estimated']: tt += _(' (date of birth and age are estimated)\n') self._LBL_age.SetLabel(age) self._LBL_age.SetToolTipString(tt)
def _get_gfr_schwartz(self): try: return self.__cache['gfr_schwartz'] except KeyError: pass result = cClinicalResult(_('unknown eGFR (Schwartz)')) result.formula_name = 'eGFR from updated Schwartz "bedside" formula (age < 19yrs)' result.formula_source = '1/2013: http://en.wikipedia.org/Renal_function / http://www.ganfyd.org/index.php?title=Estimated_glomerular_filtration_rate (NHS) / doi 10.1681/ASN.2008030287 / doi: 10.2215/CJN.01640309' result.hints.append(_('only applies @ age <18')) if self.__patient is None: result.message = _('eGFR (Schwartz): no patient') return result if self.__patient['dob'] is None: result.message = _('eGFR (Schwartz): DOB needed for age') return result result.variables['dob'] = self.__patient['dob'] # creatinine result.variables['serum_crea'] = self.__patient.emr.get_most_recent_results_in_loinc_group(loincs = gmLOINC.LOINC_creatinine_quantity, no_of_results = 1) if result.variables['serum_crea'] is None: result.message = _('eGFR (Schwartz): serum creatinine value not found (LOINC: %s') % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _('eGFR (Schwartz): creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d(result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in ['mg/dl', 'mg/dL']: result.variables['unit_multiplier'] = self.d(1) elif result.variables['serum_crea']['val_unit'] in ['µmol/L', 'µmol/l']: result.variables['unit_multiplier'] = self.d('0.00113') else: result.message = _('eGFR (Schwartz): unknown serum creatinine unit (%s)') % result.variables['serum_crea']['val_unit'] return result # age result.variables['age@crea'] = self.d ( gmDateTime.calculate_apparent_age ( start = result.variables['dob'], end = result.variables['serum_crea']['clin_when'] )[0] ) if result.variables['age@crea'] > 17: result.message = _('eGFR (Schwartz): formula does not apply at age [%s] (age must be <18)') % result.variables['age@crea'] return result # age-dependant constant if result.variables['age@crea'] < 1: # first year pre-term: k = 0.33 # first year full-term: k = (0.45) 0.41 (updated) result.variables['constant_for_age'] = self.d('0.41') result.warnings.append(_('eGFR (Schwartz): not known whether pre-term birth, applying full-term formula')) else: result.variables['constant_for_age'] = self.d('0.41') # height result.variables['height'] = self.__patient.emr.get_result_at_timestamp ( timestamp = result.variables['serum_crea']['clin_when'], loinc = gmLOINC.LOINC_height, tolerance_interval = '7 days' ) if result.variables['height'] is None: result.message = _('eGFR (Schwartz): height not found') return result if result.variables['height']['val_num'] is None: result.message = _('eGFR (Schwartz): height not numeric') return result if result.variables['height']['val_unit'] == 'cm': result.variables['height_cm'] = self.d(result.variables['height']['val_num']) elif result.variables['height']['val_unit'] == 'mm': result.variables['height_cm'] = self.d(result.variables['height']['val_num'] / self.d(10)) elif result.variables['height']['val_unit'] == 'm': result.variables['height_cm'] = self.d(result.variables['height']['val_num'] * 100) else: result.message = _('eGFR (Schwartz): height not in m, cm, or mm') return result # calculate result.numeric_value = ( result.variables['constant_for_age'] * result.variables['height_cm'] ) / ( result.variables['unit_multiplier'] * result.variables['serum_crea_val'] ) result.unit = 'ml/min/1.73m²' result.message = _('eGFR (Schwartz): %.1f %s (%s)') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime ( result.variables['serum_crea']['clin_when'], format = '%Y %b %d' ) ) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['gfr_schwartz'] = result _log.debug('%s' % result) return result
def _get_gfr_cockcroft_gault(self): try: return self.__cache['cockcroft_gault'] except KeyError: pass result = cClinicalResult(_('unknown Cockcroft-Gault')) result.formula_name = 'eGFR from Cockcroft-Gault' result.formula_source = '8/2014: http://en.wikipedia.org/Renal_function' result.hints.append(_('best @ age >65')) if self.__patient is None: result.message = _('Cockcroft-Gault: no patient') return result if self.__patient['dob'] is None: result.message = _('Cockcroft-Gault: no DOB (no age)') return result # 1) gender from Gnumed.business.gmPerson import map_gender2mf result.variables['gender'] = self.__patient['gender'] result.variables['gender_mf'] = map_gender2mf[self.__patient['gender']] if result.variables['gender_mf'] not in ['m', 'f']: result.message = _('Cockcroft-Gault: neither male nor female') return result # 2) creatinine result.variables['serum_crea'] = self.__patient.emr.get_most_recent_results_in_loinc_group(loincs = gmLOINC.LOINC_creatinine_quantity, no_of_results = 1) if result.variables['serum_crea'] is None: result.message = _('Cockcroft-Gault: serum creatinine value not found (LOINC: %s)') % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _('Cockcroft-Gault: creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d(result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in ['mg/dl', 'mg/dL']: result.variables['unit_multiplier'] = self.d(72) if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d('1') else: #result.variables['gender_mf'] == 'f' result.variables['gender_multiplier'] = self.d('0.85') elif result.variables['serum_crea']['val_unit'] in ['µmol/L', 'µmol/l']: result.variables['unit_multiplier'] = self.d(1) if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d('1.23') else: #result.variables['gender_mf'] == 'f' result.variables['gender_multiplier'] = self.d('1.04') else: result.message = _('Cockcroft-Gault: unknown serum creatinine unit (%s)') % result.variables['serum_crea']['val_unit'] return result # 3) age (at creatinine evaluation) result.variables['dob'] = self.__patient['dob'] result.variables['age@crea'] = self.d ( gmDateTime.calculate_apparent_age ( start = result.variables['dob'], end = result.variables['serum_crea']['clin_when'] )[0] ) if (result.variables['age@crea'] < 18): result.message = _('Cockcroft-Gault: formula does not apply at age [%s] (17 < age)') % result.variables['age@crea'] return result result.variables['weight'] = self.__patient.emr.get_most_recent_results_in_loinc_group(loincs = gmLOINC.LOINC_weight, no_of_results = 1) if result.variables['weight'] is None: result.message = _('Cockcroft-Gault: weight not found') return result if result.variables['weight']['val_num'] is None: result.message = _('Cockcroft-Gault: weight not numeric') return result if result.variables['weight']['val_unit'] == 'kg': result.variables['weight_kg'] = self.d(result.variables['weight']['val_num']) elif result.variables['weight']['val_unit'] == 'g': result.variables['weight_kg'] = self.d(result.variables['weight']['val_num'] / self.d(1000)) else: result.message = _('Cockcroft-Gault: weight not in kg or g') return result # calculate result.numeric_value = (( (140 - result.variables['age@crea']) * result.variables['weight_kg'] * result.variables['gender_multiplier']) \ / \ (result.variables['unit_multiplier'] * result.variables['serum_crea_val']) ) result.unit = 'ml/min' #/1.73m² result.message = _('eGFR(CG): %.1f %s (%s)') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime ( result.variables['serum_crea']['clin_when'], format = '%Y %b %d' ) ) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['cockroft_gault'] = result _log.debug('%s' % result) return result
def _get_gfr_ckd_epi(self): try: return self.__cache['CKD-EPI'] except KeyError: pass result = cClinicalResult(_('unknown CKD-EPI')) result.formula_name = 'eGFR from CKD-EPI' result.formula_source = '8/2014: http://en.wikipedia.org/Renal_function' result.hints.append(_('best @ GFR > 60 ml/min')) if self.__patient is None: result.message = _('CKD-EPI: no patient') return result if self.__patient['dob'] is None: result.message = _('CKD-EPI: no DOB (no age)') return result # 1) gender from Gnumed.business.gmPerson import map_gender2mf result.variables['gender'] = self.__patient['gender'] result.variables['gender_mf'] = map_gender2mf[self.__patient['gender']] if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d(1) result.variables['k:gender_divisor'] = self.d('0.9') result.variables['a:gender_power'] = self.d('-0.411') elif result.variables['gender_mf'] == 'f': result.variables['gender_multiplier'] = self.d('1.018') result.variables['k:gender_divisor'] = self.d('0.7') result.variables['a:gender_power'] = self.d('-0.329') else: result.message = _('CKD-EPI: neither male nor female') return result # 2) creatinine result.variables['serum_crea'] = self.__patient.emr.get_most_recent_results_in_loinc_group(loincs = gmLOINC.LOINC_creatinine_quantity, no_of_results = 1) if result.variables['serum_crea'] is None: result.message = _('CKD-EPI: serum creatinine value not found (LOINC: %s)') % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _('CKD-EPI: creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d(result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in ['mg/dl', 'mg/dL']: result.variables['serum_crea_val'] = self.d(result.variables['serum_crea']['val_num']) elif result.variables['serum_crea']['val_unit'] in ['µmol/L', 'µmol/l']: result.variables['serum_crea_val'] = self.d(result.variables['serum_crea']['val_num']) / self.d('88.4') else: result.message = _('CKD-EPI: unknown serum creatinine unit (%s)') % result.variables['serum_crea']['val_unit'] return result # 3) age (at creatinine evaluation) result.variables['dob'] = self.__patient['dob'] result.variables['age@crea'] = self.d ( gmDateTime.calculate_apparent_age ( start = result.variables['dob'], end = result.variables['serum_crea']['clin_when'] )[0] ) # if (result.variables['age@crea'] > 84) or (result.variables['age@crea'] < 18): # result.message = _('CKD-EPI: formula does not apply at age [%s] (17 < age < 85)') % result.variables['age@crea'] # return result # 4) ethnicity result.variables['ethnicity_multiplier'] = self.d(1) # non-black result.warnings.append(_('ethnicity: GNUmed does not know patient ethnicity, ignoring correction factor of 1.519 for "black"')) # calculate result.numeric_value = ( self.d(141) * \ pow(min((result.variables['serum_crea_val'] / result.variables['k:gender_divisor']), self.d(1)), result.variables['a:gender_power']) * \ pow(max((result.variables['serum_crea_val'] / result.variables['k:gender_divisor']), self.d(1)), self.d('-1.209')) * \ pow(self.d('0.993'), result.variables['age@crea']) * \ result.variables['gender_multiplier'] * \ result.variables['ethnicity_multiplier'] ) result.unit = 'ml/min/1.73m²' result.message = _('eGFR(CKD-EPI): %.1f %s (%s)') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime ( result.variables['serum_crea']['clin_when'], format = '%Y %b %d' ) ) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['CKD-EPI'] = result _log.debug('%s' % result) return result
def _get_gfr_mdrd_short(self): try: return self.__cache['MDRD_short'] except KeyError: pass result = cClinicalResult(_('unknown MDRD (4 vars/IDMS)')) result.formula_name = 'eGFR from 4-variables IDMS-MDRD' result.formula_source = '1/2013: http://en.wikipedia.org/Renal_function / http://www.ganfyd.org/index.php?title=Estimated_glomerular_filtration_rate (NHS)' result.hints.append(_('best @ 30 < GFR < 60 ml/min')) if self.__patient is None: result.message = _('MDRD (4 vars/IDMS): no patient') return result if self.__patient['dob'] is None: result.message = _('MDRD (4 vars/IDMS): no DOB (no age)') return result # 1) gender from Gnumed.business.gmPerson import map_gender2mf result.variables['gender'] = self.__patient['gender'] result.variables['gender_mf'] = map_gender2mf[self.__patient['gender']] if result.variables['gender_mf'] == 'm': result.variables['gender_multiplier'] = self.d(1) elif result.variables['gender_mf'] == 'f': result.variables['gender_multiplier'] = self.d('0.742') else: result.message = _('MDRD (4 vars/IDMS): neither male nor female') return result # 2) creatinine result.variables['serum_crea'] = self.__patient.emr.get_most_recent_results_in_loinc_group(loincs = gmLOINC.LOINC_creatinine_quantity, no_of_results = 1) if result.variables['serum_crea'] is None: result.message = _('MDRD (4 vars/IDMS): serum creatinine value not found (LOINC: %s)') % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _('MDRD (4 vars/IDMS): creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d(result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in ['mg/dl', 'mg/dL']: result.variables['unit_multiplier'] = self.d(175) # older: 186 elif result.variables['serum_crea']['val_unit'] in ['µmol/L', 'µmol/l']: result.variables['unit_multiplier'] = self.d(30849) # older: 32788 else: result.message = _('MDRD (4 vars/IDMS): unknown serum creatinine unit (%s)') % result.variables['serum_crea']['val_unit'] return result # 3) age (at creatinine evaluation) result.variables['dob'] = self.__patient['dob'] result.variables['age@crea'] = self.d ( gmDateTime.calculate_apparent_age ( start = result.variables['dob'], end = result.variables['serum_crea']['clin_when'] )[0] ) if (result.variables['age@crea'] > 84) or (result.variables['age@crea'] < 18): result.message = _('MDRD (4 vars/IDMS): formula does not apply at age [%s] (17 < age < 85)') % result.variables['age@crea'] return result # 4) ethnicity result.variables['ethnicity_multiplier'] = self.d(1) # non-black result.warnings.append(_('ethnicity: GNUmed does not know patient ethnicity, ignoring correction factor')) # calculate result.numeric_value = result.variables['unit_multiplier'] * \ pow(result.variables['serum_crea_val'], self.d('-1.154')) * \ pow(result.variables['age@crea'], self.d('-0.203')) * \ result.variables['ethnicity_multiplier'] * \ result.variables['gender_multiplier'] result.unit = 'ml/min/1.73m²' BSA = self.body_surface_area result.sub_results.append(BSA) if BSA.numeric_value is None: result.warnings.append(_('NOT corrected for non-average body surface (average = 1.73m²)')) else: result.variables['BSA'] = BSA.numeric_value result_numeric_value = result.numeric_value / BSA.numeric_value result.message = _('eGFR(MDRD): %.1f %s (%s) [4-vars, IDMS]') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime ( result.variables['serum_crea']['clin_when'], format = '%Y %b %d' ) ) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['MDRD_short'] = result _log.debug('%s' % result) return result
def create_timeline_file(patient=None, filename=None, include_documents=False, include_vaccinations=False, include_encounters=False): emr = patient.emr global now now = gmDateTime.pydt_now_here() if filename is None: timeline_fname = gmTools.get_unique_filename(prefix = 'gm-', suffix = '.timeline') # .timeline required ... else: timeline_fname = filename _log.debug('exporting EMR as timeline into [%s]', timeline_fname) timeline = io.open(timeline_fname, mode = 'wt', encoding = 'utf8', errors = 'xmlcharrefreplace') if patient['dob'] is None: lifespan_start = format_pydt(now.replace(year = now.year - 100)) else: lifespan_start = format_pydt(patient['dob']) if patient['deceased'] is None: life_ends2day = 'True' lifespan_end = format_pydt(now) else: life_ends2day = 'False' lifespan_end = format_pydt(patient['deceased']) earliest_care_date = emr.earliest_care_date most_recent_care_date = emr.most_recent_care_date if most_recent_care_date is None: most_recent_care_date = lifespan_end care_ends2day = life_ends2day else: most_recent_care_date = format_pydt(most_recent_care_date) care_ends2day = 'False' timeline.write(xml_start % ( # era: life span of patient _('Lifespan'), lifespan_start, lifespan_end, life_ends2day, ERA_NAME_CARE_PERIOD, format_pydt(earliest_care_date), most_recent_care_date, care_ends2day, # categories _('Health issues'), _('Episodes'), _('Encounters'), _('Hospital stays'), _('Procedures'), _('Documents'), _('Vaccinations'), _('Substances'), _('Life events') )) # birth if patient['dob'] is None: start = now.replace(year = now.year - 100) timeline.write(__xml_encounter_template % ( format_pydt(start), format_pydt(start), '?', _('Life events'), _('Date of birth unknown'), 'True' )) else: start = patient['dob'] timeline.write(__xml_encounter_template % ( format_pydt(patient['dob']), format_pydt(patient['dob']), '*', _('Life events'), _('Birth: %s') % patient.get_formatted_dob(format = '%Y %b %d %H:%M', honor_estimation = True), 'True' )) # start of care timeline.write(__xml_encounter_template % ( format_pydt(earliest_care_date), format_pydt(earliest_care_date), gmTools.u_heavy_greek_cross, _('Life events'), _('Start of Care: %s\n(the earliest recorded event of care in this praxis)') % format_pydt(earliest_care_date, format = '%Y %b %d'), 'True' )) # containers must be defined before their # subevents, so put health issues first timeline.write('\n <!-- ========================================\n Health issues\n======================================== -->') for issue in emr.health_issues: timeline.write(__format_health_issue_as_timeline_xml(issue, patient, emr)) timeline.write('\n <!-- ========================================\n Episodes\n======================================== -->') for epi in emr.get_episodes(order_by = 'pk_health_issue'): timeline.write(__format_episode_as_timeline_xml(epi, patient)) if include_encounters: timeline.write(u'\n<!--\n========================================\n Encounters\n======================================== -->') for enc in emr.get_encounters(skip_empty = True): timeline.write(__format_encounter_as_timeline_xml(enc, patient)) timeline.write('\n<!--\n========================================\n Hospital stays\n======================================== -->') for stay in emr.hospital_stays: timeline.write(__format_hospital_stay_as_timeline_xml(stay)) timeline.write('\n<!--\n========================================\n Procedures\n======================================== -->') for proc in emr.performed_procedures: timeline.write(__format_procedure_as_timeline_xml(proc)) if include_vaccinations: timeline.write(u'\n<!--\n========================================\n Vaccinations\n======================================== -->') for vacc in emr.vaccinations: timeline.write(__format_vaccination_as_timeline_xml(vacc)) timeline.write('\n<!--\n========================================\n Substance intakes\n======================================== -->') for intake in emr.get_current_medications(include_inactive = True, include_unapproved = False): timeline.write(__format_intake_as_timeline_xml(intake)) if include_documents: timeline.write(u'\n<!--\n========================================\n Documents\n======================================== -->') for doc in patient.document_folder.documents: timeline.write(__format_document_as_timeline_xml(doc)) # allergies ? # - unclear where and how to place # test results ? # - too many events, at most "day sample drawn" # death if patient['deceased'] is None: end = now else: end = patient['deceased'] death_ago = gmDateTime.format_apparent_age_medically ( age = gmDateTime.calculate_apparent_age(start = end, end = now) ) timeline.write(__xml_encounter_template % ( format_pydt(end), format_pydt(end), gmTools.u_dagger, _('Life events'), _('Death: %s\n(%s ago at age %s)') % ( format_pydt(end, format = '%Y %b %d %H:%M'), death_ago, patient.get_medical_age() ), 'True' )) # display range if end.month == 2: if end.day == 29: # leap years aren't consecutive end = end.replace(day = 28) 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
def _get_gfr_schwartz(self): try: return self.__cache['gfr_schwartz'] except KeyError: pass result = cClinicalResult(_('unknown eGFR (Schwartz)')) result.formula_name = u'eGFR from updated Schwartz "bedside" formula (age < 19yrs)' result.formula_source = u'1/2013: http://en.wikipedia.org/Renal_function / http://www.ganfyd.org/index.php?title=Estimated_glomerular_filtration_rate (NHS) / doi 10.1681/ASN.2008030287 / doi: 10.2215/CJN.01640309' result.hints.append(_('only applies @ age <18')) if self.__patient is None: result.message = _('eGFR (Schwartz): no patient') return result if self.__patient['dob'] is None: result.message = _('eGFR (Schwartz): DOB needed for age') return result result.variables['dob'] = self.__patient['dob'] # creatinine result.variables[ 'serum_crea'] = self.__patient.emr.get_most_recent_results( loinc=gmLOINC.LOINC_creatinine_quantity, no_of_results=1) if result.variables['serum_crea'] is None: result.message = _( 'eGFR (Schwartz): serum creatinine value not found (LOINC: %s' ) % gmLOINC.LOINC_creatinine_quantity return result if result.variables['serum_crea']['val_num'] is None: result.message = _('eGFR (Schwartz): creatinine value not numeric') return result result.variables['serum_crea_val'] = self.d( result.variables['serum_crea']['val_num']) if result.variables['serum_crea']['val_unit'] in [u'mg/dl', u'mg/dL']: result.variables['unit_multiplier'] = self.d(1) elif result.variables['serum_crea']['val_unit'] in [ u'µmol/L', u'µmol/l' ]: result.variables['unit_multiplier'] = self.d('0.00113') else: result.message = _( 'eGFR (Schwartz): unknown serum creatinine unit (%s)' ) % result.variables['serum_crea']['val_unit'] return result # age result.variables['age@crea'] = self.d( gmDateTime.calculate_apparent_age( start=result.variables['dob'], end=result.variables['serum_crea']['clin_when'])[0]) if result.variables['age@crea'] > 17: result.message = _( 'eGFR (Schwartz): formula does not apply at age [%s] (age must be <18)' ) % result.variables['age@crea'] return result # age-dependant constant if result.variables['age@crea'] < 1: # first year pre-term: k = 0.33 # first year full-term: k = (0.45) 0.41 (updated) result.variables['constant_for_age'] = self.d('0.41') result.warnings.append( _('eGFR (Schwartz): not known whether pre-term birth, applying full-term formula' )) else: result.variables['constant_for_age'] = self.d('0.41') # height result.variables[ 'height'] = self.__patient.emr.get_result_at_timestamp( timestamp=result.variables['serum_crea']['clin_when'], loinc=gmLOINC.LOINC_height, tolerance_interval='7 days') if result.variables['height'] is None: result.message = _('eGFR (Schwartz): height not found') return result if result.variables['height']['val_num'] is None: result.message = _('eGFR (Schwartz): height not numeric') return result if result.variables['height']['val_unit'] == u'cm': result.variables['height_cm'] = self.d( result.variables['height']['val_num']) elif result.variables['height']['val_unit'] == u'mm': result.variables['height_cm'] = self.d( result.variables['height']['val_num'] / self.d(10)) elif result.variables['height']['val_unit'] == u'm': result.variables['height_cm'] = self.d( result.variables['height']['val_num'] * 100) else: result.message = _('eGFR (Schwartz): height not in m, cm, or mm') return result # calculate result.numeric_value = (result.variables['constant_for_age'] * result.variables['height_cm']) / ( result.variables['unit_multiplier'] * result.variables['serum_crea_val']) result.unit = u'ml/min/1.73m²' result.message = _('eGFR (Schwartz): %.1f %s (%s)') % ( result.numeric_value, result.unit, gmDateTime.pydt_strftime( result.variables['serum_crea']['clin_when'], format='%Y %b %d')) result.date_valid = result.variables['serum_crea']['clin_when'] self.__cache['gfr_schwartz'] = result _log.debug(u'%s' % result) return result
def _get_body_mass_index(self): try: return self.__cache['body_mass_index'] except KeyError: pass result = cClinicalResult(_('unknown BMI')) result.formula_name = 'BMI/Quetelet Index' result.formula_source = '08/2014: https://en.wikipedia.org/wiki/Body_mass_index' if self.__patient is None: result.message = _('BMI: no patient') return result result.variables['height'] = self.__patient.emr.get_most_recent_results_in_loinc_group(loincs = gmLOINC.LOINC_height, no_of_results = 1) if result.variables['height'] is None: result.message = _('BMI: height not found') return result if result.variables['height']['val_num'] is None: result.message = _('BMI: height not numeric') return result if result.variables['height']['val_unit'] == 'cm': result.variables['height_m'] = self.d(result.variables['height']['val_num'] / self.d(100)) elif result.variables['height']['val_unit'] == 'mm': result.variables['height_m'] = self.d(result.variables['height']['val_num'] / self.d(1000)) elif result.variables['height']['val_unit'] == 'm': result.variables['height_m'] = self.d(result.variables['height']['val_num']) else: result.message = _('BMI: height not in m, cm, or mm') return result result.variables['weight'] = self.__patient.emr.get_result_at_timestamp ( timestamp = result.variables['height']['clin_when'], loinc = gmLOINC.LOINC_weight, tolerance_interval = '10 days' ) if result.variables['weight'] is None: result.message = _('BMI: weight not found') return result if result.variables['weight']['val_num'] is None: result.message = _('BMI: weight not numeric') return result if result.variables['weight']['val_unit'] == 'kg': result.variables['weight_kg'] = self.d(result.variables['weight']['val_num']) elif result.variables['weight']['val_unit'] == 'g': result.variables['weight_kg'] = self.d(result.variables['weight']['val_num'] / self.d(1000)) else: result.message = _('BMI: weight not in kg or g') return result result.variables['dob'] = self.__patient['dob'] start = result.variables['dob'] end = result.variables['height']['clin_when'] multiplier = 1 if end < start: start = result.variables['height']['clin_when'] end = result.variables['dob'] multiplier = -1 result.variables['age@height'] = multiplier * self.d(gmDateTime.calculate_apparent_age(start, end)[0]) if (result.variables['age@height'] < 18): result.message = _('BMI (Quetelet): formula does not apply at age [%s] (0 < age < 18)') % result.variables['age@height'] return result # bmi = mass kg / height m2 result.numeric_value = result.variables['weight_kg'] / (result.variables['height_m'] * result.variables['height_m']) result.unit = 'kg/m²' result.message = _('BMI (Quetelet): %.2f %s') % ( result.numeric_value, result.unit ) result.date_valid = gmDateTime.pydt_now_here() self.__cache['body_mass_index'] = result _log.debug('%s' % result) return result
def _get_body_mass_index(self): try: return self.__cache['body_mass_index'] except KeyError: pass result = cClinicalResult(_('unknown BMI')) result.formula_name = u'BMI/Quetelet Index' result.formula_source = u'08/2014: https://en.wikipedia.org/wiki/Body_mass_index' if self.__patient is None: result.message = _('BMI: no patient') return result result.variables[ 'height'] = self.__patient.emr.get_most_recent_results( loinc=gmLOINC.LOINC_height, no_of_results=1) if result.variables['height'] is None: result.message = _('BMI: height not found') return result if result.variables['height']['val_num'] is None: result.message = _('BMI: height not numeric') return result if result.variables['height']['val_unit'] == u'cm': result.variables['height_m'] = self.d( result.variables['height']['val_num'] / self.d(100)) elif result.variables['height']['val_unit'] == u'mm': result.variables['height_m'] = self.d( result.variables['height']['val_num'] / self.d(1000)) elif result.variables['height']['val_unit'] == u'm': result.variables['height_m'] = self.d( result.variables['height']['val_num']) else: result.message = _('BMI: height not in m, cm, or mm') return result result.variables[ 'weight'] = self.__patient.emr.get_result_at_timestamp( timestamp=result.variables['height']['clin_when'], loinc=gmLOINC.LOINC_weight, tolerance_interval='10 days') if result.variables['weight'] is None: result.message = _('BMI: weight not found') return result if result.variables['weight']['val_num'] is None: result.message = _('BMI: weight not numeric') return result if result.variables['weight']['val_unit'] == u'kg': result.variables['weight_kg'] = self.d( result.variables['weight']['val_num']) elif result.variables['weight']['val_unit'] == u'g': result.variables['weight_kg'] = self.d( result.variables['weight']['val_num'] / self.d(1000)) else: result.message = _('BMI: weight not in kg or g') return result result.variables['dob'] = self.__patient['dob'] start = result.variables['dob'] end = result.variables['height']['clin_when'] multiplier = 1 if end < start: start = result.variables['height']['clin_when'] end = result.variables['dob'] multiplier = -1 result.variables['age@height'] = multiplier * self.d( gmDateTime.calculate_apparent_age(start, end)[0]) if (result.variables['age@height'] < 18): result.message = _( 'BMI (Quetelet): formula does not apply at age [%s] (0 < age < 18)' ) % result.variables['age@height'] return result # bmi = mass kg / height m2 result.numeric_value = result.variables['weight_kg'] / ( result.variables['height_m'] * result.variables['height_m']) result.unit = u'kg/m²' result.message = _('BMI (Quetelet): %.2f %s') % (result.numeric_value, result.unit) result.date_valid = gmDateTime.pydt_now_here() self.__cache['body_mass_index'] = result _log.debug(u'%s' % result) return result
def __update_lab(self): if not self.curr_pat.connected: self._LBL_lab.SetLabel('') self._LBL_lab.SetToolTip(None) return tests2show = [] tooltip_lines = [] RRs = self.curr_pat.emr.get_most_recent_results_in_loinc_group( loincs=gmLOINC.LOINC_rr_quantity, max_no_of_results=1) if len(RRs) == 0: tests2show.append(_('BP ?')) else: tests2show.append(RRs[0]['unified_val']) tooltip_lines.append( _('BP: %s ago') % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=RRs[0]['clin_when']))) HRs = self.curr_pat.emr.get_most_recent_results_in_loinc_group( loincs=gmLOINC.LOINC_heart_rate_quantity, max_no_of_results=1) if len(HRs) > 0: tests2show.append('@ %s' % HRs[0]['unified_val']) tooltip_lines.append( _('%s (@) in bpm: %s ago') % (HRs[0]['abbrev_tt'], gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=HRs[0]['clin_when'])))) bmi = self.curr_pat.emr.bmi if bmi.numeric_value is not None: tests2show.append( _('BMI %s') % bmi.numeric_value.quantize(decimal.Decimal('1.'))) tooltip_lines.append( _('BMI: %s ago') % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=bmi.date_valid))) else: weights = self.curr_pat.emr.get_most_recent_results_in_loinc_group( loincs=gmLOINC.LOINC_weight, max_no_of_results=1) if len(weights) == 0: tests2show.append(_('BMI ?')) else: tests2show.append( '%s%s' % (weights[0]['unified_val'], weights[0]['val_unit'])) tooltip_lines.append( _('weight: %s ago') % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=weights[0]['clin_when']))) gfr_or_crea = self.curr_pat.emr.best_gfr_or_crea if gfr_or_crea is None: tests2show.append(_('GFR ?')) else: try: tests2show.append( _('GFR %s') % gfr_or_crea.numeric_value.quantize(decimal.Decimal('1.'))) tooltip_lines.append( _('GFR: %s ago') % gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=gfr_or_crea.date_valid))) except AttributeError: tests2show.append( '%s %s' % (gfr_or_crea['abbrev_tt'], gfr_or_crea['unified_val'])) tooltip_lines.append( _('%s: %s ago') % (gfr_or_crea['abbrev_tt'], gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=gfr_or_crea['clin_when'])))) edc = self.curr_pat.emr.EDC if edc is not None: if self.curr_pat.emr.EDC_is_fishy: tests2show.append( _('?EDC %s') % gmDateTime.pydt_strftime( edc, '%Y-%b-%d', accuracy=gmDateTime.acc_days)) else: tests2show.append( _('EDC %s') % gmDateTime.pydt_strftime( edc, '%Y-%b-%d', accuracy=gmDateTime.acc_days)) INRs = self.curr_pat.emr.get_most_recent_results_in_loinc_group( loincs=gmLOINC.LOINC_inr_quantity, max_no_of_results=1) if len(INRs) > 0: tests2show.append('%s %s' % (INRs[0]['abbrev_tt'], INRs[0]['unified_val'])) tooltip_lines.append( _('%s: %s ago') % (INRs[0]['abbrev_tt'], gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=INRs[0]['clin_when'])))) # include panel if configured, only show if exist if self.__lab_panel is not None: for result in self.__lab_panel.get_most_recent_results( pk_patient=self.curr_pat.ID, order_by='unified_abbrev', group_by_meta_type=True): tests2show.append('%s %s' % (result['abbrev_tt'], result['unified_val'])) tooltip_lines.append( _('%s: %s ago') % (result['abbrev_tt'], gmDateTime.format_apparent_age_medically( age=gmDateTime.calculate_apparent_age( start=result['clin_when'])))) self._LBL_lab.Label = '; '.join(tests2show) self._LBL_lab.SetToolTip('\n'.join(tooltip_lines))