Tonic commited on
Commit
bf761ef
·
unverified ·
1 Parent(s): 03b34b8

complete response parser

Browse files
Files changed (1) hide show
  1. responseparser.py +222 -18
responseparser.py CHANGED
@@ -1,9 +1,9 @@
1
  import json
2
  from datetime import datetime
3
- from typing import List, Dict, Optional
4
 
5
  class PatientDataExtractor:
6
- """Class to extract patient data from a FHIR Bundle response and map it to discharge form fields."""
7
 
8
  def __init__(self, patient_data: str):
9
  """Initialize with patient data in JSON string format."""
@@ -36,13 +36,35 @@ class PatientDataExtractor:
36
  """Get the currently selected patient resource."""
37
  return self.patients[self.current_patient_idx]
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  def get_first_name(self) -> str:
40
  """Extract patient's first name."""
41
  patient = self._get_current_patient()
42
  names = patient.get("name", [])
43
  for name in names:
44
  if name.get("use") == "official" and "given" in name:
45
- return name["given"][0] # First given name
46
  return ""
47
 
48
  def get_last_name(self) -> str:
@@ -60,13 +82,31 @@ class PatientDataExtractor:
60
  names = patient.get("name", [])
61
  for name in names:
62
  if name.get("use") == "official" and "given" in name and len(name["given"]) > 1:
63
- return name["given"][1][0] # First letter of second given name
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  return ""
65
 
 
66
  def get_dob(self) -> str:
67
  """Extract patient's date of birth."""
68
- patient = self._get_current_patient()
69
- return patient.get("birthDate", "")
70
 
71
  def get_age(self) -> str:
72
  """Calculate patient's age based on birth date."""
@@ -78,12 +118,24 @@ class PatientDataExtractor:
78
  age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
79
  return str(age)
80
 
81
- def get_sex(self) -> str:
82
- """Extract patient's sex (gender)."""
 
 
 
 
83
  patient = self._get_current_patient()
84
- return patient.get("gender", "").capitalize()
 
 
 
 
 
 
 
85
 
86
- def get_address(self) -> str:
 
87
  """Extract patient's street address."""
88
  patient = self._get_current_patient()
89
  addresses = patient.get("address", [])
@@ -107,20 +159,173 @@ class PatientDataExtractor:
107
  addresses = patient.get("address", [])
108
  return addresses[0]["postalCode"] if addresses and "postalCode" in addresses[0] else ""
109
 
110
- def get_patient_dict(self) -> Dict[str, str]:
111
- """Return a dictionary of patient data mapped to discharge form fields."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  return {
 
 
 
 
 
113
  "first_name": self.get_first_name(),
114
  "last_name": self.get_last_name(),
115
  "middle_initial": self.get_middle_initial(),
 
 
116
  "dob": self.get_dob(),
117
  "age": self.get_age(),
118
- "sex": self.get_sex(),
119
- "address": self.get_address(),
 
 
120
  "city": self.get_city(),
121
  "state": self.get_state(),
122
  "zip_code": self.get_zip_code(),
123
- # Fields not directly available in Patient resource can be left blank or populated separately
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  "doctor_first_name": "",
125
  "doctor_last_name": "",
126
  "doctor_middle_initial": "",
@@ -143,20 +348,19 @@ class PatientDataExtractor:
143
  }
144
 
145
  def get_all_patients(self) -> List[Dict[str, str]]:
146
- """Return a list of dictionaries for all patients."""
147
  original_idx = self.current_patient_idx
148
  all_patients = []
149
  for i in range(len(self.patients)):
150
  self.set_patient_by_index(i)
151
  all_patients.append(self.get_patient_dict())
152
- self.set_patient_by_index(original_idx) # Restore original selection
153
  return all_patients
154
 
155
  def get_patient_ids(self) -> List[str]:
156
  """Return a list of all patient IDs in the Bundle."""
157
  return [patient["id"] for patient in self.patients]
158
 
159
-
160
  # # Example usage with integration into app.py
161
  # def integrate_with_app(patient_data: str):
162
  # """Integrate PatientDataExtractor with the Gradio app."""
 
1
  import json
2
  from datetime import datetime
3
+ from typing import List, Dict, Optional, Union
4
 
5
  class PatientDataExtractor:
6
+ """Class to extract all fields from a FHIR Patient resource in a Bundle response."""
7
 
8
  def __init__(self, patient_data: str):
9
  """Initialize with patient data in JSON string format."""
 
36
  """Get the currently selected patient resource."""
37
  return self.patients[self.current_patient_idx]
38
 
39
+ # Basic Identification Fields
40
+ def get_id(self) -> str:
41
+ """Extract FHIR Patient ID."""
42
+ return self._get_current_patient().get("id", "")
43
+
44
+ def get_resource_type(self) -> str:
45
+ """Extract resource type (should always be 'Patient')."""
46
+ return self._get_current_patient().get("resourceType", "")
47
+
48
+ def get_meta_last_updated(self) -> str:
49
+ """Extract last updated timestamp from meta."""
50
+ return self._get_current_patient().get("meta", {}).get("lastUpdated", "")
51
+
52
+ def get_meta_profile(self) -> List[str]:
53
+ """Extract profile URIs from meta."""
54
+ return self._get_current_patient().get("meta", {}).get("profile", [])
55
+
56
+ def get_text_div(self) -> str:
57
+ """Extract generated text narrative (div content)."""
58
+ return self._get_current_patient().get("text", {}).get("div", "")
59
+
60
+ # Name Fields
61
  def get_first_name(self) -> str:
62
  """Extract patient's first name."""
