epipack

epipack: An infectious disease modeling package for Python - Published in JOSS (2021)

https://github.com/benmaier/epipack

Science Score: 93.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 1 DOI reference(s) in JOSS metadata
  • Academic publication links
    Links to: arxiv.org
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
    Published in Journal of Open Source Software

Scientific Fields

Mathematics Computer Science - 41% confidence
Physics Physical Sciences - 40% confidence
Last synced: 4 months ago · JSON representation

Repository

Fast prototyping of infectious-disease models based on reaction equations. Analyze the ODEs analytically or numerically, or run stochastic simulations on networks/well-mixed systems.

Basic Info
  • Host: GitHub
  • Owner: benmaier
  • License: mit
  • Language: Python
  • Default Branch: master
  • Homepage:
  • Size: 41.1 MB
Statistics
  • Stars: 33
  • Watchers: 4
  • Forks: 2
  • Open Issues: 10
  • Releases: 11
Created over 5 years ago · Last pushed almost 3 years ago
Metadata Files
Readme Changelog Contributing License Code of conduct

README.md

logo

Fast prototyping of epidemiological models based on reaction equations. Analyze the ODEs analytically or numerically, or run/animate stochastic simulations on networks/well-mixed systems.

  • repository: https://github.com/benmaier/epipack/
  • documentation: http://epipack.benmaier.org/

```python import epipack as epk from epipack.vis import visualize import netwulf as nw

network, , _ = nw.load('cookbook/readme_vis/MHRN.json') N = len(network['nodes']) links = [ (l['source'], l['target'], 1.0) for l in network['links'] ]

S, I, R = list("SIR") model = epk.StochasticEpiModel([S,I,R],N,links)\ .setlinktransmissionprocesses([ (I, S, 1.0, I, I) ])\ .setnodetransitionprocesses([ (I, 1.0, R) ])\ .setrandominitial_conditions({ S: N-5, I: 5 })

visualize(model, network, sampling_dt=0.1) ```

sir-example

Idea

Simple compartmental models of infectious diseases are useful to investigate effects of certain processes on disease dissemination. Using pen and paper, quickly adding/removing compartments and transition processes is easy, yet the analytical and numerical analysis or stochastic simulations can be tedious to set up and debug—especially when the model changes (even slightly). epipack aims at streamlining this process such that all the analysis steps can be performed in an efficient manner, simply by defining processes based on reaction equations. epipack provides three main base classes to accomodate different problems.

  • EpiModel: Define a model based on transition, birth, death, fission, fusion, or transmission reactions, integrate the ordinary differential equations (ODEs) of the corresponding well-mixed system numerically or simulate it using Gillespie's algorithm. Process rates can be numerical functions of time and the system state.
  • SymbolicEpiModel: Define a model based on transition, birth, death, fission, fusion, or transmission reactions. Obtain the ODEs, fixed points, Jacobian, and the Jacobian's eigenvalues at fixed points as symbolic expressions. Process rates can be symbolic expressions of time and the system state. Set numerical parameter values and integrate the ODEs numerically or simulate the stochastic systems using Gillespie's algorithm.
  • StochasticEpiModel: Define a model based on node transition and link transmission reactions. Add conditional link transmission reactions. Simulate your model on any (un-/)directed, (un-/)weighted static/temporal network, or in a well-mixed system.

Additionally, epipack provides a visualization framework to animate stochastic simulations on networks, lattices, well-mixed systems, or reaction-diffusion systems based on MatrixEpiModel.

Check out the Example section for some demos.

Note that the internal simulation algorithm for network simulations is based on the following paper:

"Efficient sampling of spreading processes on complex networks using a composition and rejection algorithm", G.St-Onge, J.-G. Young, L. Hébert-Dufresne, and L. J. Dubé, Comput. Phys. Commun. 240, 30-37 (2019), http://arxiv.org/abs/1808.05859.

Install

pip install epipack

epipack was developed and tested for

  • Python 3.6
  • Python 3.7
  • Python 3.8

So far, the package's functionality was tested on Mac OS X and CentOS only.

Dependencies

