Health economic evaluation in Python: PSA parameters, swappable model engines, cost-effectiveness analysis, and value of information
Project description
heormodel
Health economic evaluation in Python: parameter specification and probabilistic sampling, simulation across model types, cost-effectiveness analysis (CEA), and value-of-information (VoI) analysis for model-based HEOR and HTA work.
Every model engine returns costs and effects in one standardized structure, so CEA and VoI run the same on outputs from any source. You do not need a built-in engine to start: a PSA table from a spreadsheet or a legacy simulator enters the pipeline through one call.
Documentation: pedroliman.github.io/heormodel
Install
pip install heormodel
The calibration extra adds ABC-SMC calibration: pip install "heormodel[calibration]". Development uses uv; see Development.
Quickstart
Load a costs/effects PSA table with as_outcomes, then run incremental analysis and value of information from the same object:
import numpy as np
import pandas as pd
from heormodel.run import as_outcomes
from heormodel.cea import icer_table
from heormodel.voi import evpi
rng = np.random.default_rng(7)
n = 2_000
df = pd.concat(
pd.DataFrame({
"strategy": name, "iteration": range(n),
"cost": rng.normal(cost, 2_000, n), "qaly": rng.normal(q, 0.4, n),
})
for name, cost, q in [("Standard care", 40_000, 8.0), ("New drug", 52_000, 8.6)]
)
outcomes = as_outcomes(df) # accepts a DataFrame or a CSV path
icer_table(outcomes).round(1)
# cost effect inc_cost inc_effect icer status
# strategy
# Standard care 39920.1 8.0 NaN NaN NaN ND
# New drug 51985.1 8.6 12065.0 0.6 20606.0 ND
round(evpi(outcomes, wtp=30_000), 1)
# 4339.3
examples/byoo_example.py runs the same wedge end to end: an external table through CEA, VoI, plots, and a run report, plus the full pipeline (ParameterSet sampling, SeedManager, run_psa).
The examples/mdm_*.py scripts replicate three published Sick-Sicker cost-effectiveness tutorials and match their deterministic results: a cohort state-transition model (mdm_cohort.py), its time-dependent version with age-varying mortality (mdm_cohort_timedep.py), and a microsimulation (mdm_microsim.py). Each has a companion page in the replication gallery.
examples/microsim.py builds an individual-level model with MicrosimModel: frailty heterogeneity and a mortality risk that rises with time spent sick, two features a cohort average cannot carry, then runs it through CEA and VoI. Run it with uv run python examples/microsim.py.
examples/markov_vs_microsim.py builds one Sick-Sicker-style model as both a MarkovModel cohort trace and a MicrosimModel individual simulation from the same rates. The homogeneous microsimulation converges to the cohort trace (a cross-engine cross-validation), then a mean-1 frailty raises the microsimulation QALYs about 8% above the cohort on unchanged mean rates, the heterogeneity a cohort averages away. Run it with uv run python examples/markov_vs_microsim.py.
examples/des.py builds a resource-constrained clinic with DESModel, a thin SimPy wrapper: patients queue for a scarce specialist, so added capacity buys QALYs by cutting waiting time, a coupling a cohort model cannot carry. Run it with uv run python examples/des.py after installing the des extra.
examples/calibration_workflow.py mixes parameter sources: a natural-history model's transition rates are calibrated to observed prevalence with abc_calibrate, utilities and costs come from the literature, and mix_draws joins the two into one PSA that flows through CEA and VoI. Run it with uv run python examples/calibration_workflow.py after installing the calibration extra.
examples/parameter_inputs.py shows the three ways parameters enter the run loop besides distribution sampling: single_draw (and ParameterSet.at_means) for a base-case run, read_draws for a draw matrix from a CSV or DataFrame, and resample_posterior for a weighted posterior resampled with replacement. Run it with uv run python examples/parameter_inputs.py.
Package layout
| Subpackage | Status | Contents |
|---|---|---|
heormodel.params |
done | Distribution specs with mean/SE constructors; correlated sampling; draw matrices from point values, CSVs, and weighted posteriors |
heormodel.models |
done | Outcomes schema, ModelEngine protocol; cohort state-transition, microsimulation, and discrete-event engines built |
heormodel.run |
done | SeedManager, run_psa, as_outcomes, running-mean diagnostics |
heormodel.cea |
done | ICERs, dominance, extended dominance, frontier, NMB/NHB, CEAC/CEAF |
heormodel.dsa |
done | One-way, one-at-a-time, and full-factorial grid deterministic sensitivity designs |
heormodel.voi |
done | EVPI; EVPPI (spline/GP metamodels); EVSI (regression; others stubbed) |
heormodel.calibrate |
done, optional | ABC-SMC via pyabc; posterior as an iteration-indexed draw matrix |
heormodel.report |
done | CE plane, CEAC/CEAF, frontier, tornado plots; provenance, run report |
Full docs are at pedroliman.github.io/heormodel. Next steps are prioritized in roadmap/; shipped changes are in CHANGELOG.md; the release process is in RELEASING.md. Prose follows guidance/writing_style.md.
Development
Requires Python 3.11+ and uv:
uv venv && uv pip install -e ".[dev]" # extras: calibration (pyabc), des (simpy), dev
uv run pytest # suite incl. validation checks
uv run pytest --doctest-modules src # every docstring example runs
uv run ruff check . && uv run mypy
Two validation checks anchor the suite: a hand-verified five-strategy dominance and ICER example (tests/test_cea.py), and analytic Gaussian EVPI/EVPPI/EVSI recovered within Monte Carlo error at 80,000 iterations (tests/test_voi.py).
The documentation site lives in docs/ and builds with Quarto and quartodoc; tutorials execute at render time, so the build doubles as a test. With Quarto installed and the docs extra synced (uv sync --extra docs):
uv run quartodoc build --config docs/_quarto.yml # generate the API reference
quarto preview docs # or: quarto render docs
CI (.github/workflows/docs.yml) rebuilds and publishes the site to GitHub Pages on every push to main.
Design notes
- VoI metamodeling uses scikit-learn;
method=leaves room for other backends. heormodel.calibrateis a seventh subpackage beyond the original six; calibrated draws re-enter the pipeline as a standard draw matrix.- Mean/SE constructors turn published estimates into sampling distributions; direct parameterisation remains available.
- Dirichlet vectors sample as normalised independent Gammas; leave their correlation targets at zero.
- Tornado diagrams are PSA-based (linear fits at outer percentiles); phase 1 has no deterministic engine to re-run.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file heormodel-0.6.0.tar.gz.
File metadata
- Download URL: heormodel-0.6.0.tar.gz
- Upload date:
- Size: 80.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a97b56608a482882f7453d9faa884b1b7e2cd02f702b7a25cf5eed82100114f
|
|
| MD5 |
d6759418f40a91f1b525ddb4f2dfe526
|
|
| BLAKE2b-256 |
d5773ef64c1254c286089d604860c4bd9dbb3c39f6068449af5cc1cb7adabb25
|
Provenance
The following attestation bundles were made for heormodel-0.6.0.tar.gz:
Publisher:
release.yml on pedroliman/heormodel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
heormodel-0.6.0.tar.gz -
Subject digest:
9a97b56608a482882f7453d9faa884b1b7e2cd02f702b7a25cf5eed82100114f - Sigstore transparency entry: 2082597044
- Sigstore integration time:
-
Permalink:
pedroliman/heormodel@6374c7d46428bc81eb37b1bf58c69696125c8c12 -
Branch / Tag:
refs/tags/0.6.0 - Owner: https://github.com/pedroliman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6374c7d46428bc81eb37b1bf58c69696125c8c12 -
Trigger Event:
release
-
Statement type:
File details
Details for the file heormodel-0.6.0-py3-none-any.whl.
File metadata
- Download URL: heormodel-0.6.0-py3-none-any.whl
- Upload date:
- Size: 72.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d2545138c8b47b0f4a4a1aa3be4806216b57328401f53ea357744a868c30784
|
|
| MD5 |
a9dca968edb82d9bac41eca97eb7a22f
|
|
| BLAKE2b-256 |
8761fc90272394d6b7ef8e49144b3375d5d008051eff6017a729f08ddeac4502
|
Provenance
The following attestation bundles were made for heormodel-0.6.0-py3-none-any.whl:
Publisher:
release.yml on pedroliman/heormodel
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
heormodel-0.6.0-py3-none-any.whl -
Subject digest:
3d2545138c8b47b0f4a4a1aa3be4806216b57328401f53ea357744a868c30784 - Sigstore transparency entry: 2082597083
- Sigstore integration time:
-
Permalink:
pedroliman/heormodel@6374c7d46428bc81eb37b1bf58c69696125c8c12 -
Branch / Tag:
refs/tags/0.6.0 - Owner: https://github.com/pedroliman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6374c7d46428bc81eb37b1bf58c69696125c8c12 -
Trigger Event:
release
-
Statement type: