Skip to contents

Claims and criteria

The unit of evidence is a claim, not a scenario. Each claim has a criterion that decides it and a verdict, so the result is a decision rather than a number to interpret. A claim can fail, and two currently do.

Criteria are drawn from the mechanism rather than from the result: “inside the IBM replicate band”, because that band is the noise floor a deterministic model should land inside, not “at five of six EIRs”, because five is what came out. The replicate band is the IBM median plus or minus 1.28 standard deviations across replicates, the 10-90% interval of a normal distribution. It adapts as the comparison gets harder: splitting the IBM by age thins its counts and widens its spread, so the test becomes more forgiving where the reference is less certain, and the measured value records this rather than hiding it.

Claims about how a burden is distributed by age are scored only on the age bands carrying at least 5% of it. The notes on those claims say what the exclusion costs.

Statistics

Every comparison statistic is defined once, in R/metrics.R, and unit-tested. agreement() returns correlation, RMSE, bias, relative bias and slope together, because a slope of 1 with a positive bias is a constant offset while a slope above 1 with no bias is a fan, and either statistic alone hides which. replicate_band() defines the band named in the criteria of 17 claims; band_summary() scores a set of cells against it, and outside_rates() sets the bar for claims tested over many cells.

Because figures and tables use the same functions, they cannot disagree: the site-file correlation in render.R’s figure and in tables.R’s table both come from agreement().

Provenance and precision

stamp() records, with every result, the fleet and malariasimulation versions and the commits they were installed from, the R version, the platform, the date, and any fields the run adds. A package installed from a local source tree has no commit to record, so that field is null; fleet’s Built field is recorded beside it to show when and on what it was built.

The site-file statistics also record the age grid and the mosquito sub-step count they were measured at. Their snapshot carries two stamps, which are not interchangeable. run records the site-file sweep, including the fleet version that produced the per-country results, and changes only when the sweep is repeated. summarised records the pass that reduces those results to the four numbers on this site; it takes seconds and can be repeated at any later version. A single stamp would report today’s fleet against numbers from months earlier.

Simulation output is quoted to three or four significant figures. run.R rounds the stored summaries to six with round_sig() as it writes them, so a re-run cannot store full precision again. One file keeps full precision: rep_eq.csv, which the drift check in assess.R compares against at a tolerance of 1e-6.

Tiers

Each claim records a tier: the cost of reproducing it.

Tier Cost Who can reproduce it
0 seconds anyone, from the committed summaries
1 minutes anyone; re-runs fleet only
2 about 2 hours anyone with about 10 cores
3 about 30 minutes anyone with 4 cores and the site files, which are not redistributable

These costs are for P. falciparum. For P. vivax, tier 1 takes a few minutes and tier 2 about an hour.

Tier 3 is the 63-country site-file comparison. Its figures and statistics are public, but the site files behind them are not redistributable, so nobody outside the project can repeat it: a limitation of the evidence, not a property of the result. The constraint is the inputs rather than the compute: the sweep re-runs fleet only, because the IBM arm is the pre-run diagnostic shipped with each site file.

Reproducing the results

Installation, the tier-0 checks and the fleet-only drift check are in the README. Paths below are relative to the repository root. No script has a hardcoded path: each finds the checkout by walking up to DESCRIPTION, so it runs from any working directory.

R/ holds the unit-tested package code listed in the reference. validations/ has one directory per body of evidence, with its scripts and committed results; 01-seed-stability to 04-parameter-draws each have a README with script-level detail. Raw model output is never committed, only summaries and their stamps.

Scenario comparison

validations/02-scenarios/ runs every scenario through both models on the same parameter list. Its assess.R re-runs fleet alone against the committed IBM rows, which stay valid for any change to fleet because the IBM does not depend on it. It reports two things separately: whether anything moved (fleet now against fleet’s committed rows), and whether the match still holds (fleet against the IBM medians and replicate bands, at the thresholds the claims rest on). Only the second fails the run by default, with exit status 1, so the script can gate CI.

CMP_ONLY=eir_20,smc Rscript validations/02-scenarios/assess.R   # a subset, seconds
CMP_STRICT=1 Rscript validations/02-scenarios/assess.R          # also fail if any number moved

Before re-running both models, run the smoke path. It runs every scenario end to end at a 4-year horizon with one replicate, in about two minutes, and writes to validations/02-scenarios/results/smoke/, so it cannot touch the committed results.

CMP_SMOKE=1 Rscript validations/02-scenarios/run.R

The full run takes about two hours on ten cores. It runs the IBM N_REP times per scenario on a PSOCK cluster of ten workers (fewer with CMP_WORKERS) and re-stamps ibm_reference.json. After a change to fleet alone, CMP_FLEET_ONLY=1 refreshes fleet’s rows in minutes and keeps the IBM’s.

Rscript validations/02-scenarios/run.R
CMP_FLEET_ONLY=1 Rscript validations/02-scenarios/run.R

