simpar package
sim module
SIR-style model simulation.
The module defines a [Sim] class. The class is initialized with base parameters for the simulation. The [step] method allows one to step through the simulation one or many time periods at a time. Infection spread and discovery parameters can be specified and the base parameters are used by default.
- class simpar.sim.Sim(max_T: int, init_susceptible: ndarray, init_infected: ndarray, init_recovered: ndarray, infection_rate: ndarray, init_discovered: ndarray | None = None, init_hidden: ndarray | None = None, infection_discovery_frac: float | ndarray = 1, recovered_discovery_frac: float | ndarray = 1, outside_rate: ndarray = 0)[source]
Bases:
object
Maintains an SIR-style model simulation on a heterogeneous population.
Infections last a single generation, after which people recover and are immune for the remainder of the simulation. Infections may be discovered immediately (e.g., through symptomatic self-reporting or surveillance) or may be discovered later (e.g., because of an asymptomatic test applied to the whole population).
During execution, S, I, and R are TxK matrices that track the number of susceptible, infectious, and recovered people in each of the K groups over T time periods. Additionally, D and H track the number of discovered and hidden non-susceptible people.
Initialize an SIR-style model simulation.
The initial state of the simulation is passed through the [init_susceptible], [init_infected], and [init_recovered] parameters. The [init_discovered] and [init_hidden] are optional parameters. If they are not set, the initial discovered and hidden assumes all recovered are discovered and [infection_discovery_frac] of infected are discovered.
Internal infection spread is determined by the [infection_rate] matrix parameter which indicates the number new infections that an infected person in one group creates in another. Additionally, the [outside_rate] parameter specifies the outside rate of infection.
To model infection discovery, the [infection_discovery_frac] parameter determines what fraction of infected are discovered in the generation they are infected. Otherwise, they become “hidden recovered.” Furthermore, the [recovered_discovery_frac] parameter determines what fraction of hidden recovered infections are discovered in each generation.
- Parameters:
max_T (int) – Maximum number of time periods to simulate.
init_susceptible (np.ndarray) – Vector of the initial number of people in each group that are susceptible.
init_infected (np.ndarray) – Vector of the initial number of people in each group that are infected.
init_recovered (np.ndarray) – Vector of the initial number of people in each group that are recovered.
infection_rate (np.ndarray) – Matrix where infection_rate[i,j] is the number of new infections that an infected person in group i creates in group j
init_discovered (np.ndarray) – Vector of the initial number of people in each group that are discovered.
init_hidden (np.ndarray) – Vector of the initial number of people in each group that are hidden.
infection_discovery_frac (float or np.ndarray) – Fraction of infections discovered in the generation they are infected. Can be specified globally (as a float) or separately for each group (as a np.ndarray). Defaults to 1.
recovered_discovery_frac (float or np.ndarray) – Fraction of hidden recovered discovered in each generation. Can be specified globally (as a float) or separately for each group (as a np.ndarray). Defaults to 1.
outside_rate (np.ndarray) – infections per time period, weighed by population of each group in a meta-group.
- property D
- property H
- property I
- property R
- property S
- step(n: int = 1, infection_rate: ndarray | None = None, infection_discovery_frac: float | ndarray | None = None, recovered_discovery_frac: float | ndarray | None = None, outside_rate: ndarray | None = None)[source]
Take [n] steps forward in the simulation.
To model change in infection and discovery parameters over time, these parameters can be provided to be applied to the next [n] time periods.
- Parameters:
infection_rate (np.ndarray) – Matrix where infection_rate[i,j] is the number of new infections that an infected person in group i creates in group j
infection_discovery_frac (float or np.ndarray) – Fraction of infections discovered in the generation they are infected. Can be specified globally (as a float) or separately for each group (as a np.ndarray). Defaults to 1.
recovered_discovery_frac (float or np.ndarray) – Fraction of hidden recovered discovered in each generation. Can be specified globally (as a float) or separately for each group (as a np.ndarray). Defaults to 1.
outside_rate (np.ndarray) – infections per time period, weighed by population of each group in a meta-group.
micro module
Methods to perform “microscopic” calculations that predict days infectious.
T | time between surveillance tests
X | beginning of period when an individual is infectious (and detectable)
D | delay to isolate after testing positive
R | total length of the infectious period
N | index of first surveillance to test
I | total time an individual is infectious AND free
========================================
Example timeline:
Individual tests positive on second test
|---|------|-----|----|-----|----|----|
0 X T T+D 2T I 3T R
N 0 1 2
========================================
We will use the above notation to discuss the calculations performed in this module. The infection begins between two surveillance tests at some point X which is uniformly distributed on [0,T]. Hence, the number of days between infection and the first surveillance test is T-X.
Note: We (pessimistically) assume a person is infectious the entire time they are PCR-detectable and that the infection level remains constant.
Using this notation, the number of days when the person is infectious is I = min(T-X+NT+D, R) where the first case represents isolating the individual before the end of their infectious period.
- simpar.micro.days_infectious(days_between_tests: float, isolation_delay: float, sensitivity: float, max_infectious_days: float)[source]
Return the expected time someone is infectious and free.
Equivalently, Compute E[I]. The number of surveillance tests N that are required for a person to test positive is a geometric random variable with probability given by [sensitivity]. So the person tests positive on test n (where the first test is n=0) with probability P(N=n) = [sensitivity] * np.pow(1-[sensitivity], n).
- Parameters:
days_between_tests (float) – Number of days between surveillance tests. Provide np.inf for no surveillance testing.
isolation_delay (float) – Number of days to isolate after positive test.
sensitivity (float) – Sensitivity of surveillance test.
max_infectious_days (float) – Maximum infectious period.
groups module
Heterogeneous population manager.
This module defines a [MetaGroup] class which describes a group of people for which most parameters are similar but who have varying degrees of social contact. Furthermore, it defines a [Population] which is comprised of multiple [MetaGroup]s. Testing strategies can be set at granularity of [MetaGroup]s.
- class simpar.groups.MetaGroup(name, pop, contact_units)[source]
Bases:
object
Initialize a meta-group.
A “meta-group” is a collection of groups. Each group within the meta-group is associated with a level of social contact.
The population is assumed to be well-mixed meaning that group i’s amount of interaction with group j is proportional to group j’s fraction of the population and both groups contact levels.
In a school setting, example meta-groups could be undergraduates, professional students, graduate students, and faculty/staff.
- static from_truncated_pareto(name: str, population: float, a: float, ub: int)[source]
Initialize a meta-group from a truncated Pareto distribution.
- Parameters:
name (str) – Name of the metagroup.
population (float) – Total population in this metagroup.
a (float) – Shape parameter (alpha) for the Pareto distribution.
ub (int) – Truncation point for the Pareto distribution.
- get_init_SIR_and_DH(init_infections: float, init_recovered: float, init_discovered: float | None = None, init_hidden: float | None = None, weight: str = 'population')[source]
Return initial SIR and DH vectors.
Given [init_infections] and [init_recovered] and optionally [init_discovered] and [init_hidden] aggregated at the meta-group level, the [weight] parameter specifies how these counts should be distributed across the groups within this metagroup. The available options for [weight] are:
“population”: Each person is equally likely to be infected.
“population x contacts”: A person’s probability of being infected is proportional to their amount of contact.
“most social”: The initial infections are in the most social group.
If [init_discovered] and [init_hidden] are not provided, assume that everyone is discovered.
- Parameters:
init_infections (float) – Initial infections count in meta-group.
init_recovered (float) – Initial recovered count in meta-group.
init_discovered (float) – Initial discovered count in meta-group.
init_hidden (float) – Initial hidden count in meta-group.
weight (str) – {population, population x contacts, most_social}
- class simpar.groups.Population(meta_groups_dict: Dict[str, MetaGroup], meta_group_contact_matrix: ndarray)[source]
Bases:
object
A population is a collection of meta-groups.
Initialize a population.
A population is defined by a dictionary of meta-groups: [meta_groups_dict]. Meta-group interactions are not assumed to be well-mixed. The matrix [meta_group_contact_matrix] indicates how metagroups interact with one another. This is encoded in the [infection_matrix] which is normalized to be in “contact units.”
- Parameters:
meta_groups_dict (Dict[str, MetaGroup]) – Dictionary of meta-groups.
meta_group_contact_matrix (np.ndarray) – Interactions between meta-groups where entry (i,j) is the conditional probability that the exposed is in meta-group j, given that the source is in meta-group i.
- static from_truncated_paretos_dictionary(d: Dict)[source]
Return a [Population] initialized from the given dictionary.
- get_init_SIR_and_DH(init_infections: ndarray, init_recovered: ndarray, init_discovered: ndarray | None = None, init_hidden: ndarray | None = None, weight: str = 'population')[source]
Return initial SIR and DH vectors.
Given [init_infections] and [init_recovered] and optionally [init_discovered] and [init_hidden] at the meta-group level, the [weight] parameter specifies how these counts should be distributed across the groups within each metagroup. The available options for [weight] are:
“population”: Each person is equally likely to be infected.
“population x contacts”: A person’s probability of being infected is proportional to their amount of contact.
“most social”: The initial infections are in the most social group.
If [init_discovered] and [init_hidden] are not provided, assume that everyone is discovered.
- Parameters:
init_infections (np.ndarray) – Initial infections per meta-group.
init_recovered (np.ndarray) – Initial recovered per meta-group.
init_discovered (np.ndarray) – Initial discovered per meta-group.
init_hidden (np.ndarray) – Initial hidden per meta-group.
weight (str) – {population, population x contacts, most_social}
strategy module
Manage types of surveillance tests and strategies.
This module defines a [Test] class which maintains properties about a specific surveillance test. Furthermore, it defines an [IsolationRegime], [ArrivalTestingRegime], and [TestingRegime] which are used to comprise a [Strategy]. This specifies how long people are isolated, how people are tested upon arrival, and what testing regime(s) are used after they arrive and for what periods of time.
- class simpar.strategy.ArrivalTestingRegime(pre_departure_test_type: List[Test], arrival_test_type: List[Test])[source]
Bases:
object
This class maintains an arrival testing regime.
It offers methods to return the percentage of people that are discovered in pre-departure testing and the percentage of people that are discovered upon arrival. This allows for planning surrounding potential isolation of those who arrive and test positive.
Initialize an arrival testing regime.
- Parameters:
- static from_dictionary(d: Dict, tests: Dict[str, Test])[source]
Initialize a [ArrivalTestingRegime] instance.
The dictionary [d] should contain two keys: [pre_departure_test_type] and [arrival_test_type] which contain list of strings. These are interpreted as keys in the [tests] dictionary which provides the corresponding [Test] instance.
- Parameters:
d (Dict) – Dictionary representing the arrival testing regime.
tests (Dict[str, Test]) – Dictionary of [Test] instances.
- class simpar.strategy.IsolationRegime(iso_lengths: List[int], iso_props: List[int])[source]
Bases:
object
This class maintains properties about an isolation regime.
Initialize an isolation regime.
- Parameters:
iso_lengths (List[int]) – List of isolation lengths (in days).
iso_props (List[int])) – List of probability of isolation lengths.
- class simpar.strategy.Strategy(name: str, period_lengths: List[int], testing_regimes: List[TestingRegime], transmission_multipliers: List[float] | None = None, arrival_testing_regime: ArrivalTestingRegime | None = None, isolation_regime: IsolationRegime | None = None)[source]
Bases:
object
This class maintains a testing strategy comprised of an [IsolationRegime], [ArrivalTestingRegime], and a list of [TestingRegime]s.
If offers methods to return the initial number of infections, the initial number of recovered, and the arrival discovered (useful for understanding isolation capacity needs).
Initialize a testing strategy.
- Parameters:
name (str) – Name for this strategy.
period_lengths (List[int]) – Length (in generations) of each period of the simulation.
testing_regimes (List[TestingRegime]) – Testing regime to be used in each period of the simulation.
transmission_multipliers (List[float]) – Transmission multiplier to be used in each period of the simulation. Defaults to 1.
arrival_testing_regime (ArrivalTestingRegime) – Arrival testing regime to be used. Defaults to None.
isolation_regime (IsolationRegime) – Isolation regime to be used. Defaults to None.
- static from_dictionary(d: Dict, arrival_testing_regimes: Dict, testing_regimes: Dict, isolation_regimes: Dict)[source]
Initialize a [Strategy] instance.
The dictionary [d] should contain a key [testing_regimes] and [isolation_regime] and may contain a key [arrival_testing_regime]. These should be keys in [arrival_testing_regimes], [testing_regimes], and [isolation_regimes], respectively.
- Parameters:
d (Dict) – Dictionary representing the strategy.
arrival_testing_regimes (Dict) – Dictionary of [ArrivalTestingRegimes] instances.
testing_regimes (Dict) – Dictionary of [TestingRegimes] instances.
isolation_regimes (Dict) – Dictionary of [IsolationRegime] instances.
- get_initial_discovered(recovered: ndarray, pct_recovered_discovered: ndarray, active_infections: ndarray)[source]
Return the initial discovered when this strategy is used.
- Parameters:
recovered (np.ndarray) – Recovered per meta-group.
pct_recovered_discovered (np.ndarray) – Percentage of the recovered population that is discovered per meta-group.
active_infections (np.ndarray) – True number of active infections per meta-group.
Return the initial hidden when this strategy is used.
- Parameters:
recovered (np.ndarray) – Recovered per meta-group.
pct_recovered_discovered (np.ndarray) – Percentage of the recovered population that is discovered per meta-group.
active_infections (np.ndarray) – True number of active infections per meta-group.
- class simpar.strategy.Test(name: str, test_sensitivity: float, test_delay: float, compliance: float = 1)[source]
Bases:
object
Initialize a test
- Parameters:
name (str) – Name of the surveillance test.
test_sensitivity (float) – Probability of positive given infectious.
test_delay (float) – Delay in receiving results from test (in days).
compliance (float, optional) – Compliance with test. Defaults to 1.
- class simpar.strategy.TestingRegime(test_type: List[Test], tests_per_week: ndarray)[source]
Bases:
object
Initialize a testing regime.
- Parameters:
test_type (List[Test]) – The test type to be used per meta-group.
tests_per_week (np.ndarray) – Test frequency per meta-group.
- static from_dictionary(d: Dict, tests: Dict[str, Test])[source]
Initialize a [TestingRegime] instance.
The dictionary [d] should contain a key [test_type] which contain list of strings. These are interpreted as keys in the [tests] dictionary which provides the corresponding [Test] instance.
- Parameters:
d (Dict) – Dictionary representing the testing regime.
tests (Dict[str, Test]) – Dictionary of [Test] instances.
- get_days_infectious(max_infectious_days: float)[source]
Return the expected number of days infectious.
This value requires the context of the maximum infectious days.
- Parameters:
max_infectious_days (float) – Max days someone is infected.
- get_infection_discovery_frac(symptomatic_rate: float)[source]
Return the discovery rate among infected people.
This value is equivalent to the “true sensitivity” of a test when surveillance testing is in place. Otherwise, it is the test sensitivity multiplied by the symptomatic rate as only those that are symptomatic seek out a test. This assumes all symptomatic people will seek out a test. I.e. compliance among the symptomatic is 100%.
- Parameters:
symptomatic_rate (float) – Symptomatic rate.
- get_recovered_discovery_frac(no_surveillance_test_rate: ndarray)[source]
Return the discovery rate among recovered people.
This value is equivalent to the “true sensitivity” of a test when surveillance testing is in place. This serves as a rough estimate which becomes more inaccurate with less frequent testing. If there is no surveillance testing, it is the no surveillance test rate multiplied by the test sensitivity.
- Parameters:
no_surveillance_test_rate (np.ndarray) – Test rate per meta-group.
scenario module
Scenario for disease spread.
This module defines a [Scenario] class which maintains a scenario on which a testing strategy can be applied. By combining a scenario with a testing strategy, a simulation can be run allowing for the comparison of multiple testing strategies on a single scenario.
- class simpar.scenario.Scenario(population: Population, max_T: int, generation_time: float, infections_per_contact_unit: ndarray, init_infections: ndarray, init_recovered: ndarray, outside_rate: ndarray, max_infectious_days: float, symptomatic_rate: float, no_surveillance_test_rate: ndarray, pct_recovered_discovered: ndarray, hospitalization_rates: ndarray, arrival_period: float, tests: Dict[str, Test])[source]
Bases:
object
This class maintains a scenario on which a testing strategy can be applied.
A scenario is a list of parameters which describe the population of people, the environment, and the disease spreading. By combining a scenario with a testing strategy, a simulation can be run allowing for the comparison of multiple testing strategies on a single scenario.
Initialize a [Scenario] instance.
- Parameters:
population (Population) – The population.
max_T (int) – The length of the simulation.
generation_time (float) – Number of days per generation of sim.
infections_per_contact_unit (np.ndarray) – Number of infections per contact unit across meta-groups.
init_infections (np.ndarray) – Number of initial infections across meta-groups.
init_recovered (np.ndarray) – Number of initial recovered across meta-groups.
outside_rate (np.ndarray) – The number of infections caused by outside infection in a generation time across meta-groups.
max_infectious_days (float) – Maximum period someone is infectious.
symptomatic_rate (float) – Symptomatic rate.
no_surveillance_test_rate (np.ndarray) – Rate at which people test under no surveillance testing across meta-groups.
pct_recovered_discovered (np.ndarray) – Percentage of the recovered population who are discovered across meta-groups.
hospitalization_rates (np.ndarray) – Rate of hospitalizations among those who get infected across meta-groups.
arrival_period (float) – The number of generations the arrival occurs over. Testing is assumed constant over these days. If there is no arrival period, set to None.
tests (Dict[str, Test]) – Dictionary of available tests.
trajectory module
Simulation trajectory manager.
Defines a [Trajectory] class which is comprised of a fully run [Sim] that was the result of applying a given [Strategy] to a [Scenario]. The class offers methods to return various metrics.
- class simpar.trajectory.Trajectory(scenario: Scenario, strategy: Strategy, sim: Sim, color: str = 'black', name: str | None = None)[source]
Bases:
object
Manages all of the attributes of a simulation run.
This includes the underlying simulation [Sim] and the scenario [Scenario] and the strategy [Strategy] that was used. It also maintains a color and name for use when plotting trajectories.
Initialize a [Trajectory] instance.
- Parameters:
- get_bucket(bucket: str, meta_groups: List[str] | None = None, aggregate: bool = True, cumulative: bool = False, normalize: bool = False)[source]
Return the given bucket vector.
- Parameters:
bucket (str) – One of the simulation buckets: {S, I, R, D, H}.
meta_groups (List[str]) – Meta-groups to aggregate over. Default to all.
aggregate (bool) – Aggregate over the meta-groups if True.
cumulative (bool) – Return cumulative metric over time if True.
normalize (bool) – Normalize relative to total population.
- get_hospitalizations(meta_groups: List[str] | None = None, aggregate: bool = True, cumulative: bool = False, normalize: bool = False)[source]
Return hospitalizations as computed from hospitalization rates.
- Parameters:
meta_groups (List[str]) – Meta-groups to aggregate over. Default to all.
aggregate (bool) – Aggregate over the meta-groups if True.
cumulative (bool) – Return cumulative metric over time if True.
normalize (bool) – Normalize relative to total population.
- get_isolated(meta_groups: List[str] | None = None, aggregate: bool = True, cumulative: bool = False, normalize: bool = False)[source]
Return the number of isolated individuals at each generation.
- Parameters:
meta_groups (List[str]) – Limit to isolated in these metagroups.
aggregate (bool) – Aggregate over the meta-groups if True.
cumulative (bool) – Return cumulative metric over time if True.
normalize (bool) – Normalize relative to total population.