Skip to main content

library.diseases

library.diseases

Example disease models: cholera, COVID, dengue, Ebola, gonorrhea, HIV, influenza, malaria, measles, pertussis, polio, RSV, syphilis, TB, typhoid, and a non-communicable disease (NCD), and Starsim 3’s SIR, SEIR, and SIS written as agent-based code.

These are illustrative, lightly-parameterized models intended as starting points for building your own disease modules, not as validated models for any specific setting. Each one says in its docstring where its structure and its default parameters came from. Core disease base classes (ss.Disease, ss.AgentDisease, ss.SIR, etc.) live in starsim.diseases.

Classes

Name Description
ART Antiretroviral therapy, delivered as ss.treat() delivers a treatment
AgentSEIR An SEIR model written as agent-based code rather than declared: Starsim 3’s ss.SEIR
AgentSIR An SIR model written as code: Starsim 3’s ss.SIR
AgentSIS An SIS model with waning immunity, written as code: Starsim 3’s ss.SIS (see ssl.AgentSIR), with its lognormal dur_inf
CD4_analyzer Record the CD4 count of every agent at every timestep.
COVID COVID-19, as a SECIR model by age: a chain of increasingly severe states, each of which some people leave by recovering
Cholera Cholera, with both direct and environmental (waterborne) transmission
Dengue Dengue: several serotypes, each passed on by mosquitoes, with partial cross-protection between them
DengueSerotype One dengue serotype: people are susceptible, infectious, or recovered, with mosquitoes of its own
Ebola Ebola, including severe disease and transmission from unburied bodies
Gonorrhea Gonorrhea, as an SIS model on a sexual network
HIV Simple HIV model with CD4 count dynamics and ART.
Influenza Seasonal influenza, as a SEIRS model with a yearly cycle in transmission
Malaria Malaria as the Ross-Macdonald model of humans and mosquitoes
MalariaImmunity Malaria with immunity, as the Garki model
Measles Measles, as an SEIR model with deaths
NCD Example non-communicable disease
Pertussis Pertussis (whooping cough), as a SEIRS model with slowly waning immunity
Polio Poliovirus, with a paralytic fraction
RSV Respiratory syncytial virus (RSV), as a seasonal MSEIRS model
Syphilis Syphilis, as a staged infection, wholly declared
TB Tuberculosis, as the LSHTM model of the spectrum of TB disease
Typhoid Typhoid fever, with chronic carriers

ART

library.diseases.ART(
    coverage=1.0,
    who=None,
    when=None,
    art_delay=ss.years(1),
    name=None,
    **kwargs,
)

Antiretroviral therapy, delivered as ss.treat() delivers a treatment

By default, ART is offered once to each person who has been infected with HIV for art_delay and is not on it, with the probability coverage; who= restricts who among them is offered it, and when= when, as for any delivery (see ss.Delivery). The people treated are on ART for good: their CD4 count recovers, and they are less infectious (see HIV). Requires the HIV module.

Note: CRN safe.

Parameters

Name Type Description Default
coverage float / timeseries the probability that each person eligible starts ART, e.g. scaled up over time with ss.timeseries({2000: 0, 2020: 0.8}, 'linear') 1.0
who Cond / func who among the people eligible is offered it (e.g. ss.person.female) None
when various when it is offered, as for any delivery (default: on every step, once to each person when they become eligible) None
art_delay dur the time from infection to being eligible ss.years(1)
kwargs dict passed to ss.Delivery (e.g. capacity=, name=)

Examples

import starsim as ss
import starsim.library as ssl

art = ssl.ART(coverage=ss.timeseries({2000: 0, 2010: 0.4, 2020: 0.8}, 'linear'))

Methods

Name Description
eligible The people infected for at least art_delay who are not on ART
eligible
library.diseases.ART.eligible(sim)

The people infected for at least art_delay who are not on ART

AgentSEIR

library.diseases.AgentSEIR(pars=None, dur_exp=_, **kwargs)

An SEIR model written as agent-based code rather than declared: Starsim 3’s ss.SEIR (see ssl.AgentSIR), with its lognormal dur_exp and dur_inf and p_death=0.01.

This class extends AgentSIR with an exposed state: agents who are infected but not yet infectious. exposed and infectious are the literal E and I compartments, and infected is derived from them: an agent is infected from the moment it acquires the infection, whether or not it is yet transmitting. So infected and prevalence count E plus I, while transmission depends on infectious alone.

Correspondingly, ti_exposed is the time of acquisition and ti_infectious is the time of becoming infectious. ti_infected is deliberately not defined, since it is too easily confused with ti_infectious.

Note: CRN safe.

Parameters

Name Type Description Default
beta float/ss.prob the infectiousness
init_prev float/ss.bernoulli the fraction of people to start off being infected
dur_exp float/ss.Duration/ss.Dist how long people are exposed (latent) for _
dur_inf float/ss.Duration/ss.Dist how long people are infectious for
p_death float/ss.bernoulli the probability of death from infection

Methods

Name Description
clear_infection infected is derived, so clear the states it is derived from
not_naive The agents who have ever been infected, for dynamic rescaling
set_infection Agents are exposed first, and become infectious after the latent period
set_progression Schedule recovery or death, relative to the end of the latent period
step_state Progress exposed -> infectious, then the usual SIR transitions
clear_infection
library.diseases.AgentSEIR.clear_infection(uids)

infected is derived, so clear the states it is derived from

not_naive
library.diseases.AgentSEIR.not_naive()

The agents who have ever been infected, for dynamic rescaling

set_infection
library.diseases.AgentSEIR.set_infection(uids)

