-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: don't load all of an i2b2 file into memory
The primary change in this commit is to stop loading i2b2 input files all at once, but rather stream them in, in chunks determined by the --batch-size parameter. But this commit also includes several small fixes: - Fixes location of MS tool during CI - Adds comma-formatting to a lot of progress-count prints - Continues ETL even if cTAKES can't process one message (just logs the error instead) - Changes default batch size from 10M to 200k. This works more reliably for small-memory (8G) machines. The previous number was optimized for the size of the resulting parquet files. This number is optimized for memory during the run, which feels like a safer default. - When using --input-format=ndjson and pointing at a local folder, we now still use a temporary folder and copy in just the resource ndjson files we want. This is to speed up the MS deid tool, so it doesn't have to read all possible ndjson inputs. - Add better progress messaging while reading i2b2 files. - Separate out race & ethnicity from i2b2, which combines them
- Loading branch information
Showing
17 changed files
with
170 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# This file contains a mapping of various external coding systems to the concepts they represent | ||
|
||
|
||
# PHIN VADS 1000-9, Race & Ethnicity - CDC | ||
# https://phinvads.cdc.gov/vads/ViewCodeSystemConcept.action?oid=2.16.840.1.113883.6.238&code=1000-9 | ||
# https://hl7.org/fhir/us/core/StructureDefinition-us-core-race.html | ||
CDC_RACE = { | ||
'White': ('urn:oid:2.16.840.1.113883.6.238', '2106-3'), | ||
'Black or African American': ('urn:oid:2.16.840.1.113883.6.238', '2054-5'), | ||
'American Indian or Alaska Native': ('urn:oid:2.16.840.1.113883.6.238', '1002-5'), | ||
'Asian': ('urn:oid:2.16.840.1.113883.6.238', '2028-9'), | ||
'Native Hawaiian or Other Pacific Islander': ('urn:oid:2.16.840.1.113883.6.238', '2076-8'), | ||
'Other': ('urn:oid:2.16.840.1.113883.6.238', '2131-1'), | ||
'Declined to Answer': ('http://terminology.hl7.org/CodeSystem/v3-NullFlavor', 'ASKU'), | ||
'Unable to Answer': ('http://terminology.hl7.org/CodeSystem/v3-NullFlavor', 'ASKU'), | ||
'Unknown': ('http://terminology.hl7.org/CodeSystem/v3-NullFlavor', 'UNK'), | ||
} | ||
|
||
# https://hl7.org/fhir/us/core/StructureDefinition-us-core-ethnicity.html | ||
CDC_ETHNICITY = { | ||
'Hispanic or Latino': ('urn:oid:2.16.840.1.113883.6.238', '2135-2'), | ||
'Not Hispanic or Latino': ('urn:oid:2.16.840.1.113883.6.238', '2186-5'), | ||
'Declined to Answer': ('http://terminology.hl7.org/CodeSystem/v3-NullFlavor', 'ASKU'), | ||
'Unable to Answer': ('http://terminology.hl7.org/CodeSystem/v3-NullFlavor', 'ASKU'), | ||
'Unknown': ('http://terminology.hl7.org/CodeSystem/v3-NullFlavor', 'UNK'), | ||
} | ||
|
||
# FHIR AdministrativeGender code (not a full gender spectrum, but quite limited) | ||
# https://www.hl7.org/fhir/valueset-administrative-gender.html | ||
# Anything not in this dictionary maps should map to 'other' | ||
FHIR_GENDER = { | ||
'F': 'female', | ||
'M': 'male', | ||
'U': 'unknown', | ||
} | ||
|
||
|
||
# BCH internal lab codes mapping to international covid-19 codes | ||
# system: http://loinc.org | ||
LOINC_COVID_LAB_TESTS = { | ||
'LAB:1043473617': '94500-6', | ||
'LAB:1044804335': '94500-6', | ||
'LAB:1044704735': '94500-6', | ||
'LAB:1134792565': '95406-5', | ||
'LAB:1148157467': '95406-5', | ||
'LAB:467288722': '85477-8', | ||
'LAB:152831642': '85476-0', | ||
'LAB:467288694': '85478-6', | ||
'LAB:467288700': '85479-4', | ||
'LAB:13815125': '62462-7' | ||
} | ||
|
||
|
||
# PHIN VADS General adjectival modifier (qualifier value) {106234000 , SNOMED-CT } | ||
# Subset of codes related to evaluating lab results | ||
# system: http://snomed.info/sct | ||
SNOMED_LAB_RESULT = { | ||
'Positive': '10828004', | ||
'Negative': '260385009', | ||
'Absent': '272519000' | ||
} | ||
|
||
|
||
# PHIN VADS Admission statuses {308277006, SNOMED-CT } | ||
# Subset of codes related to means of admission | ||
# system: http://snomed.info/sct | ||
# https://terminology.hl7.org/5.0.0/ValueSet-v3-ActEncounterCode.html | ||
# Other terms seen: | ||
# - "Recurring Outpatient Series" (AMB?) | ||
# - "Day Surgery" (AMB?) | ||
SNOMED_ADMISSION = { | ||
'Emergency': 'EMER', | ||
'Inpatient': 'IMP', | ||
'Outpatient': 'AMB', | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,58 @@ | ||
"""Read files into data structures""" | ||
|
||
from typing import List | ||
import logging | ||
from typing import Iterator | ||
|
||
import pandas | ||
from cumulus import common | ||
|
||
from cumulus.loaders.i2b2.schema import ObservationFact, PatientDimension, VisitDimension | ||
|
||
|
||
def extract_csv(path_csv: str, sample=1.0) -> pandas.DataFrame: | ||
def extract_csv(path_csv: str, batch_size: int) -> Iterator[dict]: | ||
""" | ||
:param path_csv: /path/to/i2b2_formatted_file.csv | ||
:param sample: %percentage of file to read | ||
:return: pandas Dataframe | ||
:param batch_size: how many entries to load into memory at once | ||
:return: an iterator over each row from the file | ||
""" | ||
return common.extract_csv(path_csv, sample) | ||
print(f'Reading csv {path_csv}...') | ||
count = 0 | ||
with pandas.read_csv(path_csv, dtype=str, na_filter=False, chunksize=batch_size) as reader: | ||
for chunk in reader: | ||
print(f' Read {count:,} entries...') | ||
for _, row in chunk.iterrows(): | ||
yield dict(row) | ||
count += batch_size | ||
print(f'Done reading {path_csv} .') | ||
|
||
|
||
def extract_csv_observation_facts(path_csv: str, | ||
sample=1.0) -> List[ObservationFact]: | ||
def extract_csv_observation_facts(path_csv: str, batch_size: int) -> Iterator[ObservationFact]: | ||
""" | ||
:param path_csv: /path/to/file.csv | ||
:param sample: %percentage of file to read | ||
:param batch_size: how many entries to load into memory at once | ||
:return: i2b2 ObservationFact table | ||
""" | ||
df = extract_csv(path_csv, sample) | ||
|
||
logging.info('Transforming text into List[ObservationFact]') | ||
facts = [] | ||
for _, row in df.iterrows(): | ||
facts.append(ObservationFact(row)) | ||
|
||
logging.info('Ready List[ObservationFact]') | ||
return facts | ||
for row in extract_csv(path_csv, batch_size): | ||
yield ObservationFact(row) | ||
|
||
|
||
def extract_csv_patients(path_csv: str, sample=1.0) -> List[PatientDimension]: | ||
def extract_csv_patients(path_csv: str, batch_size: int) -> Iterator[PatientDimension]: | ||
""" | ||
:param path_csv: /path/to/file.csv | ||
:param sample: %percentage of file to read | ||
:param batch_size: how many entries to load into memory at once | ||
:return: List i2b2 patient dimension table | ||
""" | ||
df = extract_csv(path_csv, sample) | ||
|
||
logging.info('Transforming text into List[PatientDimension]') | ||
patients = [] | ||
for _, row in df.iterrows(): | ||
patients.append(PatientDimension(row)) | ||
|
||
logging.info('Ready List[PatientDimension]') | ||
return patients | ||
for row in extract_csv(path_csv, batch_size): | ||
yield PatientDimension(row) | ||
|
||
|
||
def extract_csv_visits(path_csv: str, sample=1.0) -> List[VisitDimension]: | ||
def extract_csv_visits(path_csv: str, batch_size: int) -> Iterator[VisitDimension]: | ||
""" | ||
:param path_csv: /path/to/file.csv | ||
:param sample: %percentage of file to read | ||
:param batch_size: how many entries to load into memory at once | ||
:return: List i2b2 visit dimension table | ||
""" | ||
df = extract_csv(path_csv, sample) | ||
|
||
logging.info('Transforming text into List[VisitDimension]') | ||
visits = [] | ||
for _, row in df.iterrows(): | ||
visits.append(VisitDimension(row)) | ||
|
||
logging.info('Ready List[VisitDimension]') | ||
return visits | ||
for row in extract_csv(path_csv, batch_size): | ||
yield VisitDimension(row) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.