Assemble an infectious disease model
as_turing_model interface.
Interchangeable parts, one interface
A model has three roles — latent process, infection mechanism, observation model. Each is an interchangeable part; all speak the same as_turing_model interface, so they nest freely and swap without rewrites.
Uncertainty through the full pipeline
Uncertainty propagates from the latent process through infection dynamics, reporting delays, ascertainment, and observation noise — all captured in one posterior via the same inference engine.
Built for the workflow, not the model
The same assembly simulates from the prior, conditions on data, nowcasts unobserved infections, and forecasts forward — no separate model for each step in the analysis workflow.
using ComposableTuringIDModels, Distributions, Turing
# Renewal infections with inline latent process
data = IDData(gen_distribution = Gamma(1.4, 1 / 0.38))
model = IDModel(
Renewal(data;
rt = AR(; ϵ_t = HierarchicalNormal(
std_prior = HalfNormal(0.1))),
initialisation_prior = Normal(log(1.0), 1.0)),
# Multiple observation layers:
# delay → ascertainment → negative-binomial noise
LatentDelay(
Ascertainment(
NegativeBinomialError(),
ascertainment_prior = Beta(10, 2)),
truncated(Normal(5.0, 2.0), 0.0, Inf)))
# Fit to case data with Turing's NUTS
chain = sample(as_turing_model(model, cases, length(cases)),
NUTS(), MCMCThreads(), 1_000, 2)The approach
ComposableTuringIDModels is a meta-language for composing Turing models — it provides the wiring that lets any latent process, infection model, and observation layer nest inside one another through the single as_turing_model interface. An epidemiological model couples three processes: what drives transmission over time (the latent process), how that driver generates infections (the infection process), and how those infections become the observed data (the observation process). The key design choice is that each of these is an interchangeable part, and every part speaks the same as_turing_model interface — so any latent process nests inside any infection model, and any observation model wraps the result.
No model rewrites, only part swaps
Changing an assumption means swapping one part for another — replacing the renewal equation with exponential growth, switching from Poisson to negative-binomial observation, adding a reporting delay. The model structure stays the same; the swapped part carries the new assumption. This makes it practical to test sensitivity to each modelling choice without maintaining N bespoke models for N assumptions.
Layered observation models
Real data is never a direct readout of infections. Reporting delays, ascertainment (under-reporting), right-truncation, day-of-week effects, and count noise each modify how infections become data. These are composable modifiers: each wraps the underlying observation model and adds one transformation. Layers are added or removed independently — a delay is a LatentDelay wrapper, ascertainment is an Ascertainment wrapper, noise is the core error model — and every layer is still a part that speaks as_turing_model.
One assembly for the full workflow
The same IDModel that defines the joint distribution also generates prior predictives, conditions on observed data, runs NUTS inference, and produces posterior draws. There is no separate simulation model, inference model, and forecasting model — the assembly is the model for every step. This means the generative story, the inference, and the forecast all share the same structure, and a change to the model propagates through the workflow automatically.
Full Turing toolchain
Every assembly is a DynamicPPL model under the hood, so the full Turing ecosystem applies: NUTS and Pathfinder for sampling, MCMCThreads for parallel chains, prior and posterior predictive checks, and the standard Turing diagnostics. There is no separate inference engine to learn.
Where next
- The ComposableTuringIDModels.jl documentation covers the part catalogue, design, and worked examples.
- See the overview for the full design rationale and the nested architecture diagram.
- Interested in the delay side of the model? See the composed distributions approach.