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

Source Code for Module Gnumed.business.gmClinNarrative

  1  """GNUmed clinical narrative business object.""" 
  2  #============================================================ 
  3  __version__ = "$Revision: 1.45 $" 
  4  __author__ = "Carlos Moro <cfmoro1976@yahoo.es>, Karsten Hilbert <Karsten.Hilbert@gmx.net>" 
  5  __license__ = 'GPL (for details see http://gnu.org)' 
  6   
  7  import sys, logging 
  8   
  9   
 10  if __name__ == '__main__': 
 11          sys.path.insert(0, '../../') 
 12  from Gnumed.pycommon import gmPG2, gmExceptions, gmBusinessDBObject, gmTools, gmDispatcher 
 13   
 14  try: 
 15          _('dummy-no-need-to-translate-but-make-epydoc-happy') 
 16  except NameError: 
 17          _ = lambda x:x 
 18   
 19  _log = logging.getLogger('gm.emr') 
 20  _log.info(__version__) 
 21   
 22   
 23  soap_cat2l10n = { 
 24          's': _('soap_S').replace(u'soap_', u''), 
 25          'o': _('soap_O').replace(u'soap_', u''), 
 26          'a': _('soap_A').replace(u'soap_', u''), 
 27          'p': _('soap_P').replace(u'soap_', u''), 
 28          #None: _('soap_ADMIN').replace(u'soap_', u'') 
 29          None: gmTools.u_ellipsis 
 30  } 
 31   
 32  soap_cat2l10n_str = { 
 33          's': _('soap_Subjective').replace(u'soap_', u''), 
 34          'o': _('soap_Objective').replace(u'soap_', u''), 
 35          'a': _('soap_Assessment').replace(u'soap_', u''), 
 36          'p': _('soap_Plan').replace(u'soap_', u''), 
 37          None: _('soap_Administrative').replace(u'soap_', u'') 
 38  } 
 39   
 40  l10n2soap_cat = { 
 41          _('soap_S').replace(u'soap_', u''): 's', 
 42          _('soap_O').replace(u'soap_', u''): 'o', 
 43          _('soap_A').replace(u'soap_', u''): 'a', 
 44          _('soap_P').replace(u'soap_', u''): 'p', 
 45          #_('soap_ADMIN').replace(u'soap_', u''): None 
 46          gmTools.u_ellipsis: None 
 47  } 
 48   
 49  #============================================================ 
