Skip to content

Commit

Permalink
🚧 WIP Wavefront Speed in Rabies
Browse files Browse the repository at this point in the history
  • Loading branch information
clorton committed Feb 3, 2025
1 parent 438ca2e commit 0a8e6b2
Show file tree
Hide file tree
Showing 21 changed files with 1,185 additions and 758 deletions.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,19 @@ pip install laser-generic

## Running in Codespace

Check the installed version(s) of NumPy
```bash
pip list | grep numpy
```
Note if there is a 2.x version of NumPy installed. If so, uninstall it (sub your 2.x version for `2.1.1` below).
```bash
pip uninstall numpy==2.1.1
```
Install `laser-generic` in development mode:
```bash
pip install -e .
```

## Notebooks

1. [notebooks/SI_nobirths_logistic_growth.ipynb](notebooks/SI_nobirths_logistic_growth.ipynb)
2. [notebooks/SI_wbirths_logistic_growth.ipynb](notebooks/SI_wbirths_logistic_growth.ipynb)
3. [notebooks/SIS_nobirths_logistic_growth.ipynb](notebooks/SIS_nobirths_logistic_growth.ipynb)
4. [notebooks/SIR_nobirths_outbreak_size.ipynb](notebooks/SIR_nobirths_outbreak_size.ipynb)
5. [notebooks/SIR_wbirths_age_distribution.ipynb](notebooks/SIR_wbirths_age_distribution.ipynb)
6. [notebooks/SIR_wbirths_natural_periodicity.ipynb](notebooks/SIR_wbirths_natural_periodicity.ipynb)
7. [notebooks/2patch_SIR_wbirths_correlation.ipynb](notebooks/2patch_SIR_wbirths_correlation.ipynb)
8. [notebooks/SIR_CCS.ipynb](notebooks/SIR_CCS.ipynb)
9. [notebooks/SEIR_wavefrontspeed.ipynb](notebooks/SEIR_wavefrontspeed.ipynb)
129 changes: 47 additions & 82 deletions notebooks/2patch_SIR_wbirths_correlation.ipynb

Large diffs are not rendered by default.

