Plotting
Every figure in the report. The functions take a chain and the observations and return a Makie Figure, so a page renders a figure in one call.
Index
BVDOutbreakSize.ZONE_MAP_PROVINCESBVDOutbreakSize.fitted_onset_hazardBVDOutbreakSize.load_health_zones_geojsonBVDOutbreakSize.onset_nowcast_drawsBVDOutbreakSize.plot_cfr_priorBVDOutbreakSize.plot_confirmed_cfrBVDOutbreakSize.plot_correlation_heatmapBVDOutbreakSize.plot_cumulative_casesBVDOutbreakSize.plot_cumulative_trajectoriesBVDOutbreakSize.plot_density_overlayBVDOutbreakSize.plot_diagnostic_contrastBVDOutbreakSize.plot_divergence_locationsBVDOutbreakSize.plot_estimate_comparisonBVDOutbreakSize.plot_estimate_evolutionBVDOutbreakSize.plot_evolution_by_groupBVDOutbreakSize.plot_forecastBVDOutbreakSize.plot_forecast_bedsBVDOutbreakSize.plot_forecast_beds_vs_truthBVDOutbreakSize.plot_forecast_crps_by_horizonBVDOutbreakSize.plot_forecast_flowsBVDOutbreakSize.plot_forecast_latentBVDOutbreakSize.plot_forecast_overlayBVDOutbreakSize.plot_forecast_relative_skillBVDOutbreakSize.plot_forecast_skill_by_cutoffBVDOutbreakSize.plot_forecast_skill_by_vintageBVDOutbreakSize.plot_forecast_vs_truthBVDOutbreakSize.plot_forecast_vs_truth_latentBVDOutbreakSize.plot_imports_patchesBVDOutbreakSize.plot_infections_patchesBVDOutbreakSize.plot_no_onward_deathsBVDOutbreakSize.plot_onset_nowcast_gridBVDOutbreakSize.plot_pairBVDOutbreakSize.plot_parameter_index_diagnosticsBVDOutbreakSize.plot_patch_summaryBVDOutbreakSize.plot_posterior_predictiveBVDOutbreakSize.plot_posterior_predictive_gridBVDOutbreakSize.plot_prior_predictiveBVDOutbreakSize.plot_projection_comparisonBVDOutbreakSize.plot_province_composition_ppcBVDOutbreakSize.plot_province_forecastBVDOutbreakSize.plot_province_forecast_detailBVDOutbreakSize.plot_province_mapBVDOutbreakSize.plot_province_mapBVDOutbreakSize.plot_province_split_ppcBVDOutbreakSize.plot_recoveryBVDOutbreakSize.plot_rhat_spreadBVDOutbreakSize.plot_rtBVDOutbreakSize.plot_rt_patchesBVDOutbreakSize.plot_rt_streamsBVDOutbreakSize.plot_rt_zonesBVDOutbreakSize.plot_scenario_comparisonBVDOutbreakSize.plot_start_date_pairBVDOutbreakSize.plot_stream_calibrationBVDOutbreakSize.plot_stream_pairsBVDOutbreakSize.plot_stream_trajectoriesBVDOutbreakSize.plot_vintage_conditional_ppcBVDOutbreakSize.plot_vintage_incidence_ppcBVDOutbreakSize.plot_zone_comparisonBVDOutbreakSize.plot_zone_forecastBVDOutbreakSize.plot_zone_mapBVDOutbreakSize.plot_zone_map_panelsBVDOutbreakSize.plot_zone_rankingBVDOutbreakSize.plot_zone_sharesBVDOutbreakSize.province_map_summaryBVDOutbreakSize.province_map_summaryBVDOutbreakSize.province_zone_valuesBVDOutbreakSize.reconstruct_patch_rtBVDOutbreakSize.reconstruct_rtBVDOutbreakSize.zone_geojson_pathBVDOutbreakSize.zone_keyBVDOutbreakSize.zone_summary_table
Reference
BVDOutbreakSize.fitted_onset_hazard Method
fitted_onset_hazard(
model::DynamicPPL.Model,
chn
) -> NamedTuple{(:logit_h0, :γ, :alpha), <:Tuple{Any, Any, Any}}fitted_onset_hazard(model, chn) -> NamedTupleEvery posterior draw's fitted symptom-onset reporting hazard, read off the fitted model's own onset-reporting state at each draw of chn (returned): logit_h0 (the baseline delay hazard), γ (the report-date calendar walk) and alpha (the ascertainment level over the triangle's onset dates), one vector per draw, as the composers return them. The model is the one the chain was fitted with, such as a fit spec's model() in the report.
BVDOutbreakSize.onset_nowcast_draws Method
onset_nowcast_draws(
days::AbstractVector{<:Integer},
observed::AbstractVector{<:Real},
delays::AbstractVector{<:Integer},
onsets::AbstractVector{<:AbstractVector{<:Real}},
hazard::NamedTuple;
grid_start,
target_delays
)onset_nowcast_draws(days, observed, delays, onsets, hazard;
grid_start, target_delays)onset_nowcast per posterior draw, one ndraws-long vector per onset day in days. observed[k] is the count a digitised figure prints for days[k] and delays[k] is that figure's own reporting delay, so a snapshot's cells are nowcast from the delay that snapshot had run to.
target_delays is the delay to nowcast to, one per day; the default nothing targets each day's eventual total. Pass the delay of the figure the prediction will be compared against to keep the two like for like.
onsets holds each draw's daily onsets indexed by grid day, the diff of the chain's cumulative_onsets. hazard is fitted_onset_hazard's (; logit_h0, γ, alpha), with alpha indexed from grid_start and held flat outside the fitted grid. The two are paired draw by draw and must come from one fit. Summarised by plot_onset_nowcast_grid.
BVDOutbreakSize.plot_cfr_prior Method
plot_cfr_prior(
prior::Distributions.Distribution
) -> Makie.FigureDensity of a prior over the case-fatality ratio (CFR) on [0, 1], plotted on the sub-range [0, 0.7]. The CDC central estimate of 55/169 ≈ 0.33 is drawn as a solid vertical rule and the report's 26% and 40% scenario bounds as dashed rules, so the prior reads against the published CFR scenarios.
BVDOutbreakSize.plot_confirmed_cfr Method
plot_confirmed_cfr(res) -> Makie.FigurePosterior densities of the delay-corrected confirmed case-fatality ratio and the structural (infection-based) CFR from a delay_corrected_confirmed_cfr result res, on the CFR percentage scale. The naive observed confirmed ratio is a solid vertical rule and the median uncorrected modelled confirmed ratio a dashed one. The gap from the naive rule to the corrected density is the real-time delay debiasing, and the gap to the structural density the residual case/death ascertainment difference.
BVDOutbreakSize.plot_correlation_heatmap Method
plot_correlation_heatmap(
chn,
params::AbstractVector{Symbol};
labels
) -> Makie.FigurePosterior correlation heatmap over the named scalar quantities params, tracked deterministics or sampled parameters. Each cell is the Pearson correlation of two quantities' posterior draws, drawn on a symmetric red–blue scale with the value printed in the cell. The whole joint identifiability structure sits in one panel, including the cross-block degeneracies the plot_pair corners split apart: the size–ascertainment seesaw (C_T vs p_drc), the weaker size–fatality tilt (C_T vs CFR), and the pooled p_drc–p_uganda link.
labels maps a parameter symbol to a display string, read as LaTeX math without the $ delimiters, so "p_\mathrm{drc}" renders with a subscript. A parameter absent from labels falls back to its symbol name. Returns the Figure.
plot_correlation_heatmap(draws::NamedTuple; labels) takes one draw vector per named quantity instead of a chain, for quantities a chain holds only inside a vector deterministic, such as one province's entry of C_T_patch.
BVDOutbreakSize.plot_cumulative_cases Method
plot_cumulative_cases(
streams::Pair{String, <:AbstractVector}...;
scenarios,
xmax,
xlabel,
title
) -> AlgebraOfGraphics.FigureGridOverlaid posterior densities of C_T from one or more fits, built through AlgebraOfGraphics. The published scenario point estimates are drawn as faint dashed vlines on top.
BVDOutbreakSize.plot_cumulative_trajectories Method
plot_cumulative_trajectories(chn; n, seeding)Headline 3x2 cumulative figure. Rows are cumulative infections, cumulative symptom onsets and cumulative deaths, all modelled BVD-only latent renewal quantities. The deaths row excludes the non-BVD background, so it stays as smooth as the infection and onset rows. The left column is the modelled expected cumulative trajectory over the grid as 30%, 60% and 90% ribbons with no median line. The right column is the posterior density of the cut-off cumulative.
The chain must carry the vector deterministics cumulative_infections, cumulative_onsets and cumulative_expected_deaths, one per draw. seeding is the calendar date of grid day 1, so day d is seeding + (d - 1). No observed data is overlaid. Each row is a latent quantity upstream of ascertainment, confirmation and reporting delays, so the observed counts are not on the same scale.
BVDOutbreakSize.plot_density_overlay Method
plot_density_overlay(
streams::Pair{String, <:AbstractVector}...;
xlabel,
title,
lower
) -> AlgebraOfGraphics.FigureGridOverlaid posterior densities of an arbitrary scalar quantity from one or more fits, built through AlgebraOfGraphics. Pass each fit as "label" => draws; xlabel and title set the axis text.
lower clips the axis for a quantity that cannot fall below it, such as a count or a duration. The kernel density spreads mass past the smallest draw, so without it the curve runs onto the impossible side of the bound. The estimate itself is left alone, as on _bounded_density!.
BVDOutbreakSize.plot_diagnostic_contrast Method
plot_diagnostic_contrast(
df::DataFrames.DataFrame;
xlabel,
ylabel,
title
) -> Makie.FigureBulk effective sample size in a reference fit against the same parameter's bulk effective sample size in the fits it is compared with, from the frame diagnostic_contrast returns. Both axes are logarithmic and the dashed line is equality.
A point on the line is a parameter the reference fit handles as well as the comparison does. A point far below it is a parameter that mixes on its own and stops mixing in the reference, so the cause is what the reference adds rather than the parameter.
sourceBVDOutbreakSize.plot_divergence_locations Method
plot_divergence_locations(
chn,
params::AbstractVector;
labels,
ncols,
title
) -> Makie.FigureWhere the divergent transitions sit against the posterior, one panel per parameter in params. Each panel draws the full posterior as a density and the divergent draws as ticks along the axis, with the middle 90% of the divergent draws shaded.
Ticks spread under the whole density are divergences scattered through the posterior, which points at the sampler settings. Ticks piled into one shaded stretch are divergences confined to one region, which points at the geometry there.
sourceBVDOutbreakSize.plot_estimate_comparison Method
plot_estimate_comparison(
rows::AbstractVector;
xlabel,
xmax,
groups,
group_colours
) -> Makie.FigureHorizontal point-and-interval comparison of cumulative-case estimates from several sources. rows is a vector of (label, central, lower, upper) tuples, drawn top to bottom with the central estimate as a point and [lower, upper] as a bar. A row whose lower and upper match its central is a deterministic point estimate and is drawn as a bare marker with no bar.
groups is an optional vector of group keys, one per row, matched against group_colours (a vector of key => colour pairs) to colour each row's marker and bar and build a legend. Without groups the rows share a single colour.
BVDOutbreakSize.plot_estimate_evolution Method
plot_estimate_evolution(
released::AbstractVector;
renewal,
trajectory,
xlabel,
ylabel,
title,
released_label,
renewal_label,
trajectory_label,
refline,
ymax
) -> Makie.FigureEstimate-evolution plot: how the outbreak-size estimate moves as the data cut-off advances, drawn against the calendar date.
released is a vector of (cutoff_date, median, lo30, hi30, lo60, hi60, lo90, hi90) tuples, one per published project release, drawn in blue. renewal is the same tuple shape for the current renewal model re-fit frozen at each release date, drawn in red. Each release and each frozen re-fit is its own fit, so both are drawn as discrete per-date estimates, a median marker with nested 30/60/90% vertical interval bars. Marks sharing a date are dodged horizontally so each reads as a separate estimate.
trajectory is the current-data, current-model cumulative-infection trajectory over the day grid, a (dates, lo30, hi30, lo60, hi60, lo90, hi90) tuple where dates is the calendar date of each grid day. It is a single fit shown over time, so it is drawn in a third colour as one continuous ribbon on the same calendar axis. When its dates collapse to a single day the ribbon is widened across the span of the discrete marks, so a flat reference still reads as a band.
Release dates are marked with dotted vertical rules.
xlabel, ylabel and title set the axis text. released_label, renewal_label and trajectory_label name the three series.
ymax fixes the value axis rather than sizing it to the widest interval. An interval, median or band past it is clamped and the series marked with an open triangle where it leaves the axis, so a quantity whose estimates sit in a narrow range is not flattened by one wide tail.
BVDOutbreakSize.plot_evolution_by_group Method
plot_evolution_by_group(
groups::AbstractVector;
trajectories,
xlabel,
ylabel,
title,
released_label,
trajectory_label,
refline,
ncols,
shared_yrange,
ymax,
empty_note
) -> Makie.FigureFaceted estimate evolution, one panel per group, for comparing how the same quantity moved across releases under each of several fits.
groups is a vector of label => released pairs, where released is the (cutoff_date, median, lo30, hi30, lo60, hi60, lo90, hi90) tuple vector plot_estimate_evolution takes. Panels share one calendar mapping and are laid out over ncols columns. Groups with no estimates are dropped rather than drawn as an empty panel. refline draws a faint horizontal rule in every panel, e.g. Rt = 1.
trajectories optionally maps a group's label to that group's own current-data, current-model trajectory, a (dates, lo30, hi30, lo60, hi60, lo90, hi90) tuple in the shape plot_estimate_evolution takes, drawn with the same band styling. A group absent from trajectories still draws its released points with no band.
shared_yrange (default true) draws every panel on one y range, sized to the largest of them, so groups on a comparable scale read against each other. Set it to false when the groups span very different scales, so a wide-scale group does not squash every other panel's band. Each panel then uses its own range, floored at 1.0.
ymax overrides both, fixing every panel's value axis at it. An interval, median or band past it is clamped and marked with an open triangle, as in plot_estimate_evolution.
Returns a figure carrying empty_note in place of the panels when no group has any estimate.
BVDOutbreakSize.plot_forecast Method
plot_forecast(fc::DataFrames.DataFrame) -> Makie.FigureOne-week-ahead forecast of the observed count streams from forecast_reported: the new count each stream adds over the horizon. Panels cover reported cases, suspected deaths, laboratory-confirmed cases, confirmed deaths and recovered, each drawn only when the forecast carries that stream's *_new column. Passing a column subset restricts the panels further, which is how the report draws the stopped streams on their own. Each panel histograms the projected new count with its 90% predictive interval shaded. The latent counterparts are in plot_forecast_latent.
BVDOutbreakSize.plot_forecast_beds Method
plot_forecast_beds(fc::DataFrames.DataFrame) -> Makie.FigureOne-week-ahead isolation/treatment-bed forecast from forecast_reported: the projected bed demand (the need a week ahead, under unconstrained supply) against the occupancy the situation reports would print, and the demand above the beds available. The left panel overlays the two predictive distributions. The right panel histograms the shortfall, which is the need above the capacity rather than the gap between the two panels' densities, since the occupancy carries the fitted reporting-basis offset and the shortfall does not. Drawn only when the forecast carries the bed streams (bed_demand and isolation_level).
This shortfall is national, so it cannot show local saturation. On 13 June Ituri was at 93.9% occupancy while Sud-Kivu was at 21.9%, and beds free in one province cannot serve patients in another, so the national shortfall understates the local unmet need.
sourceBVDOutbreakSize.plot_forecast_beds_vs_truth Method
plot_forecast_beds_vs_truth(
fc::DataFrames.DataFrame;
isolation,
individual
)Validate a forecast_reported bed projection against the beds actually occupied a week later. Histograms the projected reported isolation-bed occupancy with the 90% predictive interval shaded and the isolation count observed at the target date drawn as a dashed black rule, so last week's bed forecast is scored against what the beds held. Drawn only when the forecast carries isolation_level.
individual, when given, is a second predictive sample: the frozen individual (treatment-only) model's own forecast draws at the same cut-off, from forecast_stream, overlaid as a dotted step outline on the joint's own bins so both bed forecasts are visible against the observed occupancy.
At a one-week-back freeze the bed capacity has no implied-capacity anchor, the reported occupancy rate starting only on 9 June, so the projected occupancy rides the capacity random walk back to the freeze date and the interval is wide.
sourceBVDOutbreakSize.plot_forecast_crps_by_horizon Method
plot_forecast_crps_by_horizon(
scores::DataFrames.DataFrame;
ylabel,
title,
ncols,
empty_message
) -> Makie.FigureBy-horizon CRPS figure: one panel per stream, the mean CRPS split into the three parts it decomposes into (dispersion, overprediction and underprediction) and drawn as one stacked bar per horizon, dodged by fit role where a stream carries more than one.
scores is a forecast_score_by_horizon-shaped table carrying stream, horizon, fit and the three component columns. The bar's full height is the mean CRPS, so a panel shows both how the error grows with the horizon and whether it is made of width, of forecasting too high or of forecasting too low. This is the figure for the by-horizon score table, which is too long to read as numbers.
Each panel takes its own y range, since a stream's CRPS is on the scale of its own counts. empty_message replaces the panels when scores has no rows.
BVDOutbreakSize.plot_forecast_flows Method
plot_forecast_flows(
fc::DataFrames.DataFrame
) -> Makie.FigureOne-week-ahead forecast of the daily isolation/treatment flows from forecast_reported: the projected new admissions, in-care deaths and rule-outs a day at the horizon. Each panel histograms the projected daily count with its 90% predictive interval shaded, drawn only when the forecast carries the flow streams (admissions_fc, incare_deaths_fc, ruleouts_fc). These are the daily-flow counterparts of the bed-stock forecast in plot_forecast_beds.
BVDOutbreakSize.plot_forecast_latent Method
plot_forecast_latent(
fc::DataFrames.DataFrame
) -> Makie.FigureOne-week-ahead forecast of the unobserved (latent) quantities from forecast_reported: new infections, new symptom onsets and new deaths over the horizon, with the reproduction number left to keep evolving. Each count panel histograms the projected new latent count with its 90% predictive interval shaded. The reproduction-number panel shows the posterior of the end-of-horizon forecast R_t with the no-growth line at one marked. These are the latent counterparts of the observed-stream forecast in plot_forecast.
BVDOutbreakSize.plot_forecast_overlay Method
plot_forecast_overlay(
overlay::DataFrames.DataFrame;
empty_message
) -> Makie.FigureForecasts-versus-now overlay: a grid of panels, one row per observed stream and one column per forecast horizon, each showing the forecasts made at every release (median with the 90% predictive interval as a vertical bar) against the value observed since (black points). overlay is the data/forecast_overlay.csv table with columns stream, made_date, horizon, fit, observed, median, lo90 and hi90.
The x-axis is the date the forecast was made, not the target date. For an incident stream the observed value is the new count over the forecast's own (made_date, target_date] window, so it depends on the made date. Keying on the target date would stack several different observed windows at one x with no way to pair each forecast to its own truth.
Forecasts are coloured by fit role (baseline, individual, joint) and dodged by a small fraction of the made-date spacing so the series read apart. A stream that carries only some roles is drawn with those alone, and the legend covers every role drawn in any panel.
Each panel is cropped to zero and about three times the larger of its own observed values and forecast medians, so one very wide predictive interval elsewhere cannot squash every other panel to a line near the bottom. An interval or median past that crop is clamped and marked with an open triangle at the top of the axis. Every made date gets its own x tick, thinning to about a dozen for a busier release history.
Returns a figure carrying empty_message in place of the panels when no forecasts have been scored yet.
BVDOutbreakSize.plot_forecast_relative_skill Method
plot_forecast_relative_skill(
scores::DataFrames.DataFrame;
value_col,
ylabel,
title,
ncols,
empty_message
) -> Makie.FigureBy-horizon relative-skill figure: one panel per stream, plotting relative skill against the persistence baseline (rel_to_baseline, or log_rel_to_baseline on the log scale) against the forecast horizon, with one series per fit role (individual, joint). scores is a forecast_score_by_horizon-shaped table, baseline rows already excluded, carrying stream, horizon, fit and the column named by value_col.
The skill axis is log-scaled, so a fit twice as good and a fit twice as bad sit the same distance from the reference line at one, drawn as a dashed horizontal rule. A series below the line beats the baseline on average at that horizon. A (stream, horizon, fit) cell whose skill is missing or non-finite is absent from its series rather than drawn as a break, and a stream with no individual fit is drawn with the joint series alone.
empty_message is shown in place of the panels when scores has no rows. The caller sets it, since an empty table can mean either that no release carries a stored forecast or that no stored forecast's target has resolved.
BVDOutbreakSize.plot_forecast_skill_by_cutoff Method
plot_forecast_skill_by_cutoff(
scores::DataFrames.DataFrame;
value_col,
ylabel,
xlabel,
title,
ncols,
empty_message
) -> Makie.FigureBy-cut-off relative-skill figure: one panel per stream, plotting relative skill against the persistence baseline against the date the forecast was made, with one series per fit role. scores is a forecast_score_by_release-shaped table, carrying stream, made_date, fit and the column named by value_col.
The made dates sit at evenly spaced slots in date order, not to calendar scale, since the cut-offs are a handful of discrete dates and the ones a few days apart would otherwise overprint. The skill axis is log-scaled about a reference line at one, as in plot_forecast_relative_skill.
This is the figure for the by-cut-off (or by-release) score tables, which carry one row per stream and cut-off and are too long to read as numbers.
A cell whose skill is missing or non-finite is absent from its series. empty_message replaces the panels when scores has no rows.
BVDOutbreakSize.plot_forecast_skill_by_vintage Method
plot_forecast_skill_by_vintage(
scores::DataFrames.DataFrame;
value_col,
ylabel,
title,
ncols,
empty_message
) -> Makie.FigureBy-vintage relative-skill figure: one panel per stream, plotting relative skill against the persistence baseline against the release that made the forecast, with one series per fit role. scores is a forecast_score_by_vintage-shaped table, carrying stream, release, release_date, fit and the column named by value_col.
Releases sit at evenly spaced slots in release_date order, not to calendar scale, and are labelled with the date each was cut. The skill axis is log-scaled about a reference line at one, as in plot_forecast_relative_skill.
A cell whose skill is missing or non-finite is absent from its series. empty_message replaces the panels when scores has no rows.
BVDOutbreakSize.plot_forecast_vs_truth Method
plot_forecast_vs_truth(
fc::DataFrames.DataFrame;
observed,
baseline,
breaks,
individual
)Validation figure for a forecast_reported projection, laid out as a two-row grid with one column per scored stream: the top row shows the cumulative forecast distribution, the bottom row the new count forecast over the horizon. Each panel is a histogram with the 90% predictive interval shaded and the later-observed count drawn as a dashed black rule, so the forecast distribution is scored against the count that was actually observed.
Streams are drawn in the order reported cases, suspected deaths, laboratory-confirmed cases, confirmed deaths and recovered, each shown only when the forecast carries that stream's *_cum/*_new columns and an observed cumulative count is supplied for it.
observed maps a stream's cumulative column (:confirmed_cum, :cases_cum, …) to its observed cumulative count at the target date. A stream absent from observed is skipped, which is how the caller withholds a stream whose reporting does not cover the target date (see stream_reporting). baseline maps the same columns to the cumulative count at the forecast origin (default 0), and breaks to each stream's retrospective harmonisation correction over the forecast window (see confirmed_break_correction, default 0), so the observed new count is max(observed − baseline − breaks, 0).
individual maps a stream's new-count column (:confirmed_new, :cases_new, …) to that stream's own frozen single-stream model's forecast draws of the new count, from forecast_stream. A stream present in individual gets a second, dotted outline over the joint's histogram on both its panels, on the same bins and reweighted to the joint's draw count, the cumulative panel from baseline + individual new-count draws. A stream absent from it draws the joint alone. The latent counterparts are scored distribution-versus-distribution by plot_forecast_vs_truth_latent.
BVDOutbreakSize.plot_forecast_vs_truth_latent Method
plot_forecast_vs_truth_latent(fc::DataFrames.DataFrame; now)Latent-quantity validation figure. For each unobserved quantity (new infections, new symptom onsets, new deaths over the past week) the distribution the frozen last-week fit forecast is overlaid against the distribution the current fit now estimates for the same window. Both are latent, so the comparison is density versus density rather than density versus a single observed count.
fc is the frozen forecast from forecast_reported, its *_new latent columns. now is a NamedTuple carrying the current fit's draws of the same quantities, (; infections_new, onsets_new, deaths_latent_new).
BVDOutbreakSize.plot_imports_patches Method
plot_imports_patches(
chn;
n,
seeding,
n_patches,
patch_labels,
colours
)Imported infections by province over time, one panel per province: the daily infections a province received from the others through the importation kernel, as 30/60/90% credible ribbons.
Every arrival is debited from its origin the same day, so these are transmission relocated rather than transmission added. The national total still moves with the coupling, because the destination then grows at its own reproduction number. The intensity is weakly identified against the secondary provinces' seeds, since both raise a secondary province's early incidence, so the level is read as the coupling the data tolerate rather than as a measured flow. Reads the importation_patch deterministic.
BVDOutbreakSize.plot_infections_patches Method
plot_infections_patches(
chn;
n,
seeding,
n_patches,
patch_labels,
colours
)Modelled infections by province over time, one column per province, with the daily infections on the top row and the cumulative total on the bottom. Every panel is 30/60/90% credible ribbons with no median line.
Each panel carries its own y-axis. The provinces differ by orders of magnitude, so a shared axis would flatten every province but the epicentre into the floor. The cross-province comparison belongs in patch_overview_table. Reads the infections_patch deterministic, the daily per-province infection matrix flattened column-major.
BVDOutbreakSize.plot_no_onward_deaths Method
plot_no_onward_deaths(df::DataFrames.DataFrame; obs_deaths)Two-panel density of the no-onward-transmission counterfactual from predict_no_onward_deaths. The left panel shows the still expected deaths (:delta_deaths, the future deaths in cases already infected by T, net of the obs_deaths already observed). The right panel shows the projected total (:total_projected = obs_deaths + delta_deaths), whose axis starts at obs_deaths. Both are lower bounds, assuming every onward transmission stops at time T.
BVDOutbreakSize.plot_onset_nowcast_grid Method
plot_onset_nowcast_grid(
panels::AbstractVector;
ncol,
colour,
title
) -> Makie.Figureplot_onset_nowcast_grid(panels; kwargs...)Nowcast of the symptom-onset reporting triangle, one panel per digitised snapshot: what that snapshot's own figure implied for the onset dates it printed, against what the figures print for them now.
Each panel is a NamedTuple of title (the snapshot's report date), dates (the onset dates, one per x position), observed (that snapshot's own counts, grey crosses), nowcast (per-draw predictions of the count the latest figure prints, drawn as 30/60/90% ribbons with a median line) and latest (that count, black points).
The panel is read on whether the ribbon covers the black points. Pass nowcast as a predictive rather than the latent count. Two scans of one bar disagree by the read error the stream estimates, so on the onset dates where reporting had already finished the latent quantity is the grey cross exactly and would be scored against a reading it cannot match. Build it from onset_nowcast_draws at the latest figure's own delay, then through the stream's bar measurement error.
A panel whose series disagree in length raises, and an empty panels returns a blank figure.
BVDOutbreakSize.plot_pair Method
plot_pair(
chn,
params::AbstractVector{Symbol};
thin,
prior,
labels,
patch
) -> AnyPairPlots.jl corner plot over the named posterior parameters, thinned by thin. Pass prior, another chain holding the same parameters, to overlay the prior as a second series with a legend, so the data's contribution to each marginal is visible. Draws non-finite in any parameter are left out of their series with a warning naming the parameter.
labels maps a raw chain symbol to a display name (e.g. Symbol("rt_state.sigma_rw") => "Rt step size"), applied to the axis labels only. Symbols absent from the map keep their raw name.
patch selects one entry of vector-valued deterministics such as R_T_patch or province_ascertainment, so the corner plot shows one province. Every parameter in params is then read as a per-patch vector.
plot_pair(draws::NamedTuple; ...) takes one draw vector per named quantity instead of a chain, for quantities a chain holds only inside a vector deterministic, such as one province's entry of C_T_patch. prior is then a NamedTuple with the same names.
BVDOutbreakSize.plot_parameter_index_diagnostics Method
plot_parameter_index_diagnostics(
fit;
groups,
n_groups,
min_elements,
rhat_threshold,
ess_threshold,
labels,
title
) -> Makie.FigureBulk effective sample size against element index for the vector-valued parameters of a fit that mix worst, one panel each. fit is a chain or a frame parameter_diagnostics has already produced. Points are coloured by whether the element's R-hat exceeds rhat_threshold.
The element index runs in model order, so for a random walk or a daily latent series a higher index is later in the outbreak. Bad mixing piled up at one end of a panel is a problem confined to that stretch of the window. Bad mixing spread evenly across a panel is a problem with the whole walk.
sourceBVDOutbreakSize.plot_patch_summary Function
plot_patch_summary(chn; ...) -> Makie.Figure
plot_patch_summary(
chn,
n_patches::Integer;
patch_labels,
colours,
ncols,
title
) -> Makie.FigurePer-province posterior summary as a figure: one panel per quantity, the provinces side by side on a shared axis, each drawn as a median dot over nested 30/60/90% credible bars.
This is the figure form of patch_summary_table and reads the same chain deterministics in the same order: the cut-off cumulative infections C_T, the cut-off reproduction number R_T, the daily infections at the cut-off, and the log-Rt deviation δ from the common national trend, plus the contrast against the primary patch, the deviation-walk scale and the relative case ascertainment wherever the chain carries them.
Each panel carries its own y-axis, the quantities having different units and differing by orders of magnitude. Panels whose quantity has a meaningful reference value are drawn with it as a dashed rule, at one for the reproduction number and the relative ascertainment and at zero for the log-Rt deviations.
The deviations are sum-to-zero contrasts around the national trend (see patch_rt_model), so δ is read relative to the national average across provinces rather than to any one patch. Ascertainment and the reproduction number must be read together. The case composition identifies only their product, and it is the per-province deaths that tilt the balance between them.
BVDOutbreakSize.plot_posterior_predictive Method
plot_posterior_predictive(
pp_exports::Union{Nothing, AbstractVector},
pp_deaths::Union{Nothing, AbstractVector},
obs_exports::Union{Nothing, Real},
obs_deaths::Union{Nothing, Real};
pp_cases,
obs_cases,
pp_exports_deaths,
obs_exports_deaths,
pp_confirmed_deaths,
obs_confirmed_deaths,
pp_confirmed,
obs_confirmed,
pp_tests,
obs_tests,
predictive_label
) -> Makie.FigurePosterior predictive histogram with one panel per supplied data stream. Pass pp_exports/pp_deaths as nothing to suppress either of the first two panels, and supply pp_cases and/or pp_exports_deaths to add the reported-cases and deaths-among-exports panels. Observed values are drawn as red vlines. Four or more streams lay out over three columns, fewer in a single row.
BVDOutbreakSize.plot_posterior_predictive_grid Method
plot_posterior_predictive_grid(
;
individual,
joint,
observed
)Two-row comparison of posterior-predictive distributions, one column per stream. The top row holds replicates from the per-stream fits, the bottom row replicates from the joint fit conditioning on every observed stream. Observed values are drawn as red vertical lines.
Each NamedTuple carries a subset of (; exports, exports_deaths, deaths, cases, tests, confirmed). Columns are drawn in that order for whichever streams are present in individual. Each panel is a histogram of replicated counts, and the two rows share one x-axis so they read against each other.
BVDOutbreakSize.plot_prior_predictive Method
plot_prior_predictive(
pp_exports::Union{Nothing, AbstractVector},
pp_deaths::Union{Nothing, AbstractVector},
obs_exports::Union{Nothing, Real},
obs_deaths::Union{Nothing, Real};
pp_cases,
obs_cases,
pp_confirmed,
obs_confirmed,
pp_tests,
obs_tests
) -> Makie.FigurePrior predictive variant of plot_posterior_predictive, with the panel labels switched to "Prior".
BVDOutbreakSize.plot_projection_comparison Method
plot_projection_comparison(
;
external,
ours,
observed,
external_label,
ours_label,
observed_label,
external_colour,
ours_colour,
ylabel,
title
)Calendar time-series comparison of cumulative-count projections against the data observed since. external is another group's published projection and ours is our own forward projection, each drawn as a central line with a shaded [lower, upper] band. observed is the data observed so far, drawn as a marked line.
Each is a vector of (date, ...) tuples with date an ISO string. external and ours are (date, central, lower, upper), observed is (date, value). The dates share one calendar x-axis, so the projections read against what the outbreak did. Used to set our forward projection beside the Chamla et al. (2026) confirmed-case projection.
BVDOutbreakSize.plot_province_composition_ppc Method
plot_province_composition_ppc(
chn;
share_key,
obs_increments,
days,
seeding,
n_patches,
patch_labels,
colours,
rho_key,
title
)Posterior predictive check on a per-province composition: the modelled share of each province at every spatial vintage, with the observed share drawn over it as black points.
Each panel carries two bands. The grey predictive band is what the observed points are drawn from. Every posterior draw's expected shares and composition overdispersion are pushed back through the stick-breaking allocation province_composition_model scores, at that vintage's observed total, so the band carries the composition's extra-Multinomial scatter on top of the posterior width. The coloured ribbon inside it is the expected share alone, the modelled centre the points scatter around.
share_key is the chain's share deterministic (province_shares for the confirmed cases, province_death_shares for the confirmed deaths), obs_increments the matching (n_patches x n_vintages) observed increments and days their grid days, both from province_increment_matrix.
Shares rather than counts is what the model scores. The per-province totals are an exact partition of the national totals the confirmed streams already carry, so only the split is new information (see province_composition_model).
Every panel starts at zero but takes its own upper limit. The shares differ by orders of magnitude, so a common axis leaves every province but the epicentre pinned to the floor.
rho_key names the chain's overdispersion for this composition and defaults to the one matching share_key. A chain carrying neither that deterministic nor the submodel's own draw is drawn with the expected-share ribbon only.
BVDOutbreakSize.plot_province_forecast Method
plot_province_forecast(
pp,
fc::DataFrames.DataFrame;
n_patches,
patch_labels,
colours,
observed,
title
) -> Makie.FigureOne-week-ahead forecast by province: one panel per forecast target, the provinces side by side on a shared axis, each drawn as a median dot over nested 30/60/90% credible bars, in the style of plot_patch_summary. The targets are the new confirmed cases and confirmed deaths over the week to T + 7, the patients in isolation and the isolation beds at T + 7, the new infections over the week and the reproduction number at T + 7, each drawn only when fc carries it.
fc is a forecast_provinces frame. A national forecast_reported result is replaced by the one-week province forecast read from the posterior-predictive draws pp.
observed optionally gives, per forecast column, one value per province to mark with a cross, such as what each province went on to report.
BVDOutbreakSize.plot_province_forecast_detail Method
plot_province_forecast_detail(
pp,
fc::DataFrames.DataFrame;
province,
n_patches,
patch_labels,
observed
)One-week-ahead forecast for a single province, the per-province counterpart of plot_forecast: one histogram panel per target plot_province_forecast draws for patch province, each with its 90% predictive interval shaded, and the reproduction-number panel with the no-growth line at one.
fc is a forecast_provinces frame. A national forecast_reported result is replaced by the one-week province forecast read from the draws pp.
observed optionally gives a value per forecast column (for example a recent observed week from province_recent_counts, or what the province went on to report), drawn as a dashed rule.
BVDOutbreakSize.plot_province_split_ppc Method
plot_province_split_ppc(
chn;
share_key,
rows,
seeding,
n_patches,
patch_labels,
colours,
rho_key,
title
)Posterior predictive check on a province split scored on the provinces present each day (province_split_logpdf): the isolation occupancy (share_key = :province_occupancy_share, a daily share matrix), the beds (share_key = :province_capacity_share, also a daily share matrix; a static share vector per patch is also read) and the 24h admissions (share_key = :province_admissions_share). Each panel shows the modelled share of that province among the provinces printed that day, with the observed share as black points, over the days the split is scored (rows, the long format from province_care_observations the fit was given). The grey band is the posterior predictive interval on the observed share, the stick-breaking allocation at the day's printed total under the split's overdispersion, and the coloured ribbon the expected share alone. A day on which a province is absent leaves a gap. Reads like plot_province_composition_ppc.
BVDOutbreakSize.plot_recovery Method
plot_recovery(
params::DataFrames.DataFrame,
draws::AbstractDict,
prior::DataFrames.DataFrame;
quantities,
labels,
panel_labels,
row_labels,
log_x,
difference,
ncols
) -> Makie.FigureParameter recovery over every seed (see scripts/recovery.jl). params is the stacked recovery_table of each seed with a seed column, draws maps each seed to a frame of its thinned posterior draws and prior is a frame of prior draws, one column per quantity in both.
The top panel puts every quantity and seed on one scale relative to the truth: each seed's posterior median with its 50% and 90% intervals divided by that seed's true value, on a log axis about a line at one. A quantity in difference is shown as exp(value - truth) instead, the ratio of daily growth factors for a growth rate. Below, one panel per quantity on its natural scale holds the prior draws in grey, each seed's posterior in its colour and each seed's true value as a dashed line; quantities in log_x are drawn on a log axis. Panels are laid out ncols to a row in the order of quantities, titled by panel_labels (by default labels), with row_labels down the left when given. The axes cover the posteriors and the truths, so a wide prior shows as a low grey floor. Returns the Figure.
BVDOutbreakSize.plot_rhat_spread Method
plot_rhat_spread(
fits::Pair{String}...;
xmax,
clip,
thresholds,
title
) -> Makie.FigureCumulative share of parameters at or below each R-hat, one line per fit. Pass each fit as "label" => chain, or as "label" => frame where the frame is one parameter_diagnostics has already produced.
A line that climbs to one just past the left edge is a fit where a handful of parameters are bad and the rest are fine. A line that stays low across the axis is a fit where most of the model has not converged. The axis runs to the worst fit's clip quantile so one extreme parameter cannot stretch it, and anything beyond that is drawn at the right edge.
BVDOutbreakSize.plot_rt Method
plot_rt(
chn;
n,
breakpoint,
as_of_date,
seeding,
rt_start,
rt_walk_start,
week,
ramp,
n_traj
)Daily reproduction-number trajectory Rt per posterior draw, rebuilt by reconstruct_rt and plotted over the established-outbreak window.
That window runs from rt_start, the renewal start where the random walk begins, to the cut-off. Only that period is drawn, as 30%, 60% and 90% credible ribbons with no median line, with about n_traj thinned sampled trajectories overlaid faint to show the per-draw spread. The intervention breakpoint, the end of the scale-up (breakpoint + ramp, dotted) and the cut-off are marked. seeding is the calendar date of grid day 1, so day d is seeding + (d - 1).
BVDOutbreakSize.plot_rt_patches Method
plot_rt_patches(
chn;
n,
breakpoint,
as_of_date,
seeding,
n_patches,
patch_labels,
rt_start,
rt_walk_start,
display_start,
week,
ramp,
ncols,
colours,
national_colour
)Faceted reproduction number by province, one panel per patch, each with the national trajectory overlaid in grey as the shared reference. Provincial Rt is rebuilt by reconstruct_patch_rt. The national reference is reconstruct_rt, the same trajectory plot_rt draws.
Every panel draws 30/60/90% credible ribbons with no median line, on a shared y-axis so the provinces are compared rather than each rescaled to its own range. The intervention breakpoint (dashed), the end of the scale-up (dotted) and the cut-off are marked as in plot_rt.
The grey reference is the reproduction number implied by the summed provinces, the incidence-weighted mean of the panels rather than any one province or the central trend they pool toward. A panel tracking the grey band says that province moves with the country. Separation between panels is the spatial signal, and region_drift_sd, the sd of each province's weekly deviation innovation, measures it.
BVDOutbreakSize.plot_rt_streams Method
plot_rt_streams(
streams::AbstractVector;
joint,
n,
breakpoint,
as_of_date,
seeding,
display_start,
week,
ramp,
ncols,
joint_colour,
title,
reference_label,
panel_label
)Faceted implied reproduction number, one panel per single-stream fit, each with the joint fit overlaid as the reference. Each fit's daily Rt comes from reconstruct_rt on its own sampled random walk, so the figure shows what reproduction number each data stream implies on its own against the all-streams-together joint estimate.
Every panel draws 30/60/90% credible ribbons with no median line, the joint in grey first and then the stream in its colour on top, with the panel title in that colour. The y-axis is shared across panels and capped from the panels' 90% bands, so a weakly-informed stream does not stretch the scale. Ribbon above the cap is clipped.
Each stream is a NamedTuple (; label, chn, rt_start, rt_walk_start, colour) and joint is (; label, chn, rt_start, rt_walk_start), where chn is that fit's chain and rt_start/rt_walk_start are the renewal start and random-walk start that fit used. The per-stream fits walk from day 1, the joint from the breakpoint lead. display_start is the shared grid day the panels draw from, so every stream reads over the same window. seeding is the calendar date of grid day 1, so day d is seeding + (d - 1). The intervention breakpoint, the end of the scale-up (breakpoint + ramp, dotted) and the cut-off are marked as in plot_rt.
title, reference_label and panel_label name what the figure is showing. They default to the per-stream reading, and the sensitivity page passes its own to set two model structures against each other instead.
BVDOutbreakSize.plot_rt_zones Method
plot_rt_zones(
rt_draws::AbstractVector{<:AbstractMatrix},
zone_labels::AbstractVector,
zone_patch::AbstractVector{<:Integer};
patch_labels,
dates,
as_of_date,
cumulative,
top,
patch_rt,
reference_rt,
reference_label,
ncols,
patch_colours,
patch_colour,
title
)plot_rt_zones(
rt_draws::AbstractVector{<:AbstractMatrix},
zone_labels::AbstractVector,
zone_patch::AbstractVector{<:Integer};
patch_labels,
dates,
as_of_date,
cumulative,
top,
patch_rt,
reference_rt,
reference_label,
ncols,
patch_colours,
patch_colour,
title
)Faceted reproduction number by health zone for the top zones by cumulative (the first top zones when cumulative is nothing), grouped and coloured by patch. rt_draws[z] is the ndraws × n daily trajectory of zone z (missing where a day is not established), zone_labels names the zones and zone_patch[z] indexes the patch the zone belongs to.
Every panel draws 30/60/90% credible ribbons on a shared y-axis. patch_rt[p], when given, is the patch's own trajectory, drawn behind each of its zones in grey with its median as a line. reference_rt[z], when given, is another fit's trajectory for the same zone, drawn behind it as a dashed grey median with its 90% band. The days are placed by dates (one per column) or by as_of_date, the date the series ends on. That date is marked.
BVDOutbreakSize.plot_scenario_comparison Method
plot_scenario_comparison(
scenarios::AbstractVector;
ours,
date_titles,
method_names,
method_colours,
xlabel,
title
) -> Makie.FigureFaceted point-and-interval comparison of published scenario estimates, one panel per date of estimation. scenarios is REPORT_SCENARIOS_CI-shaped (date, label, central, lower, upper) with label of the form "M1|M2 <family>, <swept level>", for example "M2 τ=14 d, CFR 26%".
Within a panel each (method, family) is one row, and the swept nuisance level (the CFR, window or doubling time) is dodged onto that line so every scenario keeps its own interval while the sweep adds no rows. Method sets the colour. ours maps a date string to our matched (median, lower, upper) estimate, drawn as a grey reference band with a dashed median in that date's panel. date_titles are date => title pairs giving each panel its heading.
BVDOutbreakSize.plot_start_date_pair Method
plot_start_date_pair(chn; as_of_date, thin)One-row, two-panel figure summarising when the outbreak began. The left panel is the posterior density of the outbreak start date, the calendar date of the import that started the outbreak, from the outbreak age T as as_of_date minus T. The right panel is the joint (doubling_time, T) posterior pair plot. Shorter doubling times mean faster early growth, which reaches the same epidemic size in less time.
BVDOutbreakSize.plot_stream_calibration Method
plot_stream_calibration(
tbl::DataFrames.DataFrame
) -> Makie.FigurePer-stream calibration of the one-step-ahead conditional posterior predictive, plotting the table from stream_calibration. Pass that table as returned, with its prettified columns Stream, 50% coverage, 90% coverage and Bias.
Two panels share a categorical y-axis of streams. The left panel marks each stream's empirical 50% and 90% coverage against vertical dashed reference lines at the nominal 0.5 and 0.9, so a well-calibrated stream sits on its line and a marker to the left of it flags under-coverage. The right panel marks the mean forecast Bias, negative for under-prediction and positive for over-prediction, with a dashed line at zero.
BVDOutbreakSize.plot_stream_pairs Method
plot_stream_pairs(
modelled::NamedTuple,
observed::NamedTuple
) -> Makie.FigurePairs plot of the per-stream modelled totals. modelled is a NamedTuple of one per-draw vector per stream, each summed to that stream's own observed support, and observed a NamedTuple of scalars drawn as crosshair reference lines.
The diagonals show how much predictive density sits above or below each observed value, and the off-diagonals whether those shoots move together across draws. This is the posterior-predictive view of data-stream conflict, the counterpart to the parameter-space plot_correlation_heatmap. Returns the Figure.
BVDOutbreakSize.plot_stream_trajectories Method
plot_stream_trajectories(
streams::AbstractVector;
n,
seeding,
ymax,
title
)Overlaid cumulative-infection trajectories, one per single-stream fit, each projected out to the cut-off on day n even when that stream's data stops earlier. Each stream is drawn as 30%, 60% and 90% credible ribbons with no median line. A dotted vertical rule in each stream's colour marks the date that stream's data stops reporting, so the projection beyond the data reads apart from the fitted span.
Each stream is a NamedTuple (; label, trajs, last_day, colour), where trajs is a vector of per-draw cumulative-infection vectors of length n (one per posterior draw) and last_day the 1-based grid day that stream's data last reports (or nothing to omit the rule). seeding is the calendar date of grid day 1, so day d is seeding + (d - 1).
ymax crops the count axis. A stream whose data barely bounds the infection count runs to a 90% upper on the scale of the source population, which on a free axis flattens every other stream onto the baseline. Pass a multiple of a reference fit's upper bound, as the cut-off density figure does, and the streams that run past it are clipped and marked with an open triangle at the day each one first leaves the axis rather than dropped. The default nothing sizes the axis to the widest stream.
BVDOutbreakSize.plot_vintage_conditional_ppc Method
plot_vintage_conditional_ppc(
panels::AbstractVector;
xlabel,
max_date
) -> Makie.FigurePer-vintage conditional one-step-ahead posterior-predictive for the DRC streams. For each panel the predicted cumulative count at vintage v conditions on the observed cumulative at the previous vintage and adds only the posterior-predictive between-vintage increment,
Each panel is a NamedTuple (; title, dates, replicates, observed), where replicates is a vector of per-draw increment vectors, one entry per vintage oldest first, and observed the matching observed cumulative counts used as the conditioning baselines. colour is optional per panel. A panel may set cumulative = false to plot standalone per-day counts instead of a cumulative series, such as the daily new-suspect inflow or the 24h analysed volume. There is no previous-vintage baseline then, so each replicate is plotted as its own daily count and the y-axis reads "Daily count". A panel may also set ylabel to name its own y-axis, which is how an occupancy census is kept from reading as either a running total or a count of new events.
max_date (an ISO date string or Date) truncates every panel to the vintages on or before that date, so streams that keep reporting past the others are cut back to the shared last date. Without it the confirmed panel runs further along the date axis than the suspected panel and reads as though it overtakes it, when the two are simply shown to different end dates.
The date axis carries about one label a week and always labels the last vintage.
sourceBVDOutbreakSize.plot_vintage_incidence_ppc Method
plot_vintage_incidence_ppc(
panels::AbstractVector;
xlabel,
max_date
) -> Makie.FigurePer-vintage incidence posterior-predictive check: the same panels as plot_vintage_conditional_ppc but plotting the count between consecutive vintages rather than the running cumulative, so a rise or a slowdown reads off the height of each step instead of the slope of a near-straight cumulative line.
For a cumulative panel the observed incidence is the between-vintage increment, the first vintage being its own baseline. For a non-cumulative panel it is the count itself. The replicates are already per-vintage increments, so they are the modelled incidence directly and are summarised as 30/60/90% credible ribbons with the observed incidence overlaid. panels, max_date and the weekly date axis match plot_vintage_conditional_ppc, including the optional per-panel ylabel.
BVDOutbreakSize.plot_zone_comparison Method
plot_zone_comparison(
series::AbstractVector{<:Pair};
top,
rank_by,
patch_labels,
patch_colours,
reference_line,
xlabel,
title
) -> Makie.Figureplot_zone_comparison(
series::AbstractVector{<:Pair};
top,
rank_by,
patch_labels,
patch_colours,
reference_line,
xlabel,
title
) -> Makie.FigurePer-zone cut-off posteriors compared across fits: one row per zone for the top zones by the rank_by-th series' median, grouped by patch, with each series drawn at a small vertical offset as its 90% (thin) and, where the table carries it, 50% (thick) interval in the patch's colour, topped by a median marker whose shape names the series. series pairs each fit's name with its table, in either layout plot_zone_forecast accepts. A reference_line (one for a reproduction number) is drawn dashed.
BVDOutbreakSize.plot_zone_forecast Method
plot_zone_forecast(
tbl::DataFrames.DataFrame;
top,
patch_labels,
patch_colours,
xlabel,
title
) -> Makie.Figureplot_zone_forecast(
tbl::DataFrames.DataFrame;
top,
patch_labels,
patch_colours,
xlabel,
title
) -> Makie.FigureOne-week-ahead forecast by health zone for the top zones by forecast median, grouped by patch: each zone's median as a dot over its 90% (thin) and, when the table carries it, 50% (thick) interval, in the patch's colour, with the observed value as a hollow diamond when an observed column is present (the frozen validation).
tbl is a zone_summary_table (label, patch, median, lo90, hi90, optionally lo50, hi50 and observed) or a zone forecast table in the report's layout (zone, patch as the patch label, central_estimate, lower_90, upper_90, optionally lower_60, upper_60 and observed; its "Patch total" rows are left out). The draws method builds the first from per-zone draw vectors.
BVDOutbreakSize.plot_zone_ranking Method
plot_zone_ranking(
overview::DataFrames.DataFrame;
patch_labels,
patch_colours,
max_zones,
title
) -> Makie.Figureplot_zone_ranking(
overview::DataFrames.DataFrame;
patch_labels,
patch_colours,
max_zones,
title
) -> Makie.FigureDot plot ranking the health zones by the probability that their reproduction number at the cut-off exceeds one. The left panel is that probability, the right the reproduction number's median and 90% interval, one row per zone, sorted by the probability and coloured by patch. A zone whose walking flag is false carries a level rather than its own reproduction-number walk and is drawn hollow in grey. Its estimate is the patch's rather than its own.
overview has one row per zone with label (or zone), patch (the index of the zone's patch, or its label), rt_median, rt_lo90, rt_hi90 and p_rt_above_one (or p_R_above_1), and optionally walking. A zone whose probability is NaN, below the reporting floor, is left out.
BVDOutbreakSize.plot_zone_shares Method
plot_zone_shares(
share_draws::AbstractVector{<:AbstractMatrix},
obs_shares::AbstractMatrix,
dates::AbstractVector,
zone_labels::AbstractVector;
zone_patch,
patch_labels,
pred_draws,
prior_draws,
tick_step,
top,
ncols,
patch_colours,
title
) -> Makie.Figureplot_zone_shares(
share_draws::AbstractVector{<:AbstractMatrix},
obs_shares::AbstractMatrix,
dates::AbstractVector,
zone_labels::AbstractVector;
zone_patch,
patch_labels,
pred_draws,
prior_draws,
tick_step,
top,
ncols,
patch_colours,
title
) -> Makie.FigurePosterior predictive check on the zone composition: for the top zones by observed share, the modelled share of the patch's confirmed cases at every vintage as 30/60/90% ribbons in the patch's colour, with the observed share as black points. share_draws[z] is the ndraws × n_vintages modelled share of zone z, obs_shares the (n_zones × n_vintages) observed share (NaN where the patch reported no cases in that vintage, drawn as a gap) and dates the vintage dates.
pred_draws, when given with the same shape as share_draws, is the predictive share and is drawn behind the ribbon in grey, dashed at its 90% edges. prior_draws, same shape, is the prior predictive share, drawn behind everything as a tan 90% band with a dashed median. Every panel starts at zero and takes its upper limit from the posterior bands and the points. Date ticks are every tick_step days (automatic when nothing).
BVDOutbreakSize.reconstruct_patch_rt Method
reconstruct_patch_rt(
chn;
n,
breakpoint,
n_patches,
rt_start,
rt_walk_start,
week,
ramp
)Reconstruct each posterior draw's daily reproduction number for every province, returning a vector of ndraws × n matrices, one per patch, each masked to the draw's established window exactly as reconstruct_rt masks the national trajectory.
The chain stores the provincial Rt only at the cut-off (R_T_patch), so the trajectory is rebuilt by mirroring the model: the central trend from reconstruct_rt, times exp(δ_p(t)) with δ_p the sum-to-zero deviation interpolated from the weekly knots the chain carries as delta_knots (interpolate_knots). delta_knots is the (n_patches × n_knots) deviation matrix flattened column-major.
Each province runs its own renewal at its own Rt and nothing rescales it, so μ(t) · exp(δ_p(t)) is what the model used. Scaled by the province's susceptible fraction the day before (the chain's susceptible_fraction_patch), it is what R_T_patch reports. A chain without that series is returned unscaled. The national reproduction number is not μ but the value implied by the summed infections, which is why plot_rt_patches draws it from the chain's own national trajectory rather than from these.
A chain carrying no usable deviations is an error here rather than a silent national trajectory repeated per panel.
sourceBVDOutbreakSize.reconstruct_rt Method
reconstruct_rt(
chn;
n,
breakpoint,
rt_start,
rt_walk_start,
week,
ramp
)Reconstruct each posterior draw's daily reproduction-number trajectory Rt from the sampled weekly random-walk parameters, returning a ndraws × n matrix masked to each draw's established window (missing before rt_start). The saved chain stores only the cut-off R_T, so each draw's daily Rt is rebuilt by mirroring rt_walk_model: weekly knots (knot_days) from rt_walk_start follow a non-centred Gaussian walk (rt_state.log_R0 plus the cumulative sum of rt_state.sigma_rw .* rt_state.z), linearly interpolated to the day grid (interpolate_knots) and shifted by the sampled rt_state.intervention_effect along a logistic ramp (sigmoid_ramp) centred at the outbreak-response breakpoint. Each day is then scaled by the draw's susceptible fraction at the end of the day before, the chain's susceptible_fraction, so the trajectory is net of depletion (adjusted_rt). A chain without that series is returned unscaled. Shared by plot_rt and plot_rt_streams.
BVDOutbreakSize.zone_summary_table Method
zone_summary_table(
draws::AbstractVector{<:AbstractVector},
zone_labels::AbstractVector,
zone_patch::AbstractVector{<:Integer};
observed
) -> DataFrames.DataFramezone_summary_table(
draws::AbstractVector{<:AbstractVector},
zone_labels::AbstractVector,
zone_patch::AbstractVector{<:Integer};
observed
) -> DataFrames.DataFrameSummarise per-zone draws into one row per zone: label, patch, the median, the 90% (lo90, hi90) and 50% (lo50, hi50) intervals, and observed when given. This is the table plot_zone_forecast and plot_zone_comparison draw, for any cut-off quantity.
BVDOutbreakSize.ZONE_MAP_PROVINCES Constant
ZONE_MAP_PROVINCESThe provinces whose health zones the maps draw. Zones outside them are dropped when the geojson is read.
sourceBVDOutbreakSize.load_health_zones_geojson Function
load_health_zones_geojson(
;
...
) -> Vector{@NamedTuple{zone::String, label::String, province::String, polygons::Vector{GeometryBasics.Polygon}, centroid::GeometryBasics.Point{2, Float32}}}
load_health_zones_geojson(
path::AbstractString;
provinces
) -> Vector{@NamedTuple{zone::String, label::String, province::String, polygons::Vector{GeometryBasics.Polygon}, centroid::GeometryBasics.Point{2, Float32}}}load_health_zones_geojson(
;
...
) -> Vector{@NamedTuple{zone::String, label::String, province::String, polygons::Vector{GeometryBasics.Polygon}, centroid::GeometryBasics.Point{2, Float32}}}
load_health_zones_geojson(
path::AbstractString;
provinces
) -> Vector{@NamedTuple{zone::String, label::String, province::String, polygons::Vector{GeometryBasics.Polygon}, centroid::GeometryBasics.Point{2, Float32}}}Read the health zones of provinces (matched through zone_key) from a geojson, one NamedTuple per zone of zone (the key), label, province, polygons (one Makie polygon per part, holes included) and centroid (of the largest part). A feature is named by its label (or nom) property and keyed by its zone property when that is non-empty, otherwise by zone_key of the name.
BVDOutbreakSize.plot_province_map Method
plot_province_map(
panels::AbstractVector{<:NamedTuple};
geojson,
provinces,
ncols,
title,
panel_size,
fontsize
) -> Makie.Figureplot_province_map(
panels::AbstractVector{<:NamedTuple};
geojson,
provinces,
ncols,
title,
panel_size,
fontsize
) -> Makie.FigureChoropleths of the patches, one per entry of panels, wrapping after ncols. Each panel is a NamedTuple with per-patch values in PROVINCE_NAMES order, optional per-patch lower and upper, and any of the other plot_zone_map keywords. Every health zone takes its patch's value through province_zone_values, so a pooled patch colours all its provinces, and each province is named at its centre instead of the zones being labelled. With diverging_at, a patch whose interval straddles it is washed out.
BVDOutbreakSize.plot_province_map Method
plot_province_map(
values::AbstractVector{<:Real};
geojson,
provinces,
panel_size,
kwargs...
) -> Makie.Figureplot_province_map(
values::AbstractVector{<:Real};
geojson,
provinces,
panel_size,
kwargs...
) -> Makie.FigureOne province choropleth of per-patch values. The keywords are those of a plot_province_map panel (lower, upper, title, diverging_at, scale, colorbar_label, ...) plus its geojson, provinces and panel_size.
BVDOutbreakSize.plot_zone_map Method
plot_zone_map(
values::AbstractVector,
zones::AbstractVector;
geojson,
provinces,
title,
colormap,
colorrange,
lower,
upper,
label_top,
diverging_at,
scale,
colorbar_label,
size
) -> Makie.Figureplot_zone_map(
values::AbstractVector,
zones::AbstractVector;
geojson,
provinces,
title,
colormap,
colorrange,
lower,
upper,
label_top,
diverging_at,
scale,
colorbar_label,
size
) -> Makie.FigureChoropleth of the health zones, coloured by values, one per key in zones. Zones absent from zones are grey, province boundaries are black outlines dissolved from the zone polygons, and the label_top zones with the largest values are labelled at their centroids.
With diverging_at the colour range is symmetric about that value on a red-blue colormap with a neutral centre. Without it the map is sequential in blue over the range drawn. scale (log10, or CairoMakie.Makie.pseudolog10 when zeros are present) is applied before colouring and the colourbar shows the untransformed values. With diverging_at, per-zone lower and upper bounds wash out the zones whose interval straddles the centre. colormap and colorrange override the defaults, and geojson is read by load_health_zones_geojson for provinces.
BVDOutbreakSize.plot_zone_map_panels Method
plot_zone_map_panels(
panels::AbstractVector{<:NamedTuple};
geojson,
provinces,
ncols,
label_top,
title,
panel_size
) -> Makie.Figureplot_zone_map_panels(
panels::AbstractVector{<:NamedTuple};
geojson,
provinces,
ncols,
label_top,
title,
panel_size
) -> Makie.FigureSeveral choropleths of the same zones side by side, one per entry of panels, wrapping after ncols. Each panel is a NamedTuple with values and zones, plus any of the plot_zone_map keywords (title, colormap, colorrange, diverging_at, scale, lower, upper, colorbar_label, label_top). The polygons are read once and shared.
BVDOutbreakSize.province_map_summary Method
province_map_summary(
draws::AbstractVector{<:AbstractVector};
level
) -> NamedTuple{(:values, :lower, :upper), <:Tuple{Any, Any, Any}}province_map_summary(
draws::AbstractVector{<:AbstractVector};
level
) -> NamedTuple{(:values, :lower, :upper), <:Tuple{Any, Any, Any}}The posterior median and equal-tailed level interval of each patch's draws, as the values, lower and upper a plot_province_map panel takes. draws holds one draw vector per patch.
BVDOutbreakSize.province_map_summary Method
province_map_summary(
chn,
key::Symbol,
n_patches::Integer;
level
) -> NamedTuple{(:values, :lower, :upper), <:Tuple{Any, Any, Any}}province_map_summary(
chn,
key::Symbol,
n_patches::Integer;
level
) -> NamedTuple{(:values, :lower, :upper), <:Tuple{Any, Any, Any}}province_map_summary of the per-patch deterministic key of chn, for its first n_patches patches.
BVDOutbreakSize.province_zone_values Method
province_zone_values(
values::AbstractVector;
lower,
upper,
geojson,
provinces
) -> NamedTuple{(:values, :zones), <:Tuple{Vector, Vector{String}}}province_zone_values(
values::AbstractVector;
lower,
upper,
geojson,
provinces
) -> NamedTuple{(:values, :zones), <:Tuple{Vector, Vector{String}}}Spread per-patch values, in PROVINCE_NAMES order, over the health zones of the provinces each patch pools, as the values and zones of a plot_zone_map_panels panel. lower and upper, when given, are spread the same way. A zone whose province no patch pools, or whose patch has no value, is left out.
BVDOutbreakSize.zone_geojson_path Method
zone_geojson_path() -> Stringzone_geojson_path() -> StringPath of the packaged health-zone geojson, src/assets/health_zones.geojson.
BVDOutbreakSize.zone_key Method
zone_key(name::AbstractString) -> Stringzone_key(name::AbstractString) -> StringFold a zone name to the snake_case key the zone data and the geojson share: accents stripped, lower-cased, and every run of non-alphanumerics collapsed to one underscore, so "Bili (Bas-Uele)" becomes "bili_bas_uele".