Add headless CLI for batch simulation and outbreak statistics#3
Open
edwenger wants to merge 5 commits into
Open
Add headless CLI for batch simulation and outbreak statistics#3edwenger wants to merge 5 commits into
edwenger wants to merge 5 commits into
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
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.SimRngresource (entropy-seeded in interactive mode, deterministic seed in headless) with sorted HashMap iterations for full reproducibility.sweep.pyruns 10 seeds × 4 fecal-oral dose levels and plots weekly epidemic curves with seed-averaged overlays;transmission_tree.pyvisualizes infection chains as branching trees colored by contact level.Example outputs
Epidemic curves across fecal-oral dose sweep:

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

Test plan
cargo build --bin headlesscompilescargo build --bin bevy-multiscalestill compiles (interactive mode unchanged)cargo run --bin headless -- --config config/base_params.yaml --output /tmp/test.csvproduces valid CSVpython scripts/sweep.pyproduces overlay plotpython scripts/transmission_tree.py output/seed2_dose5e-05.csvproduces tree plot🤖 Generated with Claude Code