Agents are exposed first, and become infectious after the latent period

set_progression
library.diseases.AgentSEIR.set_progression(uids)

Schedule recovery or death, relative to the end of the latent period

step_state
library.diseases.AgentSEIR.step_state()

Progress exposed -> infectious, then the usual SIR transitions

AgentSIR

library.diseases.AgentSIR(
    pars=None,
    beta=_,
    init_prev=_,
    dur_inf=_,
    p_death=_,
    **kwargs,
)

An SIR model written as code: Starsim 3’s ss.SIR

This class implements a basic SIR model with states for susceptible, infected/infectious, and recovered, as per-agent arrays updated in code (see ss.AgentDisease). It also includes deaths, and basic results. It is a teaching example, showing in code what the declared ss.SIR does as agents, and a starting point for a disease written as code (e.g. ssl.HIV).

Its defaults are Starsim 3’s: a lognormal dur_inf (a mean of 6 years, std 1 year) and p_death=0.01, where the declared ss.SIR is the textbook SIR, with an exponential dur_inf and no deaths. Use it to keep a Starsim 3 model’s parameters; its timing is the agent engine’s (see above), so each case is infectious for half a step longer on average than in Starsim 3.

Note: CRN safe.

Parameters

Name Type Description Default
beta float/ss.prob the infectiousness _
init_prev float/ss.bernoulli the fraction of people to start off being infected _
dur_inf float/ss.Duration/ss.Dist how long (in years) people are infected for _
p_death float/ss.bernoulli the probability of death from infection _

Methods

Name Description
clear_infection Clear the infection states, on recovery or death (AgentSEIR overrides this, since its infected is derived)
on_death Reset infected/recovered flags for dead agents
plot Default plot for SIR model
set_infection Make the agents infectious, immediately (AgentSEIR overrides this to add a latent period)
set_prognoses Infect the agents, then schedule what happens to them
set_progression Schedule recovery or death, relative to when each agent becomes infectious
clear_infection
library.diseases.AgentSIR.clear_infection(uids)

Clear the infection states, on recovery or death (AgentSEIR overrides this, since its infected is derived)

on_death
library.diseases.AgentSIR.on_death(uids)

Reset infected/recovered flags for dead agents

plot
library.diseases.AgentSIR.plot(**kwargs)

Default plot for SIR model

set_infection
library.diseases.AgentSIR.set_infection(uids)

Make the agents infectious, immediately (AgentSEIR overrides this to add a latent period)

set_prognoses
library.diseases.AgentSIR.set_prognoses(uids, sources=None)

Infect the agents, then schedule what happens to them

set_progression
library.diseases.AgentSIR.set_progression(uids)

Schedule recovery or death, relative to when each agent becomes infectious

AgentSIS

library.diseases.AgentSIS(
    pars=None,
    beta=_,
    init_prev=_,
    dur_inf=_,
    waning=_,
    imm_boost=_,
    **kwargs,
)

An SIS model with waning immunity, written as code: Starsim 3’s ss.SIS (see ssl.AgentSIR), with its lognormal dur_inf

This class implements a basic SIS model with states for susceptible, infected/infectious, and back to susceptible, with a per-agent immunity level that is boosted by each infection and wanes exponentially, which sets each agent’s rel_sus. There is no death in this case. For an SIS model without immunity, use the declared ss.SIS, which runs with every solver.

Note: CRN safe.

Parameters

Name Type Description Default
beta float/ss.prob the infectiousness _
init_prev float/ss.bernoulli the fraction of people to start off being infected _
dur_inf float/ss.Duration/ss.Dist how long (in years) people are infected for _
waning float/ss.per how quickly immunity wanes _
imm_boost float how much an infection boosts immunity _

Methods

Name Description
clear_infection Clear the infection, on recovery or cure (e.g. by ss.treat()): the agents are susceptible again
init_results As for ss.AgentDisease, and the mean susceptibility
make_naive Reset agents to never having had the disease, for dynamic rescaling: every state to its default (rel_sus too, since SIS sets it from its own immunity), except rel_trans
plot Default plot for SIS model
record_states As for ss.AgentDisease, and the population immunity (susceptibility), at the start of the step
set_prognoses Infect the agents, at the end of this step, and schedule their recovery
step_state Progress infectious -> recovered
update_immunity Apply exponential waning to immunity and update relative susceptibility.
clear_infection
library.diseases.AgentSIS.clear_infection(uids)

Clear the infection, on recovery or cure (e.g. by ss.treat()): the agents are susceptible again

init_results
library.diseases.AgentSIS.init_results()

As for ss.AgentDisease, and the mean susceptibility

make_naive
library.diseases.AgentSIS.make_naive(uids)

Reset agents to never having had the disease, for dynamic rescaling: every state to its default (rel_sus too, since SIS sets it from its own immunity), except rel_trans

plot
library.diseases.AgentSIS.plot(**kwargs)

Default plot for SIS model

record_states
library.diseases.AgentSIS.record_states()

As for ss.AgentDisease, and the population immunity (susceptibility), at the start of the step

set_prognoses
library.diseases.AgentSIS.set_prognoses(uids, sources=None)

Infect the agents, at the end of this step, and schedule their recovery

step_state
library.diseases.AgentSIS.step_state()

Progress infectious -> recovered

update_immunity
library.diseases.AgentSIS.update_immunity()

Apply exponential waning to immunity and update relative susceptibility.

CD4_analyzer

library.diseases.CD4_analyzer(**kwargs)

Record the CD4 count of every agent at every timestep.

