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