Skip to content

Milestone 0: Rwanda district-level VCI smoke test - #65

Draft
goldingn wants to merge 15 commits into
mainfrom
iss45-milestone-0-smoke-test
Draft

Milestone 0: Rwanda district-level VCI smoke test#65
goldingn wants to merge 15 commits into
mainfrom
iss45-milestone-0-smoke-test

Conversation

@goldingn

@goldingn goldingn commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🤖 Posted by Claude (Opus 4.8), an AI coding agent, from the @goldingn account — not written by a human. Why.

Milestone 0: the first end-to-end run of the package — a district-level VCI
smoke test for Rwanda
, built (per DESIGN.md §14) to shake out architecture and
integration problems before the science is signed off. It computes vector control
impact across Rwanda's 30 GADM admin-2 districts for three scenarios: no
intervention
(reference), business-as-usual (current net use, all pyrethroid
LLIN), and an alternative (the same use, all dual-AI LLIN).

Illustrative only. Ballpark parameters and a clearly-labelled intervention
stub — the outputs are not a real analysis, and every surface says so.

The kernel is pure base R (zero runtime Imports); sf/terra/geodata and
ggplot2/patchwork are Suggests, used only in data-raw/ and the vignette.
devtools::check() is clean: 0 errors, 0 warnings, 0 notes; 93 test
assertions plus a pinned integration snapshot.

The eight commits are thematic and dependency-ordered: scaffolding → capacity
kernel → host-choice + intervention stub → input contract → dataset → pipeline →
vignette + integration test → session log.

How this was produced

  • Issue: Milestone 0: minimal working example (district-level VCI smoke test) #45 (and the Refine Rwanda smoke test example #64 refinement)
  • Core prompt(s): build the Milestone 0 smoke test — Rwanda, admin-2, pyrethroid
    vs dual-AI LLIN, three scenarios; test-first kernel following the maths spec;
    prepare district inputs in data-raw/ from provided Africa rasters; a vignette
    with clean ggplot2/sf figures of the inputs and of capacity/VCI.
  • Key decisions / trade-offs:
  • New dependencies (all Suggests, none at runtime): sf, terra, geodata
    (data prep); ggplot2, patchwork (vignette figures); knitr, rmarkdown
    (vignette builder). patchwork was flagged and approved.
  • Session log: dev/sessions/2026-07-24-54f0b094-iss45-milestone-0-smoke-test.md

Fixes #45
Fixes #64

🤖 Generated with Claude Code

goldingn and others added 15 commits July 24, 2026 17:15
Create the R package skeleton with usethis: DESCRIPTION, MIT licence,
NEWS, package-level docs, and testthat (3rd edition) infrastructure. Add the
formatting/linting toolchain (Air config, .lintr deferring line-width and
indentation to Air) and the build/ignore rules that keep dev files out of the
built package.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Implement the core equations, test-first: vectorial_capacity() (the
species-specific Garrett-Jones form, maths spec section 1), sum_species()
(aggregation across species, section 18), and compute_vci() (the reference-vs-
alternative scenario comparison, section 19), plus small internal input
validators. Tests encode the section 10.1 scientific invariants (zero abundance
gives zero capacity, monotonicity, identical-scenario VCI of zero, ...).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Implement the intervention-dependent stage (maths spec sections 15-17):
host_destination() redistributes feeding attempts under repellency,
successful_feeding_rate() and mortality_hazard() assemble the realised feeding
rate and survival, and survival_probability() converts hazard to survival.
intervention_effect_stub() maps product/coverage/susceptibility to the (R, B, K)
channels -- a deliberately crude, clearly-labelled placeholder (not issue #17),
capturing only that pyrethroid killing collapses with resistance while dual-AI
killing does not.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
vci_inputs() constructs and validates the minimal Milestone 0 input object
(DESIGN.md section 7): three keyed tables (per-district-species abundance,
per-species bionomics, per-district intervention context) plus optional
geometry, with a print method. Validation is strict and non-imputing -- required
columns, value ranges, no missing data (section 7.4), and referential
integrity between the tables.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
data-raw/rwanda_inputs.R builds rwanda_inputs from GADM admin-2 boundaries and
cached Africa rasters (abundance, pyrethroid susceptibility, 2024 net use),
attaching malariasimulation bionomics and ballpark stub parameters. The abundance
layer (proportional to the biting rate m*a) is divided by the feeding rate to
recover adults per human m. Host-opportunity weights use an explicit, documented
equal-availability assumption (issues #13, #16). Source rasters are git-ignored;
the small derived object is committed for a deterministic example.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
compute_capacity() runs the whole pipeline (intervention stub, host choice,
survival, capacity equation, species sum) for each scenario, returning tidy
per-district capacity; vci_by_scenario() turns those capacities into vector
control impact against a named reference. Together they express the three
Milestone 0 scenarios: no intervention, pyrethroid BAU, and dual-AI alternative.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
The vignette (vignette("rwanda-smoke-test")) runs the three scenarios end to
end and maps the inputs (per-species abundance, LLIN use, susceptibility) and
results (capacity and VCI), with a prominent illustrative-only banner. The
integration test pins the run on the committed rwanda_inputs: the DoD invariants
(reference VCI of zero, BAU in (0,1), dual-AI at least pyrethroid, invariance to
abundance) plus a snapshot of district VCI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Auto-generated Claude Code session log capturing the prompts behind this branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
biting_rate() and eip() are simple mechanistic Briere thermal responses (the
An. gambiae fits from Mordecai et al. 2013, as used by Villena et al. 2022): the
biting rate peaks near the thermal optimum and falls to zero at the limits, and
the EIP is shortest near the optimum and lengthens (to infinity outside the
parasite-development range) as it cools. These map the two temperature-sensitive
Garrett-Jones parameters across space from a temperature layer.

Refs #64

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Move the biting rate and EIP out of the (constant) bionomics and derive them,
per district, from a WorldClim annual-mean-temperature layer added to the sites
table: compute_capacity() now computes them once via biting_rate()/eip(). This
fixes the smoke test's implausible moderate capacity in cool, high-altitude
districts (e.g. Burera, Musanze, Nyabihu in the north), which now show near-zero
capacity, matching the low malaria burden there. VCI stays invariant to absolute
abundance; the vignette gains a temperature map and the input maps are updated.

Fixes #64

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
The source species-abundance raster was updated to fix a bug. Rebuild
rwanda_inputs from it (via data-raw/rwanda_inputs.R): abundances are lower and
the species composition shifts, so the district capacities and the pinned VCI
snapshot change. Invariants and check remain clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
The species-abundance layers are relative, not on a daily-landing scale. Add a
single multiplicative calibration constant (~2.19) anchoring them to observed
24-h outdoor human landing rates from Msugupakulya et al. 2024 (Parasites &
Vectors, Table 2) in the Kilombero Valley. Calibrate on An. arabiensis (outdoor
0.72 bites/person/hour) rather than the endophilic An. funestus, whose outdoor
rate (~0.01/hour) is a poor anchor; the paper pools its two villages. As a single
uniform constant this rescales absolute vectorial capacity but leaves VCI (and
the pinned snapshot) unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8QmvZEJTz9b7uNfJZTy3n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refine Rwanda smoke test example Milestone 0: minimal working example (district-level VCI smoke test)

1 participant