What it simulates
epydemix simulates an epidemic as a chain of random transitions between compartments such as S (susceptible), I (infectious) and R (recovered). Each simulated day, every compartment sends a random number of people to the next one. Repeating the run many times gives a spread of outcomes instead of a single curve.
The package also handles age groups, contact matrices, interventions and fitting to data (approximate Bayesian computation). The biosimhub example uses the simplest case: one well-mixed population and an SIR or SEIR model.
The key assumptions are random mixing and a fixed time step. In the 1.3.2 source, run_simulations takes dt in days with a default of 1. Transition probabilities are the rate times dt, and the people who move are drawn from a multinomial distribution. Rates stay constant over the run.
Input is a model, a start and end date and the number of runs. Output is a table of compartment sizes per day and per quantile.
When to use it
- You want the range of outcomes of an outbreak, for example the 5th and 95th percentile of the peak size, in a population of 100,000.
- You want to compare R0, infectious period or latent period and see how the peak date moves.
- You plan to add age structure, interventions or calibration to data later.
GillesPy2 on biosimhub fits when you need an exact event-by-event simulation of any reaction network, or when you want to choose the solver. NetLogo Web (the Virus model) fits when you want individuals that move in space. Use the webR page when you want SimInf or adaptivetau and an R workflow.
Install it yourself
Pinned to 1.3.2 (conda-forge, checked with a micromamba dry run, 162 MB of downloads):
micromamba create -n epx -c conda-forge epydemix=1.3.2
micromamba activate epx
The project documents pip install epydemix, and pip install epydemix[numba] for a faster stochastic loop.
Minimal script with the Python API, an SIR model with a fixed seed (run in the recipe's 1.3.2 image):
from epydemix import EpiModel
model = EpiModel(name="SIR", compartments=["S", "I", "R"], default_population_size=100000)
model.add_parameter("beta", 0.4)
model.add_parameter("gamma", 0.2)
model.add_transition("S", "I", params=("beta", "I"), kind="mediated")
model.add_transition("I", "R", params="gamma", kind="spontaneous")
res = model.run_simulations(start_date="2024-01-01", end_date="2024-04-10",
Nsim=20, percentage_in_agents=0.0005, rng=42)
q = res.get_quantiles_compartments(quantiles=[0.05, 0.5, 0.95])
This run gave a median of 13,143.5 infectious people on 2024-01-31 and 17.5 on 2024-04-10. The table q has 303 rows: 101 dates times 3 quantiles.