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

Source Code for Module Gnumed.business.gmSOAPimporter

  1  """GNUmed SOAP importer 
  2   
  3  (specification by Karsten Hilbert <Karsten.Hilbert@gmx.net>) 
  4   
  5  This script is designed for importing GNUmed SOAP input "bundles". 
  6   
  7          - "bundle" is list of dicts 
  8          - each "bundle" is processed dict by dict 
  9          - the dicts in the list are INDEPENDANT of each other 
 10          - each dict contains information for one new clin_narrative row 
 11          - each dict has the keys: 'soap', 'types', 'text', 'clin_context' 
 12                  - 'soap': 
 13                          - relates to clin_narrative.soap_cat 
 14                  - 'types': 
 15                          - a list of strings 
 16                          - the strings must be found in clin_item_type.type 
 17                          - strings not found in clin_item_type.type are ignored during 
 18                            import and the user is warned about that 
 19                  - 'text': 
 20                          - the narrative for clin_narrative.narrative, imported as is 
 21                  - 'clin_context': 
 22                          - 'clin_context' is a dictionary containing clinical 
 23                            context information, required to properly create clinical items. 
 24                            Its 'episode_id' must always be supplied. 
 25  """ 
 26  #=============================================================== 
 27  __version__ = "$Revision: 1.24 $" 
 28  __author__ = "Carlos Moro <cfmoro1976@yahoo.es>" 
 29  __license__ = "GPL v2 or later (details at http://www.gnu.org)" 
 30   
 31  # stdlib 
 32  import sys, re, logging 
 33   
 34   
 35  # GNUmed 
 36  from Gnumed.pycommon import gmExceptions, gmI18N, gmDispatcher 
 37  from Gnumed.business import gmClinNarrative, gmPerson, gmPersonSearch 
 38   
 39   
 40  _log = logging.getLogger('gm.soap') 
 41   
 42   
 43  # module level constants 
 44  soap_bundle_SOAP_CAT_KEY = "soap" 
 45  soap_bundle_TYPES_KEY = "types" 
 46  soap_bundle_TEXT_KEY = "text" 
 47  soap_bundle_CLIN_CTX_KEY = "clin_context" 
 48  soap_bundle_TYPE_KEY = "type" 
 49  soap_bundle_EPISODE_ID_KEY = "episode_id" 
 50  soap_bundle_ENCOUNTER_ID_KEY = "encounter_id" 
 51  soap_bundle_STAFF_ID_KEY = "staff_id" 
 52  soap_bundle_SOAP_CATS = ['s','o','a','p']               # these are pretty much fixed 
 53  #=============================================================== 
