cehrbert-data 0.0.6__tar.gz → 0.0.7__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.6 → cehrbert_data-0.0.7}/PKG-INFO +3 -2
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_included_concept_list.py +21 -3
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_training_data.py +22 -1
- cehrbert_data-0.0.7/src/cehrbert_data/cohorts/atrial_fibrillation.py +63 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/cabg.py +13 -5
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/coronary_artery_disease.py +15 -5
- cehrbert_data-0.0.7/src/cehrbert_data/cohorts/ischemic_stroke.py +61 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/last_visit_discharged_home.py +1 -1
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/spark_app_base.py +62 -32
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/type_two_diabietes.py +16 -7
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/decorators/__init__.py +1 -0
- cehrbert_data-0.0.7/src/cehrbert_data/decorators/prediction_token_decorator.py +73 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/decorators/token_priority.py +1 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/copd_readmission.py +2 -2
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/hf_readmission.py +2 -2
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/hospitalization_mortality.py +1 -1
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/tools/extract_features.py +54 -87
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/utils/spark_parse_args.py +7 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/utils/spark_utils.py +182 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data.egg-info/PKG-INFO +3 -2
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data.egg-info/SOURCES.txt +1 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/integration_tests/test_hf_readmission.py +1 -0
- cehrbert_data-0.0.6/src/cehrbert_data/cohorts/atrial_fibrillation.py +0 -45
- cehrbert_data-0.0.6/src/cehrbert_data/cohorts/ischemic_stroke.py +0 -45
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/.github/workflows/python-build.yml +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/.github/workflows/tests.yml +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/.gitignore +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/.pre-commit-config.yaml +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/LICENSE +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/README.md +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/pyproject.toml +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/.part-00000-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/.part-00003-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/.part-00010-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/part-00000-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/part-00003-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept/part-00010-4b12270c-f6c8-4b59-8e0f-fd588bd79386-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/.part-00000-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/.part-00002-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/.part-00006-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/.part-00011-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/.part-00013-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/part-00000-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/part-00002-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/part-00006-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/part-00011-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_ancestor/part-00013-eafbd8be-3337-46da-89d3-20f79c2565d4-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/.part-00000-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/.part-00002-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/.part-00007-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/.part-00012-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/part-00000-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/part-00002-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/part-00007-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/concept_relationship/part-00012-5752b472-8ba7-4189-ab69-8c92e46443aa-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/condition_occurrence/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/condition_occurrence/.part-00000-4eff03a1-cdcf-4c89-b0cd-9ce590b9b1eb-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/condition_occurrence/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/condition_occurrence/part-00000-4eff03a1-cdcf-4c89-b0cd-9ce590b9b1eb-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/drug_exposure/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/drug_exposure/.part-00000-10bbf1a4-a7da-416e-9703-58609c7edfad-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/drug_exposure/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/drug_exposure/part-00000-10bbf1a4-a7da-416e-9703-58609c7edfad-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/observation_period/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/observation_period/.part-00000-694316e5-cc95-49f1-9fad-5a7f377e2602-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/observation_period/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/observation_period/part-00000-694316e5-cc95-49f1-9fad-5a7f377e2602-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/person/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/person/.part-00000-7d789011-f361-48da-af6f-cfe102978b3a-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/person/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/person/part-00000-7d789011-f361-48da-af6f-cfe102978b3a-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/procedure_occurrence/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/procedure_occurrence/.part-00000-e73003c1-aed5-41c0-b2d4-eaccaccf044a-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/procedure_occurrence/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/procedure_occurrence/part-00000-e73003c1-aed5-41c0-b2d4-eaccaccf044a-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/visit_occurrence/._SUCCESS.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/visit_occurrence/.part-00000-e874b5f1-bf9e-4cb9-93bf-c309a47b0476-c000.snappy.parquet.crc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/visit_occurrence/_SUCCESS +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/sample_data/omop_sample/visit_occurrence/part-00000-e874b5f1-bf9e-4cb9-93bf-c309a47b0476-c000.snappy.parquet +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/setup.cfg +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_concept_similarity_table.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_hierarchical_bert_training_data.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_information_content.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_required_labs.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/covid.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/covid_inpatient.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/death.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/heart_failure.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/query_builder.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/ventilation.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/config/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/config/output_names.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/const/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/const/__pycache__/__init__.cpython-311.pyc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/const/__pycache__/common.cpython-311.pyc +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/const/artificial_tokens.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/const/common.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/decorators/artificial_time_token_decorator.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/decorators/clinical_event_decorator.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/decorators/death_event_decorator.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/decorators/demographic_event_decorator.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/decorators/patient_event_decorator_base.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/afib_ischemic_stroke.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/cad_cabg_cohort.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/cad_hf_cohort.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/covid_death.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/covid_ventilation.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/discharge_home_death.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/hospitalization.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/prediction_cohorts/t2dm_hf_cohort.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/queries/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/queries/measurement_queries.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/tools/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/tools/connect_omop_visit.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/tools/download_omop_tables.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/tools/ehrshot_to_omop.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/tools/prepare_ehrshot_cohorts.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/tools/update_omop_visit.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/utils/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/utils/logging_utils.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data.egg-info/dependency_links.txt +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data.egg-info/requires.txt +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data.egg-info/top_level.txt +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/integration_tests/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/integration_tests/test_generate_training_data.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/integration_tests/test_hf_readmission_cohort_meds.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/pyspark_test_base.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/unit_tests/__init__.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/unit_tests/test_ehrshot_to_omop.py +0 -0
- {cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/tests/unit_tests/test_spark_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: cehrbert_data
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.7
|
|
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
|
|
@@ -25,6 +25,7 @@ Requires-Dist: pytest-subtests; extra == "dev"
|
|
|
25
25
|
Requires-Dist: rootutils; extra == "dev"
|
|
26
26
|
Requires-Dist: hypothesis; extra == "dev"
|
|
27
27
|
Requires-Dist: black; extra == "dev"
|
|
28
|
+
Dynamic: license-file
|
|
28
29
|
|
|
29
30
|
# cehrbert_data
|
|
30
31
|
|
{cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_included_concept_list.py
RENAMED
|
@@ -18,6 +18,7 @@ Command-line Arguments:
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
import os
|
|
21
|
+
from typing import List
|
|
21
22
|
|
|
22
23
|
from pyspark.sql import SparkSession
|
|
23
24
|
from pyspark.sql import functions as F
|
|
@@ -29,7 +30,13 @@ from cehrbert_data.utils.spark_utils import join_domain_tables, preprocess_domai
|
|
|
29
30
|
DOMAIN_TABLE_LIST = ["condition_occurrence", "procedure_occurrence", "drug_exposure"]
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
def main(
|
|
33
|
+
def main(
|
|
34
|
+
input_folder: str,
|
|
35
|
+
output_folder: str,
|
|
36
|
+
min_num_of_patients: int,
|
|
37
|
+
with_drug_rollup: bool = True,
|
|
38
|
+
ehr_table_list: List[str] = None
|
|
39
|
+
):
|
|
33
40
|
"""
|
|
34
41
|
Main function to generate a qualified concept list based on patient event data from multiple.
|
|
35
42
|
|
|
@@ -39,8 +46,9 @@ def main(input_folder, output_folder, min_num_of_patients, with_drug_rollup: boo
|
|
|
39
46
|
input_folder (str): The directory where the input data is stored.
|
|
40
47
|
output_folder (str): The directory where the output (qualified concept list) will be saved.
|
|
41
48
|
min_num_of_patients (int): Minimum number of patients that a concept must be linked to for
|
|
42
|
-
|
|
49
|
+
inclusion.
|
|
43
50
|
with_drug_rollup (bool): If True, applies drug rollup logic to the drug_exposure domain.
|
|
51
|
+
ehr_table_list (List[str]): List of patient event tables to include in the concept list.
|
|
44
52
|
|
|
45
53
|
The function processes patient event data across various domain tables, excludes low-frequency
|
|
46
54
|
concepts, and saves the filtered concepts to a specified output folder.
|
|
@@ -50,7 +58,8 @@ def main(input_folder, output_folder, min_num_of_patients, with_drug_rollup: boo
|
|
|
50
58
|
domain_tables = []
|
|
51
59
|
# Exclude measurement from domain_table_list if exists because we need to process measurement
|
|
52
60
|
# in a different way
|
|
53
|
-
|
|
61
|
+
domain_table_list = ehr_table_list if ehr_table_list else DOMAIN_TABLE_LIST
|
|
62
|
+
for domain_table_name in domain_table_list:
|
|
54
63
|
if domain_table_name != MEASUREMENT:
|
|
55
64
|
domain_tables.append(
|
|
56
65
|
preprocess_domain_table(
|
|
@@ -105,6 +114,14 @@ if __name__ == "__main__":
|
|
|
105
114
|
required=False,
|
|
106
115
|
)
|
|
107
116
|
parser.add_argument("--with_drug_rollup", dest="with_drug_rollup", action="store_true")
|
|
117
|
+
parser.add_argument(
|
|
118
|
+
"--ehr_table_list",
|
|
119
|
+
dest="ehr_table_list",
|
|
120
|
+
nargs="+",
|
|
121
|
+
action="store",
|
|
122
|
+
help="The list of domain tables you want to include for feature extraction",
|
|
123
|
+
required=False,
|
|
124
|
+
)
|
|
108
125
|
|
|
109
126
|
ARGS = parser.parse_args()
|
|
110
127
|
|
|
@@ -113,4 +130,5 @@ if __name__ == "__main__":
|
|
|
113
130
|
ARGS.output_folder,
|
|
114
131
|
ARGS.min_num_of_patients,
|
|
115
132
|
ARGS.with_drug_rollup,
|
|
133
|
+
ARGS.ehr_table_list,
|
|
116
134
|
)
|
{cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/apps/generate_training_data.py
RENAMED
|
@@ -22,6 +22,7 @@ from cehrbert_data.utils.spark_utils import (
|
|
|
22
22
|
preprocess_domain_table,
|
|
23
23
|
get_measurement_table,
|
|
24
24
|
validate_table_names,
|
|
25
|
+
construct_artificial_visits
|
|
25
26
|
)
|
|
26
27
|
from cehrbert_data.utils.logging_utils import add_console_logging
|
|
27
28
|
|
|
@@ -50,6 +51,7 @@ def main(
|
|
|
50
51
|
continue_from_events: bool = False,
|
|
51
52
|
refresh_measurement: bool = False,
|
|
52
53
|
aggregate_by_hour: bool = True,
|
|
54
|
+
should_construct_artificial_visits: bool = False,
|
|
53
55
|
):
|
|
54
56
|
spark = SparkSession.builder.appName("Generate CEHR-BERT Training Data").getOrCreate()
|
|
55
57
|
|
|
@@ -74,6 +76,7 @@ def main(
|
|
|
74
76
|
f"with_drug_rollup: {with_drug_rollup}\n"
|
|
75
77
|
f"refresh_measurement: {refresh_measurement}\n"
|
|
76
78
|
f"aggregate_by_hour: {aggregate_by_hour}\n"
|
|
79
|
+
f"should_construct_artificial_visits: {should_construct_artificial_visits}\n"
|
|
77
80
|
)
|
|
78
81
|
|
|
79
82
|
domain_tables = []
|
|
@@ -94,6 +97,7 @@ def main(
|
|
|
94
97
|
"visit_start_date",
|
|
95
98
|
"visit_start_datetime",
|
|
96
99
|
"visit_end_date",
|
|
100
|
+
"visit_end_datetime",
|
|
97
101
|
"visit_concept_id",
|
|
98
102
|
"person_id",
|
|
99
103
|
"discharged_to_concept_id",
|
|
@@ -159,6 +163,15 @@ def main(
|
|
|
159
163
|
|
|
160
164
|
patient_events = spark.read.parquet(os.path.join(output_folder, "all_patient_events"))
|
|
161
165
|
|
|
166
|
+
if should_construct_artificial_visits:
|
|
167
|
+
# Construct artificial visits or re-link the visits for the problem list events
|
|
168
|
+
patient_events, visit_occurrence_person = construct_artificial_visits(
|
|
169
|
+
patient_events,
|
|
170
|
+
visit_occurrence_person,
|
|
171
|
+
spark=spark,
|
|
172
|
+
persistence_folder=output_folder,
|
|
173
|
+
)
|
|
174
|
+
|
|
162
175
|
if is_new_patient_representation:
|
|
163
176
|
sequence_data = create_sequence_data_with_att(
|
|
164
177
|
patient_events,
|
|
@@ -274,7 +287,7 @@ if __name__ == "__main__":
|
|
|
274
287
|
type=lambda s: datetime.datetime.strptime(s, "%Y-%m-%d"),
|
|
275
288
|
action="store",
|
|
276
289
|
required=False,
|
|
277
|
-
default="
|
|
290
|
+
default="1985-01-01",
|
|
278
291
|
)
|
|
279
292
|
parser.add_argument(
|
|
280
293
|
"-iv",
|
|
@@ -349,6 +362,13 @@ if __name__ == "__main__":
|
|
|
349
362
|
action="store",
|
|
350
363
|
choices=[e.value for e in AttType],
|
|
351
364
|
)
|
|
365
|
+
parser.add_argument(
|
|
366
|
+
"--should_construct_artificial_visits",
|
|
367
|
+
dest="should_construct_artificial_visits",
|
|
368
|
+
action="store_true",
|
|
369
|
+
help="Indicate whether we should construct artificial visits for "
|
|
370
|
+
"the problem list records that could occur years ahead",
|
|
371
|
+
)
|
|
352
372
|
|
|
353
373
|
ARGS = parser.parse_args()
|
|
354
374
|
|
|
@@ -378,4 +398,5 @@ if __name__ == "__main__":
|
|
|
378
398
|
continue_from_events=ARGS.continue_from_events,
|
|
379
399
|
refresh_measurement=ARGS.refresh_measurement,
|
|
380
400
|
aggregate_by_hour=ARGS.aggregate_by_hour,
|
|
401
|
+
should_construct_artificial_visits=ARGS.should_construct_artificial_visits,
|
|
381
402
|
)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from cehrbert_data.cohorts.query_builder import AncestorTableSpec, QueryBuilder, QuerySpec
|
|
2
|
+
from cehrbert_data.const.common import CONDITION_OCCURRENCE, PERSON, VISIT_OCCURRENCE
|
|
3
|
+
|
|
4
|
+
COHORT_QUERY_TEMPLATE = """
|
|
5
|
+
SELECT
|
|
6
|
+
DISTINCT
|
|
7
|
+
c.person_id,
|
|
8
|
+
c.index_date,
|
|
9
|
+
c.visit_occurrence_id
|
|
10
|
+
FROM
|
|
11
|
+
(
|
|
12
|
+
SELECT
|
|
13
|
+
co.person_id,
|
|
14
|
+
vo.visit_occurrence_id,
|
|
15
|
+
CASE
|
|
16
|
+
WHEN co.condition_start_datetime < vo.visit_start_datetime AND datediff(vo.visit_start_date, co.condition_start_date) <= 1
|
|
17
|
+
THEN to_timestamp(concat(date_format(vo.visit_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
18
|
+
ELSE
|
|
19
|
+
to_timestamp(concat(date_format(co.condition_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
20
|
+
END AS index_date,
|
|
21
|
+
ROW_NUMBER() OVER(
|
|
22
|
+
PARTITION BY co.person_id
|
|
23
|
+
ORDER BY co.condition_start_datetime,
|
|
24
|
+
co.condition_start_date,
|
|
25
|
+
co.visit_occurrence_id
|
|
26
|
+
) as r_number
|
|
27
|
+
FROM global_temp.condition_occurrence AS co
|
|
28
|
+
JOIN global_temp.visit_occurrence AS vo
|
|
29
|
+
ON co.visit_occurrence_id = vo.visit_occurrence_id
|
|
30
|
+
JOIN global_temp.{atrial_fibrillation_concepts} AS c
|
|
31
|
+
ON co.condition_concept_id = c.concept_id
|
|
32
|
+
) AS c
|
|
33
|
+
WHERE c.r_number = 1
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
ATRIAL_FIBRILLATION_CONCEPT_ID = [313217]
|
|
37
|
+
|
|
38
|
+
DEPENDENCY_LIST = [PERSON, VISIT_OCCURRENCE, CONDITION_OCCURRENCE]
|
|
39
|
+
|
|
40
|
+
DEFAULT_COHORT_NAME = "atrial_fibrillation"
|
|
41
|
+
ATRIAL_FIBRILLATION_CONCEPTS = "atrial_fibrillation_concepts"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def query_builder():
|
|
45
|
+
query = QuerySpec(
|
|
46
|
+
table_name=DEFAULT_COHORT_NAME,
|
|
47
|
+
query_template=COHORT_QUERY_TEMPLATE,
|
|
48
|
+
parameters={"atrial_fibrillation_concepts": ATRIAL_FIBRILLATION_CONCEPTS},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
ancestor_table_specs = [
|
|
52
|
+
AncestorTableSpec(
|
|
53
|
+
table_name=ATRIAL_FIBRILLATION_CONCEPTS,
|
|
54
|
+
ancestor_concept_ids=ATRIAL_FIBRILLATION_CONCEPT_ID,
|
|
55
|
+
is_standard=True,
|
|
56
|
+
)
|
|
57
|
+
]
|
|
58
|
+
return QueryBuilder(
|
|
59
|
+
cohort_name=DEFAULT_COHORT_NAME,
|
|
60
|
+
dependency_list=DEPENDENCY_LIST,
|
|
61
|
+
query=query,
|
|
62
|
+
ancestor_table_specs=ancestor_table_specs,
|
|
63
|
+
)
|
|
@@ -10,10 +10,18 @@ FROM
|
|
|
10
10
|
(
|
|
11
11
|
SELECT DISTINCT
|
|
12
12
|
vo.person_id,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
vo.visit_occurrence_id,
|
|
14
|
+
CASE
|
|
15
|
+
WHEN po.procedure_datetime < vo.visit_start_datetime AND datediff(vo.visit_start_datetime, po.procedure_datetime) <= 1
|
|
16
|
+
THEN to_timestamp(concat(date_format(vo.visit_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
17
|
+
ELSE to_timestamp(concat(date_format(po.procedure_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
18
|
+
END AS index_date,
|
|
19
|
+
ROW_NUMBER() OVER(
|
|
20
|
+
PARTITION BY po.person_id
|
|
21
|
+
ORDER BY po.procedure_datetime,
|
|
22
|
+
po.procedure_date,
|
|
23
|
+
po.visit_occurrence_id
|
|
24
|
+
) as r_number
|
|
17
25
|
FROM global_temp.procedure_occurrence AS po
|
|
18
26
|
JOIN global_temp.visit_occurrence AS vo
|
|
19
27
|
ON po.visit_occurrence_id = vo.visit_occurrence_id
|
|
@@ -23,7 +31,7 @@ FROM
|
|
|
23
31
|
WHERE po.procedure_concept_id = ie.concept_id
|
|
24
32
|
)
|
|
25
33
|
) c
|
|
26
|
-
WHERE c.index_date >= '{date_lower_bound}'
|
|
34
|
+
WHERE c.index_date >= '{date_lower_bound}' AND c.r_number = 1
|
|
27
35
|
"""
|
|
28
36
|
|
|
29
37
|
DEFAULT_COHORT_NAME = "cabg"
|
{cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/coronary_artery_disease.py
RENAMED
|
@@ -21,10 +21,18 @@ FROM
|
|
|
21
21
|
(
|
|
22
22
|
SELECT DISTINCT
|
|
23
23
|
vo.person_id,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
vo.visit_occurrence_id,
|
|
25
|
+
CASE
|
|
26
|
+
WHEN co.condition_start_datetime < vo.visit_start_datetime AND datediff(vo.visit_start_datetime, co.condition_start_datetime) <= 1
|
|
27
|
+
THEN to_timestamp(concat(date_format(vo.visit_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
28
|
+
ELSE to_timestamp(concat(date_format(co.condition_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
29
|
+
END AS index_date,
|
|
30
|
+
ROW_NUMBER() OVER(
|
|
31
|
+
PARTITION BY co.person_id
|
|
32
|
+
ORDER BY co.condition_start_datetime,
|
|
33
|
+
co.condition_start_date,
|
|
34
|
+
co.visit_occurrence_id
|
|
35
|
+
) as r_number
|
|
28
36
|
FROM global_temp.condition_occurrence AS co
|
|
29
37
|
JOIN global_temp.visit_occurrence AS vo
|
|
30
38
|
ON co.visit_occurrence_id = vo.visit_occurrence_id
|
|
@@ -41,7 +49,9 @@ WHERE NOT EXISTS (
|
|
|
41
49
|
FROM prior_graft_stent AS exclusion
|
|
42
50
|
WHERE exclusion.person_id = c.person_id
|
|
43
51
|
AND c.index_date > exclusion.procedure_date
|
|
44
|
-
)
|
|
52
|
+
)
|
|
53
|
+
AND c.r_number = 1
|
|
54
|
+
AND c.index_date >= '{date_lower_bound}'
|
|
45
55
|
"""
|
|
46
56
|
|
|
47
57
|
DEFAULT_COHORT_NAME = "coronary_artery_disease"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from cehrbert_data.cohorts.query_builder import AncestorTableSpec, QueryBuilder, QuerySpec
|
|
2
|
+
from cehrbert_data.const.common import CONDITION_OCCURRENCE, PERSON, VISIT_OCCURRENCE
|
|
3
|
+
|
|
4
|
+
COHORT_QUERY_TEMPLATE = """
|
|
5
|
+
SELECT DISTINCT
|
|
6
|
+
c.person_id,
|
|
7
|
+
c.index_date,
|
|
8
|
+
c.visit_occurrence_id
|
|
9
|
+
FROM
|
|
10
|
+
(
|
|
11
|
+
SELECT
|
|
12
|
+
co.person_id,
|
|
13
|
+
vo.visit_occurrence_id,
|
|
14
|
+
CASE
|
|
15
|
+
WHEN co.condition_start_datetime < vo.visit_start_datetime AND datediff(vo.visit_start_datetime, co.condition_start_datetime) <= 1
|
|
16
|
+
THEN to_timestamp(concat(date_format(vo.visit_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
17
|
+
ELSE to_timestamp(concat(date_format(co.condition_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
18
|
+
END AS index_date,
|
|
19
|
+
ROW_NUMBER() OVER(
|
|
20
|
+
PARTITION BY co.person_id
|
|
21
|
+
ORDER BY co.condition_start_datetime,
|
|
22
|
+
co.condition_start_date,
|
|
23
|
+
co.visit_occurrence_id
|
|
24
|
+
) as r_number
|
|
25
|
+
FROM global_temp.condition_occurrence AS co
|
|
26
|
+
JOIN global_temp.visit_occurrence AS vo
|
|
27
|
+
ON co.visit_occurrence_id = vo.visit_occurrence_id
|
|
28
|
+
JOIN global_temp.{ischemic_stroke_concepts} AS c
|
|
29
|
+
ON co.condition_concept_id = c.concept_id
|
|
30
|
+
) AS c
|
|
31
|
+
WHERE c.r_number = 1
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
ISCHEMIC_STROKE_CONCEPT_ID = [443454]
|
|
35
|
+
|
|
36
|
+
DEPENDENCY_LIST = [PERSON, VISIT_OCCURRENCE, CONDITION_OCCURRENCE]
|
|
37
|
+
|
|
38
|
+
DEFAULT_COHORT_NAME = "ischemic_stroke"
|
|
39
|
+
ISCHEMIC_STROKE_CONCEPTS = "ischemic_stroke_concepts"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def query_builder():
|
|
43
|
+
query = QuerySpec(
|
|
44
|
+
table_name=DEFAULT_COHORT_NAME,
|
|
45
|
+
query_template=COHORT_QUERY_TEMPLATE,
|
|
46
|
+
parameters={"ischemic_stroke_concepts": ISCHEMIC_STROKE_CONCEPTS},
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
ancestor_table_specs = [
|
|
50
|
+
AncestorTableSpec(
|
|
51
|
+
table_name=ISCHEMIC_STROKE_CONCEPTS,
|
|
52
|
+
ancestor_concept_ids=ISCHEMIC_STROKE_CONCEPT_ID,
|
|
53
|
+
is_standard=True,
|
|
54
|
+
)
|
|
55
|
+
]
|
|
56
|
+
return QueryBuilder(
|
|
57
|
+
cohort_name=DEFAULT_COHORT_NAME,
|
|
58
|
+
dependency_list=DEPENDENCY_LIST,
|
|
59
|
+
query=query,
|
|
60
|
+
ancestor_table_specs=ancestor_table_specs,
|
|
61
|
+
)
|
{cehrbert_data-0.0.6 → cehrbert_data-0.0.7}/src/cehrbert_data/cohorts/last_visit_discharged_home.py
RENAMED
|
@@ -11,7 +11,7 @@ FROM
|
|
|
11
11
|
SELECT
|
|
12
12
|
v.person_id,
|
|
13
13
|
v.visit_occurrence_id,
|
|
14
|
-
v.visit_end_date AS index_date,
|
|
14
|
+
coalesce(v.visit_end_datetime, v.visit_end_date) AS index_date,
|
|
15
15
|
v.discharged_to_concept_id,
|
|
16
16
|
ROW_NUMBER() OVER(PARTITION BY v.person_id ORDER BY DATE(v.visit_end_date) DESC) AS rn
|
|
17
17
|
FROM global_temp.visit_occurrence AS v
|
|
@@ -5,7 +5,6 @@ import shutil
|
|
|
5
5
|
from abc import ABC
|
|
6
6
|
from typing import List
|
|
7
7
|
|
|
8
|
-
from numpy.random import permutation
|
|
9
8
|
from pandas import to_datetime
|
|
10
9
|
from pyspark.sql import DataFrame, SparkSession
|
|
11
10
|
from pyspark.sql import functions as F
|
|
@@ -22,6 +21,7 @@ from cehrbert_data.utils.spark_utils import (
|
|
|
22
21
|
extract_ehr_records,
|
|
23
22
|
get_descendant_concept_ids,
|
|
24
23
|
preprocess_domain_table,
|
|
24
|
+
construct_artificial_visits
|
|
25
25
|
)
|
|
26
26
|
from cehrbert_data.utils.logging_utils import add_console_logging
|
|
27
27
|
|
|
@@ -232,8 +232,8 @@ class BaseCohortBuilder(ABC):
|
|
|
232
232
|
FROM global_temp.cohort AS c
|
|
233
233
|
JOIN global_temp.observation_period AS p
|
|
234
234
|
ON c.person_id = p.person_id
|
|
235
|
-
AND
|
|
236
|
-
AND
|
|
235
|
+
AND c.index_date - INTERVAL {prior_observation_period} DAY >= p.observation_period_start_date
|
|
236
|
+
AND c.index_date + INTERVAL {post_observation_period} DAY <= p.observation_period_end_date
|
|
237
237
|
""".format(
|
|
238
238
|
prior_observation_period=self._prior_observation_period,
|
|
239
239
|
post_observation_period=self._post_observation_period,
|
|
@@ -317,6 +317,7 @@ class NestedCohortBuilder:
|
|
|
317
317
|
exclude_features: bool = True,
|
|
318
318
|
meds_format: bool = False,
|
|
319
319
|
cache_events: bool = False,
|
|
320
|
+
should_construct_artificial_visits: bool = False,
|
|
320
321
|
):
|
|
321
322
|
self._cohort_name = cohort_name
|
|
322
323
|
self._input_folder = input_folder
|
|
@@ -363,6 +364,7 @@ class NestedCohortBuilder:
|
|
|
363
364
|
self._exclude_features = exclude_features
|
|
364
365
|
self._meds_format = meds_format
|
|
365
366
|
self._cache_events = cache_events
|
|
367
|
+
self._should_construct_artificial_visits = should_construct_artificial_visits
|
|
366
368
|
|
|
367
369
|
self.get_logger().info(
|
|
368
370
|
f"cohort_name: {cohort_name}\n"
|
|
@@ -403,6 +405,7 @@ class NestedCohortBuilder:
|
|
|
403
405
|
f"extract_features: {exclude_features}\n"
|
|
404
406
|
f"meds_format: {meds_format}\n"
|
|
405
407
|
f"cache_events: {cache_events}\n"
|
|
408
|
+
f"should_construct_artificial_visits: {should_construct_artificial_visits}\n"
|
|
406
409
|
)
|
|
407
410
|
|
|
408
411
|
self.spark = SparkSession.builder.appName(f"Generate {self._cohort_name}").getOrCreate()
|
|
@@ -434,7 +437,7 @@ class NestedCohortBuilder:
|
|
|
434
437
|
FROM global_temp.target_cohort AS t
|
|
435
438
|
LEFT JOIN global_temp.{entry_cohort} AS o
|
|
436
439
|
ON t.person_id = o.person_id
|
|
437
|
-
|
|
440
|
+
AND t.index_date + INTERVAL {prediction_start_days} DAY > o.index_date
|
|
438
441
|
WHERE o.person_id IS NULL
|
|
439
442
|
""".format(
|
|
440
443
|
entry_cohort=ENTRY_COHORT,
|
|
@@ -468,7 +471,7 @@ class NestedCohortBuilder:
|
|
|
468
471
|
LEFT JOIN global_temp.outcome_cohort AS exclusion
|
|
469
472
|
ON t.person_id = exclusion.person_id
|
|
470
473
|
AND exclusion.index_date BETWEEN t.index_date
|
|
471
|
-
AND
|
|
474
|
+
AND t.index_date + INTERVAL {prediction_start_days} DAY
|
|
472
475
|
WHERE exclusion.person_id IS NULL
|
|
473
476
|
""".format(
|
|
474
477
|
prediction_start_days=max(prediction_start_days - 1, 0)
|
|
@@ -485,7 +488,7 @@ class NestedCohortBuilder:
|
|
|
485
488
|
FROM global_temp.target_cohort AS t
|
|
486
489
|
LEFT JOIN global_temp.outcome_cohort AS o
|
|
487
490
|
ON t.person_id = o.person_id
|
|
488
|
-
AND o.index_date >=
|
|
491
|
+
AND o.index_date >= t.index_date + INTERVAL {prediction_start_days} DAY
|
|
489
492
|
"""
|
|
490
493
|
else:
|
|
491
494
|
query_template = """
|
|
@@ -496,11 +499,11 @@ class NestedCohortBuilder:
|
|
|
496
499
|
FROM global_temp.target_cohort AS t
|
|
497
500
|
LEFT JOIN global_temp.observation_period AS op
|
|
498
501
|
ON t.person_id = op.person_id
|
|
499
|
-
AND
|
|
502
|
+
AND t.index_date + INTERVAL {prediction_window} DAY <= op.observation_period_end_date
|
|
500
503
|
LEFT JOIN global_temp.outcome_cohort AS o
|
|
501
504
|
ON t.person_id = o.person_id
|
|
502
|
-
AND o.index_date BETWEEN
|
|
503
|
-
AND
|
|
505
|
+
AND o.index_date BETWEEN t.index_date + INTERVAL {prediction_start_days} DAY
|
|
506
|
+
AND t.index_date + INTERVAL {prediction_window} DAY
|
|
504
507
|
WHERE op.person_id IS NOT NULL OR o.person_id IS NOT NULL
|
|
505
508
|
"""
|
|
506
509
|
|
|
@@ -557,20 +560,24 @@ class NestedCohortBuilder:
|
|
|
557
560
|
observation_period = self._dependency_dict[OBSERVATION_PERIOD]
|
|
558
561
|
# Add time_to_event
|
|
559
562
|
cohort = cohort.join(
|
|
560
|
-
observation_period.select("person_id", "observation_period_end_date"),
|
|
563
|
+
observation_period.select("person_id", "observation_period_end_date"),
|
|
564
|
+
cohort[person_id_column] == observation_period["person_id"]
|
|
565
|
+
).select(
|
|
566
|
+
[cohort[c] for c in cohort.columns] +
|
|
567
|
+
[observation_period["observation_period_end_date"]]
|
|
561
568
|
).withColumn(
|
|
562
569
|
"study_end_date",
|
|
563
570
|
F.coalesce(F.col("outcome_date"), F.col("observation_period_end_date"))
|
|
564
|
-
).drop(
|
|
571
|
+
).drop(
|
|
572
|
+
"observation_period_end_date"
|
|
573
|
+
)
|
|
565
574
|
else:
|
|
566
575
|
# Add time_to_event
|
|
567
576
|
cohort = cohort.withColumn(
|
|
568
577
|
"study_end_date",
|
|
569
578
|
F.coalesce(
|
|
570
579
|
F.col("outcome_date"),
|
|
571
|
-
F.
|
|
572
|
-
cohort[index_date_column], self._prediction_window
|
|
573
|
-
)
|
|
580
|
+
F.expr(f"{index_date_column} + INTERVAL {self._prediction_window} DAYS")
|
|
574
581
|
)
|
|
575
582
|
)
|
|
576
583
|
cohort = cohort.withColumn("time_to_event", F.datediff("study_end_date", index_date_column))
|
|
@@ -578,11 +585,11 @@ class NestedCohortBuilder:
|
|
|
578
585
|
# if patient_splits is provided, we will
|
|
579
586
|
if self._patient_splits_folder:
|
|
580
587
|
patient_splits = self.spark.read.parquet(self._patient_splits_folder)
|
|
581
|
-
cohort.join(
|
|
582
|
-
patient_splits,
|
|
583
|
-
cohort
|
|
588
|
+
cohort.alias("cohort").join(
|
|
589
|
+
patient_splits.alias("split"),
|
|
590
|
+
F.col(f"cohort.{person_id_column}") == F.col("split.person_id")
|
|
584
591
|
).select(
|
|
585
|
-
[cohort
|
|
592
|
+
[F.col(f"cohort.{c}").alias(c) for c in cohort.columns] + [F.col("split.split").alias("split")]
|
|
586
593
|
).orderBy(person_id_column, index_date_column).write.mode(
|
|
587
594
|
"overwrite"
|
|
588
595
|
).parquet(
|
|
@@ -596,7 +603,9 @@ class NestedCohortBuilder:
|
|
|
596
603
|
cohort.where('split="test"').write.mode("overwrite").parquet(os.path.join(self._output_data_folder, "test"))
|
|
597
604
|
shutil.rmtree(os.path.join(self._output_data_folder, "temp"))
|
|
598
605
|
else:
|
|
599
|
-
cohort.orderBy(person_id_column, index_date_column).write.mode("overwrite").parquet(
|
|
606
|
+
cohort.orderBy(person_id_column, index_date_column).write.mode("overwrite").parquet(
|
|
607
|
+
os.path.join(self._output_data_folder, "data")
|
|
608
|
+
)
|
|
600
609
|
|
|
601
610
|
def extract_ehr_records_for_cohort(self, cohort: DataFrame):
|
|
602
611
|
"""
|
|
@@ -618,6 +627,25 @@ class NestedCohortBuilder:
|
|
|
618
627
|
aggregate_by_hour=self._aggregate_by_hour,
|
|
619
628
|
)
|
|
620
629
|
|
|
630
|
+
if self._cache_events:
|
|
631
|
+
all_patient_events_dir = os.path.join(self._output_data_folder, "all_patient_events")
|
|
632
|
+
ehr_records.write.mode("overwrite").parquet(
|
|
633
|
+
all_patient_events_dir
|
|
634
|
+
)
|
|
635
|
+
ehr_records = self.spark.read.parquet(
|
|
636
|
+
all_patient_events_dir
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
if self._should_construct_artificial_visits:
|
|
640
|
+
ehr_records, visit_occurrence_with_artificial_visits = construct_artificial_visits(
|
|
641
|
+
ehr_records,
|
|
642
|
+
self._dependency_dict[VISIT_OCCURRENCE],
|
|
643
|
+
spark=self.spark if self._cache_events else None,
|
|
644
|
+
persistence_folder=self._output_data_folder if self._cache_events else None,
|
|
645
|
+
)
|
|
646
|
+
# Refresh the dependency
|
|
647
|
+
self._dependency_dict[VISIT_OCCURRENCE] = visit_occurrence_with_artificial_visits
|
|
648
|
+
|
|
621
649
|
# Duplicate the records for cohorts that allow multiple entries
|
|
622
650
|
ehr_records = ehr_records.alias("ehr").join(
|
|
623
651
|
cohort.alias("cohort"), F.col("ehr.person_id") == F.col("cohort.person_id")
|
|
@@ -628,30 +656,29 @@ class NestedCohortBuilder:
|
|
|
628
656
|
# Only allow the data records that occurred between the index date and the prediction window
|
|
629
657
|
if self._is_population_estimation:
|
|
630
658
|
if self._is_prediction_window_unbounded:
|
|
631
|
-
record_window_filter = F.col("ehr.
|
|
659
|
+
record_window_filter = F.col("ehr.datetime") <= F.current_timestamp()
|
|
632
660
|
else:
|
|
633
|
-
record_window_filter =
|
|
634
|
-
|
|
661
|
+
record_window_filter = (
|
|
662
|
+
F.col("ehr.datetime") <=
|
|
663
|
+
F.expr(f"cohort.index_date - INTERVAL {self._hold_off_window} DAYS + INTERVAL 0.1 SECOND")
|
|
635
664
|
)
|
|
636
665
|
else:
|
|
637
666
|
# For patient level prediction, we remove all records post index date
|
|
638
667
|
if self._is_observation_post_index:
|
|
639
|
-
record_window_filter = F.col("ehr.
|
|
668
|
+
record_window_filter = F.col("ehr.datetime").between(
|
|
640
669
|
F.col("cohort.index_date"),
|
|
641
|
-
F.
|
|
670
|
+
F.expr(f"cohort.index_date + INTERVAL {self._observation_window} DAYS + INTERVAL 0.1 SECOND")
|
|
642
671
|
)
|
|
643
672
|
else:
|
|
644
673
|
if self._is_observation_window_unbounded:
|
|
645
|
-
record_window_filter =
|
|
646
|
-
F.col("
|
|
674
|
+
record_window_filter = (
|
|
675
|
+
F.col("ehr.datetime")
|
|
676
|
+
<= F.expr(f"cohort.index_date - INTERVAL {self._hold_off_window} DAYS + INTERVAL 0.1 SECOND")
|
|
647
677
|
)
|
|
648
678
|
else:
|
|
649
|
-
record_window_filter = F.col("ehr.
|
|
650
|
-
F.
|
|
651
|
-
|
|
652
|
-
self._observation_window + self._hold_off_window,
|
|
653
|
-
),
|
|
654
|
-
F.date_sub(F.col("cohort.index_date"), self._hold_off_window),
|
|
679
|
+
record_window_filter = F.col("ehr.datetime").between(
|
|
680
|
+
F.expr(f"cohort.index_date - INTERVAL {self._observation_window + self._hold_off_window} DAYS"),
|
|
681
|
+
F.expr(f"cohort.index_date - INTERVAL {self._hold_off_window} DAYS + INTERVAL 0.1 SECOND"),
|
|
655
682
|
)
|
|
656
683
|
|
|
657
684
|
# Somehow the dataframe join does not work without using the alias
|
|
@@ -709,6 +736,7 @@ class NestedCohortBuilder:
|
|
|
709
736
|
include_inpatient_hour_token=self._include_inpatient_hour_token,
|
|
710
737
|
spark=self.spark if self._cache_events else None,
|
|
711
738
|
persistence_folder=self._output_data_folder if self._cache_events else None,
|
|
739
|
+
cohort_index=cohort.select("person_id", "cohort_member_id", "index_date")
|
|
712
740
|
)
|
|
713
741
|
|
|
714
742
|
return create_sequence_data(
|
|
@@ -832,4 +860,6 @@ def create_prediction_cohort(
|
|
|
832
860
|
single_contribution=spark_args.single_contribution,
|
|
833
861
|
exclude_features=spark_args.exclude_features,
|
|
834
862
|
meds_format=spark_args.meds_format,
|
|
863
|
+
cache_events=spark_args.cache_events,
|
|
864
|
+
should_construct_artificial_visits=spark_args.should_construct_artificial_visits,
|
|
835
865
|
).build()
|
|
@@ -20,8 +20,7 @@ person_ids_to_exclude_observation AS
|
|
|
20
20
|
JOIN global_temp.{observation_exclusion_concepts} AS oec
|
|
21
21
|
ON o.observation_concept_id = oec.concept_id
|
|
22
22
|
)
|
|
23
|
-
SELECT
|
|
24
|
-
distinct
|
|
23
|
+
SELECT DISTINCT
|
|
25
24
|
c.person_id,
|
|
26
25
|
c.index_date,
|
|
27
26
|
c.visit_occurrence_id
|
|
@@ -29,10 +28,18 @@ FROM
|
|
|
29
28
|
(
|
|
30
29
|
SELECT DISTINCT
|
|
31
30
|
vo.person_id,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
vo.visit_occurrence_id,
|
|
32
|
+
CASE
|
|
33
|
+
WHEN co.condition_start_datetime < vo.visit_start_datetime AND datediff(vo.visit_start_datetime, co.condition_start_datetime) <= 1
|
|
34
|
+
THEN to_timestamp(concat(date_format(vo.visit_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
35
|
+
ELSE to_timestamp(concat(date_format(co.condition_start_date, 'yyyy-MM-dd'), ' 23:59:00'), 'yyyy-MM-dd HH:mm:ss')
|
|
36
|
+
END AS index_date,
|
|
37
|
+
ROW_NUMBER() OVER(
|
|
38
|
+
PARTITION BY co.person_id
|
|
39
|
+
ORDER BY co.condition_start_datetime,
|
|
40
|
+
co.condition_start_date,
|
|
41
|
+
co.visit_occurrence_id
|
|
42
|
+
) as r_number
|
|
36
43
|
FROM global_temp.condition_occurrence AS co
|
|
37
44
|
JOIN global_temp.{diabetes_inclusion_concepts} AS ie
|
|
38
45
|
ON co.condition_concept_id = ie.concept_id
|
|
@@ -43,7 +50,9 @@ JOIN person_ids_to_include_drug AS d
|
|
|
43
50
|
ON c.person_id = d.person_id
|
|
44
51
|
LEFT JOIN person_ids_to_exclude_observation AS eo
|
|
45
52
|
ON c.person_id = eo.person_id AND c.index_date > eo.observation_date
|
|
46
|
-
WHERE eo.person_id IS NULL
|
|
53
|
+
WHERE eo.person_id IS NULL
|
|
54
|
+
AND c.r_number = 1
|
|
55
|
+
AND c.index_date >= '{date_lower_bound}'
|
|
47
56
|
"""
|
|
48
57
|
|
|
49
58
|
DIABETES_INCLUSION = [443238, 201820, 442793, 4016045]
|
|
@@ -2,4 +2,5 @@ from .artificial_time_token_decorator import AttEventDecorator
|
|
|
2
2
|
from .death_event_decorator import DeathEventDecorator
|
|
3
3
|
from .clinical_event_decorator import ClinicalEventDecorator
|
|
4
4
|
from .demographic_event_decorator import DemographicEventDecorator
|
|
5
|
+
from .prediction_token_decorator import PredictionEventDecorator
|
|
5
6
|
from .patient_event_decorator_base import time_token_func, get_att_function, AttType
|