Package Gnumed :: Package business :: Module gmPathLab
[frames] | no frames]

Source Code for Module Gnumed.business.gmPathLab

   1  """GNUmed measurements related business objects.""" 
   2  #============================================================ 
   3  __version__ = "$Revision: 1.81 $" 
   4  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" 
   5  __license__ = "GPL" 
   6   
   7   
   8  import types, sys, logging, codecs, decimal 
   9   
  10  if __name__ == '__main__': 
  11          sys.path.insert(0, '../../') 
  12   
  13  from Gnumed.pycommon import gmDateTime 
  14  if __name__ == '__main__': 
  15          from Gnumed.pycommon import gmLog2 
  16          from Gnumed.pycommon import gmI18N 
  17          gmDateTime.init() 
  18  from Gnumed.pycommon import gmExceptions 
  19  from Gnumed.pycommon import gmBusinessDBObject 
  20  from Gnumed.pycommon import gmPG2 
  21  from Gnumed.pycommon import gmTools 
  22  from Gnumed.pycommon import gmDispatcher 
  23  from Gnumed.pycommon import gmHooks 
  24   
  25   
  26  _log = logging.getLogger('gm.lab') 
  27  _log.info(__version__) 
  28   
  29  # FIXME: use UCUM from Regenstrief Institute 
  30   
  31  #============================================================ 
