Output Format#
Every pipeline run writes its artifacts under
{storages.artifacts.filesystem.base_path}/{run_id}/. The canonical
prediction table is always at outputs/predictions.csv regardless of the
model / output mode chosen. This page documents every column in that CSV,
the auxiliary outputs (charts, maps, interactive HTML brief), and the
Largest-Remainder invariant that ties parent and child predictions together
in the downscale pipeline.
Directory layout#
Path (relative to run root) |
What it is |
|---|---|
|
Case data trimmed to the modelling window |
|
Weather features aligned to the modelling window |
|
Long-form (region_id, date, Mean, StdDev, threshold_method) table
covering every configured method, used as input to
|
|
Canonical predictions table (see column reference below) |
|
Per-model copies (only in |
|
Region-level forecast time-series chart embedded in the HTML brief |
|
Choropleth PNGs, one per |
|
Interactive HTML brief with an embedded D3 choropleth (see The HTML brief below) |
|
Human-readable summary of the downscale step (downscale runs only) |
predictions.csv — column reference#
A real header line from artifacts/ap/ap-repro-fixed/outputs/predictions.csv:
recordDate,thresholdMethod,Mean,StdDev,Zero,Inf,T0.00,T1.00,T2.00,
startDatePredictedWeek,dateOfComputingPrediction,regionID,lgdCode,
predictionRaw,ISOWeek,model,predictionMin,predictionMax,
predictionZone,whoZone,prediction,icmrZone,percentileZone
A real data row from the same file:
2026-03-17,previousNweeks,1.6666666666666667,0.478713553878169,
0.0,inf,1.6666666666666667,2.1453812205448357,2.6240957744230045,
2026-03-17,2026-07-24,district_502,502,1.5658082125731811,12,
ensembleModel,,,3,1.0,2,3,2
Columns are grouped by role below.
Identity columns#
Column |
Meaning |
|---|---|
|
Fully qualified region id (e.g. |
|
ISO date (Mon-anchored) of the week the prediction is for. |
|
Wall-clock date the run executed. Useful for hindcast reproducibility audits. |
|
ISO week number (1..53) of |
|
Model that produced the row: |
|
Threshold-generation method whose Mean/StdDev feed this row’s
|
|
Local Government Directory numeric code, added by
|
Numeric prediction columns#
Column |
Meaning |
|---|---|
|
Display integer. This is the value dashboards and briefs show.
Rounded from |
|
Raw float from the model / ensemble. Used by backtesting,
calibration, and downscale shares. Never rounded internally —
the CSV boundary is the only place the rename happens
( |
|
Inter-ensemble range (PR #87 / issue #84). For ensemble rows,
these are the min and max of the corresponding per-model
predictions for the same |
|
LRM-consistent integer produced by |
Threshold columns#
The threshold columns are copied from the inputs/thresholds_<res>.csv
table for the (regionID, startDatePredictedWeek, thresholdMethod) key.
Column |
Meaning |
|---|---|
|
The μ value for the row’s |
|
The σ value. Inflated to |
|
Threshold cut-points at α ∈ |
|
Sentinel bounds (always 0.0 and |
Zone assignment columns#
Three parallel classifications are always computed and always written.
predictionZone is a copy of one of them, selected by
thresholds.classification_method in the config.
Column |
Meaning |
|---|---|
|
WHO-style band. Integer in |
|
ICMR quartile stratum (A1–A4 → 4..1). Cross-sectional per date:
distinct predicted values across all regions on that date are
ranked descending and cut into four equal strata. Set to |
|
Per-region historical-percentile band (PR #73, issue #62). Cut
points come from the region’s own weekly-aggregated case history
at |
|
Convenience copy of whichever of the above is selected by
|
LRM invariant#
The downscale pipeline (pipelines/dengue_downscale) apportions each
parent-level predictionRaw across its children using the Largest
Remainder Method (Hamilton’s method, apportionment.py).
For every (parent, week):
sum(child.prediction) == round_half_up(sum(child.predictionRaw))
== round_half_up(parent.predictionRaw)
Each child’s integer allocation is either floor(child_raw) or
floor(child_raw) + 1 — off by at most one from the natural round.
Ties on fractional remainder are broken by (a) higher recent-cases wins
(issue #86), then (b) lower region_id lexicographically. The
downscale step logs
sum(predictionInt) vs round_half_up(sum(prediction)): M/N parent-weeks
match — this should always be N/N.
Charts and maps#
outputs/charts/hero_forecast.png— the region-focused forecast chart embedded at the top ofreport.html. Always produced.outputs/maps/<model>_<thresholdMethod>_<YYYYMMDD>.png— a static choropleth per prediction week. Only produced whenmaps.enabled: truein the config. The set is deterministic: one image per(model in outputs, thresholdMethod in outputs, startDatePredictedWeek)combination.
The HTML brief#
outputs/report.html is a fully self-contained HTML document — no
external assets. It embeds:
The hero chart as an inline PNG.
A per-week narrative summary.
An interactive D3 choropleth. All map data is inlined as a JS global by
pipelines/dengue/templates/partials/_d3_map_script.html.j2:window.__BRIEF_DATA = { geojson: <FeatureCollection of all rendered regions>, parent_lookup: {<parent_id>: {name, children: [...], ...}}, weekly_zones: {<week_index>: {<region_id>: <zone_int>}} };
geojsonis the union of every parent polygon that has predictions in the brief;parent_lookuppowers the drill-in / drill-out behaviour;weekly_zonesis the per-week zone assignment used to paint the polygons. All three are trimmed to the horizon that the brief covers, keepingreport.htmlsmall enough to email.
Output modes#
model.output controls what ends up on disk:
Mode |
Canonical |
|
|---|---|---|
|
Ensemble rows |
(not written) |
|
Ensemble rows |
One file per non-ensemble model |
|
Copy of |
One file per configured model |
The canonical path never changes — consumers (officials, the HTML brief,
the downscale pipeline) can always read outputs/predictions.csv
without needing to know the mode.