API reference
TransmissionLinelist.ConvolvedDelays Type
Distribution of the convolved chain delay δ + Inc(sec), with Inc(sec) ~ inc and δ ~ δ. Used as the joint right-truncation distribution for sourced offspring at a real-time cut-off.
cdf(d, x; upper_δ = Inf) evaluates P(δ + Inc ≤ x ∧ δ ≤ upper_δ) by GaussLegendre quadrature over (mean(d.δ) − K·std(d.δ), min(upper_δ, mean(d.δ) + K·std(d.δ))). With the default upper_δ = Inf the integration domain is the full truncated support and the result is the ordinary chain-completion CDF. A finite upper_δ caps the inner δ integral and is used by _pipeline_probability for the controlled-outbreak counterfactual.
Accepts both x::Real (returns a scalar) and x::AbstractVector (returns a vector, evaluating every point in a single GaussLegendre solve). Prefer the vector form when evaluating at many points: cdf.(d, xs) would otherwise trigger one solve per element.
Fields
inc: incubation period distribution for the secondary case.δ: per-pair transmission timing distribution.
TransmissionLinelist._R_at_onsets Method
_R_at_onsets(T_d, edges, logR_d) -> AnyEvaluate the time-varying reproduction number at each per-case onset offset T_d[i] using piecewise-constant interpolation against edges and the per-draw log-R vector logR_d. Returns a Vector{Float64} of length length(T_d).
TransmissionLinelist._pipeline_probability Method
_pipeline_probability(
inc,
δd,
Δ_q::Real,
Δ_p::Real;
alg
) -> AnyProbability that an offspring of a source case is currently in incubation at Δ_p days after the source's onset, given the counterfactual that transmission from that source stops Δ_q days after its onset:
P(δ ≤ Δ_q ∧ δ + Inc > Δ_p)
= cdf(δd, Δ_q) − cdf(ConvolvedDelays(inc, δd), Δ_p; upper_δ = Δ_q)Routed through [Distributions.cdf(::ConvolvedDelays, x; upper_δ)] so the GaussLegendre quadrature lives in one place. The natural-chain limit (no intervention) falls out as Δ_q = +Inf, where the result reduces to 1 − cdf(ConvolvedDelays(inc, δd), Δ_p). The exclusion sentinel Δ_q = -Inf returns exactly 0.
Arguments
inc: incubation period distribution for the secondary case.δd: per-pair transmission-timing distributionδ.Δ_q: per-source intervention offset (days from source onset).Δ_p: per-source observation offset (days from source onset).
TransmissionLinelist.analyse Method
analyse(
;
data,
obs_time,
t0,
output,
figures,
samples,
chains,
seed,
progress,
plots
) -> Tuple{Any, NamedTuple{(:μ_inc, :σ_inc, :μ_δ, :σ_δ, :k, :σ_rw, :log_R_chain, :mean_gi_si, :sd_gi_si, :p_pre), <:Tuple{Any, Any, Any, Any, Any, Any, Any, Any, Any, Dict{Float64, Vector{Float64}}}}}Load the line list, fit the joint model, save the posterior summary to output/posterior.csv, and (unless plots = false) write all figures into figures/. Returns (chain, post).
Keyword Arguments
data: path to the line-list CSV, or a pre-loadedDataFrame.obs_time: optional real-time cut-offDate; omit for a retrospective fit.t0: optional explicit time origin (Date); defaults tominimum(onset_date) - 60 d.output: directory forposterior.csv.figures: directory for the figure PNGs.samples: NUTS samples per chain.chains: number of parallel chains.seed: random seed.progress: show a NUTS progress bar.plots: skip all figure generation whenfalse.
TransmissionLinelist.bin_labels Method
bin_labels() -> Vector{String}Return string labels for the weekly R(t) knots.
One entry per log_R element. Used to label plots and posterior summaries produced by summarise and plot_rt.
Returns
A Vector{String} of ISO-format knot dates.
TransmissionLinelist.build_data Method
build_data(
ll;
obs_time,
t0
) -> NamedTuple{(:t0, :onset_lo_day, :onset_hi_day, :exp_lo_day, :exp_hi_day, :source_idx, :Zobs, :N, :obs_time), <:Tuple{Any, Any, Any, Any, Any, Any, Any, Any, Nothing}}Build the model input from a line-list DataFrame.
Anchors all times in days relative to t0 (defaults to minimum(onset_date) - 60 d) and encodes interval-censored onset and exposure windows as [lo, hi) pairs. Resolves the source_case column to integer indices into the line list (0 denotes a zoonotic index case with no human source) and reads observed offspring counts from the Z column. When obs_time is supplied, encodes the per-case real-time cut-off in days relative to t0.
Arguments
ll: aDataFramereturned byload_linelist.
Keyword Arguments
obs_time: optional real-time observation cut-off. Either a singleDate(broadcast to all cases) or anAbstractVectorofDates with one entry per case.nothing(the default) collapses the model to its retrospective form.t0: optional explicit time origin. Defaults tominimum(onset_date) - 60 d.
Returns
A named tuple (t0, onset_lo_day, onset_hi_day, exp_lo_day, exp_hi_day, source_idx, Zobs, N, obs_time) ready to pass to joint_model.
Examples
ll = load_linelist()
d = build_data(ll)
d.NTransmissionLinelist.case_model Method
case_model(Z, edges, T_onset, p; rt, dispersion) -> AnyPer-case negative binomial likelihood for offspring counts Z. Draws log_R from the nested rt submodel and the NB dispersion k from the nested dispersion submodel; both are surfaced as deterministic chain variables via :=. In real-time mode, the per-case rate is thinned by the offspring-completeness p (pass empty p for retrospective mode, where R_eff = R).
Arguments
Z: vector of observed offspring counts per case.edges: vector of knot dates at whichlog_Ris defined.T_onset: vector of per-case onset times used to indexlog_R.p: vector of per-case offspring-completeness values, or empty for retrospective mode.
Keyword Arguments
rt: Turing submodel for the log R(t) random walk. Defaults torandom_walk_rt_model(length(edges)).dispersion: Turing submodel for the NB dispersionk. Defaults tonb_dispersion_model().
TransmissionLinelist.delays_only_model Method
delays_only_model(d; incubation, transmission) -> AnyDelays-only model: composes the incubation, transmission timing, and per-case latent submodels into a standalone diagnostic fit. Useful when the full joint fit collapses: a clean delays-only fit isolates any pathology to the R(t) / case_model half of the joint likelihood rather than the delay parameters.
Returns (; T_inf, T_onset, p, inc, δ). The p field carries the per-case offspring-completeness vector from latent_times_model (empty in retrospective mode); inc and δ are the realised incubation and transmission timing distributions so downstream submodels can re-use them.
Arguments
d: structured line-list data as returned bybuild_data, including per-case onset bounds, exposure bounds, source indices, and optionalobs_timefor real-time fits.
Keyword Arguments
incubation: Turing submodel for the incubation period. Defaults toincubation_model().transmission: Turing submodel for the transmission timingδ. Defaults totransmission_delta_model().
TransmissionLinelist.diagnostics Method
diagnostics(
chn
) -> NamedTuple{(:rhat, :ess, :ndiv), <:Tuple{Float64, Float64, Any}}Return convergence diagnostics for chn: (; rhat, ess, ndiv) — the maximum R̂ across scalar parameter entries, the minimum bulk ESS, and the divergent transition count.
Arguments
chn: FlexiChain returned bysample_fit.
TransmissionLinelist.diagnostics_table Method
diagnostics_table(chn) -> DataFrames.DataFrameSingle-row DataFrame summarising sampler diagnostics: maximum R̂, minimum bulk ESS, divergence count, and wall-clock sampling time in seconds. The runtime is read from FlexiChains' per-chain sampling_time metadata; under MCMCThreads chains run in parallel so the wall clock is approximated by the maximum over chains. Returns missing for the runtime if the chain carries no timing metadata.
Arguments
chn: a sampled chain fromjoint_model.
TransmissionLinelist.extract_simulated_Zobs Method
extract_simulated_Zobs(sim, N::Integer) -> AnyExtract simulated offspring counts Zobs from the NamedTuple returned by rand(rng, fix(joint_model(...), truth)). case_model declares Z[i] ~ safe_nb(...), so each sampled Z[i] appears under a VarName whose string form is "Z[i]". Matching by string form keeps the helper decoupled from AbstractPPL's internal VarName API.
Used by simulation-based recovery checks (see the sim-recovery walkthrough and test/test_joint_recovery.jl) to round-trip a fixed truth through the joint generative model and back into a refit.
Arguments
sim: NamedTuple of sampled values returned byrandon afix-edjoint_model.N: number of cases in the line list (d.N); used to allocate the result and to validate that everyZ[i]was sampled.
TransmissionLinelist.filter_by_exposure Method
filter_by_exposure(ll, obs_date::Dates.Date) -> AnyCounterfactual retrospective view: trim to cases known to have been infected by obs_date (sourced cases by their exposure upper bound, index cases by onset). Source attributions outside the retained set are dropped and Z is rebuilt. Relies on eventual exposure attribution and is not realisable in real time; use as a comparator for the corrected real-time fit only.
Arguments
ll: the full line-listDataFramewith columns includingonset_date,exposure_upper,patient_id, andsource_case.obs_date: the cut-offDate. Sourced cases are retained whenexposure_upper ≤ obs_date; index cases whenonset_date ≤ obs_date.
TransmissionLinelist.filter_realtime Method
filter_realtime(ll, obs_date::Dates.Date) -> AnyTrim the line-list to cases whose onset is on or before obs_date (those an analyst would know about at the cut-off). Source attributions pointing outside the retained set are dropped and Z is rebuilt to count only retained offspring.
Arguments
ll: the full line-listDataFramewith columns includingonset_date,patient_id, andsource_case.obs_date: the real-time observation cut-offDate. Cases with onset after this date are dropped.
TransmissionLinelist.incubation_model Method
incubation_model(
;
dist_constructor,
μ_prior,
σ_prior
) -> DynamicPPL.Model{typeof(incubation_model), (), (:dist_constructor, :μ_prior, :σ_prior), (), Tuple{}, Tuple{UnionAll, Distributions.Normal{Float64}, Distributions.Truncated{Distributions.Normal{Float64}, Distributions.Continuous, Float64, Float64, Nothing}}, DynamicPPL.DefaultContext, false}Model sampling the location μ_inc and scale σ_inc of the incubation period distribution. Returns (; dist = dist_constructor(μ, σ), μ, σ).
The dist_constructor keyword lets the family be swapped without editing the model. Defaults to LogNormal, in which case μ/σ are the log-mean and log-SD of the incubation period.
Keyword Arguments
dist_constructor: two-argument distribution constructor called asdist_constructor(μ, σ). Defaults toLogNormal.μ_prior: prior on the location parameter. Defaults toNormal(3.0, 0.5).σ_prior: prior on the scale parameter, constrained positive. Defaults totruncated(Normal(0.0, 0.5); lower = 0).
TransmissionLinelist.joint_model Method
joint_model(
d,
edges;
incubation,
transmission,
rt,
dispersion,
cases
) -> AnyJoint Bayesian model. Composes delays_only_model (incubation
- δ + per-case latents + real-time right-truncation) with
case_model (R(t) random walk + NB dispersion + per-case NB offspring likelihood). The case-level outputs log_R and k are surfaced via := from inside case_model.
Arguments
d: structured line-list data as returned bybuild_data, including per-case onset bounds, exposure bounds, source indices, offspring countsZobs, and optionalobs_timefor real-time fits.edges: vector of knot dates (as day numbers) at whichlog_Ris defined.
Keyword Arguments
incubation: Turing submodel for the incubation period passed through todelays_only_model. Defaults toincubation_model().transmission: Turing submodel for the transmission timingδpassed through todelays_only_model. Defaults totransmission_delta_model().rt: Turing submodel for the log R(t) random walk passed through tocase_model. Defaults torandom_walk_rt_model(length(edges)).dispersion: Turing submodel for the NB dispersionkpassed through tocase_model. Defaults tonb_dispersion_model().cases: observation-submodel constructor invoked ascases(d.Zobs, edges, delays.T_onset, delays.p; rt, dispersion). Defaults tocase_model. Exposed onmodel.defaults.casesso real-time predictors and the PPC dispatchpredict_future_offspringandreplicate_offspringon the obs submodel.
TransmissionLinelist.latent_times_model Method
latent_times_model(d, inc_dist, δ_dist) -> AnyPer-case latent infection and onset time submodel. Samples T_onset[i] and T_inf[i] for each case and adds the marginal incubation and transmission-timing log-densities for the resulting pairs. Sourced cases enforce the GI > 0 constraint by rejecting infeasible draws.
The real-time right-truncation contributions live in the nested truncation_model, invoked unconditionally with empty inputs in retrospective mode so the truncation reduces to a no-op.
Arguments
d: structured line-list data as returned bybuild_data, providing per-case onset bounds, exposure bounds, source indices, and optionalobs_timefor real-time fits.inc_dist: incubation period distribution from the incubation submodel.δ_dist: transmission-timing distribution from the transmission submodel.
TransmissionLinelist.load_linelist Function
load_linelist() -> DataFrames.DataFrame
load_linelist(path) -> DataFrames.DataFrameLoad and clean the Epuyén line list from a CSV file.
Reads the CSV at path, drops any duplicated rows with patient IDs ending in _alt, parses exposure_lower, exposure_upper, onset_date, onset_lower, and onset_upper as Dates (defaulting onset_lower and onset_upper to onset_date when absent), and sorts the rows by integer-valued patient_id. Used by build_data to produce the model input tuple.
Arguments
path: path to a line-list CSV. Defaults to the bundleddata/linelist.csvshipped with the package.
Returns
A DataFrame with one row per case and parsed date columns ready for build_data.
Examples
using TransmissionLinelist
ll = load_linelist()
first(ll, 3)TransmissionLinelist.log_R_at Method
log_R_at(
t::Real,
knots::AbstractVector{<:Real},
log_R
) -> AnyPiecewise-linear interpolation of log R(t) between weekly knots.
Linearly interpolates log_R against knots at the time t, clamping to the endpoint values outside the knot range.
Arguments
t: time (in days fromt0) at which to evaluate log R.knots: knot positions in days, as returned byprepare_rt_edges.log_R: vector of log R values at each knot.
Returns
The interpolated log R value at t.
TransmissionLinelist.main Method
main(args) -> Int64CLI entry point invoked by julia -m TransmissionLinelist. Parses command-line arguments and forwards them to analyse.
Arguments
args: vector of command-line argument strings.
TransmissionLinelist.nb_dispersion_model Function
nb_dispersion_model(
) -> DynamicPPL.Model{typeof(nb_dispersion_model), (:phi_prior,), (), (), Tuple{Distributions.Truncated{Distributions.Normal{Float64}, Distributions.Continuous, Float64, Float64, Nothing}}, Tuple{}, DynamicPPL.DefaultContext, false}
nb_dispersion_model(phi_prior) -> AnyModel for the negative binomial dispersion k using the Stan-default 1/√k reparameterisation. Samples phi_inv_sqrt from phi_prior and returns (; k = 1 / phi_inv_sqrt^2, phi_inv_sqrt).
Arguments
phi_prior: prior on1/√k, constrained positive. Defaults totruncated(Normal(0.0, 1.0); lower = 0).
TransmissionLinelist.per_source_predictive_summary Method
per_source_predictive_summary(pred; q) -> AnySummarise per-source future-onset samples into a DataFrame with columns source_idx, median, lo10, hi90, mean — one row per source case in the order they appear in the predictor's d argument.
Useful for diagnosing which sources drive a controlled-outbreak prediction.
Arguments
pred: the named tuple returned bypredict_controlled_outbreakorpredict_natural_chain_outbreak, carrying thefuture_samples_per_sourcematrix.
Keyword Arguments
q: three-tuple of lower, central, and upper quantiles used for thelo10,median, andhi90columns.
TransmissionLinelist.plot_data Method
plot_data(ll) -> FigureTwo-panel view of the raw line list: epicurve by ISO week of onset (left) and exposure windows against onset dates (right). Returns a Makie.Figure.
Arguments
ll: line-listDataFramewithonset_date,exposure_lower, andexposure_uppercolumns.
TransmissionLinelist.plot_delta_sense_check Method
plot_delta_sense_check(chn, d) -> FigureSense-check the per-pair posterior of δ against the fitted population Normal(μ_δ, σ_δ). For each sourced pair, take the posterior of δ_pair = T_inf[secondary] − T_onset[source] and reduce to its median; then plot the histogram of those per-pair medians with the population density overlaid. Returns a Makie.Figure.
Arguments
chn: a sampled chain fromjoint_model.d: the augmented data NamedTuple frombuild_data.
TransmissionLinelist.plot_inc_sense_check Method
plot_inc_sense_check(chn, data; n_density_draws) -> FigureSense-check the per-case posterior of the incubation period against the fitted population LogNormal(μ_inc, σ_inc). For each case, takes the posterior of inc_i = T_onset[i] − T_inf[i] and reduces to its median; plots the histogram of those per-case medians with the median PDF (and 95% pointwise ribbon) of the population LogNormal overlaid. Returns a Makie.Figure.
Arguments
chn: a sampled chain fromjoint_model.data: the augmented data NamedTuple frombuild_data.
Keyword Arguments
n_density_draws: target number of posterior draws to thin to when building the population density ribbon.
TransmissionLinelist.plot_marginal_overlay Method
plot_marginal_overlay(
df;
size_kw,
row_col,
col_col,
layout_col,
bins
) -> AlgebraOfGraphics.FigureGridFaceted overlay of marginal posterior histograms across fits. Designed for side-by-side comparison of multiple chains: one row per value of row_col, one column per value of col_col, with one coloured histogram per :fit level inside each panel.
df must be long-form with at least the columns :value, :fit, plus the row_col and col_col columns. The histogram is normalised to a PDF so overlaid fits with different sample sizes share a y-axis.
Used by the real-time monitoring walkthrough (rows = :obs_date, columns = :param) and the prior sensitivity walkthrough (rows = :scenario, columns = :param).
Arguments
df: long-formDataFrameof posterior draws.
Keyword Arguments
size_kw: figure size tuple passed to AoG'sfigurekeyword.row_col: name of the column used for the facet rows. Defaults to:obs_date.col_col: name of the column used for the facet columns. Defaults to:param.bins: number of histogram bins per panel.
TransmissionLinelist.plot_pair Method
plot_pair(chn; thin) -> FigureCorner plot of the population scalars μ_inc, σ_inc, μ_δ, σ_δ, k via PairPlots.jl. Returns a Makie Figure.
Arguments
chn: a sampled chain fromjoint_model.
Keyword Arguments
thin: stride applied to the posterior draws before plotting.
TransmissionLinelist.plot_predictive_distributions Method
plot_predictive_distributions(chn; rng) -> FigureTwo-by-two panel of the implied population distributions under the posterior for incubation period, transmission timing δ, generation interval, and serial interval. Each panel shows draws from p(y_new | data) = ∫ p(y_new | θ) p(θ | data) dθ, i.e. what a new case or transmission pair would look like under the fitted parameters.
This is not a posterior-predictive check against observed data; for that, see plot_z_ppc, plot_delta_sense_check, and plot_inc_sense_check.
Inc and δ panels overlay the parametric density (median PDF with a 95% pointwise ribbon across draws) and a histogram of one predictive sample per draw. GI and SI show the predictive-sample histogram only. Returns a Makie.Figure.
Arguments
chn: a sampled chain fromjoint_model.
Keyword Arguments
rng: RNG used to draw one predictive sample per posterior draw.
TransmissionLinelist.plot_prior_predictives Method
plot_prior_predictives(; n, rng) -> FigurePrior-predictive panel: histograms of Inc, δ, and GI/SI drawn from the package's independent priors on μ_inc, σ_inc, μ_δ, σ_δ. Returns a Makie.Figure.
Three histograms faceted by quantity is the kind of plot AoG was built for: one long-form data frame, mapping(:value, layout = :panel), visual(Hist). Each panel still has its own viewing window so long tails don't squash the bars; rather than per-facet axis limits, the input is pre-clipped to the window for each panel.
Keyword Arguments
n: number of prior draws per quantity.rng: RNG used to draw the prior samples.
TransmissionLinelist.plot_rt Method
plot_rt(chn; n_draws_plot, ymax, t0, edges) -> FigureSpaghetti plot of R(t) over the weekly knots. Each thinned posterior draw is a piecewise-linear trajectory through (knot_date[b], exp(log_R[b])). Returns a Makie.Figure.
Per-draw spaghetti is built as a long-form DataFrame and drawn via AlgebraOfGraphics with group = :draw, which is the idiomatic way to spell "one line per draw" once the data is tidy.
Knot dates default to BIN_EDGES (data.jl). Pass t0 (with optional edges) to recover the calendar dates from a real-time fit whose knot grid was truncated at the observation cut-off.
Arguments
chn: a sampled chain fromjoint_model.
Keyword Arguments
n_draws_plot: target number of posterior draws to thin to before plotting.ymax: upper limit of the R(t) y-axis.t0: time origin (Date) for the fit. When supplied, the x-axis is mapped to calendar datest0 + Day(edges[b]). Defaults to the package retrospective gridBIN_EDGES.edges: knot positions in days fromt0, as returned byprepare_rt_edges. Defaults toprepare_rt_edges(t0)whent0is supplied.
TransmissionLinelist.plot_z_dumbbell Method
plot_z_dumbbell(chn, d; n_draws_plot = 60, jitter = 0.35,
rng = Random.MersenneTwister(20260518))Offspring count Z plotted against time, with one horizontal dumbbell per case running from the latent infection time T_inf to the latent onset time T_onset. Each case is drawn at its Zobs value (with small vertical jitter to break ties); thin segments overlay n_draws_plot posterior pairs, and two dots mark the posterior medians of T_inf (filled) and T_onset (hollow). Index and sourced cases are coloured separately. Returns a Makie Figure.
Arguments
chn: FlexiChain returned bysample_fit.d: model data tuple frombuild_data.
Keyword Arguments
n_draws_plot: posterior draws drawn as thin segments per case.jitter: half-range of vertical jitter on theZaxis.rng: RNG used for jitter and draw subsampling.
TransmissionLinelist.plot_z_ppc Method
plot_z_ppc(model, chn, d; rng, edges) -> FigurePosterior predictive check for offspring counts Z. Replicates Z from the joint posterior and overlays the simulated counts against the observed counts per case.
Arguments
model: thejoint_modelinstance that producedchn; itsdefaults.casesfield dispatches the per-case posterior-predictive draw.chn: a sampled chain fromjoint_model.d: the augmented data NamedTuple frombuild_data.
Keyword Arguments
rng: RNG used for the posterior draws.edges: weekly knot edges; defaults tonothing, in which case the knots are taken fromprepare_rt_edges(d.t0)[1:length(log_R)]inside_z_ppc_replicate.
TransmissionLinelist.predict_controlled_outbreak Method
predict_controlled_outbreak(
model,
chn,
post,
d;
obs_time,
intervention_time,
rng
)Strict controlled-outbreak counterfactual: predict future onsets assuming all transmission stops at intervention_time (default obs_time). Only people already infected by intervention_time (transmission event before the cut-off, chain not yet symptomatic) contribute. For each posterior draw and observed source i, the contribution is Poisson(λ_i · pipeline_i) where pipeline_i = P(δ ≤ Δ_q[i] ∧ δ + Inc > Δ_p[i]) is the joint probability that transmission from source i happened by Δ_q[i] = intervention_time_i − T_onset[i] and the offspring is still in incubation at the observation horizon Δ_p[i] = obs_time − T_onset[i], p_i = cdf(ConvolvedDelays(inc, δ), Δ_p[i]) is the probability the full chain has completed by obs_time, and λ_i | Z_obs[i], k, R_i, p_i ~ Gamma(k + Z_obs[i], R_i / (k + R_i · p_i)). pipeline_i is evaluated via _pipeline_probability, which truncates δ at Δ_q[i] before convolving with Inc so the formula is correct whether the intervention precedes, coincides with, or follows the observation cut-off. Incubation and transmission timing distributions per draw are recovered from the fitted model's submodels via DynamicPPL.fix.
The prediction is a pure function of the fit (the fitted model, its chain, posterior summary, and the same d the model was fit on). realised_future_count returns the corresponding realised count from the full line list as a separate evaluation step.
Returns a named tuple with fields future_samples (a Vector{Int} of length n_draws giving the total future count per draw), future_samples_per_source (an n_draws × N Matrix{Int} whose row sums equal future_samples), and n_obs. Use per_source_predictive_summary to turn the per-source matrix into a DataFrame for downstream diagnostics.
Arguments
model: theDynamicPPL.Modelthat producedchn, carrying the incubation, transmission, and observation submodels undermodel.defaults.chn: chain from a real-time joint fit.post: posterior summary returned bysummarise(chn).d: structured line-list data the model was fit on (returned bybuild_data).
Keyword Arguments
obs_time: cut-offDate.intervention_time: when transmission stops. Three forms are accepted:nothing(default): intervention coincides withobs_timefor every source, equivalent to passingobs_timeas a scalarDate.A scalar
Date: applies uniformly to every source.Δ_q[i] = intervention_time − T_onset[i]. Sources whose onset is afterintervention_timeget a negativeΔ_q[i], soq_i = cdf(δ, Δ_q[i])evaluates in the left tail of the transmission-timing distribution.A
Vector{Date}of lengthN(one entry per observed source): encodes per-source intervention dates, useful when isolation timing differs across cases (e.g. a per-case isolation date derived fromll_rt.onset_date). ElementisetsΔ_q[i] = intervention_time[i] − T_onset[i].
rng: RNG used for posterior-predictive draws.
TransmissionLinelist.predict_controlled_outbreak Method
predict_controlled_outbreak(
fit::NamedTuple;
corrected,
obs_time,
intervention_time,
rng
)Convenience wrapper that unpacks a fit-like NamedTuple (as returned by the real-time joint-fit map: fields m_rt, chn_rt, post_rt, d_rt and, for the counterfactual retro, m_truth, chn_truth, post_truth, d_truth). Pass corrected = true (default) for the real-time fit; pass corrected = false for the counterfactual retro fit.
TransmissionLinelist.predict_future_offspring Method
predict_future_offspring(
_::typeof(case_model),
rng,
k,
Z_obs,
R,
p_i,
prob
) -> AnyPredict the number of future offspring from a source case under the case_model likelihood. The Gamma posterior on the source's latent rate λ conditional on the Z_obs already-attributed offspring (with completion probability p_i) is λ | Z_obs ~ Gamma(k + Z_obs, R / (k + R · p_i)), and the future count is then Poisson(λ · prob). Real-time predictors dispatch on the joint model's observation-submodel constructor (model.defaults.cases) so alternative obs models can supply their own methods without editing the predictor.
This is not the posterior-predictive replication used by plot_z_ppc; for that, see replicate_offspring, which draws a fresh Z_rep from the likelihood at the chain's (k, R) draw without conditioning on Z_obs.
Arguments
cases_sub: the observation-submodel constructor stored onjoint_model's defaults; heretypeof(case_model).rng: RNG used for the Gamma and Poisson draws.k: per-draw NB dispersionk.Z_obs: observed offspring count for this source.R: per-source rateR_i = exp(log_R_at(T_onset_i, edges, log_R)).p_i: offspring-completeness probability for this source.prob: per-source future-onset thinning probability (e.g.q_i − p_ifor the controlled counterfactual).
TransmissionLinelist.predict_natural_chain_outbreak Method
predict_natural_chain_outbreak(
model,
chn,
post,
d;
obs_time,
rng
)Natural-chain counterfactual: predict future onsets assuming currently-observed sources keep transmitting at their existing rate but no second-generation chains form from those new offspring. Each observed source contributes Poisson(λ_i · (1 − p_i)) future onsets, covering both offspring already infected by obs_time (chain in incubation) and offspring still to be infected by the source. Same Gamma posterior on λ_i as predict_controlled_outbreak; this is the Δ_q = +Inf limit of that predictor, where _pipeline_probability reduces to 1 − p_i. Incubation and transmission timing distributions per draw are recovered from the fitted model's submodels via DynamicPPL.fix.
Returns the same named tuple shape as predict_controlled_outbreak: future_samples, future_samples_per_source, and n_obs. per_source_predictive_summary turns the per-source matrix into a DataFrame for downstream diagnostics.
Arguments
model: theDynamicPPL.Modelthat producedchn, carrying the incubation, transmission, and observation submodels undermodel.defaults.chn: chain from a real-time joint fit.post: posterior summary returned bysummarise(chn).d: structured line-list data the model was fit on (returned bybuild_data).
Keyword Arguments
obs_time: cut-offDate.rng: RNG used for posterior-predictive draws.
TransmissionLinelist.predict_natural_chain_outbreak Method
predict_natural_chain_outbreak(
fit::NamedTuple;
corrected,
obs_time,
rng
)Convenience wrapper that unpacks a fit-like NamedTuple; see predict_controlled_outbreak. Pass corrected = true (default) for the real-time fit; corrected = false for the counterfactual retro fit.
TransmissionLinelist.prepare_rt_edges Method
prepare_rt_edges(t0; obs_time) -> Vector{Float64}Return the weekly R(t) knot positions expressed as days relative to t0.
The knots span the outbreak in weekly steps; combined with log_R_at this defines the piecewise-linear log R(t) trajectory used by joint_model.
When obs_time is supplied, knots strictly after the cut-off are dropped and the final knot is set to the cut-off itself, so the last segment of the piecewise-linear log R(t) trajectory ends exactly at obs_time. This is the form needed for a real-time fit.
Arguments
t0: the model's time origin (thet0field of the tuple returned bybuild_data).
Keyword Arguments
obs_time: optional real-time observation cut-offDate.nothing(the default) returns the full weekly knot set for a retrospective fit.
Returns
A Vector{Float64} of knot positions in days. Length equals length(BIN_EDGES) for obs_time === nothing, and at most that for a real-time fit.
TransmissionLinelist.random_walk_rt_model Method
random_walk_rt_model(
n_knots::Integer;
init_prior,
sigma_prior
) -> AnyNon-centred weekly random walk on log R(t) at n_knots knots. Returns the length-n_knots log_R vector evaluated at the knot dates; log_R_at linearly interpolates between knots.
Arguments
n_knots: number of weekly knot points at whichlog_Ris evaluated.
Keyword Arguments
init_prior: prior on the initial log R(t) valuelog_R_init. Defaults toNormal(log(1.5), 1.0).sigma_prior: prior on the random walk step SDσ_rw, constrained positive. Defaults totruncated(Normal(0.0, 0.2); lower = 0), reflecting our prior experience estimating transmission intensity across a range of outbreaks. At weekly knot spacing this puts the typical weekly innovation SD around 5% per day, with a 95th percentile near 15% per day — wide enough to accommodate outbreak-scale R(t) swings while ruling out biologically implausible per-week step sizes.
TransmissionLinelist.realised_future_count Method
realised_future_count(ll, obs_time::Dates.Date) -> AnyCount line-list cases with onset strictly after obs_time. The realised analogue of the future_samples field returned by predict_controlled_outbreak and predict_natural_chain_outbreak; kept as a separate function so the predictors stay pure functions of the fit.
Arguments
ll: full line-listDataFramewith anonset_datecolumn.obs_time: real-time cut-offDate. Cases whose onset is strictly after this date are counted.
TransmissionLinelist.regression_summary Method
regression_summary(chn) -> DataFrames.DataFrameLong-form DataFrame snapshot of the headline posterior, sampler diagnostics, and per-knot R(t) for use by the docs CI regression check: each PR build dumps one of these per walkthrough and a follow-up CI step diffs the result against a checked-in baseline (or the latest main build) to flag drift in the headline numbers.
Columns:
section: one of"headline","diagnostics","rt".quantity: row label — matchessummary_table'squantityfor headline rows,"R_knot_<b>"for rt rows,"rhat_max"/"ess_min"/"divergences"for diagnostics.median,lower_95,upper_95: posterior median and 95% CrI. Diagnostic rows store the scalar inmedianwithNaNbounds.
Arguments
chn: a sampled chain fromjoint_model.
TransmissionLinelist.replicate_offspring Method
replicate_offspring(
_::typeof(case_model),
rng,
k,
R,
p_i
) -> AnyDraw a fresh offspring count Z_rep from the case_model likelihood safe_nb(k, R · p_i) for a single source at a posterior draw of (k, R, p_i). Used by plot_z_ppc and z_ppc_summary for posterior-predictive checking; p_i = 1 recovers the retrospective NB(k, R) likelihood, while real-time mode applies the offspring-completeness thinning R · p_i to match the fitted likelihood.
Unlike predict_future_offspring, this draw does not condition on the source's observed count — Z_obs already informs the posterior on (k, R) through the chain, and a PPC replicates from p(Z | θ) at posterior draws of θ, not from p(Z | θ, Z_obs).
Arguments
cases_sub: the observation-submodel constructor stored onjoint_model's defaults; heretypeof(case_model).rng: RNG used for the NB draw.k: per-draw NB dispersionk.R: per-source rateR_i = exp(log_R_at(T_onset_i, edges, log_R)).p_i: offspring-completeness probability for this source;1.0in retrospective mode.
TransmissionLinelist.rt_band Method
rt_band(post; q, t0, edges) -> DataFrames.DataFrameQuantile band for R(t) across knots from one posterior. Returns a DataFrame with one row per knot and columns bin, lo, med, hi taken from the three quantiles q of exp.(post.log_R_chain[b]). When t0 is supplied, an additional :date column maps each knot to its calendar date via t0 + Day(edges[b]) (using prepare_rt_edges(t0) when edges is not given).
Arguments
post: posterior summary named tuple fromsummarise.
Keyword Arguments
q: three-tuple of lower, central, and upper quantiles.t0: time origin (Date) for the fit. When supplied, the returned frame includes a:datecolumn for plotting on a calendar-date axis.edges: knot positions in days fromt0, as returned byprepare_rt_edges. Defaults toprepare_rt_edges(t0).
TransmissionLinelist.safe_nb Method
safe_nb(k, R)NegativeBinomial(k, p) with p = max(k/(k+R), eps(typeof(k))). The clamp stabilises the gradient when an extreme NUTS proposal makes R so large that p underflows to zero, which would otherwise leave logpdf at -Inf and break AD.
TransmissionLinelist.sample_fit Method
sample_fit(
model;
samples,
chains,
target_accept,
seed,
progress,
adtype
) -> AnyRun NUTS on model and return the sampled chain.
Uses Mooncake as the default AD backend and InitFromPrior() chain initialisation. Override adtype to swap backends (e.g. Enzyme).
Arguments
model: a Turing model, e.g. fromjoint_model.
Keyword Arguments
samples: NUTS samples per chain.chains: number of parallel chains.target_accept: NUTS acceptance target.seed: optional random seed.progress: show a NUTS progress bar.adtype: AD backend for NUTS. Defaults toAutoMooncake(; config = Mooncake.Config()).
TransmissionLinelist.save_posterior Method
save_posterior(post, path) -> AnyWrite the posterior summary post (as returned by summarise) to a CSV at path, one column per scalar parameter plus one column per log_R knot.
Arguments
post: posterior named tuple fromsummarise.path: output CSV path.
TransmissionLinelist.save_regression_summary Method
save_regression_summary(path, chn) -> AnyWrite regression_summary(chn) to a CSV at path. Creates the parent directory if needed.
Arguments
path: output CSV path.chn: a sampled chain fromjoint_model.
TransmissionLinelist.summarise Method
summarise(
chn
) -> NamedTuple{(:μ_inc, :σ_inc, :μ_δ, :σ_δ, :k, :σ_rw, :log_R_chain, :mean_gi_si, :sd_gi_si, :p_pre), <:Tuple{Any, Any, Any, Any, Any, Any, Any, Any, Any, Dict{Float64, Vector{Float64}}}}Build the named-tuple of posterior draws consumed by save_posterior. Call summary_table directly to print the headline summary.
Arguments
chn: FlexiChain returned bysample_fit.
TransmissionLinelist.summarise_predictive Method
summarise_predictive(
samples::AbstractVector{<:Real};
q
) -> NamedTuple{(:med, :lo, :hi, :mean), <:NTuple{4, Any}}Single-row summary of predictive samples. Returns a NamedTuple (med, lo, hi, mean) with med, lo, hi taken from the quantiles q and rounded to Int, and mean the raw sample mean.
Arguments
samples: vector of predictive draws (typically integer counts).
Keyword Arguments
q: three-tuple of lower, central, and upper quantiles.
TransmissionLinelist.summary_table Method
summary_table(chn) -> DataFrames.DataFramePosterior summary DataFrame for the headline quantities: incubation mean, 95th and 99th percentiles, transmission timing μ_δ / σ_δ, GI / SI mean and SD, and Negative-Binomial dispersion k. Columns: quantity, median, lower_95, upper_95.
Arguments
chn: a sampled chain fromjoint_model.
TransmissionLinelist.transmission_delta_model Method
transmission_delta_model(
;
dist_constructor,
μ_prior,
σ_prior
) -> DynamicPPL.Model{typeof(transmission_delta_model), (), (:dist_constructor, :μ_prior, :σ_prior), (), Tuple{}, Tuple{UnionAll, Distributions.Normal{Float64}, Distributions.Truncated{Distributions.Normal{Float64}, Distributions.Continuous, Float64, Float64, Nothing}}, DynamicPPL.DefaultContext, false}Model for the population mean μ_δ and SD σ_δ of the per-pair transmission timing. Returns (; dist = dist_constructor(μ, σ), μ, σ).
Keyword Arguments
dist_constructor: two-argument distribution constructor called asdist_constructor(μ, σ). Defaults toNormal.μ_prior: prior on the population meanμ_δ. Defaults toNormal(0.0, 5.0).σ_prior: prior on the population SDσ_δ, constrained positive. Defaults totruncated(Normal(0.0, 1.0); lower = 0).
TransmissionLinelist.truncation_model Method
truncation_model(
T_inf,
T_onset,
source_idx,
obs_time,
inc_dist,
delta_dist
) -> AnyReal-time right-truncation submodel. Adds two contributions to the log-likelihood:
Per-case Inc right-truncation
-logcdf(inc_dist, obs_time − T_inf[i])for index cases only. Sourced cases already get their offspring- chain right-truncation through the convolved-delay denominator in contribution (2), so applying-logcdfto them would double-count.Per-pair offspring-completeness denominator
-log(p[src])for each sourced case, withp = cdf(ConvolvedDelays(inc_dist, delta_dist), obs_time .- T_onset).
Both contributions are vectorised into a single @addlogprob! call each rather than per-case loops. Returns (; p), where p is the offspring-chain completion cdf cdf(ConvolvedDelays(inc_dist, delta_dist), obs_time .- T_onset). Called with empty T_inf / T_onset / source_idx in retrospective mode so both @addlogprob! calls reduce to 0 and p comes back empty.
Arguments
T_inf: per-case infection times.T_onset: per-case onset times.source_idx: per-case source indices (0 for index cases).obs_time: per-case real-time cut-off as a vector of day numbers, same length asT_infandT_onset.inc_dist: incubation period distribution.delta_dist: per-pair transmission timing distribution.
TransmissionLinelist.vector_chain Method
vector_chain(chn, name::Symbol) -> AnyReturn a vector of pooled posterior samples for each entry of a vector-valued parameter (e.g. :T_inf, :log_R).
Arguments
chn: FlexiChain returned bysample_fit.name: name of a vector-valued parameter inchn.
TransmissionLinelist.z_ppc_summary Method
z_ppc_summary(model, chn, d; rng, edges) -> AnyCompanion to plot_z_ppc returning a DataFrame of numeric posterior-predictive summaries for three discrete test statistics — sum(Z), max(Z), and count(Z = 0). Replicates Z_rep jointly in (T_inf, log_R, k) to match plot_z_ppc. Columns: statistic, observed, rep_median, rep_lower_95, rep_upper_95, p_ppp, where p_ppp = 2 · min(P(T_rep ≥ T_obs), P(T_rep ≤ T_obs)) is the two-sided Bayesian posterior-predictive p-value.
Arguments
model: thejoint_modelinstance that producedchn; itsdefaults.casesfield dispatches the per-case posterior-predictive draw.chn: a sampled chain fromjoint_model.d: the augmented data NamedTuple frombuild_data.
Keyword Arguments
rng: RNG used to replicate the offspring counts.edges: weekly knot edges; defaults tonothing, in which case the knots are taken fromprepare_rt_edges(d.t0)[1:length(log_R)]inside_z_ppc_replicate.