Skip to content

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.

source
TransmissionLinelist._R_at_onsets Method
julia
_R_at_onsets(T_d, edges, logR_d) -> Any

Evaluate 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).

source
TransmissionLinelist._pipeline_probability Method
julia
_pipeline_probability(
    inc,
    δd,
    Δ_q::Real,
    Δ_p::Real;
    alg
) -> Any

Probability 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:

julia
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).

source
TransmissionLinelist.analyse Method
julia
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-loaded DataFrame.

  • obs_time: optional real-time cut-off Date; omit for a retrospective fit.

  • t0: optional explicit time origin (Date); defaults to minimum(onset_date) - 60 d.

  • output: directory for posterior.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 when false.

source
TransmissionLinelist.bin_labels Method
julia
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.

source
TransmissionLinelist.build_data Method
julia
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

Keyword Arguments

  • obs_time: optional real-time observation cut-off. Either a single Date (broadcast to all cases) or an AbstractVector of Dates with one entry per case. nothing (the default) collapses the model to its retrospective form.

  • t0: optional explicit time origin. Defaults to minimum(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

julia
ll = load_linelist()
d  = build_data(ll)
d.N
source
TransmissionLinelist.case_model Method
julia
case_model(Z, edges, T_onset, p; rt, dispersion) -> Any

Per-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 which log_R is defined.

  • T_onset: vector of per-case onset times used to index log_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 to random_walk_rt_model(length(edges)).

  • dispersion: Turing submodel for the NB dispersion k. Defaults to nb_dispersion_model().

source
TransmissionLinelist.delays_only_model Method
julia
delays_only_model(d; incubation, transmission) -> Any

Delays-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 by build_data, including per-case onset bounds, exposure bounds, source indices, and optional obs_time for real-time fits.

Keyword Arguments

  • incubation: Turing submodel for the incubation period. Defaults to incubation_model().

  • transmission: Turing submodel for the transmission timing δ. Defaults to transmission_delta_model().

source
TransmissionLinelist.diagnostics Method
julia
diagnostics(
    chn
) -> NamedTuple{(:rhat, :ess, :ndiv), <:Tuple{Float64, Float64, Any}}

Return convergence diagnostics for chn: (; rhat, ess, ndiv) — the maximum across scalar parameter entries, the minimum bulk ESS, and the divergent transition count.

Arguments

source
TransmissionLinelist.diagnostics_table Method
julia
diagnostics_table(chn) -> DataFrames.DataFrame

Single-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

source
TransmissionLinelist.extract_simulated_Zobs Method
julia
extract_simulated_Zobs(sim, N::Integer) -> Any

Extract 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 by rand on a fix-ed joint_model.

  • N: number of cases in the line list (d.N); used to allocate the result and to validate that every Z[i] was sampled.

source
TransmissionLinelist.filter_by_exposure Method
julia
filter_by_exposure(ll, obs_date::Dates.Date) -> Any

Counterfactual 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-list DataFrame with columns including onset_date, exposure_upper, patient_id, and source_case.

  • obs_date: the cut-off Date. Sourced cases are retained when exposure_upper ≤ obs_date; index cases when onset_date ≤ obs_date.

source
TransmissionLinelist.filter_realtime Method
julia
filter_realtime(ll, obs_date::Dates.Date) -> Any

Trim 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-list DataFrame with columns including onset_date, patient_id, and source_case.

  • obs_date: the real-time observation cut-off Date. Cases with onset after this date are dropped.

source
TransmissionLinelist.incubation_model Method
julia
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 as dist_constructor(μ, σ). Defaults to LogNormal.

  • μ_prior: prior on the location parameter. Defaults to Normal(3.0, 0.5).

  • σ_prior: prior on the scale parameter, constrained positive. Defaults to truncated(Normal(0.0, 0.5); lower = 0).

source
TransmissionLinelist.joint_model Method
julia
joint_model(
    d,
    edges;
    incubation,
    transmission,
    rt,
    dispersion,
    cases
) -> Any

Joint 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 by build_data, including per-case onset bounds, exposure bounds, source indices, offspring counts Zobs, and optional obs_time for real-time fits.

  • edges: vector of knot dates (as day numbers) at which log_R is defined.

Keyword Arguments

  • incubation: Turing submodel for the incubation period passed through to delays_only_model. Defaults to incubation_model().

  • transmission: Turing submodel for the transmission timing δ passed through to delays_only_model. Defaults to transmission_delta_model().

  • rt: Turing submodel for the log R(t) random walk passed through to case_model. Defaults to random_walk_rt_model(length(edges)).

  • dispersion: Turing submodel for the NB dispersion k passed through to case_model. Defaults to nb_dispersion_model().

  • cases: observation-submodel constructor invoked as cases(d.Zobs, edges, delays.T_onset, delays.p; rt, dispersion). Defaults to case_model. Exposed on model.defaults.cases so real-time predictors and the PPC dispatch predict_future_offspring and replicate_offspring on the obs submodel.

source
TransmissionLinelist.latent_times_model Method
julia
latent_times_model(d, inc_dist, δ_dist) -> Any

Per-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 by build_data, providing per-case onset bounds, exposure bounds, source indices, and optional obs_time for real-time fits.

  • inc_dist: incubation period distribution from the incubation submodel.

  • δ_dist: transmission-timing distribution from the transmission submodel.

source
TransmissionLinelist.load_linelist Function
julia
load_linelist() -> DataFrames.DataFrame
load_linelist(path) -> DataFrames.DataFrame

Load 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 bundled data/linelist.csv shipped with the package.

Returns

A DataFrame with one row per case and parsed date columns ready for build_data.

Examples

julia
using TransmissionLinelist
ll = load_linelist()
first(ll, 3)
source
TransmissionLinelist.log_R_at Method
julia
log_R_at(
    t::Real,
    knots::AbstractVector{<:Real},
    log_R
) -> Any

Piecewise-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 from t0) at which to evaluate log R.

  • knots: knot positions in days, as returned by prepare_rt_edges.

  • log_R: vector of log R values at each knot.

