| Trees | Indices | Help |
|
|---|
|
|
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 # $Source: /cvsroot/gnumed/gnumed/gnumed/client/business/gmSOAPimporter.py,v $
28 # $Id: gmSOAPimporter.py,v 1.24 2009/12/21 14:59:31 ncq Exp $
29 __version__ = "$Revision: 1.24 $"
30 __author__ = "Carlos Moro <cfmoro1976@yahoo.es>"
31 __license__ = "GPL (details at http://www.gnu.org)"
32
33 # stdlib
34 import sys, re, logging
35
36
37 # 3rd party
38 import mx.DateTime as mxDT
39
40
41 # GnuMed
42 from Gnumed.pycommon import gmExceptions, gmI18N, gmDispatcher
43 from Gnumed.business import gmClinNarrative, gmPerson
44
45
46 _log = logging.getLogger('gm.soap')
47
48
49 # module level constants
50 soap_bundle_SOAP_CAT_KEY = "soap"
51 soap_bundle_TYPES_KEY = "types"
52 soap_bundle_TEXT_KEY = "text"
53 soap_bundle_CLIN_CTX_KEY = "clin_context"
54 soap_bundle_TYPE_KEY = "type"
55 soap_bundle_EPISODE_ID_KEY = "episode_id"
56 soap_bundle_ENCOUNTER_ID_KEY = "encounter_id"
57 soap_bundle_STAFF_ID_KEY = "staff_id"
58 soap_bundle_SOAP_CATS = ['s','o','a','p'] # these are pretty much fixed
59 #===============================================================
61 """
62 Main SOAP importer class
63 """
64
65 #-----------------------------------------------------------
68 #-----------------------------------------------------------
69 # external API
70 #-----------------------------------------------------------
72 """
73 Import supplied GnuMed SOAP input "bundle". For details consult current
74 module's description information.
75
76 @param bundle: GnuMed SOAP input data (as described in module's information)
77 @type bundle: list of dicts
78 """
79 # process each entry in soap bundle independently
80 for soap_entry in bundle:
81 if not self.__import_narrative(soap_entry):
82 _log.error('skipping soap entry')
83 continue
84 gmDispatcher.send(signal = 'clin_item_updated')
85 return True
86 #-----------------------------------------------------------
87 # internal helpers
88 #-----------------------------------------------------------
90 """Import soap entry into GnuMed backend.
91
92 @param soap_entry: dictionary containing information related
93 to one SOAP input line
94 @type soap_entry: dictionary with keys 'soap', 'types', 'text'
95
96 FIXME: Later we may want to allow for explicitly setting a staff ID to be
97 FIXME: used for import. This would allow to import data "on behalf of" someone.
98 """
99 if not self.__verify_soap_entry(soap_entry=soap_entry):
100 _log.error('cannot verify soap entry')
101 return False
102 # obtain clinical context information
103 emr = gmPerson.gmCurrentPatient().get_emr()
104 epi_id = soap_entry[soap_bundle_CLIN_CTX_KEY][soap_bundle_EPISODE_ID_KEY]
105 try:
106 enc_id = soap_entry[soap_bundle_CLIN_CTX_KEY][soap_bundle_ENCOUNTER_ID_KEY]
107 except KeyError:
108 enc = emr.active_encounter
109 enc_id = enc['pk_encounter']
110
111 # create narrative row
112 status, narr = gmClinNarrative.create_clin_narrative (
113 narrative = soap_entry[soap_bundle_TEXT_KEY],
114 soap_cat = soap_entry[soap_bundle_SOAP_CAT_KEY],
115 episode_id = epi_id,
116 encounter_id = enc_id
117 )
118
119 # # attach types
120 # if soap_entry.has_key(soap_bundle_TYPES_KEY):
121 # print "code missing to attach types to imported narrative"
122
123 return status
124 #-----------------------------------------------------------
126 """Perform basic integrity check of a supplied SOAP entry.
127
128 @param soap_entry: dictionary containing information related to one
129 SOAP input
130 @type soap_entry: dictionary with keys 'soap', 'types', 'text'
131 """
132 required_keys = [
133 soap_bundle_SOAP_CAT_KEY,
134 soap_bundle_CLIN_CTX_KEY,
135 soap_bundle_TEXT_KEY
136 ]
137 # verify key existence
138 for a_key in required_keys:
139 try:
140 soap_entry[a_key]
141 except KeyError:
142 _log.error('key [%s] is missing from soap entry' % a_key)
143 _log.error('%s' % soap_entry)
144 return False
145 # verify key *values*
146 if not soap_entry[soap_bundle_SOAP_CAT_KEY] in soap_bundle_SOAP_CATS:
147 _log.error('invalid soap category [%s]' % soap_entry[soap_bundle_SOAP_CAT_KEY])
148 _log.error('%s' % soap_entry)
149 return False
150 try:
151 soap_entry[soap_bundle_CLIN_CTX_KEY][soap_bundle_EPISODE_ID_KEY]
152 except KeyError:
153 _log.error('SOAP entry does not provide mandatory episode ID')
154 _log.error('%s' % soap_entry)
155 return False
156 return True
157 #-----------------------------------------------------------
158 # def _verify_types(self, soap_entry):
159 # """
160 # Perform types key check of a supplied SOAP entry
161 #
162 # @param soap_entry: dictionary containing information related to one
163 # SOAP input
164 # @type soap_entry: dictionary with keys 'soap', 'types', 'text'
165 # """
166 #
167 # # FIXME fetch from backend
168 # allowed_types = ['Hx']
169 # for input_type in soap_entry[soap_bundle_TYPES_KEY]:
170 # if not input_type in allowed_types:
171 # _log.error('bad clin_item_type.type in supplied soap entry [%s]' %
172 # soap_entry)
173 # return False
174 # return True
175
176 #================================================================
177 # MAIN
178 #----------------------------------------------------------------
179 if __name__ == '__main__':
180 _log.info("starting SOAP importer...")
181
182 try:
183 # obtain patient
184 patient = gmPerson.ask_for_patient()
185 if patient is None:
186 print "No patient. Exiting gracefully..."
187 sys.exit(0)
188 gmPerson.set_active_patient(patient=patient)
189
190 # now import
191 importer = cSOAPImporter()
192 bundle = [
193 {soap_bundle_SOAP_CAT_KEY: 's',
194 soap_bundle_TYPES_KEY: ['Hx'],
195 soap_bundle_TEXT_KEY: 'Test subjective narrative',
196 soap_bundle_CLIN_CTX_KEY: {soap_bundle_EPISODE_ID_KEY: '1'}
197 },
198 {soap_bundle_SOAP_CAT_KEY: 'o',
199 soap_bundle_TYPES_KEY: ['Hx'],
200 soap_bundle_TEXT_KEY: 'Test objective narrative',
201 soap_bundle_CLIN_CTX_KEY: {soap_bundle_EPISODE_ID_KEY: '1'}
202 },
203 {soap_bundle_SOAP_CAT_KEY: 'a',
204 soap_bundle_TYPES_KEY: ['Hx'],
205 soap_bundle_TEXT_KEY: 'Test assesment narrative',
206 soap_bundle_CLIN_CTX_KEY: {soap_bundle_EPISODE_ID_KEY: '1'}
207 },
208 {soap_bundle_SOAP_CAT_KEY: 'p',
209 soap_bundle_TYPES_KEY: ['Hx'],
210 soap_bundle_TEXT_KEY: 'Test plan narrative. [:tetanus:]. [:pneumoniae:].',
211 soap_bundle_CLIN_CTX_KEY: {
212 soap_bundle_EPISODE_ID_KEY: '1',
213 soap_bundle_ENCOUNTER_ID_KEY: '1',
214 soap_bundle_STAFF_ID_KEY: '1'
215 },
216 }
217 ]
218 importer.import_soap(bundle)
219
220 # clean up
221 if patient is not None:
222 try:
223 patient.cleanup()
224 except:
225 print "error cleaning up patient"
226 except StandardError:
227 _log.exception("unhandled exception caught !", sys.exc_info(), 1)
228 # but re-raise them
229 raise
230
231 _log.info("closing SOAP importer...")
232 #================================================================
233 # $Log: gmSOAPimporter.py,v $
234 # Revision 1.24 2009/12/21 14:59:31 ncq
235 # - typo
236 #
237 # Revision 1.23 2009/09/13 18:25:54 ncq
238 # - no more get-active-encounter()
239 #
240 # Revision 1.22 2008/02/25 17:31:41 ncq
241 # - logging cleanup
242 #
243 # Revision 1.21 2008/01/30 13:34:50 ncq
244 # - switch to std lib logging
245 #
246 # Revision 1.20 2007/12/23 11:55:21 ncq
247 # - cleanup
248 #
249 # Revision 1.19 2007/12/11 12:59:11 ncq
250 # - cleanup and explicit signal handling
251 #
252 # Revision 1.18 2007/03/08 11:31:08 ncq
253 # - just cleanup
254 #
255 # Revision 1.17 2006/10/31 11:27:15 ncq
256 # - remove use of gmPG
257 #
258 # Revision 1.16 2006/10/25 07:17:40 ncq
259 # - no more gmPG
260 # - no more cClinItem
261 #
262 # Revision 1.15 2006/10/23 13:06:54 ncq
263 # - vaccs DB object not yet converted
264 #
265 # Revision 1.14 2006/07/19 21:37:51 ncq
266 # - cleanup
267 #
268 # Revision 1.13 2006/06/17 13:58:39 ncq
269 # - cleanup
270 #
271 # Revision 1.12 2006/05/12 12:05:04 ncq
272 # - cleanup
273 #
274 # Revision 1.11 2006/05/04 09:49:20 ncq
275 # - get_clinical_record() -> get_emr()
276 # - adjust to changes in set_active_patient()
277 # - need explicit set_active_patient() after ask_for_patient() if wanted
278 #
279 # Revision 1.10 2005/10/19 09:14:46 ncq
280 # - remove half-baked support for embedded data, now handled elsewhere
281 # - general cleanup/doc fixes
282 #
283 # Revision 1.9 2005/10/11 21:50:33 ncq
284 # - create_clin_narrative() should not be aware of emr object
285 #
286 # Revision 1.8 2005/10/08 12:33:08 sjtan
287 # tree can be updated now without refetching entire cache; done by passing emr object to create_xxxx methods and calling emr.update_cache(key,obj);refresh_historical_tree non-destructively checks for changes and removes removed nodes and adds them if cache mismatch.
288 #
289 # Revision 1.7 2005/05/17 08:03:30 ncq
290 # - cleanup
291 #
292 # Revision 1.6 2005/04/12 09:59:16 ncq
293 # - cleanup
294 # - enable actual backend storage
295 #
296 # Revision 1.5 2005/01/31 13:00:40 ncq
297 # - use ask_for_patient() in gmPerson
298 #
299 # Revision 1.4 2005/01/31 10:37:26 ncq
300 # - gmPatient.py -> gmPerson.py
301 #
302 # Revision 1.3 2004/12/20 09:51:28 ncq
303 # - tie constants to bundle not importer re naming
304 #
305 # Revision 1.2 2004/12/19 18:41:55 cfmoro
306 # Struct keys made module level constants
307 #
308 # Revision 1.1 2004/12/18 16:14:13 ncq
309 # - moved here from test area
310 #
311 # Revision 1.7 2004/12/18 16:00:37 ncq
312 # - final touch up before moving over
313 #
314 # Revision 1.6 2004/12/16 17:59:38 cfmoro
315 # Encapsulation syntax fixed (_ replaced by __). Using tab indentation, in consistency with the rest of gnumed files
316 #
317 # Revision 1.5 2004/12/13 19:37:08 ncq
318 # - cleanup after review by Carlos
319 # - will be moved to main trunk RSN
320 #
321 #
322
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Tue Feb 9 04:02:35 2010 | http://epydoc.sourceforge.net |