#
# SIR Epidemiology toy model.
#
# This file is part of PINTS (https://github.com/pints-team/pints/) which is
# released under the BSD 3-clause license. See accompanying LICENSE.md for
# copyright notice and full license details.
#
#
import numpy as np
import pints
from scipy.integrate import odeint
from . import ToyModel
[docs]
class SIRModel(pints.ForwardModel, ToyModel):
r"""
The SIR model of infectious disease models the number of susceptible (S),
infected (I), and recovered (R) people in a population [1]_, [2]_.
The particular model given here is analysed in [3],_ and is described by
the following three-state ODE:
.. math::
\dot{S} = -\gamma S I
\dot{I} = \gamma S I - v I
\dot{R} = v I
Where the parameters are ``gamma`` (infection rate), and ``v``, recovery
rate. In addition, we assume the initial value of S, ``S0``, is unknwon,
leading to a three parameter model ``(gamma, v, S0)``.
The number of infected people and recovered people are observable, making
this a 2-output system. S can be thought of as an unknown number of
susceptible people within a larger population.
The model does not account for births and deaths, which are assumed to
happen much slower than the spread of the (non-lethal) disease.
Real data is included via :meth:`suggested_values`, which was taken from
[3]_, [4]_, [5]_.
Extends :class:`pints.ForwardModel`, `pints.toy.ToyModel`.
Parameters
----------
y0
The system's initial state, must have 3 entries all >=0.
References
----------
.. [1] A Contribution to the Mathematical Theory of Epidemics. Kermack,
McKendrick (1927) Proceedings of the Royal Society A.
https://doi.org/10.1098/rspa.1927.0118
.. [2] https://en.wikipedia.org/wiki/Compartmental_models_in_epidemiology
.. [3] Approximate Bayesian computation scheme for parameter inference and
model selection in dynamical systems. Toni, Welch, Strelkowa, Ipsen,
Stumpf (2009) J. R. Soc. Interface.
https://doi.org/10.1098/rsif.2008.0172
.. [4] A mathematical model of common-cold epidemics on Tristan da Cunha.
Hammond, Tyrrell (1971) Epidemiology & Infection.
https://doi.org/10.1017/S0022172400021677
.. [5] Common colds on Tristan da Cunha. Shybli, Gooch, Lewis, Tyrell
(1971) Epidemiology & Infection.
https://doi.org/10.1017/S0022172400021483
"""
def __init__(self, y0=None):
super(SIRModel, self).__init__()
# Check initial values
if y0 is None:
# Toni et al.:
self._y0 = np.array([38, 1, 0])
else:
self._y0 = np.array(y0, dtype=float)
if len(self._y0) != 3:
raise ValueError('Initial value must have size 3.')
if np.any(self._y0 < 0):
raise ValueError('Initial states can not be negative.')
[docs]
def n_outputs(self):
""" See :meth:`pints.ForwardModel.n_outputs()`. """
return 2
[docs]
def n_parameters(self):
""" See :meth:`pints.ForwardModel.n_parameters()`. """
return 3
def _rhs(self, y, t, gamma, v):
"""
Calculates the model RHS.
"""
dS = -gamma * y[0] * y[1]
dI = gamma * y[0] * y[1] - v * y[1]
dR = v * y[1]
return np.array([dS, dI, dR])
[docs]
def simulate(self, parameters, times):
""" See :meth:`pints.ForwardModel.simulate()`. """
gamma, v, S0 = parameters
y0 = np.array(self._y0, copy=True)
y0[0] = S0
y = odeint(self._rhs, y0, times, (gamma, v))
return y[:, 1:]
[docs]
def suggested_parameters(self):
"""
Returns a suggested set of parameters for this toy model.
"""
# Guesses based on Toni et al.:
return [0.026, 0.285, 38]
[docs]
def suggested_times(self):
"""
Returns a suggested set of simulation times for this toy model.
"""
# Toni et al.:
return np.arange(1, 22)
[docs]
def suggested_values(self):
"""
Returns the data from a common-cold outbreak on the remote island of
Tristan da Cunha, as given in [3]_, [4]_, [5]_.
"""
# Toni et al.
return np.array([
[1, 0], # day 1
[1, 0],
[3, 0],
[7, 0],
[6, 5], # day 5
[10, 7],
[13, 8],
[13, 13],
[14, 13],
[14, 16], # day 10
[17, 17],
[10, 24],
[6, 30],
[6, 31],
[4, 33], # day 15
[3, 34],
[1, 36],
[1, 36],
[1, 36],
[1, 36], # day 20
[0, 37], # day 21
])