Returns

The interpolated log R value at t.

source
TransmissionLinelist.main Method
julia
main(args) -> Int64

CLI entry point invoked by julia -m TransmissionLinelist. Parses command-line arguments and forwards them to analyse.

Arguments

  • args: vector of command-line argument strings.
source
TransmissionLinelist.nb_dispersion_model Function
julia
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) -> Any

Model 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 on 1/√k, constrained positive. Defaults to truncated(Normal(0.0, 1.0); lower = 0).
source
TransmissionLinelist.per_source_predictive_summary Method
julia
per_source_predictive_summary(pred; q) -> Any

Summarise 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

Keyword Arguments

  • q: three-tuple of lower, central, and upper quantiles used for the lo10, median, and hi90 columns.
source
TransmissionLinelist.plot_data Method
julia
plot_data(ll) -> Figure

Two-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-list DataFrame with onset_date, exposure_lower, and exposure_upper columns.
source
TransmissionLinelist.plot_delta_sense_check Method
julia
plot_delta_sense_check(chn, d) -> Figure

Sense-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

source
TransmissionLinelist.plot_inc_sense_check Method
julia
plot_inc_sense_check(chn, data; n_density_draws) -> Figure

Sense-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

Keyword Arguments

  • n_density_draws: target number of posterior draws to thin to when building the population density ribbon.
source
TransmissionLinelist.plot_marginal_overlay Method
julia
plot_marginal_overlay(
    df;
    size_kw,
    row_col,
    col_col,
    layout_col,
    bins
) -> AlgebraOfGraphics.FigureGrid

Faceted 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-form DataFrame of posterior draws.

Keyword Arguments

  • size_kw: figure size tuple passed to AoG's figure keyword.

  • 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.

source
TransmissionLinelist.plot_pair Method
julia
plot_pair(chn; thin) -> Figure

Corner plot of the population scalars μ_inc, σ_inc, μ_δ, σ_δ, k via PairPlots.jl. Returns a Makie Figure.

Arguments

Keyword Arguments

  • thin: stride applied to the posterior draws before plotting.
source
TransmissionLinelist.plot_predictive_distributions Method
julia
plot_predictive_distributions(chn; rng) -> Figure

Two-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

Keyword Arguments

  • rng: RNG used to draw one predictive sample per posterior draw.