63
  patient = self._get_current_patient()
64
  names = patient.get("name", [])
65
  for name in names:
66
  if name.get("use") == "official" and "given" in name:
67
+ return name["given"][0]
68
  return ""
69
 
70
  def get_last_name(self) -> str:
 
82
  names = patient.get("name", [])
83
  for name in names:
84
  if name.get("use") == "official" and "given" in name and len(name["given"]) > 1:
85
+ return name["given"][1][0]
86
+ return ""
87
+
88
+ def get_name_prefix(self) -> str:
89
+ """Extract patient's name prefix (e.g., Mr., Mrs.)."""
90
+ patient = self._get_current_patient()
91
+ names = patient.get("name", [])
92
+ for name in names:
93
+ if name.get("use") == "official" and "prefix" in name:
94
+ return name["prefix"][0]
95
+ return ""
96
+
97
+ def get_maiden_name(self) -> str:
98
+ """Extract patient's maiden name if available."""
99
+ patient = self._get_current_patient()
100
+ names = patient.get("name", [])
101
+ for name in names:
102
+ if name.get("use") == "maiden" and "family" in name:
103
+ return name["family"]
104
  return ""
105
 
106
+ # Demographic Fields
107
  def get_dob(self) -> str:
108
  """Extract patient's date of birth."""
109
+ return self._get_current_patient().get("birthDate", "")
 
110
 
111
  def get_age(self) -> str:
112
  """Calculate patient's age based on birth date."""
 
118
  age = today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
119
  return str(age)
120
 
121
+ def get_gender(self) -> str:
122
+ """Extract patient's gender."""
123
+ return self._get_current_patient().get("gender", "").capitalize()
124
+
125
+ def get_birth_sex(self) -> str:
126
+ """Extract patient's birth sex from extensions."""
127
  patient = self._get_current_patient()
128
+ for ext in patient.get("extension", []):
129
+ if ext.get("url") == "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex":
130
+ return ext.get("valueCode", "")
131
+ return ""
132
+
133
+ def get_multiple_birth(self) -> Union[bool, None]:
134
+ """Extract multiple birth status."""
135
+ return self._get_current_patient().get("multipleBirthBoolean", None)
136
 
137
+ # Address Fields
138
+ def get_address_line(self) -> str:
139
  """Extract patient's street address."""
140
  patient = self._get_current_patient()
141
  addresses = patient.get("address", [])
 
159
  addresses = patient.get("address", [])
160
  return addresses[0]["postalCode"] if addresses and "postalCode" in addresses[0] else ""
161
 
