Skip to content

Add headless CLI for batch simulation and outbreak statistics#3

Open
edwenger wants to merge 5 commits into
mainfrom
outbreak-statistics
Open

Add headless CLI for batch simulation and outbreak statistics#3
edwenger wants to merge 5 commits into
mainfrom
outbreak-statistics

Conversation

@edwenger

Copy link
Copy Markdown
Owner

Summary

  • Headless CLI (src/bin/headless.rs): runs the same neighborhood-scale transmission model without rendering, accepts parameters via YAML, outputs transmission events to CSV. Enables batch parameter sweeps and reproducible outbreak analysis.
  • Seeded RNG: all stochastic systems now use a shared SimRng resource (entropy-seeded in interactive mode, deterministic seed in headless) with sorted HashMap iterations for full reproducibility.
  • Python analysis scripts: sweep.py runs 10 seeds × 4 fecal-oral dose levels and plots weekly epidemic curves with seed-averaged overlays; transmission_tree.py visualizes infection chains as branching trees colored by contact level.

Example outputs

Epidemic curves across fecal-oral dose sweep:
sweep

Transmission tree (seed=2, dose=5e-05):
tree

Test plan

  • cargo build --bin headless compiles
  • cargo build --bin bevy-multiscale still compiles (interactive mode unchanged)
  • cargo run --bin headless -- --config config/base_params.yaml --output /tmp/test.csv produces valid CSV
  • Same seed run twice → identical CSV output (reproducibility verified 5 runs)
  • python scripts/sweep.py produces overlay plot
  • python scripts/transmission_tree.py output/seed2_dose5e-05.csv produces tree plot

🤖 Generated with Claude Code

edwenger and others added 5 commits March 9, 2026 22:40
Enable parameter sweeps and outbreak analysis by adding a headless
entrypoint that runs the same transmission model without rendering.

Motivation: The interactive visualization is useful for understanding
dynamics but insufficient for statistical analysis. Batch runs across
parameter combinations (e.g. fecal-oral dose × random seeds) require
a fast, scriptable, reproducible simulation mode that outputs structured
transmission data.

Implementation:
- New `headless` binary (`src/bin/headless.rs`): accepts YAML config via
  clap, builds a Bevy app with MinimalPlugins (no window/rendering),
  spawns population without visual components, and outputs transmission
  events to CSV on completion.
- Seeded RNG (`SimRng` resource): wraps StdRng, always present in both
  modes — entropy-seeded for interactive, deterministic seed for headless.
  Threaded through all stochastic systems (transmission, campaigns,
  disease stepping) and immunity methods, replacing thread_rng() calls.
- Headless time stepping: bypasses real-time timer gating, advancing one
  simulation day per frame via reset+tick pattern.
- Transmission logging: `TransmissionLog` resource accumulates records
  with day, source/target IDs and ages, contact level, and strain.
  Written to CSV on stop condition (end_time reached or outbreak extinct).
- Deterministic ordering: sorted HashMap iterations in village transmission
  for reproducible contact sampling; all headless systems chained after
  the main simulation systems to prevent scheduler race conditions.
- Plugin resources changed from insert_resource to init_resource for
  TransmissionParams and PopulationConfig so the headless binary can
  pre-insert custom values without being overwritten by plugin defaults.
- YAML config (`config/base_params.yaml`) and Python sweep script
  (`scripts/sweep.py`) for running parameter combinations and plotting
  epidemic curves.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Expand parameter sweep to 10 seeds × 4 dose levels (1e-5, 2e-5, 5e-5,
1e-4) for 40 total runs. Aggregate transmissions per week instead of
per day. Plot faint individual traces with bold seed-averaged lines per
dose. Clip x-axis to the last week with any transmission activity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New `transmission_tree.py`: plots infection chains as a branching tree
  from a single simulation CSV, with elbow connectors colored by contact
  level and leaf nodes labeled by age. Handles re-infections by treating
  each transmission event as a unique node.
- New `scripts/README.md` with usage instructions and inline example
  figures for both the sweep plot and transmission tree.
- Example figures committed under `scripts/examples/`.
- Add `/output/` to `.gitignore` to exclude bulk simulation CSVs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Log source and target prechallenge_immunity (not post-boost current_immunity)
so recorded titers reflect the immunity that drove shedding profile (source)
and infection probability (target). Transmission tree nodes now use marker
shapes for titer terciles: squares (low), filled circles (mid), open circles
(high). All nodes labeled with age, not just leaves.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…stics (Stages 1-2)

Stage 1: Rust snapshot infrastructure — --snapshot-dir CLI flag emits
population_initial.csv and population_final.csv with per-individual
immunity, shedding, strain, and household/neighborhood membership.

Stage 2: Python analytical toolkit — disease_model.py ports key formulas
(infection probability, peak shedding, shed duration, NGM with household
structure), outbreak_stats.py computes empirical + analytical metrics,
and diagnostic scripts generate 9 review figures covering population
structure, model validation, snapshot consistency, NGM decomposition,
R0 landscape, and bridging analysis across immunity scenarios.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant