Skip to main content

heartland-synthetic

Synthetic heart-failure cohorts with modeled rural access, social support, and the ten proposed HEARTLAND risk criteria.

CI PyPI Dataset on Hugging Face License: MIT Python 3.10+

heartland-synthetic generates simulated HF cohorts, computes a proposed HEARTLAND point score, and writes standalone REDCap and FHIR R4 collection exports. It supports research workflow development, software tests and educational demonstrations using synthetic data. It does not establish clinical realism, predictive validity, patient outcomes, or institutional interoperability. Do not supply real patient, personal, or health information.

Release line: 0.3.1 (documentation maintenance). Input checks and export changes were released in 0.3.0, archived at 10.5281/zenodo.23050640. Version 0.3.1 corrects release documentation; it does not change the generator, scoring or exporters. The preserved benchmark remains dataset v1.0.0; its original provenance cites the v0.2.1 software archive, not the later PyPI release. It is not renamed or regenerated when the software changes.

Why this exists

The package makes two modeled rural-HF domains explicit:

  • Distance to cardiology care (rural barrier)
  • Social support (a legacy synthetic numeric proxy, not an ESSI instrument)

Researchers can inspect the simulation assumptions and point weights used by the HEARTLAND clinical implementation companion. This is not a benchmark establishing superiority or exclusivity over other generators or risk models.

Install

pip install heartland-synthetic==0.3.1

That command targets this release line. Verify availability and file hashes on the versioned registry page; a source version or successful build alone is not a publication receipt. For a reviewed source checkout, use an editable development install:

git clone https://github.com/vickymuller-md/heartland-synthetic
cd heartland-synthetic
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest -q

Python >= 3.10; core deps: numpy, pandas, scipy.

Quickstart

from heartland_synthetic import generate_cohort, HeartlandCohortConfig

config = HeartlandCohortConfig(
    n_patients=500,
    rural_fraction=0.7,
    hf_type_distribution={"hfref": 0.45, "hfmref": 0.15, "hfpef": 0.40},
    age_range=(45, 95),
    include_outcomes=True,
    seed=42,
)
df = generate_cohort(config)
print(df["heartland_risk_tier"].value_counts())

The returned DataFrame has one row per patient; every patient comes with the HEARTLAND score and tier already computed.

HeartlandCohortConfig

Field Default Description
n_patients 500 Cohort size (must be > 0)
rural_fraction 0.5 Share of patients with USDA RUCA >= 4
hf_type_distribution {hfref: .45, hfmref: .15, hfpef: .40} HF subtype mix (must sum to 1.0)
age_range (45, 95) Inclusive age bounds (min >= 18)
female_fraction 0.48 Share of female patients
include_outcomes True Attach mortality_1yr / hospitalization_1yr
include_medications True Sample GDMT flags; if False, retain columns as simulation zeros
seed None Integer seed; None yields OS-entropy randomness

Output schema

Column Type Notes
patient_id str HS-000001-style identifier
age int Years
sex str F / M
race str White / Black / Hispanic / Other
state str US postal abbreviation
county_fips str Synthetic 5-digit code
rural_urban_code int USDA RUCA 1-10
hf_type str hfref / hfmref / hfpef
lvef float % (by stratum)
egfr float mL/min/1.73 m^2
bnp float pg/mL
sbp, dbp, hr int mmHg / mmHg / bpm
bmi float kg/m^2
diabetes, af int 0/1
ckd_stage int eGFR-derived 1-5 bin; not a clinical CKD diagnosis
ckm_stage int Legacy 0-4 simulation category; not adjudicated AHA CKM staging
distance_to_cardiology_mi float Miles
social_support_score int Legacy synthetic proxy, generated range 8-40; not an ESSI scale
prior_hf_hosp_6mo int 0/1
on_acei_arb_arni / on_beta_blocker / on_mra / on_sglt2i int 0/1
gdmt_classes_count int 0-4
heartland_risk_score int 0-18
heartland_risk_tier str low / moderate / high
mortality_1yr, hospitalization_1yr int 0/1 (only if include_outcomes=True)

Model assumptions and background literature

The named studies provide background context, not proof that the numerical settings below were extracted from or fitted to those studies. No calibration dataset, parameter-estimation procedure, or clinical validation is supplied. See the model-assumptions ledger for the code paths, limitations and separate version histories.

Variable Implemented model Background context / evidence boundary
Age Truncated Normal(72, 12) GWTG-HF
Sex Bernoulli GWTG-HF
Race Categorical GWTG-HF / NHANES
LVEF (HFrEF / HFmrEF / HFpEF) Strata-specific PARADIGM-HF / DELIVER / EMPEROR-Preserved
eGFR LogNormal(ln 60, 0.35), elderly shift STRONG-HF / CKD-EPI
BNP LogNormal(ln 600, 0.9); HFpEF -30% PARADIGM-HF
SBP Normal(125, 20); rural +5 mmHg GWTG-HF
DBP 0.6 * SBP + N(0, 14) (rho ~ 0.65) Derived
HR Normal(78, 14) GWTG-HF
BMI Normal(30, 6); HFpEF +3 DELIVER
Diabetes Bernoulli(0.42 + HFpEF/obesity bumps) GWTG-HF
AF Bernoulli(0.35 + elderly bump) GWTG-HF
CKD stage Deterministic eGFR bin KDIGO terminology only; no chronicity/albuminuria assessment
CKM stage Legacy cascade on diabetes, CKD bin, BMI, age Not an implementation of clinical AHA staging
Distance to cardiology Assumed LogNormal (rural vs urban) No NPPES lookup, routing, or Atlas join
Social support Normal (rural 24, urban 29), rounded and clipped to 8-40 Legacy simulation assumption, not an ESSI implementation
GDMT rates Assumed Bernoulli, rural vs urban CHAMP-HF context; no fitted rates or assessed prescribing
1-yr mortality per tier Assumed 0.06 / 0.15 / 0.32 Not MAGGIC predictions or Manemann hazard-ratio conversion
1-yr hospitalization per tier Assumed 0.18 / 0.35 / 0.55 Not fitted GWTG-HF outcome estimates

The principal settings live in src/heartland_synthetic/registries.py; sampling modules also contain clipping, rounding and category rules. The six-dimensional copula covers LVEF/eGFR/BNP/SBP/HR/BMI; DBP is generated separately from SBP plus noise. Associations in generated data are properties of these assumptions, not measured clinical relationships.

Apply HEARTLAND scoring on a synthetic input table

from heartland_synthetic import apply_heartland_scoring
import pandas as pd

df = pd.read_csv("synthetic_cohort.csv")  # complete synthetic inputs only
scored = apply_heartland_scoring(df)

Required columns: age, prior_hf_hosp_6mo, egfr, bnp, sbp, diabetes, lvef, ckm_stage, distance_to_cardiology_mi, social_support_score.

The ten weights and tier boundaries follow heartland-app/lib/risk-score/engine.ts (Protocol v3.3, Table 1): 18 points maximum, tiers low 0-4 / moderate 5-8 / high 9-18. The numeric adapter uses BNP only, not NT-proBNP. The existing social_support_score < 18 criterion is retained solely as a legacy simulation proxy. It does not establish equivalence to an ESSI version, questionnaire, item score, or clinical cutoff. Complete boolean-criterion agreement is not clinical validation.

Since 0.3.0, scoring rejects incomplete or structurally invalid input:

  • All ten required fields must be present in every row. Missing columns raise KeyError; nulls, NaN, infinity, strings, and other unsupported values raise ValueError. There is no imputation, string parsing, or default-negative rule.
  • Measurements accept finite Python/NumPy integers or floating-point scalars, but not booleans. diabetes and prior_hf_hosp_6mo accept explicit booleans or numeric values exactly equal to 0 or 1. ckm_stage must be integral in 0–4.
  • classify_tier accepts integral numeric totals in 0–18, never booleans, fractional values, or missing values. Integral floating-point values are supported for pandas compatibility.
  • Duplicate column labels are rejected. An empty table still needs all ten columns and returns typed, empty score/tier columns. Row order, index (including duplicate labels), and extra columns are retained. Missing values in unrelated extra columns do not prevent scoring.
  • Existing score/tier columns are recomputed on a copy. One invalid row fails the whole call, without changing the input or returning a partially scored table. Errors identify a fixed field name, not input values or row identifiers.