epipack directly depends on the following packages which will be installed by pip during the installation process

  • numpy>=1.17
  • scipy>=1.3
  • sympy==1.6
  • pyglet<1.6
  • matplotlib>=3.0.0
  • ipython>=7.14.0
  • ipywidgets>=7.5.1

Please note that fast network simulations are only available if you install

manually (pip won't do it for you).

Documentation

The full documentation is available at epipack.benmaier.org.

Changelog

Changes are logged in a separate file.

License

This project is licensed under the MIT License. Note that this excludes any images/pictures/figures shown here or in the documentation.

Contributing

If you want to contribute to this project, please make sure to read the code of conduct and the contributing guidelines. In case you're wondering about what to contribute, we're always collecting ideas of what we want to implement next in the outlook notes.

Contributor Covenant

Examples

Let's define an SIRS model with infection rate eta, recovery rate rho, and waning immunity rate omega and analyze the system

Pure Numeric Models

Basic Definition (EpiModel)

Define a pure numeric model with EpiModel. Integrate the ODEs or simulate the system stochastically.

```python from epipack import EpiModel import matplotlib.pyplot as plt import numpy as np

S, I, R = list("SIR") N = 1000

SIRS = EpiModel([S,I,R],N)\ .set_processes([ #### transmission process #### # S + I (eta=2.5/d)-> I + I (S, I, 2.5, I, I),

    #### transition processes ####
    # I (rho=1/d)-> R
    # R (omega=1/14d)-> S
    (I, 1, R),
    (R, 1/14, S),
])\
.set_initial_conditions({S:N-10, I:10})

t = np.linspace(0,40,1000) resultint = SIRS.integrate(t) tsim, result_sim = SIRS.simulate(t[-1])

for C in SIRS.compartments: plt.plot(t, resultint[C]) plt.plot(tsim, result_sim[C]) ```

numeric-model

Functional Rates

It's also straight-forward to define temporally varying (functional) rates.

```python import numpy as np from epipack import SISModel

N = 100 recovery_rate = 1.0

def infection_rate(t, y, args, *kwargs): return 3 + np.sin(2np.pit/100)

SIS = SISModel( infectionrate=infectionrate, recoveryrate=recoveryrate, initialpopulationsize=N )\ .setinitialconditions({ 'S': 90, 'I': 10, })

t = np.arange(200) resultint = SIS.integrate(t) tsim, result_sim = SIS.simulate(199)

for C in SIS.compartments: plt.plot(tsim, resultsim[C]) plt.plot(t, result_int[C]) ```

numeric-model-time-varying

Symbolic Models

Basic Definition

Symbolic models are more powerful because they can do the same as the pure numeric models while also offering the possibility to do analytical evaluations

```python from epipack import SymbolicEpiModel import sympy as sy

S, I, R, eta, rho, omega = sy.symbols("S I R eta rho omega")

SIRS = SymbolicEpiModel([S,I,R])\ .set_processes([ (S, I, eta, I, I), (I, rho, R), (R, omega, S), ])
```

Analytical Evaluations

Print the ODE system in a Jupyter notebook

```python

SIRS.ODEs_jupyter() ```

ODEs

Get the Jacobian

```python

SIRS.jacobian() ```

Jacobian

Find the fixed points

```python

SIRS.findfixedpoints() ```

fixedpoints

Get the eigenvalues at the disease-free state in order to find the epidemic threshold

```python

SIRS.geteigenvaluesatdiseasefree_state() {-omega: 1, eta - rho: 1, 0: 1} ```

Numerical Evaluations

Set numerical parameter values and integrate the ODEs numerically

```python

SIRS.setparametervalues({eta: 2.5, rho: 1.0, omega:1/14}) t = np.linspace(0,40,1000) result = SIRS.integrate(t) ```

If set up as

```python

N = 10000 SIRS = SymbolicEpiModel([S,I,R],N) ```

the system can simulated directly.

```python

tsim, resultsim = SIRS.simulate(40) ```

Temporally Varying Rates

Let's set up some temporally varying rates

```python from epipack import SymbolicEpiModel import sympy as sy

S, I, R, eta, rho, omega, t, T = \ sy.symbols("S I R eta rho omega t T")

N = 1000 SIRS = SymbolicEpiModel([S,I,R],N)\ .set_processes([ (S, I, 2+sy.cos(2sy.pit/T), I, I), (I, rho, R), (R, omega, S), ])

SIRS.ODEs_jupyter() ```

SIRS-forced-ODEs

Now we can integrate the ODEs or simulate the system using Gillespie's SSA for inhomogeneous Poisson processes.

```python import numpy as np

SIRS.setparametervalues({ rho : 1, omega : 1/14, T : 100, }) SIRS.setinitialconditions({S:N-100, I:100}) t = np.linspace(0,200,1000) result = SIRS.integrate(t) tsim, resultsim = SIRS.simulate(max(_t)) ```

SIRS-forced-results

Interactive Analyses

epipack offers a classs called InteractiveIntegrator that allows an interactive exploration of a system in a Jupyter notebook.

Make sure to first run

%matplotlib widget

in a cell.

```python from epipack import SymbolicEpiModel from epipack.interactive import InteractiveIntegrator, Range, LogRange import sympy

S, I, R, R0, tau, omega = sympy.symbols("S I R R_0 tau omega")

I0 = 0.01 model = SymbolicEpiModel([S,I,R])\ .setprocesses([ (S, I, R0/tau, I, I), (I, 1/tau, R), (R, omega, S), ])\ .setinitial_conditions({S:1-I0, I:I0})

define a log slider, a linear slider and a constant value

parameters = { R0: LogRange(min=0.1,max=10,step_count=1000), tau: Range(min=0.1,max=10,value=8.0), omega: 1/14 }

t = np.logspace(-3,2,1000) InteractiveIntegrator(model, parameters, t, figsize=(4,4)) ```

interactive

Pure Stochastic Models

On a Network

Let's simulate an SIRS system on a random graph (using the parameter definitions above).

```python from epipack import StochasticEpiModel import networkx as nx

k0 = 50 R0 = 2.5 rho = 1 eta = R0 * rho / k0 omega = 1/14 N = int(1e4) edges = [ (e[0], e[1], 1.0) for e in \ nx.fastgnprandom_graph(N,k0/(N-1)).edges() ]

SIRS = StochasticEpiModel( compartments=list('SIR'), N=N, edgeweighttuples=edges )\ .setlinktransmissionprocesses([ ('I', 'S', eta, 'I', 'I'), ])\ .setnodetransitionprocesses([ ('I', rho, 'R'), ('R', omega, 'S'), ])\
.setrandominitialconditions({ 'S': N-100, 'I': 100 }) ts, result_s = SIRS.simulate(40) ```

network-simulation

Visualize

Likewise, it's straight-forward to visualize this system

```python

from epipack.vis import visualize from epipack.networks import getrandomlayout layoutednetwork = getrandomlayout(N, edges) visualize(SIRS, layoutednetwork, samplingdt=0.1, config={'drawlinks': False}) ```

sirs-example

On a Lattice

A lattice is nothing but a network, we can use get_grid_layout and get_2D_lattice_links to set up a visualization.

```python from epipack.vis import visualize from epipack import ( StochasticSIRModel, get2Dlatticelinks, getgrid_layout )

define links and network layout

Nside = 100 N = Nside**2 links = get2Dlatticelinks(Nside, periodic=True, diagonallinks=True) lattice = getgrid_layout(N)

define model

R0 = 3; recoveryrate = 1/8 model = StochasticSIRModel(N,R0,recoveryrate, edgeweighttuples=links) model.setrandominitial_conditions({'I':20,'S':N-20})

sampling_dt = 1

visualize(model,lattice,samplingdt, config={ 'drawnodesasrectangles':True, 'draw_links':False, } ) ```

sir-lattice

Reaction-Diffusion Models

Since reaction-diffusion systems in discrete space can be interpreted as being based on reaction equations, we can set those up using epipack's framework.

Checkout the docs on Reaction-Diffusion Systems.

Every node in a network is associated with a compartment and we're using MatrixEpiModel because it's faster than EpiModel.

```python from epipack import MatrixEpiModel

N = 100 basecompartments = list("SIR") compartments = [ (node, C) for node in range(N) for C in basecompartments ] model = MatrixEpiModel(compartments) ```

Now, we define both epidemiological and movement processes on a hypothetical list links.

```python infectionrate = 2 recoveryrate = 1 mobility_rate = 0.1

quadraticprocesses = [] linearprocesses = []

for node in range(N): quadraticprocesses.append( ( (node, "S"), (node, "I"), infectionrate, (node, "I"), (node, "I") ), )

linear_processes.append(
          ( (node, "I"), recovery_rate, (node, "R") ) 
    )

for u, v, w in links: for C in base_compartments:

    linear_processes.extend([
              ( (u, C), w*mobility_rate, (v, C) ),
              ( (v, C), w*mobility_rate, (u, C) ),
        ])

```

reac-diff-lattice

Dev notes

Fork this repository, clone it, and install it in dev mode.

bash git clone git@github.com:YOURUSERNAME/epipack.git make

If you want to upload to PyPI, first convert the new README.md to README.rst

bash make readme

It will give you warnings about bad .rst-syntax. Fix those errors in README.rst. Then wrap the whole thing

bash make pypi

It will probably give you more warnings about .rst-syntax. Fix those until the warnings disappear. Then do

bash make upload

Owner

  • Name: Benjamin F. Maier
  • Login: benmaier
  • Kind: user
  • Location: Copenhagen
  • Company: Technical University of Denmark

Postdoc @suneman 's, generative art, electronic music. DTU Compute & SODAS.

JOSS Publication

epipack: An infectious disease modeling package for Python
Published
April 05, 2021
Volume 6, Issue 60, Page 3097
Authors
Benjamin F. Maier ORCID
Institute for Theoretical Biology, Humboldt-University of Berlin, Philippstr. 13, D-10115 Berlin, Robert Koch Institute, Nordufer 20, D-13353 Berlin
Editor
Frederick Boehm ORCID
Tags
infectious disease modeling stochastic simulations computer algebra systems networks visualization

GitHub Events

Total
  • Watch event: 2
Last Year
  • Watch event: 2

Committers

Last synced: 5 months ago

All Time
  • Total Commits: 254
  • Total Committers: 1
  • Avg Commits per committer: 254.0
  • Development Distribution Score (DDS): 0.0
Past Year
  • Commits: 0
  • Committers: 0
  • Avg Commits per committer: 0.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Benjamin Maier b****r@g****m 254

Issues and Pull Requests

Last synced: 4 months ago

All Time
  • Total issues: 20
  • Total pull requests: 3
  • Average time to close issues: 29 days
  • Average time to close pull requests: 4 minutes
  • Total issue authors: 3
  • Total pull request authors: 1
  • Average comments per issue: 0.75
  • Average comments per pull request: 0.33
  • Merged pull requests: 3
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 0
  • Pull request authors: 0
  • Average comments per issue: 0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • benmaier (18)
  • zierenberg (1)
  • edwenger (1)
Pull Request Authors
  • benmaier (3)
Top Labels
Issue Labels
documentation (7) feature request (5) bug (3) enhancement (2) deprecation (1) question (1)
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • pypi 9 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 2
  • Total versions: 5
  • Total maintainers: 1
pypi.org: epipack

Fast prototyping of epidemiological models based on reaction equations. Analyze the ODEs analytically or numerically, or run stochastic simulations on networks/well-mixed systems.

  • Versions: 5
  • Dependent Packages: 0
  • Dependent Repositories: 2
  • Downloads: 9 Last month
Rankings
Dependent packages count: 10.0%
Stargazers count: 11.4%
Dependent repos count: 11.6%
Forks count: 19.1%
Average: 22.2%
Downloads: 58.9%
Maintainers (1)
Last synced: 4 months ago

Dependencies

docs/requirements.txt pypi
  • pip >=18.0
  • sphinxcontrib-websupport ==1.1.0
requirements.txt pypi
  • ipython >=7.14.0
  • ipywidgets >=7.5.1
  • matplotlib >=3.0.0
  • numpy >=1.17
  • pyglet >=1.5.15,<1.6
  • scipy >=1.3
  • sympy >=1.6
setup.py pypi
  • ipython >=7.14.0
  • ipywidgets >=7.5.1
  • matplotlib >=3.0.0
  • numpy >=1.17
  • pyglet >=1.5.15,<1.6
  • scipy >=1.3
  • sympy >=1.6