fhir-sheets 2.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fhir-sheets might be problematic. Click here for more details.
- fhir_sheets/__init__.py +0 -0
- fhir_sheets/__init__.pyi +0 -0
- fhir_sheets/cli/__init__.py +0 -0
- fhir_sheets/cli/__init__.pyi +0 -0
- fhir_sheets/cli/main.py +69 -0
- fhir_sheets/cli/main.pyi +6 -0
- fhir_sheets/core/__init__.py +0 -0
- fhir_sheets/core/__init__.pyi +0 -0
- fhir_sheets/core/config/FhirSheetsConfiguration.py +12 -0
- fhir_sheets/core/conversion.py +390 -0
- fhir_sheets/core/conversion.pyi +22 -0
- fhir_sheets/core/fhir_formatting.py +279 -0
- fhir_sheets/core/fhir_formatting.pyi +13 -0
- fhir_sheets/core/model/cohort_data_entity.py +45 -0
- fhir_sheets/core/model/common.py +12 -0
- fhir_sheets/core/model/resource_definition_entity.py +30 -0
- fhir_sheets/core/model/resource_link_entity.py +32 -0
- fhir_sheets/core/read_input.py +102 -0
- fhir_sheets/core/read_input.pyi +8 -0
- fhir_sheets/core/special_values.py +361 -0
- fhir_sheets/core/special_values.pyi +52 -0
- fhir_sheets/core/util.py +1 -0
- fhir_sheets/core/util.pyi +0 -0
- fhir_sheets-2.1.6.dist-info/METADATA +77 -0
- fhir_sheets-2.1.6.dist-info/RECORD +27 -0
- fhir_sheets-2.1.6.dist-info/WHEEL +4 -0
- fhir_sheets-2.1.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
|
|
2
|
+
from . import conversion
|
|
3
|
+
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
|
|
6
|
+
# Define an abstract base class
|
|
7
|
+
class AbstractCustomValueHandler(ABC):
|
|
8
|
+
|
|
9
|
+
@abstractmethod
|
|
10
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
class PatientRaceExtensionValueHandler(AbstractCustomValueHandler):
|
|
14
|
+
omb_categories = {
|
|
15
|
+
"american indian or alaska native" : {
|
|
16
|
+
"url" : "ombCategory",
|
|
17
|
+
"valueCoding" : {
|
|
18
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
19
|
+
"code" : "1002-5",
|
|
20
|
+
"display" : "American Indian or Alaska Native"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"asian" : {
|
|
24
|
+
"url" : "ombCategory",
|
|
25
|
+
"valueCoding" : {
|
|
26
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
27
|
+
"code" : "2028-9",
|
|
28
|
+
"display" : "Asian"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"black or african american" : {
|
|
32
|
+
"url" : "ombCategory",
|
|
33
|
+
"valueCoding" : {
|
|
34
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
35
|
+
"code" : "2054-5",
|
|
36
|
+
"display" : "Black or African American"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"native hawaiian or other pacific islander" : {
|
|
40
|
+
"url" : "ombCategory",
|
|
41
|
+
"valueCoding" : {
|
|
42
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
43
|
+
"code" : "2054-5",
|
|
44
|
+
"display" : "Native Hawaiian or Other Pacific Islander"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"white" : {
|
|
48
|
+
"url" : "ombCategory",
|
|
49
|
+
"valueCoding" : {
|
|
50
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
51
|
+
"code" : "2106-3",
|
|
52
|
+
"display" : "White"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
initial_race_json = {
|
|
58
|
+
"extension" : [
|
|
59
|
+
{
|
|
60
|
+
"$ombCategory"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"url" : "text",
|
|
64
|
+
"valueString" : "$text"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race"
|
|
68
|
+
}
|
|
69
|
+
#Create an ombcategory and detailed section of race extension
|
|
70
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
71
|
+
#Retrieve the race extension if it exists; make it if it does not.
|
|
72
|
+
if 'extension' not in final_struct:
|
|
73
|
+
final_struct['extension'] = []
|
|
74
|
+
race_block = utilFindExtensionWithURL(final_struct['extension'], 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-race')
|
|
75
|
+
if race_block is None:
|
|
76
|
+
race_block = self.initial_race_json
|
|
77
|
+
final_struct['extension'].append(race_block)
|
|
78
|
+
for race_key, race_structure in self.omb_categories.items():
|
|
79
|
+
if value.strip().lower() == race_key:
|
|
80
|
+
# Replace $ombCategory in the extension list
|
|
81
|
+
for i, item in enumerate(race_block["extension"]):
|
|
82
|
+
if isinstance(item, set) and "$ombCategory" in item:
|
|
83
|
+
# Replace the set with the new structure
|
|
84
|
+
race_block["extension"][i] = race_structure
|
|
85
|
+
elif isinstance(item, dict) and item.get("valueString") == "$text":
|
|
86
|
+
item['valueString'] = race_key
|
|
87
|
+
return final_struct
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
class PatientEthnicityExtensionValueHandler(AbstractCustomValueHandler):
|
|
91
|
+
omb_categories = {
|
|
92
|
+
"Hispanic or Latino" : {
|
|
93
|
+
"url" : "ombCategory",
|
|
94
|
+
"valueCoding" : {
|
|
95
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
96
|
+
"code" : "2135-2",
|
|
97
|
+
"display" : "Hispanic or Latino"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"Non Hispanic or Latino" : {
|
|
101
|
+
"url" : "ombCategory",
|
|
102
|
+
"valueCoding" : {
|
|
103
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
104
|
+
"code" : "2186-5",
|
|
105
|
+
"display" : "Not Hispanic or Latino"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"Not Hispanic or Latino" : {
|
|
109
|
+
"url" : "ombCategory",
|
|
110
|
+
"valueCoding" : {
|
|
111
|
+
"system" : "urn:oid:2.16.840.1.113883.6.238",
|
|
112
|
+
"code" : "2186-5",
|
|
113
|
+
"display" : "Not Hispanic or Latino"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
initial_ethnicity_json = {
|
|
119
|
+
"extension" : [
|
|
120
|
+
{
|
|
121
|
+
"$ombCategory"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"url" : "text",
|
|
125
|
+
"valueString" : "$text"
|
|
126
|
+
}
|
|
127
|
+
],
|
|
128
|
+
"url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity"
|
|
129
|
+
}
|
|
130
|
+
#Create an ombcategory and detailed section of ethnicitiy extension
|
|
131
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
132
|
+
#Retrieve the ethncitiy extension if it exists; make it if it does not.
|
|
133
|
+
if 'extension' not in final_struct:
|
|
134
|
+
final_struct['extension'] = []
|
|
135
|
+
ethnicity_block = utilFindExtensionWithURL(final_struct['extension'], 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity')
|
|
136
|
+
if ethnicity_block is None:
|
|
137
|
+
ethnicity_block = self.initial_ethnicity_json
|
|
138
|
+
final_struct['extension'].append(ethnicity_block)
|
|
139
|
+
for race_key, race_structure in self.omb_categories.items():
|
|
140
|
+
if value.strip().lower() == race_key.strip().lower():
|
|
141
|
+
# Replace $ombCategory in the extension list
|
|
142
|
+
for i, item in enumerate(ethnicity_block["extension"]):
|
|
143
|
+
if isinstance(item, set) and "$ombCategory" in item:
|
|
144
|
+
# Replace the set with the new structure
|
|
145
|
+
ethnicity_block["extension"][i] = race_structure
|
|
146
|
+
elif isinstance(item, dict) and item.get("valueString") == "$text":
|
|
147
|
+
item['valueString'] = race_key
|
|
148
|
+
return final_struct
|
|
149
|
+
pass
|
|
150
|
+
|
|
151
|
+
class PatientBirthSexExtensionValueHandler(AbstractCustomValueHandler):
|
|
152
|
+
birth_sex_block = {
|
|
153
|
+
"url" : "http://hl7.org/fhir/us/core/StructureDefinition/us-core-birthsex",
|
|
154
|
+
"valueCode" : "$value"
|
|
155
|
+
}
|
|
156
|
+
#Assigna birthsex extension
|
|
157
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
158
|
+
#Retrieve the birthsex extension if it exists; make it if it does not.
|
|
159
|
+
if 'extension' not in final_struct:
|
|
160
|
+
final_struct['extension'] = []
|
|
161
|
+
birthsex_block = utilFindExtensionWithURL(final_struct['extension'], 'http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity')
|
|
162
|
+
if birthsex_block is None:
|
|
163
|
+
birthsex_block = self.birth_sex_block
|
|
164
|
+
birthsex_block['valueCode'] = value
|
|
165
|
+
final_struct['extension'].append(birthsex_block)
|
|
166
|
+
pass
|
|
167
|
+
|
|
168
|
+
class PatientMRNIdentifierValueHandler(AbstractCustomValueHandler):
|
|
169
|
+
patient_mrn_block = {
|
|
170
|
+
"use" : "usual",
|
|
171
|
+
"type" : {
|
|
172
|
+
"coding" : [
|
|
173
|
+
{
|
|
174
|
+
"system" : "http://terminology.hl7.org/CodeSystem/v2-0203",
|
|
175
|
+
"code" : "MR",
|
|
176
|
+
"display" : "Medical Record Number"
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"text" : "Medical Record Number"
|
|
180
|
+
},
|
|
181
|
+
"system" : "$system",
|
|
182
|
+
"value" : "$value"
|
|
183
|
+
}
|
|
184
|
+
#Assign a MRN identifier
|
|
185
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
186
|
+
#Retrieve the MRN identifier if it exists; make it if it does not.
|
|
187
|
+
target_identifier = self.patient_mrn_block
|
|
188
|
+
new_identifier = True
|
|
189
|
+
if 'identifier' not in final_struct:
|
|
190
|
+
final_struct['identifier'] = []
|
|
191
|
+
for identifier in final_struct['identifier']:
|
|
192
|
+
if 'type' in identifier:
|
|
193
|
+
for coding in identifier['type']['coding']:
|
|
194
|
+
if coding['code'] == 'MR':
|
|
195
|
+
target_identifier = identifier
|
|
196
|
+
new_identifier = False
|
|
197
|
+
if new_identifier:
|
|
198
|
+
final_struct['identifier'].append(target_identifier)
|
|
199
|
+
target_identifier[key] = value
|
|
200
|
+
pass
|
|
201
|
+
|
|
202
|
+
class PatientSSNIdentifierValueHandler(AbstractCustomValueHandler):
|
|
203
|
+
patient_mrn_block = {
|
|
204
|
+
"use" : "usual",
|
|
205
|
+
"type" : {
|
|
206
|
+
"coding" : [
|
|
207
|
+
{
|
|
208
|
+
"system" : "http://terminology.hl7.org/CodeSystem/v2-0203",
|
|
209
|
+
"code" : "SS"
|
|
210
|
+
}
|
|
211
|
+
],
|
|
212
|
+
"text" : "Social Security Number"
|
|
213
|
+
},
|
|
214
|
+
"system" : "$system",
|
|
215
|
+
"value" : "$value"
|
|
216
|
+
}
|
|
217
|
+
#Assign a MRN identifier
|
|
218
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
219
|
+
#Retrieve the MRN identifier if it exists; make it if it does not.
|
|
220
|
+
target_identifier = self.patient_mrn_block
|
|
221
|
+
new_identifier = True
|
|
222
|
+
if 'identifier' not in final_struct:
|
|
223
|
+
final_struct['identifier'] = []
|
|
224
|
+
for identifier in final_struct['identifier']:
|
|
225
|
+
if 'type' in identifier:
|
|
226
|
+
for coding in identifier['type']['coding']:
|
|
227
|
+
if coding['code'] == 'SS':
|
|
228
|
+
target_identifier = identifier
|
|
229
|
+
new_identifier = False
|
|
230
|
+
if new_identifier:
|
|
231
|
+
final_struct['identifier'].append(target_identifier)
|
|
232
|
+
target_identifier[key] = value
|
|
233
|
+
pass
|
|
234
|
+
|
|
235
|
+
class OrganizationIdentiferNPIValueHandler(AbstractCustomValueHandler):
|
|
236
|
+
npi_identifier_block = {
|
|
237
|
+
"system" : "http://hl7.org.fhir/sid/us-npi",
|
|
238
|
+
"value" : "$value"
|
|
239
|
+
}
|
|
240
|
+
#Assigna birthsex extension
|
|
241
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
242
|
+
#Retrieve the birthsex extension if it exists; make it if it does not.
|
|
243
|
+
if 'identifier' not in final_struct:
|
|
244
|
+
final_struct['identifier'] = []
|
|
245
|
+
identifier_block = next((entry for entry in final_struct['identifier'] if entry['system'] == "http://hl7.org.fhir/sid/us-npi"), None)
|
|
246
|
+
if identifier_block is None:
|
|
247
|
+
identifier_block = self.npi_identifier_block
|
|
248
|
+
final_struct['identifier'].append(identifier_block)
|
|
249
|
+
identifier_block['value'] = str(value)
|
|
250
|
+
pass
|
|
251
|
+
|
|
252
|
+
class OrganizationIdentiferCLIAValueHandler(AbstractCustomValueHandler):
|
|
253
|
+
clia_identifier_block = {
|
|
254
|
+
"system" : "urn:oid:2.16.840.1.113883.4.7",
|
|
255
|
+
"value" : "$value"
|
|
256
|
+
}
|
|
257
|
+
#Assign a birthsex extension
|
|
258
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
259
|
+
#Retrieve the birthsex extension if it exists; make it if it does not.
|
|
260
|
+
if 'identifier' not in final_struct:
|
|
261
|
+
final_struct['identifier'] = []
|
|
262
|
+
identifier_block = next((entry for entry in final_struct['identifier'] if entry['system'] == "urn:oid:2.16.840.1.113883.4.7"), None)
|
|
263
|
+
if identifier_block is None:
|
|
264
|
+
identifier_block = self.clia_identifier_block
|
|
265
|
+
final_struct['identifier'].append(identifier_block)
|
|
266
|
+
identifier_block['value'] = str(value)
|
|
267
|
+
pass
|
|
268
|
+
|
|
269
|
+
class PractitionerIdentiferNPIValueHandler(AbstractCustomValueHandler):
|
|
270
|
+
npi_identifier_block = {
|
|
271
|
+
"system" : "http://hl7.org.fhir/sid/us-npi",
|
|
272
|
+
"value" : "$value"
|
|
273
|
+
}
|
|
274
|
+
#Assigna birthsex extension
|
|
275
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
276
|
+
#Retrieve the birthsex extension if it exists; make it if it does not.
|
|
277
|
+
if 'identifier' not in final_struct:
|
|
278
|
+
final_struct['identifier'] = []
|
|
279
|
+
identifier_block = next((entry for entry in final_struct['identifier'] if entry['system'] == "http://hl7.org.fhir/sid/us-npi"), None)
|
|
280
|
+
if identifier_block is None:
|
|
281
|
+
identifier_block = self.npi_identifier_block
|
|
282
|
+
final_struct['identifier'].append(identifier_block)
|
|
283
|
+
identifier_block['value'] = value
|
|
284
|
+
pass
|
|
285
|
+
|
|
286
|
+
class ObservationComponentHandler(AbstractCustomValueHandler):
|
|
287
|
+
pulse_oximetry_oxygen_flow_rate = {
|
|
288
|
+
"code" : {
|
|
289
|
+
"coding" : [
|
|
290
|
+
{
|
|
291
|
+
"system" : "http://loinc.org",
|
|
292
|
+
"code" : "3151-8",
|
|
293
|
+
"display" : "Inhaled oxygen flow rate"
|
|
294
|
+
}
|
|
295
|
+
],
|
|
296
|
+
"text" : "Inhaled oxygen flow rate"
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
pulse_oximetry_oxygen_concentration = {
|
|
300
|
+
"code" : {
|
|
301
|
+
"coding" : [
|
|
302
|
+
{
|
|
303
|
+
"system" : "http://loinc.org",
|
|
304
|
+
"code" : "3150-0",
|
|
305
|
+
"display" : "Inhaled oxygen concentration"
|
|
306
|
+
}
|
|
307
|
+
],
|
|
308
|
+
"text" : "Inhaled oxygen concentration"
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
#Find the appropriate component for the observaiton; then call build_structure again to continue the drill down
|
|
312
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value):
|
|
313
|
+
#Check to make sure the component part exists
|
|
314
|
+
if 'component' not in final_struct:
|
|
315
|
+
final_struct['component'] = []
|
|
316
|
+
components = final_struct['component']
|
|
317
|
+
#Look through the qualifier parts.
|
|
318
|
+
parts = json_path.split('.')
|
|
319
|
+
key_part = parts[1][:parts[1].index('[')]
|
|
320
|
+
qualifier = parts[1][parts[1].index('[')+1:parts[1].index(']')]
|
|
321
|
+
qualifier_condition = qualifier.split('=')
|
|
322
|
+
|
|
323
|
+
target_component: dict = {}
|
|
324
|
+
if qualifier_condition[0] == 'code' and qualifier_condition[1] == '3151-8':
|
|
325
|
+
target_component = findComponentWithCoding(components, '3151-8') or self.pulse_oximetry_oxygen_flow_rate
|
|
326
|
+
if target_component is self.pulse_oximetry_oxygen_flow_rate:
|
|
327
|
+
components.append(target_component)
|
|
328
|
+
if qualifier_condition[0] == 'code' and qualifier_condition[1] == '3150-0':
|
|
329
|
+
target_component = findComponentWithCoding(components, '3150-0') or self.pulse_oximetry_oxygen_concentration
|
|
330
|
+
if target_component is self.pulse_oximetry_oxygen_concentration:
|
|
331
|
+
components.append(target_component)
|
|
332
|
+
#Recurse back down into
|
|
333
|
+
# current_struct: Dict, json_path: str, resource_definition: ResourceDefinition, dataType: str, parts: List[str], value: Any, previous_parts: List[str]
|
|
334
|
+
return conversion.build_structure(target_component, '.'.join(parts[2:]), resource_definition, dataType, parts[2:], value, parts[:2])
|
|
335
|
+
pass
|
|
336
|
+
|
|
337
|
+
def utilFindExtensionWithURL(extension_block, url):
|
|
338
|
+
for extension in extension_block:
|
|
339
|
+
if "url" in extension and extension['url'] == url:
|
|
340
|
+
return extension
|
|
341
|
+
return None
|
|
342
|
+
|
|
343
|
+
def findComponentWithCoding(components, code):
|
|
344
|
+
return next((component for component in components if any(coding['code'] == code for coding in component['code']['coding'])), None)
|
|
345
|
+
|
|
346
|
+
#Data dictionary of jsonpaths to match vs classes that need to be called
|
|
347
|
+
custom_handlers = {
|
|
348
|
+
"Patient.extension[Race].ombCategory": PatientRaceExtensionValueHandler(),
|
|
349
|
+
"Patient.extension[Ethnicity].ombCategory": PatientEthnicityExtensionValueHandler(),
|
|
350
|
+
"Patient.extension[Birthsex].value": PatientBirthSexExtensionValueHandler(),
|
|
351
|
+
"Patient.identifier[type=MR].system": PatientMRNIdentifierValueHandler(),
|
|
352
|
+
"Patient.identifier[type=MR].value": PatientMRNIdentifierValueHandler(),
|
|
353
|
+
"Patient.identifier[type=MRN].system": PatientMRNIdentifierValueHandler(),
|
|
354
|
+
"Patient.identifier[type=MRN].value": PatientMRNIdentifierValueHandler(),
|
|
355
|
+
"Patient.identifier[type=SSN].system": PatientSSNIdentifierValueHandler(),
|
|
356
|
+
"Patient.identifier[type=SSN].value": PatientSSNIdentifierValueHandler(),
|
|
357
|
+
"Organization.identifier[system=NPI].value": OrganizationIdentiferNPIValueHandler(),
|
|
358
|
+
"Organization.identifier[system=CLIA].value": OrganizationIdentiferCLIAValueHandler(),
|
|
359
|
+
"Practitioner.identifier[system=NPI].value": PractitionerIdentiferNPIValueHandler(),
|
|
360
|
+
"Observation.component[": ObservationComponentHandler()
|
|
361
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from . import conversion as conversion
|
|
3
|
+
from _typeshed import Incomplete
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
|
|
6
|
+
class AbstractCustomValueHandler(ABC, metaclass=abc.ABCMeta):
|
|
7
|
+
@abstractmethod
|
|
8
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value): ...
|
|
9
|
+
|
|
10
|
+
class PatientRaceExtensionValueHandler(AbstractCustomValueHandler):
|
|
11
|
+
omb_categories: Incomplete
|
|
12
|
+
initial_race_json: Incomplete
|
|
13
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value): ...
|
|
14
|
+
|
|
15
|
+
class PatientEthnicityExtensionValueHandler(AbstractCustomValueHandler):
|
|
16
|
+
omb_categories: Incomplete
|
|
17
|
+
initial_ethnicity_json: Incomplete
|
|
18
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value): ...
|
|
19
|
+
|
|
20
|
+
class PatientBirthSexExtensionValueHandler(AbstractCustomValueHandler):
|
|
21
|
+
birth_sex_block: Incomplete
|
|
22
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value) -> None: ...
|
|
23
|
+
|
|
24
|
+
class PatientMRNIdentifierValueHandler(AbstractCustomValueHandler):
|
|
25
|
+
patient_mrn_block: Incomplete
|
|
26
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value) -> None: ...
|
|
27
|
+
|
|
28
|
+
class PatientSSNIdentifierValueHandler(AbstractCustomValueHandler):
|
|
29
|
+
patient_mrn_block: Incomplete
|
|
30
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value) -> None: ...
|
|
31
|
+
|
|
32
|
+
class OrganizationIdentiferNPIValueHandler(AbstractCustomValueHandler):
|
|
33
|
+
npi_identifier_block: Incomplete
|
|
34
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value) -> None: ...
|
|
35
|
+
|
|
36
|
+
class OrganizationIdentiferCLIAValueHandler(AbstractCustomValueHandler):
|
|
37
|
+
clia_identifier_block: Incomplete
|
|
38
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value) -> None: ...
|
|
39
|
+
|
|
40
|
+
class PractitionerIdentiferNPIValueHandler(AbstractCustomValueHandler):
|
|
41
|
+
npi_identifier_block: Incomplete
|
|
42
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value) -> None: ...
|
|
43
|
+
|
|
44
|
+
class ObservationComponentHandler(AbstractCustomValueHandler):
|
|
45
|
+
pulse_oximetry_oxygen_flow_rate: Incomplete
|
|
46
|
+
pulse_oximetry_oxygen_concentration: Incomplete
|
|
47
|
+
def assign_value(self, json_path, resource_definition, dataType, final_struct, key, value): ...
|
|
48
|
+
|
|
49
|
+
def utilFindExtensionWithURL(extension_block, url): ...
|
|
50
|
+
def findComponentWithCoding(components, code): ...
|
|
51
|
+
|
|
52
|
+
custom_handlers: Incomplete
|
fhir_sheets/core/util.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
resource_
|
|
File without changes
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fhir-sheets
|
|
3
|
+
Version: 2.1.6
|
|
4
|
+
Summary: FhirSheets is a command-line tool that reads an Excel file in FHIR cohort format and generates FHIR bundle JSON files from it. Each row in the template Excel file is used to create an individual JSON file, outputting them to a specified folder.
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Author: Michael Riley
|
|
7
|
+
Author-email: Michael.Riley@gtri.gatech.edu
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Requires-Dist: et-xmlfile (==1.1.0)
|
|
13
|
+
Requires-Dist: jsonpath-ng (==1.6.1)
|
|
14
|
+
Requires-Dist: openpyxl (==3.1.5)
|
|
15
|
+
Requires-Dist: orjson (==3.10.7)
|
|
16
|
+
Requires-Dist: ply (==3.11)
|
|
17
|
+
Requires-Dist: pytest (==8.4.2)
|
|
18
|
+
Requires-Dist: pytest_cov (==7.0.0)
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# FHIRSheets
|
|
22
|
+
|
|
23
|
+
FhirSheets is a command-line tool that reads an Excel file in FHIR cohort format and generates FHIR bundle JSON files from it. Each row in the template Excel file is used to create an individual JSON file, outputting them to a specified folder.
|
|
24
|
+
|
|
25
|
+
## Table of Contents
|
|
26
|
+
- [FHIRSheets](#fhirsheets)
|
|
27
|
+
- [Table of Contents](#table-of-contents)
|
|
28
|
+
- [Features](#features)
|
|
29
|
+
- [Requirements](#requirements)
|
|
30
|
+
- [Installation](#installation)
|
|
31
|
+
- [Usage](#Usage)
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
- Reads an Excel file following the FHIR cohort import template.
|
|
35
|
+
- Converts each row in the Excel file to a FHIR bundle JSON file.
|
|
36
|
+
- Exports generated JSON files to a specified output folder.
|
|
37
|
+
|
|
38
|
+
## Requirements
|
|
39
|
+
- Python 3.x
|
|
40
|
+
- Required Python packages (see `requirements.txt`)
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
1. Clone this repository:
|
|
44
|
+
```bash
|
|
45
|
+
git clone https://github.com/CDCgov/synthetic-data.git
|
|
46
|
+
cd fhir-python-cohort-generation
|
|
47
|
+
2. Install the required packages:
|
|
48
|
+
```bash
|
|
49
|
+
pip install -r requirements.txt
|
|
50
|
+
```
|
|
51
|
+
Or use poetry
|
|
52
|
+
```bash
|
|
53
|
+
poetry build
|
|
54
|
+
```
|
|
55
|
+
## Usage
|
|
56
|
+
1. **Fill Out the Template:**
|
|
57
|
+
- Open the template file `src/resources/Fhir_Cohort_Import_Template.xlsx`.
|
|
58
|
+
- Fill out each row with the relevant data.
|
|
59
|
+
|
|
60
|
+
2. **Run the Tool:**
|
|
61
|
+
- Use the `python -m src.cli.fhirsheets` module script with the required arguments:
|
|
62
|
+
- `--input-file`: The path to the input Excel file.
|
|
63
|
+
- `--output-folder`: The path to the output folder where the JSON files will be saved.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
python -m src.fhir_sheets.cli.main --input_file src/resources/Fhir_Cohort_Import_Template.xlsx --output_folder /path/to/output/folder
|
|
67
|
+
3. The tool will generate one FHIR bundle JSON file for each row defined in the template.
|
|
68
|
+
|
|
69
|
+
## Example
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python -m src.fhir_sheets.cli.main --input_file src/resources/Fhir_Cohort_Import_Template.xlsx --output_folder ./output_bundles
|
|
73
|
+
In this example, each row in the `Fhir_Cohort_Import_Template.xlsx` file will be processed, and a corresponding JSON file will be generated in the `output_bundles` folder.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
This project is licensed under the MIT License. See the `LICENSE` file for more information.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
fhir_sheets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
fhir_sheets/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
fhir_sheets/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
fhir_sheets/cli/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
fhir_sheets/cli/main.py,sha256=zpCieUZUyC1JVVGo8eV4slaTxjHPhsJDUYpX3Pq-BaY,3417
|
|
6
|
+
fhir_sheets/cli/main.pyi,sha256=XvDH_2-keuxAgh2ZPfM7bjX86kA9ruqZwbvFtw7td78,315
|
|
7
|
+
fhir_sheets/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
fhir_sheets/core/__init__.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
fhir_sheets/core/config/FhirSheetsConfiguration.py,sha256=YFXfNaA5hpFPwp9wBeNogo7u2VR11-KO5uBY-Ckh8QY,465
|
|
10
|
+
fhir_sheets/core/conversion.py,sha256=ZVogAKNjA3odb87NwDlP_oLMloUfFBFth51ZZsbRe1c,22726
|
|
11
|
+
fhir_sheets/core/conversion.pyi,sha256=s9-ntcPaqIQYqXvkItO-uXhV13A3khBw5n4H2l2aqmw,2140
|
|
12
|
+
fhir_sheets/core/fhir_formatting.py,sha256=-ZND6RHmamX3vVfpTWLfFGEdH0A3E-JP8mDJkHSdfdw,13206
|
|
13
|
+
fhir_sheets/core/fhir_formatting.pyi,sha256=JVju6WwzG7H9iI-5MO5Q0V-8-dNoWVxCzWLCFUW3cl4,512
|
|
14
|
+
fhir_sheets/core/model/cohort_data_entity.py,sha256=Nt_RIhHZQ_bnf6tihcMNDMmdUJDp01ZgBofMY2YJ5D0,2039
|
|
15
|
+
fhir_sheets/core/model/common.py,sha256=b9CqSNyY-JxnipydjWtXiEaKEXQkinWr3KwtO9RVQSA,435
|
|
16
|
+
fhir_sheets/core/model/resource_definition_entity.py,sha256=ek8HmCkhlCo6hBL-TAFQTEAf1yE4cV0Juvb-vUcMm2o,1189
|
|
17
|
+
fhir_sheets/core/model/resource_link_entity.py,sha256=5p6Rzusela-VnzkvlcL0VCXEPfFX11mxVUeScqR-alA,1394
|
|
18
|
+
fhir_sheets/core/read_input.py,sha256=IMuU44gsvyFmDioG89qs218GVBnTmnJndxWhcScpEVU,5450
|
|
19
|
+
fhir_sheets/core/read_input.pyi,sha256=W7sStgDvwRFoEUGKGMkMWw2b3uZRicncHbHU0r3bFQw,489
|
|
20
|
+
fhir_sheets/core/special_values.py,sha256=TfUuYYWeZgjG45eNtjY_oUqXj9pAPAmlzGtIbmZac08,15579
|
|
21
|
+
fhir_sheets/core/special_values.pyi,sha256=fs3bm8QdzohNLQ_9roX79pYhuUDEJv_2NNzta3jFAJk,2472
|
|
22
|
+
fhir_sheets/core/util.py,sha256=gudEPi_xTDC9YHqUlGEkn_tA26HbhNjuqGgjtuOEINk,9
|
|
23
|
+
fhir_sheets/core/util.pyi,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
fhir_sheets-2.1.6.dist-info/METADATA,sha256=MKYFlBBaX_A4RP92G4LxMavERScObkyFPR7MvtxWEaQ,2979
|
|
25
|
+
fhir_sheets-2.1.6.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
26
|
+
fhir_sheets-2.1.6.dist-info/licenses/LICENSE,sha256=Qv2ilebwoUtMJnRsZwRy729xS5JZQzLauJ0tQzkAkTA,1088
|
|
27
|
+
fhir_sheets-2.1.6.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [year] [fullname]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|