These checks establish structural completeness only. They do not check physiologic plausibility, reconcile units, validate the social-support instrument, or authorize processing of real patient data. The generator's 8–40 proxy range is not imposed on external numeric inputs. Predicates exposed through RISK_VARIABLES are low-level definitions for already validated input; use apply_heartland_scoring or compute_row_score for input checking. The HEARTLAND framework remains proposed pending validation against clinical outcomes. Do not provide real patient, personal, or health information.

Monthly time series

from heartland_synthetic import generate_time_series

ts = generate_time_series(df, months=12, seed=42)
# one row per (patient_id, month); rows after the first death_event are omitted

Columns: patient_id, month, sbp, dbp, hr, weight_kg, bnp, hosp_event, death_event. Vitals follow an AR(1) mean-reverting process around each patient's baseline. Event probabilities are tier-indexed annual rates compounded to monthly. The monthly simulation uses tier-indexed assumptions, not the cohort's binary annual outcome flags; the two event histories can disagree. Neither is an observed outcome or a validation target for the score.

REDCap export

Since 0.3.0, exporters require the complete generated cohort schema, including the ten score inputs. They reject extra/duplicate columns, invalid categories, missing or lossy numeric values, unsafe/duplicate IDs and inconsistent score, tier or GDMT count. Optional annual outcome columns must be supplied together. All rows are validated and serialized before output; input tables are not changed. See the export input contract for exact boundaries. These checks are structural, not clinical validation or PHI detection.

Use a fresh output directory or prefix: existing targets (including symbolic links) are refused, never overwritten. A later I/O failure can leave partial new output; the whole export batch is not an atomic filesystem transaction.

from heartland_synthetic import export_redcap
data_csv, dict_csv = export_redcap(df, "outputs/heartland_cohort")

Writes two files:

  • outputs/heartland_cohort.csv — data with record_id (= patient_id)
  • outputs/heartland_cohort_datadict.csv — 18-column REDCap data dictionary (radio for categoricals, dropdown for coded integers, yesno for booleans, text+number validation for continuous vitals).

Standalone instrument. export_redcap() writes a self-contained REDCap project: one single-form instrument (heartland_cohort) whose data dictionary is generated from the cohort columns. It follows the official 18-column REDCap data dictionary layout, intended for evaluation in a new, empty REDCap project. A generated CSV and local tests do not demonstrate a successful institutional import or clinical deployment.

It is not an import file for the HEARTLAND REDCap Instrument Template, which is a separately versioned instrument. This function is not a direct Template importer and does not prove compatibility with its current candidate.

The review of the historical crosswalk for the earlier 75-field/5-form Template is in docs/redcap_template_crosswalk.md. It withdraws unsupported ESSI, staging, geography, medication and outcome-count mappings. The standalone dictionary includes simulation labels/field notes; it does not convert source values into clinically adjudicated measurements. It is not a current conversion or institutional import receipt.

FHIR R4 export

from heartland_synthetic import export_fhir_bundle
paths = export_fhir_bundle(df, "outputs/fhir/")
# one Bundle per patient at outputs/fhir/{patient_id}.json