162
+ def get_country(self) -> str:
163
+ """Extract patient's country."""
164
+ patient = self._get_current_patient()
165
+ addresses = patient.get("address", [])
166
+ return addresses[0]["country"] if addresses and "country" in addresses[0] else ""
167
+
168
+ def get_geolocation(self) -> Dict[str, float]:
169
+ """Extract geolocation (latitude and longitude) from address extension."""
170
+ patient = self._get_current_patient()
171
+ addresses = patient.get("address", [])
172
+ if not addresses:
173
+ return {"latitude": None, "longitude": None}
174
+ for ext in addresses[0].get("extension", []):
175
+ if ext.get("url") == "http://hl7.org/fhir/StructureDefinition/geolocation":
176
+ geo = {}
177
+ for sub_ext in ext.get("extension", []):
178
+ if sub_ext.get("url") == "latitude":
179
+ geo["latitude"] = sub_ext.get("valueDecimal")
180
+ elif sub_ext.get("url") == "longitude":
181
+ geo["longitude"] = sub_ext.get("valueDecimal")
182
+ return geo
183
+ return {"latitude": None, "longitude": None}
184
+
185
+ # Contact Fields
186
+ def get_phone(self) -> str:
187
+ """Extract patient's phone number."""
188
+ patient = self._get_current_patient()
189
+ telecoms = patient.get("telecom", [])
190
+ for telecom in telecoms:
191
+ if telecom.get("system") == "phone" and telecom.get("use") == "home":
192
+ return telecom.get("value", "")
193
+ return ""
194
+
195
+ # Identifiers
196
+ def get_identifiers(self) -> Dict[str, str]:
197
+ """Extract all identifiers (e.g., SSN, MRN, Driver's License)."""
198
+ patient = self._get_current_patient()
199
+ identifiers = patient.get("identifier", [])
200
+ id_dict = {}
201
+ for id_entry in identifiers:
202
+ id_type = id_entry.get("type", {}).get("text", "Unknown")
203
+ id_dict[id_type] = id_entry.get("value", "")
204
+ return id_dict
205
+
206
+ # Extensions
207
+ def get_race(self) -> str:
208
+ """Extract patient's race from extensions."""
209
+ patient = self._get_current_patient()
210
+ for ext in patient.get("extension", []):
211
+ if ext.get("url") == "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race":
212
+ for sub_ext in ext.get("extension", []):
213
+ if sub_ext.get("url") == "text":
214
+ return sub_ext.get("valueString", "")
215
+ return ""
216
+
217
+ def get_ethnicity(self) -> str:
218
+ """Extract patient's ethnicity from extensions."""
219
+ patient = self._get_current_patient()
220
+ for ext in patient.get("extension", []):
221
+ if ext.get("url") == "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity":
222
+ for sub_ext in ext.get("extension", []):
223
+ if sub_ext.get("url") == "text":
224
+ return sub_ext.get("valueString", "")
225
+ return ""
226
+
227
+ def get_mothers_maiden_name(self) -> str:
228
+ """Extract patient's mother's maiden name from extensions."""
229
+ patient = self._get_current_patient()
230
+ for ext in patient.get("extension", []):
231
+ if ext.get("url") == "http://hl7.org/fhir/StructureDefinition/patient-mothersMaidenName":
232
+ return ext.get("valueString", "")
233
+ return ""
234
+
235
+ def get_birth_place(self) -> Dict[str, str]:
236
+ """Extract patient's birth place from extensions."""
237
+ patient = self._get_current_patient()
238
+ for ext in patient.get("extension", []):
239
+ if ext.get("url") == "http://hl7.org/fhir/StructureDefinition/patient-birthPlace":
240
+ addr = ext.get("valueAddress", {})
241
+ return {
242
+ "city": addr.get("city", ""),
243
+ "state": addr.get("state", ""),
244
+ "country": addr.get("country", "")
245
+ }
246
+ return {"city": "", "state": "", "country": ""}
247
+
248
+ def get_disability_adjusted_life_years(self) -> Optional[float]:
249
+ """Extract disability-adjusted life years from extensions."""
250
+ patient = self._get_current_patient()
251
+ for ext in patient.get("extension", []):
252
+ if ext.get("url") == "http://synthetichealth.github.io/synthea/disability-adjusted-life-years":
253
+ return ext.get("valueDecimal")
254
+ return None
255
+
256
+ def get_quality_adjusted_life_years(self) -> Optional[float]:
257
+ """Extract quality-adjusted life years from extensions."""
258
+ patient = self._get_current_patient()
259
+ for ext in patient.get("extension", []):
260
+ if ext.get("url") == "http://synthetichealth.github.io/synthea/quality-adjusted-life-years":
261
+ return ext.get("valueDecimal")
262
+ return None
263
+
264
+ # Marital Status
265
+ def get_marital_status(self) -> str:
266
+ """Extract patient's marital status."""
267
+ patient = self._get_current_patient()
268
+ status = patient.get("maritalStatus", {}).get("text", "")
269
+ return status if status else patient.get("maritalStatus", {}).get("coding", [{}])[0].get("display", "")
270
+
271
+ # Communication
272
+ def get_language(self) -> str:
273
+ """Extract patient's preferred language."""
274
+ patient = self._get_current_patient()
275
+ comms = patient.get("communication", [])
276
+ return comms[0]["language"]["text"] if comms and "language" in comms[0] else ""
277
+
278
+ # Comprehensive Extraction
279
+ def get_all_patient_data(self) -> Dict[str, Union[str, Dict, List, float, bool, None]]:
280
+ """Extract all available data for the current patient."""
281
  return {
282
+ "id": self.get_id(),
283
+ "resource_type": self.get_resource_type(),
284
+ "meta_last_updated": self.get_meta_last_updated(),
285
+ "meta_profile": self.get_meta_profile(),
286
+ "text_div": self.get_text_div(),
287
  "first_name": self.get_first_name(),
288
  "last_name": self.get_last_name(),
289
  "middle_initial": self.get_middle_initial(),
290
+ "name_prefix": self.get_name_prefix(),
291
+ "maiden_name": self.get_maiden_name(),
292
  "dob": self.get_dob(),
293
  "age": self.get_age(),
294
+ "gender": self.get_gender(),
295
+ "birth_sex": self.get_birth_sex(),
296
+ "multiple_birth": self.get_multiple_birth(),
297
+ "address_line": self.get_address_line(),
298
  "city": self.get_city(),
299
  "state": self.get_state(),
300
  "zip_code": self.get_zip_code(),
301
+ "country": self.get_country(),
302
+ "geolocation": self.get_geolocation(),
303
+ "phone": self.get_phone(),
304
+ "identifiers": self.get_identifiers(),
305
+ "race": self.get_race(),
306
+ "ethnicity": self.get_ethnicity(),
307
+ "mothers_maiden_name": self.get_mothers_maiden_name(),
308
+ "birth_place": self.get_birth_place(),
309
+ "disability_adjusted_life_years": self.get_disability_adjusted_life_years(),
310
+ "quality_adjusted_life_years": self.get_quality_adjusted_life_years(),
311
+ "marital_status": self.get_marital_status(),
312
+ "language": self.get_language()
313
+ }
314
+
315
+ def get_patient_dict(self) -> Dict[str, str]:
316
+ """Return a dictionary of patient data mapped to discharge form fields (for app.py compatibility)."""
317
+ patient_data = self.get_all_patient_data()
318
+ return {
319
+ "first_name": patient_data["first_name"],
320
+ "last_name": patient_data["last_name"],
321
+ "middle_initial": patient_data["middle_initial"],
322
+ "dob": patient_data["dob"],
323
+ "age": patient_data["age"],
324
+ "sex": patient_data["gender"],
325
+ "address": patient_data["address_line"],
326
+ "city": patient_data["city"],
327
+ "state": patient_data["state"],
328
+ "zip_code": patient_data["zip_code"],
329
  "doctor_first_name": "",
330
  "doctor_last_name": "",
331
  "doctor_middle_initial": "",
 
348
  }
349
 
350
  def get_all_patients(self) -> List[Dict[str, str]]:
351
+ """Return a list of dictionaries for all patients (for app.py)."""
352
  original_idx = self.current_patient_idx
353
  all_patients = []
354
  for i in range(len(self.patients)):
355
  self.set_patient_by_index(i)
356
  all_patients.append(self.get_patient_dict())
357
+ self.set_patient_by_index(original_idx)
358
  return all_patients
359
 
360
  def get_patient_ids(self) -> List[str]:
361
  """Return a list of all patient IDs in the Bundle."""
362
  return [patient["id"] for patient in self.patients]
363
 
 
364
  # # Example usage with integration into app.py
365
  # def integrate_with_app(patient_data: str):
366
  # """Integrate PatientDataExtractor with the Gradio app."""