The P. vivax suite is the same scripts under CMP_PARASITE=pv, with results in validations/02-scenarios/results/pv/. It runs on its own transmission grid (EIR 0.3 to 30, against 1 to 120 for falciparum), without SMC, PMC or RTS,S, and with radical cure in their place: malariasimulation cannot run chemoprevention under vivax, and its vaccines carry no vivax calibration.

CMP_PARASITE=pv Rscript validations/02-scenarios/run.R
CMP_PARASITE=pv CMP_FLEET_ONLY=1 Rscript validations/02-scenarios/run.R
CMP_PARASITE=pv Rscript validations/02-scenarios/assess.R

The speed and speed-pv tables time both models side by side, one run of each, alone on one core. Run them on an otherwise idle machine:

Rscript validations/02-scenarios/speed.R                   # about 15 min: results/speed.csv, vignettes/tab_speed.md
CMP_PARASITE=pv Rscript validations/02-scenarios/speed.R   # about 25 min: results/pv/speed.csv, vignettes/tab_speed_pv.md

The figures and tables are redrawn from the committed results in seconds, without running a model:

Rscript validations/02-scenarios/render.R      # cmp_*.png into man/figures/ and vignettes/
Rscript validations/02-scenarios/tables.R      # validations/02-scenarios/results/tables.md
Rscript validations/02-scenarios/render_pv.R   # the vivax figures, cmp_pv_*.png
Rscript validations/02-scenarios/tables_pv.R   # validations/02-scenarios/results/pv/tables.md

Neither pair redraws its site-file panel, which is a snapshot of tier-3 results that cannot be repeated without the site files. CMP_REFRESH_SITES=1 re-takes the snapshot from the tier-3 results in validations/03-real-settings/results/raw/.

Seed stability and parameter draws

validations/01-seed-stability/run.R reproduces seed-stability and seed-stability-pv in a few minutes, running fleet only, and writes results/seed_stability.json and results/seed_stability_pv.json.

validations/04-parameter-draws/ is also tier 2: eight of set_parameter_draw()’s posterior draws at three EIRs, for parameter-draws. select.R chooses the draws. run.R runs both models, in about two hours on four workers; assess.R re-runs fleet alone against the committed IBM rows; render.R draws the figure. diagnose.R tests what moves the severe-incidence gap, with 40 IBM runs in about fifteen minutes.

Rscript validations/01-seed-stability/run.R
Rscript validations/04-parameter-draws/run.R
Rscript validations/04-parameter-draws/assess.R
Rscript validations/04-parameter-draws/render.R
Rscript validations/04-parameter-draws/diagnose.R

Site-file comparison

Tier 3 runs from this repository given the malariaverse site files, located by FLEET_VALIDATE:

FLEET_VALIDATE=/path/to/site-files Rscript validations/03-real-settings/run.R
Rscript validations/03-real-settings/assess.R

The P. vivax arm is the same pair under CMP_PARASITE=pv, with results in validations/03-real-settings/results/pv/. A vivax run of fleet costs about thirteen times a falciparum one, so each country is represented by at most ten sub-sites, spread evenly across its vivax EIR range. diagnose.R draws every sub-site’s monthly clinical series, IBM against fleet, as a PDF for investigating where they disagree; its output is not committed.

With a single site file, example-one-site.R runs the same pipeline on one sub-site in about two minutes: it subsets the site file, converts ITN usage to a distribution, builds the parameter list, seeds both models from it, reduces both through postie, and scores them with the same agreement() the register uses. One sub-site against one IBM replicate shows that the pipeline runs; it is not evidence about the model, so read the shape of the output rather than its third decimal. validations/03-real-settings/README.md describes each step and the details that matter.

FLEET_VALIDATE=/path/to/fleet_validate Rscript validations/03-real-settings/example-one-site.R BFA

Updating the register

Edit claims.yml (the criterion, the measured value, the verdict), then regenerate its rendered copies:

Rscript report/make_scoreboard.R

This rewrites the register list and badges in README.md, pkgdown/index.md (generated from README.md) and inst/claims.yml. Do not edit those copies by hand: CI runs the same script with --check and fails if they do not match. The evidence articles read claims.yml when the site is built:

Rscript -e 'pkgdown::build_site()'

Environment variables

Variable Effect
CMP_PARASITE=pv run the P. vivax suite, or the vivax arm of tier 3, instead of P. falciparum
CMP_SMOKE=1 4-year, one-replicate end-to-end check, written to results/smoke/
CMP_ONLY=a,b run or check only these scenarios (countries in tier 3), merging into the existing results
CMP_FLEET_ONLY=1 re-run fleet’s rows only, keeping the committed IBM rows
CMP_STRICT=1 make assess.R fail on any movement, not only on lost agreement
CMP_WORKERS worker pool size for run.R (default 10 in 02-scenarios, 4 in 04-parameter-draws)
CMP_REFRESH_SITES=1 re-take the site-file snapshot behind the tier-3 figure panels and tables
FLEET_VALIDATE location of the site files; required by the tier-3 sweep, and ../fleet_validate, beside the checkout, by default elsewhere
FLEET_LIB library path prepended to .libPaths(), for installations that do not pick up R_LIBS_USER
FLEETCHECK_ROOT the checkout root, for a job that runs from outside it