Each collection Bundle contains:

  • Patient with the US Core 6.1 race and ethnicity extensions as two separate extensions. The cohort carries one 4-level variable that mixes race and ethnicity, so Hispanic is written to ethnicity (race UNK) and Other is written as UNK on both axes — neither axis is inferred from the other.
  • Text-only Condition for the assigned HF simulation group and positive diabetes/AF flags; no inferred ICD diagnoses, CKD or diabetes subtype
  • Quantity Observation for LVEF / BNP / SBP / DBP / HR / BMI (LOINC), with SBP/DBP as components of one blood-pressure panel and generic text-only eGFR because no estimation formula was actually calculated
  • Text-only Observation for legacy eGFR/CKM bins, support proxy, modeled distance and prior-hospitalization flag, with their simulation limits
  • Text-only MedicationStatement for positive simulated class flags, with status unknown; no specific drug, dose or actual receipt is inferred
  • Observation for the HEARTLAND score total (0-18 points) under the custom CodeSystem https://fhir.heartlandprotocol.org/CodeSystem/heartland-risk-score, plus all ten Boolean criterion components (including false), explicitly labeled as simulated inputs/proxies rather than a verified clinical assessment
  • RiskAssessment carrying the tier as a coded prediction.qualitativeRisk (https://fhir.heartlandprotocol.org/CodeSystem/heartland-risk-tier), with the score Observation as basis. prediction.probabilityDecimal is left empty: the total is a point count, not a likelihood.

Address carries state and country only. The synthetic county code travels in an extension whose system URI marks it as synthetic; it is never written to Address.postalCode. No resource declares meta.profile: the Bundles have not been validated against US Core 6.1 or the HEARTLAND IG, so they assert no profile conformance. Valid UUID entry URLs and exact internal references make subjects/basis resolvable within each collection. Every resource is tagged as synthetic research/testing data; the fixed reference date is not an actual clinical event date. This is not a lossless cohort export or EHR import plan. See FHIR mapping and compatibility changes, including omitted source fields and withdrawn legacy codes.

Reproducibility

The public generators accept a seed (HeartlandCohortConfig.seed and generate_time_series(..., seed=...)). The same seed, configuration and runtime produce repeatable DataFrames. This is not a promise of byte-identical results across dependency/platform versions. FHIR resources use random UUIDs and are not byte-deterministic exports. Record runtime versions alongside the seed.

cfg = HeartlandCohortConfig(n_patients=100, seed=42)
assert generate_cohort(cfg).equals(generate_cohort(cfg))

Limitations

  • Synthetic use only: the bundled benchmark and generator outputs are synthetic. APIs can accept caller-supplied tables; the package does not detect PHI or anonymize those tables. Do not provide real patient data.
  • Assumed outcomes are not clinical evidence. Tier-indexed event rates are fixed simulation settings. Validating the HEARTLAND score against events generated from that score's tiers would be circular, not independent validation. Do not estimate treatment benefit, population risk or efficacy.
  • County FIPS codes are synthetic and must not be decoded. They are not ANSI/Census county GEOIDs: the 2-digit prefix is an alphabetical index over the state pool, not a real state FIPS, so a code can collide with the real FIPS of a different state and contradict the state column. The RUCA assignment and state pool are modeled but not geo-accurate.
  • CKM and CKD fields are legacy simulation categories, not adjudicated clinical stages or diagnoses. Their limitations are documented in the ledger.
  • GDMT utilization is point-prevalence at a single reference date; no titration trajectory is modeled.
  • There is no NT-proBNP, ECG, echo structural anatomy or NYHA class. BMI is a modeled anthropometric measure, not a laboratory assay. Social support is a numeric proxy with no questionnaire items or validated ESSI implementation.
  • No regulatory, HIPAA-compliance, de-identification, clinical-safety or patient-care authorization is established by this software or its tests.

Benchmark dataset

The public 1,000-row, seed-42 benchmark cohort is available from the dataset landing page and Hugging Face. Its original provenance cites the v0.2.1 software archive. That archive retained internal version metadata of 0.2.0; neither that metadata nor the later 0.2.2 packaging release proves the original execution environment. The original Python/dependency receipt is unavailable, so byte-identical regeneration is not promised. Download the preserved CSV and verify SHA-256 8fbce909272274129f94db2b80b179b493e64fbc382a88515a851089b2edda8e. It contains no real patient data or protected health information.

Citation

Software:

@software{mullerferreira_heartland_synthetic_2026,
  author = {Muller Ferreira, Vicky},
  title  = {heartland-synthetic: Synthetic heart-failure cohort generator with HEARTLAND risk variables},
  year   = {2026},
  publisher = {Zenodo},
  doi    = {10.5281/zenodo.19635042},
  url    = {https://doi.org/10.5281/zenodo.19635042}
}

Technical report:

@techreport{mullerferreira_heartland_synthetic_report_2026,
  author = {Muller Ferreira, Vicky},
  title  = {heartland-synthetic: A Reproducible Generator and Benchmark Dataset for Rural Heart-Failure Research Workflows},
  year   = {2026},
  institution = {Zenodo},
  doi    = {10.5281/zenodo.22137199},
  url    = {https://doi.org/10.5281/zenodo.22137199}
}

The report concept DOI resolves to all versions. Version 1.0 is archived at 10.5281/zenodo.22137200.

Cite alongside the HEARTLAND Protocol: Muller Ferreira V. HEARTLAND Protocol v3.3. Zenodo. DOI 10.5281/zenodo.19101219.

Software preservation

Software Heritage snapshot (archived 2026-08-25): swh:1:snp:53d48ef3e36293ebabf274cb8db4b35cb55a30d7

This persistent SWHID identifies the repository snapshot captured on that date; archival does not imply endorsement or validation.

License

MIT. See LICENSE.

Landing page

A Next.js static landing page that mirrors the HEARTLAND design system lives in site/. It's deployed (by the maintainer) at synthetic.heartlandprotocol.org.

cd site
npm install
npm run dev          # http://localhost:3000
npm run build        # static export -> site/out/

Deploy on Vercel with Root Directory = site. Add the custom domain synthetic.heartlandprotocol.org; Vercel issues the CNAME target and manages TLS.

Publish runbook

Publication is separate from a local commit or build. Before an authorized release, review the exact commit and version in pyproject.toml, __init__.py, the changelog and site; run tests; verify the frozen CSV hash; build into a new empty output directory; inspect both wheel and source archive for unintended files; validate metadata and test an isolated installation of the built wheel. The distribution-verification guide describes the exact inventory checker, non-editable installed-package tests and release gates. CI tests wheel and source installations across Python 3.10–3.12; a local run only establishes the environments actually exercised in its receipt.

The repository's release workflow uses PyPI Trusted Publishing. Review its tag/version and environment gates before creating a release, because a public release can trigger external publication. Do not push all tags or upload an unreviewed dist/* directory. Select the exact reviewed tag/artifacts only. Verify the resulting PyPI files, GitHub release and Zenodo record separately; do not assume a webhook completed. Update website publication labels only after public readback. A software release does not replace the benchmark's provenance or automatically update its technical report or dataset record.

Metadata

Release files for heartland-synthetic 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for heartland-synthetic 0.3.1
File Size Uploaded Provenance Actions
heartland_synthetic-0.3.1.tar.gz 112.6 kB With provenance Details for heartland_synthetic-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for heartland-synthetic 0.3.1
File Interpreter ABI Platform Actions
heartland_synthetic-0.3.1-py3-none-any.whl Python 3 none any Details for heartland_synthetic-0.3.1-py3-none-any.whl

Total release size: 157.6 kB

Release files / heartland_synthetic-0.3.1.tar.gz

Download URL heartland_synthetic-0.3.1.tar.gz
Size 112.6 kB
Tags Source
SHA-256 checksum
How to use checksums
81bb13f3edd56ff5a8ad35d3ffe55d42befcf1292ab3dbd4a1bfa333c99ee5bf
BLAKE2b-256 checksum
How to use checksums
1bf6f5958d06dae9714d1c5317189cc54fbafc54b984c2f70d24e6aaa21fc3c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Release files / heartland_synthetic-0.3.1-py3-none-any.whl

Download URL heartland_synthetic-0.3.1-py3-none-any.whl
Size 44.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e7b97093aae7adb58f4b6acfff10df0046c4710a533f145651c75b1ab40bf776
BLAKE2b-256 checksum
How to use checksums
23dd564604d6331d9507bbbb8b55eaa9dc49fedf87801900e22715e23460308f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

Security for heartland-synthetic 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for heartland_synthetic-0.3.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 30, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page