54 -class cSOAPImporter:
55 """ 56 Main SOAP importer class 57 """ 58 #-----------------------------------------------------------
59 - def __init__(self):
60 pass
61 #----------------------------------------------------------- 62 # external API 63 #-----------------------------------------------------------
64 - def import_soap(self, bundle=None):
65 """ 66 Import supplied GNUmed SOAP input "bundle". For details consult current 67 module's description information. 68 69 @param bundle: GNUmed SOAP input data (as described in module's information) 70 @type bundle: list of dicts 71 """ 72 # process each entry in soap bundle independently 73 for soap_entry in bundle: 74 if not self.__import_narrative(soap_entry): 75 _log.error('skipping soap entry') 76 continue 77 gmDispatcher.send(signal = 'clin_item_updated') 78 return True
79 #----------------------------------------------------------- 80 # internal helpers 81 #-----------------------------------------------------------
82 - def __import_narrative(self, soap_entry):
83 """Import soap entry into GNUmed backend. 84 85 @param soap_entry: dictionary containing information related 86 to one SOAP input line 87 @type soap_entry: dictionary with keys 'soap', 'types', 'text' 88 89 FIXME: Later we may want to allow for explicitly setting a staff ID to be 90 FIXME: used for import. This would allow to import data "on behalf of" someone. 91 """ 92 if not self.__verify_soap_entry(soap_entry=soap_entry): 93 _log.error('cannot verify soap entry') 94 return False 95 # obtain clinical context information 96 emr = gmPerson.gmCurrentPatient().get_emr() 97 epi_id = soap_entry[soap_bundle_CLIN_CTX_KEY][soap_bundle_EPISODE_ID_KEY] 98 try: 99 enc_id = soap_entry[soap_bundle_CLIN_CTX_KEY][soap_bundle_ENCOUNTER_ID_KEY] 100 except KeyError: 101 enc = emr.active_encounter 102 enc_id = enc['pk_encounter'] 103 104 # create narrative row 105 status, narr = gmClinNarrative.create_clin_narrative ( 106 narrative = soap_entry[soap_bundle_TEXT_KEY], 107 soap_cat = soap_entry[soap_bundle_SOAP_CAT_KEY], 108 episode_id = epi_id, 109 encounter_id = enc_id 110 ) 111 112 # # attach types 113 # if soap_entry.has_key(soap_bundle_TYPES_KEY): 114 # print "code missing to attach types to imported narrative" 115 116 return status
117 #-----------------------------------------------------------
118 - def __verify_soap_entry(self, soap_entry):
119 """Perform basic integrity check of a supplied SOAP entry. 120 121 @param soap_entry: dictionary containing information related to one 122 SOAP input 123 @type soap_entry: dictionary with keys 'soap', 'types', 'text' 124 """ 125 required_keys = [ 126 soap_bundle_SOAP_CAT_KEY, 127 soap_bundle_CLIN_CTX_KEY, 128 soap_bundle_TEXT_KEY 129 ] 130 # verify key existence 131 for a_key in required_keys: 132 try: 133 soap_entry[a_key] 134 except KeyError: 135 _log.error('key [%s] is missing from soap entry' % a_key) 136 _log.error('%s' % soap_entry) 137 return False 138 # verify key *values* 139 if not soap_entry[soap_bundle_SOAP_CAT_KEY] in soap_bundle_SOAP_CATS: 140 _log.error('invalid soap category [%s]' % soap_entry[soap_bundle_SOAP_CAT_KEY]) 141 _log.error('%s' % soap_entry) 142 return False 143 try: 144 soap_entry[soap_bundle_CLIN_CTX_KEY][soap_bundle_EPISODE_ID_KEY] 145 except KeyError: 146 _log.error('SOAP entry does not provide mandatory episode ID') 147 _log.error('%s' % soap_entry) 148 return False 149 return True
150 #----------------------------------------------------------- 151 # def _verify_types(self, soap_entry): 152 # """ 153 # Perform types key check of a supplied SOAP entry 154 # 155 # @param soap_entry: dictionary containing information related to one 156 # SOAP input 157 # @type soap_entry: dictionary with keys 'soap', 'types', 'text' 158 # """ 159 # 160 # # FIXME fetch from backend 161 # allowed_types = ['Hx'] 162 # for input_type in soap_entry[soap_bundle_TYPES_KEY]: 163 # if not input_type in allowed_types: 164 # _log.error('bad clin_item_type.type in supplied soap entry [%s]' % 165 # soap_entry) 166 # return False 167 # return True 168 169 #================================================================ 170 # MAIN 171 #---------------------------------------------------------------- 172 if __name__ == '__main__': 173 _log.info("starting SOAP importer...") 174 175 try: 176 # obtain patient 177 patient = gmPersonSearch.ask_for_patient() 178 if patient is None: 179 print "No patient. Exiting gracefully..." 180 sys.exit(0) 181 gmPerson.set_active_patient(patient=patient) 182 183 # now import 184 importer = cSOAPImporter() 185 bundle = [ 186 {soap_bundle_SOAP_CAT_KEY: 's', 187 soap_bundle_TYPES_KEY: ['Hx'], 188 soap_bundle_TEXT_KEY: 'Test subjective narrative', 189 soap_bundle_CLIN_CTX_KEY: {soap_bundle_EPISODE_ID_KEY: '1'} 190 }, 191 {soap_bundle_SOAP_CAT_KEY: 'o', 192 soap_bundle_TYPES_KEY: ['Hx'], 193 soap_bundle_TEXT_KEY: 'Test objective narrative', 194 soap_bundle_CLIN_CTX_KEY: {soap_bundle_EPISODE_ID_KEY: '1'} 195 }, 196 {soap_bundle_SOAP_CAT_KEY: 'a', 197 soap_bundle_TYPES_KEY: ['Hx'], 198 soap_bundle_TEXT_KEY: 'Test assesment narrative', 199 soap_bundle_CLIN_CTX_KEY: {soap_bundle_EPISODE_ID_KEY: '1'} 200 }, 201 {soap_bundle_SOAP_CAT_KEY: 'p', 202 soap_bundle_TYPES_KEY: ['Hx'], 203 soap_bundle_TEXT_KEY: 'Test plan narrative. [:tetanus:]. [:pneumoniae:].', 204 soap_bundle_CLIN_CTX_KEY: { 205 soap_bundle_EPISODE_ID_KEY: '1', 206 soap_bundle_ENCOUNTER_ID_KEY: '1', 207 soap_bundle_STAFF_ID_KEY: '1' 208 }, 209 } 210 ] 211 importer.import_soap(bundle) 212 213 # clean up 214 if patient is not None: 215 try: 216 patient.cleanup() 217 except: 218 print "error cleaning up patient" 219 except StandardError: 220 _log.exception("unhandled exception caught !", sys.exc_info(), 1) 221 # but re-raise them 222 raise 223 224 _log.info("closing SOAP importer...") 225 #================================================================ 226