source
TransmissionLinelist.plot_prior_predictives Method
julia
plot_prior_predictives(; n, rng) -> Figure

Prior-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.

source
TransmissionLinelist.plot_rt Method
julia
plot_rt(chn; n_draws_plot, ymax, t0, edges) -> Figure

Spaghetti 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

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 dates t0 + Day(edges[b]). Defaults to the package retrospective grid BIN_EDGES.

  • edges: knot positions in days from t0, as returned by prepare_rt_edges. Defaults to prepare_rt_edges(t0) when t0 is supplied.

source
TransmissionLinelist.plot_z_dumbbell Method
julia
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

Keyword Arguments

  • n_draws_plot: posterior draws drawn as thin segments per case.

  • jitter: half-range of vertical jitter on the Z axis.

  • rng: RNG used for jitter and draw subsampling.

source
TransmissionLinelist.plot_z_ppc Method
julia
plot_z_ppc(model, chn, d; rng, edges) -> Figure

Posterior 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: the joint_model instance that produced chn; its defaults.cases field dispatches the per-case posterior-predictive draw.

  • chn: a sampled chain from joint_model.

  • d: the augmented data NamedTuple from build_data.

Keyword Arguments

  • rng: RNG used for the posterior draws.

  • edges: weekly knot edges; defaults to nothing, in which case the knots are taken from prepare_rt_edges(d.t0)[1:length(log_R)] inside _z_ppc_replicate.

source
TransmissionLinelist.predict_controlled_outbreak Method
julia
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: the DynamicPPL.Model that produced chn, carrying the incubation, transmission, and observation submodels under model.defaults.

  • chn: chain from a real-time joint fit.

  • post: posterior summary returned by summarise(chn).

  • d: structured line-list data the model was fit on (returned by build_data).

Keyword Arguments

  • obs_time: cut-off Date.

  • intervention_time: when transmission stops. Three forms are accepted:

    • nothing (default): intervention coincides with obs_time for every source, equivalent to passing obs_time as a scalar Date.

    • A scalar Date: applies uniformly to every source. Δ_q[i] = intervention_time − T_onset[i]. Sources whose onset is after intervention_time get a negative Δ_q[i], so q_i = cdf(δ, Δ_q[i]) evaluates in the left tail of the transmission-timing distribution.

    • A Vector{Date} of length N (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 from ll_rt.onset_date). Element i sets Δ_q[i] = intervention_time[i] − T_onset[i].

  • rng: RNG used for posterior-predictive draws.

source
TransmissionLinelist.predict_controlled_outbreak Method
julia
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.

source
TransmissionLinelist.predict_future_offspring Method
julia
predict_future_offspring(
    _::typeof(case_model),
    rng,
    k,
    Z_obs,
    R,
    p_i,
    prob
) -> Any

Predict 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 on joint_model's defaults; here typeof(case_model).

  • rng: RNG used for the Gamma and Poisson draws.

  • k: per-draw NB dispersion k.

  • Z_obs: observed offspring count for this source.

  • R: per-source rate R_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_i for the controlled counterfactual).

source
TransmissionLinelist.predict_natural_chain_outbreak Method
julia
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: the DynamicPPL.Model that produced chn, carrying the incubation, transmission, and observation submodels under model.defaults.

  • chn: chain from a real-time joint fit.

  • post: posterior summary returned by summarise(chn).

  • d: structured line-list data the model was fit on (returned by build_data).

Keyword Arguments

  • obs_time: cut-off Date.

  • rng: RNG used for posterior-predictive draws.

source
TransmissionLinelist.predict_natural_chain_outbreak Method
julia
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.

source
TransmissionLinelist.prepare_rt_edges Method
julia
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 (the t0 field of the tuple returned by build_data).

Keyword Arguments

  • obs_time: optional real-time observation cut-off Date. 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.

source
TransmissionLinelist.random_walk_rt_model Method
julia
random_walk_rt_model(
    n_knots::Integer;
    init_prior,
    sigma_prior
) -> Any

Non-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 which log_R is evaluated.

