cehrbert-data 0.0.7__tar.gz → 0.0.8__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.
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/PKG-INFO +1 -1
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/apps/generate_included_concept_list.py +23 -17
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/apps/generate_training_data.py +70 -74
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/spark_app_base.py +35 -17
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/const/common.py +2 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/clinical_event_decorator.py +11 -4
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/tools/extract_features.py +30 -18
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/utils/spark_parse_args.py +6 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/utils/spark_utils.py +285 -785
- cehrbert_data-0.0.8/src/cehrbert_data/utils/vocab_utils.py +361 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data.egg-info/PKG-INFO +1 -1
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data.egg-info/SOURCES.txt +1 -4
- cehrbert_data-0.0.7/src/cehrbert_data/apps/generate_concept_similarity_table.py +0 -423
- cehrbert_data-0.0.7/src/cehrbert_data/apps/generate_hierarchical_bert_training_data.py +0 -238
- cehrbert_data-0.0.7/src/cehrbert_data/apps/generate_information_content.py +0 -131
- cehrbert_data-0.0.7/src/cehrbert_data/apps/generate_required_labs.py +0 -140
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/.github/workflows/python-build.yml +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/.github/workflows/tests.yml +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/.gitignore +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/.pre-commit-config.yaml +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/LICENSE +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/README.md +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/pyproject.toml +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/.part-00000-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/.part-00003-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/.part-00010-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/part-00000-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/part-00003-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept/part-00010-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/.part-00000-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/.part-00002-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/.part-00006-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/.part-00011-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/.part-00013-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/part-00000-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/part-00002-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/part-00006-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/part-00011-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_ancestor/part-00013-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/.part-00000-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/.part-00002-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/.part-00007-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/.part-00012-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/part-00000-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/part-00002-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/part-00007-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/concept_relationship/part-00012-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/condition_occurrence/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/condition_occurrence/.part-00000-4eff03a1-cdcf-4c89-b0cd-9ce590b9b1eb-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/condition_occurrence/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/condition_occurrence/part-00000-4eff03a1-cdcf-4c89-b0cd-9ce590b9b1eb-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/drug_exposure/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/drug_exposure/.part-00000-10bbf1a4-a7da-416e-9703-58609c7edfad-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/drug_exposure/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/drug_exposure/part-00000-10bbf1a4-a7da-416e-9703-58609c7edfad-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/observation_period/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/observation_period/.part-00000-694316e5-cc95-49f1-9fad-5a7f377e2602-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/observation_period/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/observation_period/part-00000-694316e5-cc95-49f1-9fad-5a7f377e2602-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/person/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/person/.part-00000-7d789011-f361-48da-af6f-cfe102978b3a-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/person/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/person/part-00000-7d789011-f361-48da-af6f-cfe102978b3a-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/procedure_occurrence/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/procedure_occurrence/.part-00000-e73003c1-aed5-41c0-b2d4-eaccaccf044a-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/procedure_occurrence/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/procedure_occurrence/part-00000-e73003c1-aed5-41c0-b2d4-eaccaccf044a-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/visit_occurrence/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/visit_occurrence/.part-00000-e874b5f1-bf9e-4cb9-93bf-c309a47b0476-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/visit_occurrence/_SUCCESS +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/sample_data/omop_sample/visit_occurrence/part-00000-e874b5f1-bf9e-4cb9-93bf-c309a47b0476-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/setup.cfg +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/apps/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/atrial_fibrillation.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/cabg.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/coronary_artery_disease.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/covid.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/covid_inpatient.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/death.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/heart_failure.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/ischemic_stroke.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/last_visit_discharged_home.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/query_builder.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/type_two_diabietes.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/cohorts/ventilation.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/config/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/config/output_names.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/const/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/const/__pycache__/__init__.cpython-311.pyc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/const/__pycache__/common.cpython-311.pyc +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/const/artificial_tokens.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/artificial_time_token_decorator.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/death_event_decorator.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/demographic_event_decorator.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/patient_event_decorator_base.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/prediction_token_decorator.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/token_priority.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/afib_ischemic_stroke.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/cad_cabg_cohort.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/cad_hf_cohort.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/copd_readmission.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/covid_death.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/covid_ventilation.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/discharge_home_death.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/hf_readmission.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/hospitalization.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/hospitalization_mortality.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/prediction_cohorts/t2dm_hf_cohort.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/queries/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/queries/measurement_queries.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/tools/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/tools/connect_omop_visit.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/tools/download_omop_tables.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/tools/ehrshot_to_omop.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/tools/prepare_ehrshot_cohorts.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/tools/update_omop_visit.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/utils/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/utils/logging_utils.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data.egg-info/dependency_links.txt +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data.egg-info/requires.txt +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data.egg-info/top_level.txt +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/integration_tests/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/integration_tests/test_generate_training_data.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/integration_tests/test_hf_readmission.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/integration_tests/test_hf_readmission_cohort_meds.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/pyspark_test_base.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/unit_tests/__init__.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/unit_tests/test_ehrshot_to_omop.py +0 -0
- {cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/tests/unit_tests/test_spark_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cehrbert_data
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: The Spark ETL tools for generating the CEHR-BERT and CEHR-GPT pre-training and finetuning data
|
|
5
5
|
Author-email: Chao Pang <chaopang229@gmail.com>, Xinzhuo Jiang <xj2193@cumc.columbia.edu>, Krishna Kalluri <kk3326@cumc.columbia.edu>, Nishanth Parameshwar Pavinkurve <np2689@cumc.columbia.edu>, Karthik Natarajan <kn2174@cumc.columbia.edu>
|
|
6
6
|
License: MIT License
|
{cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/apps/generate_included_concept_list.py
RENAMED
|
@@ -24,8 +24,8 @@ from pyspark.sql import SparkSession
|
|
|
24
24
|
from pyspark.sql import functions as F
|
|
25
25
|
|
|
26
26
|
from cehrbert_data.config.output_names import QUALIFIED_CONCEPT_LIST_PATH
|
|
27
|
-
from cehrbert_data.const.common import
|
|
28
|
-
from cehrbert_data.utils.spark_utils import
|
|
27
|
+
from cehrbert_data.const.common import CONCEPT
|
|
28
|
+
from cehrbert_data.utils.spark_utils import extract_events_by_domain, preprocess_domain_table
|
|
29
29
|
|
|
30
30
|
DOMAIN_TABLE_LIST = ["condition_occurrence", "procedure_occurrence", "drug_exposure"]
|
|
31
31
|
|
|
@@ -55,32 +55,38 @@ def main(
|
|
|
55
55
|
"""
|
|
56
56
|
spark = SparkSession.builder.appName("Generate concept list").getOrCreate()
|
|
57
57
|
|
|
58
|
-
domain_tables = []
|
|
59
58
|
# Exclude measurement from domain_table_list if exists because we need to process measurement
|
|
60
59
|
# in a different way
|
|
61
60
|
domain_table_list = ehr_table_list if ehr_table_list else DOMAIN_TABLE_LIST
|
|
61
|
+
concept = preprocess_domain_table(spark, input_folder, CONCEPT)
|
|
62
|
+
patient_ehr_events = None
|
|
62
63
|
for domain_table_name in domain_table_list:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
domain_table = preprocess_domain_table(
|
|
65
|
+
spark=spark,
|
|
66
|
+
input_folder=input_folder,
|
|
67
|
+
domain_table_name=domain_table_name,
|
|
68
|
+
with_drug_rollup=with_drug_rollup
|
|
69
|
+
)
|
|
70
|
+
ehr_events = extract_events_by_domain(
|
|
71
|
+
domain_table,
|
|
72
|
+
spark=spark,
|
|
73
|
+
concept=concept,
|
|
74
|
+
aggregate_by_hour=False,
|
|
75
|
+
refresh=False,
|
|
76
|
+
persistence_folder=input_folder
|
|
77
|
+
)
|
|
78
|
+
if patient_ehr_events is None:
|
|
79
|
+
patient_ehr_events = ehr_events
|
|
80
|
+
else:
|
|
81
|
+
patient_ehr_events = patient_ehr_events.unionByName(ehr_events)
|
|
75
82
|
|
|
76
83
|
# Filter out concepts that are linked to less than 100 patients
|
|
77
84
|
qualified_concepts = (
|
|
78
|
-
|
|
85
|
+
patient_ehr_events.where("visit_occurrence_id IS NOT NULL")
|
|
79
86
|
.groupBy("standard_concept_id")
|
|
80
87
|
.agg(F.countDistinct("person_id").alias("freq"))
|
|
81
88
|
.where(F.col("freq") >= min_num_of_patients)
|
|
82
89
|
)
|
|
83
|
-
|
|
84
90
|
qualified_concepts.write.mode("overwrite").parquet(os.path.join(output_folder, QUALIFIED_CONCEPT_LIST_PATH))
|
|
85
91
|
|
|
86
92
|
|
{cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/apps/generate_training_data.py
RENAMED
|
@@ -12,15 +12,14 @@ from cehrbert_data.const.common import (
|
|
|
12
12
|
PERSON,
|
|
13
13
|
VISIT_OCCURRENCE,
|
|
14
14
|
DEATH,
|
|
15
|
-
|
|
15
|
+
CONCEPT
|
|
16
16
|
)
|
|
17
17
|
from cehrbert_data.decorators import AttType
|
|
18
18
|
from cehrbert_data.utils.spark_utils import (
|
|
19
19
|
create_sequence_data,
|
|
20
20
|
create_sequence_data_with_att,
|
|
21
|
-
join_domain_tables,
|
|
22
21
|
preprocess_domain_table,
|
|
23
|
-
|
|
22
|
+
extract_events_by_domain,
|
|
24
23
|
validate_table_names,
|
|
25
24
|
construct_artificial_visits
|
|
26
25
|
)
|
|
@@ -43,7 +42,6 @@ def main(
|
|
|
43
42
|
include_death: bool,
|
|
44
43
|
att_type: AttType,
|
|
45
44
|
inpatient_att_type: AttType,
|
|
46
|
-
include_sequence_information_content: bool = False,
|
|
47
45
|
exclude_demographic: bool = False,
|
|
48
46
|
use_age_group: bool = False,
|
|
49
47
|
with_drug_rollup: bool = True,
|
|
@@ -52,6 +50,7 @@ def main(
|
|
|
52
50
|
refresh_measurement: bool = False,
|
|
53
51
|
aggregate_by_hour: bool = True,
|
|
54
52
|
should_construct_artificial_visits: bool = False,
|
|
53
|
+
duplicate_records: bool = False
|
|
55
54
|
):
|
|
56
55
|
spark = SparkSession.builder.appName("Generate CEHR-BERT Training Data").getOrCreate()
|
|
57
56
|
|
|
@@ -77,19 +76,30 @@ def main(
|
|
|
77
76
|
f"refresh_measurement: {refresh_measurement}\n"
|
|
78
77
|
f"aggregate_by_hour: {aggregate_by_hour}\n"
|
|
79
78
|
f"should_construct_artificial_visits: {should_construct_artificial_visits}\n"
|
|
79
|
+
f"duplicate_records: {duplicate_records}\n"
|
|
80
80
|
)
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
concept = preprocess_domain_table(spark, input_folder, CONCEPT)
|
|
83
|
+
patient_ehr_events = None
|
|
83
84
|
for domain_table_name in domain_table_list:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
domain_table = preprocess_domain_table(
|
|
86
|
+
spark=spark,
|
|
87
|
+
input_folder=input_folder,
|
|
88
|
+
domain_table_name=domain_table_name,
|
|
89
|
+
with_drug_rollup=with_drug_rollup
|
|
90
|
+
)
|
|
91
|
+
ehr_events = extract_events_by_domain(
|
|
92
|
+
domain_table,
|
|
93
|
+
spark=spark,
|
|
94
|
+
concept=concept,
|
|
95
|
+
aggregate_by_hour=aggregate_by_hour,
|
|
96
|
+
refresh=refresh_measurement,
|
|
97
|
+
persistence_folder=input_folder
|
|
98
|
+
)
|
|
99
|
+
if patient_ehr_events is None:
|
|
100
|
+
patient_ehr_events = ehr_events
|
|
101
|
+
else:
|
|
102
|
+
patient_ehr_events = patient_ehr_events.unionByName(ehr_events)
|
|
93
103
|
|
|
94
104
|
visit_occurrence = preprocess_domain_table(spark, input_folder, VISIT_OCCURRENCE)
|
|
95
105
|
visit_occurrence = visit_occurrence.select(
|
|
@@ -119,35 +129,17 @@ def main(
|
|
|
119
129
|
|
|
120
130
|
death = preprocess_domain_table(spark, input_folder, DEATH) if include_death else None
|
|
121
131
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if include_concept_list and patient_events:
|
|
125
|
-
column_names = patient_events.schema.fieldNames()
|
|
132
|
+
if include_concept_list and patient_ehr_events:
|
|
126
133
|
# Filter out concepts
|
|
127
|
-
qualified_concepts = preprocess_domain_table(spark, input_folder, "qualified_concept_list")
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
patient_events = patient_events.join(qualified_concepts, "standard_concept_id").select(column_names)
|
|
132
|
-
|
|
133
|
-
# Process the measurement table if exists
|
|
134
|
-
if MEASUREMENT in domain_table_list:
|
|
135
|
-
processed_measurement = get_measurement_table(
|
|
136
|
-
spark,
|
|
137
|
-
input_folder,
|
|
138
|
-
refresh=refresh_measurement,
|
|
139
|
-
aggregate_by_hour=aggregate_by_hour,
|
|
134
|
+
qualified_concepts = preprocess_domain_table(spark, input_folder, "qualified_concept_list")
|
|
135
|
+
patient_ehr_events = patient_ehr_events.join(
|
|
136
|
+
qualified_concepts.select("standard_concept_id"), "standard_concept_id"
|
|
140
137
|
)
|
|
141
|
-
if patient_events:
|
|
142
|
-
# Union all measurement records together with other domain records
|
|
143
|
-
patient_events = patient_events.unionByName(processed_measurement)
|
|
144
|
-
else:
|
|
145
|
-
patient_events = processed_measurement
|
|
146
138
|
|
|
147
|
-
|
|
148
|
-
|
|
139
|
+
patient_ehr_events = (
|
|
140
|
+
patient_ehr_events.join(visit_occurrence_person, "visit_occurrence_id")
|
|
149
141
|
.select(
|
|
150
|
-
[
|
|
142
|
+
[patient_ehr_events[fieldName] for fieldName in patient_ehr_events.schema.fieldNames()]
|
|
151
143
|
+ ["visit_concept_id", "age"]
|
|
152
144
|
)
|
|
153
145
|
.withColumn("cohort_member_id", F.col("person_id"))
|
|
@@ -156,25 +148,35 @@ def main(
|
|
|
156
148
|
# Apply the age security measure
|
|
157
149
|
# We only keep the patient records, whose corresponding age is less than 90
|
|
158
150
|
if apply_age_filter:
|
|
159
|
-
|
|
151
|
+
patient_ehr_events = patient_ehr_events.where(F.col("age") < 90)
|
|
160
152
|
|
|
161
153
|
if not continue_from_events:
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
patient_events = spark.read.parquet(os.path.join(output_folder, "all_patient_events"))
|
|
154
|
+
patient_ehr_events.write.mode("overwrite").parquet(os.path.join(output_folder, "all_patient_events"))
|
|
165
155
|
|
|
156
|
+
patient_ehr_events = spark.read.parquet(os.path.join(output_folder, "all_patient_events"))
|
|
166
157
|
if should_construct_artificial_visits:
|
|
167
158
|
# Construct artificial visits or re-link the visits for the problem list events
|
|
168
|
-
|
|
169
|
-
|
|
159
|
+
patient_ehr_events, visit_occurrence_person = construct_artificial_visits(
|
|
160
|
+
patient_ehr_events,
|
|
170
161
|
visit_occurrence_person,
|
|
171
162
|
spark=spark,
|
|
172
163
|
persistence_folder=output_folder,
|
|
164
|
+
duplicate_records=duplicate_records
|
|
173
165
|
)
|
|
166
|
+
# Update age if some of the ehr_records have been re-associated with the new visits
|
|
167
|
+
patient_ehr_events = patient_ehr_events.join(
|
|
168
|
+
person.select("person_id", "birth_datetime"),
|
|
169
|
+
"person_id",
|
|
170
|
+
).join(
|
|
171
|
+
visit_occurrence_person.select("visit_occurrence_id", "visit_start_date"), "visit_occurrence_id"
|
|
172
|
+
).withColumn(
|
|
173
|
+
"age",
|
|
174
|
+
F.ceil(F.months_between(F.col("visit_start_date"), F.col("birth_datetime")) / F.lit(12))
|
|
175
|
+
).drop("visit_start_date", "birth_datetime")
|
|
174
176
|
|
|
175
177
|
if is_new_patient_representation:
|
|
176
|
-
|
|
177
|
-
|
|
178
|
+
patient_sequence_data = create_sequence_data_with_att(
|
|
179
|
+
patient_ehr_events,
|
|
178
180
|
visit_occurrence_person,
|
|
179
181
|
date_filter=date_filter,
|
|
180
182
|
include_visit_type=include_visit_type,
|
|
@@ -190,8 +192,8 @@ def main(
|
|
|
190
192
|
persistence_folder=output_folder,
|
|
191
193
|
)
|
|
192
194
|
else:
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
patient_sequence_data = create_sequence_data(
|
|
196
|
+
patient_ehr_events,
|
|
195
197
|
date_filter=date_filter,
|
|
196
198
|
include_visit_type=include_visit_type,
|
|
197
199
|
classic_bert_seq=is_classic_bert,
|
|
@@ -215,47 +217,33 @@ def main(
|
|
|
215
217
|
)
|
|
216
218
|
.distinct()
|
|
217
219
|
)
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if include_sequence_information_content:
|
|
221
|
-
concept_df = patient_events.select("person_id", F.col("standard_concept_id").alias("concept_id"))
|
|
222
|
-
concept_freq = (
|
|
223
|
-
concept_df.groupBy("concept_id")
|
|
224
|
-
.count()
|
|
225
|
-
.withColumn("prob", F.col("count") / F.sum("count").over(Window.partitionBy()))
|
|
226
|
-
.withColumn("ic", -F.log("prob"))
|
|
227
|
-
)
|
|
228
|
-
|
|
229
|
-
patient_ic_df = concept_df.join(concept_freq, "concept_id").groupby("person_id").agg(F.mean("ic").alias("ic"))
|
|
230
|
-
|
|
231
|
-
sequence_data = sequence_data.join(patient_ic_df, "person_id")
|
|
220
|
+
patient_sequence_data = patient_sequence_data.join(visit_occurrence, "person_id")
|
|
232
221
|
|
|
233
222
|
patient_splits_folder = os.path.join(input_folder, "patient_splits")
|
|
234
223
|
if os.path.exists(patient_splits_folder):
|
|
235
224
|
patient_splits = spark.read.parquet(patient_splits_folder)
|
|
236
225
|
temp_folder = os.path.join(output_folder, "patient_sequence", "temp")
|
|
237
|
-
|
|
226
|
+
patient_sequence_data.join(
|
|
238
227
|
patient_splits.select("person_id", "split"),
|
|
239
228
|
"person_id"
|
|
240
229
|
).write.mode("overwrite").parquet(
|
|
241
230
|
temp_folder
|
|
242
231
|
)
|
|
243
|
-
|
|
244
|
-
|
|
232
|
+
patient_sequence_data = spark.read.parquet(temp_folder)
|
|
233
|
+
patient_sequence_data.where('split="train"').write.mode("overwrite").parquet(
|
|
245
234
|
os.path.join(output_folder, "patient_sequence/train")
|
|
246
235
|
)
|
|
247
|
-
|
|
236
|
+
patient_sequence_data.where('split="test"').write.mode("overwrite").parquet(
|
|
248
237
|
os.path.join(output_folder, "patient_sequence/test")
|
|
249
238
|
)
|
|
250
239
|
shutil.rmtree(temp_folder)
|
|
251
240
|
else:
|
|
252
|
-
|
|
241
|
+
patient_sequence_data.write.mode("overwrite").parquet(os.path.join(output_folder, "patient_sequence"))
|
|
253
242
|
|
|
254
243
|
|
|
255
|
-
|
|
256
|
-
parser = argparse.ArgumentParser(description="Arguments for generate training data for Bert")
|
|
244
|
+
def create_argparser():
|
|
245
|
+
parser = argparse.ArgumentParser(description="Arguments for generate training data for CEHR-Bert/GPT")
|
|
257
246
|
parser.add_argument(
|
|
258
|
-
"-i",
|
|
259
247
|
"--input_folder",
|
|
260
248
|
dest="input_folder",
|
|
261
249
|
action="store",
|
|
@@ -263,7 +251,6 @@ if __name__ == "__main__":
|
|
|
263
251
|
required=True,
|
|
264
252
|
)
|
|
265
253
|
parser.add_argument(
|
|
266
|
-
"-o",
|
|
267
254
|
"--output_folder",
|
|
268
255
|
dest="output_folder",
|
|
269
256
|
action="store",
|
|
@@ -271,7 +258,6 @@ if __name__ == "__main__":
|
|
|
271
258
|
required=True,
|
|
272
259
|
)
|
|
273
260
|
parser.add_argument(
|
|
274
|
-
"-tc",
|
|
275
261
|
"--domain_table_list",
|
|
276
262
|
dest="domain_table_list",
|
|
277
263
|
nargs="+",
|
|
@@ -369,8 +355,17 @@ if __name__ == "__main__":
|
|
|
369
355
|
help="Indicate whether we should construct artificial visits for "
|
|
370
356
|
"the problem list records that could occur years ahead",
|
|
371
357
|
)
|
|
358
|
+
parser.add_argument(
|
|
359
|
+
"--duplicate_records",
|
|
360
|
+
dest="duplicate_records",
|
|
361
|
+
action="store_true",
|
|
362
|
+
help="Indicate whether we want to duplicate the problem list records when constructing artificial visits"
|
|
363
|
+
)
|
|
364
|
+
return parser
|
|
365
|
+
|
|
372
366
|
|
|
373
|
-
|
|
367
|
+
if __name__ == "__main__":
|
|
368
|
+
ARGS = create_argparser().parse_args()
|
|
374
369
|
|
|
375
370
|
# Enable logging
|
|
376
371
|
add_console_logging()
|
|
@@ -399,4 +394,5 @@ if __name__ == "__main__":
|
|
|
399
394
|
refresh_measurement=ARGS.refresh_measurement,
|
|
400
395
|
aggregate_by_hour=ARGS.aggregate_by_hour,
|
|
401
396
|
should_construct_artificial_visits=ARGS.should_construct_artificial_visits,
|
|
397
|
+
duplicate_records=ARGS.duplicate_records
|
|
402
398
|
)
|
|
@@ -13,16 +13,17 @@ from pyspark.sql.window import Window
|
|
|
13
13
|
from cehrbert_data.decorators import AttType
|
|
14
14
|
from cehrbert_data.const.common import VISIT_OCCURRENCE
|
|
15
15
|
from cehrbert_data.utils.spark_utils import (
|
|
16
|
-
build_ancestry_table_for,
|
|
17
16
|
create_concept_frequency_data,
|
|
18
|
-
create_hierarchical_sequence_data,
|
|
19
17
|
create_sequence_data,
|
|
20
18
|
create_sequence_data_with_att,
|
|
21
19
|
extract_ehr_records,
|
|
22
|
-
get_descendant_concept_ids,
|
|
23
20
|
preprocess_domain_table,
|
|
24
21
|
construct_artificial_visits
|
|
25
22
|
)
|
|
23
|
+
from cehrbert_data.utils.vocab_utils import (
|
|
24
|
+
build_ancestry_table_for,
|
|
25
|
+
get_descendant_concept_ids
|
|
26
|
+
)
|
|
26
27
|
from cehrbert_data.utils.logging_utils import add_console_logging
|
|
27
28
|
|
|
28
29
|
from ..cohorts.query_builder import ENTRY_COHORT, NEGATIVE_COHORT, QueryBuilder
|
|
@@ -300,7 +301,6 @@ class NestedCohortBuilder:
|
|
|
300
301
|
aggregate_by_hour: bool = True,
|
|
301
302
|
is_new_patient_representation: bool = False,
|
|
302
303
|
gpt_patient_sequence: bool = False,
|
|
303
|
-
is_hierarchical_bert: bool = False,
|
|
304
304
|
classic_bert_seq: bool = False,
|
|
305
305
|
is_first_time_outcome: bool = False,
|
|
306
306
|
is_questionable_outcome_existed: bool = False,
|
|
@@ -318,6 +318,7 @@ class NestedCohortBuilder:
|
|
|
318
318
|
meds_format: bool = False,
|
|
319
319
|
cache_events: bool = False,
|
|
320
320
|
should_construct_artificial_visits: bool = False,
|
|
321
|
+
duplicate_records: bool = False,
|
|
321
322
|
):
|
|
322
323
|
self._cohort_name = cohort_name
|
|
323
324
|
self._input_folder = input_folder
|
|
@@ -342,7 +343,6 @@ class NestedCohortBuilder:
|
|
|
342
343
|
self._is_drug_roll_up_concept = is_drug_roll_up_concept
|
|
343
344
|
self._is_new_patient_representation = is_new_patient_representation
|
|
344
345
|
self._gpt_patient_sequence = gpt_patient_sequence
|
|
345
|
-
self._is_hierarchical_bert = is_hierarchical_bert
|
|
346
346
|
self._is_first_time_outcome = is_first_time_outcome
|
|
347
347
|
self._is_remove_index_prediction_starts = is_remove_index_prediction_starts
|
|
348
348
|
self._is_questionable_outcome_existed = is_questionable_outcome_existed
|
|
@@ -365,6 +365,7 @@ class NestedCohortBuilder:
|
|
|
365
365
|
self._meds_format = meds_format
|
|
366
366
|
self._cache_events = cache_events
|
|
367
367
|
self._should_construct_artificial_visits = should_construct_artificial_visits
|
|
368
|
+
self._duplicate_records = duplicate_records
|
|
368
369
|
|
|
369
370
|
self.get_logger().info(
|
|
370
371
|
f"cohort_name: {cohort_name}\n"
|
|
@@ -386,7 +387,6 @@ class NestedCohortBuilder:
|
|
|
386
387
|
f"is_drug_roll_up_concept: {is_drug_roll_up_concept}\n"
|
|
387
388
|
f"is_new_patient_representation: {is_new_patient_representation}\n"
|
|
388
389
|
f"gpt_patient_sequence: {gpt_patient_sequence}\n"
|
|
389
|
-
f"is_hierarchical_bert: {is_hierarchical_bert}\n"
|
|
390
390
|
f"is_first_time_outcome: {is_first_time_outcome}\n"
|
|
391
391
|
f"is_questionable_outcome_existed: {is_questionable_outcome_existed}\n"
|
|
392
392
|
f"is_remove_index_prediction_starts: {is_remove_index_prediction_starts}\n"
|
|
@@ -406,6 +406,7 @@ class NestedCohortBuilder:
|
|
|
406
406
|
f"meds_format: {meds_format}\n"
|
|
407
407
|
f"cache_events: {cache_events}\n"
|
|
408
408
|
f"should_construct_artificial_visits: {should_construct_artificial_visits}\n"
|
|
409
|
+
f"duplicate_records: {duplicate_records}\n"
|
|
409
410
|
)
|
|
410
411
|
|
|
411
412
|
self.spark = SparkSession.builder.appName(f"Generate {self._cohort_name}").getOrCreate()
|
|
@@ -637,12 +638,36 @@ class NestedCohortBuilder:
|
|
|
637
638
|
)
|
|
638
639
|
|
|
639
640
|
if self._should_construct_artificial_visits:
|
|
641
|
+
person = self._dependency_dict[PERSON]
|
|
642
|
+
birthdate_udf = F.coalesce(
|
|
643
|
+
"birth_datetime",
|
|
644
|
+
F.concat("year_of_birth", F.lit("-01-01")).cast("timestamp"),
|
|
645
|
+
)
|
|
646
|
+
patient_demographic = person.select(
|
|
647
|
+
"person_id",
|
|
648
|
+
birthdate_udf.alias("birth_datetime"),
|
|
649
|
+
)
|
|
640
650
|
ehr_records, visit_occurrence_with_artificial_visits = construct_artificial_visits(
|
|
641
651
|
ehr_records,
|
|
642
652
|
self._dependency_dict[VISIT_OCCURRENCE],
|
|
643
653
|
spark=self.spark if self._cache_events else None,
|
|
644
654
|
persistence_folder=self._output_data_folder if self._cache_events else None,
|
|
655
|
+
duplicate_records=self._duplicate_records
|
|
645
656
|
)
|
|
657
|
+
|
|
658
|
+
# Update age if some of the ehr_records have been re-associated with the new visits
|
|
659
|
+
ehr_records = ehr_records.join(
|
|
660
|
+
patient_demographic,
|
|
661
|
+
"person_id"
|
|
662
|
+
).join(
|
|
663
|
+
visit_occurrence_with_artificial_visits.select(
|
|
664
|
+
"visit_occurrence_id", "visit_start_date"
|
|
665
|
+
), "visit_occurrence_id"
|
|
666
|
+
).withColumn(
|
|
667
|
+
"age",
|
|
668
|
+
F.ceil(F.months_between(F.col("visit_start_date"), F.col("birth_datetime")) / F.lit(12))
|
|
669
|
+
).drop("visit_start_date", "birth_datetime")
|
|
670
|
+
|
|
646
671
|
# Refresh the dependency
|
|
647
672
|
self._dependency_dict[VISIT_OCCURRENCE] = visit_occurrence_with_artificial_visits
|
|
648
673
|
|
|
@@ -672,8 +697,9 @@ class NestedCohortBuilder:
|
|
|
672
697
|
else:
|
|
673
698
|
if self._is_observation_window_unbounded:
|
|
674
699
|
record_window_filter = (
|
|
675
|
-
|
|
676
|
-
|
|
700
|
+
F.col("ehr.datetime")
|
|
701
|
+
<= F.expr(
|
|
702
|
+
f"cohort.index_date - INTERVAL {self._hold_off_window} DAYS + INTERVAL 0.1 SECOND")
|
|
677
703
|
)
|
|
678
704
|
else:
|
|
679
705
|
record_window_filter = F.col("ehr.datetime").between(
|
|
@@ -692,14 +718,6 @@ class NestedCohortBuilder:
|
|
|
692
718
|
[F.col("ehr." + field_name) for field_name in ehr_records.schema.fieldNames()]
|
|
693
719
|
)
|
|
694
720
|
|
|
695
|
-
if self._is_hierarchical_bert:
|
|
696
|
-
return create_hierarchical_sequence_data(
|
|
697
|
-
person=self._dependency_dict[PERSON],
|
|
698
|
-
visit_occurrence=self._dependency_dict[VISIT_OCCURRENCE],
|
|
699
|
-
patient_events=cohort_ehr_records,
|
|
700
|
-
allow_measurement_only=self._allow_measurement_only,
|
|
701
|
-
)
|
|
702
|
-
|
|
703
721
|
if self._is_feature_concept_frequency:
|
|
704
722
|
return create_concept_frequency_data(cohort_ehr_records, None)
|
|
705
723
|
|
|
@@ -840,7 +858,6 @@ def create_prediction_cohort(
|
|
|
840
858
|
aggregate_by_hour=spark_args.aggregate_by_hour,
|
|
841
859
|
is_new_patient_representation=spark_args.is_new_patient_representation,
|
|
842
860
|
gpt_patient_sequence=spark_args.gpt_patient_sequence,
|
|
843
|
-
is_hierarchical_bert=spark_args.is_hierarchical_bert,
|
|
844
861
|
classic_bert_seq=spark_args.classic_bert_seq,
|
|
845
862
|
is_first_time_outcome=spark_args.is_first_time_outcome,
|
|
846
863
|
# If the outcome negative query exists, that means we need to remove those questionable
|
|
@@ -862,4 +879,5 @@ def create_prediction_cohort(
|
|
|
862
879
|
meds_format=spark_args.meds_format,
|
|
863
880
|
cache_events=spark_args.cache_events,
|
|
864
881
|
should_construct_artificial_visits=spark_args.should_construct_artificial_visits,
|
|
882
|
+
duplicate_records=spark_args.duplicate_records,
|
|
865
883
|
).build()
|
|
@@ -7,6 +7,8 @@ DEVICE_EXPOSURE = "device_exposure"
|
|
|
7
7
|
OBSERVATION = "observation"
|
|
8
8
|
MEASUREMENT = "measurement"
|
|
9
9
|
PROCESSED_MEASUREMENT = "processed_measurement"
|
|
10
|
+
PROCESSED_OBSERVATION = "processed_observation"
|
|
11
|
+
PROCESSED_DEVICE = "processed_device"
|
|
10
12
|
CATEGORICAL_MEASUREMENT = "categorical_measurement"
|
|
11
13
|
OBSERVATION_PERIOD = "observation_period"
|
|
12
14
|
DEATH = "death"
|
{cehrbert_data-0.0.7 → cehrbert_data-0.0.8}/src/cehrbert_data/decorators/clinical_event_decorator.py
RENAMED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import os.path
|
|
2
|
-
|
|
3
1
|
from ..const.common import (
|
|
4
2
|
MEASUREMENT,
|
|
5
3
|
CATEGORICAL_MEASUREMENT,
|
|
4
|
+
OBSERVATION,
|
|
6
5
|
)
|
|
7
6
|
from pyspark.sql import SparkSession, DataFrame, functions as F, Window as W, types as T
|
|
8
7
|
|
|
@@ -127,6 +126,13 @@ class ClinicalEventDecorator(PatientEventDecorator):
|
|
|
127
126
|
).otherwise(F.col("datetime"))
|
|
128
127
|
)
|
|
129
128
|
|
|
129
|
+
outpatient_datetime_udf = (
|
|
130
|
+
F.when(
|
|
131
|
+
F.col("is_inpatient") == 0,
|
|
132
|
+
F.to_timestamp("date")
|
|
133
|
+
).otherwise(F.col("datetime"))
|
|
134
|
+
)
|
|
135
|
+
|
|
130
136
|
patient_events = (
|
|
131
137
|
patient_events.join(visits, ["cohort_member_id", "visit_occurrence_id"])
|
|
132
138
|
.withColumn("datetime", F.to_timestamp("datetime"))
|
|
@@ -136,6 +142,7 @@ class ClinicalEventDecorator(PatientEventDecorator):
|
|
|
136
142
|
.withColumn("visit_end_datetime", F.expr("visit_end_datetime - INTERVAL 1 MINUTE"))
|
|
137
143
|
.withColumn("date", bound_medical_event_date)
|
|
138
144
|
.withColumn("datetime", bound_medical_event_datetime)
|
|
145
|
+
.withColumn("datetime", outpatient_datetime_udf)
|
|
139
146
|
.withColumn("concept_order", concept_order_udf)
|
|
140
147
|
.withColumn("visit_concept_order", visit_concept_order_udf)
|
|
141
148
|
.drop("is_inpatient", "visit_end_date", "visit_end_datetime")
|
|
@@ -154,9 +161,9 @@ class ClinicalEventDecorator(PatientEventDecorator):
|
|
|
154
161
|
# Create the concept_value_mask field to indicate whether domain values should be skipped
|
|
155
162
|
# As of now only measurement has values, so other domains would be skipped.
|
|
156
163
|
patient_events = patient_events.withColumn(
|
|
157
|
-
"concept_value_mask", (F.col("
|
|
164
|
+
"concept_value_mask", (F.col("number_as_value").isNotNull() | F.col("concept_as_value").isNotNull()).cast("int")
|
|
158
165
|
).withColumn(
|
|
159
|
-
"is_numeric_type",
|
|
166
|
+
"is_numeric_type", F.col("number_as_value").isNotNull().cast("int")
|
|
160
167
|
).withColumn(
|
|
161
168
|
"mlm_skip_value",
|
|
162
169
|
(F.col("domain").isin([MEASUREMENT, CATEGORICAL_MEASUREMENT])).cast("int"),
|
|
@@ -13,10 +13,12 @@ from cehrbert_data.decorators import AttType
|
|
|
13
13
|
from cehrbert_data.utils.spark_parse_args import create_spark_args
|
|
14
14
|
from cehrbert_data.utils.spark_utils import (
|
|
15
15
|
extract_ehr_records,
|
|
16
|
+
preprocess_domain_table,
|
|
16
17
|
construct_artificial_visits,
|
|
17
18
|
create_sequence_data_with_att,
|
|
18
19
|
create_concept_frequency_data,
|
|
19
20
|
)
|
|
21
|
+
from cehrbert_data.const.common import PERSON, VISIT_OCCURRENCE
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
class PredictionType(Enum):
|
|
@@ -128,15 +130,41 @@ def main(args):
|
|
|
128
130
|
ehr_records.write.mode("overwrite").parquet(ehr_records_temp_folder)
|
|
129
131
|
ehr_records = spark.read.parquet(ehr_records_temp_folder)
|
|
130
132
|
|
|
131
|
-
|
|
133
|
+
|
|
134
|
+
birthdate_udf = f.coalesce(
|
|
135
|
+
"birth_datetime",
|
|
136
|
+
f.concat("year_of_birth", f.lit("-01-01")).cast("timestamp"),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
person = preprocess_domain_table(spark, args.input_folder, PERSON)
|
|
140
|
+
patient_demographic = person.select(
|
|
141
|
+
"person_id",
|
|
142
|
+
birthdate_udf.alias("birth_datetime"),
|
|
143
|
+
"race_concept_id",
|
|
144
|
+
"gender_concept_id",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
visit_occurrence = preprocess_domain_table(spark, args.input_folder, VISIT_OCCURRENCE)
|
|
132
149
|
|
|
133
150
|
if args.should_construct_artificial_visits:
|
|
134
151
|
ehr_records, visit_occurrence = construct_artificial_visits(
|
|
135
152
|
ehr_records,
|
|
136
153
|
visit_occurrence=visit_occurrence,
|
|
137
154
|
spark=spark,
|
|
138
|
-
persistence_folder = str(os.path.join(args.output_folder, args.cohort_name))
|
|
155
|
+
persistence_folder = str(os.path.join(args.output_folder, args.cohort_name)),
|
|
156
|
+
duplicate_records=args.duplicate_records
|
|
139
157
|
)
|
|
158
|
+
# Update age if some of the ehr_records have been re-associated with the new visits
|
|
159
|
+
ehr_records = ehr_records.join(
|
|
160
|
+
patient_demographic.select("person_id", "birth_datetime"),
|
|
161
|
+
"person_id",
|
|
162
|
+
).join(
|
|
163
|
+
visit_occurrence.select("visit_occurrence_id", "visit_start_date"), "visit_occurrence_id"
|
|
164
|
+
).withColumn(
|
|
165
|
+
"age",
|
|
166
|
+
f.ceil(f.months_between(f.col("visit_start_date"), f.col("birth_datetime")) / f.lit(12))
|
|
167
|
+
).drop("visit_start_date", "birth_datetime")
|
|
140
168
|
|
|
141
169
|
cohort_visit_occurrence = visit_occurrence.join(
|
|
142
170
|
cohort.select("person_id", "cohort_member_id", "index_date"),
|
|
@@ -157,22 +185,6 @@ def main(args):
|
|
|
157
185
|
f.col("visit_end_date").cast(t.TimestampType()),
|
|
158
186
|
f.col("visit_start_datetime")
|
|
159
187
|
).cast(t.TimestampType())
|
|
160
|
-
).where(
|
|
161
|
-
f.col("visit_start_datetime") <=
|
|
162
|
-
f.expr(f"index_date - INTERVAL {args.hold_off_window} DAYS + INTERVAL 0.1 SECOND")
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
birthdate_udf = f.coalesce(
|
|
167
|
-
"birth_datetime",
|
|
168
|
-
f.concat("year_of_birth", f.lit("-01-01")).cast("timestamp"),
|
|
169
|
-
)
|
|
170
|
-
person = spark.read.parquet(os.path.join(args.input_folder, "person"))
|
|
171
|
-
patient_demographic = person.select(
|
|
172
|
-
"person_id",
|
|
173
|
-
birthdate_udf.alias("birth_datetime"),
|
|
174
|
-
"race_concept_id",
|
|
175
|
-
"gender_concept_id",
|
|
176
188
|
)
|
|
177
189
|
|
|
178
190
|
age_udf = f.ceil(f.months_between(f.col("visit_start_date"), f.col("birth_datetime")) / f.lit(12))
|
|
@@ -416,4 +416,10 @@ def create_spark_args(parse: bool = True):
|
|
|
416
416
|
help="Indicate whether we should construct artificial visits for "
|
|
417
417
|
"the problem list records that could occur years ahead",
|
|
418
418
|
)
|
|
419
|
+
parser.add_argument(
|
|
420
|
+
"--duplicate_records",
|
|
421
|
+
dest="duplicate_records",
|
|
422
|
+
action="store_true",
|
|
423
|
+
help="Indicate whether we want to duplicate the problem list records when constructing artificial visits"
|
|
424
|
+
)
|
|
419
425
|
return parser.parse_args() if parse else parser
|