32 -def _on_test_result_modified():
33 """Always relates to the active patient.""" 34 gmHooks.run_hook_script(hook = u'after_test_result_modified')
35 36 gmDispatcher.connect(_on_test_result_modified, u'test_result_mod_db') 37 38 #============================================================
39 -class cTestOrg(gmBusinessDBObject.cBusinessDBObject):
40 """Represents one test org/lab.""" 41 42 _cmd_fetch_payload = u"""SELECT *, xmin FROM clin.test_org WHERE pk = %s""" 43 44 _cmds_store_payload = [ 45 u"""UPDATE clin.test_org SET 46 internal_name = gm.nullify_empty_string(%(internal_name)s), 47 contact = gm.nullify_empty_string(%(contact)s), 48 comment = gm.nullify_empty_string(%(comment)s) 49 WHERE 50 pk = %(pk)s 51 AND 52 xmin = %(xmin)s 53 RETURNING 54 xmin 55 """ 56 ] 57 58 _updatable_fields = [ 59 u'internal_name', 60 u'contact', 61 u'comment' 62 ]
63 #------------------------------------------------------------
64 -def create_test_org(name=None):
65 cmd = u'insert into clin.test_org (internal_name) values (%(name)s) returning pk' 66 args = {'name': name.strip()} 67 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 68 return cTestOrg(aPK_obj = rows[0]['pk'])
69 #------------------------------------------------------------
70 -def get_test_orgs(order_by=u'internal_name'):
71 cmd = u'select *, xmin from clin.test_org order by %s' % order_by 72 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 73 return [ cTestOrg(row = {'pk_field': 'pk', 'data': r, 'idx': idx}) for r in rows ]
74 #============================================================
75 -class cMetaTestType(gmBusinessDBObject.cBusinessDBObject):
76 """Represents one meta test type under which actual test types can be aggregated.""" 77 78 _cmd_fetch_payload = u"""select * from clin.meta_test_type where pk = %s""" 79 80 _cmds_store_payload = [] 81 82 _updatable_fields = []
83 #------------------------------------------------------------
84 -def delete_meta_type(meta_type=None):
85 cmd = u'delete from clin.meta_test_type where pk = %(pk)s' 86 args = {'pk': meta_type} 87 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
88 #------------------------------------------------------------
89 -def get_meta_test_types():
90 cmd = u'select * from clin.meta_test_type' 91 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 92 return [ cMetaTestType(row = {'pk_field': 'pk', 'data': r, 'idx': idx}) for r in rows ]
93 #============================================================
94 -class cUnifiedTestType(gmBusinessDBObject.cBusinessDBObject):
95 """Represents one unified test type.""" 96 97 # FIXME: if we ever want to write we need to include XMIN in the view 98 _cmd_fetch_payload = u"""select * from clin.v_unified_test_types where pk_test_type = %s""" 99 100 _cmds_store_payload = [] 101 102 _updatable_fields = [] 103 #--------------------------------------------------------
104 - def get_most_recent_result(self, pk_patient=None):
105 cmd = u""" 106 SELECT pk_test_result, clin_when 107 FROM clin.v_test_results 108 WHERE 109 pk_patient = %(pat)s 110 AND 111 pk_meta_test_type = %(pkmtt)s 112 ORDER BY clin_when DESC 113 LIMIT 1 114 """ 115 args = {'pat': pk_patient, 'pkmtt': self._payload[self._idx['pk_meta_test_type']]} 116 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 117 if len(rows) == 0: 118 return None 119 return cTestResult(aPK_obj = rows[0]['pk_test_result'])
120 #============================================================
121 -class cMeasurementType(gmBusinessDBObject.cBusinessDBObject):
122 """Represents one test result type.""" 123 124 _cmd_fetch_payload = u"""select * from clin.v_test_types where pk_test_type = %s""" 125 126 _cmds_store_payload = [ 127 u"""update clin.test_type set 128 abbrev = %(abbrev)s, 129 name = %(name)s, 130 loinc = gm.nullify_empty_string(%(loinc)s), 131 code = gm.nullify_empty_string(%(code)s), 132 coding_system = gm.nullify_empty_string(%(coding_system)s), 133 comment = gm.nullify_empty_string(%(comment_type)s), 134 conversion_unit = gm.nullify_empty_string(%(conversion_unit)s), 135 fk_test_org = %(pk_test_org)s 136 where pk = %(pk_test_type)s""", 137 u"""select xmin_test_type from clin.v_test_types where pk_test_type = %(pk_test_type)s""" 138 ] 139 140 _updatable_fields = [ 141 'abbrev', 142 'name', 143 'loinc', 144 'code', 145 'coding_system', 146 'comment_type', 147 'conversion_unit', 148 'pk_test_org' 149 ] 150 #--------------------------------------------------------
151 - def __setitem__(self, attribute, value):
152 153 # find fk_test_org from name 154 if (attribute == 'fk_test_org') and (value is not None): 155 try: 156 int(value) 157 except: 158 cmd = u"select pk from clin.test_org where internal_name = %(val)s" 159 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'val': value}}]) 160 if len(rows) == 0: 161 raise ValueError('[%s]: no test org for [%s], cannot set <%s>' % (self.__class__.__name__, value, attribute)) 162 value = rows[0][0] 163 164 gmBusinessDBObject.cBusinessDBObject.__setitem__(self, attribute, value)
165 #--------------------------------------------------------
166 - def _get_in_use(self):
167 cmd = u'select exists(select 1 from clin.test_result where fk_type = %(pk_type)s)' 168 args = {'pk_type': self._payload[self._idx['pk_test_type']]} 169 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 170 return rows[0][0]
171 172 in_use = property(_get_in_use, lambda x:x)
173 #------------------------------------------------------------
174 -def get_measurement_types(order_by=None):
175 cmd = u'select * from clin.v_test_types %s' % gmTools.coalesce(order_by, u'', u'order by %s') 176 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 177 return [ cMeasurementType(row = {'pk_field': 'pk_test_type', 'data': r, 'idx': idx}) for r in rows ]
178 #------------------------------------------------------------
179 -def find_measurement_type(lab=None, abbrev=None, name=None):
180 181 if (abbrev is None) and (name is None): 182 raise ValueError('must have <abbrev> and/or <name> set') 183 184 where_snippets = [] 185 186 if lab is None: 187 where_snippets.append('pk_test_org is null') 188 else: 189 try: 190 int(lab) 191 where_snippets.append('pk_test_org = %(lab)s') 192 except (TypeError, ValueError): 193 where_snippets.append('pk_test_org = (select pk from clin.test_org where internal_name = %(lab)s)') 194 195 if abbrev is not None: 196 where_snippets.append('abbrev = %(abbrev)s') 197 198 if name is not None: 199 where_snippets.append('name = %(name)s') 200 201 where_clause = u' and '.join(where_snippets) 202 cmd = u"select * from clin.v_test_types where %s" % where_clause 203 args = {'lab': lab, 'abbrev': abbrev, 'name': name} 204 205 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 206 207 if len(rows) == 0: 208 return None 209 210 tt = cMeasurementType(row = {'pk_field': 'pk_test_type', 'data': rows[0], 'idx': idx}) 211 return tt
212 #------------------------------------------------------------
213 -def delete_measurement_type(measurement_type=None):
214 cmd = u'delete from clin.test_type where pk = %(pk)s' 215 args = {'pk': measurement_type} 216 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
217 #------------------------------------------------------------
218 -def create_measurement_type(lab=None, abbrev=None, unit=None, name=None):
219 """Create or get test type.""" 220 221 ttype = find_measurement_type(lab = lab, abbrev = abbrev, name = name) 222 # found ? 223 if ttype is not None: 224 return ttype 225 226 _log.debug('creating test type [%s:%s:%s:%s]', lab, abbrev, name, unit) 227 228 # not found, so create it 229 if unit is None: 230 _log.error('need <unit> to create test type: %s:%s:%s:%s' % (lab, abbrev, name, unit)) 231 raise ValueError('need <unit> to create test type') 232 233 # make query 234 cols = [] 235 val_snippets = [] 236 vals = {} 237 238 # lab 239 if lab is None: 240 lab = create_measurement_org() 241 242 cols.append('fk_test_org') 243 try: 244 vals['lab'] = int(lab) 245 val_snippets.append('%(lab)s') 246 except: 247 vals['lab'] = lab 248 val_snippets.append('(select pk from clin.test_org where internal_name = %(lab)s)') 249 250 # code 251 cols.append('abbrev') 252 val_snippets.append('%(abbrev)s') 253 vals['abbrev'] = abbrev 254 255 # unit 256 cols.append('conversion_unit') 257 val_snippets.append('%(unit)s') 258 vals['unit'] = unit 259 260 # name 261 if name is not None: 262 cols.append('name') 263 val_snippets.append('%(name)s') 264 vals['name'] = name 265 266 col_clause = u', '.join(cols) 267 val_clause = u', '.join(val_snippets) 268 queries = [ 269 {'cmd': u'insert into clin.test_type (%s) values (%s)' % (col_clause, val_clause), 'args': vals}, 270 {'cmd': u"select * from clin.v_test_types where pk_test_type = currval(pg_get_serial_sequence('clin.test_type', 'pk'))"} 271 ] 272 rows, idx = gmPG2.run_rw_queries(queries = queries, get_col_idx = True, return_data = True) 273 ttype = cMeasurementType(row = {'pk_field': 'pk_test_type', 'data': rows[0], 'idx': idx}) 274 275 return ttype
276 #------------------------------------------------------------
277 -def create_measurement_org(name=None, comment=None):
278 279 if name is None: 280 name = _('inhouse lab') 281 comment = _('auto-generated') 282 283 cmd = u'select * from clin.test_org where internal_name = %(name)s' 284 if comment is not None: 285 comment = comment.strip() 286 args = {'name': name, 'cmt': comment} 287 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 288 289 if len(rows) == 0: 290 queries = [ 291 {'cmd': u'insert into clin.test_org (fk_org, internal_name, comment) values (null, %(name)s, %(cmt)s)', 'args': args}, 292 {'cmd': u"select currval(pg_get_serial_sequence('clin.test_org', 'pk')) as pk"} 293 ] 294 else: 295 # use 1st result only, ignore if more than one 296 args['pk'] = rows[0]['pk'] 297 queries = [ 298 {'cmd': u'update clin.test_org set comment = %(cmt)s where pk = %(pk)s', 'args': args}, 299 {'cmd': u'select %(pk)s as pk', 'args': args} 300 ] 301 302 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True) 303 304 return rows[0]['pk']
305 #============================================================
306 -class cTestResult(gmBusinessDBObject.cBusinessDBObject):
307 """Represents one test result.""" 308 309 _cmd_fetch_payload = u"select * from clin.v_test_results where pk_test_result = %s" 310 311 _cmds_store_payload = [ 312 u"""update clin.test_result set 313 clin_when = %(clin_when)s, 314 narrative = nullif(trim(%(comment)s), ''), 315 val_num = %(val_num)s, 316 val_alpha = nullif(trim(%(val_alpha)s), ''), 317 val_unit = nullif(trim(%(val_unit)s), ''), 318 val_normal_min = %(val_normal_min)s, 319 val_normal_max = %(val_normal_max)s, 320 val_normal_range = nullif(trim(%(val_normal_range)s), ''), 321 val_target_min = %(val_target_min)s, 322 val_target_max = %(val_target_max)s, 323 val_target_range = nullif(trim(%(val_target_range)s), ''), 324 abnormality_indicator = nullif(trim(%(abnormality_indicator)s), ''), 325 norm_ref_group = nullif(trim(%(norm_ref_group)s), ''), 326 note_test_org = nullif(trim(%(note_test_org)s), ''), 327 material = nullif(trim(%(material)s), ''), 328 material_detail = nullif(trim(%(material_detail)s), ''), 329 fk_intended_reviewer = %(pk_intended_reviewer)s, 330 fk_encounter = %(pk_encounter)s, 331 fk_episode = %(pk_episode)s, 332 fk_type = %(pk_test_type)s, 333 fk_request = %(pk_request)s 334 where 335 pk = %(pk_test_result)s and 336 xmin = %(xmin_test_result)s""", 337 u"""select xmin_test_result from clin.v_test_results where pk_test_result = %(pk_test_result)s""" 338 ] 339 340 _updatable_fields = [ 341 'clin_when', 342 'comment', 343 'val_num', 344 'val_alpha', 345 'val_unit', 346 'val_normal_min', 347 'val_normal_max', 348 'val_normal_range', 349 'val_target_min', 350 'val_target_max', 351 'val_target_range', 352 'abnormality_indicator', 353 'norm_ref_group', 354 'note_test_org', 355 'material', 356 'material_detail', 357 'pk_intended_reviewer', 358 'pk_encounter', 359 'pk_episode', 360 'pk_test_type', 361 'pk_request' 362 ] 363 #--------------------------------------------------------
364 - def format(self, with_review=True, with_comments=True, date_format='%Y-%m-%d %H:%M'):
365 366 lines = [] 367 368 lines.append(u' %s %s (%s): %s %s%s' % ( 369 self._payload[self._idx['clin_when']].strftime(date_format), 370 self._payload[self._idx['unified_abbrev']], 371 self._payload[self._idx['unified_name']], 372 self._payload[self._idx['unified_val']], 373 self._payload[self._idx['val_unit']], 374 gmTools.coalesce(self._payload[self._idx['abnormality_indicator']], u'', u' (%s)') 375 )) 376 377 if with_comments: 378 if gmTools.coalesce(self._payload[self._idx['comment']], u'').strip() != u'': 379 lines.append(_(' Doc: %s') % self._payload[self._idx['comment']].strip()) 380 if gmTools.coalesce(self._payload[self._idx['note_test_org']], u'').strip() != u'': 381 lines.append(_(' MTA: %s') % self._payload[self._idx['note_test_org']].strip()) 382 383 if with_review: 384 if self._payload[self._idx['reviewed']]: 385 if self._payload[self._idx['is_clinically_relevant']]: 386 lines.append(u' %s %s: %s' % ( 387 self._payload[self._idx['last_reviewer']], 388 self._payload[self._idx['last_reviewed']].strftime('%Y-%m-%d %H:%M'), 389 gmTools.bool2subst ( 390 self._payload[self._idx['is_technically_abnormal']], 391 _('abnormal and relevant'), 392 _('normal but relevant') 393 ) 394 )) 395 else: 396 lines.append(_(' unreviewed')) 397 398 return lines
399 #--------------------------------------------------------
400 - def _get_reference_ranges(self):
401 402 cmd = u""" 403 select 404 distinct on (norm_ref_group_str, val_unit, val_normal_min, val_normal_max, val_normal_range, val_target_min, val_target_max, val_target_range) 405 pk_patient, 406 val_unit, 407 val_normal_min, val_normal_max, val_normal_range, 408 val_target_min, val_target_max, val_target_range, 409 norm_ref_group, 410 coalesce(norm_ref_group, '') as norm_ref_group_str 411 from 412 clin.v_test_results 413 where 414 pk_test_type = %(pk_type)s 415 """ 416 args = {'pk_type': self._payload[self._idx['pk_test_type']]} 417 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 418 return rows
419
420 - def _set_reference_ranges(self, val):
421 raise AttributeError('[%s]: reference ranges not settable') % self.__class__.__name__
422 423 reference_ranges = property(_get_reference_ranges, _set_reference_ranges) 424 #--------------------------------------------------------
425 - def set_review(self, technically_abnormal=None, clinically_relevant=None, comment=None, make_me_responsible=False):
426 427 if comment is not None: 428 comment = comment.strip() 429 430 if ((technically_abnormal is None) and 431 (clinically_relevant is None) and 432 (comment is None) and 433 (make_me_responsible is False)): 434 return True 435 436 # FIXME: this is not concurrency safe 437 if self._payload[self._idx['reviewed']]: 438 self.__change_existing_review ( 439 technically_abnormal = technically_abnormal, 440 clinically_relevant = clinically_relevant, 441 comment = comment 442 ) 443 else: 444 self.__set_new_review ( 445 technically_abnormal = technically_abnormal, 446 clinically_relevant = clinically_relevant, 447 comment = comment 448 ) 449 450 if make_me_responsible is True: 451 cmd = u"select pk from dem.staff where db_user = current_user" 452 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) 453 self['pk_intended_reviewer'] = rows[0][0] 454 self.save_payload() 455 else: 456 self.refetch_payload()
457 #-------------------------------------------------------- 458 # internal API 459 #--------------------------------------------------------
460 - def __set_new_review(self, technically_abnormal=None, clinically_relevant=None, comment=None):
461 """Add a review to a row. 462 463 - if technically abnormal is not provided/None it will be set 464 to True if the lab's indicator has a meaningful value 465 - if clinically relevant is not provided/None it is set to 466 whatever technically abnormal is 467 """ 468 if technically_abnormal is None: 469 technically_abnormal = False 470 if self._payload[self._idx['abnormality_indicator']] is not None: 471 if self._payload[self._idx['abnormality_indicator']].strip() != u'': 472 technically_abnormal = True 473 474 if clinically_relevant is None: 475 clinically_relevant = technically_abnormal 476 477 cmd = u""" 478 insert into clin.reviewed_test_results ( 479 fk_reviewed_row, 480 is_technically_abnormal, 481 clinically_relevant, 482 comment 483 ) values ( 484 %(pk)s, 485 %(abnormal)s, 486 %(relevant)s, 487 %(cmt)s 488 )""" 489 args = { 490 'pk': self._payload[self._idx['pk_test_result']], 491 'abnormal': technically_abnormal, 492 'relevant': clinically_relevant, 493 'cmt': comment 494 } 495 496 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
497 #--------------------------------------------------------
498 - def __change_existing_review(self, technically_abnormal=None, clinically_relevant=None, comment=None):
499 """Change a review on a row. 500 501 - if technically abnormal/clinically relevant/comment are 502 None (or empty) they are not set 503 """ 504 args = { 505 'pk_row': self._payload[self._idx['pk_test_result']], 506 'abnormal': technically_abnormal, 507 'relevant': clinically_relevant 508 } 509 510 set_parts = [] 511 512 if technically_abnormal is not None: 513 set_parts.append(u'is_technically_abnormal = %(abnormal)s') 514 515 if clinically_relevant is not None: 516 set_parts.append(u'clinically_relevant= %(relevant)s') 517 518 if comment is not None: 519 set_parts.append('comment = %(cmt)s') 520 args['cmt'] = comment 521 522 cmd = u""" 523 update clin.reviewed_test_results set 524 fk_reviewer = (select pk from dem.staff where db_user = current_user), 525 %s 526 where 527 fk_reviewed_row = %%(pk_row)s 528 """ % u',\n '.join(set_parts) 529 530 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
531 #------------------------------------------------------------
532 -def delete_test_result(result=None):
533 534 try: 535 pk = int(result) 536 except (TypeError, AttributeError): 537 pk = result['pk_test_result'] 538 539 cmd = u'delete from clin.test_result where pk = %(pk)s' 540 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk}}])
541 #------------------------------------------------------------
542 -def create_test_result(encounter=None, episode=None, type=None, intended_reviewer=None, val_num=None, val_alpha=None, unit=None):
543 544 cmd1 = u""" 545 insert into clin.test_result ( 546 fk_encounter, 547 fk_episode, 548 fk_type, 549 fk_intended_reviewer, 550 val_num, 551 val_alpha, 552 val_unit 553 ) values ( 554 %(enc)s, 555 %(epi)s, 556 %(type)s, 557 %(rev)s, 558 %(v_num)s, 559 %(v_alpha)s, 560 %(unit)s 561 )""" 562 563 cmd2 = u""" 564 select * 565 from 566 clin.v_test_results 567 where 568 pk_test_result = currval(pg_get_serial_sequence('clin.test_result', 'pk'))""" 569 570 args = { 571 u'enc': encounter, 572 u'epi': episode, 573 u'type': type, 574 u'rev': intended_reviewer, 575 u'v_num': val_num, 576 u'v_alpha': val_alpha, 577 u'unit': unit 578 } 579 580 rows, idx = gmPG2.run_rw_queries ( 581 queries = [ 582 {'cmd': cmd1, 'args': args}, 583 {'cmd': cmd2} 584 ], 585 return_data = True, 586 get_col_idx = True 587 ) 588 589 tr = cTestResult(row = { 590 'pk_field': 'pk_test_result', 591 'idx': idx, 592 'data': rows[0] 593 }) 594 595 return tr
596 #------------------------------------------------------------
597 -def format_test_results(results=None, output_format=u'latex'):
598 599 _log.debug(u'formatting test results into [%s]', output_format) 600 601 if output_format == u'latex': 602 return __format_test_results_latex(results = results) 603 604 msg = _('unknown test results output format [%s]') % output_format 605 _log.error(msg) 606 return msg
607 #------------------------------------------------------------
608 -def __tests2latex_minipage(results=None, width=u'1.5cm', show_time=False, show_range=True):
609 610 if len(results) == 0: 611 return u'\\begin{minipage}{%s} \\end{minipage}' % width 612 613 lines = [] 614 for t in results: 615 616 tmp = u'' 617 618 if show_time: 619 tmp += u'{\\tiny (%s)} ' % t['clin_when'].strftime('%H:%M') 620 621 tmp += u'%.8s' % t['unified_val'] 622 623 lines.append(tmp) 624 tmp = u'' 625 626 if show_range: 627 has_range = ( 628 t['unified_target_range'] is not None 629 or 630 t['unified_target_min'] is not None 631 or 632 t['unified_target_max'] is not None 633 ) 634 if has_range: 635 if t['unified_target_range'] is not None: 636 tmp += u'{\\tiny %s}' % t['unified_target_range'] 637 else: 638 tmp += u'{\\tiny %s}' % ( 639 gmTools.coalesce(t['unified_target_min'], u'- ', u'%s - '), 640 gmTools.coalesce(t['unified_target_max'], u'', u'%s') 641 ) 642 lines.append(tmp) 643 644 return u'\\begin{minipage}{%s} \\begin{flushright} %s \\end{flushright} \\end{minipage}' % (width, u' \\\\ '.join(lines))
645 #------------------------------------------------------------
646 -def __tests2latex_cell(results=None, show_time=False, show_range=True):
647 648 if len(results) == 0: 649 return u'' 650 651 lines = [] 652 for t in results: 653 654 tmp = u'' 655 656 if show_time: 657 tmp += u'\\tiny %s ' % t['clin_when'].strftime('%H:%M') 658 659 tmp += u'\\normalsize %.8s' % t['unified_val'] 660 661 lines.append(tmp) 662 tmp = u'\\tiny %s' % gmTools.coalesce(t['val_unit'], u'', u'%s:') 663 664 if not show_range: 665 lines.append(tmp) 666 continue 667 668 has_range = ( 669 t['unified_target_range'] is not None 670 or 671 t['unified_target_min'] is not None 672 or 673 t['unified_target_max'] is not None 674 ) 675 676 if not has_range: 677 lines.append(tmp) 678 continue 679 680 if t['unified_target_range'] is not None: 681 tmp += t['unified_target_range'] 682 else: 683 tmp += u'%s%s' % ( 684 gmTools.coalesce(t['unified_target_min'], u'- ', u'%s - '), 685 gmTools.coalesce(t['unified_target_max'], u'', u'%s') 686 ) 687 lines.append(tmp) 688 689 return u' \\\\ '.join(lines)
690 #------------------------------------------------------------
691 -def __format_test_results_latex(results=None):
692 693 if len(results) == 0: 694 return u'\\noindent %s' % _('No test results to format.') 695 696 # discover the columns and rows 697 dates = {} 698 tests = {} 699 grid = {} 700 for result in results: 701 # row_label = u'%s \\ \\tiny (%s)}' % (result['unified_abbrev'], result['unified_name']) 702 row_label = result['unified_abbrev'] 703 tests[row_label] = None 704 col_label = u'{\\scriptsize %s}' % result['clin_when'].strftime('%Y-%m-%d') 705 dates[col_label] = None 706 try: 707 grid[row_label] 708 except KeyError: 709 grid[row_label] = {} 710 try: 711 grid[row_label][col_label].append(result) 712 except KeyError: 713 grid[row_label][col_label] = [result] 714 715 col_labels = sorted(dates.keys(), reverse = True) 716 del dates 717 row_labels = sorted(tests.keys()) 718 del tests 719 720 col_def = len(col_labels) * u'>{\\raggedleft}p{1.7cm}|' 721 722 # format them 723 tex = u"""\\noindent %s 724 725 \\noindent \\begin{tabular}{|l|%s} 726 \\hline 727 & %s \\tabularnewline 728 \\hline 729 730 %%s \\tabularnewline 731 732 \\hline 733 734 \\end{tabular}""" % ( 735 _('Test results'), 736 col_def, 737 u' & '.join(col_labels) 738 ) 739 740 rows = [] 741 742 # loop over rows 743 for rl in row_labels: 744 cells = [rl] 745 # loop over cols per row 746 for cl in col_labels: 747 try: 748 # get tests for this (row/col) position 749 tests = grid[rl][cl] 750 except KeyError: 751 # none there, so insert empty cell 752 cells.append(u' ') 753 continue 754 755 cells.append ( 756 __tests2latex_cell ( 757 results = tests, 758 show_time = (len(tests) > 1), 759 show_range = True 760 ) 761 ) 762 763 rows.append(u' & '.join(cells)) 764 765 return tex % u' \\tabularnewline\n \\hline\n'.join(rows)
766 767 #============================================================
768 -def export_results_for_gnuplot(results=None, filename=None):
769 770 if filename is None: 771 filename = gmTools.get_unique_filename(prefix = u'gm2gpl-', suffix = '.dat') 772 773 # sort results into series by test type 774 series = {} 775 for r in results: 776 try: 777 series[r['unified_name']].append(r) 778 except KeyError: 779 series[r['unified_name']] = [r] 780 781 gp_data = codecs.open(filename, 'wb', 'utf8') 782 783 gp_data.write(u'# %s\n' % _('GNUmed test results export for Gnuplot plotting')) 784 gp_data.write(u'# -------------------------------------------------------------\n') 785 gp_data.write(u'# first line of index: test type abbreviation & name\n') 786 gp_data.write(u'#\n') 787 gp_data.write(u'# clin_when at full precision\n') 788 gp_data.write(u'# value\n') 789 gp_data.write(u'# unit\n') 790 gp_data.write(u'# unified (target or normal) range: lower bound\n') 791 gp_data.write(u'# unified (target or normal) range: upper bound\n') 792 gp_data.write(u'# normal range: lower bound\n') 793 gp_data.write(u'# normal range: upper bound\n') 794 gp_data.write(u'# target range: lower bound\n') 795 gp_data.write(u'# target range: upper bound\n') 796 gp_data.write(u'# clin_when formatted into string as x-axis tic label\n') 797 gp_data.write(u'# -------------------------------------------------------------\n') 798 799 for test_type in series.keys(): 800 if len(series[test_type]) == 0: 801 continue 802 803 r = series[test_type][0] 804 title = u'%s (%s)' % ( 805 r['unified_abbrev'], 806 r['unified_name'] 807 ) 808 gp_data.write(u'\n\n"%s" "%s"\n' % (title, title)) 809 810 prev_date = None 811 prev_year = None 812 for r in series[test_type]: 813 curr_date = r['clin_when'].strftime('%Y-%m-%d') 814 if curr_date == prev_date: 815 gp_data.write(u'\n# %s\n' % _('blank line inserted to allow for discontinued line drawing for same-day values')) 816 if r['clin_when'].year == prev_year: 817 when_template = '%b %d %H:%M' 818 else: 819 when_template = '%b %d %H:%M (%Y)' 820 prev_year = r['clin_when'].year 821 gp_data.write (u'%s %s "%s" %s %s %s %s %s %s "%s"\n' % ( 822 r['clin_when'].strftime('%Y-%m-%d_%H:%M'), 823 r['unified_val'], 824 gmTools.coalesce(r['val_unit'], u'"<?>"'), 825 gmTools.coalesce(r['unified_target_min'], u'"<?>"'), 826 gmTools.coalesce(r['unified_target_max'], u'"<?>"'), 827 gmTools.coalesce(r['val_normal_min'], u'"<?>"'), 828 gmTools.coalesce(r['val_normal_max'], u'"<?>"'), 829 gmTools.coalesce(r['val_target_min'], u'"<?>"'), 830 gmTools.coalesce(r['val_target_max'], u'"<?>"'), 831 gmDateTime.pydt_strftime ( 832 r['clin_when'], 833 format = when_template, 834 accuracy = gmDateTime.acc_minutes 835 ) 836 )) 837 prev_date = curr_date 838 839 gp_data.close() 840 841 return filename
842 #============================================================
843 -class cLabResult(gmBusinessDBObject.cBusinessDBObject):
844 """Represents one lab result.""" 845 846 _cmd_fetch_payload = """ 847 select *, xmin_test_result from v_results4lab_req 848 where pk_result=%s""" 849 _cmds_lock_rows_for_update = [ 850 """select 1 from test_result where pk=%(pk_result)s and xmin=%(xmin_test_result)s for update""" 851 ] 852 _cmds_store_payload = [ 853 """update test_result set 854 clin_when = %(val_when)s, 855 narrative = %(progress_note_result)s, 856 fk_type = %(pk_test_type)s, 857 val_num = %(val_num)s::numeric, 858 val_alpha = %(val_alpha)s, 859 val_unit = %(val_unit)s, 860 val_normal_min = %(val_normal_min)s, 861 val_normal_max = %(val_normal_max)s, 862 val_normal_range = %(val_normal_range)s, 863 val_target_min = %(val_target_min)s, 864 val_target_max = %(val_target_max)s, 865 val_target_range = %(val_target_range)s, 866 abnormality_indicator = %(abnormal)s, 867 norm_ref_group = %(ref_group)s, 868 note_provider = %(note_provider)s, 869 material = %(material)s, 870 material_detail = %(material_detail)s 871 where pk = %(pk_result)s""", 872 """select xmin_test_result from v_results4lab_req where pk_result=%(pk_result)s""" 873 ] 874 875 _updatable_fields = [ 876 'val_when', 877 'progress_note_result', 878 'val_num', 879 'val_alpha', 880 'val_unit', 881 'val_normal_min', 882 'val_normal_max', 883 'val_normal_range', 884 'val_target_min', 885 'val_target_max', 886 'val_target_range', 887 'abnormal', 888 'ref_group', 889 'note_provider', 890 'material', 891 'material_detail' 892 ] 893 #--------------------------------------------------------
894 - def __init__(self, aPK_obj=None, row=None):
895 """Instantiate. 896 897 aPK_obj as dict: 898 - patient_id 899 - when_field (see view definition) 900 - when 901 - test_type 902 - val_num 903 - val_alpha 904 - unit 905 """ 906 # instantiate from row data ? 907 if aPK_obj is None: 908 gmBusinessDBObject.cBusinessDBObject.__init__(self, row=row) 909 return 910 pk = aPK_obj 911 # find PK from row data ? 912 if type(aPK_obj) == types.DictType: 913 # sanity checks 914 if None in [aPK_obj['patient_id'], aPK_obj['when'], aPK_obj['when_field'], aPK_obj['test_type'], aPK_obj['unit']]: 915 raise gmExceptions.ConstructorError, 'parameter error: %s' % aPK_obj 916 if (aPK_obj['val_num'] is None) and (aPK_obj['val_alpha'] is None): 917 raise gmExceptions.ConstructorError, 'parameter error: val_num and val_alpha cannot both be None' 918 # get PK 919 where_snippets = [ 920 'pk_patient=%(patient_id)s', 921 'pk_test_type=%(test_type)s', 922 '%s=%%(when)s' % aPK_obj['when_field'], 923 'val_unit=%(unit)s' 924 ] 925 if aPK_obj['val_num'] is not None: 926 where_snippets.append('val_num=%(val_num)s::numeric') 927 if aPK_obj['val_alpha'] is not None: 928 where_snippets.append('val_alpha=%(val_alpha)s') 929 930 where_clause = ' and '.join(where_snippets) 931 cmd = "select pk_result from v_results4lab_req where %s" % where_clause 932 data = gmPG.run_ro_query('historica', cmd, None, aPK_obj) 933 if data is None: 934 raise gmExceptions.ConstructorError, 'error getting lab result for: %s' % aPK_obj 935 if len(data) == 0: 936 raise gmExceptions.NoSuchClinItemError, 'no lab result for: %s' % aPK_obj 937 pk = data[0][0] 938 # instantiate class 939 gmBusinessDBObject.cBusinessDBObject.__init__(self, aPK_obj=pk)
940 #--------------------------------------------------------
941 - def get_patient(self):
942 cmd = """ 943 select 944 %s, 945 vbp.title, 946 vbp.firstnames, 947 vbp.lastnames, 948 vbp.dob 949 from v_basic_person vbp 950 where vbp.pk_identity=%%s""" % self._payload[self._idx['pk_patient']] 951 pat = gmPG.run_ro_query('historica', cmd, None, self._payload[self._idx['pk_patient']]) 952 return pat[0]
953 #============================================================
954 -class cLabRequest(gmBusinessDBObject.cBusinessDBObject):
955 """Represents one lab request.""" 956 957 _cmd_fetch_payload = """ 958 select *, xmin_lab_request from v_lab_requests 959 where pk_request=%s""" 960 _cmds_lock_rows_for_update = [ 961 """select 1 from lab_request where pk=%(pk_request)s and xmin=%(xmin_lab_request)s for update""" 962 ] 963 _cmds_store_payload = [ 964 """update lab_request set 965 request_id=%(request_id)s, 966 lab_request_id=%(lab_request_id)s, 967 clin_when=%(sampled_when)s, 968 lab_rxd_when=%(lab_rxd_when)s, 969 results_reported_when=%(results_reported_when)s, 970 request_status=%(request_status)s, 971 is_pending=%(is_pending)s::bool, 972 narrative=%(progress_note)s 973 where pk=%(pk_request)s""", 974 """select xmin_lab_request from v_lab_requests where pk_request=%(pk_request)s""" 975 ] 976 _updatable_fields = [ 977 'request_id', 978 'lab_request_id', 979 'sampled_when', 980 'lab_rxd_when', 981 'results_reported_when', 982 'request_status', 983 'is_pending', 984 'progress_note' 985 ] 986 #--------------------------------------------------------
987 - def __init__(self, aPK_obj=None, row=None):
988 """Instantiate lab request. 989 990 The aPK_obj can be either a dict with the keys "req_id" 991 and "lab" or a simple primary key. 992 """ 993 # instantiate from row data ? 994 if aPK_obj is None: 995 gmBusinessDBObject.cBusinessDBObject.__init__(self, row=row) 996 return 997 pk = aPK_obj 998 # instantiate from "req_id" and "lab" ? 999 if type(aPK_obj) == types.DictType: 1000 # sanity check 1001 try: 1002 aPK_obj['req_id'] 1003 aPK_obj['lab'] 1004 except: 1005 _log.exception('[%s:??]: faulty <aPK_obj> structure: [%s]' % (self.__class__.__name__, aPK_obj), sys.exc_info()) 1006 raise gmExceptions.ConstructorError, '[%s:??]: cannot derive PK from [%s]' % (self.__class__.__name__, aPK_obj) 1007 # generate query 1008 where_snippets = [] 1009 vals = {} 1010 where_snippets.append('request_id=%(req_id)s') 1011 if type(aPK_obj['lab']) == types.IntType: 1012 where_snippets.append('pk_test_org=%(lab)s') 1013 else: 1014 where_snippets.append('lab_name=%(lab)s') 1015 where_clause = ' and '.join(where_snippets) 1016 cmd = "select pk_request from v_lab_requests where %s" % where_clause 1017 # get pk 1018 data = gmPG.run_ro_query('historica', cmd, None, aPK_obj) 1019 if data is None: 1020 raise gmExceptions.ConstructorError, '[%s:??]: error getting lab request for [%s]' % (self.__class__.__name__, aPK_obj) 1021 if len(data) == 0: 1022 raise gmExceptions.NoSuchClinItemError, '[%s:??]: no lab request for [%s]' % (self.__class__.__name__, aPK_obj) 1023 pk = data[0][0] 1024 # instantiate class 1025 gmBusinessDBObject.cBusinessDBObject.__init__(self, aPK_obj=pk)
1026 #--------------------------------------------------------
1027 - def get_patient(self):
1028 cmd = """ 1029 select vpi.pk_patient, vbp.title, vbp.firstnames, vbp.lastnames, vbp.dob 1030 from v_pat_items vpi, v_basic_person vbp 1031 where 1032 vpi.pk_item=%s 1033 and 1034 vbp.pk_identity=vpi.pk_patient""" 1035 pat = gmPG.run_ro_query('historica', cmd, None, self._payload[self._idx['pk_item']]) 1036 if pat is None: 1037 _log.error('cannot get patient for lab request [%s]' % self._payload[self._idx['pk_item']]) 1038 return None 1039 if len(pat) == 0: 1040 _log.error('no patient associated with lab request [%s]' % self._payload[self._idx['pk_item']]) 1041 return None 1042 return pat[0]
1043 #============================================================ 1044 # convenience functions 1045 #------------------------------------------------------------
1046 -def create_lab_request(lab=None, req_id=None, pat_id=None, encounter_id=None, episode_id=None):
1047 """Create or get lab request. 1048 1049 returns tuple (status, value): 1050 (True, lab request instance) 1051 (False, error message) 1052 (None, housekeeping_todo primary key) 1053 """ 1054 req = None 1055 aPK_obj = { 1056 'lab': lab, 1057 'req_id': req_id 1058 } 1059 try: 1060 req = cLabRequest (aPK_obj) 1061 except gmExceptions.NoSuchClinItemError, msg: 1062 _log.info('%s: will try to create lab request' % str(msg)) 1063 except gmExceptions.ConstructorError, msg: 1064 _log.exception(str(msg), sys.exc_info(), verbose=0) 1065 return (False, msg) 1066 # found 1067 if req is not None: 1068 db_pat = req.get_patient() 1069 if db_pat is None: 1070 _log.error('cannot cross-check patient on lab request') 1071 return (None, '') 1072 # yes but ambigous 1073 if pat_id != db_pat[0]: 1074 _log.error('lab request found for [%s:%s] but patient mismatch: expected [%s], in DB [%s]' % (lab, req_id, pat_id, db_pat)) 1075 me = '$RCSfile: gmPathLab.py,v $ $Revision: 1.81 $' 1076 to = 'user' 1077 prob = _('The lab request already exists but belongs to a different patient.') 1078 sol = _('Verify which patient this lab request really belongs to.') 1079 ctxt = _('lab [%s], request ID [%s], expected link with patient [%s], currently linked to patient [%s]') % (lab, req_id, pat_id, db_pat) 1080 cat = 'lab' 1081 status, data = gmPG.add_housekeeping_todo(me, to, prob, sol, ctxt, cat) 1082 return (None, data) 1083 return (True, req) 1084 # not found 1085 queries = [] 1086 if type(lab) is types.IntType: 1087 cmd = "insert into lab_request (fk_encounter, fk_episode, fk_test_org, request_id) values (%s, %s, %s, %s)" 1088 else: 1089 cmd = "insert into lab_request (fk_encounter, fk_episode, fk_test_org, request_id) values (%s, %s, (select pk from test_org where internal_name=%s), %s)" 1090 queries.append((cmd, [encounter_id, episode_id, str(lab), req_id])) 1091 cmd = "select currval('lab_request_pk_seq')" 1092 queries.append((cmd, [])) 1093 # insert new 1094 result, err = gmPG.run_commit('historica', queries, True) 1095 if result is None: 1096 return (False, err) 1097 try: 1098 req = cLabRequest(aPK_obj=result[0][0]) 1099 except gmExceptions.ConstructorError, msg: 1100 _log.exception(str(msg), sys.exc_info(), verbose=0) 1101 return (False, msg) 1102 return (True, req)
1103 #------------------------------------------------------------
1104 -def create_lab_result(patient_id=None, when_field=None, when=None, test_type=None, val_num=None, val_alpha=None, unit=None, encounter_id=None, request=None):
1105 tres = None 1106 data = { 1107 'patient_id': patient_id, 1108 'when_field': when_field, 1109 'when': when, 1110 'test_type': test_type, 1111 'val_num': val_num, 1112 'val_alpha': val_alpha, 1113 'unit': unit 1114 } 1115 try: 1116 tres = cLabResult(aPK_obj=data) 1117 # exists already, so fail 1118 _log.error('will not overwrite existing test result') 1119 _log.debug(str(tres)) 1120 return (None, tres) 1121 except gmExceptions.NoSuchClinItemError: 1122 _log.debug('test result not found - as expected, will create it') 1123 except gmExceptions.ConstructorError, msg: 1124 _log.exception(str(msg), sys.exc_info(), verbose=0) 1125 return (False, msg) 1126 if request is None: 1127 return (False, _('need lab request when inserting lab result')) 1128 # not found 1129 if encounter_id is None: 1130 encounter_id = request['pk_encounter'] 1131 queries = [] 1132 cmd = "insert into test_result (fk_encounter, fk_episode, fk_type, val_num, val_alpha, val_unit) values (%s, %s, %s, %s, %s, %s)" 1133 queries.append((cmd, [encounter_id, request['pk_episode'], test_type, val_num, val_alpha, unit])) 1134 cmd = "insert into lnk_result2lab_req (fk_result, fk_request) values ((select currval('test_result_pk_seq')), %s)" 1135 queries.append((cmd, [request['pk_request']])) 1136 cmd = "select currval('test_result_pk_seq')" 1137 queries.append((cmd, [])) 1138 # insert new 1139 result, err = gmPG.run_commit('historica', queries, True) 1140 if result is None: 1141 return (False, err) 1142 try: 1143 tres = cLabResult(aPK_obj=result[0][0]) 1144 except gmExceptions.ConstructorError, msg: 1145 _log.exception(str(msg), sys.exc_info(), verbose=0) 1146 return (False, msg) 1147 return (True, tres)
1148 #------------------------------------------------------------
1149 -def get_unreviewed_results(limit=50):
1150 # sanity check 1151 if limit < 1: 1152 limit = 1 1153 # retrieve one more row than needed so we know there's more available ;-) 1154 lim = limit + 1 1155 cmd = """ 1156 select pk_result 1157 from v_results4lab_req 1158 where reviewed is false 1159 order by pk_patient 1160 limit %s""" % lim 1161 rows = gmPG.run_ro_query('historica', cmd) 1162 if rows is None: 1163 _log.error('error retrieving unreviewed lab results') 1164 return (None, _('error retrieving unreviewed lab results')) 1165 if len(rows) == 0: 1166 return (False, []) 1167 # more than LIMIT rows ? 1168 if len(rows) == lim: 1169 more_avail = True 1170 # but deliver only LIMIT rows so that our assumption holds true... 1171 del rows[limit] 1172 else: 1173 more_avail = False 1174 results = [] 1175 for row in rows: 1176 try: 1177 results.append(cLabResult(aPK_obj=row[0])) 1178 except gmExceptions.ConstructorError: 1179 _log.exception('skipping unreviewed lab result [%s]' % row[0], sys.exc_info(), verbose=0) 1180 return (more_avail, results)
1181 #------------------------------------------------------------
1182 -def get_pending_requests(limit=250):
1183 lim = limit + 1 1184 cmd = "select pk from lab_request where is_pending is true limit %s" % lim 1185 rows = gmPG.run_ro_query('historica', cmd) 1186 if rows is None: 1187 _log.error('error retrieving pending lab requests') 1188 return (None, None) 1189 if len(rows) == 0: 1190 return (False, []) 1191 results = [] 1192 # more than LIMIT rows ? 1193 if len(rows) == lim: 1194 too_many = True 1195 # but deliver only LIMIT rows so that our assumption holds true... 1196 del rows[limit] 1197 else: 1198 too_many = False 1199 requests = [] 1200 for row in rows: 1201 try: 1202 requests.append(cLabRequest(aPK_obj=row[0])) 1203 except gmExceptions.ConstructorError: 1204 _log.exception('skipping pending lab request [%s]' % row[0], sys.exc_info(), verbose=0) 1205 return (too_many, requests)
1206 #------------------------------------------------------------
1207 -def get_next_request_ID(lab=None, incrementor_func=None):
1208 """Get logically next request ID for given lab. 1209 1210 - lab either test_org PK or test_org.internal_name 1211 - incrementor_func: 1212 - if not supplied the next ID is guessed 1213 - if supplied it is applied to the most recently used ID 1214 """ 1215 if type(lab) == types.IntType: 1216 lab_snippet = 'vlr.fk_test_org=%s' 1217 else: 1218 lab_snippet = 'vlr.lab_name=%s' 1219 lab = str(lab) 1220 cmd = """ 1221 select request_id 1222 from lab_request lr0 1223 where lr0.clin_when = ( 1224 select max(vlr.sampled_when) 1225 from v_lab_requests vlr 1226 where %s 1227 )""" % lab_snippet 1228 rows = gmPG.run_ro_query('historica', cmd, None, lab) 1229 if rows is None: 1230 _log.warning('error getting most recently used request ID for lab [%s]' % lab) 1231 return '' 1232 if len(rows) == 0: 1233 return '' 1234 most_recent = rows[0][0] 1235 # apply supplied incrementor 1236 if incrementor_func is not None: 1237 try: 1238 next = incrementor_func(most_recent) 1239 except TypeError: 1240 _log.error('cannot call incrementor function [%s]' % str(incrementor_func)) 1241 return most_recent 1242 return next 1243 # try to be smart ourselves 1244 for pos in range(len(most_recent)): 1245 header = most_recent[:pos] 1246 trailer = most_recent[pos:] 1247 try: 1248 return '%s%s' % (header, str(int(trailer) + 1)) 1249 except ValueError: 1250 header = most_recent[:-1] 1251 trailer = most_recent[-1:] 1252 return '%s%s' % (header, chr(ord(trailer) + 1))
1253 #============================================================
1254 -def calculate_bmi(mass=None, height=None, age=None):
1255 """Calculate BMI. 1256 1257 mass: kg 1258 height: cm 1259 age: not yet used 1260 1261 returns: 1262 (True/False, data) 1263 True: data = (bmi, lower_normal, upper_normal) 1264 False: data = error message 1265 """ 1266 converted, mass = gmTools.input2decimal(mass) 1267 if not converted: 1268 return False, u'mass: cannot convert <%s> to Decimal' % mass 1269 1270 converted, height = gmTools.input2decimal(height) 1271 if not converted: 1272 return False, u'height: cannot convert <%s> to Decimal' % height 1273 1274 approx_surface = (height / decimal.Decimal(100))**2 1275 bmi = mass / approx_surface 1276 1277 print mass, height, '->', approx_surface, '->', bmi 1278 1279 lower_normal_mass = 20.0 * approx_surface 1280 upper_normal_mass = 25.0 * approx_surface 1281 1282 return True, (bmi, lower_normal_mass, upper_normal_mass)
1283 #============================================================ 1284 # main - unit testing 1285 #------------------------------------------------------------ 1286 if __name__ == '__main__': 1287 1288 if len(sys.argv) < 2: 1289 sys.exit() 1290 1291 if sys.argv[1] != 'test': 1292 sys.exit() 1293 1294 import time 1295 1296 gmI18N.activate_locale() 1297 gmI18N.install_domain() 1298 1299 #------------------------------------------
1300 - def test_create_test_result():
1301 tr = create_test_result ( 1302 encounter = 1, 1303 episode = 1, 1304 type = 1, 1305 intended_reviewer = 1, 1306 val_num = '12', 1307 val_alpha=None, 1308 unit = 'mg/dl' 1309 ) 1310 print tr 1311 return tr
1312 #------------------------------------------
1313 - def test_delete_test_result():
1314 tr = test_create_test_result() 1315 delete_test_result(tr)
1316 #------------------------------------------
1317 - def test_result():
1318 r = cTestResult(aPK_obj=1) 1319 print r 1320 print r.reference_ranges
1321 #------------------------------------------
1322 - def test_lab_result():
1323 print "test_result()" 1324 # lab_result = cLabResult(aPK_obj=4) 1325 data = { 1326 'patient_id': 12, 1327 'when_field': 'val_when', 1328 'when': '2000-09-17 18:23:00+02', 1329 'test_type': 9, 1330 'val_num': 17.3, 1331 'val_alpha': None, 1332 'unit': 'mg/l' 1333 } 1334 lab_result = cLabResult(aPK_obj=data) 1335 print lab_result 1336 fields = lab_result.get_fields() 1337 for field in fields: 1338 print field, ':', lab_result[field] 1339 print "updatable:", lab_result.get_updatable_fields() 1340 print time.time() 1341 print lab_result.get_patient() 1342 print time.time()
1343 #------------------------------------------
1344 - def test_request():
1345 print "test_request()" 1346 try: 1347 # lab_req = cLabRequest(aPK_obj=1) 1348 # lab_req = cLabRequest(req_id='EML#SC937-0176-CEC#11', lab=2) 1349 data = { 1350 'req_id': 'EML#SC937-0176-CEC#11', 1351 'lab': 'Enterprise Main Lab' 1352 } 1353 lab_req = cLabRequest(aPK_obj=data) 1354 except gmExceptions.ConstructorError, msg: 1355 print "no such lab request:", msg 1356 return 1357 print lab_req 1358 fields = lab_req.get_fields() 1359 for field in fields: 1360 print field, ':', lab_req[field] 1361 print "updatable:", lab_req.get_updatable_fields() 1362 print time.time() 1363 print lab_req.get_patient() 1364 print time.time()
1365 #--------------------------------------------------------
1366 - def test_unreviewed():
1367 data = get_unreviewed_results() 1368 for result in data: 1369 print result
1370 #--------------------------------------------------------
1371 - def test_pending():
1372 data = get_pending_requests() 1373 for result in data: 1374 print result
1375 #--------------------------------------------------------
1376 - def test_create_measurement_type():
1377 print create_measurement_type ( 1378 lab = None, 1379 abbrev = u'tBZ2', 1380 unit = u'mg%', 1381 name = 'BZ (test 2)' 1382 )
1383 #--------------------------------------------------------
1384 - def test_meta_test_type():
1385 mtt = cMetaTestType(aPK_obj = 1) 1386 print mtt 1387 print get_meta_test_types()
1388 #--------------------------------------------------------
1389 - def test_test_type():
1390 tt = cMeasurementType(aPK_obj = 1) 1391 print tt 1392 print get_measurement_types()
1393 #--------------------------------------------------------
1394 - def test_format_test_results():
1395 results = [ 1396 cTestResult(aPK_obj=1), 1397 cTestResult(aPK_obj=2), 1398 cTestResult(aPK_obj=3) 1399 # cTestResult(aPK_obj=4) 1400 ] 1401 print format_test_results(results = results)
1402 #--------------------------------------------------------
1403 - def test_calculate_bmi():
1404 done, data = calculate_bmi(mass = sys.argv[2], height = sys.argv[3]) 1405 bmi, low, high = data 1406 1407 print "BMI:", bmi 1408 print "low:", low, "kg" 1409 print "hi :", high, "kg"
1410 1411 #-------------------------------------------------------- 1412 1413 #test_result() 1414 #test_create_test_result() 1415 #test_delete_test_result() 1416 #test_create_measurement_type() 1417 #test_lab_result() 1418 #test_request() 1419 #test_create_result() 1420 #test_unreviewed() 1421 #test_pending() 1422 #test_meta_test_type() 1423 #test_test_type() 1424 #test_format_test_results() 1425 test_calculate_bmi() 1426 1427 #============================================================ 1428