fhir-sheets 1.1.0__tar.gz → 1.2.0__tar.gz

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.

@@ -1,12 +1,14 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: fhir-sheets
3
- Version: 1.1.0
4
- Summary: FhirSheetsiIs 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.
3
+ Version: 1.2.0
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
5
6
  Author: Michael Riley
6
7
  Author-email: Michael.Riley@gtri.gatech.edu
7
8
  Requires-Python: >=3.13
8
9
  Classifier: Programming Language :: Python :: 3
9
10
  Classifier: Programming Language :: Python :: 3.13
11
+ Classifier: Programming Language :: Python :: 3.14
10
12
  Requires-Dist: et-xmlfile (==1.1.0)
11
13
  Requires-Dist: jsonpath-ng (==1.6.1)
12
14
  Requires-Dist: openpyxl (==3.1.5)
@@ -1,7 +1,7 @@
1
1
  [tool.poetry]
2
2
  name = "fhir-sheets"
3
- version = "1.1.0"
4
- description = "FhirSheetsiIs 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."
3
+ version = "1.2.0"
4
+ description = "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
5
  authors = ["Michael Riley <Michael.Riley@gtri.gatech.edu>"]
6
6
  packages = [{include = "fhir_sheets", from = "src"}]
7
7
 
@@ -5,6 +5,7 @@ import argparse
5
5
  import orjson
6
6
  import json
7
7
  from pathlib import Path
8
+ from pprint import pprint
8
9
 
9
10
  def find_sets(d, path=""):
10
11
  if isinstance(d, dict):
@@ -27,16 +28,14 @@ def main(input_file, output_folder):
27
28
  output_folder_path = Path().cwd() / Path(output_folder)
28
29
  if not output_folder_path.exists():
29
30
  output_folder_path.mkdir(parents=True, exist_ok=True) # Create the folder if it doesn't exist
30
- data = read_input.read_xlsx_and_process(input_file)
31
- resource_definition_entities = data['resource_definition_entities']
32
-
31
+ resource_definition_entities, resource_link_entities, cohort_data = read_input.read_xlsx_and_process(input_file)
32
+ pprint(cohort_data)
33
33
  #For each index of patients
34
- for i in range(0,data['num_entries']):
34
+ for i in range(0,cohort_data.num_entries):
35
35
  # Construct the file path for each JSON file
36
36
  file_path = output_folder_path / f"{i}.json"
37
37
  #Create a bundle
38
- fhir_bundle = conversion.create_transaction_bundle(data['resource_definition_entities'],
39
- data['resource_link_entities'], data['patient_data_entities'], i)
38
+ fhir_bundle = conversion.create_transaction_bundle(resource_definition_entities, resource_link_entities, cohort_data, i)
40
39
  # Step 3: Write the processed data to the output file
41
40
  find_sets(fhir_bundle)
42
41
  json_string = orjson.dumps(fhir_bundle)
@@ -1,18 +1,23 @@
1
+ from typing import Any, Dict, List
1
2
  import uuid
2
3
  from jsonpath_ng.jsonpath import Fields, Slice, Where
3
4
  from jsonpath_ng.ext import parse as parse_ext
5
+
6
+ from .model.cohort_data_entity import CohortData, FieldEntry
7
+ from .model.resource_definition_entity import ResourceDefinition
8
+ from .model.resource_link_entity import ResourceLink
4
9
  from . import fhir_formatting
5
10
  from . import special_values
6
11
 
7
12
  #Main top level function
8
13
  #Creates a full transaction bundle for a patient at index
9
- def create_transaction_bundle(resource_definition_entities, resource_link_entities, patient_data, index = 0):
14
+ def create_transaction_bundle(resource_definition_entities: List[ResourceDefinition], resource_link_entities: List[ResourceLink], cohort_data: CohortData, index = 0):
10
15
  root_bundle = initialize_bundle()
11
16
  created_resources = {}
12
17
  for resource_definition in resource_definition_entities:
13
- entity_name = resource_definition['Entity Name']
18
+ entity_name = resource_definition.entity_name
14
19
  #Create and collect fhir resources
15
- fhir_resource = create_fhir_resource(resource_definition, patient_data, index)
20
+ fhir_resource = create_fhir_resource(resource_definition, cohort_data, index)
16
21
  created_resources[entity_name] = fhir_resource
17
22
  #Link resources after creation
