diff --git a/.gitignore b/.gitignore index f0c1ff431..316679579 100644 --- a/.gitignore +++ b/.gitignore @@ -154,4 +154,8 @@ test-resources/meds_demo/ .venv312/ # Tool caches -.ruff_cache/ \ No newline at end of file +.ruff_cache/ + +# Generated Synthea outputs and dataset caches +.artifacts/ +examples/.artifacts/ diff --git a/docs/api/datasets.rst b/docs/api/datasets.rst index f629bef8a..e382aa497 100644 --- a/docs/api/datasets.rst +++ b/docs/api/datasets.rst @@ -288,6 +288,7 @@ Available Datasets datasets/pyhealth.datasets.ISRUCDataset datasets/pyhealth.datasets.MIMICExtractDataset datasets/pyhealth.datasets.OMOPDataset + datasets/pyhealth.datasets.SyntheaCSVDataset datasets/pyhealth.datasets.DREAMTDataset datasets/pyhealth.datasets.SHHSDataset datasets/pyhealth.datasets.SleepEDFDataset diff --git a/docs/api/datasets/pyhealth.datasets.SyntheaCSVDataset.rst b/docs/api/datasets/pyhealth.datasets.SyntheaCSVDataset.rst new file mode 100644 index 000000000..fef45f827 --- /dev/null +++ b/docs/api/datasets/pyhealth.datasets.SyntheaCSVDataset.rst @@ -0,0 +1,169 @@ +pyhealth.datasets.SyntheaCSVDataset +=================================== + +Loads the CSV export of `Synthea `_, +a synthetic patient simulator, through the standard PyHealth dataset API. +Synthea data is fully synthetic, so it needs no credentialing and is useful for +prototyping pipelines before you have access to MIMIC or eICU. + +Getting Data +------------ + +``root`` is a directory of Synthea CSV files. There are two ways to get one: + +- **Generate it** with :class:`~pyhealth.models.Synthea` (requires Java 17+; + see its Setup section). This lets you choose the population size, seed, + location, and age range. +- **Download a pre-generated sample** from the + `Synthea downloads page `_ and unzip it. + No Java is needed; pick the CSV variant. + +.. code-block:: python + + from pyhealth.datasets import SyntheaCSVDataset + from pyhealth.models import Synthea + + csv_dir = Synthea("./synthea-output").generate(population=100, seed=42) + # or: csv_dir = "/path/to/unzipped/sample/csv" # directory with patients.csv + + dataset = SyntheaCSVDataset( + csv_dir, + tables=["conditions", "medications", "observations"], + ) + dataset.stats() + +How Synthea Differs From Other PyHealth Datasets +------------------------------------------------ + +**What Synthea writes is very different from MIMIC; what PyHealth gives you +back is the same.** The differences to watch for are in the raw files and in +the medical codes, not in the dataset object. + +Raw output: many wide tables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A Synthea run writes about 18 CSV files. Each has many columns, every row is +keyed by a UUID, and the files include synthetic billing and insurance data. +For example, the first rows of ``conditions.csv`` and ``observations.csv``: + +.. code-block:: text + + START,STOP,PATIENT,ENCOUNTER,SYSTEM,CODE,DESCRIPTION + 2004-07-17,,ba419d35-...-eebf02485a56,ba419d35-...-4d3d0f870810,SNOMED-CT,224299000,Received higher education (finding) + + DATE,PATIENT,ENCOUNTER,CATEGORY,CODE,DESCRIPTION,VALUE,UNITS,TYPE + 2023-08-12T20:03:25Z,ba419d35-...-eebf02485a56,ba419d35-...-b4779d5cf14b,laboratory,4548-4,Hemoglobin A1c/Hemoglobin.total in Blood,6.3,%,numeric + +Not every file can be loaded, because PyHealth organizes events by patient: + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Files + - Loaded? + * - ``patients``, ``encounters``, ``conditions``, ``medications``, + ``observations``, ``procedures``, ``immunizations``, ``careplans``, + ``allergies``, ``devices``, ``imaging_studies``, ``supplies``, + ``payer_transitions`` + - Yes, by default. Files Synthea did not emit (no rows) are skipped. + * - ``claims``, ``claims_transactions`` + - Only when listed in ``tables``. They are large and mostly billing + detail. + * - ``organizations``, ``providers``, ``payers`` + - No. They describe institutions, not patients, so they have no patient + column. + +After loading: the standard PyHealth event table +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Like every PyHealth dataset, ``SyntheaCSVDataset`` turns each row of each table +into one **event** with three fixed columns, ``patient_id``, ``event_type`` (the +table name), and ``timestamp``, plus one ``/`` column per kept +attribute. Columns belonging to other tables are null for that event: + +.. code-block:: text + + patient_id event_type timestamp conditions/code conditions/description observations/code observations/value ... + ba419d35-... conditions 2004-07-17 00:00:00 224299000 Received higher ... null null + ba419d35-... observations 2023-08-12 20:03:25 null null 4548-4 6.3 + +Through the patient API, the table prefix is dropped: + +.. code-block:: python + + patient = dataset.get_patient(dataset.unique_patient_ids[0]) + for event in patient.get_events(event_type="conditions"): + print(event.timestamp, event.code, event.description) + + numeric_obs = patient.get_events( + event_type="observations", + filters=[("type", "==", "numeric")], + ) + +The columns kept per table are listed in +``pyhealth/datasets/configs/synthea_csv.yaml``. Columns that identify a person +(name, SSN, street address, coordinates) are not loaded. + +Medical codes: SNOMED-CT, RxNorm, LOINC, CVX +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This difference matters most. MIMIC codes diagnoses with ICD-9/ICD-10 and drugs +with NDC; Synthea uses different vocabularies: + +.. list-table:: + :header-rows: 1 + :widths: 30 25 45 + + * - Table + - Code system + - Example ``code`` + * - ``conditions`` + - SNOMED-CT + - ``714628002`` (Prediabetes) + * - ``procedures``, ``encounters``, ``careplans``, ``devices``, + ``supplies`` + - SNOMED-CT + - ``252160004`` (Standard pregnancy test) + * - ``medications`` + - RxNorm + - ``849574`` (Naproxen sodium 220 MG Oral Tablet) + * - ``observations`` + - LOINC + - ``4548-4`` (Hemoglobin A1c) + * - ``immunizations`` + - CVX + - ``140`` (Influenza, split virus, trivalent, PF) + * - ``allergies`` + - Mostly SNOMED-CT; drug allergies use RxNorm. The ``system`` column is + often ``Unknown``, so do not rely on it. + - ``84489001`` (Mold) + +As a result: + +- Built-in tasks written for MIMIC (for example + :class:`~pyhealth.tasks.MortalityPredictionMIMIC3`) read ICD columns and do + not work on Synthea. Write a task for Synthea instead (see :doc:`../tasks`). +- ICD-based code mappings in :mod:`pyhealth.medcode` (such as ICD to CCS) do + not apply. RxNorm codes are supported by ``pyhealth.medcode.RxNorm``. +- Every code comes with a human-readable ``description`` column. + +Other differences +^^^^^^^^^^^^^^^^^ + +- **Each patient has a ``patients`` event at their birth date.** Demographics + (``gender``, ``race``, ``deathdate``, ...) are attributes of that event. +- **Visits are not a separate level.** Each clinical event has an + ``encounter`` attribute holding the UUID of its encounter; group events by it + to rebuild visits. +- **Lab values are strings.** ``observations/value`` holds numbers and text + answers in one column; ``observations/type`` (``numeric`` or ``text``) says + which. +- **Timestamps mix dates and date-times across tables** (for example + ``conditions`` has dates, ``observations`` has date-times). PyHealth parses + both; date-only events get a midnight timestamp. + +.. autoclass:: pyhealth.datasets.SyntheaCSVDataset + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/api/models.rst b/docs/api/models.rst index 278de1fe8..e636b6c48 100644 --- a/docs/api/models.rst +++ b/docs/api/models.rst @@ -245,6 +245,7 @@ API Reference models/pyhealth.models.PromptEHR models/pyhealth.models.MedGAN models/pyhealth.models.CorGAN + models/pyhealth.models.Synthea models/pyhealth.models.SDOH models/pyhealth.models.VisionEmbeddingModel models/pyhealth.models.TextEmbedding diff --git a/docs/api/models/pyhealth.models.Synthea.rst b/docs/api/models/pyhealth.models.Synthea.rst new file mode 100644 index 000000000..66737bfc8 --- /dev/null +++ b/docs/api/models/pyhealth.models.Synthea.rst @@ -0,0 +1,154 @@ +pyhealth.models.Synthea +=================================== + +`Synthea `_ is a rule-based +synthetic patient simulator from MITRE. Unlike the trained generators (HALO, +MedGAN, ...), Synthea is not fitted to data; it simulates patient lifetimes from +clinical care modules. This class runs the pinned Synthea release as a Java +subprocess and writes CSV files to disk. It subclasses +:class:`~pyhealth.models.BaseModel` for API consistency but has no trainable +parameters and no forward pass; load its output with +:class:`~pyhealth.datasets.SyntheaCSVDataset`. + +Quick Start +----------- + +The constructor only sets up the generator: where output goes, and where to +find Java and the Synthea JAR. Nothing runs until +:meth:`~pyhealth.models.Synthea.generate`, which takes the population settings +and returns the directory of CSV files that +:class:`~pyhealth.datasets.SyntheaCSVDataset` takes as ``root``. + +.. code-block:: python + + from pyhealth.datasets import SyntheaCSVDataset + from pyhealth.models import Synthea + + synthea = Synthea("./synthea-output") # setup only; nothing runs yet + + csv_dir = synthea.generate(population=100, seed=42) # runs Java + dataset = SyntheaCSVDataset(csv_dir, tables=["conditions", "medications"]) + dataset.stats() + + # The same instance can generate as many populations as you like. + larger = synthea.generate(population=1000, seed=42) + ohio = synthea.generate(population=100, seed=42, state="Ohio") + +Each combination of settings is written to its own subdirectory of +``output_dir``, so populations never overwrite each other:: + + synthea-output/ + └── 3f9c...e1/ # SHA-256 of the generation settings + └── csv/ + ├── patients.csv + ├── conditions.csv + └── ... + +Calling ``generate()`` again with the same settings returns the existing +directory without rerunning Synthea, which can take minutes. Pass +``overwrite=True`` to force a fresh run. If you omit ``seed``, a random seed is +chosen and logged, so every call produces a new population; pass a seed when +you need reproducible output. + +See :doc:`../datasets/pyhealth.datasets.SyntheaCSVDataset` for what the CSV +files contain and how they differ from other PyHealth datasets. + +Setup +----- + +You do **not** need to download or build Synthea yourself. The only manual +step is installing Java. + +**1. Install Java 17 or newer.** ``pip install pyhealth`` does not provide it. +Any JDK distribution works, for example: + +- conda: ``conda install -c conda-forge openjdk`` +- macOS (Homebrew): ``brew install openjdk`` +- Ubuntu/Debian: ``sudo apt install openjdk-17-jre-headless`` +- Windows or any platform: an installer from + `Eclipse Temurin `_ + +Check the installation with ``java -version``; the first line should report +version 17 or higher. + +**2. Generate.** On the first call to :meth:`~pyhealth.models.Synthea.generate`, +PyHealth downloads the pinned Synthea release JAR (v4.0.0, about 200 MB), +verifies its SHA-256 checksum, and caches it under the PyHealth cache +directory: + +- Linux: ``~/.cache/pyhealth/synthea/`` +- macOS: ``~/Library/Caches/pyhealth/synthea/`` +- Windows: ``%LOCALAPPDATA%\pyhealth\pyhealth\Cache\synthea\`` + +Later runs reuse the cached JAR. + +**Offline machines or a custom Synthea build.** Download +``synthea-with-dependencies.jar`` from the +`Synthea releases page `_ +on a machine with internet access, copy it over, and pass its path: + +.. code-block:: python + + synthea = Synthea( + "./synthea-output", + jar_path="/path/to/synthea-with-dependencies.jar", + auto_download=False, + ) + +**How Java is found.** The first of these that exists is used: + +1. the ``java_path`` argument, +2. ``$JAVA_HOME/bin/java``, +3. ``java`` on ``PATH``. + +If none is found, or it is older than Java 17, +:meth:`~pyhealth.models.Synthea.generate` raises a ``RuntimeError`` naming the +executable and its version. Constructing the class and calling +:meth:`~pyhealth.models.Synthea.build_argv` do not need Java. + +Choosing What to Generate +------------------------- + +Synthea's command-line options are arguments of +:meth:`~pyhealth.models.Synthea.generate` (``population``, ``seed``, +``state``, ``city``, ``gender``, ``age_range``, ``reference_date``, ...). +Anything from Synthea's +`synthea.properties `_ +file goes in ``synthea_config``. Use +:meth:`~pyhealth.models.Synthea.get_available_config` to list the properties +the JAR accepts. + +.. code-block:: python + + csv_dir = synthea.generate( + population=500, + seed=7, + state="Massachusetts", + age_range="40-80", + synthea_config={ + "generate.only_alive_patients": True, + "exporter.years_of_history": 10, + }, + ) + +CSV export is switched on automatically and other export formats (FHIR, C-CDA, +...) are switched off. ``synthea_config`` cannot change which exporters run or +where output is written; use ``output_dir`` for that. + +To check the exact command without running anything (no Java needed), call +:meth:`~pyhealth.models.Synthea.build_argv` with the same settings:: + + synthea.build_argv("java", "synthea.jar", population=500, seed=7) + +Reference: + Walonoski, J., Kramer, M., Nichols, J., Quina, A., Moesel, C., Hall, D., + Duffett, C., Dube, K., Gallagher, T., & McLachlan, S. (2018). + *Synthea: An approach, method, and software mechanism for generating + synthetic patients and the synthetic electronic health care record.* + Journal of the American Medical Informatics Association, 25(3), 230-238. + https://doi.org/10.1093/jamia/ocx079 + +.. autoclass:: pyhealth.models.Synthea + :members: + :undoc-members: + :show-inheritance: diff --git a/examples/synthea_end_to_end.ipynb b/examples/synthea_end_to_end.ipynb new file mode 100644 index 000000000..033ae340a --- /dev/null +++ b/examples/synthea_end_to_end.ipynb @@ -0,0 +1,4038 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "35a52037", + "metadata": {}, + "source": [ + "# Synthea CSV integration: complete walkthrough\n", + "\n", + "**Prerequisite:** Java 17+ must be installed (on `PATH`, via `JAVA_HOME`, or passed as `java_path=`). PyHealth does not install it. You do not need to download Synthea itself: the pinned JAR is downloaded and checksum-verified on the first `generate()` call. See the *Setup* section of the `pyhealth.models.Synthea` API docs for Java install commands and offline use.\n", + "\n", + "This notebook walks through the CSV integration:\n", + "\n", + "- discovering supported `synthea.properties` before generating anything;\n", + "- setting up one `Synthea` generator and previewing its command;\n", + "- generating several populations from that one instance, with reuse and `overwrite`;\n", + "- every `generate()` argument and the Synthea CLI flag it maps to;\n", + "- loading generated CSV through `SyntheaCSVDataset`; and\n", + "- how Synthea data differs from other PyHealth datasets." + ] + }, + { + "cell_type": "markdown", + "id": "3c0e7de5", + "metadata": {}, + "source": [ + "## Prerequisites\n", + "\n", + "Java 17 or newer and, on first use, internet access to download the pinned Synthea JAR (about 200 MB) unless `jar_path` is supplied. Each live generation below takes roughly 15 seconds for a handful of patients." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "4aa97e71", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:27:43.314093Z", + "iopub.status.busy": "2026-10-08T18:27:43.313996Z", + "iopub.status.idle": "2026-10-08T18:27:48.212906Z", + "shell.execute_reply": "2026-10-08T18:27:48.212293Z" + } + }, + "outputs": [], + "source": [ + "import inspect\n", + "import shlex\n", + "from pathlib import Path\n", + "\n", + "from pyhealth.datasets import SyntheaCSVDataset\n", + "from pyhealth.models import Synthea" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "fcf49eae", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:27:48.214956Z", + "iopub.status.busy": "2026-10-08T18:27:48.214596Z", + "iopub.status.idle": "2026-10-08T18:27:48.219182Z", + "shell.execute_reply": "2026-10-08T18:27:48.218702Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "PosixPath('/home/soham/PyHealth/examples/.artifacts/synthea_csv')" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "artifact_root = Path(\".artifacts/synthea_csv\").resolve()\n", + "artifact_root.mkdir(parents=True, exist_ok=True)\n", + "artifact_root" + ] + }, + { + "cell_type": "markdown", + "id": "1d37cd2b", + "metadata": {}, + "source": [ + "## Public generator API\n", + "\n", + "| Member | Purpose |\n", + "|---|---|\n", + "| `Synthea(output_dir, ...)` | Set up the generator: output location, Java and JAR discovery, timeout. Generates nothing. |\n", + "| `generate(...)` | Generate a population from per-call settings and return its CSV directory; reuses existing output for identical settings unless `overwrite=True` |\n", + "| `build_argv(java, jar, ...)` | Build the Java/Synthea command for given settings without running it |\n", + "| `get_available_config()` | Return properties supported by the selected Synthea JAR |" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "73b7f2d8", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:27:48.220460Z", + "iopub.status.busy": "2026-10-08T18:27:48.220351Z", + "iopub.status.idle": "2026-10-08T18:27:48.230171Z", + "shell.execute_reply": "2026-10-08T18:27:48.229674Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'Synthea': \"(output_dir: 'str | Path', java_path: 'str | Path | None' = None, jar_path: 'str | Path | None' = None, auto_download: 'bool' = True, timeout: 'float | None' = None) -> 'None'\",\n", + " 'generate': \"(self, population: 'int | None' = None, seed: 'int | None' = None, state: 'str | None' = None, city: 'str | None' = None, clinician_seed: 'int | None' = None, single_person_seed: 'int | None' = None, reference_date: 'str | None' = None, end_date: 'str | None' = None, gender: 'str | None' = None, age_range: 'str | None' = None, overflow_population: 'bool | None' = None, local_config_path: 'str | Path | None' = None, local_modules_dir: 'str | Path | None' = None, initial_population_snapshot_path: 'str | Path | None' = None, updated_population_snapshot_path: 'str | Path | None' = None, update_time_period: 'int | None' = None, fixed_record_path: 'str | Path | None' = None, keep_matching_patients_path: 'str | Path | None' = None, synthea_config: 'Mapping[str, str | int | float | bool] | None' = None, overwrite: 'bool' = False) -> 'Path'\",\n", + " 'build_argv': \"(self, java: 'Path', jar: 'Path', **settings) -> 'list[str]'\",\n", + " 'get_available_config': \"(jar_path: 'str | Path | None' = None, auto_download: 'bool' = True, pattern: 'str' = '*') -> 'dict[str, str | None]'\"}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "{\n", + " \"Synthea\": str(inspect.signature(Synthea)),\n", + " \"generate\": str(inspect.signature(Synthea.generate)),\n", + " \"build_argv\": str(inspect.signature(Synthea.build_argv)),\n", + " \"get_available_config\": str(inspect.signature(Synthea.get_available_config)),\n", + "}" + ] + }, + { + "cell_type": "markdown", + "id": "c64dfbe4", + "metadata": {}, + "source": [ + "## 1. Discover supported Synthea configuration\n", + "\n", + "These class methods work before a generator exists. `pattern` uses shell-style glob matching. Discovery reads `synthea.properties` from the actual pinned or explicitly supplied JAR, so it reflects the Synthea version that will run." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4ce9fcae", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:27:48.231476Z", + "iopub.status.busy": "2026-10-08T18:27:48.231343Z", + "iopub.status.idle": "2026-10-08T18:27:48.696833Z", + "shell.execute_reply": "2026-10-08T18:27:48.696339Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('generate.append_numbers_to_person_names', 'true'),\n", + " ('generate.birthweights.default_file', 'birthweights.csv'),\n", + " ('generate.birthweights.logging', 'false'),\n", + " ('generate.costs.default_device_cost', '0.00'),\n", + " ('generate.costs.default_encounter_cost', '125.00'),\n", + " ('generate.costs.default_immunization_cost', '136.00'),\n", + " ('generate.costs.default_lab_cost', '100.00'),\n", + " ('generate.costs.default_medication_cost', '255.00'),\n", + " ('generate.costs.default_procedure_cost', '500.00'),\n", + " ('generate.costs.default_supply_cost', '0.00')]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "generation_properties = Synthea.get_available_config(\n", + " pattern=\"generate.*\"\n", + ")\n", + "list(sorted(generation_properties.items()))[:10]" + ] + }, + { + "cell_type": "markdown", + "id": "940f68ae", + "metadata": {}, + "source": [ + "The examples below use several ordinary Synthea properties:\n", + "\n", + "- `generate.thread_pool_size=1` makes generation serial, so output is deterministic for a fixed seed;\n", + "- `generate.only_alive_patients=true` keeps only patients alive at the simulation end;\n", + "- `exporter.years_of_history=5` limits exported history;\n", + "- `exporter.csv.folder_per_run=false` keeps CSV files directly under the CSV directory; and\n", + "- `exporter.csv.append_mode=false` replaces rather than appends to prior CSV files.\n", + "\n", + "CSV exporter selection and the output directory are managed by the wrapper and are rejected if placed in `synthea_config`." + ] + }, + { + "cell_type": "markdown", + "id": "c1696b40", + "metadata": {}, + "source": [ + "## 2. Set up the generator\n", + "\n", + "The constructor holds only setup. Population settings are passed to `generate()`, so one instance can produce any number of populations." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "b4d12cee", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:27:48.698377Z", + "iopub.status.busy": "2026-10-08T18:27:48.698251Z", + "iopub.status.idle": "2026-10-08T18:27:48.701733Z", + "shell.execute_reply": "2026-10-08T18:27:48.701082Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "Synthea(output_dir='/home/soham/PyHealth/examples/.artifacts/synthea_csv/generated')" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "synthea = Synthea(output_dir=artifact_root / \"generated\", timeout=900)\n", + "synthea" + ] + }, + { + "cell_type": "markdown", + "id": "be0bb097", + "metadata": {}, + "source": [ + "`build_argv()` shows the exact command `generate()` would run for some settings, without needing Java. Each distinct combination of settings is written to its own fingerprinted directory under `output_dir`, visible as `--exporter.baseDirectory`." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "2bb3d472", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:27:48.702802Z", + "iopub.status.busy": "2026-10-08T18:27:48.702690Z", + "iopub.status.idle": "2026-10-08T18:27:48.711444Z", + "shell.execute_reply": "2026-10-08T18:27:48.710968Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "java -jar synthea.jar --exporter.baseDirectory=/home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4 --exporter.bfd.export=false --exporter.ccda.export=false --exporter.cdw.export=false --exporter.clinical_note.export=false --exporter.cpcds.export=false --exporter.csv.append_mode=false --exporter.csv.export=true --exporter.csv.folder_per_run=false --exporter.fhir.export=false --exporter.fhir_dstu2.export=false --exporter.fhir_stu3.export=false --exporter.json.export=false --exporter.symptoms.csv.export=false --exporter.symptoms.text.export=false --exporter.text.export=false --exporter.years_of_history=5 --generate.only_alive_patients=true --generate.thread_pool_size=1 -s 42 -cs 43 -p 10 -r 20240101 -g F -a 30-40 -o false Massachusetts Boston\n" + ] + } + ], + "source": [ + "common_config = {\n", + " \"generate.thread_pool_size\": 1,\n", + " \"generate.only_alive_patients\": True,\n", + " \"exporter.years_of_history\": 5,\n", + " \"exporter.csv.folder_per_run\": False,\n", + " \"exporter.csv.append_mode\": False,\n", + "}\n", + "settings = dict(\n", + " population=10,\n", + " seed=42,\n", + " clinician_seed=43,\n", + " reference_date=\"20240101\",\n", + " gender=\"F\",\n", + " age_range=\"30-40\",\n", + " overflow_population=False,\n", + " state=\"Massachusetts\",\n", + " city=\"Boston\",\n", + " synthea_config=common_config,\n", + ")\n", + "\n", + "preview_argv = synthea.build_argv(Path(\"java\"), Path(\"synthea.jar\"), **settings)\n", + "print(shlex.join(preview_argv))" + ] + }, + { + "cell_type": "markdown", + "id": "cb349ed8", + "metadata": {}, + "source": [ + "## 3. Generate several populations from one instance\n", + "\n", + "Each call runs Synthea once and returns the CSV directory. Different settings go to different directories, so populations never overwrite each other." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "42310199", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:27:48.712607Z", + "iopub.status.busy": "2026-10-08T18:27:48.712423Z", + "iopub.status.idle": "2026-10-08T18:28:14.758012Z", + "shell.execute_reply": "2026-10-08T18:28:14.757505Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Synthea: /home/soham/.local/jvm/jdk-17.0.20.1+1/bin/java -jar /home/soham/.cache/pyhealth/synthea/synthea-with-dependencies-v4.0.0.jar --exporter.baseDirectory=/home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4 --exporter.bfd.export=false --exporter.ccda.export=false --exporter.cdw.export=false --exporter.clinical_note.export=false --exporter.cpcds.export=false --exporter.csv.append_mode=false --exporter.csv.export=true --exporter.csv.folder_per_run=false --exporter.fhir.export=false --exporter.fhir_dstu2.export=false --exporter.fhir_stu3.export=false --exporter.json.export=false --exporter.symptoms.csv.export=false --exporter.symptoms.text.export=false --exporter.text.export=false --exporter.years_of_history=5 --generate.only_alive_patients=true --generate.thread_pool_size=1 -s 42 -cs 43 -p 10 -r 20240101 -g F -a 30-40 -o false Massachusetts Boston\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "org.mitre.synthea.X12.ExporterAdaptor\n", + "org.mitre.synthea.X12.ExporterAdaptor\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "SLF4J: No SLF4J providers were found.\n", + "SLF4J: Defaulting to no-operation (NOP) logger implementation\n", + "SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanned 92 modules and 449 submodules.\n", + "Loading submodule modules/allergies/allergy_panel.json\n", + "Loading submodule modules/allergies/drug_allergy_incidence.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/allergies/environmental_allergy_incidence.json\n", + "Loading submodule modules/allergies/food_allergy_incidence.json\n", + "Loading submodule modules/allergies/immunotherapy.json\n", + "Loading submodule modules/allergies/outgrow_env_allergies.json\n", + "Loading submodule modules/allergies/outgrow_food_allergies.json\n", + "Loading submodule modules/allergies/severe_allergic_reaction.json\n", + "Loading submodule modules/anemia/anemia_sub.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/breast_cancer/chemotherapy_breast.json\n", + "Loading submodule modules/breast_cancer/hormone_diagnosis.json\n", + "Loading submodule modules/breast_cancer/hormonetherapy_breast.json\n", + "Loading submodule modules/breast_cancer/surgery_therapy_breast.json\n", + "Loading submodule modules/breast_cancer/tnm_diagnosis.json\n", + "Loading submodule modules/contraceptives/clear_contraceptive.json\n", + "Loading submodule modules/contraceptives/female_sterilization.json\n", + "Loading submodule modules/contraceptives/implant_contraceptive.json\n", + "Loading submodule modules/contraceptives/injectable_contraceptive.json\n", + "Loading submodule modules/contraceptives/intrauterine_device.json\n", + "Loading submodule modules/contraceptives/male_sterilization.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/contraceptives/oral_contraceptive.json\n", + "Loading submodule modules/contraceptives/patch_contraceptive.json\n", + "Loading submodule modules/contraceptives/ring_contraceptive.json\n", + "Loading submodule modules/covid19/admission.json\n", + "Loading submodule modules/covid19/determine_risk.json\n", + "Loading Lookup Table: covid-19-severity-outcomes.csv\n", + "Loading Lookup Table: covid-19-survival-outcomes.csv\n", + "Loading submodule modules/covid19/diagnose_bacterial_infection.json\n", + "Loading submodule modules/covid19/diagnose_blood_clot.json\n", + "Loading submodule modules/covid19/end_outcomes.json\n", + "Loading submodule modules/covid19/end_symptoms.json\n", + "Loading submodule modules/covid19/infection.json\n", + "Loading submodule modules/covid19/measurements_daily.json\n", + "Loading submodule modules/covid19/measurements_frequent.json\n", + "Loading submodule modules/covid19/measurements_vitals.json\n", + "Loading submodule modules/covid19/medications.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/covid19/nonsurvivor_lab_values.json\n", + "Loading submodule modules/covid19/outcomes.json\n", + "Loading submodule modules/covid19/supplies_hospitalization.json\n", + "Loading submodule modules/covid19/supplies_icu.json\n", + "Loading submodule modules/covid19/supplies_intubation.json\n", + "Loading submodule modules/covid19/survivor_lab_values.json\n", + "Loading submodule modules/covid19/symptoms.json\n", + "Loading submodule modules/covid19/treat_blood_clot.json\n", + "Loading submodule modules/dental/dental_emergency.json\n", + "Loading submodule modules/dental/dental_encounter.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/dental_hospital.json\n", + "Loading submodule modules/dental/dental_telephone.json\n", + "Loading submodule modules/dental/diagnosis/cavity.json\n", + "Loading submodule modules/dental/diagnosis/dental disorder.json\n", + "Loading submodule modules/dental/diagnosis/gingivitis.json\n", + "Loading submodule modules/dental/diagnosis/periodontitis.json\n", + "Loading submodule modules/dental/diagnosis/plaque.json\n", + "Loading submodule modules/dental/end_dental_diagnoses.json\n", + "Loading submodule modules/dental/procedure/d01.json\n", + "Loading submodule modules/dental/procedure/d02.json\n", + "Loading submodule modules/dental/procedure/d03.json\n", + "Loading submodule modules/dental/procedure/d04.json\n", + "Loading submodule modules/dental/procedure/d05.json\n", + "Loading submodule modules/dental/procedure/d06.json\n", + "Loading submodule modules/dental/procedure/d09.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d11.json\n", + "Loading submodule modules/dental/procedure/d12.json\n", + "Loading submodule modules/dental/procedure/d13.json\n", + "Loading submodule modules/dental/procedure/d15.json\n", + "Loading submodule modules/dental/procedure/d19.json\n", + "Loading submodule modules/dental/procedure/d21.json\n", + "Loading submodule modules/dental/procedure/d23.json\n", + "Loading submodule modules/dental/procedure/d25.json\n", + "Loading submodule modules/dental/procedure/d26.json\n", + "Loading submodule modules/dental/procedure/d27.json\n", + "Loading submodule modules/dental/procedure/d29.json\n", + "Loading submodule modules/dental/procedure/d31.json\n", + "Loading submodule modules/dental/procedure/d32.json\n", + "Loading submodule modules/dental/procedure/d33.json\n", + "Loading submodule modules/dental/procedure/d34.json\n", + "Loading submodule modules/dental/procedure/d39.json\n", + "Loading submodule modules/dental/procedure/d42.json\n", + "Loading submodule modules/dental/procedure/d43.json\n", + "Loading submodule modules/dental/procedure/d49.json\n", + "Loading submodule modules/dental/procedure/d51.json\n", + "Loading submodule modules/dental/procedure/d52.json\n", + "Loading submodule modules/dental/procedure/d54.json\n", + "Loading submodule modules/dental/procedure/d55.json\n", + "Loading submodule modules/dental/procedure/d56.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d57.json\n", + "Loading submodule modules/dental/procedure/d58.json\n", + "Loading submodule modules/dental/procedure/d59.json\n", + "Loading submodule modules/dental/procedure/d60.json\n", + "Loading submodule modules/dental/procedure/d61.json\n", + "Loading submodule modules/dental/procedure/d62.json\n", + "Loading submodule modules/dental/procedure/d65.json\n", + "Loading submodule modules/dental/procedure/d66.json\n", + "Loading submodule modules/dental/procedure/d67.json\n", + "Loading submodule modules/dental/procedure/d69.json\n", + "Loading submodule modules/dental/procedure/d71.json\n", + "Loading submodule modules/dental/procedure/d72.json\n", + "Loading submodule modules/dental/procedure/d73.json\n", + "Loading submodule modules/dental/procedure/d74.json\n", + "Loading submodule modules/dental/procedure/d75.json\n", + "Loading submodule modules/dental/procedure/d76.json\n", + "Loading submodule modules/dental/procedure/d77.json\n", + "Loading submodule modules/dental/procedure/d78.json\n", + "Loading submodule modules/dental/procedure/d79.json\n", + "Loading submodule modules/dental/procedure/d80.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d82.json\n", + "Loading submodule modules/dental/procedure/d86.json\n", + "Loading submodule modules/dental/procedure/d89.json\n", + "Loading submodule modules/dental/procedure/d91.json\n", + "Loading submodule modules/dental/procedure/d92.json\n", + "Loading submodule modules/dental/procedure/d93.json\n", + "Loading submodule modules/dental/procedure/d94.json\n", + "Loading submodule modules/dental/procedure/d96.json\n", + "Loading submodule modules/dental/procedure/d99.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_0.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_1.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/dental_idr_cluster_2.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_3.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_4.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c00.json\n", + "Loading submodule modules/dental_idr/diagnosis/c01.json\n", + "Loading submodule modules/dental_idr/diagnosis/c02.json\n", + "Loading submodule modules/dental_idr/diagnosis/c03.json\n", + "Loading submodule modules/dental_idr/diagnosis/c04.json\n", + "Loading submodule modules/dental_idr/diagnosis/c05.json\n", + "Loading submodule modules/dental_idr/diagnosis/c06.json\n", + "Loading submodule modules/dental_idr/diagnosis/c07.json\n", + "Loading submodule modules/dental_idr/diagnosis/c08.json\n", + "Loading submodule modules/dental_idr/diagnosis/c09.json\n", + "Loading submodule modules/dental_idr/diagnosis/c10.json\n", + "Loading submodule modules/dental_idr/diagnosis/c11.json\n", + "Loading submodule modules/dental_idr/diagnosis/c12.json\n", + "Loading submodule modules/dental_idr/diagnosis/c13.json\n", + "Loading submodule modules/dental_idr/diagnosis/c14.json\n", + "Loading submodule modules/dental_idr/diagnosis/c15.json\n", + "Loading submodule modules/dental_idr/diagnosis/c16.json\n", + "Loading submodule modules/dental_idr/diagnosis/c17.json\n", + "Loading submodule modules/dental_idr/diagnosis/c18.json\n", + "Loading submodule modules/dental_idr/diagnosis/c19.json\n", + "Loading submodule modules/dental_idr/diagnosis/c20.json\n", + "Loading submodule modules/dental_idr/diagnosis/c21.json\n", + "Loading submodule modules/dental_idr/diagnosis/c22.json\n", + "Loading submodule modules/dental_idr/diagnosis/c24.json\n", + "Loading submodule modules/dental_idr/diagnosis/c25.json\n", + "Loading submodule modules/dental_idr/diagnosis/c26.json\n", + "Loading submodule modules/dental_idr/diagnosis/c30.json\n", + "Loading submodule modules/dental_idr/diagnosis/c31.json\n", + "Loading submodule modules/dental_idr/diagnosis/c32.json\n", + "Loading submodule modules/dental_idr/diagnosis/c33.json\n", + "Loading submodule modules/dental_idr/diagnosis/c34.json\n", + "Loading submodule modules/dental_idr/diagnosis/c37.json\n", + "Loading submodule modules/dental_idr/diagnosis/c38.json\n", + "Loading submodule modules/dental_idr/diagnosis/c39.json\n", + "Loading submodule modules/dental_idr/diagnosis/c40.json\n", + "Loading submodule modules/dental_idr/diagnosis/c41.json\n", + "Loading submodule modules/dental_idr/diagnosis/c43.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c44.json\n", + "Loading submodule modules/dental_idr/diagnosis/c45.json\n", + "Loading submodule modules/dental_idr/diagnosis/c46.json\n", + "Loading submodule modules/dental_idr/diagnosis/c47.json\n", + "Loading submodule modules/dental_idr/diagnosis/c48.json\n", + "Loading submodule modules/dental_idr/diagnosis/c49.json\n", + "Loading submodule modules/dental_idr/diagnosis/c4a.json\n", + "Loading submodule modules/dental_idr/diagnosis/c50.json\n", + "Loading submodule modules/dental_idr/diagnosis/c51.json\n", + "Loading submodule modules/dental_idr/diagnosis/c53.json\n", + "Loading submodule modules/dental_idr/diagnosis/c54.json\n", + "Loading submodule modules/dental_idr/diagnosis/c56.json\n", + "Loading submodule modules/dental_idr/diagnosis/c57.json\n", + "Loading submodule modules/dental_idr/diagnosis/c61.json\n", + "Loading submodule modules/dental_idr/diagnosis/c62.json\n", + "Loading submodule modules/dental_idr/diagnosis/c63.json\n", + "Loading submodule modules/dental_idr/diagnosis/c64.json\n", + "Loading submodule modules/dental_idr/diagnosis/c65.json\n", + "Loading submodule modules/dental_idr/diagnosis/c66.json\n", + "Loading submodule modules/dental_idr/diagnosis/c67.json\n", + "Loading submodule modules/dental_idr/diagnosis/c68.json\n", + "Loading submodule modules/dental_idr/diagnosis/c69.json\n", + "Loading submodule modules/dental_idr/diagnosis/c71.json\n", + "Loading submodule modules/dental_idr/diagnosis/c72.json\n", + "Loading submodule modules/dental_idr/diagnosis/c73.json\n", + "Loading submodule modules/dental_idr/diagnosis/c74.json\n", + "Loading submodule modules/dental_idr/diagnosis/c75.json\n", + "Loading submodule modules/dental_idr/diagnosis/c76.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c77.json\n", + "Loading submodule modules/dental_idr/diagnosis/c78.json\n", + "Loading submodule modules/dental_idr/diagnosis/c79.json\n", + "Loading submodule modules/dental_idr/diagnosis/c7a.json\n", + "Loading submodule modules/dental_idr/diagnosis/c7b.json\n", + "Loading submodule modules/dental_idr/diagnosis/c80.json\n", + "Loading submodule modules/dental_idr/diagnosis/c81.json\n", + "Loading submodule modules/dental_idr/diagnosis/c82.json\n", + "Loading submodule modules/dental_idr/diagnosis/c83.json\n", + "Loading submodule modules/dental_idr/diagnosis/c84.json\n", + "Loading submodule modules/dental_idr/diagnosis/c85.json\n", + "Loading submodule modules/dental_idr/diagnosis/c86.json\n", + "Loading submodule modules/dental_idr/diagnosis/c88.json\n", + "Loading submodule modules/dental_idr/diagnosis/c90.json\n", + "Loading submodule modules/dental_idr/diagnosis/c91.json\n", + "Loading submodule modules/dental_idr/diagnosis/c92.json\n", + "Loading submodule modules/dental_idr/diagnosis/c93.json\n", + "Loading submodule modules/dental_idr/diagnosis/c95.json\n", + "Loading submodule modules/dental_idr/diagnosis/c96.json\n", + "Loading submodule modules/dental_idr/diagnosis/d00.json\n", + "Loading submodule modules/dental_idr/diagnosis/d01.json\n", + "Loading submodule modules/dental_idr/diagnosis/d02.json\n", + "Loading submodule modules/dental_idr/diagnosis/d03.json\n", + "Loading submodule modules/dental_idr/diagnosis/d04.json\n", + "Loading submodule modules/dental_idr/diagnosis/d05.json\n", + "Loading submodule modules/dental_idr/diagnosis/d06.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/d07.json\n", + "Loading submodule modules/dental_idr/diagnosis/d09.json\n", + "Loading submodule modules/dental_idr/diagnosis/d10.json\n", + "Loading submodule modules/dental_idr/diagnosis/d11.json\n", + "Loading submodule modules/dental_idr/diagnosis/d12.json\n", + "Loading submodule modules/dental_idr/diagnosis/d13.json\n", + "Loading submodule modules/dental_idr/diagnosis/d14.json\n", + "Loading submodule modules/dental_idr/diagnosis/d16.json\n", + "Loading submodule modules/dental_idr/diagnosis/d17.json\n", + "Loading submodule modules/dental_idr/diagnosis/d18.json\n", + "Loading submodule modules/dental_idr/diagnosis/d19.json\n", + "Loading submodule modules/dental_idr/diagnosis/d21.json\n", + "Loading submodule modules/dental_idr/diagnosis/d22.json\n", + "Loading submodule modules/dental_idr/diagnosis/d23.json\n", + "Loading submodule modules/dental_idr/diagnosis/d24.json\n", + "Loading submodule modules/dental_idr/diagnosis/d25.json\n", + "Loading submodule modules/dental_idr/diagnosis/d28.json\n", + "Loading submodule modules/dental_idr/diagnosis/d29.json\n", + "Loading submodule modules/dental_idr/diagnosis/d30.json\n", + "Loading submodule modules/dental_idr/diagnosis/d31.json\n", + "Loading submodule modules/dental_idr/diagnosis/d32.json\n", + "Loading submodule modules/dental_idr/diagnosis/d33.json\n", + "Loading submodule modules/dental_idr/diagnosis/d34.json\n", + "Loading submodule modules/dental_idr/diagnosis/d35.json\n", + "Loading submodule modules/dental_idr/diagnosis/d36.json\n", + "Loading submodule modules/dental_idr/diagnosis/d37.json\n", + "Loading submodule modules/dental_idr/diagnosis/d38.json\n", + "Loading submodule modules/dental_idr/diagnosis/d39.json\n", + "Loading submodule modules/dental_idr/diagnosis/d3a.json\n", + "Loading submodule modules/dental_idr/diagnosis/d40.json\n", + "Loading submodule modules/dental_idr/diagnosis/d41.json\n", + "Loading submodule modules/dental_idr/diagnosis/d44.json\n", + "Loading submodule modules/dental_idr/diagnosis/d45.json\n", + "Loading submodule modules/dental_idr/diagnosis/d46.json\n", + "Loading submodule modules/dental_idr/diagnosis/d47.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/d48.json\n", + "Loading submodule modules/dental_idr/diagnosis/d49.json\n", + "Loading submodule modules/dental_idr/diagnosis/k00.json\n", + "Loading submodule modules/dental_idr/diagnosis/k01.json\n", + "Loading submodule modules/dental_idr/diagnosis/k02.json\n", + "Loading submodule modules/dental_idr/diagnosis/k03.json\n", + "Loading submodule modules/dental_idr/diagnosis/k04.json\n", + "Loading submodule modules/dental_idr/diagnosis/k05.json\n", + "Loading submodule modules/dental_idr/diagnosis/k06.json\n", + "Loading submodule modules/dental_idr/diagnosis/k08.json\n", + "Loading submodule modules/dental_idr/diagnosis/k09.json\n", + "Loading submodule modules/dental_idr/diagnosis/k11.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/k12.json\n", + "Loading submodule modules/dental_idr/diagnosis/k13.json\n", + "Loading submodule modules/dental_idr/diagnosis/m26.json\n", + "Loading submodule modules/dental_idr/diagnosis/m27.json\n", + "Loading submodule modules/dental_idr/diagnosis/r69.json\n", + "Loading submodule modules/dental_idr/diagnosis/s02.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/z00.json\n", + "Loading submodule modules/dental_idr/diagnosis/z01.json\n", + "Loading submodule modules/dental_idr/diagnosis/z13.json\n", + "Loading submodule modules/dental_idr/diagnosis/z40.json\n", + "Loading submodule modules/dental_idr/diagnosis/z41.json\n", + "Loading submodule modules/dental_idr/diagnosis/z51.json\n", + "Loading submodule modules/dental_idr/end_dental_diagnoses.json\n", + "Loading submodule modules/dental_idr/procedure/d01.json\n", + "Loading submodule modules/dental_idr/procedure/d02.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d03.json\n", + "Loading submodule modules/dental_idr/procedure/d04.json\n", + "Loading submodule modules/dental_idr/procedure/d05.json\n", + "Loading submodule modules/dental_idr/procedure/d06.json\n", + "Loading submodule modules/dental_idr/procedure/d07.json\n", + "Loading submodule modules/dental_idr/procedure/d08.json\n", + "Loading submodule modules/dental_idr/procedure/d09.json\n", + "Loading submodule modules/dental_idr/procedure/d11.json\n", + "Loading submodule modules/dental_idr/procedure/d12.json\n", + "Loading submodule modules/dental_idr/procedure/d13.json\n", + "Loading submodule modules/dental_idr/procedure/d15.json\n", + "Loading submodule modules/dental_idr/procedure/d17.json\n", + "Loading submodule modules/dental_idr/procedure/d19.json\n", + "Loading submodule modules/dental_idr/procedure/d21.json\n", + "Loading submodule modules/dental_idr/procedure/d23.json\n", + "Loading submodule modules/dental_idr/procedure/d24.json\n", + "Loading submodule modules/dental_idr/procedure/d25.json\n", + "Loading submodule modules/dental_idr/procedure/d26.json\n", + "Loading submodule modules/dental_idr/procedure/d27.json\n", + "Loading submodule modules/dental_idr/procedure/d29.json\n", + "Loading submodule modules/dental_idr/procedure/d31.json\n", + "Loading submodule modules/dental_idr/procedure/d32.json\n", + "Loading submodule modules/dental_idr/procedure/d33.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d34.json\n", + "Loading submodule modules/dental_idr/procedure/d35.json\n", + "Loading submodule modules/dental_idr/procedure/d39.json\n", + "Loading submodule modules/dental_idr/procedure/d42.json\n", + "Loading submodule modules/dental_idr/procedure/d43.json\n", + "Loading submodule modules/dental_idr/procedure/d49.json\n", + "Loading submodule modules/dental_idr/procedure/d51.json\n", + "Loading submodule modules/dental_idr/procedure/d52.json\n", + "Loading submodule modules/dental_idr/procedure/d54.json\n", + "Loading submodule modules/dental_idr/procedure/d55.json\n", + "Loading submodule modules/dental_idr/procedure/d56.json\n", + "Loading submodule modules/dental_idr/procedure/d57.json\n", + "Loading submodule modules/dental_idr/procedure/d58.json\n", + "Loading submodule modules/dental_idr/procedure/d59.json\n", + "Loading submodule modules/dental_idr/procedure/d60.json\n", + "Loading submodule modules/dental_idr/procedure/d61.json\n", + "Loading submodule modules/dental_idr/procedure/d62.json\n", + "Loading submodule modules/dental_idr/procedure/d65.json\n", + "Loading submodule modules/dental_idr/procedure/d66.json\n", + "Loading submodule modules/dental_idr/procedure/d67.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d69.json\n", + "Loading submodule modules/dental_idr/procedure/d71.json\n", + "Loading submodule modules/dental_idr/procedure/d72.json\n", + "Loading submodule modules/dental_idr/procedure/d73.json\n", + "Loading submodule modules/dental_idr/procedure/d74.json\n", + "Loading submodule modules/dental_idr/procedure/d75.json\n", + "Loading submodule modules/dental_idr/procedure/d76.json\n", + "Loading submodule modules/dental_idr/procedure/d77.json\n", + "Loading submodule modules/dental_idr/procedure/d78.json\n", + "Loading submodule modules/dental_idr/procedure/d79.json\n", + "Loading submodule modules/dental_idr/procedure/d80.json\n", + "Loading submodule modules/dental_idr/procedure/d82.json\n", + "Loading submodule modules/dental_idr/procedure/d86.json\n", + "Loading submodule modules/dental_idr/procedure/d87.json\n", + "Loading submodule modules/dental_idr/procedure/d89.json\n", + "Loading submodule modules/dental_idr/procedure/d91.json\n", + "Loading submodule modules/dental_idr/procedure/d92.json\n", + "Loading submodule modules/dental_idr/procedure/d93.json\n", + "Loading submodule modules/dental_idr/procedure/d94.json\n", + "Loading submodule modules/dental_idr/procedure/d96.json\n", + "Loading submodule modules/dental_idr/procedure/d99.json\n", + "Loading submodule modules/dermatitis/early_moderate_eczema_obs.json\n", + "Loading submodule modules/dermatitis/early_severe_eczema_obs.json\n", + "Loading submodule modules/dermatitis/mid_moderate_eczema_obs.json\n", + "Loading submodule modules/dermatitis/mid_severe_eczema_obs.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dermatitis/moderate_cd_obs.json\n", + "Loading submodule modules/dermatitis/severe_cd_obs.json\n", + "Loading submodule modules/dme/wheelchair.json\n", + "Loading submodule modules/dme/wheelchair_end.json\n", + "Loading submodule modules/encounter/anxiety_screening.json\n", + "Loading submodule modules/encounter/depression_screening.json\n", + "Loading submodule modules/encounter/fall_risk_screening.json\n", + "Loading submodule modules/encounter/hark_screening.json\n", + "Loading submodule modules/encounter/hospital_basic_labs.json\n", + "Loading submodule modules/encounter/sdoh_hrsn.json\n", + "Loading submodule modules/encounter/substance_use_screening.json\n", + "Loading submodule modules/encounter/vitals.json\n", + "Loading submodule modules/eye/intraocular_pressure.json\n", + "Loading submodule modules/eye/ophthalmic_progression.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/eye/ophthalmic_tomography.json\n", + "Loading submodule modules/eye/visual_acuity.json\n", + "Loading submodule modules/heart/acs_anticoagulant.json\n", + "Loading submodule modules/heart/acs_antiplatelet.json\n", + "Loading submodule modules/heart/acs_arrival_medications.json\n", + "Loading submodule modules/heart/acs_discharge_meds.json\n", + "Loading submodule modules/heart/avrr/antithrombotic.json\n", + "Loading submodule modules/heart/avrr/avrr_referral.json\n", + "Loading submodule modules/heart/avrr/intraop_meds_blood.json\n", + "Loading submodule modules/heart/avrr/outcomes.json\n", + "Loading submodule modules/heart/avrr/preoperative.json\n", + "Loading submodule modules/heart/avrr/savrr_operation.json\n", + "Loading submodule modules/heart/avrr/savrr_postop.json\n", + "Loading submodule modules/heart/avrr/sequence.json\n", + "Loading submodule modules/heart/cabg/cabg_referral.json\n", + "Loading submodule modules/heart/cabg/details.json\n", + "Loading Lookup Table: cabg_details_operative_approach.csv\n", + "Loading Lookup Table: cabg_details_num_grafts.csv\n", + "Loading Lookup Table: cabg_details_num_art_cond.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/cabg/icu_meds_devices.json\n", + "Loading submodule modules/heart/cabg/labs_common.json\n", + "Loading submodule modules/heart/cabg/operation.json\n", + "Loading submodule modules/heart/cabg/or_intraop.json\n", + "Loading submodule modules/heart/cabg/or_labs_meds.json\n", + "Loading submodule modules/heart/cabg/outcomes.json\n", + "Loading submodule modules/heart/cabg/postop.json\n", + "Loading submodule modules/heart/cabg/postop_blood.json\n", + "Loading submodule modules/heart/cabg/preoperative.json\n", + "Loading submodule modules/heart/cabg_sequence.json\n", + "Loading submodule modules/heart/cardiac_labs.json\n", + "Loading submodule modules/heart/chf_lab_work.json\n", + "Loading submodule modules/heart/chf_lvad.json\n", + "Loading submodule modules/heart/chf_meds.json\n", + "Loading submodule modules/heart/chf_meds_hfmef.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha2.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha3.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha4.json\n", + "Loading submodule modules/heart/chf_nyha_panel.json\n", + "Loading submodule modules/heart/chf_transplant.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/nsteacs_pathway.json\n", + "Loading submodule modules/heart/operative_status.json\n", + "Loading submodule modules/heart/or_blood.json\n", + "Loading Lookup Table: or_blood_anemia_check.csv\n", + "Loading Lookup Table: or_blood_platelet_check.csv\n", + "Loading Lookup Table: or_blood_plasma_check.csv\n", + "Loading submodule modules/heart/savrepair/operative_status.json\n", + "Loading submodule modules/heart/savreplace/operative_status.json\n", + "Loading submodule modules/heart/stemi_fibrinolytic.json\n", + "Loading submodule modules/heart/stemi_pathway.json\n", + "Loading submodule modules/heart/tavr/alt_access.json\n", + "Loading submodule modules/heart/tavr/operation.json\n", + "Loading submodule modules/heart/tavr/operative_status.json\n", + "Loading submodule modules/heart/tavr/outcomes.json\n", + "Loading submodule modules/heart/tavr/postop.json\n", + "Loading submodule modules/heart/vhd_risks.json\n", + "Loading submodule modules/hiv/art_sequence.json\n", + "Loading submodule modules/hiv/art_sequence_1987_1994.json\n", + "Loading submodule modules/hiv/art_sequence_1995_1996.json\n", + "Loading submodule modules/hiv/art_sequence_1997_2002.json\n", + "Loading submodule modules/hiv/art_sequence_2003_2005.json\n", + "Loading submodule modules/hiv/art_sequence_2006_2014.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/hiv/art_sequence_2015.json\n", + "Loading submodule modules/hiv/hiv_baseline.json\n", + "Loading submodule modules/hiv/hiv_cd4.json\n", + "Loading Lookup Table: hiv_stage.csv\n", + "Loading submodule modules/hiv/hiv_oi_prophylaxis.json\n", + "Loading submodule modules/hiv/hiv_screening.json\n", + "Loading submodule modules/hiv/hiv_viral_load.json\n", + "Loading submodule modules/hiv/stop_all_art_meds.json\n", + "Loading submodule modules/injuries/broken_jaw.json\n", + "Loading submodule modules/lung_cancer/lung_cancer_probabilities.json\n", + "Loading submodule modules/medications/ace_arb.json\n", + "Loading Lookup Table: ace_arb_ingredient_distribution.csv\n", + "Loading Lookup Table: ace_arb_amlodipine_benazepril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_benazepril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_benazepril_hydrochlorothiazide_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_enalapril_product_distribution.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading Lookup Table: ace_arb_hydrochlorothiazide_lisinopril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_losartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_valsartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_irbesartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_lisinopril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_losartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_quinapril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_ramipril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_sacubitril_valsartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_telmisartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_valsartan_product_distribution.csv\n", + "Loading submodule modules/medications/beta_blocker.json\n", + "Loading Lookup Table: beta_blocker_ingredient_distribution.csv\n", + "Loading Lookup Table: beta_blocker_atenolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_bisoprolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_bisoprolol_hydrochlorothiazide_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_carvedilol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_labetalol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_metoprolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_nebivolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_propranolol_product_distribution.csv\n", + "Loading submodule modules/medications/ear_infection_antibiotic.json\n", + "Loading submodule modules/medications/emergency_inhaler.json\n", + "Loading Lookup Table: emergency_inhaler_ingredient_distribution.csv\n", + "Loading Lookup Table: emergency_inhaler_albuterol_product_distribution.csv\n", + "Loading Lookup Table: emergency_inhaler_levalbuterol_product_distribution.csv\n", + "Loading submodule modules/medications/hypertension_medication.json\n", + "Loading submodule modules/medications/maintenance_inhaler.json\n", + "Loading Lookup Table: maintenance_inhaler_ingredient_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_beclomethasone_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_budesonide_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_fluticasone_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_mometasone_product_distribution.csv\n", + "Loading submodule modules/medications/moderate_opioid_pain_reliever.json\n", + "Loading submodule modules/medications/otc_antihistamine.json\n", + "Loading submodule modules/medications/otc_pain_reliever.json\n", + "Loading submodule modules/medications/statin.json\n", + "Loading Lookup Table: statin_ingredient_distribution.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading Lookup Table: statin_atorvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_ezetimibe_simvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_lovastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_pitavastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_pravastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_rosuvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_simvastatin_product_distribution.csv\n", + "Loading submodule modules/medications/strong_opioid_pain_reliever.json\n", + "Loading submodule modules/metabolic_syndrome/amputations.json\n", + "Loading submodule modules/metabolic_syndrome/diabetic_retinopathy_diagnoses.json\n", + "Loading submodule modules/metabolic_syndrome/diabetic_retinopathy_progression.json\n", + "Loading submodule modules/metabolic_syndrome/dme_supplies.json\n", + "Loading submodule modules/metabolic_syndrome/kidney_conditions.json\n", + "Loading submodule modules/metabolic_syndrome/medications.json\n", + "Loading submodule modules/snf/skilled_nursing_facility.json\n", + "Loading submodule modules/surgery/general_anesthesia.json\n", + "Loading submodule modules/total_joint_replacement/functional_status_assessments.json\n", + "Loading submodule modules/uti/abx_tx.json\n", + "Loading submodule modules/uti/ambulatory_eval.json\n", + "Loading submodule modules/uti/ambulatory_path.json\n", + "Loading submodule modules/uti/ed_bundle.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/uti/ed_eval.json\n", + "Loading submodule modules/uti/ed_path.json\n", + "Loading submodule modules/uti/gu_pregnancy_check.json\n", + "Loading submodule modules/uti/hpi.json\n", + "Loading submodule modules/uti/lab_follow_up.json\n", + "Loading submodule modules/uti/labs.json\n", + "Loading submodule modules/uti/telemed_path.json\n", + "Loading submodule modules/veterans/veteran_suicide_probabilities.json\n", + "Loading submodule modules/weight_loss/mend_week.json\n", + "Loading module modules/AIS_From_School_Screening_to_SOSORT_Recommendations.json\n", + "Loading module modules/acute_myeloid_leukemia.json\n", + "Loading Lookup Table: AML.csv\n", + "Loading module modules/allergic_rhinitis.json\n", + "Loading module modules/allergies.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/anemia___unknown_etiology.json\n", + "Loading module modules/appendicitis.json\n", + "Loading module modules/asthma.json\n", + "Loading module modules/atopy.json\n", + "Loading module modules/atrial_fibrillation.json\n", + "Loading module modules/attention_deficit_disorder.json\n", + "Loading module modules/bone_marrow_transplant.json\n", + "Loading module modules/breast_cancer.json\n", + "Loading module modules/bronchitis.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/cerebral_palsy.json\n", + "Loading module modules/chronic_kidney_disease.json\n", + "Loading module modules/colorectal_cancer.json\n", + "Loading module modules/congestive_heart_failure.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/contraceptive_maintenance.json\n", + "Loading module modules/contraceptives.json\n", + "Loading module modules/copd.json\n", + "Loading module modules/covid19.json\n", + "Loading Lookup Table: covid19_prob.csv\n", + "Loading module modules/cystic_fibrosis.json\n", + "Loading module modules/dementia.json\n", + "Loading module modules/dental_and_oral_examination.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/dental_encounters.json\n", + "Loading module modules/dental_medicare_clustered_encounters.json\n", + "Loading module modules/dentures.json\n", + "Loading module modules/dermatitis.json\n", + "Loading module modules/diabetic_retinopathy_treatment.json\n", + "Loading Lookup Table: diabetic_retinopathy_followup.csv\n", + "Loading module modules/dialysis.json\n", + "Loading module modules/ear_infections.json\n", + "Loading module modules/epilepsy.json\n", + "Loading module modules/female_reproduction.json\n", + "Loading module modules/fibromyalgia.json\n", + "Loading module modules/food_allergies.json\n", + "Loading module modules/gallstones.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/gout.json\n", + "Loading module modules/hiv_care.json\n", + "Loading Lookup Table: hiv_care.csv\n", + "Loading module modules/hiv_diagnosis.json\n", + "Loading Lookup Table: hiv_mortality_later.csv\n", + "Loading Lookup Table: hiv_mortality_early.csv\n", + "Loading Lookup Table: hiv_mortality_very_early.csv\n", + "Loading Lookup Table: hiv_diagnosis_early.csv\n", + "Loading Lookup Table: hiv_diagnosis_later.csv\n", + "Loading module modules/home_health_treatment.json\n", + "Loading module modules/home_hospice_snf.json\n", + "Loading module modules/homelessness.json\n", + "Loading module modules/hospice_treatment.json\n", + "Loading module modules/hypertension.json\n", + "Loading module modules/hypothyroidism.json\n", + "Loading module modules/injuries.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/kidney_transplant.json\n", + "Loading module modules/lung_cancer.json\n", + "Loading module modules/lupus.json\n", + "Loading module modules/mTBI.json\n", + "Loading module modules/med_rec.json\n", + "Loading module modules/mend_program.json\n", + "Loading module modules/metabolic_syndrome_care.json\n", + "Loading module modules/metabolic_syndrome_disease.json\n", + "Loading module modules/myocardial_infarction.json\n", + "Loading module modules/opioid_addiction.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/osteoarthritis.json\n", + "Loading module modules/osteoporosis.json\n", + "Loading module modules/pregnancy.json\n", + "Loading module modules/prescribing_opioids_for_chronic_pain_and_treatment_of_oud.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/rheumatoid_arthritis.json\n", + "Loading module modules/self_harm.json\n", + "Loading module modules/sepsis.json\n", + "Loading module modules/sexual_activity.json\n", + "Loading module modules/sinusitis.json\n", + "Loading module modules/sleep_apnea.json\n", + "Loading module modules/sore_throat.json\n", + "Loading module modules/spina_bifida.json\n", + "Loading module modules/stable_ischemic_heart_disease.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/stroke.json\n", + "Loading module modules/total_joint_replacement.json\n", + "Loading module modules/trigger_bone_marrow_transplant.json\n", + "Loading module modules/urinary_tract_infections.json\n", + "Loading Lookup Table: uti.csv\n", + "Loading Lookup Table: uti_recurrence.csv\n", + "Loading module modules/veteran.json\n", + "Loading module modules/veteran_hyperlipidemia.json\n", + "Loading module modules/veteran_lung_cancer.json\n", + "Loading module modules/veteran_mdd.json\n", + "Loading module modules/veteran_prostate_cancer.json\n", + "Loading module modules/veteran_ptsd.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/veteran_self_harm.json\n", + "Loading module modules/veteran_substance_abuse_conditions.json\n", + "Loading module modules/veteran_substance_abuse_treatment.json\n", + "Loading module modules/vhd_aortic.json\n", + "Loading Lookup Table: vhd_as.csv\n", + "Loading Lookup Table: vhd_ar.csv\n", + "Loading module modules/vhd_mitral.json\n", + "Loading Lookup Table: vhd_mr.csv\n", + "Loading Lookup Table: vhd_ms.csv\n", + "Loading module modules/vhd_pulmonic.json\n", + "Loading Lookup Table: vhd_ps.csv\n", + "Loading Lookup Table: vhd_pr.csv\n", + "Loading module modules/vhd_tricuspid.json\n", + "Loading Lookup Table: vhd_tr.csv\n", + "Loading Lookup Table: vhd_ts.csv\n", + "Loading module modules/wellness_encounters.json\n", + "Running with options:\n", + "Population: 10\n", + "Seed: 42\n", + "Provider Seed:43\n", + "Reference Time: 1704067200000\n", + "Location: Boston, Massachusetts\n", + "Min Age: 30\n", + "Max Age: 40\n", + "Gender: F\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 -- Corie618 Sofia418 Rath779 (40 y/o F) Boston, Massachusetts (55751)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 -- Antonia30 Rosa195 Tapia475 (41 y/o F) Boston, Massachusetts (55585)\n", + "3 -- Lola232 Ariadna374 Cardona494 (37 y/o F) Boston, Massachusetts (50158)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4 -- Esperanza675 María Luisa888 Valverde277 (32 y/o F) Boston, Massachusetts (45515)\n", + "5 -- Jona712 Bonnie873 Rosenbaum794 (35 y/o F) Boston, Massachusetts (51640)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6 -- Tennille443 Denna536 Nitzsche158 (36 y/o F) Boston, Massachusetts (49197)\n", + "7 -- Ocie984 Bernie827 Homenick806 (40 y/o F) Boston, Massachusetts (56300)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "8 -- Lindsay928 Deja232 Pollich983 (38 y/o F) Boston, Massachusetts (52138)\n", + "9 -- Shondra529 Kyra237 Spinka232 (34 y/o F) Boston, Massachusetts (46387)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10 -- Chrissy459 Jolynn62 Stanton715 (40 y/o F) Boston, Massachusetts (58930)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Records: total=10, alive=10, dead=0\n", + "RNG=10\n", + "Clinician RNG=5638\n", + "\n", + "\u001b[32mYou've just generated 10 patients!\u001b[0m We're happy to know Synthea is helping you with your project.\n", + "Like what we're doing? Synthea is an open-source project, and your support helps us keep building.\n", + "Please consider \u001b[34m\u001b]8;;https://github.com/sponsors/synthetichealth\u0007making a donation\u001b]8;;\u0007\u001b[0m (https://github.com/sponsors/synthetichealth).\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Synthea: /home/soham/.local/jvm/jdk-17.0.20.1+1/bin/java -jar /home/soham/.cache/pyhealth/synthea/synthea-with-dependencies-v4.0.0.jar --exporter.baseDirectory=/home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/36cf651f1ef161fa3ee3de791f868b850be4dda4485fe4f0772e1d7dfbcb38bf --exporter.bfd.export=false --exporter.ccda.export=false --exporter.cdw.export=false --exporter.clinical_note.export=false --exporter.cpcds.export=false --exporter.csv.append_mode=false --exporter.csv.export=true --exporter.csv.folder_per_run=false --exporter.fhir.export=false --exporter.fhir_dstu2.export=false --exporter.fhir_stu3.export=false --exporter.json.export=false --exporter.symptoms.csv.export=false --exporter.symptoms.text.export=false --exporter.text.export=false --exporter.years_of_history=5 --generate.only_alive_patients=true --generate.thread_pool_size=1 -s 7 -p 3\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "org.mitre.synthea.X12.ExporterAdaptor\n", + "org.mitre.synthea.X12.ExporterAdaptor\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "SLF4J: No SLF4J providers were found.\n", + "SLF4J: Defaulting to no-operation (NOP) logger implementation\n", + "SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanned 92 modules and 449 submodules.\n", + "Loading submodule modules/allergies/allergy_panel.json\n", + "Loading submodule modules/allergies/drug_allergy_incidence.json\n", + "Loading submodule modules/allergies/environmental_allergy_incidence.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/allergies/food_allergy_incidence.json\n", + "Loading submodule modules/allergies/immunotherapy.json\n", + "Loading submodule modules/allergies/outgrow_env_allergies.json\n", + "Loading submodule modules/allergies/outgrow_food_allergies.json\n", + "Loading submodule modules/allergies/severe_allergic_reaction.json\n", + "Loading submodule modules/anemia/anemia_sub.json\n", + "Loading submodule modules/breast_cancer/chemotherapy_breast.json\n", + "Loading submodule modules/breast_cancer/hormone_diagnosis.json\n", + "Loading submodule modules/breast_cancer/hormonetherapy_breast.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/breast_cancer/surgery_therapy_breast.json\n", + "Loading submodule modules/breast_cancer/tnm_diagnosis.json\n", + "Loading submodule modules/contraceptives/clear_contraceptive.json\n", + "Loading submodule modules/contraceptives/female_sterilization.json\n", + "Loading submodule modules/contraceptives/implant_contraceptive.json\n", + "Loading submodule modules/contraceptives/injectable_contraceptive.json\n", + "Loading submodule modules/contraceptives/intrauterine_device.json\n", + "Loading submodule modules/contraceptives/male_sterilization.json\n", + "Loading submodule modules/contraceptives/oral_contraceptive.json\n", + "Loading submodule modules/contraceptives/patch_contraceptive.json\n", + "Loading submodule modules/contraceptives/ring_contraceptive.json\n", + "Loading submodule modules/covid19/admission.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/covid19/determine_risk.json\n", + "Loading Lookup Table: covid-19-severity-outcomes.csv\n", + "Loading Lookup Table: covid-19-survival-outcomes.csv\n", + "Loading submodule modules/covid19/diagnose_bacterial_infection.json\n", + "Loading submodule modules/covid19/diagnose_blood_clot.json\n", + "Loading submodule modules/covid19/end_outcomes.json\n", + "Loading submodule modules/covid19/end_symptoms.json\n", + "Loading submodule modules/covid19/infection.json\n", + "Loading submodule modules/covid19/measurements_daily.json\n", + "Loading submodule modules/covid19/measurements_frequent.json\n", + "Loading submodule modules/covid19/measurements_vitals.json\n", + "Loading submodule modules/covid19/medications.json\n", + "Loading submodule modules/covid19/nonsurvivor_lab_values.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/covid19/outcomes.json\n", + "Loading submodule modules/covid19/supplies_hospitalization.json\n", + "Loading submodule modules/covid19/supplies_icu.json\n", + "Loading submodule modules/covid19/supplies_intubation.json\n", + "Loading submodule modules/covid19/survivor_lab_values.json\n", + "Loading submodule modules/covid19/symptoms.json\n", + "Loading submodule modules/covid19/treat_blood_clot.json\n", + "Loading submodule modules/dental/dental_emergency.json\n", + "Loading submodule modules/dental/dental_encounter.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/dental_hospital.json\n", + "Loading submodule modules/dental/dental_telephone.json\n", + "Loading submodule modules/dental/diagnosis/cavity.json\n", + "Loading submodule modules/dental/diagnosis/dental disorder.json\n", + "Loading submodule modules/dental/diagnosis/gingivitis.json\n", + "Loading submodule modules/dental/diagnosis/periodontitis.json\n", + "Loading submodule modules/dental/diagnosis/plaque.json\n", + "Loading submodule modules/dental/end_dental_diagnoses.json\n", + "Loading submodule modules/dental/procedure/d01.json\n", + "Loading submodule modules/dental/procedure/d02.json\n", + "Loading submodule modules/dental/procedure/d03.json\n", + "Loading submodule modules/dental/procedure/d04.json\n", + "Loading submodule modules/dental/procedure/d05.json\n", + "Loading submodule modules/dental/procedure/d06.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d09.json\n", + "Loading submodule modules/dental/procedure/d11.json\n", + "Loading submodule modules/dental/procedure/d12.json\n", + "Loading submodule modules/dental/procedure/d13.json\n", + "Loading submodule modules/dental/procedure/d15.json\n", + "Loading submodule modules/dental/procedure/d19.json\n", + "Loading submodule modules/dental/procedure/d21.json\n", + "Loading submodule modules/dental/procedure/d23.json\n", + "Loading submodule modules/dental/procedure/d25.json\n", + "Loading submodule modules/dental/procedure/d26.json\n", + "Loading submodule modules/dental/procedure/d27.json\n", + "Loading submodule modules/dental/procedure/d29.json\n", + "Loading submodule modules/dental/procedure/d31.json\n", + "Loading submodule modules/dental/procedure/d32.json\n", + "Loading submodule modules/dental/procedure/d33.json\n", + "Loading submodule modules/dental/procedure/d34.json\n", + "Loading submodule modules/dental/procedure/d39.json\n", + "Loading submodule modules/dental/procedure/d42.json\n", + "Loading submodule modules/dental/procedure/d43.json\n", + "Loading submodule modules/dental/procedure/d49.json\n", + "Loading submodule modules/dental/procedure/d51.json\n", + "Loading submodule modules/dental/procedure/d52.json\n", + "Loading submodule modules/dental/procedure/d54.json\n", + "Loading submodule modules/dental/procedure/d55.json\n", + "Loading submodule modules/dental/procedure/d56.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d57.json\n", + "Loading submodule modules/dental/procedure/d58.json\n", + "Loading submodule modules/dental/procedure/d59.json\n", + "Loading submodule modules/dental/procedure/d60.json\n", + "Loading submodule modules/dental/procedure/d61.json\n", + "Loading submodule modules/dental/procedure/d62.json\n", + "Loading submodule modules/dental/procedure/d65.json\n", + "Loading submodule modules/dental/procedure/d66.json\n", + "Loading submodule modules/dental/procedure/d67.json\n", + "Loading submodule modules/dental/procedure/d69.json\n", + "Loading submodule modules/dental/procedure/d71.json\n", + "Loading submodule modules/dental/procedure/d72.json\n", + "Loading submodule modules/dental/procedure/d73.json\n", + "Loading submodule modules/dental/procedure/d74.json\n", + "Loading submodule modules/dental/procedure/d75.json\n", + "Loading submodule modules/dental/procedure/d76.json\n", + "Loading submodule modules/dental/procedure/d77.json\n", + "Loading submodule modules/dental/procedure/d78.json\n", + "Loading submodule modules/dental/procedure/d79.json\n", + "Loading submodule modules/dental/procedure/d80.json\n", + "Loading submodule modules/dental/procedure/d82.json\n", + "Loading submodule modules/dental/procedure/d86.json\n", + "Loading submodule modules/dental/procedure/d89.json\n", + "Loading submodule modules/dental/procedure/d91.json\n", + "Loading submodule modules/dental/procedure/d92.json\n", + "Loading submodule modules/dental/procedure/d93.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d94.json\n", + "Loading submodule modules/dental/procedure/d96.json\n", + "Loading submodule modules/dental/procedure/d99.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_0.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_1.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_2.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/dental_idr_cluster_3.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_4.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c00.json\n", + "Loading submodule modules/dental_idr/diagnosis/c01.json\n", + "Loading submodule modules/dental_idr/diagnosis/c02.json\n", + "Loading submodule modules/dental_idr/diagnosis/c03.json\n", + "Loading submodule modules/dental_idr/diagnosis/c04.json\n", + "Loading submodule modules/dental_idr/diagnosis/c05.json\n", + "Loading submodule modules/dental_idr/diagnosis/c06.json\n", + "Loading submodule modules/dental_idr/diagnosis/c07.json\n", + "Loading submodule modules/dental_idr/diagnosis/c08.json\n", + "Loading submodule modules/dental_idr/diagnosis/c09.json\n", + "Loading submodule modules/dental_idr/diagnosis/c10.json\n", + "Loading submodule modules/dental_idr/diagnosis/c11.json\n", + "Loading submodule modules/dental_idr/diagnosis/c12.json\n", + "Loading submodule modules/dental_idr/diagnosis/c13.json\n", + "Loading submodule modules/dental_idr/diagnosis/c14.json\n", + "Loading submodule modules/dental_idr/diagnosis/c15.json\n", + "Loading submodule modules/dental_idr/diagnosis/c16.json\n", + "Loading submodule modules/dental_idr/diagnosis/c17.json\n", + "Loading submodule modules/dental_idr/diagnosis/c18.json\n", + "Loading submodule modules/dental_idr/diagnosis/c19.json\n", + "Loading submodule modules/dental_idr/diagnosis/c20.json\n", + "Loading submodule modules/dental_idr/diagnosis/c21.json\n", + "Loading submodule modules/dental_idr/diagnosis/c22.json\n", + "Loading submodule modules/dental_idr/diagnosis/c24.json\n", + "Loading submodule modules/dental_idr/diagnosis/c25.json\n", + "Loading submodule modules/dental_idr/diagnosis/c26.json\n", + "Loading submodule modules/dental_idr/diagnosis/c30.json\n", + "Loading submodule modules/dental_idr/diagnosis/c31.json\n", + "Loading submodule modules/dental_idr/diagnosis/c32.json\n", + "Loading submodule modules/dental_idr/diagnosis/c33.json\n", + "Loading submodule modules/dental_idr/diagnosis/c34.json\n", + "Loading submodule modules/dental_idr/diagnosis/c37.json\n", + "Loading submodule modules/dental_idr/diagnosis/c38.json\n", + "Loading submodule modules/dental_idr/diagnosis/c39.json\n", + "Loading submodule modules/dental_idr/diagnosis/c40.json\n", + "Loading submodule modules/dental_idr/diagnosis/c41.json\n", + "Loading submodule modules/dental_idr/diagnosis/c43.json\n", + "Loading submodule modules/dental_idr/diagnosis/c44.json\n", + "Loading submodule modules/dental_idr/diagnosis/c45.json\n", + "Loading submodule modules/dental_idr/diagnosis/c46.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c47.json\n", + "Loading submodule modules/dental_idr/diagnosis/c48.json\n", + "Loading submodule modules/dental_idr/diagnosis/c49.json\n", + "Loading submodule modules/dental_idr/diagnosis/c4a.json\n", + "Loading submodule modules/dental_idr/diagnosis/c50.json\n", + "Loading submodule modules/dental_idr/diagnosis/c51.json\n", + "Loading submodule modules/dental_idr/diagnosis/c53.json\n", + "Loading submodule modules/dental_idr/diagnosis/c54.json\n", + "Loading submodule modules/dental_idr/diagnosis/c56.json\n", + "Loading submodule modules/dental_idr/diagnosis/c57.json\n", + "Loading submodule modules/dental_idr/diagnosis/c61.json\n", + "Loading submodule modules/dental_idr/diagnosis/c62.json\n", + "Loading submodule modules/dental_idr/diagnosis/c63.json\n", + "Loading submodule modules/dental_idr/diagnosis/c64.json\n", + "Loading submodule modules/dental_idr/diagnosis/c65.json\n", + "Loading submodule modules/dental_idr/diagnosis/c66.json\n", + "Loading submodule modules/dental_idr/diagnosis/c67.json\n", + "Loading submodule modules/dental_idr/diagnosis/c68.json\n", + "Loading submodule modules/dental_idr/diagnosis/c69.json\n", + "Loading submodule modules/dental_idr/diagnosis/c71.json\n", + "Loading submodule modules/dental_idr/diagnosis/c72.json\n", + "Loading submodule modules/dental_idr/diagnosis/c73.json\n", + "Loading submodule modules/dental_idr/diagnosis/c74.json\n", + "Loading submodule modules/dental_idr/diagnosis/c75.json\n", + "Loading submodule modules/dental_idr/diagnosis/c76.json\n", + "Loading submodule modules/dental_idr/diagnosis/c77.json\n", + "Loading submodule modules/dental_idr/diagnosis/c78.json\n", + "Loading submodule modules/dental_idr/diagnosis/c79.json\n", + "Loading submodule modules/dental_idr/diagnosis/c7a.json\n", + "Loading submodule modules/dental_idr/diagnosis/c7b.json\n", + "Loading submodule modules/dental_idr/diagnosis/c80.json\n", + "Loading submodule modules/dental_idr/diagnosis/c81.json\n", + "Loading submodule modules/dental_idr/diagnosis/c82.json\n", + "Loading submodule modules/dental_idr/diagnosis/c83.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c84.json\n", + "Loading submodule modules/dental_idr/diagnosis/c85.json\n", + "Loading submodule modules/dental_idr/diagnosis/c86.json\n", + "Loading submodule modules/dental_idr/diagnosis/c88.json\n", + "Loading submodule modules/dental_idr/diagnosis/c90.json\n", + "Loading submodule modules/dental_idr/diagnosis/c91.json\n", + "Loading submodule modules/dental_idr/diagnosis/c92.json\n", + "Loading submodule modules/dental_idr/diagnosis/c93.json\n", + "Loading submodule modules/dental_idr/diagnosis/c95.json\n", + "Loading submodule modules/dental_idr/diagnosis/c96.json\n", + "Loading submodule modules/dental_idr/diagnosis/d00.json\n", + "Loading submodule modules/dental_idr/diagnosis/d01.json\n", + "Loading submodule modules/dental_idr/diagnosis/d02.json\n", + "Loading submodule modules/dental_idr/diagnosis/d03.json\n", + "Loading submodule modules/dental_idr/diagnosis/d04.json\n", + "Loading submodule modules/dental_idr/diagnosis/d05.json\n", + "Loading submodule modules/dental_idr/diagnosis/d06.json\n", + "Loading submodule modules/dental_idr/diagnosis/d07.json\n", + "Loading submodule modules/dental_idr/diagnosis/d09.json\n", + "Loading submodule modules/dental_idr/diagnosis/d10.json\n", + "Loading submodule modules/dental_idr/diagnosis/d11.json\n", + "Loading submodule modules/dental_idr/diagnosis/d12.json\n", + "Loading submodule modules/dental_idr/diagnosis/d13.json\n", + "Loading submodule modules/dental_idr/diagnosis/d14.json\n", + "Loading submodule modules/dental_idr/diagnosis/d16.json\n", + "Loading submodule modules/dental_idr/diagnosis/d17.json\n", + "Loading submodule modules/dental_idr/diagnosis/d18.json\n", + "Loading submodule modules/dental_idr/diagnosis/d19.json\n", + "Loading submodule modules/dental_idr/diagnosis/d21.json\n", + "Loading submodule modules/dental_idr/diagnosis/d22.json\n", + "Loading submodule modules/dental_idr/diagnosis/d23.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/d24.json\n", + "Loading submodule modules/dental_idr/diagnosis/d25.json\n", + "Loading submodule modules/dental_idr/diagnosis/d28.json\n", + "Loading submodule modules/dental_idr/diagnosis/d29.json\n", + "Loading submodule modules/dental_idr/diagnosis/d30.json\n", + "Loading submodule modules/dental_idr/diagnosis/d31.json\n", + "Loading submodule modules/dental_idr/diagnosis/d32.json\n", + "Loading submodule modules/dental_idr/diagnosis/d33.json\n", + "Loading submodule modules/dental_idr/diagnosis/d34.json\n", + "Loading submodule modules/dental_idr/diagnosis/d35.json\n", + "Loading submodule modules/dental_idr/diagnosis/d36.json\n", + "Loading submodule modules/dental_idr/diagnosis/d37.json\n", + "Loading submodule modules/dental_idr/diagnosis/d38.json\n", + "Loading submodule modules/dental_idr/diagnosis/d39.json\n", + "Loading submodule modules/dental_idr/diagnosis/d3a.json\n", + "Loading submodule modules/dental_idr/diagnosis/d40.json\n", + "Loading submodule modules/dental_idr/diagnosis/d41.json\n", + "Loading submodule modules/dental_idr/diagnosis/d44.json\n", + "Loading submodule modules/dental_idr/diagnosis/d45.json\n", + "Loading submodule modules/dental_idr/diagnosis/d46.json\n", + "Loading submodule modules/dental_idr/diagnosis/d47.json\n", + "Loading submodule modules/dental_idr/diagnosis/d48.json\n", + "Loading submodule modules/dental_idr/diagnosis/d49.json\n", + "Loading submodule modules/dental_idr/diagnosis/k00.json\n", + "Loading submodule modules/dental_idr/diagnosis/k01.json\n", + "Loading submodule modules/dental_idr/diagnosis/k02.json\n", + "Loading submodule modules/dental_idr/diagnosis/k03.json\n", + "Loading submodule modules/dental_idr/diagnosis/k04.json\n", + "Loading submodule modules/dental_idr/diagnosis/k05.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/k06.json\n", + "Loading submodule modules/dental_idr/diagnosis/k08.json\n", + "Loading submodule modules/dental_idr/diagnosis/k09.json\n", + "Loading submodule modules/dental_idr/diagnosis/k11.json\n", + "Loading submodule modules/dental_idr/diagnosis/k12.json\n", + "Loading submodule modules/dental_idr/diagnosis/k13.json\n", + "Loading submodule modules/dental_idr/diagnosis/m26.json\n", + "Loading submodule modules/dental_idr/diagnosis/m27.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/r69.json\n", + "Loading submodule modules/dental_idr/diagnosis/s02.json\n", + "Loading submodule modules/dental_idr/diagnosis/z00.json\n", + "Loading submodule modules/dental_idr/diagnosis/z01.json\n", + "Loading submodule modules/dental_idr/diagnosis/z13.json\n", + "Loading submodule modules/dental_idr/diagnosis/z40.json\n", + "Loading submodule modules/dental_idr/diagnosis/z41.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/z51.json\n", + "Loading submodule modules/dental_idr/end_dental_diagnoses.json\n", + "Loading submodule modules/dental_idr/procedure/d01.json\n", + "Loading submodule modules/dental_idr/procedure/d02.json\n", + "Loading submodule modules/dental_idr/procedure/d03.json\n", + "Loading submodule modules/dental_idr/procedure/d04.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d05.json\n", + "Loading submodule modules/dental_idr/procedure/d06.json\n", + "Loading submodule modules/dental_idr/procedure/d07.json\n", + "Loading submodule modules/dental_idr/procedure/d08.json\n", + "Loading submodule modules/dental_idr/procedure/d09.json\n", + "Loading submodule modules/dental_idr/procedure/d11.json\n", + "Loading submodule modules/dental_idr/procedure/d12.json\n", + "Loading submodule modules/dental_idr/procedure/d13.json\n", + "Loading submodule modules/dental_idr/procedure/d15.json\n", + "Loading submodule modules/dental_idr/procedure/d17.json\n", + "Loading submodule modules/dental_idr/procedure/d19.json\n", + "Loading submodule modules/dental_idr/procedure/d21.json\n", + "Loading submodule modules/dental_idr/procedure/d23.json\n", + "Loading submodule modules/dental_idr/procedure/d24.json\n", + "Loading submodule modules/dental_idr/procedure/d25.json\n", + "Loading submodule modules/dental_idr/procedure/d26.json\n", + "Loading submodule modules/dental_idr/procedure/d27.json\n", + "Loading submodule modules/dental_idr/procedure/d29.json\n", + "Loading submodule modules/dental_idr/procedure/d31.json\n", + "Loading submodule modules/dental_idr/procedure/d32.json\n", + "Loading submodule modules/dental_idr/procedure/d33.json\n", + "Loading submodule modules/dental_idr/procedure/d34.json\n", + "Loading submodule modules/dental_idr/procedure/d35.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d39.json\n", + "Loading submodule modules/dental_idr/procedure/d42.json\n", + "Loading submodule modules/dental_idr/procedure/d43.json\n", + "Loading submodule modules/dental_idr/procedure/d49.json\n", + "Loading submodule modules/dental_idr/procedure/d51.json\n", + "Loading submodule modules/dental_idr/procedure/d52.json\n", + "Loading submodule modules/dental_idr/procedure/d54.json\n", + "Loading submodule modules/dental_idr/procedure/d55.json\n", + "Loading submodule modules/dental_idr/procedure/d56.json\n", + "Loading submodule modules/dental_idr/procedure/d57.json\n", + "Loading submodule modules/dental_idr/procedure/d58.json\n", + "Loading submodule modules/dental_idr/procedure/d59.json\n", + "Loading submodule modules/dental_idr/procedure/d60.json\n", + "Loading submodule modules/dental_idr/procedure/d61.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d62.json\n", + "Loading submodule modules/dental_idr/procedure/d65.json\n", + "Loading submodule modules/dental_idr/procedure/d66.json\n", + "Loading submodule modules/dental_idr/procedure/d67.json\n", + "Loading submodule modules/dental_idr/procedure/d69.json\n", + "Loading submodule modules/dental_idr/procedure/d71.json\n", + "Loading submodule modules/dental_idr/procedure/d72.json\n", + "Loading submodule modules/dental_idr/procedure/d73.json\n", + "Loading submodule modules/dental_idr/procedure/d74.json\n", + "Loading submodule modules/dental_idr/procedure/d75.json\n", + "Loading submodule modules/dental_idr/procedure/d76.json\n", + "Loading submodule modules/dental_idr/procedure/d77.json\n", + "Loading submodule modules/dental_idr/procedure/d78.json\n", + "Loading submodule modules/dental_idr/procedure/d79.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d80.json\n", + "Loading submodule modules/dental_idr/procedure/d82.json\n", + "Loading submodule modules/dental_idr/procedure/d86.json\n", + "Loading submodule modules/dental_idr/procedure/d87.json\n", + "Loading submodule modules/dental_idr/procedure/d89.json\n", + "Loading submodule modules/dental_idr/procedure/d91.json\n", + "Loading submodule modules/dental_idr/procedure/d92.json\n", + "Loading submodule modules/dental_idr/procedure/d93.json\n", + "Loading submodule modules/dental_idr/procedure/d94.json\n", + "Loading submodule modules/dental_idr/procedure/d96.json\n", + "Loading submodule modules/dental_idr/procedure/d99.json\n", + "Loading submodule modules/dermatitis/early_moderate_eczema_obs.json\n", + "Loading submodule modules/dermatitis/early_severe_eczema_obs.json\n", + "Loading submodule modules/dermatitis/mid_moderate_eczema_obs.json\n", + "Loading submodule modules/dermatitis/mid_severe_eczema_obs.json\n", + "Loading submodule modules/dermatitis/moderate_cd_obs.json\n", + "Loading submodule modules/dermatitis/severe_cd_obs.json\n", + "Loading submodule modules/dme/wheelchair.json\n", + "Loading submodule modules/dme/wheelchair_end.json\n", + "Loading submodule modules/encounter/anxiety_screening.json\n", + "Loading submodule modules/encounter/depression_screening.json\n", + "Loading submodule modules/encounter/fall_risk_screening.json\n", + "Loading submodule modules/encounter/hark_screening.json\n", + "Loading submodule modules/encounter/hospital_basic_labs.json\n", + "Loading submodule modules/encounter/sdoh_hrsn.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/encounter/substance_use_screening.json\n", + "Loading submodule modules/encounter/vitals.json\n", + "Loading submodule modules/eye/intraocular_pressure.json\n", + "Loading submodule modules/eye/ophthalmic_progression.json\n", + "Loading submodule modules/eye/ophthalmic_tomography.json\n", + "Loading submodule modules/eye/visual_acuity.json\n", + "Loading submodule modules/heart/acs_anticoagulant.json\n", + "Loading submodule modules/heart/acs_antiplatelet.json\n", + "Loading submodule modules/heart/acs_arrival_medications.json\n", + "Loading submodule modules/heart/acs_discharge_meds.json\n", + "Loading submodule modules/heart/avrr/antithrombotic.json\n", + "Loading submodule modules/heart/avrr/avrr_referral.json\n", + "Loading submodule modules/heart/avrr/intraop_meds_blood.json\n", + "Loading submodule modules/heart/avrr/outcomes.json\n", + "Loading submodule modules/heart/avrr/preoperative.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/avrr/savrr_operation.json\n", + "Loading submodule modules/heart/avrr/savrr_postop.json\n", + "Loading submodule modules/heart/avrr/sequence.json\n", + "Loading submodule modules/heart/cabg/cabg_referral.json\n", + "Loading submodule modules/heart/cabg/details.json\n", + "Loading Lookup Table: cabg_details_operative_approach.csv\n", + "Loading Lookup Table: cabg_details_num_grafts.csv\n", + "Loading Lookup Table: cabg_details_num_art_cond.csv\n", + "Loading submodule modules/heart/cabg/icu_meds_devices.json\n", + "Loading submodule modules/heart/cabg/labs_common.json\n", + "Loading submodule modules/heart/cabg/operation.json\n", + "Loading submodule modules/heart/cabg/or_intraop.json\n", + "Loading submodule modules/heart/cabg/or_labs_meds.json\n", + "Loading submodule modules/heart/cabg/outcomes.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/cabg/postop.json\n", + "Loading submodule modules/heart/cabg/postop_blood.json\n", + "Loading submodule modules/heart/cabg/preoperative.json\n", + "Loading submodule modules/heart/cabg_sequence.json\n", + "Loading submodule modules/heart/cardiac_labs.json\n", + "Loading submodule modules/heart/chf_lab_work.json\n", + "Loading submodule modules/heart/chf_lvad.json\n", + "Loading submodule modules/heart/chf_meds.json\n", + "Loading submodule modules/heart/chf_meds_hfmef.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha2.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha3.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha4.json\n", + "Loading submodule modules/heart/chf_nyha_panel.json\n", + "Loading submodule modules/heart/chf_transplant.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/nsteacs_pathway.json\n", + "Loading submodule modules/heart/operative_status.json\n", + "Loading submodule modules/heart/or_blood.json\n", + "Loading Lookup Table: or_blood_anemia_check.csv\n", + "Loading Lookup Table: or_blood_platelet_check.csv\n", + "Loading Lookup Table: or_blood_plasma_check.csv\n", + "Loading submodule modules/heart/savrepair/operative_status.json\n", + "Loading submodule modules/heart/savreplace/operative_status.json\n", + "Loading submodule modules/heart/stemi_fibrinolytic.json\n", + "Loading submodule modules/heart/stemi_pathway.json\n", + "Loading submodule modules/heart/tavr/alt_access.json\n", + "Loading submodule modules/heart/tavr/operation.json\n", + "Loading submodule modules/heart/tavr/operative_status.json\n", + "Loading submodule modules/heart/tavr/outcomes.json\n", + "Loading submodule modules/heart/tavr/postop.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/vhd_risks.json\n", + "Loading submodule modules/hiv/art_sequence.json\n", + "Loading submodule modules/hiv/art_sequence_1987_1994.json\n", + "Loading submodule modules/hiv/art_sequence_1995_1996.json\n", + "Loading submodule modules/hiv/art_sequence_1997_2002.json\n", + "Loading submodule modules/hiv/art_sequence_2003_2005.json\n", + "Loading submodule modules/hiv/art_sequence_2006_2014.json\n", + "Loading submodule modules/hiv/art_sequence_2015.json\n", + "Loading submodule modules/hiv/hiv_baseline.json\n", + "Loading submodule modules/hiv/hiv_cd4.json\n", + "Loading Lookup Table: hiv_stage.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/hiv/hiv_oi_prophylaxis.json\n", + "Loading submodule modules/hiv/hiv_screening.json\n", + "Loading submodule modules/hiv/hiv_viral_load.json\n", + "Loading submodule modules/hiv/stop_all_art_meds.json\n", + "Loading submodule modules/injuries/broken_jaw.json\n", + "Loading submodule modules/lung_cancer/lung_cancer_probabilities.json\n", + "Loading submodule modules/medications/ace_arb.json\n", + "Loading Lookup Table: ace_arb_ingredient_distribution.csv\n", + "Loading Lookup Table: ace_arb_amlodipine_benazepril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_benazepril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_benazepril_hydrochlorothiazide_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_enalapril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_lisinopril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_losartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_valsartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_irbesartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_lisinopril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_losartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_quinapril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_ramipril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_sacubitril_valsartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_telmisartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_valsartan_product_distribution.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/medications/beta_blocker.json\n", + "Loading Lookup Table: beta_blocker_ingredient_distribution.csv\n", + "Loading Lookup Table: beta_blocker_atenolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_bisoprolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_bisoprolol_hydrochlorothiazide_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_carvedilol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_labetalol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_metoprolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_nebivolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_propranolol_product_distribution.csv\n", + "Loading submodule modules/medications/ear_infection_antibiotic.json\n", + "Loading submodule modules/medications/emergency_inhaler.json\n", + "Loading Lookup Table: emergency_inhaler_ingredient_distribution.csv\n", + "Loading Lookup Table: emergency_inhaler_albuterol_product_distribution.csv\n", + "Loading Lookup Table: emergency_inhaler_levalbuterol_product_distribution.csv\n", + "Loading submodule modules/medications/hypertension_medication.json\n", + "Loading submodule modules/medications/maintenance_inhaler.json\n", + "Loading Lookup Table: maintenance_inhaler_ingredient_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_beclomethasone_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_budesonide_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_fluticasone_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_mometasone_product_distribution.csv\n", + "Loading submodule modules/medications/moderate_opioid_pain_reliever.json\n", + "Loading submodule modules/medications/otc_antihistamine.json\n", + "Loading submodule modules/medications/otc_pain_reliever.json\n", + "Loading submodule modules/medications/statin.json\n", + "Loading Lookup Table: statin_ingredient_distribution.csv\n", + "Loading Lookup Table: statin_atorvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_ezetimibe_simvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_lovastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_pitavastatin_product_distribution.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading Lookup Table: statin_pravastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_rosuvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_simvastatin_product_distribution.csv\n", + "Loading submodule modules/medications/strong_opioid_pain_reliever.json\n", + "Loading submodule modules/metabolic_syndrome/amputations.json\n", + "Loading submodule modules/metabolic_syndrome/diabetic_retinopathy_diagnoses.json\n", + "Loading submodule modules/metabolic_syndrome/diabetic_retinopathy_progression.json\n", + "Loading submodule modules/metabolic_syndrome/dme_supplies.json\n", + "Loading submodule modules/metabolic_syndrome/kidney_conditions.json\n", + "Loading submodule modules/metabolic_syndrome/medications.json\n", + "Loading submodule modules/snf/skilled_nursing_facility.json\n", + "Loading submodule modules/surgery/general_anesthesia.json\n", + "Loading submodule modules/total_joint_replacement/functional_status_assessments.json\n", + "Loading submodule modules/uti/abx_tx.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/uti/ambulatory_eval.json\n", + "Loading submodule modules/uti/ambulatory_path.json\n", + "Loading submodule modules/uti/ed_bundle.json\n", + "Loading submodule modules/uti/ed_eval.json\n", + "Loading submodule modules/uti/ed_path.json\n", + "Loading submodule modules/uti/gu_pregnancy_check.json\n", + "Loading submodule modules/uti/hpi.json\n", + "Loading submodule modules/uti/lab_follow_up.json\n", + "Loading submodule modules/uti/labs.json\n", + "Loading submodule modules/uti/telemed_path.json\n", + "Loading submodule modules/veterans/veteran_suicide_probabilities.json\n", + "Loading submodule modules/weight_loss/mend_week.json\n", + "Loading module modules/AIS_From_School_Screening_to_SOSORT_Recommendations.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/acute_myeloid_leukemia.json\n", + "Loading Lookup Table: AML.csv\n", + "Loading module modules/allergic_rhinitis.json\n", + "Loading module modules/allergies.json\n", + "Loading module modules/anemia___unknown_etiology.json\n", + "Loading module modules/appendicitis.json\n", + "Loading module modules/asthma.json\n", + "Loading module modules/atopy.json\n", + "Loading module modules/atrial_fibrillation.json\n", + "Loading module modules/attention_deficit_disorder.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/bone_marrow_transplant.json\n", + "Loading module modules/breast_cancer.json\n", + "Loading module modules/bronchitis.json\n", + "Loading module modules/cerebral_palsy.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/chronic_kidney_disease.json\n", + "Loading module modules/colorectal_cancer.json\n", + "Loading module modules/congestive_heart_failure.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/contraceptive_maintenance.json\n", + "Loading module modules/contraceptives.json\n", + "Loading module modules/copd.json\n", + "Loading module modules/covid19.json\n", + "Loading Lookup Table: covid19_prob.csv\n", + "Loading module modules/cystic_fibrosis.json\n", + "Loading module modules/dementia.json\n", + "Loading module modules/dental_and_oral_examination.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/dental_encounters.json\n", + "Loading module modules/dental_medicare_clustered_encounters.json\n", + "Loading module modules/dentures.json\n", + "Loading module modules/dermatitis.json\n", + "Loading module modules/diabetic_retinopathy_treatment.json\n", + "Loading Lookup Table: diabetic_retinopathy_followup.csv\n", + "Loading module modules/dialysis.json\n", + "Loading module modules/ear_infections.json\n", + "Loading module modules/epilepsy.json\n", + "Loading module modules/female_reproduction.json\n", + "Loading module modules/fibromyalgia.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/food_allergies.json\n", + "Loading module modules/gallstones.json\n", + "Loading module modules/gout.json\n", + "Loading module modules/hiv_care.json\n", + "Loading Lookup Table: hiv_care.csv\n", + "Loading module modules/hiv_diagnosis.json\n", + "Loading Lookup Table: hiv_mortality_later.csv\n", + "Loading Lookup Table: hiv_mortality_early.csv\n", + "Loading Lookup Table: hiv_mortality_very_early.csv\n", + "Loading Lookup Table: hiv_diagnosis_early.csv\n", + "Loading Lookup Table: hiv_diagnosis_later.csv\n", + "Loading module modules/home_health_treatment.json\n", + "Loading module modules/home_hospice_snf.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/homelessness.json\n", + "Loading module modules/hospice_treatment.json\n", + "Loading module modules/hypertension.json\n", + "Loading module modules/hypothyroidism.json\n", + "Loading module modules/injuries.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/kidney_transplant.json\n", + "Loading module modules/lung_cancer.json\n", + "Loading module modules/lupus.json\n", + "Loading module modules/mTBI.json\n", + "Loading module modules/med_rec.json\n", + "Loading module modules/mend_program.json\n", + "Loading module modules/metabolic_syndrome_care.json\n", + "Loading module modules/metabolic_syndrome_disease.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/myocardial_infarction.json\n", + "Loading module modules/opioid_addiction.json\n", + "Loading module modules/osteoarthritis.json\n", + "Loading module modules/osteoporosis.json\n", + "Loading module modules/pregnancy.json\n", + "Loading module modules/prescribing_opioids_for_chronic_pain_and_treatment_of_oud.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/rheumatoid_arthritis.json\n", + "Loading module modules/self_harm.json\n", + "Loading module modules/sepsis.json\n", + "Loading module modules/sexual_activity.json\n", + "Loading module modules/sinusitis.json\n", + "Loading module modules/sleep_apnea.json\n", + "Loading module modules/sore_throat.json\n", + "Loading module modules/spina_bifida.json\n", + "Loading module modules/stable_ischemic_heart_disease.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/stroke.json\n", + "Loading module modules/total_joint_replacement.json\n", + "Loading module modules/trigger_bone_marrow_transplant.json\n", + "Loading module modules/urinary_tract_infections.json\n", + "Loading Lookup Table: uti.csv\n", + "Loading Lookup Table: uti_recurrence.csv\n", + "Loading module modules/veteran.json\n", + "Loading module modules/veteran_hyperlipidemia.json\n", + "Loading module modules/veteran_lung_cancer.json\n", + "Loading module modules/veteran_mdd.json\n", + "Loading module modules/veteran_prostate_cancer.json\n", + "Loading module modules/veteran_ptsd.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/veteran_self_harm.json\n", + "Loading module modules/veteran_substance_abuse_conditions.json\n", + "Loading module modules/veteran_substance_abuse_treatment.json\n", + "Loading module modules/vhd_aortic.json\n", + "Loading Lookup Table: vhd_as.csv\n", + "Loading Lookup Table: vhd_ar.csv\n", + "Loading module modules/vhd_mitral.json\n", + "Loading Lookup Table: vhd_mr.csv\n", + "Loading Lookup Table: vhd_ms.csv\n", + "Loading module modules/vhd_pulmonic.json\n", + "Loading Lookup Table: vhd_ps.csv\n", + "Loading Lookup Table: vhd_pr.csv\n", + "Loading module modules/vhd_tricuspid.json\n", + "Loading Lookup Table: vhd_tr.csv\n", + "Loading Lookup Table: vhd_ts.csv\n", + "Loading module modules/wellness_encounters.json\n", + "Running with options:\n", + "Population: 3\n", + "Seed: 7\n", + "Provider Seed:1791484082286\n", + "Reference Time: 1791484082286\n", + "Location: Massachusetts\n", + "Min Age: 0\n", + "Max Age: 140\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 -- Darron84 Hegmann834 (36 y/o M) Salem, Massachusetts (50652)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 -- Samara159 Runolfsdottir785 (14 y/o F) Chelsea, Massachusetts (20570)\n", + "3 -- Gwyn381 Runolfsson901 (22 y/o F) North Attleborough, Massachusetts (31764)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Records: total=3, alive=3, dead=0\n", + "RNG=3\n", + "Clinician RNG=5640\n", + "\n", + "\u001b[32mYou've just generated 3 patients!\u001b[0m We're happy to know Synthea is helping you with your project.\n", + "Like what we're doing? Synthea is an open-source project, and your support helps us keep building.\n", + "Please consider \u001b[34m\u001b]8;;https://github.com/sponsors/synthetichealth\u0007making a donation\u001b]8;;\u0007\u001b[0m (https://github.com/sponsors/synthetichealth).\n", + "\n" + ] + }, + { + "data": { + "text/plain": [ + "['allergies.csv',\n", + " 'careplans.csv',\n", + " 'claims.csv',\n", + " 'claims_transactions.csv',\n", + " 'conditions.csv',\n", + " 'devices.csv',\n", + " 'encounters.csv',\n", + " 'imaging_studies.csv',\n", + " 'immunizations.csv',\n", + " 'medications.csv',\n", + " 'observations.csv',\n", + " 'organizations.csv',\n", + " 'patients.csv',\n", + " 'payer_transitions.csv',\n", + " 'payers.csv',\n", + " 'procedures.csv',\n", + " 'providers.csv',\n", + " 'supplies.csv']" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "csv_path = synthea.generate(**settings)\n", + "smaller_path = synthea.generate(population=3, seed=7, synthea_config=common_config)\n", + "\n", + "assert csv_path != smaller_path\n", + "assert (csv_path / \"patients.csv\").is_file()\n", + "assert (smaller_path / \"patients.csv\").is_file()\n", + "sorted(path.name for path in csv_path.glob(\"*.csv\"))" + ] + }, + { + "cell_type": "markdown", + "id": "3f775bd5", + "metadata": {}, + "source": [ + "Calling `generate()` again with identical settings returns the existing directory immediately instead of rerunning Synthea. `overwrite=True` forces a fresh run into the same directory. If `seed` is omitted, a random seed is chosen and logged, so each seedless call is a new population." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "2e4a4c96", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:28:14.759331Z", + "iopub.status.busy": "2026-10-08T18:28:14.759213Z", + "iopub.status.idle": "2026-10-08T18:28:29.277680Z", + "shell.execute_reply": "2026-10-08T18:28:29.277143Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reusing existing Synthea output at /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Synthea: /home/soham/.local/jvm/jdk-17.0.20.1+1/bin/java -jar /home/soham/.cache/pyhealth/synthea/synthea-with-dependencies-v4.0.0.jar --exporter.baseDirectory=/home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4 --exporter.bfd.export=false --exporter.ccda.export=false --exporter.cdw.export=false --exporter.clinical_note.export=false --exporter.cpcds.export=false --exporter.csv.append_mode=false --exporter.csv.export=true --exporter.csv.folder_per_run=false --exporter.fhir.export=false --exporter.fhir_dstu2.export=false --exporter.fhir_stu3.export=false --exporter.json.export=false --exporter.symptoms.csv.export=false --exporter.symptoms.text.export=false --exporter.text.export=false --exporter.years_of_history=5 --generate.only_alive_patients=true --generate.thread_pool_size=1 -s 42 -cs 43 -p 10 -r 20240101 -g F -a 30-40 -o false Massachusetts Boston\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "org.mitre.synthea.X12.ExporterAdaptor\n", + "org.mitre.synthea.X12.ExporterAdaptor\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "SLF4J: No SLF4J providers were found.\n", + "SLF4J: Defaulting to no-operation (NOP) logger implementation\n", + "SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanned 92 modules and 449 submodules.\n", + "Loading submodule modules/allergies/allergy_panel.json\n", + "Loading submodule modules/allergies/drug_allergy_incidence.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/allergies/environmental_allergy_incidence.json\n", + "Loading submodule modules/allergies/food_allergy_incidence.json\n", + "Loading submodule modules/allergies/immunotherapy.json\n", + "Loading submodule modules/allergies/outgrow_env_allergies.json\n", + "Loading submodule modules/allergies/outgrow_food_allergies.json\n", + "Loading submodule modules/allergies/severe_allergic_reaction.json\n", + "Loading submodule modules/anemia/anemia_sub.json\n", + "Loading submodule modules/breast_cancer/chemotherapy_breast.json\n", + "Loading submodule modules/breast_cancer/hormone_diagnosis.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/breast_cancer/hormonetherapy_breast.json\n", + "Loading submodule modules/breast_cancer/surgery_therapy_breast.json\n", + "Loading submodule modules/breast_cancer/tnm_diagnosis.json\n", + "Loading submodule modules/contraceptives/clear_contraceptive.json\n", + "Loading submodule modules/contraceptives/female_sterilization.json\n", + "Loading submodule modules/contraceptives/implant_contraceptive.json\n", + "Loading submodule modules/contraceptives/injectable_contraceptive.json\n", + "Loading submodule modules/contraceptives/intrauterine_device.json\n", + "Loading submodule modules/contraceptives/male_sterilization.json\n", + "Loading submodule modules/contraceptives/oral_contraceptive.json\n", + "Loading submodule modules/contraceptives/patch_contraceptive.json\n", + "Loading submodule modules/contraceptives/ring_contraceptive.json\n", + "Loading submodule modules/covid19/admission.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/covid19/determine_risk.json\n", + "Loading Lookup Table: covid-19-severity-outcomes.csv\n", + "Loading Lookup Table: covid-19-survival-outcomes.csv\n", + "Loading submodule modules/covid19/diagnose_bacterial_infection.json\n", + "Loading submodule modules/covid19/diagnose_blood_clot.json\n", + "Loading submodule modules/covid19/end_outcomes.json\n", + "Loading submodule modules/covid19/end_symptoms.json\n", + "Loading submodule modules/covid19/infection.json\n", + "Loading submodule modules/covid19/measurements_daily.json\n", + "Loading submodule modules/covid19/measurements_frequent.json\n", + "Loading submodule modules/covid19/measurements_vitals.json\n", + "Loading submodule modules/covid19/medications.json\n", + "Loading submodule modules/covid19/nonsurvivor_lab_values.json\n", + "Loading submodule modules/covid19/outcomes.json\n", + "Loading submodule modules/covid19/supplies_hospitalization.json\n", + "Loading submodule modules/covid19/supplies_icu.json\n", + "Loading submodule modules/covid19/supplies_intubation.json\n", + "Loading submodule modules/covid19/survivor_lab_values.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/covid19/symptoms.json\n", + "Loading submodule modules/covid19/treat_blood_clot.json\n", + "Loading submodule modules/dental/dental_emergency.json\n", + "Loading submodule modules/dental/dental_encounter.json\n", + "Loading submodule modules/dental/dental_hospital.json\n", + "Loading submodule modules/dental/dental_telephone.json\n", + "Loading submodule modules/dental/diagnosis/cavity.json\n", + "Loading submodule modules/dental/diagnosis/dental disorder.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/diagnosis/gingivitis.json\n", + "Loading submodule modules/dental/diagnosis/periodontitis.json\n", + "Loading submodule modules/dental/diagnosis/plaque.json\n", + "Loading submodule modules/dental/end_dental_diagnoses.json\n", + "Loading submodule modules/dental/procedure/d01.json\n", + "Loading submodule modules/dental/procedure/d02.json\n", + "Loading submodule modules/dental/procedure/d03.json\n", + "Loading submodule modules/dental/procedure/d04.json\n", + "Loading submodule modules/dental/procedure/d05.json\n", + "Loading submodule modules/dental/procedure/d06.json\n", + "Loading submodule modules/dental/procedure/d09.json\n", + "Loading submodule modules/dental/procedure/d11.json\n", + "Loading submodule modules/dental/procedure/d12.json\n", + "Loading submodule modules/dental/procedure/d13.json\n", + "Loading submodule modules/dental/procedure/d15.json\n", + "Loading submodule modules/dental/procedure/d19.json\n", + "Loading submodule modules/dental/procedure/d21.json\n", + "Loading submodule modules/dental/procedure/d23.json\n", + "Loading submodule modules/dental/procedure/d25.json\n", + "Loading submodule modules/dental/procedure/d26.json\n", + "Loading submodule modules/dental/procedure/d27.json\n", + "Loading submodule modules/dental/procedure/d29.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d31.json\n", + "Loading submodule modules/dental/procedure/d32.json\n", + "Loading submodule modules/dental/procedure/d33.json\n", + "Loading submodule modules/dental/procedure/d34.json\n", + "Loading submodule modules/dental/procedure/d39.json\n", + "Loading submodule modules/dental/procedure/d42.json\n", + "Loading submodule modules/dental/procedure/d43.json\n", + "Loading submodule modules/dental/procedure/d49.json\n", + "Loading submodule modules/dental/procedure/d51.json\n", + "Loading submodule modules/dental/procedure/d52.json\n", + "Loading submodule modules/dental/procedure/d54.json\n", + "Loading submodule modules/dental/procedure/d55.json\n", + "Loading submodule modules/dental/procedure/d56.json\n", + "Loading submodule modules/dental/procedure/d57.json\n", + "Loading submodule modules/dental/procedure/d58.json\n", + "Loading submodule modules/dental/procedure/d59.json\n", + "Loading submodule modules/dental/procedure/d60.json\n", + "Loading submodule modules/dental/procedure/d61.json\n", + "Loading submodule modules/dental/procedure/d62.json\n", + "Loading submodule modules/dental/procedure/d65.json\n", + "Loading submodule modules/dental/procedure/d66.json\n", + "Loading submodule modules/dental/procedure/d67.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental/procedure/d69.json\n", + "Loading submodule modules/dental/procedure/d71.json\n", + "Loading submodule modules/dental/procedure/d72.json\n", + "Loading submodule modules/dental/procedure/d73.json\n", + "Loading submodule modules/dental/procedure/d74.json\n", + "Loading submodule modules/dental/procedure/d75.json\n", + "Loading submodule modules/dental/procedure/d76.json\n", + "Loading submodule modules/dental/procedure/d77.json\n", + "Loading submodule modules/dental/procedure/d78.json\n", + "Loading submodule modules/dental/procedure/d79.json\n", + "Loading submodule modules/dental/procedure/d80.json\n", + "Loading submodule modules/dental/procedure/d82.json\n", + "Loading submodule modules/dental/procedure/d86.json\n", + "Loading submodule modules/dental/procedure/d89.json\n", + "Loading submodule modules/dental/procedure/d91.json\n", + "Loading submodule modules/dental/procedure/d92.json\n", + "Loading submodule modules/dental/procedure/d93.json\n", + "Loading submodule modules/dental/procedure/d94.json\n", + "Loading submodule modules/dental/procedure/d96.json\n", + "Loading submodule modules/dental/procedure/d99.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_0.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/dental_idr_cluster_1.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_2.json\n", + "Loading submodule modules/dental_idr/dental_idr_cluster_3.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/dental_idr_cluster_4.json\n", + "Loading submodule modules/dental_idr/diagnosis/c00.json\n", + "Loading submodule modules/dental_idr/diagnosis/c01.json\n", + "Loading submodule modules/dental_idr/diagnosis/c02.json\n", + "Loading submodule modules/dental_idr/diagnosis/c03.json\n", + "Loading submodule modules/dental_idr/diagnosis/c04.json\n", + "Loading submodule modules/dental_idr/diagnosis/c05.json\n", + "Loading submodule modules/dental_idr/diagnosis/c06.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c07.json\n", + "Loading submodule modules/dental_idr/diagnosis/c08.json\n", + "Loading submodule modules/dental_idr/diagnosis/c09.json\n", + "Loading submodule modules/dental_idr/diagnosis/c10.json\n", + "Loading submodule modules/dental_idr/diagnosis/c11.json\n", + "Loading submodule modules/dental_idr/diagnosis/c12.json\n", + "Loading submodule modules/dental_idr/diagnosis/c13.json\n", + "Loading submodule modules/dental_idr/diagnosis/c14.json\n", + "Loading submodule modules/dental_idr/diagnosis/c15.json\n", + "Loading submodule modules/dental_idr/diagnosis/c16.json\n", + "Loading submodule modules/dental_idr/diagnosis/c17.json\n", + "Loading submodule modules/dental_idr/diagnosis/c18.json\n", + "Loading submodule modules/dental_idr/diagnosis/c19.json\n", + "Loading submodule modules/dental_idr/diagnosis/c20.json\n", + "Loading submodule modules/dental_idr/diagnosis/c21.json\n", + "Loading submodule modules/dental_idr/diagnosis/c22.json\n", + "Loading submodule modules/dental_idr/diagnosis/c24.json\n", + "Loading submodule modules/dental_idr/diagnosis/c25.json\n", + "Loading submodule modules/dental_idr/diagnosis/c26.json\n", + "Loading submodule modules/dental_idr/diagnosis/c30.json\n", + "Loading submodule modules/dental_idr/diagnosis/c31.json\n", + "Loading submodule modules/dental_idr/diagnosis/c32.json\n", + "Loading submodule modules/dental_idr/diagnosis/c33.json\n", + "Loading submodule modules/dental_idr/diagnosis/c34.json\n", + "Loading submodule modules/dental_idr/diagnosis/c37.json\n", + "Loading submodule modules/dental_idr/diagnosis/c38.json\n", + "Loading submodule modules/dental_idr/diagnosis/c39.json\n", + "Loading submodule modules/dental_idr/diagnosis/c40.json\n", + "Loading submodule modules/dental_idr/diagnosis/c41.json\n", + "Loading submodule modules/dental_idr/diagnosis/c43.json\n", + "Loading submodule modules/dental_idr/diagnosis/c44.json\n", + "Loading submodule modules/dental_idr/diagnosis/c45.json\n", + "Loading submodule modules/dental_idr/diagnosis/c46.json\n", + "Loading submodule modules/dental_idr/diagnosis/c47.json\n", + "Loading submodule modules/dental_idr/diagnosis/c48.json\n", + "Loading submodule modules/dental_idr/diagnosis/c49.json\n", + "Loading submodule modules/dental_idr/diagnosis/c4a.json\n", + "Loading submodule modules/dental_idr/diagnosis/c50.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c51.json\n", + "Loading submodule modules/dental_idr/diagnosis/c53.json\n", + "Loading submodule modules/dental_idr/diagnosis/c54.json\n", + "Loading submodule modules/dental_idr/diagnosis/c56.json\n", + "Loading submodule modules/dental_idr/diagnosis/c57.json\n", + "Loading submodule modules/dental_idr/diagnosis/c61.json\n", + "Loading submodule modules/dental_idr/diagnosis/c62.json\n", + "Loading submodule modules/dental_idr/diagnosis/c63.json\n", + "Loading submodule modules/dental_idr/diagnosis/c64.json\n", + "Loading submodule modules/dental_idr/diagnosis/c65.json\n", + "Loading submodule modules/dental_idr/diagnosis/c66.json\n", + "Loading submodule modules/dental_idr/diagnosis/c67.json\n", + "Loading submodule modules/dental_idr/diagnosis/c68.json\n", + "Loading submodule modules/dental_idr/diagnosis/c69.json\n", + "Loading submodule modules/dental_idr/diagnosis/c71.json\n", + "Loading submodule modules/dental_idr/diagnosis/c72.json\n", + "Loading submodule modules/dental_idr/diagnosis/c73.json\n", + "Loading submodule modules/dental_idr/diagnosis/c74.json\n", + "Loading submodule modules/dental_idr/diagnosis/c75.json\n", + "Loading submodule modules/dental_idr/diagnosis/c76.json\n", + "Loading submodule modules/dental_idr/diagnosis/c77.json\n", + "Loading submodule modules/dental_idr/diagnosis/c78.json\n", + "Loading submodule modules/dental_idr/diagnosis/c79.json\n", + "Loading submodule modules/dental_idr/diagnosis/c7a.json\n", + "Loading submodule modules/dental_idr/diagnosis/c7b.json\n", + "Loading submodule modules/dental_idr/diagnosis/c80.json\n", + "Loading submodule modules/dental_idr/diagnosis/c81.json\n", + "Loading submodule modules/dental_idr/diagnosis/c82.json\n", + "Loading submodule modules/dental_idr/diagnosis/c83.json\n", + "Loading submodule modules/dental_idr/diagnosis/c84.json\n", + "Loading submodule modules/dental_idr/diagnosis/c85.json\n", + "Loading submodule modules/dental_idr/diagnosis/c86.json\n", + "Loading submodule modules/dental_idr/diagnosis/c88.json\n", + "Loading submodule modules/dental_idr/diagnosis/c90.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/c91.json\n", + "Loading submodule modules/dental_idr/diagnosis/c92.json\n", + "Loading submodule modules/dental_idr/diagnosis/c93.json\n", + "Loading submodule modules/dental_idr/diagnosis/c95.json\n", + "Loading submodule modules/dental_idr/diagnosis/c96.json\n", + "Loading submodule modules/dental_idr/diagnosis/d00.json\n", + "Loading submodule modules/dental_idr/diagnosis/d01.json\n", + "Loading submodule modules/dental_idr/diagnosis/d02.json\n", + "Loading submodule modules/dental_idr/diagnosis/d03.json\n", + "Loading submodule modules/dental_idr/diagnosis/d04.json\n", + "Loading submodule modules/dental_idr/diagnosis/d05.json\n", + "Loading submodule modules/dental_idr/diagnosis/d06.json\n", + "Loading submodule modules/dental_idr/diagnosis/d07.json\n", + "Loading submodule modules/dental_idr/diagnosis/d09.json\n", + "Loading submodule modules/dental_idr/diagnosis/d10.json\n", + "Loading submodule modules/dental_idr/diagnosis/d11.json\n", + "Loading submodule modules/dental_idr/diagnosis/d12.json\n", + "Loading submodule modules/dental_idr/diagnosis/d13.json\n", + "Loading submodule modules/dental_idr/diagnosis/d14.json\n", + "Loading submodule modules/dental_idr/diagnosis/d16.json\n", + "Loading submodule modules/dental_idr/diagnosis/d17.json\n", + "Loading submodule modules/dental_idr/diagnosis/d18.json\n", + "Loading submodule modules/dental_idr/diagnosis/d19.json\n", + "Loading submodule modules/dental_idr/diagnosis/d21.json\n", + "Loading submodule modules/dental_idr/diagnosis/d22.json\n", + "Loading submodule modules/dental_idr/diagnosis/d23.json\n", + "Loading submodule modules/dental_idr/diagnosis/d24.json\n", + "Loading submodule modules/dental_idr/diagnosis/d25.json\n", + "Loading submodule modules/dental_idr/diagnosis/d28.json\n", + "Loading submodule modules/dental_idr/diagnosis/d29.json\n", + "Loading submodule modules/dental_idr/diagnosis/d30.json\n", + "Loading submodule modules/dental_idr/diagnosis/d31.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/d32.json\n", + "Loading submodule modules/dental_idr/diagnosis/d33.json\n", + "Loading submodule modules/dental_idr/diagnosis/d34.json\n", + "Loading submodule modules/dental_idr/diagnosis/d35.json\n", + "Loading submodule modules/dental_idr/diagnosis/d36.json\n", + "Loading submodule modules/dental_idr/diagnosis/d37.json\n", + "Loading submodule modules/dental_idr/diagnosis/d38.json\n", + "Loading submodule modules/dental_idr/diagnosis/d39.json\n", + "Loading submodule modules/dental_idr/diagnosis/d3a.json\n", + "Loading submodule modules/dental_idr/diagnosis/d40.json\n", + "Loading submodule modules/dental_idr/diagnosis/d41.json\n", + "Loading submodule modules/dental_idr/diagnosis/d44.json\n", + "Loading submodule modules/dental_idr/diagnosis/d45.json\n", + "Loading submodule modules/dental_idr/diagnosis/d46.json\n", + "Loading submodule modules/dental_idr/diagnosis/d47.json\n", + "Loading submodule modules/dental_idr/diagnosis/d48.json\n", + "Loading submodule modules/dental_idr/diagnosis/d49.json\n", + "Loading submodule modules/dental_idr/diagnosis/k00.json\n", + "Loading submodule modules/dental_idr/diagnosis/k01.json\n", + "Loading submodule modules/dental_idr/diagnosis/k02.json\n", + "Loading submodule modules/dental_idr/diagnosis/k03.json\n", + "Loading submodule modules/dental_idr/diagnosis/k04.json\n", + "Loading submodule modules/dental_idr/diagnosis/k05.json\n", + "Loading submodule modules/dental_idr/diagnosis/k06.json\n", + "Loading submodule modules/dental_idr/diagnosis/k08.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/k09.json\n", + "Loading submodule modules/dental_idr/diagnosis/k11.json\n", + "Loading submodule modules/dental_idr/diagnosis/k12.json\n", + "Loading submodule modules/dental_idr/diagnosis/k13.json\n", + "Loading submodule modules/dental_idr/diagnosis/m26.json\n", + "Loading submodule modules/dental_idr/diagnosis/m27.json\n", + "Loading submodule modules/dental_idr/diagnosis/r69.json\n", + "Loading submodule modules/dental_idr/diagnosis/s02.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/diagnosis/z00.json\n", + "Loading submodule modules/dental_idr/diagnosis/z01.json\n", + "Loading submodule modules/dental_idr/diagnosis/z13.json\n", + "Loading submodule modules/dental_idr/diagnosis/z40.json\n", + "Loading submodule modules/dental_idr/diagnosis/z41.json\n", + "Loading submodule modules/dental_idr/diagnosis/z51.json\n", + "Loading submodule modules/dental_idr/end_dental_diagnoses.json\n", + "Loading submodule modules/dental_idr/procedure/d01.json\n", + "Loading submodule modules/dental_idr/procedure/d02.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d03.json\n", + "Loading submodule modules/dental_idr/procedure/d04.json\n", + "Loading submodule modules/dental_idr/procedure/d05.json\n", + "Loading submodule modules/dental_idr/procedure/d06.json\n", + "Loading submodule modules/dental_idr/procedure/d07.json\n", + "Loading submodule modules/dental_idr/procedure/d08.json\n", + "Loading submodule modules/dental_idr/procedure/d09.json\n", + "Loading submodule modules/dental_idr/procedure/d11.json\n", + "Loading submodule modules/dental_idr/procedure/d12.json\n", + "Loading submodule modules/dental_idr/procedure/d13.json\n", + "Loading submodule modules/dental_idr/procedure/d15.json\n", + "Loading submodule modules/dental_idr/procedure/d17.json\n", + "Loading submodule modules/dental_idr/procedure/d19.json\n", + "Loading submodule modules/dental_idr/procedure/d21.json\n", + "Loading submodule modules/dental_idr/procedure/d23.json\n", + "Loading submodule modules/dental_idr/procedure/d24.json\n", + "Loading submodule modules/dental_idr/procedure/d25.json\n", + "Loading submodule modules/dental_idr/procedure/d26.json\n", + "Loading submodule modules/dental_idr/procedure/d27.json\n", + "Loading submodule modules/dental_idr/procedure/d29.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d31.json\n", + "Loading submodule modules/dental_idr/procedure/d32.json\n", + "Loading submodule modules/dental_idr/procedure/d33.json\n", + "Loading submodule modules/dental_idr/procedure/d34.json\n", + "Loading submodule modules/dental_idr/procedure/d35.json\n", + "Loading submodule modules/dental_idr/procedure/d39.json\n", + "Loading submodule modules/dental_idr/procedure/d42.json\n", + "Loading submodule modules/dental_idr/procedure/d43.json\n", + "Loading submodule modules/dental_idr/procedure/d49.json\n", + "Loading submodule modules/dental_idr/procedure/d51.json\n", + "Loading submodule modules/dental_idr/procedure/d52.json\n", + "Loading submodule modules/dental_idr/procedure/d54.json\n", + "Loading submodule modules/dental_idr/procedure/d55.json\n", + "Loading submodule modules/dental_idr/procedure/d56.json\n", + "Loading submodule modules/dental_idr/procedure/d57.json\n", + "Loading submodule modules/dental_idr/procedure/d58.json\n", + "Loading submodule modules/dental_idr/procedure/d59.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d60.json\n", + "Loading submodule modules/dental_idr/procedure/d61.json\n", + "Loading submodule modules/dental_idr/procedure/d62.json\n", + "Loading submodule modules/dental_idr/procedure/d65.json\n", + "Loading submodule modules/dental_idr/procedure/d66.json\n", + "Loading submodule modules/dental_idr/procedure/d67.json\n", + "Loading submodule modules/dental_idr/procedure/d69.json\n", + "Loading submodule modules/dental_idr/procedure/d71.json\n", + "Loading submodule modules/dental_idr/procedure/d72.json\n", + "Loading submodule modules/dental_idr/procedure/d73.json\n", + "Loading submodule modules/dental_idr/procedure/d74.json\n", + "Loading submodule modules/dental_idr/procedure/d75.json\n", + "Loading submodule modules/dental_idr/procedure/d76.json\n", + "Loading submodule modules/dental_idr/procedure/d77.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/dental_idr/procedure/d78.json\n", + "Loading submodule modules/dental_idr/procedure/d79.json\n", + "Loading submodule modules/dental_idr/procedure/d80.json\n", + "Loading submodule modules/dental_idr/procedure/d82.json\n", + "Loading submodule modules/dental_idr/procedure/d86.json\n", + "Loading submodule modules/dental_idr/procedure/d87.json\n", + "Loading submodule modules/dental_idr/procedure/d89.json\n", + "Loading submodule modules/dental_idr/procedure/d91.json\n", + "Loading submodule modules/dental_idr/procedure/d92.json\n", + "Loading submodule modules/dental_idr/procedure/d93.json\n", + "Loading submodule modules/dental_idr/procedure/d94.json\n", + "Loading submodule modules/dental_idr/procedure/d96.json\n", + "Loading submodule modules/dental_idr/procedure/d99.json\n", + "Loading submodule modules/dermatitis/early_moderate_eczema_obs.json\n", + "Loading submodule modules/dermatitis/early_severe_eczema_obs.json\n", + "Loading submodule modules/dermatitis/mid_moderate_eczema_obs.json\n", + "Loading submodule modules/dermatitis/mid_severe_eczema_obs.json\n", + "Loading submodule modules/dermatitis/moderate_cd_obs.json\n", + "Loading submodule modules/dermatitis/severe_cd_obs.json\n", + "Loading submodule modules/dme/wheelchair.json\n", + "Loading submodule modules/dme/wheelchair_end.json\n", + "Loading submodule modules/encounter/anxiety_screening.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/encounter/depression_screening.json\n", + "Loading submodule modules/encounter/fall_risk_screening.json\n", + "Loading submodule modules/encounter/hark_screening.json\n", + "Loading submodule modules/encounter/hospital_basic_labs.json\n", + "Loading submodule modules/encounter/sdoh_hrsn.json\n", + "Loading submodule modules/encounter/substance_use_screening.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/encounter/vitals.json\n", + "Loading submodule modules/eye/intraocular_pressure.json\n", + "Loading submodule modules/eye/ophthalmic_progression.json\n", + "Loading submodule modules/eye/ophthalmic_tomography.json\n", + "Loading submodule modules/eye/visual_acuity.json\n", + "Loading submodule modules/heart/acs_anticoagulant.json\n", + "Loading submodule modules/heart/acs_antiplatelet.json\n", + "Loading submodule modules/heart/acs_arrival_medications.json\n", + "Loading submodule modules/heart/acs_discharge_meds.json\n", + "Loading submodule modules/heart/avrr/antithrombotic.json\n", + "Loading submodule modules/heart/avrr/avrr_referral.json\n", + "Loading submodule modules/heart/avrr/intraop_meds_blood.json\n", + "Loading submodule modules/heart/avrr/outcomes.json\n", + "Loading submodule modules/heart/avrr/preoperative.json\n", + "Loading submodule modules/heart/avrr/savrr_operation.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/avrr/savrr_postop.json\n", + "Loading submodule modules/heart/avrr/sequence.json\n", + "Loading submodule modules/heart/cabg/cabg_referral.json\n", + "Loading submodule modules/heart/cabg/details.json\n", + "Loading Lookup Table: cabg_details_operative_approach.csv\n", + "Loading Lookup Table: cabg_details_num_grafts.csv\n", + "Loading Lookup Table: cabg_details_num_art_cond.csv\n", + "Loading submodule modules/heart/cabg/icu_meds_devices.json\n", + "Loading submodule modules/heart/cabg/labs_common.json\n", + "Loading submodule modules/heart/cabg/operation.json\n", + "Loading submodule modules/heart/cabg/or_intraop.json\n", + "Loading submodule modules/heart/cabg/or_labs_meds.json\n", + "Loading submodule modules/heart/cabg/outcomes.json\n", + "Loading submodule modules/heart/cabg/postop.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/cabg/postop_blood.json\n", + "Loading submodule modules/heart/cabg/preoperative.json\n", + "Loading submodule modules/heart/cabg_sequence.json\n", + "Loading submodule modules/heart/cardiac_labs.json\n", + "Loading submodule modules/heart/chf_lab_work.json\n", + "Loading submodule modules/heart/chf_lvad.json\n", + "Loading submodule modules/heart/chf_meds.json\n", + "Loading submodule modules/heart/chf_meds_hfmef.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha2.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha3.json\n", + "Loading submodule modules/heart/chf_meds_hfref_nyha4.json\n", + "Loading submodule modules/heart/chf_nyha_panel.json\n", + "Loading submodule modules/heart/chf_transplant.json\n", + "Loading submodule modules/heart/nsteacs_pathway.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/heart/operative_status.json\n", + "Loading submodule modules/heart/or_blood.json\n", + "Loading Lookup Table: or_blood_anemia_check.csv\n", + "Loading Lookup Table: or_blood_platelet_check.csv\n", + "Loading Lookup Table: or_blood_plasma_check.csv\n", + "Loading submodule modules/heart/savrepair/operative_status.json\n", + "Loading submodule modules/heart/savreplace/operative_status.json\n", + "Loading submodule modules/heart/stemi_fibrinolytic.json\n", + "Loading submodule modules/heart/stemi_pathway.json\n", + "Loading submodule modules/heart/tavr/alt_access.json\n", + "Loading submodule modules/heart/tavr/operation.json\n", + "Loading submodule modules/heart/tavr/operative_status.json\n", + "Loading submodule modules/heart/tavr/outcomes.json\n", + "Loading submodule modules/heart/tavr/postop.json\n", + "Loading submodule modules/heart/vhd_risks.json\n", + "Loading submodule modules/hiv/art_sequence.json\n", + "Loading submodule modules/hiv/art_sequence_1987_1994.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/hiv/art_sequence_1995_1996.json\n", + "Loading submodule modules/hiv/art_sequence_1997_2002.json\n", + "Loading submodule modules/hiv/art_sequence_2003_2005.json\n", + "Loading submodule modules/hiv/art_sequence_2006_2014.json\n", + "Loading submodule modules/hiv/art_sequence_2015.json\n", + "Loading submodule modules/hiv/hiv_baseline.json\n", + "Loading submodule modules/hiv/hiv_cd4.json\n", + "Loading Lookup Table: hiv_stage.csv\n", + "Loading submodule modules/hiv/hiv_oi_prophylaxis.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/hiv/hiv_screening.json\n", + "Loading submodule modules/hiv/hiv_viral_load.json\n", + "Loading submodule modules/hiv/stop_all_art_meds.json\n", + "Loading submodule modules/injuries/broken_jaw.json\n", + "Loading submodule modules/lung_cancer/lung_cancer_probabilities.json\n", + "Loading submodule modules/medications/ace_arb.json\n", + "Loading Lookup Table: ace_arb_ingredient_distribution.csv\n", + "Loading Lookup Table: ace_arb_amlodipine_benazepril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_benazepril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_benazepril_hydrochlorothiazide_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_enalapril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_lisinopril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_losartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_hydrochlorothiazide_valsartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_irbesartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_lisinopril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_losartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_quinapril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_ramipril_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_sacubitril_valsartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_telmisartan_product_distribution.csv\n", + "Loading Lookup Table: ace_arb_valsartan_product_distribution.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/medications/beta_blocker.json\n", + "Loading Lookup Table: beta_blocker_ingredient_distribution.csv\n", + "Loading Lookup Table: beta_blocker_atenolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_bisoprolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_bisoprolol_hydrochlorothiazide_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_carvedilol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_labetalol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_metoprolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_nebivolol_product_distribution.csv\n", + "Loading Lookup Table: beta_blocker_propranolol_product_distribution.csv\n", + "Loading submodule modules/medications/ear_infection_antibiotic.json\n", + "Loading submodule modules/medications/emergency_inhaler.json\n", + "Loading Lookup Table: emergency_inhaler_ingredient_distribution.csv\n", + "Loading Lookup Table: emergency_inhaler_albuterol_product_distribution.csv\n", + "Loading Lookup Table: emergency_inhaler_levalbuterol_product_distribution.csv\n", + "Loading submodule modules/medications/hypertension_medication.json\n", + "Loading submodule modules/medications/maintenance_inhaler.json\n", + "Loading Lookup Table: maintenance_inhaler_ingredient_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_beclomethasone_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_budesonide_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_fluticasone_product_distribution.csv\n", + "Loading Lookup Table: maintenance_inhaler_mometasone_product_distribution.csv\n", + "Loading submodule modules/medications/moderate_opioid_pain_reliever.json\n", + "Loading submodule modules/medications/otc_antihistamine.json\n", + "Loading submodule modules/medications/otc_pain_reliever.json\n", + "Loading submodule modules/medications/statin.json\n", + "Loading Lookup Table: statin_ingredient_distribution.csv\n", + "Loading Lookup Table: statin_atorvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_ezetimibe_simvastatin_product_distribution.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading Lookup Table: statin_lovastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_pitavastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_pravastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_rosuvastatin_product_distribution.csv\n", + "Loading Lookup Table: statin_simvastatin_product_distribution.csv\n", + "Loading submodule modules/medications/strong_opioid_pain_reliever.json\n", + "Loading submodule modules/metabolic_syndrome/amputations.json\n", + "Loading submodule modules/metabolic_syndrome/diabetic_retinopathy_diagnoses.json\n", + "Loading submodule modules/metabolic_syndrome/diabetic_retinopathy_progression.json\n", + "Loading submodule modules/metabolic_syndrome/dme_supplies.json\n", + "Loading submodule modules/metabolic_syndrome/kidney_conditions.json\n", + "Loading submodule modules/metabolic_syndrome/medications.json\n", + "Loading submodule modules/snf/skilled_nursing_facility.json\n", + "Loading submodule modules/surgery/general_anesthesia.json\n", + "Loading submodule modules/total_joint_replacement/functional_status_assessments.json\n", + "Loading submodule modules/uti/abx_tx.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading submodule modules/uti/ambulatory_eval.json\n", + "Loading submodule modules/uti/ambulatory_path.json\n", + "Loading submodule modules/uti/ed_bundle.json\n", + "Loading submodule modules/uti/ed_eval.json\n", + "Loading submodule modules/uti/ed_path.json\n", + "Loading submodule modules/uti/gu_pregnancy_check.json\n", + "Loading submodule modules/uti/hpi.json\n", + "Loading submodule modules/uti/lab_follow_up.json\n", + "Loading submodule modules/uti/labs.json\n", + "Loading submodule modules/uti/telemed_path.json\n", + "Loading submodule modules/veterans/veteran_suicide_probabilities.json\n", + "Loading submodule modules/weight_loss/mend_week.json\n", + "Loading module modules/AIS_From_School_Screening_to_SOSORT_Recommendations.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/acute_myeloid_leukemia.json\n", + "Loading Lookup Table: AML.csv\n", + "Loading module modules/allergic_rhinitis.json\n", + "Loading module modules/allergies.json\n", + "Loading module modules/anemia___unknown_etiology.json\n", + "Loading module modules/appendicitis.json\n", + "Loading module modules/asthma.json\n", + "Loading module modules/atopy.json\n", + "Loading module modules/atrial_fibrillation.json\n", + "Loading module modules/attention_deficit_disorder.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/bone_marrow_transplant.json\n", + "Loading module modules/breast_cancer.json\n", + "Loading module modules/bronchitis.json\n", + "Loading module modules/cerebral_palsy.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/chronic_kidney_disease.json\n", + "Loading module modules/colorectal_cancer.json\n", + "Loading module modules/congestive_heart_failure.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/contraceptive_maintenance.json\n", + "Loading module modules/contraceptives.json\n", + "Loading module modules/copd.json\n", + "Loading module modules/covid19.json\n", + "Loading Lookup Table: covid19_prob.csv\n", + "Loading module modules/cystic_fibrosis.json\n", + "Loading module modules/dementia.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/dental_and_oral_examination.json\n", + "Loading module modules/dental_encounters.json\n", + "Loading module modules/dental_medicare_clustered_encounters.json\n", + "Loading module modules/dentures.json\n", + "Loading module modules/dermatitis.json\n", + "Loading module modules/diabetic_retinopathy_treatment.json\n", + "Loading Lookup Table: diabetic_retinopathy_followup.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/dialysis.json\n", + "Loading module modules/ear_infections.json\n", + "Loading module modules/epilepsy.json\n", + "Loading module modules/female_reproduction.json\n", + "Loading module modules/fibromyalgia.json\n", + "Loading module modules/food_allergies.json\n", + "Loading module modules/gallstones.json\n", + "Loading module modules/gout.json\n", + "Loading module modules/hiv_care.json\n", + "Loading Lookup Table: hiv_care.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/hiv_diagnosis.json\n", + "Loading Lookup Table: hiv_mortality_later.csv\n", + "Loading Lookup Table: hiv_mortality_early.csv\n", + "Loading Lookup Table: hiv_mortality_very_early.csv\n", + "Loading Lookup Table: hiv_diagnosis_early.csv\n", + "Loading Lookup Table: hiv_diagnosis_later.csv\n", + "Loading module modules/home_health_treatment.json\n", + "Loading module modules/home_hospice_snf.json\n", + "Loading module modules/homelessness.json\n", + "Loading module modules/hospice_treatment.json\n", + "Loading module modules/hypertension.json\n", + "Loading module modules/hypothyroidism.json\n", + "Loading module modules/injuries.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/kidney_transplant.json\n", + "Loading module modules/lung_cancer.json\n", + "Loading module modules/lupus.json\n", + "Loading module modules/mTBI.json\n", + "Loading module modules/med_rec.json\n", + "Loading module modules/mend_program.json\n", + "Loading module modules/metabolic_syndrome_care.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/metabolic_syndrome_disease.json\n", + "Loading module modules/myocardial_infarction.json\n", + "Loading module modules/opioid_addiction.json\n", + "Loading module modules/osteoarthritis.json\n", + "Loading module modules/osteoporosis.json\n", + "Loading module modules/pregnancy.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/prescribing_opioids_for_chronic_pain_and_treatment_of_oud.json\n", + "Loading module modules/rheumatoid_arthritis.json\n", + "Loading module modules/self_harm.json\n", + "Loading module modules/sepsis.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/sexual_activity.json\n", + "Loading module modules/sinusitis.json\n", + "Loading module modules/sleep_apnea.json\n", + "Loading module modules/sore_throat.json\n", + "Loading module modules/spina_bifida.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/stable_ischemic_heart_disease.json\n", + "Loading module modules/stroke.json\n", + "Loading module modules/total_joint_replacement.json\n", + "Loading module modules/trigger_bone_marrow_transplant.json\n", + "Loading module modules/urinary_tract_infections.json\n", + "Loading Lookup Table: uti.csv\n", + "Loading Lookup Table: uti_recurrence.csv\n", + "Loading module modules/veteran.json\n", + "Loading module modules/veteran_hyperlipidemia.json\n", + "Loading module modules/veteran_lung_cancer.json\n", + "Loading module modules/veteran_mdd.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading module modules/veteran_prostate_cancer.json\n", + "Loading module modules/veteran_ptsd.json\n", + "Loading module modules/veteran_self_harm.json\n", + "Loading module modules/veteran_substance_abuse_conditions.json\n", + "Loading module modules/veteran_substance_abuse_treatment.json\n", + "Loading module modules/vhd_aortic.json\n", + "Loading Lookup Table: vhd_as.csv\n", + "Loading Lookup Table: vhd_ar.csv\n", + "Loading module modules/vhd_mitral.json\n", + "Loading Lookup Table: vhd_mr.csv\n", + "Loading Lookup Table: vhd_ms.csv\n", + "Loading module modules/vhd_pulmonic.json\n", + "Loading Lookup Table: vhd_ps.csv\n", + "Loading Lookup Table: vhd_pr.csv\n", + "Loading module modules/vhd_tricuspid.json\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loading Lookup Table: vhd_tr.csv\n", + "Loading Lookup Table: vhd_ts.csv\n", + "Loading module modules/wellness_encounters.json\n", + "Running with options:\n", + "Population: 10\n", + "Seed: 42\n", + "Provider Seed:43\n", + "Reference Time: 1704067200000\n", + "Location: Boston, Massachusetts\n", + "Min Age: 30\n", + "Max Age: 40\n", + "Gender: F\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 -- Corie618 Sofia418 Rath779 (40 y/o F) Boston, Massachusetts (55751)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2 -- Antonia30 Rosa195 Tapia475 (41 y/o F) Boston, Massachusetts (55585)\n", + "3 -- Lola232 Ariadna374 Cardona494 (37 y/o F) Boston, Massachusetts (50158)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4 -- Esperanza675 María Luisa888 Valverde277 (32 y/o F) Boston, Massachusetts (45515)\n", + "5 -- Jona712 Bonnie873 Rosenbaum794 (35 y/o F) Boston, Massachusetts (51640)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6 -- Tennille443 Denna536 Nitzsche158 (36 y/o F) Boston, Massachusetts (49197)\n", + "7 -- Ocie984 Bernie827 Homenick806 (40 y/o F) Boston, Massachusetts (56300)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "8 -- Lindsay928 Deja232 Pollich983 (38 y/o F) Boston, Massachusetts (52138)\n", + "9 -- Shondra529 Kyra237 Spinka232 (34 y/o F) Boston, Massachusetts (46387)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10 -- Chrissy459 Jolynn62 Stanton715 (40 y/o F) Boston, Massachusetts (58930)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Records: total=10, alive=10, dead=0\n", + "RNG=10\n", + "Clinician RNG=5638\n", + "\n", + "\u001b[32mYou've just generated 10 patients!\u001b[0m We're happy to know Synthea is helping you with your project.\n", + "Like what we're doing? Synthea is an open-source project, and your support helps us keep building.\n", + "Please consider \u001b[34m\u001b]8;;https://github.com/sponsors/synthetichealth\u0007making a donation\u001b]8;;\u0007\u001b[0m (https://github.com/sponsors/synthetichealth).\n", + "\n" + ] + } + ], + "source": [ + "reused_path = synthea.generate(**settings)\n", + "assert reused_path == csv_path\n", + "\n", + "overwritten_path = synthea.generate(**settings, overwrite=True)\n", + "assert overwritten_path == csv_path" + ] + }, + { + "cell_type": "markdown", + "id": "8a10f7ec", + "metadata": {}, + "source": [ + "## 4. Every `generate()` argument\n", + "\n", + "This is a **dry-run API example** using `build_argv()`. Snapshot, fixed-record, keep-matching, and custom-module inputs require domain-specific files, so these settings are only used to show argument coverage and inspect the command. Do not pass them to `generate()` until the placeholder files are replaced with valid Synthea inputs.\n", + "\n", + "Passing `None` means that option is omitted and Synthea uses its own default. When both `local_config_path` and `synthea_config` define a property, the mapping is emitted later as a command-line override and therefore wins." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "ff858a72", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:28:29.279182Z", + "iopub.status.busy": "2026-10-08T18:28:29.279065Z", + "iopub.status.idle": "2026-10-08T18:28:29.283989Z", + "shell.execute_reply": "2026-10-08T18:28:29.283505Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "java -jar synthea.jar -c /home/soham/PyHealth/examples/.artifacts/synthea_csv/argument_demo/local.properties --exporter.baseDirectory=/home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/1aa325cf3d707300d9d6e663cbaca600eaed444a06b7bf49988a6639194cfcf2 --exporter.bfd.export=false --exporter.ccda.export=false --exporter.cdw.export=false --exporter.clinical_note.export=false --exporter.cpcds.export=false --exporter.csv.append_mode=false --exporter.csv.export=true --exporter.csv.folder_per_run=false --exporter.fhir.export=false --exporter.fhir_dstu2.export=false --exporter.fhir_stu3.export=false --exporter.json.export=false --exporter.symptoms.csv.export=false --exporter.symptoms.text.export=false --exporter.text.export=false --generate.only_alive_patients=false --generate.thread_pool_size=1 -s 1001 -cs 1002 -ps 1003 -p 25 -r 20240101 -e 20241231 -g F -a 18-65 -o false -d /home/soham/PyHealth/examples/.artifacts/synthea_csv/argument_demo/modules -i /home/soham/PyHealth/examples/.artifacts/synthea_csv/argument_demo/initial.snapshot -u /home/soham/PyHealth/examples/.artifacts/synthea_csv/argument_demo/updated.snapshot -t 30 -f /home/soham/PyHealth/examples/.artifacts/synthea_csv/argument_demo/fixed_records.json -k /home/soham/PyHealth/examples/.artifacts/synthea_csv/argument_demo/keep_module.json Massachusetts Boston\n" + ] + } + ], + "source": [ + "demo_root = artifact_root / \"argument_demo\"\n", + "demo_root.mkdir(parents=True, exist_ok=True)\n", + "local_config_path = demo_root / \"local.properties\"\n", + "local_config_path.write_text(\n", + " \"generate.only_alive_patients = true\\n\"\n", + " \"exporter.years_of_history = 5\\n\",\n", + " encoding=\"utf-8\",\n", + ")\n", + "\n", + "all_generate_args = {\n", + " \"population\": 25,\n", + " \"seed\": 1001,\n", + " \"state\": \"Massachusetts\",\n", + " \"city\": \"Boston\",\n", + " \"clinician_seed\": 1002,\n", + " \"single_person_seed\": 1003,\n", + " \"reference_date\": \"20240101\",\n", + " \"end_date\": \"20241231\",\n", + " \"gender\": \"F\",\n", + " \"age_range\": \"18-65\",\n", + " \"overflow_population\": False,\n", + " \"local_config_path\": local_config_path,\n", + " \"local_modules_dir\": demo_root / \"modules\",\n", + " \"initial_population_snapshot_path\": demo_root / \"initial.snapshot\",\n", + " \"updated_population_snapshot_path\": demo_root / \"updated.snapshot\",\n", + " \"update_time_period\": 30,\n", + " \"fixed_record_path\": demo_root / \"fixed_records.json\",\n", + " \"keep_matching_patients_path\": demo_root / \"keep_module.json\",\n", + " \"synthea_config\": {\n", + " \"generate.thread_pool_size\": 1,\n", + " \"generate.only_alive_patients\": False,\n", + " \"exporter.csv.folder_per_run\": False,\n", + " \"exporter.csv.append_mode\": False,\n", + " },\n", + "}\n", + "\n", + "declared_args = set(inspect.signature(Synthea.generate).parameters) - {\"self\", \"overwrite\"}\n", + "assert set(all_generate_args) == declared_args\n", + "all_args_argv = synthea.build_argv(Path(\"java\"), Path(\"synthea.jar\"), **all_generate_args)\n", + "assert all_args_argv.index(\"-c\") < all_args_argv.index(\"--generate.only_alive_patients=false\")\n", + "print(shlex.join(all_args_argv))" + ] + }, + { + "cell_type": "markdown", + "id": "c90ff69c", + "metadata": {}, + "source": [ + "`generate()` argument to Synthea CLI mapping:\n", + "\n", + "| `generate()` argument | Synthea CLI | Meaning |\n", + "|---|---|---|\n", + "| `seed` | `-s` | Population random seed; random and logged when omitted |\n", + "| `clinician_seed` | `-cs` | Clinician generation seed |\n", + "| `single_person_seed` | `-ps` | Seed used to reproduce a particular person |\n", + "| `population` | `-p` | Requested population size |\n", + "| `reference_date` | `-r` | Reference date in `YYYYMMDD` form |\n", + "| `end_date` | `-e` | Simulation end date in `YYYYMMDD` form |\n", + "| `gender` | `-g` | Restrict generation to `M` or `F` |\n", + "| `age_range` | `-a` | Restrict age using `min-max` |\n", + "| `overflow_population` | `-o` | Permit extra generated people to satisfy filters |\n", + "| `local_config_path` | `-c` | Additional `.properties` configuration file |\n", + "| `local_modules_dir` | `-d` | Directory containing custom Synthea modules |\n", + "| `initial_population_snapshot_path` | `-i` | Load a previously saved population snapshot |\n", + "| `updated_population_snapshot_path` | `-u` | Write the population after an update run |\n", + "| `update_time_period` | `-t` | Number of days advanced during a snapshot update |\n", + "| `fixed_record_path` | `-f` | Fixed-demographics input used to generate specified people |\n", + "| `keep_matching_patients_path` | `-k` | Module used to retain only matching patients |\n", + "| `state`, `city` | trailing positional arguments | Geographic generation location |\n", + "| `synthea_config` | `--property=value` overrides | Arbitrary supported `synthea.properties` values |\n", + "| `overwrite` | wrapper-managed | Rerun Synthea even if output for these settings exists |\n", + "\n", + "Constructor arguments are all wrapper-managed setup:\n", + "\n", + "| Constructor argument | Meaning |\n", + "|---|---|\n", + "| `output_dir` | Parent of the fingerprinted generation directories |\n", + "| `java_path` | Explicit Java executable, otherwise discovered |\n", + "| `jar_path` | Explicit Synthea JAR, otherwise the pinned release is used |\n", + "| `auto_download` | Allow downloading the pinned JAR when absent |\n", + "| `timeout` | Subprocess timeout in seconds for each `generate()` call |" + ] + }, + { + "cell_type": "markdown", + "id": "8ed849e4", + "metadata": {}, + "source": [ + "## 5. Load generated CSV through PyHealth\n", + "\n", + "`SyntheaCSVDataset` only reads files: it takes the CSV directory returned by `generate()` plus an optional table selection. Omitting `tables` uses all supported defaults. `dataset_name`, `config_path`, and normal `BaseDataset` keyword arguments such as `cache_dir` and `dev` can also be supplied." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "f06ebd72", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:28:29.285321Z", + "iopub.status.busy": "2026-10-08T18:28:29.285209Z", + "iopub.status.idle": "2026-10-08T18:28:31.211950Z", + "shell.execute_reply": "2026-10-08T18:28:31.211384Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initializing synthea_csv_demo dataset from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv (dev mode: False)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using provided cache_dir: /home/soham/PyHealth/examples/.artifacts/synthea_csv/cache/fa318dd5-8d48-5265-84fa-1d581ce4cd9a\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: patients from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/patients.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: encounters from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/encounters.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: conditions from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/conditions.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: observations from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/observations.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "No cached event dataframe found. Creating: /home/soham/PyHealth/examples/.artifacts/synthea_csv/cache/fa318dd5-8d48-5265-84fa-1d581ce4cd9a/global_event_df.parquet\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: patients from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/patients.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: encounters from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/encounters.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: conditions from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/conditions.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: observations from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/observations.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Caching event dataframe to /home/soham/PyHealth/examples/.artifacts/synthea_csv/cache/fa318dd5-8d48-5265-84fa-1d581ce4cd9a/global_event_df.parquet...\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2026-10-08 18:28:31,163 - distributed.core - ERROR - Exception while handling op terminate\n", + "Traceback (most recent call last):\n", + " File \"/home/soham/PyHealth/.venv/lib/python3.13/site-packages/distributed/core.py\", line 834, in _handle_comm\n", + " result = await result\n", + " ^^^^^^^^^^^^\n", + " File \"/home/soham/PyHealth/.venv/lib/python3.13/site-packages/distributed/scheduler.py\", line 4367, in close\n", + " self.stop_services()\n", + " ~~~~~~~~~~~~~~~~~~^^\n", + " File \"/home/soham/PyHealth/.venv/lib/python3.13/site-packages/distributed/node.py\", line 79, in stop_services\n", + " application.stop()\n", + " ~~~~~~~~~~~~~~~~^^\n", + " File \"/home/soham/PyHealth/.venv/lib/python3.13/site-packages/bokeh/server/tornado.py\", line 761, in stop\n", + " raise RuntimeError(\"Cannot synchronously wait on a running event loop; use 'await stop_async()'\")\n", + "RuntimeError: Cannot synchronously wait on a running event loop; use 'await stop_async()'\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dataset: synthea_csv_demo\n", + "Dev mode: False\n", + "Number of patients: 10\n", + "Number of events: 2778\n" + ] + }, + { + "data": { + "text/html": [ + "
Dask DataFrame Structure:
\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
patient_idevent_typetimestamppatients/birthdatepatients/deathdatepatients/genderpatients/racepatients/ethnicitypatients/maritalpatients/birthplacepatients/citypatients/statepatients/countypatients/zipencounters/idencounters/startencounters/stopencounters/encounterclassencounters/codeencounters/descriptionencounters/base_encounter_costencounters/total_claim_costencounters/payer_coverageencounters/reasoncodeencounters/reasondescriptionconditions/startconditions/stopconditions/encounterconditions/codeconditions/descriptionobservations/dateobservations/encounterobservations/codeobservations/descriptionobservations/valueobservations/unitsobservations/type
npartitions=4
stringobjectdatetime64[ms]stringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstring
...............................................................................................................
...............................................................................................................
...............................................................................................................
...............................................................................................................
\n", + "
Dask Name: concat, 57 expressions
" + ], + "text/plain": [ + "Dask DataFrame Structure:\n", + " patient_id event_type timestamp patients/birthdate patients/deathdate patients/gender patients/race patients/ethnicity patients/marital patients/birthplace patients/city patients/state patients/county patients/zip encounters/id encounters/start encounters/stop encounters/encounterclass encounters/code encounters/description encounters/base_encounter_cost encounters/total_claim_cost encounters/payer_coverage encounters/reasoncode encounters/reasondescription conditions/start conditions/stop conditions/encounter conditions/code conditions/description observations/date observations/encounter observations/code observations/description observations/value observations/units observations/type\n", + "npartitions=4 \n", + " string object datetime64[ms] string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string\n", + " ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...\n", + " ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...\n", + " ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...\n", + " ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...\n", + "Dask Name: concat, 57 expressions\n", + "Expr=Concat(frames=[(RenameFrame(frame=Assign(frame=Assign(frame=Assign(frame=RenameFrame(frame=Replace(frame=ReadParquetFSSpec(861428f), to_replace='', value=), columns=)))), columns={'birthdate': 'patients/birthdate', 'deathdate': 'patients/deathdate', 'gender': 'patients/gender', 'race': 'patients/race', 'ethnicity': 'patients/ethnicity', 'marital': 'patients/marital', 'birthplace': 'patients/birthplace', 'city': 'patients/city', 'state': 'patients/state', 'county': 'patients/county', 'zip': 'patients/zip'}))[['patient_id', 'event_type', 'timestamp', 'patients/birthdate', 'patients/deathdate', 'patients/gender', 'patients/race', 'patients/ethnicity', 'patients/marital', 'patients/birthplace', 'patients/city', 'patients/state', 'patients/county', 'patients/zip']], (RenameFrame(frame=Assign(frame=Assign(frame=Assign(frame=RenameFrame(frame=Replace(frame=ReadParquetFSSpec(878097d), to_replace='', value=), columns=)))), columns={'id': 'encounters/id', 'start': 'encounters/start', 'stop': 'encounters/stop', 'encounterclass': 'encounters/encounterclass', 'code': 'encounters/code', 'description': 'encounters/description', 'base_encounter_cost': 'encounters/base_encounter_cost', 'total_claim_cost': 'encounters/total_claim_cost', 'payer_coverage': 'encounters/payer_coverage', 'reasoncode': 'encounters/reasoncode', 'reasondescription': 'encounters/reasondescription'}))[['patient_id', 'event_type', 'timestamp', 'encounters/id', 'encounters/start', 'encounters/stop', 'encounters/encounterclass', 'encounters/code', 'encounters/description', 'encounters/base_encounter_cost', 'encounters/total_claim_cost', 'encounters/payer_coverage', 'encounters/reasoncode', 'encounters/reasondescription']], (RenameFrame(frame=Assign(frame=Assign(frame=Assign(frame=RenameFrame(frame=Replace(frame=ReadParquetFSSpec(3082815), to_replace='', value=), columns=)))), columns={'start': 'conditions/start', 'stop': 'conditions/stop', 'encounter': 'conditions/encounter', 'code': 'conditions/code', 'description': 'conditions/description'}))[['patient_id', 'event_type', 'timestamp', 'conditions/start', 'conditions/stop', 'conditions/encounter', 'conditions/code', 'conditions/description']], (RenameFrame(frame=Assign(frame=Assign(frame=Assign(frame=RenameFrame(frame=Replace(frame=ReadParquetFSSpec(ba3f9c7), to_replace='', value=), columns=)))), columns={'date': 'observations/date', 'encounter': 'observations/encounter', 'code': 'observations/code', 'description': 'observations/description', 'value': 'observations/value', 'units': 'observations/units', 'type': 'observations/type'}))[['patient_id', 'event_type', 'timestamp', 'observations/date', 'observations/encounter', 'observations/code', 'observations/description', 'observations/value', 'observations/units', 'observations/type']]], )" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset = SyntheaCSVDataset(\n", + " root=csv_path,\n", + " tables=[\"patients\", \"encounters\", \"conditions\", \"observations\"],\n", + " dataset_name=\"synthea_csv_demo\",\n", + " config_path=None,\n", + " cache_dir=artifact_root / \"cache\",\n", + " dev=False,\n", + ")\n", + "\n", + "events = dataset.load_data()\n", + "dataset.stats()\n", + "# events.head(5)\n", + "events" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "20d7256b", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-08T18:28:31.213377Z", + "iopub.status.busy": "2026-10-08T18:28:31.213265Z", + "iopub.status.idle": "2026-10-08T18:28:31.265529Z", + "shell.execute_reply": "2026-10-08T18:28:31.265028Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Scanning table: patients from /home/soham/PyHealth/examples/.artifacts/synthea_csv/generated/3f9629628a6636e7bcd7cdac7b8a158b56c8732ceaa87faf747775c20b85f8e4/csv/patients.csv\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 10 unique patient IDs\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Patients: 10\n", + "Selected patient: aee7bbe1-0c45-c028-1e62-1f4cdb30c273\n", + "Configured tables: ['patients', 'encounters', 'conditions', 'observations']\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "shape: (10, 37)
patient_idevent_typetimestamppatients/birthdatepatients/deathdatepatients/genderpatients/racepatients/ethnicitypatients/maritalpatients/birthplacepatients/citypatients/statepatients/countypatients/zipencounters/idencounters/startencounters/stopencounters/encounterclassencounters/codeencounters/descriptionencounters/base_encounter_costencounters/total_claim_costencounters/payer_coverageencounters/reasoncodeencounters/reasondescriptionconditions/startconditions/stopconditions/encounterconditions/codeconditions/descriptionobservations/dateobservations/encounterobservations/codeobservations/descriptionobservations/valueobservations/unitsobservations/type
strstrdatetime[ms]strstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstrstr
"aee7bbe1-0c45-c028-1e62-1f4cdb…"patients"1985-06-04 00:00:00"1985-06-04"null"F""white""hispanic""M""Gaudalajara  Jalisco  MX""Boston""Massachusetts""Suffolk County""02114"nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"conditions"1995-05-08 00:00:00nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull"1995-05-08"null"aee7bbe1-0c45-c028-4bd4-fdd4de…"40055000""Chronic sinusitis (disorder)"nullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"encounters"1995-05-08 08:15:37nullnullnullnullnullnullnullnullnullnullnull"aee7bbe1-0c45-c028-4bd4-fdd4de…"1995-05-08T08:15:37Z""1995-05-08T08:30:37Z""ambulatory""185345009""Encounter for symptom (procedu…"85.55""92.93""55.76""75498004""Acute bacterial sinusitis (dis…nullnullnullnullnullnullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"conditions"2003-07-29 00:00:00nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull"2003-07-29"null"aee7bbe1-0c45-c028-fc17-89784f…"266934004""Transport problem (finding)"nullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"conditions"2003-07-29 00:00:00nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull"2003-07-29"null"aee7bbe1-0c45-c028-fc17-89784f…"224299000""Received higher education (fin…nullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"encounters"2003-07-29 06:15:37nullnullnullnullnullnullnullnullnullnullnull"aee7bbe1-0c45-c028-fc17-89784f…"2003-07-29T06:15:37Z""2003-07-29T07:12:15Z""wellness""162673000""General examination of patient…"136.80""919.90""0.00"nullnullnullnullnullnullnullnullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"conditions"2004-08-03 00:00:00nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull"2004-08-03"null"aee7bbe1-0c45-c028-1f6f-b01430…"713458007""Lack of access to transportati…nullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"encounters"2004-08-03 06:15:37nullnullnullnullnullnullnullnullnullnullnull"aee7bbe1-0c45-c028-1f6f-b01430…"2004-08-03T06:15:37Z""2004-08-03T07:02:44Z""wellness""162673000""General examination of patient…"136.80""919.90""0.00"nullnullnullnullnullnullnullnullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"conditions"2008-07-29 00:00:00nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull"2008-07-29"null"aee7bbe1-0c45-c028-f436-cec318…"161744009""Past pregnancy history of misc…nullnullnullnullnullnullnull
"aee7bbe1-0c45-c028-1e62-1f4cdb…"encounters"2008-07-29 10:15:37nullnullnullnullnullnullnullnullnullnullnull"aee7bbe1-0c45-c028-f436-cec318…"2008-07-29T10:15:37Z""2008-07-29T10:30:37Z""ambulatory""424619006""Prenatal visit (regime/therapy…"142.58""1005.38""603.23""79586000""Tubal pregnancy (disorder)"nullnullnullnullnullnullnullnullnullnullnullnull
" + ], + "text/plain": [ + "shape: (10, 37)\n", + "┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐\n", + "│ patient_i ┆ event_typ ┆ timestamp ┆ patients/ ┆ … ┆ observati ┆ observati ┆ observati ┆ observat │\n", + "│ d ┆ e ┆ --- ┆ birthdate ┆ ┆ ons/descr ┆ ons/value ┆ ons/units ┆ ions/typ │\n", + "│ --- ┆ --- ┆ datetime[ ┆ --- ┆ ┆ iption ┆ --- ┆ --- ┆ e │\n", + "│ str ┆ str ┆ ms] ┆ str ┆ ┆ --- ┆ str ┆ str ┆ --- │\n", + "│ ┆ ┆ ┆ ┆ ┆ str ┆ ┆ ┆ str │\n", + "╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡\n", + "│ aee7bbe1- ┆ patients ┆ 1985-06-0 ┆ 1985-06-0 ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ ┆ 4 ┆ 4 ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ condition ┆ 1995-05-0 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 8 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ encounter ┆ 1995-05-0 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 8 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 08:15:37 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ condition ┆ 2003-07-2 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 9 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ condition ┆ 2003-07-2 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 9 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ encounter ┆ 2003-07-2 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 9 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 06:15:37 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ condition ┆ 2004-08-0 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 3 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ encounter ┆ 2004-08-0 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 3 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 06:15:37 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ condition ┆ 2008-07-2 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 9 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ aee7bbe1- ┆ encounter ┆ 2008-07-2 ┆ null ┆ … ┆ null ┆ null ┆ null ┆ null │\n", + "│ 0c45-c028 ┆ s ┆ 9 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ -1e62-1f4 ┆ ┆ 10:15:37 ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "│ cdb… ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ │\n", + "└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "patients_table = dataset.load_table(\"patients\")\n", + "patient_ids = dataset.unique_patient_ids\n", + "patient = dataset.get_patient(patient_ids[0])\n", + "patient_events = patient.get_events(return_df=True)\n", + "\n", + "print(\"Patients:\", len(patient_ids))\n", + "print(\"Selected patient:\", patient.patient_id)\n", + "print(\"Configured tables:\", dataset.tables)\n", + "patient_events.head(10)" + ] + }, + { + "cell_type": "markdown", + "id": "6d034a8c", + "metadata": {}, + "source": [ + "## 6. How Synthea differs from other PyHealth datasets\n", + "\n", + "The event table above has the same shape as every PyHealth dataset: one row per event with `patient_id`, `event_type` (the source table), `timestamp`, and one `/` column per attribute, null for other tables. What differs is the raw input and the codes.\n", + "\n", + "**Raw output.** Synthea wrote the 18 CSV files listed in section 3, each wide and keyed by UUIDs, including billing (`claims`, `claims_transactions`) and institution tables (`organizations`, `providers`, `payers`). `SyntheaCSVDataset` loads the patient-keyed clinical tables by default; `claims` and `claims_transactions` load only when listed in `tables`; institution tables have no patient column and are never loaded.\n", + "\n", + "**Codes.** MIMIC uses ICD-9/10 and NDC. Synthea uses:\n", + "\n", + "| Table | Code system | Example `code` |\n", + "|---|---|---|\n", + "| `conditions`, `procedures`, `encounters`, `careplans`, `devices`, `supplies` | SNOMED-CT | `714628002` (Prediabetes) |\n", + "| `medications` | RxNorm | `849574` (Naproxen sodium 220 MG Oral Tablet) |\n", + "| `observations` | LOINC | `4548-4` (Hemoglobin A1c) |\n", + "| `immunizations` | CVX | `140` (Influenza, split virus, trivalent, PF) |\n", + "\n", + "So MIMIC tasks such as `MortalityPredictionMIMIC3` and ICD-based `pyhealth.medcode` mappings do not apply; write a Synthea-specific task instead. Every code has a human-readable `description`.\n", + "\n", + "**Other differences.**\n", + "\n", + "- Each patient has a `patients` event at their birth date carrying demographics (`gender`, `race`, `deathdate`, ...).\n", + "- There is no separate visit level: clinical events carry an `encounter` UUID; group by it to rebuild visits.\n", + "- `observations/value` is a string column holding both numbers and text; `observations/type` says which.\n", + "- `conditions` timestamps are dates (midnight); most other tables have full date-times.\n", + "\n", + "On a patient, attributes are accessed without the table prefix:\n", + "\n", + "```python\n", + "for event in patient.get_events(event_type=\"conditions\"):\n", + " print(event.timestamp, event.code, event.description)\n", + "```" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.13.15)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.15" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": { + "2e81ea6f05494e0e9b24d2e79e3022d9": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "2.0.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "2.0.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "2.0.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border_bottom": null, + "border_left": null, + "border_right": null, + "border_top": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f90b185cfed84aff8660b82faf4df391": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "VBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "VBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "2.0.0", + "_view_name": "VBoxView", + "box_style": "", + "children": [], + "layout": "IPY_MODEL_2e81ea6f05494e0e9b24d2e79e3022d9", + "tabbable": null, + "tooltip": null + } + } + }, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyhealth/datasets/__init__.py b/pyhealth/datasets/__init__.py index 7acd921e6..af55a227a 100644 --- a/pyhealth/datasets/__init__.py +++ b/pyhealth/datasets/__init__.py @@ -69,6 +69,7 @@ def __init__(self, *args, **kwargs): from .sleepedf import SleepEDFDataset from .bmd_hs import BMDHSDataset from .support2 import Support2Dataset +from .synthea_csv import SyntheaCSVDataset as SyntheaCSVDataset from .tcga_prad import TCGAPRADDataset from .splitter import ( PatientSplit as PatientSplit, diff --git a/pyhealth/datasets/configs/synthea_csv.yaml b/pyhealth/datasets/configs/synthea_csv.yaml new file mode 100644 index 000000000..8703789fd --- /dev/null +++ b/pyhealth/datasets/configs/synthea_csv.yaml @@ -0,0 +1,138 @@ +# Synthea synthetic patient data, CSV export. +# +# Requires Synthea to have been run with --exporter.csv.export=true (CSV export +# is OFF by default), or one of MITRE's pre-generated CSV sample downloads. +# +# All column names here are lowercase because BaseDataset.load_table lowercases +# every header before consulting this config. Synthea ships uppercase headers. +# +# `version` is free-form and unused at runtime; it records the Synthea CSV +# schema generation this config was validated against. +version: "4.0" +tables: + patients: + file_path: "patients.csv" + patient_id: "id" + timestamp: "birthdate" + timestamp_format: "%Y-%m-%d" + attributes: ["birthdate", "deathdate", "gender", "race", "ethnicity", + "marital", "birthplace", "city", "state", "county", "zip"] + encounters: + file_path: "encounters.csv" + patient_id: "patient" + timestamp: "start" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["id", "start", "stop", "encounterclass", "code", + "description", "base_encounter_cost", "total_claim_cost", + "payer_coverage", "reasoncode", "reasondescription"] + conditions: + file_path: "conditions.csv" + patient_id: "patient" + timestamp: "start" + timestamp_format: "%Y-%m-%d" + attributes: ["start", "stop", "encounter", "code", "description"] + medications: + file_path: "medications.csv" + patient_id: "patient" + timestamp: "start" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["start", "stop", "encounter", "code", "description", + "base_cost", "dispenses", "totalcost", + "reasoncode", "reasondescription"] + observations: + file_path: "observations.csv" + patient_id: "patient" + timestamp: "date" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["date", "encounter", "code", "description", "value", + "units", "type"] + procedures: + # `stop` and `system` are omitted on purpose: both are absent from older + # exports (e.g. the apr2020 sample), and a missing attribute is a KeyError. + # `start` is synthesized from `date` by preprocess_procedures when needed. + file_path: "procedures.csv" + patient_id: "patient" + timestamp: "start" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["encounter", "code", "description", + "base_cost", "reasoncode", "reasondescription"] + immunizations: + # Synthea's CSV data dictionary calls this column `cost`; the real files + # emit `base_cost`. Trust the files. + file_path: "immunizations.csv" + patient_id: "patient" + timestamp: "date" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["date", "encounter", "code", "description", "base_cost"] + careplans: + file_path: "careplans.csv" + patient_id: "patient" + timestamp: "start" + timestamp_format: "%Y-%m-%d" + attributes: ["id", "start", "stop", "encounter", "code", "description", + "reasoncode", "reasondescription"] + allergies: + file_path: "allergies.csv" + patient_id: "patient" + timestamp: "start" + timestamp_format: "%Y-%m-%d" + attributes: ["start", "stop", "encounter", "code", "system", + "description", "type", "category", "reaction1", + "description1", "severity1", "reaction2", "description2", + "severity2"] + devices: + file_path: "devices.csv" + patient_id: "patient" + timestamp: "start" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["start", "stop", "encounter", "code", "description", "udi"] + imaging_studies: + file_path: "imaging_studies.csv" + patient_id: "patient" + timestamp: "date" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["id", "date", "encounter", "series_uid", "bodysite_code", + "bodysite_description", "modality_code", + "modality_description", "instance_uid", "sop_code", + "sop_description", "procedure_code"] + supplies: + file_path: "supplies.csv" + patient_id: "patient" + timestamp: "date" + timestamp_format: "%Y-%m-%d" + attributes: ["date", "encounter", "code", "description", "quantity"] + payer_transitions: + file_path: "payer_transitions.csv" + patient_id: "patient" + timestamp: "start_date" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["memberid", "start_date", "end_date", "payer", + "secondary_payer", "plan_ownership", "owner_name"] + claims: + file_path: "claims.csv" + patient_id: "patientid" + timestamp: "servicedate" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["id", "providerid", "primarypatientinsuranceid", + "secondarypatientinsuranceid", "departmentid", + "patientdepartmentid", "diagnosis1", "diagnosis2", + "diagnosis3", "diagnosis4", "diagnosis5", "diagnosis6", + "diagnosis7", "diagnosis8", "referringproviderid", + "appointmentid", "currentillnessdate", "servicedate", + "supervisingproviderid", "status1", "status2", "statusp", + "outstanding1", "outstanding2", "outstandingp", + "lastbilleddate1", "lastbilleddate2", "lastbilleddatep", + "healthcareclaimtypeid1", "healthcareclaimtypeid2"] + claims_transactions: + file_path: "claims_transactions.csv" + patient_id: "patientid" + timestamp: "fromdate" + timestamp_format: "%Y-%m-%dT%H:%M:%SZ" + attributes: ["id", "claimid", "chargeid", "type", "amount", "method", + "fromdate", "todate", "placeofservice", "procedurecode", + "modifier1", "modifier2", "diagnosisref1", "diagnosisref2", + "diagnosisref3", "diagnosisref4", "units", "departmentid", + "notes", "unitamount", "transferoutid", "transfertype", + "payments", "adjustments", "transfers", "outstanding", + "appointmentid", "linenote", "patientinsuranceid", + "feescheduleid", "providerid", "supervisingproviderid"] diff --git a/pyhealth/datasets/synthea_csv.py b/pyhealth/datasets/synthea_csv.py new file mode 100644 index 000000000..cf90fba9f --- /dev/null +++ b/pyhealth/datasets/synthea_csv.py @@ -0,0 +1,117 @@ +"""Synthea CSV output exposed through the standard PyHealth dataset API.""" + +from pathlib import Path + +import narwhals as nw + +from .base_dataset import BaseDataset + +DEFAULT_TABLES = [ + "patients", + "encounters", + "conditions", + "medications", + "observations", + "procedures", + "immunizations", + "careplans", + "allergies", + "devices", + "imaging_studies", + "supplies", + "payer_transitions", +] + + +class SyntheaCSVDataset(BaseDataset): + """Loads Synthea CSV files through the PyHealth dataset API. + + The dataset only reads files; it does not run Synthea. Produce the CSV + directory with :class:`~pyhealth.models.Synthea` first, or point ``root`` + at any existing Synthea CSV export. + + Each row becomes a standard PyHealth event (``patient_id``, + ``event_type``, ``timestamp`` plus the table's attributes), but Synthea's + codes are SNOMED-CT, RxNorm, LOINC, and CVX rather than ICD and NDC, so + MIMIC tasks and ICD code mappings do not apply directly. + + Examples: + >>> from pyhealth.datasets import SyntheaCSVDataset + >>> from pyhealth.models import Synthea + >>> csv_dir = Synthea("./synthea-output").generate(population=10, seed=42) + >>> dataset = SyntheaCSVDataset(csv_dir, tables=["conditions"]) + >>> patient = dataset.get_patient(dataset.unique_patient_ids[0]) + >>> event = patient.get_events(event_type="conditions")[0] + >>> event.code, event.description # SNOMED-CT code and its text + """ + + def __init__( + self, + root: str | Path, + tables: list[str] | None = None, + dataset_name: str | None = None, + config_path: str | None = None, + **kwargs, + ) -> None: + """Initializes a Synthea CSV dataset. + + Args: + root (str or Path): Directory containing the Synthea CSV files. + tables (list[str], optional): CSV tables to load. The supported + defaults are used when omitted or empty. + dataset_name (str, optional): Dataset name used by PyHealth. + config_path (str, optional): Dataset schema configuration. The + bundled Synthea CSV schema is used when omitted. + **kwargs: Additional arguments passed to :class:`BaseDataset`. + """ + self._explicit_tables = bool(tables) + selected = list(dict.fromkeys(DEFAULT_TABLES if not tables else tables)) + if config_path is None: + config_path = str(Path(__file__).parent / "configs" / "synthea_csv.yaml") + super().__init__( + root=str(root), + tables=selected, + dataset_name=dataset_name or "synthea", + config_path=config_path, + **kwargs, + ) + + def load_data(self): + """Loads the selected tables, skipping default tables not emitted. + + Synthea omits CSV files for record types with no rows. A missing + default table is skipped; a missing table requested explicitly is + treated as an error. + + Returns: + dd.DataFrame: Concatenated lazy Dask DataFrame for the selected + tables. + + Raises: + RuntimeError: If an explicitly selected table is missing. + """ + root = Path(self.root) + missing = [ + table for table in self.tables if not (root / f"{table}.csv").is_file() + ] + if missing and self._explicit_tables: + raise RuntimeError(f"Synthea CSV tables not found: {', '.join(missing)}") + if missing: + self.tables = [table for table in self.tables if table not in missing] + return super().load_data() + + def preprocess_procedures(self, frame: nw.LazyFrame) -> nw.LazyFrame: + """Normalizes legacy Synthea procedure timestamps. + + Older exports use ``date`` where the current schema uses ``start``. + Existing ``start`` columns are preserved. + + Args: + frame (nw.LazyFrame): Procedure table before schema normalization. + + Returns: + nw.LazyFrame: Procedure table containing a ``start`` column. + """ + if "start" not in frame.columns: + frame = frame.with_columns(nw.col("date").alias("start")) + return frame diff --git a/pyhealth/models/__init__.py b/pyhealth/models/__init__.py index 6015d8e5a..ddb74249f 100644 --- a/pyhealth/models/__init__.py +++ b/pyhealth/models/__init__.py @@ -54,4 +54,5 @@ from .generators.gpt2 import GPT2 from .generators.promptehr import PromptEHR from .generators.medgan import MedGAN +from .generators.synthea import Synthea as Synthea from .generators.corgan import CorGAN \ No newline at end of file diff --git a/pyhealth/models/generators/__init__.py b/pyhealth/models/generators/__init__.py index a65bbd975..f3e6a215a 100644 --- a/pyhealth/models/generators/__init__.py +++ b/pyhealth/models/generators/__init__.py @@ -3,5 +3,6 @@ from .promptehr import PromptEHR from .medgan import MedGAN from .corgan import CorGAN +from .synthea import Synthea -__all__ = ["HALO", "GPT2", "PromptEHR", "MedGAN", "CorGAN"] +__all__ = ["GPT2", "HALO", "CorGAN", "MedGAN", "PromptEHR", "Synthea"] diff --git a/pyhealth/models/generators/synthea.py b/pyhealth/models/generators/synthea.py new file mode 100644 index 000000000..2509918e2 --- /dev/null +++ b/pyhealth/models/generators/synthea.py @@ -0,0 +1,784 @@ +"""Generate Synthea populations as CSV files.""" + +from __future__ import annotations + +import hashlib +import json +import logging +import os +import re +import secrets +import shutil +import subprocess +import urllib.request +import zipfile +from collections.abc import Mapping +from dataclasses import asdict, dataclass, field +from fnmatch import fnmatchcase +from pathlib import Path + +import platformdirs + +from ..base_model import BaseModel + +logger = logging.getLogger(__name__) + + +@dataclass(frozen=True) +class _SyntheaRelease: + """Pinned Synthea release and the exporter keys this wrapper manages. + + Bumping Synthea means updating ``version``, ``url``, and ``sha256`` + together, then re-checking the exporter keys against the new release's + ``synthea.properties``. + + Attributes: + version (str): Synthea release tag. + url (str): Download URL of the release's all-in-one JAR. + sha256 (str): Expected SHA-256 digest of the JAR. + base_directory_key (str): Property that sets the output root. + csv_export_key (str): Property that enables CSV export. + unsupported_export_flags (tuple[str, ...]): Exporter switches forced + off so that only CSV output is produced. + min_java_version (int): Oldest Java major version the JAR runs on. + """ + + version: str = "v4.0.0" + url: str = ( + "https://github.com/synthetichealth/synthea/releases/download/" + "v4.0.0/synthea-with-dependencies.jar" + ) + sha256: str = "ed43c20ad40ba5c3bc724503a5af032715fe3c491620b766148e7c2361e6ecc1" + base_directory_key: str = "exporter.baseDirectory" + csv_export_key: str = "exporter.csv.export" + unsupported_export_flags: tuple[str, ...] = ( + "exporter.bfd.export", + "exporter.ccda.export", + "exporter.cdw.export", + "exporter.clinical_note.export", + "exporter.cpcds.export", + "exporter.fhir.export", + "exporter.fhir_dstu2.export", + "exporter.fhir_stu3.export", + "exporter.json.export", + "exporter.symptoms.csv.export", + "exporter.symptoms.text.export", + "exporter.text.export", + ) + min_java_version: int = 17 + + def __post_init__(self) -> None: + """Rejects a malformed pinned digest. + + Raises: + ValueError: If ``sha256`` is not 64 lowercase hex characters. + """ + if not re.fullmatch(r"[0-9a-f]{64}", self.sha256): + raise ValueError(f"invalid Synthea SHA-256: {self.sha256!r}") + + +_RELEASE = _SyntheaRelease() + +_JAVA_VERSION = re.compile(r'version "(\d+)(?:\.(\d+))?') +_PROPERTY_KEY = re.compile(r"^[A-Za-z0-9_.-]+$") +_MANAGED_CONFIG_KEYS = frozenset( + { + _RELEASE.base_directory_key, + _RELEASE.csv_export_key, + *_RELEASE.unsupported_export_flags, + } +) + + +def _parse_properties(text: str) -> dict[str, str | None]: + """Parses Java properties text into a Python mapping. + + Commented properties are retained with a value of ``None`` so callers can + discover properties that Synthea supports but leaves unset. + + Args: + text (str): Contents of a Synthea properties file. + + Returns: + dict[str, str | None]: Parsed property names and values. + """ + config = {} + for raw_line in text.splitlines(): + line = raw_line.strip() + if not line: + continue + disabled = line.startswith(("#", "!")) + if disabled: + line = line[1:].strip() + match = re.match(r"([^=:\s]+)\s*(?:=|:)\s*(.*)", line) + if not match: + continue + key, value = match.groups() + if _PROPERTY_KEY.fullmatch(key): + config[key] = None if disabled else value.strip() + return config + + +def _optional_path(value: str | Path | None) -> Path | None: + """Converts an optional path-like value to an expanded path. + + Args: + value (str or Path, optional): Path-like value to convert. + + Returns: + Path | None: The expanded path, or ``None`` when omitted. + """ + return Path(value).expanduser() if value is not None else None + + +@dataclass(frozen=True) +class _GenerationSettings: + """Validated settings describing one Synthea population. + + One instance is built per :meth:`Synthea.generate` call. Every field + changes which patients Synthea produces, so all of them are part of the + output fingerprint. Fields are documented on :meth:`Synthea.generate`. + """ + + population: int | None = None + seed: int | None = None + clinician_seed: int | None = None + single_person_seed: int | None = None + reference_date: str | None = None + end_date: str | None = None + gender: str | None = None + age_range: str | None = None + overflow_population: bool | None = None + state: str | None = None + city: str | None = None + local_config_path: Path | None = None + local_modules_dir: Path | None = None + initial_population_snapshot_path: Path | None = None + updated_population_snapshot_path: Path | None = None + update_time_period: int | None = None + fixed_record_path: Path | None = None + keep_matching_patients_path: Path | None = None + synthea_config: Mapping[str, str | int | float | bool] = field(default_factory=dict) + local_config: dict[str, str | None] = field(init=False, default_factory=dict) + + def __post_init__(self) -> None: + """Validates the settings and normalizes paths and properties. + + Raises: + TypeError: If a value or configuration property has an invalid + type. + ValueError: If a value is outside its accepted range, ``city`` is + provided without ``state``, or configuration attempts to set + the output directory or select an exporter. + FileNotFoundError: If ``local_config_path`` cannot be read. + """ + for name in ("population", "seed", "clinician_seed", "single_person_seed"): + value = getattr(self, name) + if value is not None and ( + not isinstance(value, int) or isinstance(value, bool) + ): + raise TypeError(f"{name} must be an int or None") + if self.population is not None and self.population < 1: + raise ValueError("population must be at least 1") + for name in ("reference_date", "end_date", "age_range"): + value = getattr(self, name) + if value is not None and not isinstance(value, str): + raise TypeError(f"{name} must be a str or None") + if self.city and not self.state: + raise ValueError("city requires state") + if self.gender is not None and self.gender not in {"M", "F"}: + raise ValueError("gender must be 'M', 'F', or None") + if self.overflow_population is not None and not isinstance( + self.overflow_population, bool + ): + raise TypeError("overflow_population must be a bool or None") + if self.update_time_period is not None and ( + not isinstance(self.update_time_period, int) + or isinstance(self.update_time_period, bool) + ): + raise TypeError("update_time_period must be an int or None") + if self.update_time_period is not None and self.update_time_period < 1: + raise ValueError("update_time_period must be at least 1") + + for name in ( + "local_config_path", + "local_modules_dir", + "initial_population_snapshot_path", + "updated_population_snapshot_path", + "fixed_record_path", + "keep_matching_patients_path", + ): + object.__setattr__(self, name, _optional_path(getattr(self, name))) + + if not isinstance(self.synthea_config, Mapping): + raise TypeError("synthea_config must be a mapping") + config = {} + for key, value in self.synthea_config.items(): + if not isinstance(key, str) or not _PROPERTY_KEY.fullmatch(key): + raise TypeError(f"invalid Synthea property name: {key!r}") + if isinstance(value, bool): + config[key] = "true" if value else "false" + elif isinstance(value, (str, int, float)): + config[key] = str(value) + else: + raise TypeError(f"Synthea property {key!r} must have a scalar value") + managed = config.keys() & _MANAGED_CONFIG_KEYS + if managed: + raise ValueError( + "Synthea manages the output directory and exporter selection; " + "remove: " + ", ".join(sorted(managed)) + ) + object.__setattr__(self, "synthea_config", config) + + if self.local_config_path is not None: + try: + text = self.local_config_path.read_text(encoding="utf-8") + except OSError as error: + raise FileNotFoundError( + f"Synthea config file not found: {self.local_config_path}" + ) from error + object.__setattr__(self, "local_config", _parse_properties(text)) + + def fingerprint(self) -> str: + """Hashes the settings into a stable output directory name. + + Returns: + str: SHA-256 hex digest of the release version and all settings. + """ + payload = json.dumps( + {"version": _RELEASE.version, **asdict(self)}, + sort_keys=True, + separators=(",", ":"), + default=str, + ) + return hashlib.sha256(payload.encode()).hexdigest() + + +class Synthea(BaseModel): + """Generates Synthea populations in CSV format. + + The constructor only configures the generator: where output goes and how + to find Java and the Synthea JAR. Nothing runs until :meth:`generate`, + which takes the population settings, so one instance can produce many + populations. Each call returns a directory of CSV files for + :class:`~pyhealth.datasets.SyntheaCSVDataset`. + + Synthea is a rule-based simulator run as a Java subprocess, not a trained + network. It subclasses :class:`~pyhealth.models.BaseModel` for API + consistency but has no trainable parameters and no forward pass. Unlike the + other generators, :meth:`generate` writes CSV files to disk and returns + their directory rather than records. + + Note: + Java 17 or newer must be installed; PyHealth does not install it. + The executable is taken from ``java_path``, then ``JAVA_HOME``, then + ``java`` on ``PATH``, and its version is checked before running. + Only :meth:`generate` needs Java; construction and :meth:`build_argv` + do not. The Synthea JAR itself is downloaded and cached on first run. + See the Setup section of the API docs. + + Examples: + >>> from pyhealth.datasets import SyntheaCSVDataset + >>> from pyhealth.models import Synthea + >>> synthea = Synthea("./synthea-output") # nothing is generated yet + >>> small = synthea.generate(population=10, seed=42) + >>> large = synthea.generate(population=100, seed=7, state="Ohio") + >>> dataset = SyntheaCSVDataset(small, tables=["patients"]) + """ + + def __init__( + self, + output_dir: str | Path, + java_path: str | Path | None = None, + jar_path: str | Path | None = None, + auto_download: bool = True, + timeout: float | None = None, + ) -> None: + """Initializes a Synthea generator. + + Args: + output_dir (str or Path): Parent directory for generated + populations. Each population is written to a subdirectory + named by a hash of its settings. + java_path (str or Path, optional): Java executable override. + jar_path (str or Path, optional): Synthea JAR override. + auto_download (bool): Whether to download the pinned JAR when absent. + timeout (float, optional): Subprocess timeout in seconds for each + :meth:`generate` call. + """ + super().__init__(dataset=None) + self.output_dir = Path(output_dir).expanduser().resolve() + self.java_path = _optional_path(java_path) + self.jar_path = _optional_path(jar_path) + self.auto_download = auto_download + self.timeout = timeout + + def forward(self, **kwargs) -> dict: + """Rejects forward calls; Synthea has no forward pass. + + Args: + **kwargs: Ignored. + + Raises: + NotImplementedError: Always. Use :meth:`generate` to produce data. + """ + raise NotImplementedError( + "Synthea is a simulator with no forward pass; call generate() instead." + ) + + def extra_repr(self) -> str: + """Summarizes the generator configuration shown by ``repr``. + + Returns: + str: The output directory. + """ + return f"output_dir={str(self.output_dir)!r}" + + def _resolve_java(self) -> Path: + """Finds the Java executable used to run Synthea. + + The first executable found among ``java_path``, ``JAVA_HOME``, and + ``PATH`` is used, and must be at least the pinned release's minimum + Java version. An older Java is reported rather than skipped, so a stale + ``JAVA_HOME`` is not silently bypassed. + + Returns: + Path: The resolved Java executable. + + Raises: + RuntimeError: If no Java executable can be found, it cannot be run, + or its version is too old. + """ + candidates = [] + if self.java_path: + candidates.append(self.java_path) + if java_home := os.environ.get("JAVA_HOME"): + candidates.append(Path(java_home) / "bin" / "java") + if java := shutil.which("java"): + candidates.append(Path(java)) + minimum = _RELEASE.min_java_version + for candidate in candidates: + if candidate.is_file(): + java = candidate.resolve() + version = self._java_major_version(java) + if version is not None and version < minimum: + raise RuntimeError( + f"Synthea requires Java {minimum}+, but {java} is Java " + f"{version}. Install a JDK {minimum}+ (for example from " + "https://adoptium.net) or pass java_path=." + ) + return java + raise RuntimeError( + f"Synthea requires Java {minimum}+, but none was found via " + "java_path, JAVA_HOME, or PATH. Install a JDK " + f"{minimum}+ (for example from https://adoptium.net) or pass " + "java_path=." + ) + + @staticmethod + def _java_major_version(java: Path) -> int | None: + """Reads the major version reported by ``java -version``. + + Handles both the modern scheme (``"17.0.2"`` -> 17) and the legacy one + (``"1.8.0_392"`` -> 8). + + Args: + java (Path): Java executable to query. + + Returns: + int | None: The major version, or ``None`` if the output could not + be parsed. Unparseable output is logged and tolerated rather than + treated as a failure. + + Raises: + RuntimeError: If the executable cannot be run. + """ + try: + result = subprocess.run( + [str(java), "-version"], + capture_output=True, + text=True, + timeout=60, + check=False, + ) + except (OSError, subprocess.TimeoutExpired) as error: + raise RuntimeError(f"cannot run Java at {java}: {error}") from error + match = _JAVA_VERSION.search(result.stderr + result.stdout) + if not match: + logger.warning("Could not determine the version of Java at %s", java) + return None + major, minor = match.groups() + return int(minor) if major == "1" and minor else int(major) + + @classmethod + def _resolve_jar_path( + cls, jar_path: str | Path | None, auto_download: bool + ) -> Path: + """Resolves or downloads the pinned Synthea JAR. + + Args: + jar_path (str or Path, optional): Explicit Synthea JAR path. + auto_download (bool): Whether to download the pinned JAR when it is + absent from the PyHealth cache. + + Returns: + Path: The resolved Synthea JAR. + + Raises: + FileNotFoundError: If an explicit JAR is missing or downloading is + disabled and no cached JAR exists. + RuntimeError: If a downloaded JAR fails checksum verification. + """ + if jar_path: + jar_path = Path(jar_path).expanduser() + if not jar_path.is_file(): + raise FileNotFoundError(f"Synthea jar not found: {jar_path}") + return jar_path.resolve() + + cache = Path(platformdirs.user_cache_dir("pyhealth")) / "synthea" + jar = cache / f"synthea-with-dependencies-{_RELEASE.version}.jar" + if jar.is_file(): + return jar + if not auto_download: + raise FileNotFoundError( + f"Synthea jar not found at {jar}; pass jar_path= or enable download" + ) + + logger.warning("Downloading Synthea %s to %s", _RELEASE.version, jar) + cache.mkdir(parents=True, exist_ok=True) + partial = jar.with_suffix(".jar.part") + try: + urllib.request.urlretrieve(_RELEASE.url, partial) + if cls._sha256(partial) != _RELEASE.sha256: + raise RuntimeError("downloaded Synthea jar failed SHA256 verification") + partial.replace(jar) + finally: + partial.unlink(missing_ok=True) + return jar + + def _resolve_jar(self) -> Path: + """Resolves the JAR using this instance's configured options. + + Returns: + Path: The resolved Synthea JAR. + + Raises: + FileNotFoundError: If the JAR is unavailable and cannot be downloaded. + RuntimeError: If a downloaded JAR fails checksum verification. + """ + return self._resolve_jar_path(self.jar_path, self.auto_download) + + @staticmethod + def _sha256(path: Path) -> str: + """Computes the SHA-256 digest of a file. + + Args: + path (Path): File to hash. + + Returns: + str: Lowercase hexadecimal SHA-256 digest. + """ + digest = hashlib.sha256() + with path.open("rb") as file: + for chunk in iter(lambda: file.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + @staticmethod + def _read_jar_config(jar: Path) -> dict[str, str | None]: + """Reads ``synthea.properties`` from a Synthea JAR. + + Args: + jar (Path): Synthea JAR to inspect. + + Returns: + dict[str, str | None]: Properties supported by the JAR. + + Raises: + RuntimeError: If the JAR or its properties resource cannot be read. + """ + try: + with zipfile.ZipFile(jar) as archive: + text = archive.read("synthea.properties").decode("utf-8") + except (KeyError, OSError, zipfile.BadZipFile) as error: + raise RuntimeError(f"cannot read synthea.properties from {jar}") from error + return _parse_properties(text) + + @classmethod + def get_available_config( + cls, + jar_path: str | Path | None = None, + auto_download: bool = True, + pattern: str = "*", + ) -> dict[str, str | None]: + """Returns properties supported by a Synthea JAR. + + Args: + jar_path (str or Path, optional): Explicit Synthea JAR to inspect. + auto_download (bool): Whether to download the pinned JAR when absent. + pattern (str): Shell-style pattern used to filter property names. + + Returns: + dict[str, str | None]: Matching properties and their defaults. + Properties present only as comments have a value of ``None``. + + Raises: + FileNotFoundError: If the JAR is unavailable and cannot be downloaded. + RuntimeError: If the JAR or its properties resource cannot be read. + """ + config = cls._read_jar_config(cls._resolve_jar_path(jar_path, auto_download)) + return { + key: value for key, value in config.items() if fnmatchcase(key, pattern) + } + + @classmethod + def _validate_config_keys(cls, jar: Path, settings: _GenerationSettings) -> None: + """Checks configured property names against the active JAR. + + Args: + jar (Path): Synthea JAR whose properties define the accepted keys. + settings (_GenerationSettings): Settings whose properties to check. + + Raises: + ValueError: If a configured property is not supported by the JAR. + RuntimeError: If the JAR properties cannot be read. + """ + supported = cls._read_jar_config(jar) + supplied = settings.synthea_config.keys() | settings.local_config.keys() + unknown = supplied - supported.keys() + if unknown: + names = ", ".join(sorted(unknown)) + raise ValueError(f"properties not supported by this Synthea jar: {names}") + + def _generation_dir(self, settings: _GenerationSettings) -> Path: + """Returns the directory Synthea writes a population to. + + Args: + settings (_GenerationSettings): Settings of the population. + + Returns: + Path: ``output_dir`` joined with the settings fingerprint. + """ + return self.output_dir / settings.fingerprint() + + @staticmethod + def _find_csv_dir(generation_dir: Path) -> Path | None: + """Finds the directory holding a population's CSV files. + + With Synthea's folder-per-run option enabled, the most recently + modified directory containing ``patients.csv`` is selected. + + Args: + generation_dir (Path): Directory Synthea wrote the population to. + + Returns: + Path | None: The direct or nested CSV directory, or ``None`` if no + ``patients.csv`` exists yet. + """ + root = generation_dir / "csv" + if (root / "patients.csv").is_file(): + return root + candidates = list(root.rglob("patients.csv")) if root.is_dir() else [] + if not candidates: + return None + return max(candidates, key=lambda path: path.stat().st_mtime_ns).parent + + def _build_argv( + self, java: Path, jar: Path, settings: _GenerationSettings + ) -> list[str]: + """Builds the Synthea subprocess argument vector for given settings. + + Args: + java (Path): Java executable to invoke. + jar (Path): Synthea JAR to execute. + settings (_GenerationSettings): Settings of the population. + + Returns: + list[str]: Complete subprocess argument vector. + """ + config = dict(settings.synthea_config) + config[_RELEASE.base_directory_key] = str(self._generation_dir(settings)) + config[_RELEASE.csv_export_key] = "true" + for key in _RELEASE.unsupported_export_flags: + config[key] = "false" + + argv = [str(java), "-jar", str(jar)] + if settings.local_config_path is not None: + argv += ["-c", str(settings.local_config_path)] + argv += [f"--{key}={value}" for key, value in sorted(config.items())] + options = ( + ("-s", settings.seed), + ("-cs", settings.clinician_seed), + ("-ps", settings.single_person_seed), + ("-p", settings.population), + ("-r", settings.reference_date), + ("-e", settings.end_date), + ("-g", settings.gender), + ("-a", settings.age_range), + ("-o", settings.overflow_population), + ("-d", settings.local_modules_dir), + ("-i", settings.initial_population_snapshot_path), + ("-u", settings.updated_population_snapshot_path), + ("-t", settings.update_time_period), + ("-f", settings.fixed_record_path), + ("-k", settings.keep_matching_patients_path), + ) + for flag, value in options: + if isinstance(value, bool): + argv += [flag, "true" if value else "false"] + elif value is not None: + argv += [flag, str(value)] + if settings.state: + argv.append(settings.state) + if settings.city: + argv.append(settings.city) + return argv + + def build_argv(self, java: Path, jar: Path, **settings) -> list[str]: + """Builds the Synthea command line without running it. + + Useful for checking what :meth:`generate` would execute. Unlike + :meth:`generate`, an omitted ``seed`` is left out of the command + rather than chosen at random. + + Args: + java (Path): Java executable to invoke. + jar (Path): Synthea JAR to execute. + **settings: Population settings, accepting the same keyword + arguments as :meth:`generate` except ``overwrite``. + + Returns: + list[str]: Complete subprocess argument vector. + + Raises: + TypeError: If a setting is unknown or has an invalid type. + ValueError: If a setting is outside its accepted range. + """ + return self._build_argv(java, jar, _GenerationSettings(**settings)) + + def generate( + self, + population: int | None = None, + seed: int | None = None, + state: str | None = None, + city: str | None = None, + clinician_seed: int | None = None, + single_person_seed: int | None = None, + reference_date: str | None = None, + end_date: str | None = None, + gender: str | None = None, + age_range: str | None = None, + overflow_population: bool | None = None, + local_config_path: str | Path | None = None, + local_modules_dir: str | Path | None = None, + initial_population_snapshot_path: str | Path | None = None, + updated_population_snapshot_path: str | Path | None = None, + update_time_period: int | None = None, + fixed_record_path: str | Path | None = None, + keep_matching_patients_path: str | Path | None = None, + synthea_config: Mapping[str, str | int | float | bool] | None = None, + overwrite: bool = False, + ) -> Path: + """Generates a population and returns the directory of its CSV files. + + Each distinct combination of settings is written to its own + subdirectory of ``output_dir``. If that subdirectory already holds + output, it is returned without running Synthea again, unless + ``overwrite`` is set. An omitted command-line option is not passed + to Synthea, so Synthea's own default applies. + + Args: + population (int, optional): ``-p`` population size. + seed (int, optional): ``-s`` random seed. When omitted, a random + seed is chosen and logged, so each call produces a new + population. Pass a seed for reproducible output. + state (str, optional): State positional argument. + city (str, optional): City positional argument; requires ``state``. + clinician_seed (int, optional): ``-cs`` clinician random seed. + single_person_seed (int, optional): ``-ps`` single-person seed. + reference_date (str, optional): ``-r`` date in YYYYMMDD form. + end_date (str, optional): ``-e`` date in YYYYMMDD form. + gender (str, optional): ``-g`` gender, either ``M`` or ``F``. + age_range (str, optional): ``-a`` range in ``min-max`` form. + overflow_population (bool, optional): ``-o`` population overflow + switch. + local_config_path (str or Path, optional): ``-c`` properties file. + local_modules_dir (str or Path, optional): ``-d`` local module + directory. + initial_population_snapshot_path (str or Path, optional): ``-i`` + snapshot to load. + updated_population_snapshot_path (str or Path, optional): ``-u`` + destination for the updated snapshot. + update_time_period (int, optional): ``-t`` update period in days. + fixed_record_path (str or Path, optional): ``-f`` fixed-demographics + file. + keep_matching_patients_path (str or Path, optional): ``-k`` keep + module. + synthea_config (Mapping, optional): ``synthea.properties`` + overrides. CSV export and the output directory are managed by + this class and cannot be set here. + overwrite (bool): Whether to run Synthea even if output for these + settings already exists. + + Returns: + Path: Directory containing the generated CSV files. + + Raises: + TypeError: If a setting or configuration property has an invalid + type. + ValueError: If a setting is outside its accepted range, ``city`` is + provided without ``state``, configuration sets the output + directory or an exporter, or a property is unsupported by the + active JAR. + FileNotFoundError: If ``local_config_path`` cannot be read or the + JAR is unavailable. + RuntimeError: If Java cannot be resolved, Synthea exits + unsuccessfully, or ``patients.csv`` is not produced. + subprocess.TimeoutExpired: If generation exceeds ``timeout``. + """ + chosen_seed = secrets.randbits(63) if seed is None else seed + settings = _GenerationSettings( + population=population, + seed=chosen_seed, + state=state, + city=city, + clinician_seed=clinician_seed, + single_person_seed=single_person_seed, + reference_date=reference_date, + end_date=end_date, + gender=gender, + age_range=age_range, + overflow_population=overflow_population, + local_config_path=local_config_path, + local_modules_dir=local_modules_dir, + initial_population_snapshot_path=initial_population_snapshot_path, + updated_population_snapshot_path=updated_population_snapshot_path, + update_time_period=update_time_period, + fixed_record_path=fixed_record_path, + keep_matching_patients_path=keep_matching_patients_path, + synthea_config=synthea_config or {}, + ) + if seed is None: + logger.info("No seed given; using seed=%d", chosen_seed) + + generation_dir = self._generation_dir(settings) + existing = self._find_csv_dir(generation_dir) + if existing is not None and not overwrite: + logger.info("Reusing existing Synthea output at %s", existing) + return existing + + java = self._resolve_java() + jar = self._resolve_jar() + if settings.synthea_config or settings.local_config_path: + self._validate_config_keys(jar, settings) + generation_dir.mkdir(parents=True, exist_ok=True) + argv = self._build_argv(java, jar, settings) + logger.info("Running Synthea: %s", " ".join(argv)) + result = subprocess.run(argv, timeout=self.timeout, check=False) + if result.returncode: + raise RuntimeError(f"Synthea exited with status {result.returncode}") + + csv_dir = self._find_csv_dir(generation_dir) + if csv_dir is None: + raise RuntimeError("Synthea did not generate CSV output") + return csv_dir diff --git a/tests/core/test_synthea.py b/tests/core/test_synthea.py new file mode 100644 index 000000000..06bf05a6d --- /dev/null +++ b/tests/core/test_synthea.py @@ -0,0 +1,577 @@ +import os +import shutil +import tempfile +import unittest +import zipfile +from contextlib import contextmanager +from pathlib import Path +from unittest import mock + +import narwhals as nw +import polars as pl + +from pyhealth.datasets import SyntheaCSVDataset +from pyhealth.datasets.base_dataset import BaseDataset +from pyhealth.datasets.synthea_csv import DEFAULT_TABLES +from pyhealth.models import BaseModel, Synthea +from pyhealth.models.generators.synthea import _GenerationSettings + + +class TestSynthea(unittest.TestCase): + def setUp(self): + self._tmp = tempfile.TemporaryDirectory(prefix="synthea_") + self.tmp = Path(self._tmp.name) + self.output = self.tmp / "output" + self.cache = self.tmp / "cache" + + def tearDown(self): + self._tmp.cleanup() + + def generator(self, **kwargs): + return Synthea( + output_dir=self.output, + auto_download=False, + **kwargs, + ) + + def argv(self, **settings): + return self.generator().build_argv(Path("java"), Path("synthea.jar"), **settings) + + @staticmethod + def base_directory(argv): + prefix = "--exporter.baseDirectory=" + return next(arg[len(prefix) :] for arg in argv if arg.startswith(prefix)) + + def properties_jar(self) -> Path: + jar = self.tmp / "synthea.jar" + with zipfile.ZipFile(jar, "w") as archive: + archive.writestr( + "synthea.properties", + """\ +generate.thread_pool_size = -1 +generate.only_alive_patients = false +exporter.years_of_history = 10 +exporter.baseDirectory = ./output +exporter.csv.export = false +exporter.csv.append_mode = false +exporter.csv.folder_per_run = false +exporter.ccda.export = false +#exporter.code_map.icd10-cm=code-map.json +""", + ) + return jar + + @contextmanager + def fake_synthea(self, generator): + """Replaces Java with a stub that writes patients.csv like Synthea.""" + + def run(argv, **kwargs): + csv = Path(self.base_directory(argv)) / "csv" + csv.mkdir(parents=True, exist_ok=True) + (csv / "patients.csv").write_text("Id\npatient-1\n") + return mock.Mock(returncode=0) + + with ( + mock.patch.object(generator, "_resolve_java", return_value=Path("java")), + mock.patch.object(generator, "_resolve_jar", return_value=Path("jar")), + mock.patch( + "pyhealth.models.generators.synthea.subprocess.run", + side_effect=run, + ) as subprocess_run, + ): + yield subprocess_run + + def test_constructor_only_configures_the_generator(self): + java = self.tmp / "java" + generator = self.generator(java_path=java, timeout=60) + + self.assertNotIsInstance(generator, BaseDataset) + self.assertEqual(generator.output_dir, self.output.resolve()) + self.assertEqual(generator.java_path, java) + self.assertEqual(generator.timeout, 60) + self.assertFalse(self.output.exists()) + with self.assertRaises(TypeError): + Synthea(self.output, population=10) + + def test_is_base_model_without_forward_pass(self): + generator = self.generator() + + self.assertIsInstance(generator, BaseModel) + self.assertEqual( + [name for name, _ in generator.named_parameters()], ["_dummy_param"] + ) + self.assertIn(f"output_dir={str(self.output.resolve())!r}", repr(generator)) + with self.assertRaisesRegex(NotImplementedError, "generate\\(\\)"): + generator() + + def test_one_instance_generates_several_populations(self): + generator = self.generator() + + with self.fake_synthea(generator) as subprocess_run: + small = generator.generate(population=10, seed=1) + large = generator.generate(population=50, seed=2) + + self.assertNotEqual(small, large) + self.assertTrue((small / "patients.csv").is_file()) + self.assertTrue((large / "patients.csv").is_file()) + self.assertEqual(subprocess_run.call_count, 2) + argvs = [call.args[0] for call in subprocess_run.call_args_list] + self.assertEqual(argvs[0][argvs[0].index("-p") + 1], "10") + self.assertEqual(argvs[1][argvs[1].index("-p") + 1], "50") + + def test_generate_reuses_output_unless_overwrite(self): + generator = self.generator() + + with self.fake_synthea(generator) as subprocess_run: + first = generator.generate(population=10, seed=1) + reused = generator.generate(population=10, seed=1) + self.assertEqual(subprocess_run.call_count, 1) + overwritten = generator.generate(population=10, seed=1, overwrite=True) + + self.assertEqual(first, reused) + self.assertEqual(first, overwritten) + self.assertEqual(subprocess_run.call_count, 2) + subprocess_run.assert_called_with(mock.ANY, timeout=None, check=False) + + def test_omitted_seed_is_random_so_each_call_is_a_new_population(self): + generator = self.generator() + + with ( + self.fake_synthea(generator) as subprocess_run, + self.assertLogs("pyhealth.models.generators.synthea", "INFO") as logs, + ): + first = generator.generate(population=10) + second = generator.generate(population=10) + + self.assertNotEqual(first, second) + self.assertEqual(subprocess_run.call_count, 2) + argvs = [call.args[0] for call in subprocess_run.call_args_list] + seeds = [argv[argv.index("-s") + 1] for argv in argvs] + self.assertNotEqual(seeds[0], seeds[1]) + self.assertIn(f"using seed={seeds[0]}", "\n".join(logs.output)) + + def test_generate_raises_when_synthea_fails_or_writes_nothing(self): + generator = self.generator() + patches = ( + mock.patch.object(generator, "_resolve_java", return_value=Path("java")), + mock.patch.object(generator, "_resolve_jar", return_value=Path("jar")), + ) + with patches[0], patches[1]: + with ( + mock.patch( + "pyhealth.models.generators.synthea.subprocess.run", + return_value=mock.Mock(returncode=1), + ), + self.assertRaisesRegex(RuntimeError, "status 1"), + ): + generator.generate(seed=1) + with ( + mock.patch( + "pyhealth.models.generators.synthea.subprocess.run", + return_value=mock.Mock(returncode=0), + ), + self.assertRaisesRegex(RuntimeError, "did not generate"), + ): + generator.generate(seed=1) + + def test_settings_partition_output(self): + first = self.base_directory(self.argv(seed=1)) + repeated = self.base_directory(self.argv(seed=1)) + second = self.base_directory(self.argv(seed=2)) + configured = self.base_directory( + self.argv(seed=1, synthea_config={"generate.thread_pool_size": 4}) + ) + + self.assertEqual(first, repeated) + self.assertNotEqual(first, second) + self.assertNotEqual(first, configured) + self.assertEqual(Path(first).parent, self.output.resolve()) + + def test_setting_validation(self): + for population in (0, -1): + with self.subTest(population=population), self.assertRaises(ValueError): + self.argv(population=population) + for population in (True, "10"): + with self.subTest(population=population), self.assertRaises(TypeError): + self.argv(population=population) + with self.assertRaises(TypeError): + self.argv(seed="42") + with self.assertRaisesRegex(ValueError, "city requires state"): + self.argv(city="Boston") + with self.assertRaises(TypeError): + self.argv(unknown_setting=1) + invalid_options = ( + ({"clinician_seed": "42"}, TypeError), + ({"single_person_seed": True}, TypeError), + ({"reference_date": 20260921}, TypeError), + ({"end_date": True}, TypeError), + ({"gender": "X"}, ValueError), + ({"age_range": (18, 65)}, TypeError), + ({"overflow_population": 1}, TypeError), + ({"update_time_period": 0}, ValueError), + ({"synthea_config": [("a", 1)]}, TypeError), + ) + for kwargs, error in invalid_options: + with self.subTest(kwargs=kwargs), self.assertRaises(error): + self.argv(**kwargs) + + def test_generate_validates_before_running(self): + generator = self.generator() + + with ( + self.fake_synthea(generator) as subprocess_run, + self.assertRaisesRegex(ValueError, "city requires state"), + ): + generator.generate(city="Boston") + subprocess_run.assert_not_called() + + def test_all_documented_synthea_cli_options_are_forwarded(self): + local_config = self.tmp / "local.properties" + local_config.write_text("generate.thread_pool_size = 2\n") + argv = self.argv( + population=25, + seed=42, + clinician_seed=43, + single_person_seed=44, + reference_date="20200102", + end_date="20251231", + gender="F", + age_range="18-65", + overflow_population=False, + local_config_path=local_config, + local_modules_dir=self.tmp / "modules", + initial_population_snapshot_path=self.tmp / "initial.snapshot", + updated_population_snapshot_path=self.tmp / "updated.snapshot", + update_time_period=30, + fixed_record_path=self.tmp / "fixed.json", + keep_matching_patients_path=self.tmp / "keep.json", + state="Massachusetts", + city="Boston", + synthea_config={"generate.only_alive_patients": True}, + ) + + expected_pairs = ( + ("-c", str(local_config)), + ("-s", "42"), + ("-cs", "43"), + ("-ps", "44"), + ("-p", "25"), + ("-r", "20200102"), + ("-e", "20251231"), + ("-g", "F"), + ("-a", "18-65"), + ("-o", "false"), + ("-d", str(self.tmp / "modules")), + ("-i", str(self.tmp / "initial.snapshot")), + ("-u", str(self.tmp / "updated.snapshot")), + ("-t", "30"), + ("-f", str(self.tmp / "fixed.json")), + ("-k", str(self.tmp / "keep.json")), + ) + for option, value in expected_pairs: + with self.subTest(option=option): + index = argv.index(option) + self.assertEqual(argv[index + 1], value) + self.assertEqual(argv[-2:], ["Massachusetts", "Boston"]) + self.assertLess( + argv.index("-c"), argv.index("--generate.only_alive_patients=true") + ) + + def test_omitted_cli_options_use_synthea_defaults(self): + argv = self.argv() + + for option in ( + "-s", + "-cs", + "-ps", + "-p", + "-r", + "-e", + "-g", + "-a", + "-o", + "-c", + "-d", + "-i", + "-u", + "-t", + "-f", + "-k", + ): + self.assertNotIn(option, argv) + + def test_csv_argv_only_sets_required_exporter_values(self): + argv = self.argv( + population=25, + seed=42, + state="Massachusetts", + city="Boston", + synthea_config={ + "generate.thread_pool_size": 4, + "exporter.csv.append_mode": True, + }, + ) + + self.assertIn("--exporter.csv.export=true", argv) + self.assertIn("--exporter.csv.append_mode=true", argv) + self.assertNotIn("--exporter.csv.folder_per_run=false", argv) + self.assertEqual(argv[argv.index("-p") + 1], "25") + self.assertEqual(argv[argv.index("-s") + 1], "42") + self.assertEqual(argv[-2:], ["Massachusetts", "Boston"]) + + def test_managed_output_settings_are_rejected(self): + configs = ( + {"exporter.csv.export": False}, + {"exporter.ccda.export": True}, + {"exporter.json.export": "true"}, + {"exporter.baseDirectory": str(self.tmp / "custom-output")}, + ) + for config in configs: + with ( + self.subTest(config=config), + self.assertRaises(ValueError), + ): + self.argv(synthea_config=config) + + def test_non_selection_exporter_options_remain_configurable(self): + argv = self.argv( + synthea_config={ + "exporter.csv.append_mode": True, + "exporter.csv.folder_per_run": True, + } + ) + + self.assertIn("--exporter.csv.append_mode=true", argv) + self.assertIn("--exporter.csv.folder_per_run=true", argv) + + def test_folder_per_run_csv_output_is_resolved(self): + generation_dir = self.output / "population" + self.assertIsNone(Synthea._find_csv_dir(generation_dir)) + + nested = generation_dir / "csv" / "2026_09_20" + nested.mkdir(parents=True) + (nested / "patients.csv").write_text("Id\npatient-1\n") + + self.assertEqual(Synthea._find_csv_dir(generation_dir), nested) + + def test_config_can_be_discovered_before_construction(self): + jar = self.properties_jar() + + config = Synthea.get_available_config( + jar_path=jar, + auto_download=False, + pattern="generate.*", + ) + csv_config = Synthea.get_available_config( + jar_path=jar, + auto_download=False, + pattern="exporter.csv.*", + ) + + self.assertEqual(config["generate.thread_pool_size"], "-1") + self.assertNotIn("exporter.csv.export", config) + self.assertEqual(csv_config["exporter.csv.export"], "false") + + all_config = Synthea.get_available_config( + jar_path=jar, + auto_download=False, + ) + self.assertIsNone(all_config["exporter.code_map.icd10-cm"]) + + def test_local_config_participates_in_fingerprint_and_precedence(self): + local_config = self.tmp / "local.properties" + local_config.write_text("generate.only_alive_patients = true\n") + argv = self.argv( + local_config_path=local_config, + synthea_config={"generate.only_alive_patients": False}, + ) + + self.assertNotEqual(self.base_directory(argv), self.base_directory(self.argv())) + self.assertIn("--generate.only_alive_patients=false", argv) + self.assertLess( + argv.index("-c"), argv.index("--generate.only_alive_patients=false") + ) + with self.assertRaises(FileNotFoundError): + self.argv(local_config_path=self.tmp / "missing.properties") + + def test_unknown_config_is_checked_against_active_jar(self): + settings = _GenerationSettings(synthea_config={"future.unknown.property": 1}) + + with self.assertRaisesRegex(ValueError, "not supported"): + Synthea._validate_config_keys(self.properties_jar(), settings) + + def test_java_resolution_order(self): + explicit = self.tmp / "explicit-java" + explicit.write_text("") + home = self.tmp / "java-home" + (home / "bin").mkdir(parents=True) + (home / "bin" / "java").write_text("") + + with ( + mock.patch.dict(os.environ, {"JAVA_HOME": str(home)}), + mock.patch( + "pyhealth.models.generators.synthea.shutil.which", + return_value="/path/java", + ), + mock.patch.object(Synthea, "_java_major_version", return_value=17), + ): + self.assertEqual( + self.generator(java_path=explicit)._resolve_java(), + explicit.resolve(), + ) + self.assertEqual( + self.generator()._resolve_java(), + (home / "bin" / "java").resolve(), + ) + + def test_missing_java_raises(self): + with ( + mock.patch.dict(os.environ, {}, clear=True), + mock.patch( + "pyhealth.models.generators.synthea.shutil.which", + return_value=None, + ), + self.assertRaisesRegex(RuntimeError, "Java"), + ): + self.generator()._resolve_java() + + def test_java_version_parsing(self): + outputs = ( + ('openjdk version "17.0.20.1" 2026-08-18\n', 17), + ('openjdk version "21" 2023-09-19\n', 21), + ('openjdk version "25-ea" 2025-09-16\n', 25), + ('java version "1.8.0_392"\n', 8), + ("Error: could not find libjava.so\n", None), + ) + for stderr, expected in outputs: + with ( + self.subTest(stderr=stderr), + mock.patch( + "pyhealth.models.generators.synthea.subprocess.run", + return_value=mock.Mock(stderr=stderr, stdout=""), + ), + ): + self.assertEqual(Synthea._java_major_version(Path("java")), expected) + + def test_old_java_raises_with_its_version(self): + old_java = self.tmp / "java" + old_java.write_text("") + + with ( + mock.patch.object(Synthea, "_java_major_version", return_value=11), + self.assertRaisesRegex(RuntimeError, "is Java 11"), + ): + self.generator(java_path=old_java)._resolve_java() + + def test_unknown_java_version_is_tolerated(self): + java = self.tmp / "java" + java.write_text("") + + with mock.patch.object(Synthea, "_java_major_version", return_value=None): + self.assertEqual( + self.generator(java_path=java)._resolve_java(), java.resolve() + ) + + def test_unrunnable_java_raises(self): + with ( + mock.patch( + "pyhealth.models.generators.synthea.subprocess.run", + side_effect=PermissionError("not executable"), + ), + self.assertRaisesRegex(RuntimeError, "cannot run Java"), + ): + Synthea._java_major_version(Path("java")) + + @unittest.skipUnless(shutil.which("java"), "requires Java on PATH") + def test_real_java_version_is_detected(self): + version = Synthea._java_major_version(Path(shutil.which("java"))) + + self.assertIsInstance(version, int) + + def test_jar_resolution(self): + jar = self.tmp / "synthea.jar" + jar.write_bytes(b"jar") + self.assertEqual(self.generator(jar_path=jar)._resolve_jar(), jar.resolve()) + + with self.assertRaises(FileNotFoundError): + self.generator(jar_path=self.tmp / "missing.jar")._resolve_jar() + + +class TestSyntheaDatasets(unittest.TestCase): + def setUp(self): + self._tmp = tempfile.TemporaryDirectory(prefix="synthea_dataset_") + self.tmp = Path(self._tmp.name) + self.root = self.tmp / "csv" + self.root.mkdir() + self.cache = self.tmp / "cache" + + def tearDown(self): + self._tmp.cleanup() + + def test_csv_dataset_uses_defaults_or_exact_explicit_tables(self): + default = SyntheaCSVDataset(self.root, cache_dir=self.cache) + empty = SyntheaCSVDataset(self.root, tables=[], cache_dir=self.cache) + explicit = SyntheaCSVDataset( + self.root, + tables=["conditions", "patients", "conditions"], + cache_dir=self.cache, + ) + + self.assertEqual(default.tables, DEFAULT_TABLES) + self.assertEqual(empty.tables, DEFAULT_TABLES) + self.assertEqual(explicit.tables, ["conditions", "patients"]) + self.assertEqual(Path(default.root), self.root) + + @mock.patch.object(BaseDataset, "load_data", return_value="events") + def test_csv_dataset_loads_existing_tables(self, base_load): + (self.root / "patients.csv").write_text("Id\npatient-1\n") + dataset = SyntheaCSVDataset( + self.root, tables=["patients"], cache_dir=self.cache + ) + + self.assertEqual(dataset.load_data(), "events") + base_load.assert_called_once_with() + + @mock.patch.object(BaseDataset, "load_data", return_value="events") + def test_csv_default_tables_skip_files_not_emitted_for_empty_types(self, base_load): + for table in set(DEFAULT_TABLES) - {"allergies", "imaging_studies"}: + (self.root / f"{table}.csv").write_text("PATIENT\npatient-1\n") + dataset = SyntheaCSVDataset(self.root, cache_dir=self.cache) + + self.assertEqual(dataset.load_data(), "events") + + self.assertNotIn("allergies", dataset.tables) + self.assertNotIn("imaging_studies", dataset.tables) + base_load.assert_called_once_with() + + def test_csv_explicit_missing_table_raises(self): + dataset = SyntheaCSVDataset( + self.root, tables=["allergies"], cache_dir=self.cache + ) + + with self.assertRaisesRegex(RuntimeError, "allergies"): + dataset.load_data() + + def test_preprocess_procedures_supports_legacy_date(self): + dataset = SyntheaCSVDataset(self.root, cache_dir=self.cache) + frame = nw.from_native(pl.DataFrame({"date": ["2020-01-01T00:00:00Z"]}).lazy()) + + result = dataset.preprocess_procedures(frame).collect().to_native() + + self.assertEqual(result["start"].to_list(), ["2020-01-01T00:00:00Z"]) + + @unittest.skipUnless( + os.environ.get("PYHEALTH_SYNTHEA_LIVE"), + "requires Java and the Synthea jar", + ) + def test_live_generate_and_load_csv(self): + synthea = Synthea(output_dir=self.tmp / "live", timeout=900) + csv_dataset = SyntheaCSVDataset( + synthea.generate(population=1, seed=42), cache_dir=self.cache / "csv" + ) + + self.assertEqual(len(csv_dataset.unique_patient_ids), 1) + + +if __name__ == "__main__": + unittest.main()