Results are stored in self.cd4, a (timesteps × agents) array. Requires the HIV module. Note that this analyzer allocates a full dense array, so it is best suited to small simulations.

Note: CRN safe.

COVID

library.diseases.COVID(ages=True, **kwargs)

COVID-19, as a SECIR model by age: a chain of increasingly severe states, each of which some people leave by recovering

People who are infected are exposed (E), then infected without symptoms (INS), and then either recover or develop symptoms (ISy); of those, some become severe (ISev, in hospital), then critical (ICr, in intensive care), and some of those die. People without symptoms and with symptoms are both infectious, at rel_ins and rel_sym of the transmission rate.

The disease is stratified by age into MEmilio’s six groups (0-4, 5-14, 15-34, 35-59, 60-79, and 80+), since the severity of COVID-19 rises steeply with age: in the oldest group, a symptomatic case is 30 times as likely to become severe as in a child, and a critical one 12 times as likely to die. The fraction of people in each group is the world’s, unless the sim’s population says otherwise (e.g. people=ss.population('Germany')).

Source: the values for Germany of MEmilio (Kühn MJ et al., Mathematical Biosciences 2021, https://doi.org/10.1016/j.mbs.2021.108648; examples/ode_secir_parameter_study_graph.cpp), which gives each as a range, by age; each default here is the middle of its range. MEmilio’s transmission is a contact rate times a chance of infection per contact, which is 0.06 for adults and from 0.03 (under 5) to 0.175 (80 and over), here the relative susceptibility rel_sus (1 for adults). Without contacts given, beta is 1 a day, which with the world’s ages gives an R0 of about 3.2, as for the first strains of COVID-19. With a contact matrix, beta is per contact, and MEmilio’s is 0.06: ssl.COVID(beta=0.06) with networks=ss.contacts('Germany').

With ages=False, the model has one group, with the values of MEmilio’s simple example (ode_secir_simple.cpp), whose beta of 1 a day is one contact a day, each certain to infect; with people infectious at rel_ins for 2 days and at rel_sym for 6, this gives an R0 of about 2.7.

Note: CRN safe as agents.

Parameters

Name Type Description Default
ages bool if True (the default), stratify by age, with the values for each age group; if False, one group True
beta ss.per the transmission rate: the rate at which someone fully infectious infects others, as contacts a day times the chance that each infects (per contact, with a network)
rel_sus float/ss.by the susceptibility of each age group, relative to adults’
rel_ins float the infectiousness of people without symptoms, relative to beta
rel_sym float the infectiousness of people with symptoms, relative to beta
dur_exp ss.Duration the mean time from infection to being infectious
dur_ins ss.Duration the mean time without symptoms
dur_sym ss.Duration/ss.by the mean time with symptoms
dur_sev ss.Duration/ss.by the mean time with severe disease
dur_crit ss.Duration/ss.by the mean time with critical disease
p_sym float/ss.by the fraction of people without symptoms who go on to have symptoms
p_sev float/ss.by the fraction of people with symptoms whose disease becomes severe
p_crit float/ss.by the fraction of severe cases that become critical
p_death float/ss.by the fraction of critical cases who die
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.COVID(), total_pop=83_000, unit='day', stop=100)
sim.run()
sim.covid.plot()
sim.results.covid.outcome.select(to='dead').by('age').plot() # Deaths by age

# With Germany's ages and contacts, and MEmilio's chance of infection per contact
sim = ss.Sim(diseases=ssl.COVID(beta=0.06), networks=ss.contacts('Germany'), people=ss.population('Germany'), total_pop=83_000, unit='day', stop=200)

Cholera

