EoN module

Introduction

EoN (Epidemics on Networks) is a Python package for the simulation of epidemics on networks and solving ODE models of disease spread.

The algorithms are based on the book

Mathematics of Epidemics on Networks: from Exact to Approximate Models by Kiss, Miller & Simon

Please cite the book if using these algorithms

For simulations, we assume that input networks are NetworkX graphs; see https://networkx.github.io/

EoN consists of several sets of algorithms.

  • The first deals with stochastic simulation of epidemics on networks. The most significant of these are fast_SIS and fast_SIR which usually outperform Gillespie algorithms (also included). These algorithms are discussed in more detail in the appendix of the book.
  • A significant extension of these simulations is a set of tools designed to visualize and animate simulated epidemics, and generally help investigate a given stochastic simulation.
  • Another set deals with numerical solution of systems of analytic equations derived in the book. For these it is possible to either provide the degree distribution, or simply use a network and let the code determine the degree distribution.
  • There are a few additional algorithms which are not described in the book, but which we believe will be useful. Most notably, related to visualization and generation of animations.

Distributed under MIT license. See license.txt for full details.

Simulation Toolkit

This submodule deals with epidemic simulation. We start with a quick list of the functions with links to the individual functions. A brief description is below.

Quick list

fast_SIR(G, tau, gamma[, initial_infecteds, …]) fast SIR simulation for exponentially distributed infection and recovery times
fast_nonMarkov_SIR(G[, trans_time_fxn, …]) A modification of the algorithm in figure A.3 of Kiss, Miller, & Simon to allow for user-defined rules governing time of transmission.
fast_SIS(G, tau, gamma[, initial_infecteds, …]) Fast SIS simulations for epidemics on weighted or unweighted networks, allowing edge and node weights to scale the transmission and recovery rates.
fast_nonMarkov_SIS(G[, trans_time_fxn, …]) Similar to fast_nonMarkov_SIR.
Gillespie_SIR(G, tau, gamma[, …]) Performs SIR simulations for epidemics.
Gillespie_SIS(G, tau, gamma[, …]) Performs SIS simulations for epidemics on networks with or without weighted edges.
Gillespie_Arbitrary(G, …[, tmin, tmax, …]) Performs simulations for epidemics, allowing more flexibility than SIR/SIS.
basic_discrete_SIR(G, p[, …]) Performs simple discrete SIR simulation assuming constant transmission probability p.
basic_discrete_SIS(G, p[, …]) Does a simulation of the simple case of all nodes transmitting with probability p independently to each susceptible neighbor and then recovering.
discrete_SIR(G[, test_transmission, args, …]) Simulates an SIR epidemic on G in discrete time, allowing user-specified transmission rules
percolate_network(G, p) Performs percolation on a network G with each edge persisting with probability p
directed_percolate_network(G, tau, gamma[, …]) performs directed percolation, assuming that transmission and recovery are Markovian
nonMarkov_directed_percolate_network_with_timing(G, …) Performs directed percolation on G for user-specified transmission time and recovery time distributions.
nonMarkov_directed_percolate_network(G, xi, …) performs directed percolation on a network following user-specified rules.
estimate_SIR_prob_size(G, p) Uses percolation to estimate the probability and size of epidemics assuming constant transmission probability p
estimate_SIR_prob_size_from_dir_perc(H) Estimates probability and size of SIR epidemics for an input network after directed percolation
estimate_directed_SIR_prob_size(G, tau, gamma) Predicts probability and attack rate assuming continuous-time Markovian SIR disease on network G
estimate_nonMarkov_SIR_prob_size_with_timing(G, …) estimates probability and size for user-input transmission and recovery time functions.
estimate_nonMarkov_SIR_prob_size(G, xi, …) Predicts epidemic probability and size using nonMarkov_directed_percolate_network.
get_infected_nodes(G, tau, gamma[, …]) Finds all eventually infected nodes in an SIR simulation, through a percolation approach
percolation_based_discrete_SIR(G, p[, …]) perfoms a simple SIR epidemic but using percolation as the underlying method.

