PICdb-MEDS 0.0.1__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Robin van de Water
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: PICdb-MEDS
3
+ Version: 0.0.1
4
+ Summary: An ETL pipeline to extract the Paediatric Intensive Care (PIC) database into the MEDS format.
5
+ Author-email: Robin van de Water <rpv2114@cumc.columbia.edu>
6
+ Project-URL: Homepage, https://github.com/rvandewater/PICdb_MEDS
7
+ Project-URL: Issues, https://github.com/rvandewater/PICdb_MEDS/issues
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: <3.14,>=3.11.4
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: meds-extract[download]<0.8,>=0.7.0
15
+ Dynamic: license-file
16
+
17
+ # PICdb MEDS Extraction ETL
18
+
19
+ <!-- Placeholders until available: the PyPI badges resolve once PICdb-MEDS is published; replace
20
+ CODECOV_TOKEN_PLACEHOLDER with the repo's Codecov badge token and zenodo.XXXXXXX with its Zenodo DOI. -->
21
+
22
+ [![PyPI - Version](https://img.shields.io/pypi/v/PICdb-MEDS)](https://pypi.org/project/PICdb-MEDS/)
23
+ [![codecov](https://codecov.io/gh/rvandewater/PICdb_MEDS/graph/badge.svg?token=CODECOV_TOKEN_PLACEHOLDER)](https://codecov.io/gh/rvandewater/PICdb_MEDS)
24
+ [![tests](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/synthetic-etl.yaml/badge.svg)](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/synthetic-etl.yaml)
25
+ [![code-quality](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/code-quality-main.yaml/badge.svg)](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/code-quality-main.yaml)
26
+ ![python](https://img.shields.io/badge/python-%3E%3D3.11.4%2C%20%3C3.14-blue?logo=python&logoColor=white)
27
+ ![Static Badge](https://img.shields.io/badge/MEDS-0.4.1-blue)
28
+ [![license](https://img.shields.io/badge/License-MIT-green.svg?labelColor=gray)](https://github.com/rvandewater/PICdb_MEDS#license)
29
+ [![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/rvandewater/PICdb_MEDS/pulls)
30
+ [![contributors](https://img.shields.io/github/contributors/rvandewater/PICdb_MEDS.svg)](https://github.com/rvandewater/PICdb_MEDS/graphs/contributors)
31
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.XXXXXXX.svg)](https://doi.org/10.5281/zenodo.XXXXXXX)
32
+
33
+ This pipeline extracts the [Paediatric Intensive Care (PIC) database v1.1.0](https://physionet.org/content/picdb/1.1.0/)
34
+ from PhysioNet into the [MEDS format](https://medical-event-data-standard.github.io/). PIC holds 12,881
35
+ neonatal and paediatric patients and 13,449 hospital admissions from the Children's Hospital of Zhejiang
36
+ University School of Medicine (2010–2018). It was built from the
37
+ [ETL_MEDS_Template](https://github.com/Medical-Event-Data-Standard/ETL_MEDS_Template) and uses the
38
+ config-only layout introduced by [MEDS-Extract](https://github.com/mmcdermott/MEDS_extract) 0.7.
39
+
40
+ ## Usage
41
+
42
+ PIC is a credentialed dataset. You need a PhysioNet account that has signed the PIC data use agreement.
43
+
44
+ ```bash
45
+ pip install git+https://github.com/rvandewater/PICdb_MEDS.git
46
+ export DATASET_DOWNLOAD_USERNAME=$PHYSIONET_USERNAME
47
+ export DATASET_DOWNLOAD_PASSWORD=$PHYSIONET_PASSWORD
48
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR
49
+ ```
50
+
51
+ When you run this, the program will:
52
+
53
+ 1. Download the v1.1.0 tables (`V1.1.0/*.csv`, about 1.2 GB) from PhysioNet into
54
+ `$MEDS_OUTPUT_DIR/.meds_extract_run/raw_input`. Files that already exist and match their checksums
55
+ are skipped, so an interrupted download resumes. Pass `download_dest_dir=$RAW_INPUT_DIR` to keep the
56
+ raw data somewhere durable and reuse it across runs.
57
+ 2. Build the MEDS cohort from those files and write it to `$MEDS_OUTPUT_DIR` (`data/` and `metadata/`).
58
+ All transformations, joins and metadata extraction are declared in
59
+ [`src/PICdb_MEDS/event_configs.yaml`](src/PICdb_MEDS/event_configs.yaml).
60
+
61
+ If you already have the PhysioNet release on disk, skip the download and point `input_dir` at the
62
+ release root, the directory that contains `V1.1.0/`:
63
+
64
+ ```bash
65
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR \
66
+ do_download=false input_dir=/path/to/paediatric-intensive-care-database-1.1.0
67
+ ```
68
+
69
+ To parallelize the stages, pass a runner file:
70
+
71
+ ```bash
72
+ printf 'parallelize:\n n_workers: 8\n launcher: joblib\n' >runner.yaml
73
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR stage_runner_fp=runner.yaml
74
+ ```
75
+
76
+ Run `meds-extract-run --help` for every option.
77
+
78
+ ## How this ETL is defined
79
+
80
+ The package contains no Python. The whole ETL is one MESSY (MEDS-Extract Specification Syntax YAML)
81
+ file, [`src/PICdb_MEDS/event_configs.yaml`](src/PICdb_MEDS/event_configs.yaml). It declares:
82
+
83
+ - **`sources:`**: where the raw data lives (the PhysioNet release, restricted to `V1.1.0/*.csv`).
84
+ - **`etl:`**: the dataset name and sharding options.
85
+ - **One block per raw table**: how each row becomes one or more MEDS events, and which dictionary
86
+ tables describe the resulting codes.
87
+
88
+ `pyproject.toml` registers the file with MEDS-Extract's `MEDS_extract.pipelines` entry-point group under
89
+ the name `PICdb`. That registration is what makes `spec=PICdb` work. No pre-MEDS step is needed: every
90
+ PIC table already carries `SUBJECT_ID`, and every timestamp has the same format.
91
+
92
+ ## Events
93
+
94
+ | Table | Event codes | Notes |
95
+ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
96
+ | `PATIENTS` | `GENDER//{gender}`, `MEDS_BIRTH`, `MEDS_DEATH` | Death time is the earliest `ADMISSIONS.DEATHTIME`, falling back to `DOD`. |
97
+ | `ADMISSIONS` | `HOSPITAL_ADMISSION//{dept}`, `HOSPITAL_DISCHARGE//{dept}`, `INSURANCE//…`, `ETHNICITY//…`, `ADMISSION_DIAGNOSIS//ICD10_CN//{code}` | ED times equal admit/discharge times in every row, so there are no separate ED events. |
98
+ | `ICUSTAYS` | `ICU_ADMISSION//{careunit}`, `ICU_DISCHARGE//{careunit}` | |
99
+ | `DIAGNOSES_ICD` | `DIAGNOSIS//ICD10_CN//{code}` | Placed at hospital discharge. `seq_num` and `diag_category` are kept as columns. |
100
+ | `LABEVENTS` | `LAB//{itemid}//{unit}` | `numeric_value`, `text_value` and `flag` are kept. |
101
+ | `CHARTEVENTS` | `CHART//{itemid}//{unit}` | |
102
+ | `INPUTEVENTS` | `FLUID_INPUT//{unit}` | PIC records only fluid intake amounts here, with no item ID. |
103
+ | `OUTPUTEVENTS` | `OUTPUT//{itemid}//{unit}` | |
104
+ | `PRESCRIPTIONS` | `MEDICATION//START//{drug}//{dose unit}`, `MEDICATION//END//{drug}` | Uses the English drug name. The dose is the `numeric_value`. |
105
+ | `MICROBIOLOGYEVENTS` | `MICROBIOLOGY//SPECIMEN//{spec_itemid}`, `MICROBIOLOGY//ORGANISM//{org_itemid}`, `MICROBIOLOGY//SUSCEPTIBILITY//{ab_itemid}//{S/I/R…}` | The MIC dilution is the `numeric_value`. Organism and specimen IDs are kept as columns. |
106
+ | `OR_EXAM_REPORTS` | `EXAM//{type}//{item}` | Uses the exam time, or the report time when the exam time is missing. |
107
+ | `EMR_SYMPTOMS` | `SYMPTOM//{symptom}//{+/-}` | Symptoms extracted by NLP from clinical notes. |
108
+ | `SURGERY_INFO` | `SURGERY//START//{name}`, `SURGERY//END//{name}`, `ANESTHESIA//START//{method}`, `ANESTHESIA//END//{method}` | |
109
+ | `SURGERY_VITAL_SIGNS` | `SURGERY_VITAL//{itemid}` | Intra-operative monitoring. Units are in the code metadata (`unit`). |
110
+
111
+ A missing unit or susceptibility interpretation becomes `UNK` in the code. A row with a missing
112
+ identifying component (for example, no organism) produces no event for that component.
113
+
114
+ ### Code metadata
115
+
116
+ `metadata/codes.parquet` links codes to PIC's dictionary tables:
117
+
118
+ - **`description`**: the English label from `D_ITEMS`, `D_LABITEMS` or `D_ICD_DIAGNOSES`.
119
+ - **`parent_codes`**: `LOINC/…` for lab items with a well-formed LOINC code, and `ICD10/…` for
120
+ diagnoses whose mapped code is a valid 3- or 4-character WHO ICD-10 code. PIC's own extended codes
121
+ (7+ characters) have no parent.
122
+ - **Chinese source terms**: kept in their own columns (`title_cn`, `label_cn`, `drug_name_cn`,
123
+ `org_name_cn`, `spec_type_desc_cn`, `ab_name_cn`, `symptom_name_cn`). Codes are always built from the
124
+ English or ID columns.
125
+ - **Extra dictionary fields**: `fluid`, `category` and `unit`.
126
+
127
+ ### Data notes
128
+
129
+ - **Shifted dates.** Dates are shifted 50–100 years into the future per patient. Years between 2049 and
130
+ 2119 are expected, and intervals within a patient are preserved.
131
+ - **Release layout.** The v1.1.0 release ships the current tables under `V1.1.0/`. The gzipped files at
132
+ the release root are the superseded v1.0.0 tables, and this ETL does not read them.
133
+ - **Swapped column names.** In `PRESCRIPTIONS`, the CSV header `DRUG_NAME` holds the Chinese name and
134
+ `DRUG_NAME_EN` the English one. The bundled SQL scripts name these columns differently.
135
+ - **Many-to-many microbiology IDs.** Item IDs and their Chinese names do not map one-to-one, so codes
136
+ use the item IDs. Expect MEDS-Extract warnings that some codes have several `*_cn` values; those
137
+ values are aggregated into lists.
138
+ - **Uninformative columns.** `LANGUAGE`, `RELIGION` and `MARITAL_STATUS` hold a single value across the
139
+ release and are not extracted.
140
+ - **Local diagnosis codes.** Diagnoses use PIC's extended Chinese ICD-10 codes (`ICD10_CN`), so they do
141
+ not yet line up with standard ICD-10 codes in other datasets. Valid standard codes are attached as
142
+ `parent_codes`. Mapping equivalent codes to standard ICD-10 needs a MEDS-Extract feature; see
143
+ [#1](https://github.com/rvandewater/PICdb_MEDS/issues/1).
144
+
145
+ ## Testing
146
+
147
+ PIC has no open demo release. Instead, `tests/e2e_synthetic_test.py` writes a few fully synthetic rows
148
+ with PIC's exact headers and layout, runs `meds-extract-run spec=PICdb` over them, and checks the
149
+ events, times, values and code metadata it produces.
150
+
151
+ ```bash
152
+ uv sync --group dev
153
+ uv run pytest tests/ -v
154
+ uv run pre-commit run --all-files
155
+ ```
156
+
157
+ ## Citation
158
+
159
+ If you use this ETL, please cite the PIC database and its descriptor paper:
160
+
161
+ - Li, H., Zeng, X., & Yu, G. (2020). *Paediatric Intensive Care database* (version 1.1.0). PhysioNet.
162
+ https://doi.org/10.13026/32x9-wv38
163
+ - Zeng, X., Yu, G., Lu, Y. et al. PIC, a paediatric-specific intensive care database. *Sci Data* 7, 14
164
+ (2020). https://doi.org/10.1038/s41597-020-0355-4
165
+
166
+ See also [`CITATION.cff`](CITATION.cff).
@@ -0,0 +1,150 @@
1
+ # PICdb MEDS Extraction ETL
2
+
3
+ <!-- Placeholders until available: the PyPI badges resolve once PICdb-MEDS is published; replace
4
+ CODECOV_TOKEN_PLACEHOLDER with the repo's Codecov badge token and zenodo.XXXXXXX with its Zenodo DOI. -->
5
+
6
+ [![PyPI - Version](https://img.shields.io/pypi/v/PICdb-MEDS)](https://pypi.org/project/PICdb-MEDS/)
7
+ [![codecov](https://codecov.io/gh/rvandewater/PICdb_MEDS/graph/badge.svg?token=CODECOV_TOKEN_PLACEHOLDER)](https://codecov.io/gh/rvandewater/PICdb_MEDS)
8
+ [![tests](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/synthetic-etl.yaml/badge.svg)](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/synthetic-etl.yaml)
9
+ [![code-quality](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/code-quality-main.yaml/badge.svg)](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/code-quality-main.yaml)
10
+ ![python](https://img.shields.io/badge/python-%3E%3D3.11.4%2C%20%3C3.14-blue?logo=python&logoColor=white)
11
+ ![Static Badge](https://img.shields.io/badge/MEDS-0.4.1-blue)
12
+ [![license](https://img.shields.io/badge/License-MIT-green.svg?labelColor=gray)](https://github.com/rvandewater/PICdb_MEDS#license)
13
+ [![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/rvandewater/PICdb_MEDS/pulls)
14
+ [![contributors](https://img.shields.io/github/contributors/rvandewater/PICdb_MEDS.svg)](https://github.com/rvandewater/PICdb_MEDS/graphs/contributors)
15
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.XXXXXXX.svg)](https://doi.org/10.5281/zenodo.XXXXXXX)
16
+
17
+ This pipeline extracts the [Paediatric Intensive Care (PIC) database v1.1.0](https://physionet.org/content/picdb/1.1.0/)
18
+ from PhysioNet into the [MEDS format](https://medical-event-data-standard.github.io/). PIC holds 12,881
19
+ neonatal and paediatric patients and 13,449 hospital admissions from the Children's Hospital of Zhejiang
20
+ University School of Medicine (2010–2018). It was built from the
21
+ [ETL_MEDS_Template](https://github.com/Medical-Event-Data-Standard/ETL_MEDS_Template) and uses the
22
+ config-only layout introduced by [MEDS-Extract](https://github.com/mmcdermott/MEDS_extract) 0.7.
23
+
24
+ ## Usage
25
+
26
+ PIC is a credentialed dataset. You need a PhysioNet account that has signed the PIC data use agreement.
27
+
28
+ ```bash
29
+ pip install git+https://github.com/rvandewater/PICdb_MEDS.git
30
+ export DATASET_DOWNLOAD_USERNAME=$PHYSIONET_USERNAME
31
+ export DATASET_DOWNLOAD_PASSWORD=$PHYSIONET_PASSWORD
32
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR
33
+ ```
34
+
35
+ When you run this, the program will:
36
+
37
+ 1. Download the v1.1.0 tables (`V1.1.0/*.csv`, about 1.2 GB) from PhysioNet into
38
+ `$MEDS_OUTPUT_DIR/.meds_extract_run/raw_input`. Files that already exist and match their checksums
39
+ are skipped, so an interrupted download resumes. Pass `download_dest_dir=$RAW_INPUT_DIR` to keep the
40
+ raw data somewhere durable and reuse it across runs.
41
+ 2. Build the MEDS cohort from those files and write it to `$MEDS_OUTPUT_DIR` (`data/` and `metadata/`).
42
+ All transformations, joins and metadata extraction are declared in
43
+ [`src/PICdb_MEDS/event_configs.yaml`](src/PICdb_MEDS/event_configs.yaml).
44
+
45
+ If you already have the PhysioNet release on disk, skip the download and point `input_dir` at the
46
+ release root, the directory that contains `V1.1.0/`:
47
+
48
+ ```bash
49
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR \
50
+ do_download=false input_dir=/path/to/paediatric-intensive-care-database-1.1.0
51
+ ```
52
+
53
+ To parallelize the stages, pass a runner file:
54
+
55
+ ```bash
56
+ printf 'parallelize:\n n_workers: 8\n launcher: joblib\n' >runner.yaml
57
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR stage_runner_fp=runner.yaml
58
+ ```
59
+
60
+ Run `meds-extract-run --help` for every option.
61
+
62
+ ## How this ETL is defined
63
+
64
+ The package contains no Python. The whole ETL is one MESSY (MEDS-Extract Specification Syntax YAML)
65
+ file, [`src/PICdb_MEDS/event_configs.yaml`](src/PICdb_MEDS/event_configs.yaml). It declares:
66
+
67
+ - **`sources:`**: where the raw data lives (the PhysioNet release, restricted to `V1.1.0/*.csv`).
68
+ - **`etl:`**: the dataset name and sharding options.
69
+ - **One block per raw table**: how each row becomes one or more MEDS events, and which dictionary
70
+ tables describe the resulting codes.
71
+
72
+ `pyproject.toml` registers the file with MEDS-Extract's `MEDS_extract.pipelines` entry-point group under
73
+ the name `PICdb`. That registration is what makes `spec=PICdb` work. No pre-MEDS step is needed: every
74
+ PIC table already carries `SUBJECT_ID`, and every timestamp has the same format.
75
+
76
+ ## Events
77
+
78
+ | Table | Event codes | Notes |
79
+ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
80
+ | `PATIENTS` | `GENDER//{gender}`, `MEDS_BIRTH`, `MEDS_DEATH` | Death time is the earliest `ADMISSIONS.DEATHTIME`, falling back to `DOD`. |
81
+ | `ADMISSIONS` | `HOSPITAL_ADMISSION//{dept}`, `HOSPITAL_DISCHARGE//{dept}`, `INSURANCE//…`, `ETHNICITY//…`, `ADMISSION_DIAGNOSIS//ICD10_CN//{code}` | ED times equal admit/discharge times in every row, so there are no separate ED events. |
82
+ | `ICUSTAYS` | `ICU_ADMISSION//{careunit}`, `ICU_DISCHARGE//{careunit}` | |
83
+ | `DIAGNOSES_ICD` | `DIAGNOSIS//ICD10_CN//{code}` | Placed at hospital discharge. `seq_num` and `diag_category` are kept as columns. |
84
+ | `LABEVENTS` | `LAB//{itemid}//{unit}` | `numeric_value`, `text_value` and `flag` are kept. |
85
+ | `CHARTEVENTS` | `CHART//{itemid}//{unit}` | |
86
+ | `INPUTEVENTS` | `FLUID_INPUT//{unit}` | PIC records only fluid intake amounts here, with no item ID. |
87
+ | `OUTPUTEVENTS` | `OUTPUT//{itemid}//{unit}` | |
88
+ | `PRESCRIPTIONS` | `MEDICATION//START//{drug}//{dose unit}`, `MEDICATION//END//{drug}` | Uses the English drug name. The dose is the `numeric_value`. |
89
+ | `MICROBIOLOGYEVENTS` | `MICROBIOLOGY//SPECIMEN//{spec_itemid}`, `MICROBIOLOGY//ORGANISM//{org_itemid}`, `MICROBIOLOGY//SUSCEPTIBILITY//{ab_itemid}//{S/I/R…}` | The MIC dilution is the `numeric_value`. Organism and specimen IDs are kept as columns. |
90
+ | `OR_EXAM_REPORTS` | `EXAM//{type}//{item}` | Uses the exam time, or the report time when the exam time is missing. |
91
+ | `EMR_SYMPTOMS` | `SYMPTOM//{symptom}//{+/-}` | Symptoms extracted by NLP from clinical notes. |
92
+ | `SURGERY_INFO` | `SURGERY//START//{name}`, `SURGERY//END//{name}`, `ANESTHESIA//START//{method}`, `ANESTHESIA//END//{method}` | |
93
+ | `SURGERY_VITAL_SIGNS` | `SURGERY_VITAL//{itemid}` | Intra-operative monitoring. Units are in the code metadata (`unit`). |
94
+
95
+ A missing unit or susceptibility interpretation becomes `UNK` in the code. A row with a missing
96
+ identifying component (for example, no organism) produces no event for that component.
97
+
98
+ ### Code metadata
99
+
100
+ `metadata/codes.parquet` links codes to PIC's dictionary tables:
101
+
102
+ - **`description`**: the English label from `D_ITEMS`, `D_LABITEMS` or `D_ICD_DIAGNOSES`.
103
+ - **`parent_codes`**: `LOINC/…` for lab items with a well-formed LOINC code, and `ICD10/…` for
104
+ diagnoses whose mapped code is a valid 3- or 4-character WHO ICD-10 code. PIC's own extended codes
105
+ (7+ characters) have no parent.
106
+ - **Chinese source terms**: kept in their own columns (`title_cn`, `label_cn`, `drug_name_cn`,
107
+ `org_name_cn`, `spec_type_desc_cn`, `ab_name_cn`, `symptom_name_cn`). Codes are always built from the
108
+ English or ID columns.
109
+ - **Extra dictionary fields**: `fluid`, `category` and `unit`.
110
+
111
+ ### Data notes
112
+
113
+ - **Shifted dates.** Dates are shifted 50–100 years into the future per patient. Years between 2049 and
114
+ 2119 are expected, and intervals within a patient are preserved.
115
+ - **Release layout.** The v1.1.0 release ships the current tables under `V1.1.0/`. The gzipped files at
116
+ the release root are the superseded v1.0.0 tables, and this ETL does not read them.
117
+ - **Swapped column names.** In `PRESCRIPTIONS`, the CSV header `DRUG_NAME` holds the Chinese name and
118
+ `DRUG_NAME_EN` the English one. The bundled SQL scripts name these columns differently.
119
+ - **Many-to-many microbiology IDs.** Item IDs and their Chinese names do not map one-to-one, so codes
120
+ use the item IDs. Expect MEDS-Extract warnings that some codes have several `*_cn` values; those
121
+ values are aggregated into lists.
122
+ - **Uninformative columns.** `LANGUAGE`, `RELIGION` and `MARITAL_STATUS` hold a single value across the
123
+ release and are not extracted.
124
+ - **Local diagnosis codes.** Diagnoses use PIC's extended Chinese ICD-10 codes (`ICD10_CN`), so they do
125
+ not yet line up with standard ICD-10 codes in other datasets. Valid standard codes are attached as
126
+ `parent_codes`. Mapping equivalent codes to standard ICD-10 needs a MEDS-Extract feature; see
127
+ [#1](https://github.com/rvandewater/PICdb_MEDS/issues/1).
128
+
129
+ ## Testing
130
+
131
+ PIC has no open demo release. Instead, `tests/e2e_synthetic_test.py` writes a few fully synthetic rows
132
+ with PIC's exact headers and layout, runs `meds-extract-run spec=PICdb` over them, and checks the
133
+ events, times, values and code metadata it produces.
134
+
135
+ ```bash
136
+ uv sync --group dev
137
+ uv run pytest tests/ -v
138
+ uv run pre-commit run --all-files
139
+ ```
140
+
141
+ ## Citation
142
+
143
+ If you use this ETL, please cite the PIC database and its descriptor paper:
144
+
145
+ - Li, H., Zeng, X., & Yu, G. (2020). *Paediatric Intensive Care database* (version 1.1.0). PhysioNet.
146
+ https://doi.org/10.13026/32x9-wv38
147
+ - Zeng, X., Yu, G., Lu, Y. et al. PIC, a paediatric-specific intensive care database. *Sci Data* 7, 14
148
+ (2020). https://doi.org/10.1038/s41597-020-0355-4
149
+
150
+ See also [`CITATION.cff`](CITATION.cff).
@@ -0,0 +1,68 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "PICdb-MEDS"
7
+ # Bump with `uv version --bump patch|minor|major`, then tag the commit with the same version.
8
+ version = "0.0.1"
9
+ authors = [
10
+ { name="Robin van de Water", email="rpv2114@cumc.columbia.edu" },
11
+ ]
12
+ description = "An ETL pipeline to extract the Paediatric Intensive Care (PIC) database into the MEDS format."
13
+ readme = "README.md"
14
+ # Mirrors MEDS-Extract 0.7's own interpreter range; a looser range here admits interpreters it
15
+ # cannot be installed on.
16
+ requires-python = ">=3.11.4,<3.14"
17
+ classifiers = [
18
+ "Programming Language :: Python :: 3",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ ]
22
+ # This package ships no Python: the whole ETL is `event_configs.yaml`, run by MEDS-Extract's own
23
+ # `meds-extract-run`. The `[download]` extra adds `meds-extract-download`, which the runner spawns to
24
+ # stage the raw data from PhysioNet. MEDS-transforms, polars and hydra arrive through it at the
25
+ # versions it fences.
26
+ #
27
+ # The floor is 0.7.0: this config uses `_self` metadata blocks, aggregated joins and regex
28
+ # conditionals in `parent_codes`, none of which exist before 0.7.
29
+ dependencies = [
30
+ "meds-extract[download]>=0.7.0,<0.8",
31
+ ]
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "pre-commit~=3.8",
36
+ "ruff>=0.11,<1.0",
37
+ "pytest~=9.0",
38
+ "shfmt-py==3.12.0.2",
39
+ ]
40
+
41
+ [project.entry-points."MEDS_extract.pipelines"]
42
+ PICdb = "PICdb_MEDS:event_configs.yaml"
43
+
44
+ [project.urls]
45
+ Homepage = "https://github.com/rvandewater/PICdb_MEDS"
46
+ Issues = "https://github.com/rvandewater/PICdb_MEDS/issues"
47
+
48
+ [tool.ruff]
49
+ target-version = "py311"
50
+ line-length = 110
51
+
52
+ [tool.ruff.lint]
53
+ select = [
54
+ "E", # pycodestyle
55
+ "F", # pyflakes
56
+ "I", # isort
57
+ "UP", # pyupgrade
58
+ "B", # flake8-bugbear
59
+ "C4", # flake8-comprehensions
60
+ "RUF", # Ruff-specific rules
61
+ "SIM", # flake8-simplify
62
+ ]
63
+ ignore = [
64
+ "SIM108", # ternary operator suggestions
65
+ ]
66
+
67
+ [tool.ruff.lint.per-file-ignores]
68
+ "__init__.py" = ["F401"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ """The PIC (Paediatric Intensive Care database) MEDS ETL — a configuration package, not a library.
2
+
3
+ This distribution ships no code. Its entire content is ``PICdb_MEDS/event_configs.yaml``, a MESSY
4
+ (MEDS-Extract Specification Syntax YAML) document declaring where the raw PIC data comes from and how
5
+ every event is extracted from it. ``pyproject.toml`` registers that file with MEDS-Extract's
6
+ ``MEDS_extract.pipelines`` entry-point group under the name ``PICdb``, so the ETL runs as::
7
+
8
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR
9
+
10
+ This package exists so the YAML is addressable as package data —
11
+ ``importlib.resources.files("PICdb_MEDS")`` — from an installed wheel. Nothing here is importable API.
12
+ """
@@ -0,0 +1,166 @@
1
+ Metadata-Version: 2.4
2
+ Name: PICdb-MEDS
3
+ Version: 0.0.1
4
+ Summary: An ETL pipeline to extract the Paediatric Intensive Care (PIC) database into the MEDS format.
5
+ Author-email: Robin van de Water <rpv2114@cumc.columbia.edu>
6
+ Project-URL: Homepage, https://github.com/rvandewater/PICdb_MEDS
7
+ Project-URL: Issues, https://github.com/rvandewater/PICdb_MEDS/issues
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: <3.14,>=3.11.4
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: meds-extract[download]<0.8,>=0.7.0
15
+ Dynamic: license-file
16
+
17
+ # PICdb MEDS Extraction ETL
18
+
19
+ <!-- Placeholders until available: the PyPI badges resolve once PICdb-MEDS is published; replace
20
+ CODECOV_TOKEN_PLACEHOLDER with the repo's Codecov badge token and zenodo.XXXXXXX with its Zenodo DOI. -->
21
+
22
+ [![PyPI - Version](https://img.shields.io/pypi/v/PICdb-MEDS)](https://pypi.org/project/PICdb-MEDS/)
23
+ [![codecov](https://codecov.io/gh/rvandewater/PICdb_MEDS/graph/badge.svg?token=CODECOV_TOKEN_PLACEHOLDER)](https://codecov.io/gh/rvandewater/PICdb_MEDS)
24
+ [![tests](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/synthetic-etl.yaml/badge.svg)](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/synthetic-etl.yaml)
25
+ [![code-quality](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/code-quality-main.yaml/badge.svg)](https://github.com/rvandewater/PICdb_MEDS/actions/workflows/code-quality-main.yaml)
26
+ ![python](https://img.shields.io/badge/python-%3E%3D3.11.4%2C%20%3C3.14-blue?logo=python&logoColor=white)
27
+ ![Static Badge](https://img.shields.io/badge/MEDS-0.4.1-blue)
28
+ [![license](https://img.shields.io/badge/License-MIT-green.svg?labelColor=gray)](https://github.com/rvandewater/PICdb_MEDS#license)
29
+ [![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/rvandewater/PICdb_MEDS/pulls)
30
+ [![contributors](https://img.shields.io/github/contributors/rvandewater/PICdb_MEDS.svg)](https://github.com/rvandewater/PICdb_MEDS/graphs/contributors)
31
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.XXXXXXX.svg)](https://doi.org/10.5281/zenodo.XXXXXXX)
32
+
33
+ This pipeline extracts the [Paediatric Intensive Care (PIC) database v1.1.0](https://physionet.org/content/picdb/1.1.0/)
34
+ from PhysioNet into the [MEDS format](https://medical-event-data-standard.github.io/). PIC holds 12,881
35
+ neonatal and paediatric patients and 13,449 hospital admissions from the Children's Hospital of Zhejiang
36
+ University School of Medicine (2010–2018). It was built from the
37
+ [ETL_MEDS_Template](https://github.com/Medical-Event-Data-Standard/ETL_MEDS_Template) and uses the
38
+ config-only layout introduced by [MEDS-Extract](https://github.com/mmcdermott/MEDS_extract) 0.7.
39
+
40
+ ## Usage
41
+
42
+ PIC is a credentialed dataset. You need a PhysioNet account that has signed the PIC data use agreement.
43
+
44
+ ```bash
45
+ pip install git+https://github.com/rvandewater/PICdb_MEDS.git
46
+ export DATASET_DOWNLOAD_USERNAME=$PHYSIONET_USERNAME
47
+ export DATASET_DOWNLOAD_PASSWORD=$PHYSIONET_PASSWORD
48
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR
49
+ ```
50
+
51
+ When you run this, the program will:
52
+
53
+ 1. Download the v1.1.0 tables (`V1.1.0/*.csv`, about 1.2 GB) from PhysioNet into
54
+ `$MEDS_OUTPUT_DIR/.meds_extract_run/raw_input`. Files that already exist and match their checksums
55
+ are skipped, so an interrupted download resumes. Pass `download_dest_dir=$RAW_INPUT_DIR` to keep the
56
+ raw data somewhere durable and reuse it across runs.
57
+ 2. Build the MEDS cohort from those files and write it to `$MEDS_OUTPUT_DIR` (`data/` and `metadata/`).
58
+ All transformations, joins and metadata extraction are declared in
59
+ [`src/PICdb_MEDS/event_configs.yaml`](src/PICdb_MEDS/event_configs.yaml).
60
+
61
+ If you already have the PhysioNet release on disk, skip the download and point `input_dir` at the
62
+ release root, the directory that contains `V1.1.0/`:
63
+
64
+ ```bash
65
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR \
66
+ do_download=false input_dir=/path/to/paediatric-intensive-care-database-1.1.0
67
+ ```
68
+
69
+ To parallelize the stages, pass a runner file:
70
+
71
+ ```bash
72
+ printf 'parallelize:\n n_workers: 8\n launcher: joblib\n' >runner.yaml
73
+ meds-extract-run spec=PICdb output_dir=$MEDS_OUTPUT_DIR stage_runner_fp=runner.yaml
74
+ ```
75
+
76
+ Run `meds-extract-run --help` for every option.
77
+
78
+ ## How this ETL is defined
79
+
80
+ The package contains no Python. The whole ETL is one MESSY (MEDS-Extract Specification Syntax YAML)
81
+ file, [`src/PICdb_MEDS/event_configs.yaml`](src/PICdb_MEDS/event_configs.yaml). It declares:
82
+
83
+ - **`sources:`**: where the raw data lives (the PhysioNet release, restricted to `V1.1.0/*.csv`).
84
+ - **`etl:`**: the dataset name and sharding options.
85
+ - **One block per raw table**: how each row becomes one or more MEDS events, and which dictionary
86
+ tables describe the resulting codes.
87
+
88
+ `pyproject.toml` registers the file with MEDS-Extract's `MEDS_extract.pipelines` entry-point group under
89
+ the name `PICdb`. That registration is what makes `spec=PICdb` work. No pre-MEDS step is needed: every
90
+ PIC table already carries `SUBJECT_ID`, and every timestamp has the same format.
91
+
92
+ ## Events
93
+
94
+ | Table | Event codes | Notes |
95
+ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
96
+ | `PATIENTS` | `GENDER//{gender}`, `MEDS_BIRTH`, `MEDS_DEATH` | Death time is the earliest `ADMISSIONS.DEATHTIME`, falling back to `DOD`. |
97
+ | `ADMISSIONS` | `HOSPITAL_ADMISSION//{dept}`, `HOSPITAL_DISCHARGE//{dept}`, `INSURANCE//…`, `ETHNICITY//…`, `ADMISSION_DIAGNOSIS//ICD10_CN//{code}` | ED times equal admit/discharge times in every row, so there are no separate ED events. |
98
+ | `ICUSTAYS` | `ICU_ADMISSION//{careunit}`, `ICU_DISCHARGE//{careunit}` | |
99
+ | `DIAGNOSES_ICD` | `DIAGNOSIS//ICD10_CN//{code}` | Placed at hospital discharge. `seq_num` and `diag_category` are kept as columns. |
100
+ | `LABEVENTS` | `LAB//{itemid}//{unit}` | `numeric_value`, `text_value` and `flag` are kept. |
101
+ | `CHARTEVENTS` | `CHART//{itemid}//{unit}` | |
102
+ | `INPUTEVENTS` | `FLUID_INPUT//{unit}` | PIC records only fluid intake amounts here, with no item ID. |
103
+ | `OUTPUTEVENTS` | `OUTPUT//{itemid}//{unit}` | |
104
+ | `PRESCRIPTIONS` | `MEDICATION//START//{drug}//{dose unit}`, `MEDICATION//END//{drug}` | Uses the English drug name. The dose is the `numeric_value`. |
105
+ | `MICROBIOLOGYEVENTS` | `MICROBIOLOGY//SPECIMEN//{spec_itemid}`, `MICROBIOLOGY//ORGANISM//{org_itemid}`, `MICROBIOLOGY//SUSCEPTIBILITY//{ab_itemid}//{S/I/R…}` | The MIC dilution is the `numeric_value`. Organism and specimen IDs are kept as columns. |
106
+ | `OR_EXAM_REPORTS` | `EXAM//{type}//{item}` | Uses the exam time, or the report time when the exam time is missing. |
107
+ | `EMR_SYMPTOMS` | `SYMPTOM//{symptom}//{+/-}` | Symptoms extracted by NLP from clinical notes. |
108
+ | `SURGERY_INFO` | `SURGERY//START//{name}`, `SURGERY//END//{name}`, `ANESTHESIA//START//{method}`, `ANESTHESIA//END//{method}` | |
109
+ | `SURGERY_VITAL_SIGNS` | `SURGERY_VITAL//{itemid}` | Intra-operative monitoring. Units are in the code metadata (`unit`). |
110
+
111
+ A missing unit or susceptibility interpretation becomes `UNK` in the code. A row with a missing
112
+ identifying component (for example, no organism) produces no event for that component.
113
+
114
+ ### Code metadata
115
+
116
+ `metadata/codes.parquet` links codes to PIC's dictionary tables:
117
+
118
+ - **`description`**: the English label from `D_ITEMS`, `D_LABITEMS` or `D_ICD_DIAGNOSES`.
119
+ - **`parent_codes`**: `LOINC/…` for lab items with a well-formed LOINC code, and `ICD10/…` for
120
+ diagnoses whose mapped code is a valid 3- or 4-character WHO ICD-10 code. PIC's own extended codes
121
+ (7+ characters) have no parent.
122
+ - **Chinese source terms**: kept in their own columns (`title_cn`, `label_cn`, `drug_name_cn`,
123
+ `org_name_cn`, `spec_type_desc_cn`, `ab_name_cn`, `symptom_name_cn`). Codes are always built from the
124
+ English or ID columns.
125
+ - **Extra dictionary fields**: `fluid`, `category` and `unit`.
126
+
127
+ ### Data notes
128
+
129
+ - **Shifted dates.** Dates are shifted 50–100 years into the future per patient. Years between 2049 and
130
+ 2119 are expected, and intervals within a patient are preserved.
131
+ - **Release layout.** The v1.1.0 release ships the current tables under `V1.1.0/`. The gzipped files at
132
+ the release root are the superseded v1.0.0 tables, and this ETL does not read them.
133
+ - **Swapped column names.** In `PRESCRIPTIONS`, the CSV header `DRUG_NAME` holds the Chinese name and
134
+ `DRUG_NAME_EN` the English one. The bundled SQL scripts name these columns differently.
135
+ - **Many-to-many microbiology IDs.** Item IDs and their Chinese names do not map one-to-one, so codes
136
+ use the item IDs. Expect MEDS-Extract warnings that some codes have several `*_cn` values; those
137
+ values are aggregated into lists.
138
+ - **Uninformative columns.** `LANGUAGE`, `RELIGION` and `MARITAL_STATUS` hold a single value across the
139
+ release and are not extracted.
140
+ - **Local diagnosis codes.** Diagnoses use PIC's extended Chinese ICD-10 codes (`ICD10_CN`), so they do
141
+ not yet line up with standard ICD-10 codes in other datasets. Valid standard codes are attached as
142
+ `parent_codes`. Mapping equivalent codes to standard ICD-10 needs a MEDS-Extract feature; see
143
+ [#1](https://github.com/rvandewater/PICdb_MEDS/issues/1).
144
+
145
+ ## Testing
146
+
147
+ PIC has no open demo release. Instead, `tests/e2e_synthetic_test.py` writes a few fully synthetic rows
148
+ with PIC's exact headers and layout, runs `meds-extract-run spec=PICdb` over them, and checks the
149
+ events, times, values and code metadata it produces.
150
+
151
+ ```bash
152
+ uv sync --group dev
153
+ uv run pytest tests/ -v
154
+ uv run pre-commit run --all-files
155
+ ```
156
+
157
+ ## Citation
158
+
159
+ If you use this ETL, please cite the PIC database and its descriptor paper:
160
+
161
+ - Li, H., Zeng, X., & Yu, G. (2020). *Paediatric Intensive Care database* (version 1.1.0). PhysioNet.
162
+ https://doi.org/10.13026/32x9-wv38
163
+ - Zeng, X., Yu, G., Lu, Y. et al. PIC, a paediatric-specific intensive care database. *Sci Data* 7, 14
164
+ (2020). https://doi.org/10.1038/s41597-020-0355-4
165
+
166
+ See also [`CITATION.cff`](CITATION.cff).
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/PICdb_MEDS/__init__.py
5
+ src/PICdb_MEDS.egg-info/PKG-INFO
6
+ src/PICdb_MEDS.egg-info/SOURCES.txt
7
+ src/PICdb_MEDS.egg-info/dependency_links.txt
8
+ src/PICdb_MEDS.egg-info/entry_points.txt
9
+ src/PICdb_MEDS.egg-info/requires.txt
10
+ src/PICdb_MEDS.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [MEDS_extract.pipelines]
2
+ PICdb = PICdb_MEDS:event_configs.yaml
@@ -0,0 +1 @@
1
+ meds-extract[download]<0.8,>=0.7.0
@@ -0,0 +1 @@
1
+ PICdb_MEDS