Skip to content

Commit

Permalink
Merge pull request #115 from SABS-R3-Epidemiology/readme_fix
Browse files Browse the repository at this point in the history
Github markdown support for readme
  • Loading branch information
I-Bouros authored Dec 12, 2024
2 parents 0d116f7 + 89fe273 commit a2ec0f4
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 46 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/copyright-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.8
- name: Set up Python 3.12
uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: 3.12
architecture: x64

- name: install seirmo
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/coverage-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.8
- name: Set up Python 3.12
uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: 3.12
architecture: x64

- name: install seirmo
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/doc-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.8
- name: Set up Python 3.12
uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: 3.12
architecture: x64

- name: install seirmo
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/os-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ jobs:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2

- name: Set up Python 3.8
uses: actions/setup-python@v1
- name: Set up Python 3.12
uses: actions/setup-python@v2
with:
python-version: 3.8
python-version: 3.12
architecture: x64

- name: install seirmo
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/style-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.8
- name: Set up Python 3.12
uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: 3.12
architecture: x64

- name: install seirmo
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8]
python-version: [3.8, 3.9, 3.11, 3.12]

steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
architecture: x64
Expand Down
17 changes: 17 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2

build:
os: "ubuntu-20.04"
tools:
python: "3.12"

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/source/conf.py

