This tutorial shows how to run the standard probabilistic sensitivity analysis workflow end to end: specify parameters, sample draws, evaluate a model with run_psa, then feed the outcomes to cost-effectiveness and value-of-information analysis. Bring your own outputs covers the analysis functions in more detail; here the focus is the run itself.
Specifying and sampling parameters
Distributions are specified directly or from published mean and standard error. ParameterSet.sample returns a draw matrix, one row per iteration; a Spearman rank correlation can be requested per parameter pair.
A model is a function that takes the draw matrix and returns Outcomes. The one below is a two-intervention decision tree evaluated over one year. Outcomes.from_wide builds that result from per-intervention cost and effect columns.
run_psa evaluates the model on every draw and keeps each outcome matched to the parameters that produced it, the link value-of-information analysis relies on. It runs in parallel by default; this run is small, so sequential=True runs it without that overhead.
from heormodel.run import run_psaoutcomes = run_psa(decision_tree, draws, sequential=True).outcomesoutcomes.summary().round(3)
cost
qaly
intervention
No treatment
4986.265
0.930
Treatment
7505.804
0.951
Analyzing cost-effectiveness and value of information
Nothing from here on is specific to a decision tree: the same icer_table, evpi, and evppi_ranking calls apply to the Outcomes any model produces.
Treatment is the more expensive, more effective intervention; whether its incremental cost-effectiveness ratio stays below a given willingness-to-pay threshold, and how much resolving that uncertainty would be worth, are what EVPI and the per-parameter ranking answer next.
WTP =50_000.0print(f"EVPI at WTP {WTP:,.0f}: {evpi(outcomes, WTP):,.2f}")evppi_ranking(outcomes, draws, WTP).round(2)
running_means tracks the running mean of an outcome column per intervention as iterations accumulate; flat traces at the right edge suggest the iteration count is adequate for the means (value-of-information estimates typically need more).
from heormodel.run import running_meansrunning_means(outcomes).plot(xlabel="iterations", ylabel="mean cost");
The engines concept page describes the model types run_psa can run. Next: the value of information tutorial takes outcomes like these through the expected value of perfect, partial perfect, and sample information, checking each against a closed form.