Keyword Arguments

  • init_prior: prior on the initial log R(t) value log_R_init. Defaults to Normal(log(1.5), 1.0).

  • sigma_prior: prior on the random walk step SD σ_rw, constrained positive. Defaults to truncated(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.

source
TransmissionLinelist.realised_future_count Method
julia
realised_future_count(ll, obs_time::Dates.Date) -> Any

Count 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-list DataFrame with an onset_date column.

  • obs_time: real-time cut-off Date. Cases whose onset is strictly after this date are counted.

source
TransmissionLinelist.regression_summary Method
julia
regression_summary(chn) -> DataFrames.DataFrame

Long-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 — matches summary_table's quantity for 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 in median with NaN bounds.

Arguments

source
TransmissionLinelist.replicate_offspring Method
julia
replicate_offspring(
    _::typeof(case_model),
    rng,
    k,
    R,
    p_i
) -> Any

Draw 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 on joint_model's defaults; here typeof(case_model).

  • rng: RNG used for the NB draw.

  • k: per-draw NB dispersion k.

  • R: per-source rate R_i = exp(log_R_at(T_onset_i, edges, log_R)).

  • p_i: offspring-completeness probability for this source; 1.0 in retrospective mode.

source
TransmissionLinelist.rt_band Method
julia
rt_band(post; q, t0, edges) -> DataFrames.DataFrame

Quantile 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 from summarise.

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 :date column for plotting on a calendar-date axis.

  • edges: knot positions in days from t0, as returned by prepare_rt_edges. Defaults to prepare_rt_edges(t0).

source
TransmissionLinelist.safe_nb Method
julia
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.

source
TransmissionLinelist.sample_fit Method
julia
sample_fit(
    model;
    samples,
    chains,
    target_accept,
    seed,
    progress,
    adtype
) -> Any

Run 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

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 to AutoMooncake(; config = Mooncake.Config()).

source
TransmissionLinelist.save_posterior Method
julia
save_posterior(post, path) -> Any

Write 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 from summarise.

  • path: output CSV path.

source
TransmissionLinelist.save_regression_summary Method
julia
save_regression_summary(path, chn) -> Any

Write regression_summary(chn) to a CSV at path. Creates the parent directory if needed.

Arguments

  • path: output CSV path.

  • chn: a sampled chain from joint_model.

source
TransmissionLinelist.summarise Method
julia
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

source
TransmissionLinelist.summarise_predictive Method
julia
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.
source
TransmissionLinelist.summary_table Method
julia
summary_table(chn) -> DataFrames.DataFrame

Posterior 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

source
TransmissionLinelist.transmission_delta_model Method
julia
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 as dist_constructor(μ, σ). Defaults to Normal.

  • μ_prior: prior on the population mean μ_δ. Defaults to Normal(0.0, 5.0).

  • σ_prior: prior on the population SD σ_δ, constrained positive. Defaults to truncated(Normal(0.0, 1.0); lower = 0).

source
TransmissionLinelist.truncation_model Method
julia
truncation_model(
    T_inf,
    T_onset,
    source_idx,
    obs_time,
    inc_dist,
    delta_dist
) -> Any

Real-time right-truncation submodel. Adds two contributions to the log-likelihood:

  1. 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 -logcdf to them would double-count.

  2. Per-pair offspring-completeness denominator -log(p[src]) for each sourced case, with p = 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 as T_inf and T_onset.

  • inc_dist: incubation period distribution.

  • delta_dist: per-pair transmission timing distribution.

source
TransmissionLinelist.vector_chain Method
julia
vector_chain(chn, name::Symbol) -> Any

Return a vector of pooled posterior samples for each entry of a vector-valued parameter (e.g. :T_inf, :log_R).

Arguments

  • chn: FlexiChain returned by sample_fit.

  • name: name of a vector-valued parameter in chn.

source
TransmissionLinelist.z_ppc_summary Method
julia
z_ppc_summary(model, chn, d; rng, edges) -> Any

Companion 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: the joint_model instance that produced chn; its defaults.cases field dispatches the per-case posterior-predictive draw.

  • chn: a sampled chain from joint_model.

  • d: the augmented data NamedTuple from build_data.

Keyword Arguments

  • rng: RNG used to replicate the offspring counts.

  • edges: weekly knot edges; defaults to nothing, in which case the knots are taken from prepare_rt_edges(d.t0)[1:length(log_R)] inside _z_ppc_replicate.

source