Skip to main content

Cholera with a water reservoir

🧠0% 🤖100%

Cholera spreads mostly through water rather than from person to person: infected people shed bacteria into the water, the bacteria decay over weeks, and susceptible people are infected by drinking it. A model of it needs a state that is not people at all: the amount of bacteria in the water, W. This page models W as a state of the disease that holds a count rather than people, following the model of Codeço (2001).

The model

Infection depends on the bacteria in the water, with a dose-response curve that saturates: the rate is β W / (W + K), where K is the amount of bacteria at which the rate is half its maximum. W and K are amounts; Codeço writes them as concentrations, which is the same model for a fixed volume of water (taken here as one unit).

Parameter Value Meaning
β 0.5 per day Maximum rate of infection, when the water is saturated with bacteria
K 100,000 Amount of bacteria at which the rate is half its maximum
Infectious period 5 days Mean time in I (exponential)
Shedding 10 per day Bacteria shed into the water by each infectious person
Survival of bacteria 30 days Mean time bacteria survive in the water
Population 10,000
Infectious at the start 0.1%
import starsim as ss

S, I, R = ss.states('S I R')
W = ss.State(people=False) # Bacteria in the water: a count, not people
K = 1e5                    # Amount of bacteria at which infection is half its maximum

infection = S >> I @ ss.perday(0.5) * W.n / (W.n + K)
recovery  = I >> R @ ss.days(5)
shedding  = ss.outside >> W @ ss.perday(10) * I.n  # Each infectious person sheds 10 a day
decay     = W >> ss.dead @ ss.days(30)          # Bacteria survive 30 days on average
cholera = ss.Disease(infection, recovery, shedding, decay, init=dict(I=0.001), name='cholera')

W.n and I.n are counts (the amount of bacteria, and the number of people infectious), where a bare I in a rate would be the fraction of people infectious (I.frac). ss.outside and ss.dead are outside the model: shedding adds bacteria from outside it, and decay removes them. The diagram, from diagram(), in which W is slanted since it is not people:

cholera.diagram()

cholera.equations()
dS/dt = -perday(0.5) * W.n / (W.n + 100000) * S
dI/dt =  perday(0.5) * W.n / (W.n + 100000) * S - I / dur_I
dR/dt =  I / dur_I
dW/dt = -W / dur_W + perday(10) * I.n

Result

sim = ss.Sim(cholera, total_pop=10_000, stop=ss.days(200))
sim.run()
sim.plot('cholera')
Sim: cholera, 10,000 people, as an ODE, days 0 to 200
  Done in 0.0026 s

Bacteria build up in the water while people are infectious, and outlast them: the amount in the water peaks after the number infectious does, and keeps infecting people as the epidemic declines. Since W is a count and not people, it is left out of the population, and it stays a count when the people are run as agents (n_agents=).

Going further

  • Diseases covers states that are counts, and flows from and to ss.dead.
  • The library’s cholera model, ssl.diseases.Cholera, is a fuller version of the same model, with a latent period, asymptomatic infection, and deaths (see the library’s diseases).
  • Codeço CT (2001). Endemic and epidemic dynamics of cholera: the role of the aquatic reservoir. BMC Infectious Diseases 1:1.