# Optionally declare the Python requirements required to build your docs
python:
install:
- requirements: .requirements-docs.txt
- method: setuptools
path: .
3 changes: 3 additions & 0 deletions .requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Requirements for readthedocs.io
numpy>=1.8
sphinx>=1.5, !=1.7.3
47 changes: 23 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,20 @@
[![codecov](https://codecov.io/gh/SABS-R3-Epidemiology/seirmo/branch/main/graph/badge.svg?token=D1P3CMQTDP)](https://codecov.io/gh/SABS-R3-Epidemiology/seirmo)
[![Documentation Status](https://readthedocs.org/projects/seirmo/badge/?version=latest)](https://seirmo.readthedocs.io/en/latest/?badge=latest)



## General Information
This program models the outbreak of an infectious disease with the SEIR model. The SEIR model is a compartmental model with four compartments: susceptible (S), exposed (but not yet infectious) (E), infectious (I), and recovered (R). Each individual is in one compartment at a time, and different rates quantify the movement of an individual from one compartment to another.

Two submodels are defined in the program: a deterministic SEIR model and a stochastic SEIR model. Both are non-spatial and are time dependant. When the population size is small, the emergent behaviour of the two systems (deterministic and stochastic) can significantly differ. When the population size is larger, the dynamics tend to better align.
This program models the outbreak of an infectious disease with the SEIR model. The SEIR model is a compartmental model with four compartments: susceptible (S), exposed (but not yet infectious) (E), infectious (I), and recovered (R). Each individual is in one compartment at a time, and different rates quantify the movement of an individual from one compartment to another.

Two submodels are defined in the program: a deterministic SEIR model and a stochastic SEIR model. Both are non-spatial and are time dependant. When the population size is small, the emergent behaviour of the two systems (deterministic and stochastic) can significantly differ. When the population size is larger, the dynamics tend to better align.

 



## Deterministic SEIR

The deterministic model supposes that the population is large and well-mixed, and that small fluctuations in compartments do not impact the general solution. The conceptualisation of the model is illustrated below, and the parameters are described in a table below.

![SEIR model conceptualisation](./images/SEIR_model.png)


| Parameter | Description | Unit |
| ------------- | --------------------------------------------------------------------------------------- | ---- |
| β | Percentage of infectious and susceptible encounters per day that lead to transmission | 1/t |
Expand All @@ -29,39 +25,40 @@ The deterministic model supposes that the population is large and well-mixed, an

β > 0 controls the rate of tranmission, κ > 0 the rate at which exposed individuals become infectious, and γ > 0 the rate at which individuals recover. The model also requires initial conditions for each compartment: S(0), E(0), I(0), and R(0), which represent the initial number of people in each category.

The deterministic model solves this set of ODEs:

The deterministic model solves this set of ODEs:

<img src="https://render.githubusercontent.com/render/math?math=\frac{dS(t)}{dt} = - \beta S(t) I(t) ">
<img src="https://render.githubusercontent.com/render/math?math=\frac{dE(t)}{dt} = \beta S(t) I(t) - \kappa E(t) ">
<img src="https://render.githubusercontent.com/render/math?math=\frac{dI(t)}{dt} = \kappa E(t) - \gamma I(t)">
<img src="https://render.githubusercontent.com/render/math?math=\frac{dR(t)}{dt} = \gamma I(t)">
$$
\frac{dS(t)}{dt} = - \beta S(t) I(t), \\\\
\frac{dE(t)}{dt} = \beta S(t) I(t) - \kappa E(t), \\\\
\frac{dI(t)}{dt} = \kappa E(t) - \gamma I(t), \\\\
\frac{dR(t)}{dt} = \gamma I(t)
$$

The system of ODEs is nonlinear and must be solved by numerical integration methods. It is solved here using a forward model, using the `solve_ivp` method in the `scipy.integrate` library.


&nbsp;


## Stochastic SEIR

The stochastic model also supposes that the population is homogeneous, but it supposes that small fluctuations in compartments count toward the general solution. It models the population discretely and allows stochastic movements between compartments. The model can be illustrated as a set of chemical reactions:

![SEIR stochastic model reactions](./images/SEIR_stochastic_reactions.png)

The model is solved using the Gillespie algorithm (see documentation here: https://en.wikipedia.org/wiki/Gillespie_algorithm). The timesteps are sampled randomly. At each timestep, only one reaction takes place, and which reaction takes place is determined randomly following their propensities. For example, for a given time t, if the reaction occuring is a susceptible individual becoming exposed, then the following changes occur in the densities:

<img src="https://render.githubusercontent.com/render/math?math=S(t %2B 1)=S(t) - 1 ">

<img src="https://render.githubusercontent.com/render/math?math=E(t %2B 1)=E(t) %2B 1 ">
The model is solved using the Gillespie algorithm (see documentation [here](https://en.wikipedia.org/wiki/Gillespie_algorithm)). The timesteps are sampled randomly. At each timestep, only one reaction takes place, and which reaction takes place is determined randomly following their propensities. For example, for a given time _t_, if the reaction occuring is a susceptible individual becoming exposed, then the following changes occur in the densities:

where _(t+1)_ is the next timestep.
$$
S(t + 1)=S(t) - 1, \\\\
E(t + 1)=E(t) + 1
$$

where _(t+1)_ is the next timestep.

&nbsp;


## Installation procedure

One way to install the module is to download the repositiory to your machine of choice and type the following commands in the terminal.

```bash
git clone https://github.com/SABS-R3-Epidemiology/seirmo.git
cd ../path/to/the/file
Expand All @@ -75,12 +72,14 @@ pip install -e .

&nbsp;

## Documentation
## Documentation

Some documentation on the program's classes and methods can be found here: https://seirmo.readthedocs.io/en/latest/

### References

List of ressources that can be useful for the project:

* Gillespie D, 1977. Exact stochastic simulation of coupled chemical reactions (https://doi.org/10.1021/j100540a008)
* Erban R, Chapman J and Maini P, 2007. A practical guide to stochastic simulations of reaction-diffusion processes (https://arxiv.org/abs/0704.1908)
* Bauer F, 2008. Compartmental models in epidemiology (https://link.springer.com/chapter/10.1007/978-3-540-78911-6_2).

2 changes: 1 addition & 1 deletion seirmo/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def __init__(self, parameterNames: typing.List[str]):

def configure_parameters(self, parameters: np.ndarray):
"""Set the current parameters"""
assert parameters.shape == (self._n_parameters,),\
assert parameters.shape == (self._n_parameters,), \
f"Expected Parameter Shape {(self._n_parameters,)},\
but got {parameters.shape}"
self._parameters = parameters
Expand Down
2 changes: 1 addition & 1 deletion seirmo/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ def fix_parameters(self, name_value_dict):
self._fixed_params_values[index] = value

# If all parameters are free, set mask and values to None again
if np.alltrue(~self._fixed_params_mask):
if np.all(~self._fixed_params_mask):
self._fixed_params_mask = None
self._fixed_params_values = None

Expand Down
9 changes: 5 additions & 4 deletions seirmo/plots/_plot_from_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ def begin(self, subplots_rows: int = 1, subplots_columns: int = 1):
"""
Begins creating a figure, with given number of subfigures
Replaces init class so object can be reused"""
if type(subplots_rows) != int:
if not isinstance(subplots_rows, int):
raise TypeError("Number of rows of subplots must be an integer")
if type(subplots_columns) != int:
if not isinstance(subplots_columns, int):
raise TypeError("Number of columns of subplots must be an integer")
if subplots_rows <= 0:
raise ValueError("Number of rows of subplots must be positive")
Expand Down Expand Up @@ -84,7 +84,8 @@ def add_data_to_plot(
be plotted on a second x axis"""

if len(data_array.shape) == 1: # Turn any 1D input into 2D
if type(times) != np.ndarray or np.sum(np.shape(times)) == 1:
if (not isinstance(times, np.ndarray) or
np.sum(np.shape(times)) == 1):
# I.e. if only one np.int, or one element array
times = np.array(times, ndmin=2)
data_array = data_array[np.newaxis, :]
Expand All @@ -110,7 +111,7 @@ def add_data_to_plot(
colours = plt.cm.viridis(np.linspace(0, 1, data_width))
else:
colours = matplotlib.colors.to_rgba_array(colours)
assert data_width == np.shape(colours)[0],\
assert data_width == np.shape(colours)[0], \
'Unexpected number of colours'

if isinstance(ylabels, str):
Expand Down
2 changes: 1 addition & 1 deletion seirmo/tests/test_plotters.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_begin(self, plot_num):
'Unexpected number of subplot columns')
self.assertEqual(figure._size, int(row_num * col_num),
'Unexpected number of subplots')
self.assertEqual(np.product(np.shape(figure._axes)),
self.assertEqual(np.prod(np.shape(figure._axes)),
int(row_num * col_num),
'Unexpected number of axes objects')

Expand Down

0 comments on commit a2ec0f4

Please sign in to comment.