Short descriptions

  • Event-based algorithms:

    These algorithms use an efficient approach to simulate epidemics. fast_SIR and fast_SIS assume constant transmission and recovery rates, while fast_nonMarkov_SIR and fast_nonMarkov_SIS allow the user to specify more detailed rules for transmission.

    • fast_SIR
    • fast_nonMarkov_SIR
    • fast_SIS
    • fast_nonMarkov_SIS
  • Gillespie Algorithms

    These algorithms simulate epidemics assuming constant transmission and recovery rates. They are commonly used, but in many cases are slower than the event driven methods. I do not see evidence that they are ever significantly faster. It is not very practical to get away from the constant rate assumptions so I prefer to avoid them. However, the Gillespie_Arbitrary allows the user to do SEIR, SIRS, or any of a number of other more exotic scenarios that are not currently in the event-driven code.

    • Gillespie_SIR
    • Gillespie_SIS
    • Gillespie_Arbitrary
  • Discrete-time algorithms

    These algirthms are appropriate for where we separate infection into generations. We assume infection lasts a single time step. The basic_* algorithms assume that transmission occurs with probability p for all edges. In contrast discrete_SIR allows for very general user-specified transmission rules.

    • basic_discrete_SIR
    • basic_discrete_SIS
    • discrete_SIR
  • Percolation-based approaches

    There is a close relation between percolation and SIR disease which is described in Chapter 6 of the book. Many of these algorithms are related to demonstrating the equivalence as outlined in the book, and are not really the most efficient way to simulate an epidemic. However, these algorithms will be useful for estimating probability and size of epidemics.

    • percolate_network (undirected percolation corresponding to fixed transmission probability)
    • directed_percolate_network (directed percolation corresponding to constant transmission and recovery rates)
    • nonMarkov_directed_percolate_network_with_timing (uses user-generated duration and transmission time distributions)
    • nonMarkov_directed_percolate_network (uses user-generated transmission rules)
    • estimate_SIR_prob_size (estimates prob/size from an undirected percolated network - only appropriate if constant p)
    • estimate_SIR_prob_size_from_dir_perc (estimates epi prob and size from a given percolated network)
    • estimate_directed_SIR_prob_size (estimates based on constant transmission and recovery rates)
    • estimate_nonMarkov_SIR_prob_size_with_timing (estimates based on user-generated transmission and recovery time distributions)
    • estimate_nonMarkov_SIR_prob_size (estimates based on user-generated transmission rules)
    • get_infected_nodes (simulates epidemic and returns final infected nodes)
    • percolation_based_discrete_SIR

Simulation Investigation toolkit

We can study simulations in detail through the Simulation_Investigation class. This includes automated generation of animations.

This is particularly useful if we want to look at time series or at animations of the network as the disease spreads.

Some examples are provided.

Quick List

display(time[, ts_plots, ts_list, nodelist, …]) Provides a plot of the network at a specific time and (optionally) some of the time series
animate([frame_times, ts_plots, ts_list, …]) As in display, but this produces an animation.
node_history(node) returns the history of a node.
node_status(node, time) returns the status of a given node at a given time.
get_statuses([nodelist, time]) returns the status of nodes at a given time.
summary([nodelist]) Provides the population-scale summary of the dynamics: t, S, I, and R
t() Returns the times of events Generally better to get these all through summary()
S() Returns the number susceptible at each time.
I() Returns the number infected at each time Generally better to get these all through summary()
R() Returns the number recovered at each time Generally better to get these all through summary()
transmissions() Returns a list of tuples (t,u,v) stating that node u infected node v at time t.
transmission_tree() Produces a MultiDigraph whose edges correspond to transmission events.
add_timeseries(t, S, I[, R, colordict, label]) This allows us to include some additional timeseries for comparision with the simulation.
update_ts_kwargs(ts, **kwargs) Allows us to change some of the matplotlib key word arguments for a timeseries object
update_ts_label(ts, label) updates the label for time series plots
update_ts_colordict(ts, colordict) updates the colordict for time series plots
sim_update_kwargs(**kwargs) Allows us to change some of the matplotlib key word arguments for the simulation.
sim_update_label(label) updates the label for the simulation in the time series plots
sim_update_colordict(colordict) updates the colordict for the simulation
set_pos(pos) Set the position of the nodes.