library.diseases.Cholera(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Cholera, with both direct and environmental (waterborne) transmission

People infected are latent (E) for dur_exp, then a fraction p_symp become symptomatic (Is), and the rest are asymptomatic (Ia), shedding far less (asymp_trans). Asymptomatic people recover; symptomatic people recover, or die (with probability p_death, sooner). Besides transmission from person to person (beta), infectious people shed bacteria into a well-mixed reservoir of water (W, a count of bacteria, not people) at shedding_rate, the bacteria die off at decay_rate, and susceptible people are infected from the water at a rate that rises with the concentration, beta_env times env_conc = W/(W + half_sat_rate), as in the model of Codeço (2001). It is declared, so it runs under any solver.

Sources: Codeço CT, “Endemic and epidemic dynamics of cholera: the role of the aquatic reservoir”, BMC Infect Dis 2001;1:1 (https://doi.org/10.1186/1471-2334-1-1), for the structure; the latent period is from Azman et al. (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3677557/), a lognormal; asymptomatic shedding of 1 to 10 days (uniform) from the WHO fact sheet; 5 days of symptoms (a lognormal fit to the range of 2.9 to 14 days) from Fung (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3926264/); a rapid death of severe cases (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5767916/); half of infections symptomatic, mid range of Jackson et al. and Nelson et al.; asymptomatic carriers shedding 100 times less; the dose-response, shedding, and decay from Mukandavire et al. (https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3102413/). beta (from person to person) and beta_env are illustrative. Since the bacteria are a count, shed by everyone infectious into one reservoir, the water carries more of the epidemic in a larger population: with these values, it sustains an outbreak in a town of 10,000, and transmission from person to person alone does not.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.per the rate of transmission from person to person (per contact, if there are networks), for a symptomatic person
asymp_trans float the relative transmissibility and shedding of asymptomatic people
beta_env ss.per the rate of infection from the water, when it is saturated with bacteria
half_sat_rate float the amount of bacteria at which infection from the water is half its maximum
shedding_rate ss.freq the bacteria each symptomatic person sheds into the water, per unit time
decay_rate ss.per the rate at which bacteria in the water die off
dur_exp ss.Duration/ss.Dist the time from infection to being infectious (a duration is the mean of an exponential)
dur_asymp2rec ss.Duration/ss.Dist the time asymptomatic people are infectious
dur_symp2rec ss.Duration/ss.Dist the time symptomatic people are ill, for those who recover
dur_symp2dead ss.Duration/ss.Dist the time from symptoms to death, for those who die
p_symp float the probability that an infection is symptomatic
p_death float the probability that a symptomatic person dies
kwargs dict passed to ss.Disease, e.g. init_prev, init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Cholera(), total_pop=10_000, start='2025-01-01', stop='2026-01-01')
sim.run()
sim.cholera.plot()

Dengue

library.diseases.Dengue(n_serotypes=4, cross=0.3, init_prev=0.001, **kwargs)

Dengue: several serotypes, each passed on by mosquitoes, with partial cross-protection between them

Each serotype is a disease of its own (ssl.DengueSerotype), den1 to den4, so this is a set of diseases, given to a sim as one (ss.Sim(diseases=ssl.Dengue())), and the results are sim.results.den1 and so on. Having had one serotype gives complete protection against that one and partial protection against the others (cross), a modifier of each serotype’s rel_sus.

Sources: the host-vector structure is the Ross-Macdonald model as given by Keeling MJ, Rohani P, Modeling Infectious Diseases in Humans and Animals, Princeton University Press, 2008, section 4.4 (see ssl.Malaria). The dengue values are indicative ones from the literature rather than one source’s fitted set: about 6 days of viremia in people and an extrinsic incubation period of about 10 days in Aedes aegypti at tropical temperatures, with a mosquito lifetime of about 10 days. That infection with one serotype gives lasting protection against it and temporary, partial protection against the others is the finding of Reich NG et al., “Interactions between serotypes of dengue highlight epidemiological impact of cross-immunity”, J R Soc Interface 2013;10(86):20130414 (https://doi.org/10.1098/rsif.2013.0414); here that cross-protection does not wane, which is a simplification, and its size (cross) is illustrative.

Note: CRN safe as agents.

Parameters

Name Type Description Default
n_serotypes int how many serotypes (up to 4) 4
cross float the protection against the other serotypes after recovering from one (1 is complete) 0.3
init_prev float the fraction of people who start infected (infectious) with each serotype 0.001
kwargs dict the parameters of each serotype (see ssl.DengueSerotype), e.g. m=3, and anything else for ss.Disease

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Dengue(), demographics=True, n_agents=5000, unit='day', stop=365*5)
sim.run()
sim.den1.plot()

Without births, each serotype burns through the people susceptible to it and stops; demographics=True gives the sim births and deaths, which keep the serotypes returning.

DengueSerotype

library.diseases.DengueSerotype(others=(), cross=0.3, **kwargs)

One dengue serotype: people are susceptible, infectious, or recovered, with mosquitoes of its own

The host and vector structure is that of ssl.Malaria, plus the extrinsic incubation period in the mosquito. Having recovered from any of the other serotypes (others=, by name) protects in part (cross), a modifier of this serotype’s rel_sus. ssl.Dengue makes the serotypes together, each protecting against the others.

Note: CRN safe as agents.

Parameters

Name Type Description Default
others list the names of the other serotypes, recovery from which protects in part ()
cross float the protection against this serotype after recovering from one of the others (1 is complete) 0.3
a ss.per bites on people per mosquito per day
b float the chance that a bite by an infectious mosquito infects a person
c float the chance that a bite on an infectious person infects a mosquito
m float mosquitoes per person
dur_inf ss.Duration the mean time a person is infectious (viremic)
eip ss.Duration the extrinsic incubation period: the mean time from a mosquito being infected to being infectious
mu_v ss.per the death rate of mosquitoes, which emerge at the same rate
kwargs dict passed to ss.Disease, e.g. init_prev or name

Ebola

library.diseases.Ebola(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Ebola, including severe disease and transmission from unburied bodies

People infected are latent (E) for dur_exp, then symptomatic (I). A fraction p_sev become severely ill (Sev), and the rest recover; of the severe, a fraction p_death die, and the rest recover. Severe cases are more infectious (sev_factor), and so are the bodies of those who have died (D), until they are buried (unburied_factor): a fraction p_safe_bury are buried safely, at once, and the rest after dur_dead2buried. Bodies are people until they are buried, when they leave the population; the outcome burial counts both kinds of burial (safe_burial and unsafe_burial), and deaths every death. It is declared, so it runs under any solver.

Sources: the structure follows the model of Legrand J et al., “Understanding the dynamics of Ebola epidemics”, Epidemiol Infect 2007;135(4):610-621 (https://doi.org/10.1017/S0950268806007217), with funeral transmission; the durations and probabilities are illustrative of the 2014 West African epidemic (WHO Ebola Response Team, N Engl J Med 2014;371:1481-1495, https://doi.org/10.1056/NEJMoa1411100), and beta gives an R0 of about 1.7, within its estimates of 1.5 to 2.0.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.per the transmission rate from a symptomatic person (per contact, if there are networks)
sev_factor float the relative transmissibility of severe cases
unburied_factor float the relative transmissibility of unburied bodies
dur_exp ss.Duration/ss.Dist the time from infection to symptoms (and being infectious); each duration is a lognormal by default, and a single duration given is the mean of an exponential
dur_symp2sev ss.Duration/ss.Dist the time from symptoms to severe disease, for those who become severe
dur_symp2rec ss.Duration/ss.Dist the time from symptoms to recovery, for those who do not
dur_sev2dead ss.Duration/ss.Dist the time from severe disease to death, for those who die
dur_sev2rec ss.Duration/ss.Dist the time from severe disease to recovery, for those who recover
dur_dead2buried ss.Duration/ss.Dist the time from death to an unsafe burial
p_sev float the probability of severe disease
p_death float the probability of death, of the severe
p_safe_bury float the probability of a safe burial, at once
kwargs dict passed to ss.Disease, e.g. init_prev, init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Ebola(), total_pop=10_000, start='2025-01-01', stop='2026-01-01')
sim.run()
sim.ebola.plot()

Gonorrhea

library.diseases.Gonorrhea(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Gonorrhea, as an SIS model on a sexual network

Gonorrhea leaves no lasting immunity: people clear the infection, by treatment or on their own, and are susceptible again at once. Most infections in women go without symptoms and so last much longer than those in men, which is why a fuller model gives the duration and the transmission probability by sex.

Source: the parameters are those of the gonorrhea module of STIsim (https://github.com/starsimhub/stisim, stisim/diseases/gonorrhea.py), whose own sources are cited there: a transmission probability per act from men to women of 0.06, and durations to clearance of a few months to about a year, from which dur_inf here is a single average.

Nobody is treated here, so the level gonorrhea settles at is above what a setting with treatment would show, and it depends strongly on the network: with few partners and few acts it dies out instead.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.peract the transmission probability per act, from men to women and from women to men
dur_inf ss.Duration the mean time to clearance
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

net = ss.SexualNet(dur=ss.years(2), n_contacts=ss.poisson(1))
sim = ss.Sim(diseases=ssl.Gonorrhea(), networks=net, n_agents=5000, start=2000, stop=2030, dt=ss.months(1))
sim.run()
sim.gonorrhea.plot()

HIV

library.diseases.HIV(pars=None, **kwargs)

Simple HIV model with CD4 count dynamics and ART.

Infected agents have a CD4 count that declines towards cd4_min while untreated and recovers towards cd4_max while on ART, at a rate set by cd4_rate. The per-timestep probability of death scales with how far the CD4 count has fallen, so agents with low CD4 counts die soonest. Agents on ART have their transmissibility reduced by art_efficacy. Vertical transmission is supported: a fetus infected over ss.PrenatalNet is infected as anyone else is.

It is written as code, as agents (see ss.AgentDisease), which gives it its seeding, transmission, and the infection and prevalence results; it adds the CD4 count, ART, and death.

Use with ART to scale up treatment over time, and CD4_analyzer to record CD4 counts. Since beta defaults to 0, it must be set for transmission to occur.

Note: CRN safe.

Parameters

Name Type Description Default
beta float per-contact transmission probability (0 by default)
cd4_min float CD4 count approached by untreated agents
cd4_max float CD4 count approached by agents on ART
cd4_rate float number of timesteps to close the CD4 gap
art_efficacy float proportional reduction in transmission on ART
init_prev Dist initial prevalence
death_dist Dist death probability, by default from death_rate, modulated by CD4
death_rate rate baseline rate of death of the infected, per unit time (not a probability per infection)

Attributes

Name Type Description
on_art BoolState currently on ART
ti_art FloatArr timestep of ART initiation
ti_dead FloatArr timestep of HIV-caused death
cd4 FloatArr current CD4 count (default 500)

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(
    diseases = ssl.HIV(beta=0.02, init_prev=0.05),
    networks = 'random',
    interventions = ssl.ART(coverage=ss.timeseries({2000: 0, 2020: 0.8}, 'linear')),
)
sim.run()
sim.plot()

Methods

Name Description
init_results Initialize results
step_state Update CD4
init_results
library.diseases.HIV.init_results()

Initialize results

step_state
library.diseases.HIV.step_state()

Update CD4

Influenza

library.diseases.Influenza(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Seasonal influenza, as a SEIRS model with a yearly cycle in transmission

Transmission follows a smooth yearly cycle (ss.seasonal), highest in January in the northern hemisphere, and immunity wanes within a year or so, as the virus drifts. Together these keep influenza returning each winter. For the southern hemisphere, give the cycle another peak: ssl.Influenza(beta=ss.seasonal(mean=ss.perday(0.26), amplitude=0.3, peak='July')).

Sources: the natural history is from Carrat F et al., “Time lines of infection and disease in human influenza: a review of volunteer challenge studies”, Am J Epidemiol 2008;167(7):775-785 (https://doi.org/10.1093/aje/kwm375): about 2 days from infection to shedding, and about 5 days of shedding. beta gives an R0 of 1.3 on average over the year, the median estimate for seasonal influenza in the review of Biggerstaff M et al., BMC Infect Dis 2014;14:480 (https://doi.org/10.1186/1471-2334-14-480); R0() reports 1.7, since it reads the cycle at the start of the run, which is its January peak. The amplitude of the cycle and the duration of immunity are illustrative, and since everyone here becomes fully susceptible again, the epidemics infect more people each year than real seasons do.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.seasonal/ss.per the transmission rate over the year, as a cycle around its mean
dur_exp ss.Duration the mean time from infection to being infectious
dur_inf ss.Duration the mean time infectious
dur_imm ss.Duration the mean time immune after recovering
birth_rate ss.per the birth and death rate, which supplies new susceptible people
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Influenza(), total_pop=100_000, start='2000-01-01', stop='2010-01-01', dt=ss.days(1))
sim.run()
sim.influenza.plot()

Malaria

library.diseases.Malaria(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Malaria as the Ross-Macdonald model of humans and mosquitoes

People are susceptible, infectious, or recovered, and are born and die; mosquitoes are susceptible or infectious, and stay infectious until they die. Mosquitoes are a count, not people (Sv, Iv), and start at their density of m per person, all susceptible.

Source: the Ross-Macdonald model, in the form of Keeling MJ, Rohani P, Modeling Infectious Diseases in Humans and Animals, Princeton University Press, 2008, section 4.4. Every default here is from its Program 4.4: the biting rate a (its r of 0.5 per 1,000 humans), the transmission probabilities b and c (its transmission matrix), gamma, mu_h, mu_v, and m (its 10,091 mosquitoes per 1,000 people). The model is originally that of Ross R, The Prevention of Malaria, Murray, 1911, and Macdonald G, The Epidemiology and Control of Malaria, Oxford University Press, 1957.

R0() is 14.6 with these values, which is the square root of the classical Ross-Macdonald value, m·a²·b·c/(γ·μ_v) = 213, since each passage through a mosquito and back is two generations.

Note: CRN safe as agents.

Parameters

Name Type Description Default
a ss.per bites on people per mosquito per day
b float the chance that a bite by an infectious mosquito infects a person
c float the chance that a bite on an infectious person infects a mosquito
m float mosquitoes per person
gamma ss.per the rate at which people recover
mu_h ss.per the birth and death rate of people
mu_v ss.per the death rate of mosquitoes, which emerge at the same rate
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Malaria(), total_pop=10_000, unit='day', stop=1000)
sim.run()
sim.diseases.malaria.plot('Ih', 'Iv')

MalariaImmunity

library.diseases.MalariaImmunity(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Malaria with immunity, as the Garki model

The states keep the source’s names: x1 (nonimmune and negative), x2 (nonimmune, incubating), y1 (positive and infectious), y2 (positive, not infectious, recovering slowly), y3 (immune positive, recovering fast), x3 (immune and negative), and x4 (immune, incubating). People lose infectivity before they gain a fast recovery rate, and are detected less often once immune (q3). Everything about the mosquitoes is in one number, the vectorial capacity C: the potentially infective contacts each person makes per day through them. Inoculation saturates as C rises (h = g(1 − exp(−C·y1))), and superinfection slows recovery (R(h) = h/(exp(h/r) − 1)).

Source: the Garki model of Dietz K, Molineaux L, Thomas A, “A malaria model tested in the African savannah”, Bull World Health Organ 1974;50(3-4):347-357, in the form given by Molineaux L, Gramiccia G, The Garki Project, WHO, 1980, chapter 10. The defaults are its Table 31: g, alpha2, and r1 were fitted to the Garki data, and alpha1, delta, dur_inc, ratio (r2/r1), and q3 were assumed. C varied by season and village from below 0.01 to above 2 (its Fig. 77), so the default here is a constant chosen for illustration; give an ss.seasonal() for a seasonal one.

Malaria dies out below the critical vectorial capacity, (alpha1 + delta)/g, which is 0.022 per day with these values, as the source gives.

Note: CRN safe as agents.

Parameters

Name Type Description Default
C float the vectorial capacity: potentially infective contacts per person per day
g float the chance that an infection results, given at least one inoculation
r1 ss.per the recovery rate of nonimmune people, before superinfection
ratio float the recovery rate of immune people, relative to r1
alpha1 ss.per the rate of losing infectivity
alpha2 ss.per the rate of acquiring a high recovery rate (immunity)
delta ss.per the birth and death rate
dur_inc ss.Duration the incubation period in people
q3 float the chance that an immune positive person is detected by a blood examination
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.MalariaImmunity(C=0.1), total_pop=10_000, unit='day', dur=ss.days(365*20))
sim.run()
sim.malariaimmunity.plot()

Measles

library.diseases.Measles(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Measles, as an SEIR model with deaths

People infected are latent (E) for dur_exp, then infectious (I) for dur_inf (each a normal, with a spread of a day or two), after which they recover with lifelong immunity (R) or, with probability p_death, die. It is declared, so it runs under any solver: as compartments mixing homogeneously, or as agents on a network (where beta is the rate per contact).

Sources: the latent and infectious periods are from the US CDC (about 8 days from infection to being infectious, and infectious for about 11 days, from 4 days before the rash to 4 days after it, rounded up; the standard deviations, 2 days and 1.5 days, are illustrative, since the CDC gives ranges: 7 to 21 days from exposure to the rash); beta gives an R0 of about 15 (beta times dur_inf), within the range of 12 to 18 usually quoted (Guerra FM et al., “The basic reproduction number (R0) of measles: a systematic review”, Lancet Infect Dis 2017;17(12):e420-e428, https://doi.org/10.1016/S1473-3099(17)30307-9). The probability of death is illustrative of a setting with good care.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.per the transmission rate (per contact, if there are networks)
dur_exp ss.Duration/ss.Dist the time from infection to being infectious (a single duration given is the mean of an exponential)
dur_inf ss.Duration/ss.Dist the time infectious
p_death float the probability of death, at the end of the infectious period
kwargs dict passed to ss.Disease, e.g. init_prev, init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Measles(init=dict(R=0.9)), total_pop=100_000, start='2025-01-01', stop='2026-01-01')
sim.run()
sim.measles.plot()

NCD

library.diseases.NCD(
    pars=None,
    initial_risk=_,
    dur_risk=_,
    prognosis=_,
    **kwargs,
)

Example non-communicable disease

This class implements a basic NCD model with risk of developing a condition (e.g., hypertension, diabetes), a state for having the condition, and associated mortality. It is written as code (see ss.Disease), and is not transmitted.

Note: CRN safe.

Parameters

Name Type Description Default
initial_risk float/ss.bernoulli initial prevalence of risk factors _
dur_risk float/ss.Duration/ss.Dist how long a person is at risk for _
prognosis float/ss.Duration/ss.Dist time in years between first becoming affected and death _

Attributes

Name Description
not_at_risk Boolean array of agents not currently at risk.

Methods

Name Description
init_post Set initial values for states. This could involve passing in a full set of initial conditions,
init_results Initialize results
init_post
library.diseases.NCD.init_post()

Set initial values for states. This could involve passing in a full set of initial conditions, or using init_prev, or other. Note that this is different to initialization of the State objects i.e., creating their dynamic array, linking them to a People instance. That should have already taken place by the time this method is called.

init_results
library.diseases.NCD.init_results()

Initialize results

Pertussis

library.diseases.Pertussis(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Pertussis (whooping cough), as a SEIRS model with slowly waning immunity

Pertussis is highly transmissible, and immunity after infection, while long, is not lifelong, so people are infected again decades later. That waning, together with births, keeps pertussis circulating and gives the epidemics that return every few years, as in Keeling and Rohani’s treatment of SEIRS models with demography.

Sources: the natural history and the duration of immunity are from Wearing HJ, Rohani P, “Estimating the duration of pertussis immunity using epidemiological signatures”, PLoS Pathogens 2009;5(10):e1000647 (https://doi.org/10.1371/journal.ppat.1000647): a latent period of 8 days, an infectious period of 15 days, natural immunity of at least 30 years on average, and a pre-vaccine birth rate of 0.012 to 0.028 per year. beta gives an R0 of 13, within their pre-vaccine estimate of 11 to 15. The structure is that of Keeling MJ, Rohani P, Modeling Infectious Diseases in Humans and Animals, Princeton University Press, 2008, chapter 2.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.per the transmission rate (R0 of 13 with the default infectious period)
dur_exp ss.Duration the mean latent period
dur_inf ss.Duration the mean infectious period
dur_imm ss.Duration the mean time immune after recovering
birth_rate ss.per the birth and death rate
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Pertussis(), total_pop=500_000, start='1920-01-01', stop='1960-01-01', dt=ss.days(2))
sim.run()
sim.pertussis.plot()

Polio

library.diseases.Polio(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Poliovirus, with a paralytic fraction

Nearly every infection with wild poliovirus passes without paralysis, so the states are those of the infection, and paralysis is a rare outcome of it: a fraction p_paralysis of infections end in P rather than R, and the result outcome.P counts the paralytic cases, which are the ones surveillance sees.

Sources: about 1 in 200 infections with wild poliovirus type 1 causes paralysis in a fully susceptible person (US CDC, Epidemiology and Prevention of Vaccine-Preventable Diseases, the “Pink Book”, chapter on poliomyelitis). beta gives an R0 of 6, within the usual range of 5 to 7 for wild poliovirus in settings with poor sanitation (Fine PEM, Carneiro IAM, “Transmissibility and persistence of oral polio vaccine viruses”, Am J Epidemiol 1999;150(10):1001-1021). The latent period of 3 days and 20 days of shedding are standard values; shedding lasts longer in young children.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.per the transmission rate (R0 of 6 with the defaults)
dur_exp ss.Duration the mean time from infection to shedding
dur_inf ss.Duration the mean time shedding
p_paralysis float the fraction of infections that cause paralysis
birth_rate ss.per the birth and death rate, which supplies the susceptible children
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Polio(), total_pop=100_000, start=1980, stop=2000, dt=ss.days(2))
sim.run()
print('Paralytic cases:', sim.results.polio['outcome.P'].sum())

RSV

library.diseases.RSV(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Respiratory syncytial virus (RSV), as a seasonal MSEIRS model

Babies are born with maternal antibodies (M), which protect them for a few months; everyone else is susceptible, exposed, infectious, or immune, and immunity wanes within about a year, so people are infected again and again. Transmission follows a yearly cycle, as RSV does in temperate countries.

Sources: the infectious period of 10 days and the cosine seasonal form are from Weber A, Weber M, Milligan P, “Modeling epidemics caused by respiratory syncytial virus (RSV)”, Math Biosci 2001;172(2):95-113 (https://doi.org/10.1016/S0025-5564(01)00066-9), whose estimates of R0 for a SIRS model of RSV, 1.2 to 2.1, beta is set within (R0 of 2 on average over the year). The latent period of 5 days is the median of Crowcroft NS et al., as used by Hogan AB et al., BMC Infect Dis 2014. The duration of maternal protection, the duration of immunity, and the amplitude of the cycle are illustrative.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.seasonal/ss.per the transmission rate over the year, as a cycle around its mean
dur_mat ss.Duration the mean time babies are protected by maternal antibodies
dur_exp ss.Duration the mean time from infection to being infectious
dur_inf ss.Duration the mean time infectious
dur_imm ss.Duration the mean time immune after recovering
birth_rate ss.per the birth and death rate; babies are born into M
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.RSV(), total_pop=100_000, start='2000-01-01', stop='2006-01-01', dt=ss.days(1))
sim.run()
sim.rsv.plot()

Syphilis

library.diseases.Syphilis(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Syphilis, as a staged infection, wholly declared

People who are infected incubate (E), then have a primary chancre (P), then secondary syphilis (Se), and then early latent syphilis (El), from which some relapse to secondary syphilis and the rest pass to late latent syphilis (Ll). A fraction of those develop tertiary syphilis (T), which can kill; the rest are no longer infectious (R).

How infectious a person with latent syphilis is falls with the time since their latent stage began, a quantity each person carries: two modifiers of rel_trans, members of the disease. Since it acts on each person, this disease runs as agents.

Source: the natural history and its parameters are those of the syphilis module of STIsim (https://github.com/starsimhub/stisim, stisim/diseases/syphilis.py), whose own sources are cited there: the incubation period, primary and secondary stages from Garnett GP et al. (1997), the definition of early latent syphilis as up to two years after infection from WHO Europe, and the fraction developing tertiary syphilis. The half-life of latent infectiousness is STIsim’s.

Nobody is treated here, and the latent and tertiary stages last for years and count towards prevalence, so the level it settles at is well above what a setting with treatment and screening would show; add ss.screen() and ss.treat() to the sim for that. How far it spreads also depends on the network: the partnerships, how long they last, and the acts in them.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.peract the transmission probability per act, from men to women and from women to men
dur_exp ss.Duration the mean incubation period
dur_primary ss.Duration the mean duration of the primary stage
dur_secondary ss.Duration the mean duration of the secondary stage
dur_early ss.Duration the mean duration of early latent syphilis
dur_late ss.Duration the mean time in late latent syphilis before tertiary syphilis, for those who develop it
p_reactivate float the fraction of people with early latent syphilis who relapse to secondary syphilis
p_tertiary float the fraction who develop tertiary syphilis
death_rate ss.per the rate of dying of tertiary syphilis
latent_half_life ss.Duration the half-life of infectiousness during latent syphilis
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

net = ss.SexualNet(dur=ss.years(2), n_contacts=ss.poisson(1))
sim = ss.Sim(diseases=ssl.Syphilis(), networks=net, n_agents=5000, start=2000, stop=2030, dt=ss.months(1))
sim.run()
sim.syphilis.plot()

TB

library.diseases.TB(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Tuberculosis, as the LSHTM model of the spectrum of TB disease

People who are infected either clear the infection, or develop disease that moves back and forth between non-infectious, asymptomatic (infectious, but at trans_asymp of a symptomatic person), and symptomatic. People who cleared or recovered can be infected again, at their own relative rate. Only symptomatic people die of TB; every death is replaced by a birth, so the population stays the same size, as in the source.

Source: the LSHTM natural history of Schwalb A et al., PLOS Glob Public Health 2025, 5(1):e0005050 (https://doi.org/10.1371/journal.pgph.0005050), in the form of the reference ODE of TBsim (tbsim/compartmental/lshtm_ode.R), from which every default here is taken: beta, trans_asymp, the reinfection multipliers, the rates between states, and the background death rate. Treatment is off in that reference, and is left out here; TBsim adds treatment, drug resistance, and preventive therapy.

With the reference’s beta of 9, TB declines slowly over centuries (R0() is 0.23, since most infections are cleared and few reach disease), reproducing that reference exactly; beta is what a model of a particular place fits to its data.

Rates are per year, so a step of a year or a month suits it.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.per contacts per person per year (per contact, with a network)
trans_asymp float infectiousness of asymptomatic TB, relative to symptomatic
rr_reinfect_cleared float the rate of reinfection of people who cleared a latent infection, relative to a first infection
rr_reinfect_rec float the same, for people who recovered from disease
inf_cle, inf_non, inf_asy ss.per the rates of leaving latent infection, to cleared, non-infectious, and asymptomatic
non_rec, non_asy ss.per the rates of leaving non-infectious disease, to recovered and asymptomatic
asy_non, asy_sym ss.per the rates of leaving asymptomatic disease, to non-infectious and symptomatic
sym_asy ss.per the rate of returning from symptomatic to asymptomatic disease
sym_dead ss.per the rate of dying of symptomatic TB
mu ss.per the background birth and death rate
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.TB(), total_pop=100_000, start=1900, stop=2000)
sim.run()
sim.tb.plot()

Typhoid

library.diseases.Typhoid(
    *args,
    pars=None,
    strains=None,
    stratify=None,
    solver=None,
    _names=None,
    **kwargs,
)

Typhoid fever, with chronic carriers

Most people recover from typhoid, but a small fraction become chronic carriers, who shed for life and are much less infectious than an acute case (rel_carrier), while contributing to transmission for decades. Immunity after infection wanes slowly, if at all.

Sources: the values of the carriers are from Pitzer VE et al., “Predicting the impact of vaccination on the transmission dynamics of typhoid in South Asia”, PLoS Negl Trop Dis 2014;8(1):e2642 (https://doi.org/10.1371/journal.pntd.0002642): a relative infectiousness of carriers of 0.01, a fraction becoming carriers within their 0.3% to 10% by age, and a rate of waning immunity estimated as close to zero, so immunity is lifelong by default. beta is set to give their estimated R0 of 2.8 for Kolkata and Vellore. The duration of acute infection, 4 weeks, is a standard value.

Note: CRN safe as agents.

Parameters

Name Type Description Default
beta ss.per the transmission rate (R0 of 2.8 with the defaults)
rel_carrier float the infectiousness of a chronic carrier, relative to an acute case
p_carrier float the fraction of cases who become chronic carriers
dur_inf ss.Duration the mean duration of acute infection
dur_imm ss.Duration the mean time immune after recovering (lifelong by default)
birth_rate ss.per the birth and death rate
kwargs dict passed to ss.Disease, e.g. init or name

Examples

import starsim as ss
import starsim.library as ssl

sim = ss.Sim(diseases=ssl.Typhoid(), total_pop=100_000, start=1980, stop=2020, dt=ss.weeks(2))
sim.run()
sim.typhoid.plot()