Four cocirculating dengue serotypes with per-agent history tracking and antibody-dependent enhancement (ADE), on a spatial 5×5 grid with vital dynamics. Reproduces the empirically observed serotype rotation pattern: each serotype dominates for a period, then another takes over.
Status: prototype; not calibrated to any real-world dataset. Parameters were chosen from published dengue literature (Wearing-Rohani 2006, Ferguson 1999, Adams 2006, Reich 2013), then subjected to a 1D per-parameter sensitivity sweep — see
sensitivity/SENSITIVITY.md.
Four cocirculating dengue serotypes with per-agent history tracking and antibody-dependent enhancement (ADE) reproduce the empirically observed "serotype rotation" pattern.
Per-agent state:
history(uint8) — bitmask of past serotype exposures (bit k = had DENVk+1)current_st(int8) — serotype currently active in E or I (-1 if none)is_secondary(uint8) — 1 if this infection is at least the second distinct-serotype exposure
Transmission dynamics (per serotype k):
λ_k(t) = β · seas(t) · (IPrim_k + φ · ISec_k) / N
IPrim_k = count of DENV-k infections in previously naïve hosts.
ISec_k = count of DENV-k infections in hosts with prior heterotypic exposure.
Secondary infections are φ=2× more infectious (ADE).
Once infected with DENV-k, an agent goes E → I → R. In R, cross-protection against all four serotypes decays over ~CROSS_IMMUNITY_DAYS. On waning, the agent returns to S — but their history mask permanently excludes DENV-k. Four exposures → superimmune.
Real-geography demonstration on Laos' 18 admin-1 units (17 provinces plus the Vientiane Prefecture). Boundaries come from GADM and populations from WorldPop 2020 via the laser-init microservices; the cached responses ship under laser_dengue/data/laos/ so the runner works fully offline.
All 4 DENV serotypes cocirculate in the Greater Mekong Subregion (Wangdi et al 2019). The central-south Mekong corridor (Vientiane → Savannakhét → Champasak) is the highest-burden zone; northern mountainous provinces are lower burden but not free of transmission. Serotypes are staggered across four corridor provinces in year 1, matching the historical pattern in which each serotype tends to enter via a different border crossing / trade route. Not calibrated to Laos-specific case data.
Six panels: per-serotype aggregate active-I over time; total-N growth; per-serotype daily incidence (90-day smoothed, log-y); cumulative-infections-per-capita choropleth at end; dominant-serotype-per-province choropleth at end; host-exposure histogram (fraction of living hosts with 0/1/2/3/4 distinct serotypes in history).
Animations:
Runtime is heavier than the synthetic grid — ~15-20 min for a full 20-year Laos run at 7.27M agents.
Same model on a synthetic 5×5 grid. Useful for isolating rotation dynamics without the confound of real-geography population imbalances.
Cummings et al 2009 documented multi-year serotype rotation in Thailand from 1980 to 2000, with each serotype dominant for 2-6 years. The simulation shows the same qualitative pattern; the sensitivity analysis quantifies which parameters most control rotation frequency, coexistence, and secondary-infection burden.
pip install .[geo] # Laos runner needs geopandas + shapely + requests
python -c "from laser_dengue.run_laos import run_laos; r = run_laos({'YEARS': 3}, verbose=True); print(len(r['scenario']))"Or as scripts:
laser-dengue-laos --years 20 --out out_laos.png # real Laos geography (~15-20 min)
laser-dengue --years 20 --seed 42 # synthetic 5×5 gridfrom laser_dengue import DEFAULTS, run_model, metrics
result = run_model(overrides={"PHI_ADE": 2.5, "YEARS": 30}, verbose=True)
model = result["model"] # laser-generic Model instance
print(metrics(result))Unknown keys in overrides raise KeyError early. metrics extracts six outcome scalars used by the sensitivity harness: rotation-transition count, all-4-serotype coexistence-year fraction, secondary-infection fraction over the last 5 years, endemic prevalence at the final tick, superimmune-host fraction, and final total N.
From published dengue literature; not calibrated to any specific dataset. See sensitivity/SENSITIVITY.md for the per-parameter perturbation study.
| symbol | value | source / justification |
|---|---|---|
| R0_PRIMARY | 2.5 | Wearing-Rohani 2006 |
| PHI_ADE | 2.0 | Ferguson 1999; Adams 2006 report 1.5-3× |
| EXP_SCALE_DAYS | 5 d | E period (incubation); Wearing-Rohani 2006 |
| INF_SCALE_DAYS | 5 d | I period (viremic); Wearing-Rohani 2006 |
| CROSS_IMMUNITY_DAYS | 200 d | Reich et al 2013 (2 yr in some, less in others) |
| SEASONALITY_AMP | 0.35 | annual sinusoid; Adams 2006 |
| BACKGROUND_COUNT | 3 | cases per background-import event (random serotype); numerical hack that prevents stochastic extinction |
| BACKGROUND_PERIOD | 90 d | period between background-import events |
| CBR | 22/1000/yr | dengue-endemic tropics |
| CDR | 8/1000/yr | net +1.4%/yr population growth |
| GRID_M × GRID_N | 5×5 = 25 patches | urban core (40k), ring (15k each), rural periphery (4k each) |
| YEARS | 40 | enough to see rotation stabilize |
| SEED | 20260710 |
A 1D per-parameter perturbation study (±30% around each science parameter, three stochastic seeds per cell, 20-year sims) landed alongside this repo — see sensitivity/SENSITIVITY.md for the tornado charts and per-parameter interpretation. Rerun the sweep with:
python -m sensitivity.sensitivity --years 20 --seeds 3 --workers 1
python -m sensitivity.make_tornado- Per-agent state is essential. Compartmental dengue models need to track the joint distribution over exposure histories: 2⁴ = 16 compartments per serotype (susceptible, monotypic-immune to k, etc.), × 4 SEIR states, × 25 patches = 2 000 compartments. The ABM carries the 4-bit history in a single uint8.
- Serotype replacement dynamics are a real observation. Cummings et al 2009 documented multi-year serotype rotation in Thailand from 1980 to 2000, with each serotype dominant for 2-6 years.
- ADE as a transmission multiplier — the "vertical" ADE hypothesis (Ferguson 1999). The alternative ("severity" ADE, where φ only affects DHF outcome not transmission) doesn't produce rotation as easily. Adams et al 2006 argued for transmission-side ADE from Thai case-notification data.
- Vital dynamics are load-bearing. A single-node closed-population version burns out by year 10; adding births refills the susceptible pool for serotypes that had run out and lets rotation persist indefinitely.
- DHF risk tracking — every secondary infection has ~3-5× higher risk of Dengue Hemorrhagic Fever; track a hospitalization/mortality counter over
is_secondary==1transitions. - Vector compartment (mosquitoes) — replace β with a two-population coupling; humans⇔mosquitoes, mosquito EIP ~10 days, lifespan ~14 days. See Ferguson 1999 for the full Ross-Macdonald form.
- Vaccination (Dengvaxia-style) — asymmetric efficacy: high in seropositives, low or negative in seronegatives. Requires per-agent vaccine-status × history-bitmask interaction.
- More country runners — the Laos runner is a template. Adding e.g. Thailand (THA), Vietnam (VNM), or Cambodia (KHM) at admin-1 is a
_laser_init.load_real_scenario("<ISO>", level=1, year=2020)call plus settingSEED_SCHEDULEto the country's likely-introduction corridor.
- Ferguson NM, Anderson RM, Gupta S. 1999. The effect of antibody-dependent enhancement on the transmission dynamics and persistence of multiple-strain pathogens. Phil Trans R Soc B 354:757-768.
- Adams B et al. 2006. Cross-protective immunity can account for the alternating epidemic pattern of dengue virus serotypes circulating in Bangkok. PNAS 103:14234-14239.
- Wearing HJ, Rohani P. 2006. Ecological and immunological determinants of dengue epidemics. PNAS 103:11802-11807.
- Cummings DA et al. 2009. The impact of the demographic transition on dengue in Thailand. PLoS Med 6:e1000139.
- Reich NG et al. 2013. Interactions between serotypes of dengue. J R Soc Interface 10:20130414.
additional_states=["E0","I0","IPrim0","ISec0", ..., "ISec3"]registers 16 extra per-node vector properties so_initialize_flowspropagatesX[t] → X[t+1]for each. Missing this step is the bug the fork's author hit first — per-tick delta updates get overwritten and transmission never takes off.DengueTransmissioniterates over serotypes in random order each tick to avoid biasing which serotype "wins" if two would happen to hit the same agent on the same tick.- The
SerotypeImportationcomponent supports both a fixed schedule (initial seeding) and continuous background importation to prevent stochastic extinction of low-prevalence serotypes. - Cross-protection is stored per-agent as
rtimer(uint16). Agents whose cross-protection wanes but who have all 4 serotypes inhistorystay in R permanently — checked inDengueWaning.step. DengueSerotypeAwareMortalitywraps laser-generic'sMortalityByCDRto snapshot per-agentcurrent_st/is_secondarybefore mortality runs, then patch per-serotype compartments (E{k},I{k},IPrim{k},ISec{k}) so the sub-compartments stay consistent when infected agents die.