18
23
  add_default_resource_links(created_resources, resource_link_entities)
@@ -31,36 +36,35 @@ def initialize_bundle():
31
36
  root_bundle['entry'] = []
32
37
  return root_bundle
33
38
 
39
+ #Initialize a resource from a resource definition. Adding basic information all resources need
40
+ def initialize_resource(resource_definition):
41
+ initial_resource = {}
42
+ initial_resource['resourceType'] = resource_definition.resource_type.strip()
43
+ initial_resource['id'] = str(uuid.uuid4()).strip()
44
+ if resource_definition.profiles:
45
+ initial_resource['meta'] = {
46
+ 'profile': resource_definition.profiles
47
+ }
48
+ return initial_resource
49
+
34
50
  # Creates a fhir-json structure from a resource definition entity and the patient_data_sheet
35
- def create_fhir_resource(resource_definition, patient_data, index = 0):
51
+ def create_fhir_resource(resource_definition: ResourceDefinition, cohort_data: CohortData, index = 0):
36
52
  resource_dict = initialize_resource(resource_definition)
37
53
  #Get field entries for this entitiy
38
54
  try:
39
- all_field_entries = patient_data[resource_definition['Entity Name']]
55
+ all_field_entries = cohort_data.entities[resource_definition.entity_name].fields
40
56
  except KeyError:
41
- print(f"WARNING: Patient index {index} - Create Fhir Resource Error - {resource_definition['Entity Name']} - No columns for entity '{resource_definition['Entity Name']}' found for resource in 'PatientData' sheet")
57
+ print(f"WARNING: Patient index {index} - Create Fhir Resource Error - {resource_definition.entity_name} - No columns for entity '{resource_definition.entity_name}' found for resource in 'PatientData' sheet")
42
58
  return resource_dict
43
59
  #For each field within the entity
44
- for field_entry in all_field_entries.values():
60
+ for field_entry_key, field_entry in all_field_entries.items():
45
61
  #Create a jsonpath from each provided json path and value for this resource
46
- if field_entry['values'] and len(field_entry['values']) > index:
47
- create_structure_from_jsonpath(resource_dict, field_entry['jsonpath'], resource_definition, field_entry, field_entry['valueType'], field_entry['values'][index])
62
+ if field_entry.values and len(field_entry.values) > index:
63
+ create_structure_from_jsonpath(resource_dict, field_entry.jsonpath, resource_definition, field_entry, field_entry.value_type, field_entry.values[index])
48
64
  return resource_dict
49
-
50
- #Initialize a resource from a resource definition. Adding basic
51
- def initialize_resource(resource_definition):
52
- initial_resource = {}
53
- initial_resource['resourceType'] = resource_definition['ResourceType'].strip()
54
- resource_definition['id'] = str(uuid.uuid4())
55
- initial_resource['id'] = resource_definition['id'].strip()
56
- if resource_definition['Profile(s)']:
57
- initial_resource['meta'] = {
58
- 'profile': resource_definition['Profile(s)']
59
- }
60
- return initial_resource
61
65
 
62
66
  #Create a resource_link for default references in the cases where only 1 resourceType of the source and destination exist