50 -def _on_soap_modified():
51 """Always relates to the active patient.""" 52 gmHooks.run_hook_script(hook = u'after_soap_modified')
53 54 gmDispatcher.connect(_on_soap_modified, u'clin_narrative_mod_db') 55 56 #============================================================
57 -class cDiag(gmBusinessDBObject.cBusinessDBObject):
58 """Represents one real diagnosis. 59 """ 60 _cmd_fetch_payload = u"select *, xmin_clin_diag, xmin_clin_narrative from clin.v_pat_diag where pk_diag=%s" 61 _cmds_store_payload = [ 62 u"""update clin.clin_diag set 63 laterality=%()s, 64 laterality=%(laterality)s, 65 is_chronic=%(is_chronic)s::boolean, 66 is_active=%(is_active)s::boolean, 67 is_definite=%(is_definite)s::boolean, 68 clinically_relevant=%(clinically_relevant)s::boolean 69 where 70 pk=%(pk_diag)s and 71 xmin=%(xmin_clin_diag)s""", 72 u"""update clin.clin_narrative set 73 narrative=%(diagnosis)s 74 where 75 pk=%(pk_diag)s and 76 xmin=%(xmin_clin_narrative)s""", 77 u"""select xmin_clin_diag, xmin_clin_narrative from clin.v_pat_diag where pk_diag=%s(pk_diag)s""" 78 ] 79 80 _updatable_fields = [ 81 'diagnosis', 82 'laterality', 83 'is_chronic', 84 'is_active', 85 'is_definite', 86 'clinically_relevant' 87 ] 88 #--------------------------------------------------------
89 - def get_codes(self):
90 """ 91 Retrieves codes linked to this diagnosis 92 """ 93 cmd = u"select code, coding_system from clin.v_codes4diag where diagnosis=%s" 94 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self._payload[self._idx['diagnosis']]]}]) 95 return rows
96 #--------------------------------------------------------
97 - def add_code(self, code=None, coding_system=None):
98 """ 99 Associates a code (from coding system) with this diagnosis. 100 """ 101 # insert new code 102 cmd = u"select clin.add_coded_phrase (%(diag)s, %(code)s, %(sys)s)" 103 args = { 104 'diag': self._payload[self._idx['diagnosis']], 105 'code': code, 106 'sys': coding_system 107 } 108 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 109 return True
110 #============================================================
111 -class cNarrative(gmBusinessDBObject.cBusinessDBObject):
112 """Represents one clinical free text entry. 113 """ 114 _cmd_fetch_payload = u"select *, xmin_clin_narrative from clin.v_pat_narrative where pk_narrative=%s" 115 _cmds_store_payload = [ 116 u"""update clin.clin_narrative set 117 narrative = %(narrative)s, 118 clin_when = %(date)s, 119 soap_cat = lower(%(soap_cat)s), 120 fk_encounter = %(pk_encounter)s 121 where 122 pk=%(pk_narrative)s and 123 xmin=%(xmin_clin_narrative)s""", 124 u"""select xmin_clin_narrative from clin.v_pat_narrative where pk_narrative=%(pk_narrative)s""" 125 ] 126 127 _updatable_fields = [ 128 'narrative', 129 'date', 130 'soap_cat', 131 'pk_episode', 132 'pk_encounter' 133 ] 134 135 #xxxxxxxxxxxxxxxx 136 # support row_version in view 137 138 #--------------------------------------------------------
139 - def get_codes(self):
140 """Retrieves codes linked to *this* narrative. 141 """ 142 cmd = u"select code, xfk_coding_system from clin.coded_phrase where term=%s" 143 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': [self._payload[self._idx['narrative']]]}]) 144 return rows
145 #--------------------------------------------------------
146 - def add_code(self, code=None, coding_system=None):
147 """ 148 Associates a code (from coding system) with this narrative. 149 """ 150 # insert new code 151 cmd = u"select clin.add_coded_phrase (%(narr)s, %(code)s, %(sys)s)" 152 args = { 153 'narr': self._payload[self._idx['narrative']], 154 'code': code, 155 'sys': coding_system 156 } 157 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 158 return True
159 #--------------------------------------------------------
160 - def format(self, left_margin=u'', fancy=False, width=75):
161 162 if fancy: 163 # FIXME: add revision 164 txt = gmTools.wrap ( 165 text = _('%s: %s by %.8s\n%s') % ( 166 self._payload[self._idx['date']].strftime('%x %H:%M'), 167 soap_cat2l10n_str[self._payload[self._idx['soap_cat']]], 168 self._payload[self._idx['provider']], 169 self._payload[self._idx['narrative']] 170 ), 171 width = width, 172 initial_indent = u'', 173 subsequent_indent = left_margin + u' ' 174 ) 175 else: 176 txt = u'%s [%s]: %s (%.8s)' % ( 177 self._payload[self._idx['date']].strftime('%x %H:%M'), 178 soap_cat2l10n[self._payload[self._idx['soap_cat']]], 179 self._payload[self._idx['narrative']], 180 self._payload[self._idx['provider']] 181 ) 182 if len(txt) > width: 183 txt = txt[:width] + gmTools.u_ellipsis 184 185 return txt
186 187 # lines.append('-- %s ----------' % gmClinNarrative.soap_cat2l10n_str[soap_cat]) 188 189 #============================================================ 190 # convenience functions 191 #============================================================
192 -def search_text_across_emrs(search_term=None):
193 194 if search_term is None: 195 return [] 196 197 if search_term.strip() == u'': 198 return [] 199 200 cmd = u'select * from clin.v_narrative4search where narrative ~* %(term)s order by pk_patient limit 1000' 201 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'term': search_term}}], get_col_idx = False) 202 203 return rows
204 #============================================================
205 -def create_clin_narrative(narrative=None, soap_cat=None, episode_id=None, encounter_id=None):
206 """Creates a new clinical narrative entry 207 208 narrative - free text clinical narrative 209 soap_cat - soap category 210 episode_id - episodes's primary key 211 encounter_id - encounter's primary key 212 """ 213 # any of the args being None (except soap_cat) should fail the SQL code 214 215 # sanity checks: 216 217 # 1) silently do not insert empty narrative 218 narrative = narrative.strip() 219 if narrative == u'': 220 return (True, None) 221 222 # 2) also, silently do not insert true duplicates 223 # FIXME: this should check for .provider = current_user but 224 # FIXME: the view has provider mapped to their staff alias 225 cmd = u""" 226 select *, xmin_clin_narrative from clin.v_pat_narrative where 227 pk_encounter = %(enc)s 228 and pk_episode = %(epi)s 229 and soap_cat = %(soap)s 230 and narrative = %(narr)s 231 """ 232 args = { 233 'enc': encounter_id, 234 'epi': episode_id, 235 'soap': soap_cat, 236 'narr': narrative 237 } 238 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 239 if len(rows) == 1: 240 narrative = cNarrative(row = {'pk_field': 'pk_narrative', 'data': rows[0], 'idx': idx}) 241 return (True, narrative) 242 243 # insert new narrative 244 queries = [ 245 {'cmd': u"insert into clin.clin_narrative (fk_encounter, fk_episode, narrative, soap_cat) values (%s, %s, %s, lower(%s))", 246 'args': [encounter_id, episode_id, narrative, soap_cat] 247 }, 248 {'cmd': u"select currval('clin.clin_narrative_pk_seq')"} 249 ] 250 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data=True) 251 252 narrative = cNarrative(aPK_obj = rows[0][0]) 253 return (True, narrative)
254 #------------------------------------------------------------
255 -def delete_clin_narrative(narrative=None):
256 """Deletes a clin.clin_narrative row by it's PK.""" 257 cmd = u"delete from clin.clin_narrative where pk=%s" 258 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': [narrative]}]) 259 return True
260 #============================================================ 261 # main 262 #------------------------------------------------------------ 263 if __name__ == '__main__': 264 265 if len(sys.argv) < 2: 266 sys.exit() 267 268 if sys.argv[1] != 'test': 269 sys.exit() 270 271 from Gnumed.pycommon import gmI18N 272 gmI18N.activate_locale() 273 gmI18N.install_domain(domain = 'gnumed') 274
275 - def test_diag():
276 print "\nDiagnose test" 277 print "-------------" 278 diagnose = cDiag(aPK_obj=2) 279 fields = diagnose.get_fields() 280 for field in fields: 281 print field, ':', diagnose[field] 282 print "updatable:", diagnose.get_updatable_fields() 283 print "codes:", diagnose.get_codes()
284 #print "adding code..." 285 #diagnose.add_code('Test code', 'Test coding system') 286 #print "codes:", diagnose.get_codes() 287
288 - def test_narrative():
289 print "\nnarrative test" 290 print "--------------" 291 narrative = cNarrative(aPK_obj=7) 292 fields = narrative.get_fields() 293 for field in fields: 294 print field, ':', narrative[field] 295 print "updatable:", narrative.get_updatable_fields() 296 print "codes:", narrative.get_codes()
297 #print "adding code..." 298 #narrative.add_code('Test code', 'Test coding system') 299 #print "codes:", diagnose.get_codes() 300 301 #print "creating narrative..." 302 #status, new_narrative = create_clin_narrative(narrative = 'Test narrative', soap_cat = 'a', episode_id=1, encounter_id=2) 303 #print new_narrative 304 305 #-----------------------------------------
306 - def test_search_text_across_emrs():
307 results = search_text_across_emrs('cut') 308 for r in results: 309 print r
310 #----------------------------------------- 311 312 #test_search_text_across_emrs() 313 test_diag() 314 test_narrative() 315 316 #============================================================ 317