273 changes: 273 additions & 0 deletions notebooks/SEIR_wavefrontspeed.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Exploring Wavefront Speed with an SEIR Rabies Model\n",
"\n",
"[A Simple Model for the Spatial Spread and Control of Rabies - Källén, Arcuri, and Murray - 1985](https://doi.org/10.1016/S0022-5193(85)80276-9)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A simple model for the spatial spread of rabies models the dynamics of teh fron of an epizootic wave.\n",
"\n",
"Populations will be **S**, susceptible, **E**, exposed/incubating, **I**, infectious/rabid, and (untracked) _R_, removed/deceased.\n",
"\n",
"$$\n",
"\\delta S / \\delta t = -KIS \\\\\n",
"\n",
"\\delta I / \\delta t = D \\delta^2 I / \\delta x^2 + KIS - \\mu I\n",
"$$ (1)\n",
"\n",
"where $K$ is the transmission coefficient and $1 / \\mu$ is the life expectancy of an infective fox.\n",
"\n",
"$$\n",
"D = kA\n",
"$$ (2)\n",
"\n",
"where $D$ is the diffusion coefficient, $k$ is the rate at which infective foxes leave their territories which have average area A. $1 / k$ is the average time until a fox leaves its territory. Foxes remain in their territory until affected by rabies which leads to random migratory behavior.\n",
"\n",
"We will assume a static population and ignore birthrate for the moment expecting that we will simulate sufficiently short time scales.\n",
"\n",
"Some non-dimensions quantities:\n",
"\n",
"$$\n",
"u = I / S_0 \\\\\n",
"\n",
"v = S / S_0 \\\\\n",
"\n",
"x^* = (K S_0 / D)^{1/2} x \\\\\n",
"\n",
"t^* = K S_0 t \\\\\n",
"\n",
"r = \\mu / K S_0\n",
"$$ (3)\n",
"\n",
"Dropping the asterisks gives the following model equations:\n",
"\n",
"$$\n",
"\\delta u / \\delta t = \\delta^2 u / \\delta x^2 + u(v - r) \\\\\n",
"\n",
"\\delta v / \\delta t = - u v\n",
"$$ (4)\n",
"\n",
"where $u \\ge 0$ and $0 \\lt v \\le 1$.\n",
"\n",
"$R = 1 / r$ is the basic reproduction rate of the disease, $R_0$\n",
"\n",
"There is a typical critical minimum susceptible density, $S_c$ below which the infection cannot persist:\n",
"\n",
"$$\n",
"S_c = \\mu / K = r S_0\n",
"$$ (5)\n",
"\n",
"The proportion, $a$ of susceptibles which remain after the infective wave has passed satisfies\n",
"\n",
"$$\n",
"0 \\lt a \\lt r \\lt 1 \\\\\n",
"\n",
"a - r {log} (a) = 1\n",
"$$ (6)\n",
"\n",
"The waveforms for the two species travel together at the same speed, $c$, which is bounded below by\n",
"\n",
"$$\n",
"c = 2 \\sqrt {1 - r}\n",
"$$ (7a)\n",
"\n",
"$$\n",
"c = 2[D(KS_0 - \\mu)]^{1/2} = 2[D\\mu(1/r-1)]^{1/2}\n",
"$$ (7b)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Estimates for the Epidemiological Parameters\n",
"\n",
"$$\n",
"r = 0.5\n",
"$$\n",
"\n",
"> An infective fox first goes through an incubation period that can vary from 12 to 110 days, and then a rabid state lasting from 3 to 10 days. A life expectancy of about 35 days gives\n",
"\n",
"$$\n",
"\\mu = 10 yr^{-1}\n",
"$$\n",
"\n",
"> If we assume an average territory to be about $5 km^2$ and that an infective fox leaves its territory about the time it becomes rabid, that is about a month, then\n",
"\n",
"$$\n",
"k \\approx 12 yr^{-1} \\\\\n",
"\n",
"D \\approx 60 km^2 yr^{-1}\n",
"$$\n",
"\n",
"Estimated wave-speed $\\approx 50 km / year$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Fox Population Density from Data\n",
"\n",
"![Figure 1](media/Spatial%20Spread%20of%20Rabies%20-%20Figure%201.png)\n",
"\n",
"Fig. 1 Fluctuations in fox population density as a function of the passage of a rabies epizootic after data from the Centre National d'Etudes sur la Rage, 1977. $S_0$ is the population density in the absence of rabies and $S_c$ the critical population density below which the infection dies out. (Redrawn from MacDonald (1980), page 19).\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Travelling Wave Shape for Simplified Model\n",
"\n",
"![Figure 2](media/Spatial%20Spread%20of%20Rabies%20-%20Figure%202.png)\n",
"\n",
"Fig. 2 The shape of the (non-dimensional) travelling wave for $r = 0.5$. Here $r = \\mu / KS_0$ where $1 / \\mu$ is the life expectancy of an infective fox, $K$ the transmission coefficient and $S_0$ the undisturbed fox density.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"from matplotlib.figure import Figure\n",
"\n",
"class Incubation:\n",
" def __init__(self, model, verbose: bool = False) -> None:\n",
" return\n",
"\n",
" def census(self, model, tick) -> None:\n",
" return\n",
"\n",
" def __call__(self, model, tick) -> None:\n",
" return\n",
"\n",
" def plot(self, fig: Figure = None):\n",
" fig = plt.figure(figsize=(12, 9), dpi=128) if fig is None else fig\n",
" yield\n",
" return"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class Transmission:\n",
" def __init__(self, model, verbose: bool = False) -> None:\n",
" return\n",
"\n",
" def __call__(self, model, tick) -> None:\n",
" return\n",
"\n",
" def plot(self, fig: Figure = None):\n",
" fig = plt.figure(figsize=(12, 9), dpi=128) if fig is None else fig\n",
" yield\n",
" return"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from laser_generic import Model\n",
"from laser_generic import Susceptibility\n",
"from laser_generic import Infection\n",
"import numpy as np\n",
"import pandas as pd\n",
"\n",
"# Fox density from 1/km^2 to 4+/km^2 (higher in suburban and urban areas)\n",
"# Each patch will represent 5km^2\n",
"scenario = pd.DataFrame(data=np.full(201, 20, dtype=np.int32), columns=[\"population\"])\n",
"\n",
"model = Model(scenario)\n",
"model.components = [\n",
" Susceptibility,\n",
" Incubation,\n",
" Infection,\n",
" Transmission\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Survival Fraction for Simplified Model\n",
"\n",
"![Figure 3](media/Spatial%20Spread%20of%20Rabies%20-%20Figure%203.png)\n",
"\n",
"Fig 3. The fraction $a (= S/ S_0)$ of susceptible foxes which survive an epidemic wave as a function of $r (= \\mu / K S_0)$: $a$ and $r$ are related by $a - r log(a) = 1$ where $0 \\lt a \\lt r \\lt 1$.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Considering Reproduction\n",
"\n",
"> If $S_0$ is the carrying capacity in a particular rabies-free habitat, we can add a logistic population growth term to the equation for the susceptible foxes...\n",
"\n",
"$$\n",
"\\delta S / \\delta t = -KIS + \\beta S(1 - S / S_0)\n",
"$$ (9)\n",
"\n",
"Then\n",
"\n",
"$$\n",
"\\delta u / \\delta t = \\delta^2 u / \\delta x^2 + u(v - r) \\\\\n",
"\n",
"\\delta v / \\delta t = -uv + bv(1 - v)\n",
"$$ (10)\n",
"\n",
"where $b = \\beta / KS_0 = r \\beta / \\mu$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"## Travelling Wave Shape with Births\n",
"\n",
"![Figure 6](media/Spatial%20Spread%20of%20Rabies%20-%20Figure%206.png)\n",
"\n",
"Fig 6. The shape of the travelling wave solution when the susceptible foxes have logistic population growth with a net birth rate of 0.5 per year, that is $b = 0.05$ ($b$ is the net birth rate times the life expectancy of an infective fox). Here the model parameter $r = 0.5$."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Loading

0 comments on commit 0a8e6b2

Please sign in to comment.