63
- def add_default_resource_links(created_resources, resource_link_entities):
67
+ def add_default_resource_links(created_resources: dict, resource_link_entities: List[ResourceLink]):
64
68
  default_references = [
65
69
  ('allergyintolerance', 'patient', 'patient'),
66
70
  ('allergyintolerance', 'practitioner', 'asserter'),
@@ -115,11 +119,11 @@ def add_default_resource_links(created_resources, resource_link_entities):
115
119
  originResourceEntityName = resource_counts[sourceType]['singletonEntityName']
116
120
  destinationResourceEntityName = resource_counts[destinationType]['singletonEntityName']
117
121
  resource_link_entities.append(
118
- {
122
+ ResourceLink({
119
123
  "OriginResource": originResourceEntityName,
120
124
  "DestinationResource": destinationResourceEntityName,
121
125
  "ReferencePath": fieldName
122
- }
126
+ })
123
127
  )
124
128
  return
125
129
 
@@ -143,29 +147,29 @@ def create_resource_links(created_resources, resource_link_entites):
143
147
  print("Building resource links")
144
148
  for resource_link_entity in resource_link_entites:
145
149
  try:
146
- origin_resource = created_resources[resource_link_entity['OriginResource']]
150
+ origin_resource = created_resources[resource_link_entity.origin_resource]
147
151
  except KeyError:
148
- print(f"WARNING: In ResourceLinks tab, found a Origin Resource of : {resource_link_entity['OriginResource']} but no such entity found in PatientData")
152
+ print(f"WARNING: In ResourceLinks tab, found a Origin Resource of : {resource_link_entity.origin_resource} but no such entity found in PatientData")
149
153
  continue
150
154
  try:
151
- destination_resource = created_resources[resource_link_entity['DestinationResource']]
155
+ destination_resource = created_resources[resource_link_entity.destination_resource]
152
156
  except KeyError:
153
- print(f"WARNING: In ResourceLinks tab, found a Desitnation Resource of : {resource_link_entity['DestinationResource']} but no such entity found in PatientData")
157
+ print(f"WARNING: In ResourceLinks tab, found a Desitnation Resource of : {resource_link_entity.destination_resource} but no such entity found in PatientData")
154
158
  continue
155
- destination_resource_type = created_resources[resource_link_entity['DestinationResource']]['resourceType']
156
- destination_resource_id = created_resources[resource_link_entity['DestinationResource']]['id']
157
- link_tuple = (created_resources[resource_link_entity['OriginResource']]['resourceType'].strip().lower(),
158
- created_resources[resource_link_entity['DestinationResource']]['resourceType'].strip().lower(),
159
- resource_link_entity['ReferencePath'].strip().lower())
159
+ destination_resource_type = created_resources[resource_link_entity.destination_resource]['resourceType']
160
+ destination_resource_id = created_resources[resource_link_entity.destination_resource]['id']
161
+ link_tuple = (created_resources[resource_link_entity.origin_resource]['resourceType'].strip().lower(),
162
+ created_resources[resource_link_entity.destination_resource]['resourceType'].strip().lower(),
163
+ resource_link_entity.reference_path.strip().lower())
160
164
  if link_tuple in arrayType_references:
161
- if resource_link_entity['ReferencePath'].strip().lower() not in origin_resource:
162
- origin_resource[resource_link_entity['ReferencePath'].strip().lower()] = []
165
+ if resource_link_entity.reference_path.strip().lower() not in origin_resource:
166
+ origin_resource[resource_link_entity.reference_path.strip().lower()] = []
163
167
  new_reference = reference_json_block.copy()
164
168
  new_reference['reference'] = destination_resource_type + "/" + destination_resource_id
165
- origin_resource[resource_link_entity['ReferencePath'].strip().lower()].append(new_reference)
169
+ origin_resource[resource_link_entity.reference_path.strip().lower()].append(new_reference)
166
170
  else:
167
- origin_resource[resource_link_entity['ReferencePath'].strip().lower()] = reference_json_block.copy()
168
- origin_resource[resource_link_entity['ReferencePath'].strip().lower()]["reference"] = destination_resource_type + "/" + destination_resource_id
171
+ origin_resource[resource_link_entity.reference_path.strip().lower()] = reference_json_block.copy()
172
+ origin_resource[resource_link_entity.reference_path.strip().lower()]["reference"] = destination_resource_type + "/" + destination_resource_id
169
173
  return
170
174
 
171
175
  def add_resource_to_transaction_bundle(root_bundle, fhir_resource):
@@ -188,7 +192,7 @@ def add_resource_to_transaction_bundle(root_bundle, fhir_resource):
188
192
  # resource_definition: resource description model from import
189
193
  # entity_definition: specific field entry information for this function
190
194
  # value: Actual value to assign
191
- def create_structure_from_jsonpath(root_struct, json_path, resource_definition, entity_definition, dataType, value):
195
+ def create_structure_from_jsonpath(root_struct: Dict, json_path: str, resource_definition: ResourceDefinition, field_entry: FieldEntry, dataType: str, value: Any):
192
196
  #Get all dot notation components as seperate
193
197
  if dataType is not None and dataType.strip().lower() == 'string':
194
198
  value = str(value)
@@ -198,7 +202,7 @@ def create_structure_from_jsonpath(root_struct, json_path, resource_definition,
198
202
  return root_struct
199
203
  #Start of top-level function which calls the enclosed recursive function
200
204
  parts = json_path.split('.')
201
- return build_structure(root_struct, json_path, resource_definition, entity_definition, parts, value, [])
205
+ return build_structure(root_struct, json_path, resource_definition, field_entry, parts, value, [])
202
206
 
203
207
  # main recursive function to drill into the json structure, assign paths, and create structure where needed
204
208
  def build_structure(current_struct, json_path, resource_definition, entity_definition, parts, value, previous_parts):
@@ -211,7 +215,7 @@ def build_structure(current_struct, json_path, resource_definition, entity_defin
211
215
  if matching_handler is not None:
212
216
  return special_values.custom_handlers[matching_handler].assign_value(json_path, resource_definition, entity_definition, current_struct, parts[-1], value)
213
217
  #Ignore dollar sign ($) and drill farther down
214
- if part == '$' or part == resource_definition['ResourceType'].strip():
218
+ if part == '$' or part == resource_definition.resource_type.strip():
215
219
  #Ignore the dollar sign and the resourcetype
216
220
  return build_structure_recurse(current_struct, json_path, resource_definition, entity_definition, parts, value, previous_parts, part)
217
221
 
@@ -236,7 +240,7 @@ def build_structure(current_struct, json_path, resource_definition, entity_defin
236
240
  if part + 1 > len(current_struct):
237
241
  current_struct.extend({} for x in range (part + 1 - len(current_struct)))
238
242
  #Actual assigning to the path
239
- fhir_formatting.assign_value(current_struct, part, value, entity_definition['valueType'])
243
+ fhir_formatting.assign_value(current_struct, part, value, entity_definition.value_type)
240
244
  return current_struct
241
245
 
242
246
  # If there is a simple qualifier with '['and ']'
@@ -0,0 +1,97 @@
1
+ import pprint
2
+ from typing import Dict, Any, List, Optional
3
+
4
+ class FieldEntry:
5
+ def __init__(self, data: Dict[str, Any]):
6
+ self.jsonpath: Optional[str] = data.get('jsonpath')
7
+ self.value_type: Optional[str] = data.get('valueType')
8
+ self.valuesets: Optional[str] = data.get('valuesets')
9
+ self.values: Optional[List[str]] = data.get('values')
10
+
11
+ def __repr__(self) -> str:
12
+ return (f"FieldEntry(\n\tjsonpath='{self.jsonpath}',\n\tvalue_type='{self.value_type}', "
13
+ f"\n\tvaluesets='{self.valuesets}', \n\tvalues={self.values})")
14
+
15
+ class EntityData:
16
+ def __init__(self, data: Dict[str, Dict[str, Any]]):
17
+ """
18
+ Initializes the EntityData object. Accepts either a dictionary of raw data
19
+ or a list of FieldEntry objects.
20
+
21
+ Args:
22
+ data (Dict[str, Dict[str, Any]]): A dictionary mapping names to raw field data.
23
+ entries (List[FieldEntry]): A list of pre-created FieldEntry objects.
24
+ """
25
+ self.fields: Dict[str, FieldEntry] = {}
26
+ for name, field_data in data.items():
27
+ self.fields[name] = FieldEntry(field_data)
28
+
29
+ def __repr__(self) -> str:
30
+ return f"EntityData(fields=\n{pprint.pformat(self.fields, indent=4)})"
31
+
32
+ def insert(self, name: str, entry: FieldEntry):
33
+ """
34
+ Inserts a new FieldEntry into the collection.
35
+
36
+ Args:
37
+ name (str): The referential name for the field.
38
+ entry (FieldEntry): The FieldEntry object to insert.
39
+ """
40
+ self.fields[name] = entry
41
+
42
+ def remove(self, name: str) -> bool:
43
+ """
44
+ Removes a FieldEntry by its referential name.
45
+
46
+ Args:
47
+ name (str): The referential name of the field to remove.
48
+
49
+ Returns:
50
+ bool: True if the field was removed, False otherwise.
51
+ """
52
+ if name in self.fields:
53
+ del self.fields[name]
54
+ return True
55
+ return False
56
+
57
+ class CohortData:
58
+ def __init__(self, data: Dict[str, EntityData] = None):
59
+ """
60
+ Initializes the CohortData object.
61
+
62
+ Args:
63
+ data (Dict[str, EntityData]): A dictionary where keys are entity names
64
+ and values are EntityData objects.
65
+ """
66
+ self.entities: Dict[str, EntityData] = {}
67
+ self.num_entries = 0
68
+ if data:
69
+ self.entities.update(data)
70
+
71
+ def __repr__(self) -> str:
72
+ return f"CohortData(entities={self.entities})"
73
+
74
+ def insert_entity(self, name: str, entity_data: EntityData):
75
+ """
76
+ Inserts a new EntityData object into the cohort.
77
+
78
+ Args:
79
+ name (str): The name of the entity (e.g., 'PrimaryPatient').
80
+ entity_data (EntityData): The EntityData object to insert.
81
+ """
82
+ self.entities[name] = entity_data
83
+
84
+ def remove_entity(self, name: str) -> bool:
85
+ """
86
+ Removes an EntityData object by its name.
87
+
88
+ Args:
89
+ name (str): The name of the entity to remove.
90
+
91
+ Returns:
92
+ bool: True if the entity was removed, False otherwise.
93
+ """
94
+ if name in self.entities:
95
+ del self.entities[name]
96
+ return True
97
+ return False
@@ -0,0 +1,20 @@
1
+ from typing import Any, Dict, List, Optional
2
+
3
+
4
+ class ResourceDefinition:
5
+ """
6
+ A class to represent a Resource Definition for FHIR initialization.
7
+ """
8
+ def __init__(self, entity_data: Dict[str, Any]):
9
+ """
10
+ Initializes the ResourceLink object from a dictionary.
11
+
12
+ Args:
13
+ data: A dictionary containing 'Entity name', 'ResourceType', and 'Profile(s)'.
14
+ """
15
+ self.entity_name = entity_data.get('Entity Name')
16
+ self.resource_type = entity_data.get('ResourceType')
17
+ self.profiles = entity_data.get('Profile(s)')
18
+
19
+ def __repr__(self) -> str:
20
+ return f"FhirEntity(entity_name='{self.entity_name}', resource_type='{self.resource_type}', profiles={self.profiles})"
@@ -0,0 +1,22 @@
1
+ from typing import Any, Dict
2
+
3
+
4
+ class ResourceLink:
5
+ """
6
+ A class to represent a Fhir Reference between two resources.
7
+ """
8
+ def __init__(self, data: Dict[str, Any]):
9
+ """
10
+ Initializes the ResourceLink object from a dictionary.
11
+
12
+ Args:
13
+ data: A dictionary containing 'OriginResource', 'ReferencePath', and 'DestinationResource'.
14
+ """
15
+ self.origin_resource = data.get('OriginResource')
16
+ self.reference_path = data.get('ReferencePath')
17
+ self.destination_resource = data.get('DestinationResource')
18
+
19
+ def __repr__(self) -> str:
20
+ return (f"ResourceLink(origin_resource='{self.origin_resource}', "
21
+ f"reference_path='{self.reference_path}', "
22
+ f"destination_resource='{self.destination_resource}')")
@@ -1,5 +1,10 @@
1
1
  import openpyxl
2
2
 
3
+ from .model.cohort_data_entity import CohortData, EntityData, FieldEntry
4
+
5
+ from .model.resource_definition_entity import ResourceDefinition
6
+ from .model.resource_link_entity import ResourceLink
7
+
3
8
  # Function to read the xlsx file and access specific sheets
4
9
  def read_xlsx_and_process(file_path):
5
10
  # Load the workbook
@@ -16,19 +21,15 @@ def read_xlsx_and_process(file_path):
16
21
 
17
22
  if 'PatientData' in workbook.sheetnames:
18
23
  sheet = workbook['PatientData']
19
- patient_data_entities, num_entries = process_sheet_patient_data(sheet, resource_definition_entities)
24
+ cohort_data = process_sheet_patient_data(sheet, resource_definition_entities)
20
25
 
21
- return {
22
- "resource_definition_entities": resource_definition_entities,
23
- "resource_link_entities": resource_link_entities,
24
- "patient_data_entities": patient_data_entities,
25
- "num_entries": num_entries
26
- }
26
+ return resource_definition_entities, resource_link_entities, cohort_data
27
27
 
28
28
 
29
29
  # Function to process the specific sheet with 'Entity Name', 'ResourceType', and 'Profile(s)'
30
30
  def process_sheet_resource_definitions(sheet):
31
31
  resource_definitions = []
32
+ resource_definition_entities = []
32
33
  headers = [cell.value for cell in next(sheet.iter_rows(min_row=1, max_row=1))] # Get headers
33
34
 
34
35
  for row in sheet.iter_rows(min_row=3, values_only=True):
@@ -38,27 +39,30 @@ def process_sheet_resource_definitions(sheet):
38
39
  # Split 'Profile(s)' column into a list of URLs
39
40
  if row_data.get("Profile(s)"):
40
41
  row_data["Profile(s)"] = [url.strip() for url in row_data["Profile(s)"].split(",")]
41
-
42
+ resource_definition_entities.append(ResourceDefinition(row_data))
42
43
  resource_definitions.append(row_data)
43
44
 
44
- return resource_definitions
45
+ return resource_definition_entities
45
46
 
46
47
  # Function to process the specific sheet with 'OriginResource', 'ReferencePath', and 'DestinationResource'
47
48
  def process_sheet_resource_links(sheet):
48
49
  resource_links = []
50
+ resource_link_entities = []
49
51
  headers = [cell.value for cell in next(sheet.iter_rows(min_row=1, max_row=1))] # Get headers
50
52
  for row in sheet.iter_rows(min_row=3, values_only=True):
51
53
  row_data = dict(zip(headers, row)) # Create a dictionary for each row
52
54
  if all(cell is None or cell == "" for cell in row_data):
53
55
  continue
54
56
  resource_links.append(row_data)
57
+ resource_link_entities.append(ResourceLink(row_data))
55
58
 
56
- return resource_links
59
+ return resource_link_entities
57
60
 
58
61
  # Function to process the "PatientData" sheet
59
62
  def process_sheet_patient_data(sheet, resource_definition_entities):
60
63
  # Initialize the dictionary to store the processed data
61
64
  patient_data = {}
65
+ cohort_data = CohortData()
62
66
  # Extract the data from the first 6 rows (Entity To Query, JsonPath, etc.)
63
67
  for col in sheet.iter_cols(min_row=1, max_row=6, min_col=3, values_only=True): # Start from 3rd column
64
68
  if all(entry is None for entry in col):
@@ -68,20 +72,23 @@ def process_sheet_patient_data(sheet, resource_definition_entities):
68
72
  if (entity_name is None or entity_name == "") and (field_name is not None and field_name != ""):
69
73
  print(f"WARNING: - Reading Patient Data Issue - {field_name} - 'Entity To Query' cell missing for column labelled '{field_name}', please provide entity name from the ResourceDefinitions tab.")
70
74
 
71
- if entity_name not in [entry['Entity Name'] for entry in resource_definition_entities]:
75
+ if entity_name not in [entry.entity_name for entry in resource_definition_entities]:
72
76
  print(f"WARNING: - Reading Patient Data Issue - {field_name} - 'Entity To Query' cell has entity named '{entity_name}', however, the ResourceDefinition tab has no matching resource. Please provide a corresponding entry in the ResourceDefinition tab.")
73
77
  # Create structure for this entity if not already present
74
78
  if entity_name not in patient_data:
75
79
  patient_data[entity_name] = {}
80
+ cohort_data.insert_entity(entity_name, EntityData({}))
76
81
 
77
82
  # Add jsonpath, valuesets, and initialize an empty list for 'values'
78
83
  if field_name not in patient_data[entity_name]:
79
- patient_data[entity_name][field_name] = {
84
+ field_data = {
80
85
  "jsonpath": col[1], # JsonPath from the second row
81
86
  "valueType": col[2], # Value Type from the third row
82
87
  "valuesets": col[3], # Value Set from the fourth row
83
88
  "values": [] # Initialize empty list for actual values
84
89
  }
90
+ patient_data[entity_name][field_name] = field_data
91
+ cohort_data.entities[entity_name].insert(field_name, FieldEntry(field_data))
85
92
 
86
93
  # Now process the rows starting from the 6th row (the actual data entries)
87
94
  num_entries = 0
@@ -95,5 +102,6 @@ def process_sheet_patient_data(sheet, resource_definition_entities):
95
102
  field_name = sheet.cell(row=6, column=i + 2).value # Get the Data Element for this column
96
103
  if entity_name in patient_data and field_name in patient_data[entity_name]:
97
104
  # Append the actual data values to the 'values' array
98
- patient_data[entity_name][field_name]["values"].append(value)
99
- return patient_data, num_entries
105
+ cohort_data.entities[entity_name].fields[field_name].values.append(value)
106
+ cohort_data.num_entries = num_entries
107
+ return cohort_data
File without changes