-
Notifications
You must be signed in to change notification settings - Fork 2
Architecture
This page explains Synthea's internal design — how the simulation engine, world model, module system, and exporters fit together.
CLI / Python API
│
▼
Generator
├── reads GeneratorOptions + Config
├── loads Demographics data
├── spins up N worker threads
│
└── per thread:
Person (seed)
│
▼
Lifecycle Simulation
├── Birth → initialise attributes
├── for each time step (default: 1 week):
│ ├── run all Module state machines
│ ├── apply growth charts / vital updates
│ └── check for death condition
└── Export (FHIR / CSV / JSON)
tietai-synthea/
├── pyproject.toml # UV project config + dependencies
├── resources/
│ ├── modules/ # 231 disease modules (JSON state machines)
│ │ ├── allergies/
│ │ ├── breast_cancer/
│ │ ├── covid19/
│ │ └── *.json
│ ├── geography/ # Census demographic data
│ ├── providers/ # Healthcare facility CSVs (15 files)
│ ├── payers/ # Insurance payer data
│ ├── costs/ # Cost tables (14 files)
│ ├── lookup_tables/ # Transition probability tables
│ ├── cdc_growth_charts.json # CDC growth data
│ ├── immunization_schedule.json
│ └── synthea.properties # Default configuration
├── src/synthea/
│ ├── engine/
│ │ ├── generator.py # Orchestration: threads, lifecycle
│ │ ├── module.py # Module loader and runner
│ │ ├── state.py # All state type implementations
│ │ ├── transition.py # Transition evaluation
│ │ └── logic.py # Condition / logic evaluation
│ ├── world/
│ │ ├── person.py # Patient model (attributes + health record)
│ │ ├── health_record.py # Clinical event log
│ │ ├── demographics.py # Geographic + census data loader
│ │ ├── location.py # State / city / zip resolution
│ │ ├── provider.py # Provider selection
│ │ └── payer.py # Insurance assignment
│ ├── export/
│ │ ├── fhir.py # FHIR R4 serialiser
│ │ └── exporter.py # Base exporter + dispatch
│ ├── helpers/
│ │ └── config.py # synthea.properties reader/writer
│ └── cli.py # Click CLI entry point
├── tests/
│ ├── test_person.py
│ ├── test_state.py
│ ├── test_generator.py
│ └── test_integration.py
└── examples/
├── basic_generation.py
├── custom_module.py
└── batch_export.py
The central orchestrator. Responsibilities:
- Parse
GeneratorOptionsand loadConfig - Load demographic distributions from
resources/geography/ - Assign each patient a birth date, location, gender, race/ethnicity, and socioeconomic status
- Run the lifecycle simulation (single-threaded or via
ThreadPoolExecutor) - Dispatch each completed
Personto the configured exporters
Each disease module is a finite state machine loaded from JSON:
-
module.pyreads the JSON file and instantiatesStateobjects - On each time step, the module's current state is evaluated
-
transition.pypicks the next state (direct, probabilistic, conditional) -
logic.pyevaluates boolean conditions against thePerson's current attributes
Modules are composable: any state can call a submodule via CallSubmodule, enabling reuse across conditions (e.g., an encounter template shared by many modules).
Person holds:
-
Attributes — a dict of arbitrary key/value pairs set by modules (
age,gender,diabetes, custom flags, etc.) - Health record — an append-only log of clinical events (conditions, medications, encounters, observations, procedures, immunizations)
- Vital signs — current height, weight, BMI, blood pressure
HealthRecord maps directly onto FHIR resources at export time.
exporter.py reads the config and dispatches completed Person objects to:
-
FHIRExporter— serialises the health record to a FHIR R4 Bundle -
CSVExporter— appends rows to per-resource CSV files -
JSONExporter— dumps the raw Python object as JSON
Exporters are stateless; multiple threads write to separate files or use file locks for CSV append mode.
Main thread
└─ ThreadPoolExecutor (N workers)
├─ Worker 1: Person(seed=0) ... Person(seed=k)
├─ Worker 2: Person(seed=k+1) ...
└─ Worker N: ...
Each worker operates on independent Person objects with no shared mutable state. The RNG is seeded per-patient (seed + patient_index), so results are reproducible when --threads 1 is used (thread-order is deterministic); with multiple threads, generation order is non-deterministic but each individual patient is still reproducible given the same seed.
synthea.properties
│
▼
Config
│
├── Generator
│ ├── Demographics → Person attributes
│ ├── Modules → HealthRecord events
│ └── Provider / Payer assignment
│
└── Exporters
├── FHIRExporter → output/fhir/*.json
├── CSVExporter → output/csv/*.csv
└── JSONExporter → output/json/*.json