Short description

  • Visualizations

    There are two main commands for visualization. We can either produce a snapshot at a given time, or produce an animation. In either case we can optionally include plots of S, I, (and R) as functions of time.

    • display (allows us to plot a graph at a specific time
      point, and to optionally include the calculated time series)
    • animate (allows us to plot a graph at many time points
      We can create a visualization such as mp4, or save each individual frame of an animation. The time series are optional.
  • Data about simulation

    Often we’ll want to be able to check what happened to specific nodes in the network, or we’ll want to know what the time history of the outbreak looked like

    • node_history
    • node_status returns the status of a node at a given time
    • get_statuses returns the status of a collection of nodes at
      a given time (in a dict).
    • summary returns t, S, I, (and if SIR R) for the population (or a subset of the population)
    • t
    • S
    • I
    • R
    • transmissions returns a list of 3-tuples of the form (t, u, v) stating that u transmitted to v at time t.
    • transmission_tree returns a MultiDiGraph where an edge from u to v with attribute time = t means that u transmitted to v at time t. (For SIR this is a tree or a forest)
  • Details for plotting

    The remaining commands are to do with the specifics of how the plots appear

    • update_ts_kwargs
    • update_ts_label
    • update_ts_colordict
    • sim_update_kwargs
    • sim_update_label
    • sim_update_colordict
    • set_pos

Analytic Toolkit

This submodule deals with solution to systems of equations appearing in the book. The majority of these also have a version that take a graph G. There are additional functions that calculate properties which these need.

Quick list

SIS_individual_based(G, tau, gamma[, rho, …]) Encodes System (3.7) of Kiss, Miller, & Simon.
SIS_individual_based_pure_IC(G, tau, gamma, …) Encodes System (3.7) of Kiss, Miller, & Simon.
SIS_pair_based(G, tau, gamma[, rho, …]) Encodes System (3.26) of Kiss, Miller, & Simon.
SIS_pair_based_pure_IC(G, tau, gamma, …[, …]) Encodes System (3.26) of Kiss, Miller, & Simon, using a “pure initial condition”.
SIR_individual_based(G, tau, gamma[, rho, …]) Encodes System (3.30) of Kiss, Miller, & Simon.
SIR_individual_based_pure_IC(G, tau, gamma, …) Encodes System (3.30) of Kiss, Miller, & Simon.
SIR_pair_based(G, tau, gamma[, rho, …]) Encodes System (3.39) of Kiss, Miller, & Simon.
SIR_pair_based_pure_IC(G, tau, gamma, …[, …]) Encodes System (3.39) of Kiss, Miller, & Simon, using a “pure initial condition”.
SIS_homogeneous_meanfield(S0, I0, n, tau, gamma) Encodes System (4.8) of Kiss, Miller, & Simon.
SIR_homogeneous_meanfield(S0, I0, R0, n, …) Encodes System (4.9) of Kiss, Miller, & Simon.
SIS_homogeneous_pairwise(S0, I0, SI0, SS0, …) Encodes System (4.10) of Kiss, Miller, & Simon.
SIS_homogeneous_pairwise_from_graph(G, tau, …) Calls SIS_homogeneous_pairwise after calculating S0, I0, SI0, SS0, n based on the graph G and initial fraction infected rho.
SIR_homogeneous_pairwise(S0, I0, R0, SI0, …) Encodes System (4.11) of Kiss, Miller, & Simon.
SIR_homogeneous_pairwise_from_graph(G, tau, …) Calls SIR_homogeneous_pairwise after calculating S0, I0, R0, SI0, SS0, n, based on the graph G and initial fraction infected rho.
SIS_heterogeneous_meanfield(Sk0, Ik0, tau, gamma) Encodes System (5.10) of Kiss, Miller, & Simon.
SIS_heterogeneous_meanfield_from_graph(G, …) Calls SIS_heterogeneous_meanfield after calculating Sk0, Ik0 based on the graph G and random fraction infected rho.
SIR_heterogeneous_meanfield(Sk0, Ik0, Rk0, …) Encodes System (5.11) of Kiss, Miller, & Simon.
SIR_heterogeneous_meanfield_from_graph(G, …) Calls SIR_heterogeneous_meanfield after calculating Sk0, Ik0, Rk0 based on a graph G and initial fraction infected rho.
SIS_heterogeneous_pairwise(Sk0, Ik0, SkSl0, …) Encodes System (5.13) of Kiss, Miller, & Simon.
SIS_heterogeneous_pairwise_from_graph(G, …) Calls SIS_heterogeneous_pairwise after calculating Sk0, Ik0, SkSl0, SkIl0, IkIl0 from a graph G and initial fraction infected rho.
SIR_heterogeneous_pairwise(Sk0, Ik0, Rk0, …) Encodes System (5.15) of Kiss, Miller, & Simon.
SIR_heterogeneous_pairwise_from_graph(G, …) Calls SIR_heterogeneous_pairwise after calculating Sk0, Ik0, Rk0, SkSl0, SkIl0 from a graph G and initial fraction infected rho.
SIS_compact_pairwise(Sk0, Ik0, SI0, SS0, …) Encodes system (5.18) of Kiss, Miller, & Simon.
SIS_compact_pairwise_from_graph(G, tau, gamma) Calls SIS_compact_pairwise after calculating Sk0, Ik0, SI0, SS0, II0 from the graph G and initial fraction infected rho.
SIR_compact_pairwise(Sk0, I0, R0, SS0, SI0, …) Encodes system (5.19) of Kiss, Miller, & Simon.
SIR_compact_pairwise_from_graph(G, tau, gamma) Calls SIR_compact_pairwise after calculating Sk0, I0, R0, SS0, SI0 from the graph G and initial fraction infected rho.
SIS_super_compact_pairwise(S0, I0, SS0, SI0, …) Encodes system (5.20) of Kiss, Miller, & Simon.
SIS_super_compact_pairwise_from_graph(G, …) Calls SIS_super_compact_pairwise after calculating S0, I0, SS0, SI0, II0 from the graph G and initial fraction infected rho
SIR_super_compact_pairwise(R0, SS0, SI0, N, …) Encodes system (5.22) of Kiss, Miller, & Simon.
SIR_super_compact_pairwise_from_graph(G, …) Calls SIR_super_compact_pairwise after calculating R0, SS0, SI0 from the graph G and initial fraction infected rho
SIS_effective_degree(Ssi0, Isi0, tau, gamma) Encodes system (5.36) of Kiss, Miller, & Simon. Please cite the
SIS_effective_degree_from_graph(G, tau, gamma) Calls SIS_effective_degree after calculating Ssi0, Isi0 from the graph G and initialf fraction infected rho.
SIR_effective_degree(S_si0, I0, R0, tau, gamma) Encodes system (5.38) of Kiss, Miller, & Simon.
SIR_effective_degree_from_graph(G, tau, gamma) Calls SIR_effective_degree after calculating S_si0, I0, R0 from the graph G and initial fraction infected rho
SIR_compact_effective_degree(Skappa0, I0, …) Encodes system (5.43) of Kiss, Miller, & Simon.
SIR_compact_effective_degree_from_graph(G, …) Calls SIR_compact_effective_degree after calculating Skappa0, I0, R0, SI0 from the graph G and initial fraction infected rho.
SIS_compact_effective_degree(Sk0, Ik0, SI0, …) Encodes system (5.44) of Kiss, Miller, & Simon.
SIS_compact_effective_degree_from_graph(G, …) because the SIS compact effective degree model is identical to the compact pairwise model, simply calls SIS_compact_pairwise_from_graph
Epi_Prob_discrete(Pk, p[, number_its]) Encodes System (6.2) of Kiss, Miller, & Simon.
Epi_Prob_cts_time(Pk, tau, gamma[, umin, …]) Encodes System (6.3) of Kiss, Miller, & Simon.
Epi_Prob_non_Markovian(Pk, Pxidxi, po[, …]) Encodes system (6.5) of Kiss, Miller, & Simon.
Attack_rate_discrete(Pk, p[, rho, Sk0, …]) Encodes systems (6.6) and (6.10) of Kiss, Miller, & Simon.
Attack_rate_discrete_from_graph(G, p[, …]) if initial_infecteds and initial_recovereds is defined, then it will find Sk0, phiS0, and phiR0 and then call Attack_rate_discrete.
Attack_rate_cts_time(Pk, tau, gamma[, …]) Encodes system (6.7) of Kiss, Miller, & Simon.
Attack_rate_cts_time_from_graph(G, tau, gamma) Given a graph, predicts the attack rate for Configuration Model networks with the given degree distribution.
Attack_rate_non_Markovian(Pk, Pzetadzeta, pi) Encodes system (6.8) of Kiss, Miller, & Simon.
Attack_rate_discrete(Pk, p[, rho, Sk0, …]) Encodes systems (6.6) and (6.10) of Kiss, Miller, & Simon.
EBCM_discrete(N, psihat, psihatPrime, p, phiS0) Encodes system (6.11) of Kiss, Miller, & Simon.
EBCM_discrete_from_graph(G, p[, …]) Takes a given graph, finds the degree distribution (from which it gets psi), assumes a constant proportion of the population is infected at time 0, and then uses the discrete EBCM model.
EBCM(N, psihat, psihatPrime, tau, gamma, phiS0) Encodes system (6.12) of Kiss, Miller, & Simon.
EBCM_uniform_introduction(N, psi, psiPrime, …) Handles the case that the disease is introduced uniformly as opposed to depending on degree.
EBCM_from_graph(G, tau, gamma[, …]) Given network G and rho, calculates N, psihat, psihatPrime, and calls EBCM.
EBCM_pref_mix(N, Pk, Pnk, tau, gamma[, rho, …]) Encodes the system derived in exercise 6.21 of Kiss, Miller, & Simon.
EBCM_pref_mix_from_graph(G, tau, gamma[, …]) Takes a given graph, finds degree correlations, and calls EBCM_pref_mix
EBCM_pref_mix_discrete(N, Pk, Pnk, p[, rho, …]) Encodes the discrete version of exercise 6.21 of Kiss, Miller, & Simon.
EBCM_pref_mix_discrete_from_graph(G, p[, …]) Takes a given graph, finds degree correlations, and calls EBCM_pref_mix_discrete
get_Pk(G) Used in several places so that we can input a graph and then we can call the methods that depend on the degree distribution
get_PGF(Pk) Given a degree distribution (as a dict), returns the probability generating function
get_PGFPrime(Pk) Given a degree distribution (as a dict) returns the function \(\psi'(x)\)
get_PGFDPrime(Pk) Given a degree distribution (as a dict) returns the function \(\psi''(x)\)
estimate_R0(G[, tau, gamma, transmissibility]) provides the estimate of the reproductive number R_0 = T <K^2-K>/<K>

Short description

These come from the book. The numbers given below are the equation numbers in the book.

  • Chapter 3

    This chapter deals with models assuming we know the full network structure.

    • System (3.7): SIS model: Closes equations by assuming that knowing the probabilities for nodes to have each status is enough to predict impact of their interactions (ignores temporal correlation between statuses of neighbors).

      • SIS_individual_based
      • SIS_individual_based_pure_IC

      The pure_IC version assumes that some nodes begin infected with probability 1 and the others are susceptible with probability 1.

    • System (3.26): assumes that tracking pair correlations is enough. Many more equations than individual-based.

      • SIS_pair_based
      • SIS_pair_based_pure_IC
    • System (3.30) SIR equivalent of corresponding SIS model.

      • SIR_individual_based
      • SIR_individual_based_pure_IC
    • System (3.39) SIR equivalent of corresponding SIS model.

      • SIR_pair_based
      • SIR_pair_based_pure_IC
  • Chapter 4

    This chapter attempts to approximate the exact dynamics by ignoring heterogeneity in degree.

    • System (4.8) Assumes dynamics determined by average number of contacts and number of nodes of each status.

      • SIS_homogeneous_meanfield
    • System (4.9) As for SIS.

      • SIR_homogeneous_meanfield
    • System (4.10) Assumes dynamics are determined by the average number of contacts, nodes of each status, and pairs of each status.

      • SIS_homogeneous_pairwise
      • SIS_homogeneous_pairwise_from_graph (reads properties from input graph)
    • System (4.11)

      • SIR_homogeneous_pairwise
      • SIR_homogeneous_pairwise_from_graph
  • Chapter 5

    This chapter attempts to approximate the exact dynamics and incorporates heterogeneity in degree (at the cost of more complex models)

    • System (5.10)

      • SIS_heterogeneous_meanfield
      • SIS_heterogeneous_meanfield_from_graph
    • System (5.11)

      • SIR_heterogeneous_meanfield
      • SIR_heterogeneous_meanfield_from_graph
    • System (5.13)

      • SIS_heterogeneous_pairwise
      • SIS_heterogeneous_pairwise_from_graph
    • System (5.15)

      • SIR_heterogeneous_pairwise
      • SIR_heterogeneous_pairwise_from_graph
    • System (5.18)

      • SIS_compact_pairwise
      • SIS_compact_pairwise_from_graph
    • System (5.19)

      • SIR_compact_pairwise
      • SIR_compact_pairwise_from_graph
    • System (5.20)

      • SIS_super_compact_pairwise
      • SIS_super_compact_pairwise_from_graph
    • System (5.22)

      • SIR_super_compact_pairwise
      • SIR_super_compact_pairwise_from_graph
    • System (5.36)

      • SIS_effective_degree
      • SIS_effective_degree_from_graph
    • System (5.38)

      • SIR_effective_degree
      • SIR_effective_degree_from_graph
    • System (5.43)

      • SIR_compact_effective_degree
      • SIR_compact_effective_degree_from_graph
    • System (5.44)

      • SIS_compact_effective_degree
      • SIS_compact_effective_degree_from_graph
  • Chapter 6

    This chapter uses percolation-based techniques to explore epidemic properties.

    • System (6.2) Given a degree distribution and uniform transmission probability, find epidemic probability.

      • Epi_Prob_discrete
    • System (6.3) As in 6.2, but assuming constant transmission and recovery rates.

      • Epi_Prob_cts_time
    • System (6.5) As in 6.2, but with user-specified transmission rules

      • Epi_Prob_non_Markovian
    • System (6.6) Given a degree distribution, initial proportion infected, and transmission probability, find attack rate. See also System (6.10).

      • Attack_rate_discrete
      • Attack_rate_discrete_from_graph
    • System (6.7) as in 6.6, but assuming constant transmission and recovery rates.

      • Attack_rate_cts_time
      • Attack_rate_cts_time_from_graph
    • System (6.8) As in 6.6, but with user-specified transmission rules

      • Attack_rate_non_Markovian
    • System (6.10) See code for System (6.6).

    • System (6.11) Perform EBCM calculations for discrete-time.

      • EBCM_discrete
      • EBCM_discrete_from_graph
    • System (6.12) Perform EBCM calculations for continuous-time.

      • EBCM allows initial status to be degree dependant.
      • EBCM_uniform_introduction assumes disease introduced at t=0 uniformly at random
      • EBCM_from_graph assumes disease introduced at t=0 uniformly at random in network of given degree distribution.
    • exercise 6.21 Deals with the EBCM model assuming preferential mixing.
      • EBCM_pref_mix
      • EBCM_pref_mix_from_graph
      • EBCM_pref_mix_discrete
      • EBCM_pref_mix_discrete_from_graph

Auxiliary Functions

We have a few additional functions which are of value.

Quick List

get_time_shift(times, L, threshold) Identifies the first time at which list/array L crosses a threshold.
subsample(report_times, times, status1[, …]) Given

Short Description

  • get_time_shift (allows us to shift plots to eliminate the effect of early-time stochasticity)
  • subsample (allows us to take output given at a stochastic set of times and get output at given times - particularly useful to allow for averaging multiple simulations)