Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Setting up the model and post-processing data
Loading...
Loading...
Loading...
(Any more advanced mathematical or computational methods used, or possible configuration options, that only specialized users would need to change)
Loading...
Loading...
(Ie using a totally different compartmental model or outcomes model)
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This page describes how users specify the names, sizes, and connectivities of the different subpopulations comprising the total population to be modeled
The subpop_setup
section of the configuration file is where users can input the information required to define a population structure on which to simulate the model. The options allow the user to determine the population size of each subpopulation that makes up the overall population, and to specify the amount of mixing that occurs between each pair of subpopulations.
An example configuration file with the global header and the spatial_setup section is below:
geodata
required
path to file
path to file relative to data_path
mobility
required
path to file
path to file relative to data_path
selected
optional
string
name of selected location ingeodata
geodata
filegeodata
is a .csv with column headers, with at least two columns: subpop
and population
.
nodenames
is the name of a column in geodata
that specifies unique geographical identification strings for each subpopulation.
selected
is the list of selected locations in geodata to be modeled
mobility
fileThe mobility
file is a .csv file (it has to contain .csv as extension) with long form comma separated values. Columns have to be named ori
, dest
, amount,
with amount being the average number individuals moving from the origin subpopulation ori
to destination subpopulation dest
on any given day. Details on the mathematics of this model of contact are explained in the Model Description section. Unassigned relations are assumed to be zero. The location entries in the ori
and dest
columns should match exactly the subpop
column in geodata.csv
It is also possible, but not recommended to specify the mobility
file as a .txt with space-separated values in the shape of a matrix. This matrix is symmetric and of size K x K, with K being the number of rows in geodata
. The above example corresponds to
To simulate a simple population structure with two subpopulations, a large province with 10,000 individuals and a small province with only 1,000 individuals, where every day 100 residents of the large province travel to the small province and interact with residents there, and 50 residents of the small province visit the large province
geodata.csv
contains the population structure (with columns subpop
and population
)
mobility.csv
contains
This section describes how to specify the compartmental model of infectious disease transmission.
We want to allow users to work with a wide variety of infectious diseases or, one infectious disease under a wide variety of modeling assumptions. To facilitate this, we allow the user to specify their compartmental model of disease dynamics via the configuration file.
We originally considered asking users to specify each compartment and transition manually. However, we quickly found that this created long, confusing configuration files, and so we created a shorthand to more succinctly specify both compartments and transitions between them. This works especially well for models where individuals are stratified by other properties (like age, vaccination status, etc.) in addition to their infection status.
The model is specified in two separate sections of the configuration file. In the compartments
section, users define the possible states individuals can be categorized into. Then in the seir
section, users define the possible transitions between states, the values of parameters that govern the rates of these transitions, and the numerical method used to simulate the model.
An example section of a configuration file defining a simple SIR model is below.
compartments
)The first stage of specifying the model is to define the infection states (variables) that the model will track. These "compartments" are defined first in the compartments
section of the config file, before describing the processes that lead to transitions between them. The compartments are defined separately from the rest of the model because they are also used by the seeding
section that defines initial conditions and importations.
For simple disease models, the compartments can simply be listed with whatever notation the user chooses. For example, for a simple SIR model, the compartments could be ["S", "I", "R"]
. The config also requires that there be a variable name for the property of the individual that these compartments describe, which for example in this case could be infection_stage
Our syntax allows for more complex models to be specified without much additional notation. For example, consider a model of a disease that followed SIR dynamics but for which individuals could receive vaccination, which might change how they experience infection.
In this case we can specify compartments as the cross product of multiple states of interest. For example:
Corresponds to 6 compartments, which the code internally converts to this data frame
In order to more easily describe transitions, we want to be able to refer to a compartment by its components, but then use it by its compartment name.
If the user wants to specify a model in which some compartments are repeated across states but others are not, there will be pros and cons of how the model is specified. Specifying it using the cross product notation is simpler, less error prone, and makes config files easier to read, and there is no issue with having compartments that have zero individuals in them throughout the model. However, for very large models, extra compartments increase the memory required to conduct the simulation, and so having unnecessary compartments tracked may not be desired.
For example, consider a model of a disease that follows SI dynamics in two separate age groups (children and adults), but for which only adults receive vaccination, with one or two doses of vaccine. With the simplified notation, this model could be specified as:
corresponding to 12 compartments, 4 of which are unnecessary to the model
Or, it could be specified with the less concise notation
which does not result in any unnecessary compartments being included.
These compartments are referenced in multiple different subsequent sections of the config. In the seeding (LINK TBA)
section the user can specify how the initial (or later imported) infections are distributed across compartments; in the seir
section the user can specify the form and rate of the transitions between these compartments encoded by the model; in the outcomes
section the user can specify how the observed variables are generated from the underlying model states.
Notation must be consistent between these sections.
seir::transitions
)The way we specify transitions between compartments in the model is a bit more complicated than how the compartments themselves are specified, but allows users to specify complex stratified infectious disease models with minimal code. This makes checking, sharing, and updating models more efficient and less error-prone.
We specify one or more transition globs, each of which corresponds to one or more transitions. Since transition globs are shorthand for collections of transitions, we will first explain how to specify a single transition before discussing transition globs.
A transition has 5 pieces of associated information that a user can specify:
source
destination
rate
proportional_to
proportion_exponent
For more details on the mathematical forms possible for transitions in our models, read the Model Description section.
We first consider a simple example of an SI model where individuals may either be vaccinated (v) or unvaccinated (u), but the vaccine does not change the susceptibility to infection nor the infectiousness of infected individuals.
We will focus on describing the first transition of this model, the rate at which unvaccinated individuals move from the susceptible to infected state.
The compartment the transition moves individuals out of (e.g., the source compartment) is an array. For example, to describe a transition that moves unvaccinated susceptible individuals to another state, we would write
which corresponds to the compartment S_unvaccinated
The compartment the transition moves individuals into (e.g. the destination compartment) is an array. For example, to describe a transition that moves individuals into the unvaccinated but infected state, we would write
which corresponds to the compartment I_unvaccinated
The rate constant specifies the probability per time that an individual in the source compartment changes state and moves to the destination compartment. For example, to describe a transition that occurs with rate 5/time, we would write:
instead, we could describe the rate using a parameter beta
, which can be given a numeric value later:
The interpretation and unit of the rate constant depend on the model details, as the rate may potentially also be per number (or proportion) of individuals in other compartments (see below).
A vector of groups of compartments (each of which is an array) that modify the overall rate of transition between the source and destination compartment. Each separate group of compartments in the vector are first summed, and then all entries of the vector are multiplied to get the rate modifier. For example, to specify that the transition rate depends on the product of the number of unvaccinated susceptible individuals and the total infected individuals (vaccinated and unvaccinated), we would write:
To understand this term, consider the compartments written out as strings
and then sum the terms in each group
From here, we can say that the transition we are describing is proportional to S_unvaccinated
and I_unvaccinated + I_vaccinated,
i.e., the rate depends on the product S_unvaccinated * (I_unvaccinated + I_vaccinated)
.
This is an exponent modifying each group of compartments that contribute to the rate. It is equivalent to the "order" term in chemical kinetics. For example, if the reaction rate for the model above depends linearly on the number of unvaccinated susceptible individuals but on the total infected individuals sub-linearly, for example to a power 0.9, we would write:
or a power parameter alpha
, which can be given a numeric value later:
The (top level) length of the proportion_exponent
vector must be the same as the (top level) length of the proportional_to
vector, even if the desire of the user is to have the same exponent for all terms being multiplied together to get the rate.
Putting it all together, the model transition is specified as
would correspond to the following model if expressed as an ordinary differential equation
with parameter and parameter (we will describe how to use parameter symbols in the transitions and specify their numeric values separately in the section Specifying compartmental model parameters).
We now explain a shorthand we have developed for specifying multiple transitions that have similar forms all at once, via transition globs. The basic idea is that for each component of the single transitions described above where a term corresponded to a single model compartment, we can instead specify one or more compartment. Similarly, multiple rate values can be specified at once, for each involved compartment. From one transition glob, multiple individual transitions are created, by broadcasting across the specified compartments.
For transition globs, any time you could specify multiple arguments as a list, you may instead specify one argument as a non-list, which will be used for every broadcast. So [1,1,1] is equivalent to 1 if the dimension of that broadcast is 3.
We continue with the same SI model example, where individuals are stratified by vaccination status, but expand it to allow infection to occur at different rates in vaccinated and unvaccinated individuals:
We allow one or more arguments to be specified for each compartment. So to specify the transitions out of both susceptible compartments (S_unvaccinated
and S_unvaccinated
), we would use
The destination variable should be the same shape as the source
, and in the same relative order. So to specify a transition from S_unvaccinated
to I_unvaccinated
and S_vaccinated
to I_vaccinated
, we would write the destination
as:
If instead we wrote:
we would have a transition from S_unvaccinated
to I_vaccinated
and S_vaccinated
to I_unvaccinated
.
The rate vector allows users to specify the rate constant for all the source -> destination transitions that are defined in a shorthand way, by instead specifying how the rate is altered depending on the compartment type. For example, the rate of transmission between a susceptible (S) and an infected (I) individual may vary depending on whether the susceptible individual is vaccinated or not and whether the infected individual is vaccinated or not. The overall rate constant is constructed by multiplying together or "broadcasting" all the compartment type-specific terms that are relevant to a given compartment.
For example,
This would mean our transition from S_unvaccinated
to I_unvaccinated
would have a rate of 3 * 0.6
while our transition from S_vaccinated
to I_vaccinated
would have a rate of 3 * 0.5
.
The rate vector should be the same shape as source
and destination
and in the same relative order.
Note that if the desire is to make a model where the difference in the rate constants varies in a more complicated than multiplicative way between different compartment types, it would be better to specify separate transitions for each compartment type instead of using this shorthand.
The broadcasting here is a bit more complicated. In other cases, each broadcast is over a single component. However, in this case, we have a broadcast over a group of components. We allow a different group to be chosen for each broadcast.
Again, let's unpack what it says. Since the broadcast is over groups, let's split the config back up
into those groups
From here, we can say that we are describing two transitions. Both occur proportionally to the same compartments: S_unvaccinated
and the total number of infections (I_unvaccinated+I_vaccinated
).
If, for example, we want to model a situation where vaccinated susceptibles cannot be infected by unvaccinated individuals, we would instead write:
Similarly to rate
and proportional_to
, we provide an exponent for each component and every group across the broadcast. So we could for example use:
The (top level) length of the proportion_exponent
vector must be the same as the (top level) length of the proportional_to
vector, even if the desire of the user is to have the same exponent for all terms being multiplied together to get the rate. Within each vector entry, the arrays must have the same length as the source
and destination
vectors.
Putting it all together, the transition glob
is equivalent to the following transitions
We warn the user that with this shorthand, it is possible to specify large models with few lines of code in the configuration file. The more compartments and transitions you specify, the longer the model will take to run, and the more memory it will require.
seir::parameters
)When the transitions of the compartmental model are specified as described above, they can either be entered as numeric values (e.g., 0.1
) or as strings which can be assigned numeric values later (e.g., beta
). We recommend the latter method for all but the simplest models, since parameters may recur in multiple transitions and so that parameter values may be edited without risk of editing the model structure itself. It also improves readability of the configuration files.
Parameters can take on three types of values:
Fixed values
Value drawn from distributions
Values read from timeseries specified in a data file
The full model section of the config could then read
For the stratified SI model described above, this portion of the config would read
If there are no parameter values that need to be specified (all rates given numeric values when defining model transitions), the seir::parameters
section of the config can be left blank or omitted.
Details on the possible distributions that are currently available, and how to specify their parameters, is provided in the Distributions section.
Note that understanding when a new parameter values from this distribution is drawn becomes more complicated when the model is run in Inference mode. In Inference mode, we distinguish model runs as occurring in different "slots" – i.e., completely independent model instances that could be run on different processing cores in a parallel computing environment – and different "iterations" of the model that occur sequentially when the model is being fit to data and update fitted parameters each time based on the fit quality found in the previous iteration. A new parameter values is only drawn from the above distribution once per slot. Within a slot, at each iteration during an inference run, the parameter is only changed if it is being fit and the inference algorithm decides to perturb it to test a possible improved fit. Otherwise, it would maintain the same value no matter how many times the model was run within a slot.
Sometimes, we want to be able to specify model parameters that have different values at different timepoints. For example, the relative transmissibility may vary throughout the year based on the weather conditions, or the rate at which individuals are vaccinated may vary as vaccine programs are rolled out. One way to do this is to instead specify the parameter values as a timeseries.
This can be done by providing a data file in .csv or .parquet format that has a list of values of the parameter for a corresponding timepoint and subpopulation name. One column should be date
, which should have an entry for every calendar day of the simulation, with the first and last date corresponding to the start_date
and end_date
for the simulation specified in the header of the config. There should be another column for each subpopulation, where the column name is the subpop name used in other files and the values are the desired parameter values for that subpopulation for the corresponding day. If any day or subpopulation is missing, an error will occur. However, if you want all subpopulations to have the same parameter value for every day, then only a single column in addition to date is needed, which can have any name, and will be applied to every subpop ;
For example, for an SIR model with a simple two-province population structure where the relative transmissibility peaks on January 1 then decreases linearly to a minimal value on June 1 then increases linearly again, but varies more in the small province than the large province, the theta
parameter could be constructed from the file seasonal_transmission_2pop.csv with contents including
as a part of a configuration file with the model sections:
Note that there is an alternative way to specify time dependence in parameter values that is described in the Specifying time-varying parameter modifications section. That method allows the user to define intervention parameters that apply specific additive or multiplicative shifts to other parameter values for a defined time interval. Interventions are useful if the parameter doesn't vary frequently and if the values of the shift is unknown and it is desired to either sample over uncertainty in it or try to estimate its value by fitting the model to data. If the parameter varies frequently and its value or relative value over time is known, specifying it as a timeseries is more efficient.
Compartmental model parameters can have an additional attribute beyond value
or timeseries
, which is called stacked_modifier_method
. This value is explained in the section on coding time-dependent parameter modifications
(also known as "modifiers") as it determines what happens when two different modifiers act on the same parameter at the same time (are they combined additively or multiplicatively?) ;
value
either value or timeseries is required
numerical, or distribution
This defines the value of the parameter, as described above.
timeseries
either value or timeseries is required
path to a csv file
This defines a timeseries for each day, as above.
stacked_modifier_method
optional
string: sum
, product
, reduction_product
This option defines the method used when modifiers are applied. The default is product
.
rolling_mean_windows
optional
integer
The size of the rolling mean window if a rolling mean is applied.
(seir::integration)
A compartmental model defined using the notation in the previous sections describes rules for classifying individuals in the population based on infection state dynamically, but does not uniquely specify the mathematical framework that should be used to simulate the model.
Our framework allows for two major methods for implementing compartmental models of disease transmission:
ordinary differential equations, which are completely deterministic, operate in continuous time (consider infinitesimally small timesteps), and allow for arbitrary fractions of the population (i.e., not just discrete individuals) to move between model compartments
discrete-time stochastic process, which tracks discrete individuals and produces random variation in the number of individuals transitioning between states for any given rate, and which allows transitions between states only to occur at discrete time intervals
The mathematics behind each implementation is described in the Model Description section
method
optional
string: stochastic
,rk4
, or legacy
The algorithm used to simulate the mode equations. If stochastic
, uses a discrete-time stochastic process with a rate-saturation correction. If rk4
, model is simulated deterministically by numerical integration using a 4th order Runge-Kutta algorithm. If legacy
(Default), uses the transition rates for the stochastic model but always chooses the average rate (an Euler style update)
dt
optional
Any positive real number
The timestep used for the numerical integration or discrete time stochastic update. Default is dt = 2
For example, to simulate a model deterministically using the 4th order Runge-Kutta algorithm for numerical integration with a timestep of 1 day:
Alternatively, to simulate a model stochastically with a timestep of 0.1 days
For any method, the results of the model will be more accurate when the timestep is smaller (i.e., output will more precisely match the mathematics of the model description and be invariant to the choice of timestep). However, the computing time required to simulate the model for a certain time range of interest increases with the number of timesteps required (i.e., with smaller timesteps). In our experience, the 4th order Runge-Kutta algorithm (for details see Advanced section) is a very accurate method of numerically integrating such models and can handle timesteps as large as roughly a day for models with the maximum per capita transition rates in this same order of magnitude. However, the discrete time stochastic model or the legacy method for integrating the model in deterministic mode require smaller timesteps to be accurate (around 0.1 for COVID-19-like dynamics in our experience.
For transitions that occur at a constant per-capita rate (ie, E -> I at rate in an SEIR model), it is possible to simply write proportional_to: ["source"]
.
Parameters can be assigned values by using the value
argument after their name and then simply stating their numeric argument. For example, in a config describing a simple SIR model with transmission rate (beta
) = 0.1/day and recovery rate (gamma
) = 0.2/day. This could be specified as
Parameter values can also be specified as random values drawn from a distribution, as a way of including uncertainty in parameters in the model output. In this case, every time the model is run independently, a new random value of the parameter is drawn. For example, to choose the same value of beta
= 0.1 each time the model is run but to choose a random values of gamma
with mean on a log scale of and standard deviation on a log scale of (e.g., 1.2-fold variation):
This section describes how to specify modifications to any of the parameters of the transmission model or observational model during certain time periods.
Modifiers are a powerful feature in flepiMoP to enable users to modify any of the parameters being specified in the model during particular time periods. They can be used, for example, to mirror public health control interventions, like non-pharmaceutical interventions (NPIs) or increased access to diagnosis or care, or annual seasonal variations in disease parameters. Modifiers can act on any of the transmission model parameters or observation model parameters ;
In the seir_modifiers
and outcome_modifiers
sections of the configuration file the user can specify several possible types of modifiers which will then be implemented in the model. Each modifier changes a parameter during one or multiple time periods and for one or multiple specified subpopulations.
We currently support the following intervention types. Each of these is described in detail below:
"SinglePeriodModifier"
– Modifies a parameter during a single time period
"MultiPeriodModifier"
– Modifies a parameter by the same amount during a multiple time periods
"ModifierModifier"
– Modifies another intervention during a single time period
"StackedModifier"
– Combines two or more interventions additively or multiplicatively, and is used to be able to turn on and off groups of interventions easily for different runs ;
Note that if you want a parameter to vary continuously over time (for example, a daily transmission rate that is influenced by temperature and humidity), then it is easier to do this by using a "timeseries" parameter value than by combining many separate modifiers. Timeseries parameter values are described in the seir::parameters section. Timeseries parameters foroutcomes
parameters (e.g., a testing rate that fluctuates rapidly due to test availability) are in development but not currently available ;
Within flepiMoP, modifiers can be run as "scenarios". With scenarios, we can use the same configuration file to run multiple versions of the model where only the modifiers applied differ.
The modifiers
section contains two sub-sections: modifiers::scenarios
, which lists the name of the modifiers that will run in each separate scenario, and modifiers::modifiers
, where the details of each modifier are specified (e.g., the parameter it acts on, the time it is active, and the subpopulation it is applied to). An example is outlined below
In this example, each scenario runs a single intervention, but more complicated examples are possible. ;
The major benefit of specifying both "scenarios" and "modifiers" is that the user can use "StackedModifier"
option to combine other modifiers in different ways, and then run either the individual or combined modifiers as scenarios. This way, each scenario may consist of one or more individual parameter modifications, and each modification may be part of multiple scenarios. This provides a shorthand to quickly consider multiple different versions of a model that have different combinations of parameter modifications occurring. For example, during an outbreak we could evaluate the impact of school closures, case isolation, and masking, or any one or two of these three measures. An example of a configuration file combining modifiers to create new scenarios is given below
The seir_modifiers::scenarios
andoutcome_modifiers::scenarios
sections are optional. If the scenarios
section is not included, the model will run with all of the modifiers turned "on" ;
If thescenarios
section is included for either seir
or outcomes
, then each time a configuration file is run, the user much specify which modifier scenarios will be run. If not specified, the model will be run one time for each combination of seir
and outcome
scenario ;
[Give a configuration file that tries to use all the possible option available. Based on simple SIR model with parameters beta
and gamma
in 2 subpopulations. Maybe a SinglePeriodModifier on beta
for a lockdown and gamma
for isolation, one having a fixed value and one from a distribution, MultiPeriodModifier for school year in different places, ModifierModifer for ..., StackedModifier for .... ]
modifiers::scenarios
A optional list consisting of a subset of the modifiers that are described in modifiers::settings
, each of which will be run as a separate scenario. For example
or
modifiers::settings
A formatted list consisting of the description of each modifier, including its name, the parameter it acts on, the duration and amount of the change to that parameter, and the subset of subpopulations in which the parameter modification takes place. The list items are summarized in the table below and detailed in the sections below.
method
required
string
one of SinglePeriodModifier
, MultiPeriodModifier
, ModifierModifier
, or StackedModifier
parameter
required
string
The parameter on which the modification is acting. Must be a parameter defined in seir::parameters
or outcomes
period_start_date
or periods::start_date
required
numeric, YYYY-MM-DD
The date when the modification starts. Notation depends on value of method.
period_end_date
or periods::end_date
required
numeric, YYYY-MM-DD
The date when the modification ends. Notation depends on value of method.
subpop
required
String, or list of strings
The subpopulations to which the modifications will be applied, or "all"
. Subpopulations must appear in the geodata
file.
value
required
Distribution, or single value
The relative amount by which a modification reduces the value of a parameter.
subpop_groups
optional
string or a list of lists of strings
A list of lists defining groupings of subpopulations, which defines how modification values should be shared between them, or 'all'
in which case all subpopulations are put into one group with identical modification values. By default, if parameters are chosen randomly from a distribution or fit based on data, they can have unique values in each subpopulation.
baseline_scenario
Used only for ModifierModifier
String
Name of the original modification which will be further modified
modifiers
Used only for StackedModifier
List of strings
List of modifier names to be grouped into the new combined modifier/scenario name
SinglePeriodModifier
interventions enable the user to specify a multiplicative reduction to a parameter
of interest. It take a parameter
, and reduces it's value by value
(new = (1-value
) * old) for the subpopulations listed insubpop
during the time interval [period_start_date
, period_end_date
]
For example, if you would like to create an SEIR modifier called lockdown
that reduces transmission by 70% in the state of California and the District of Columbia between two dates, you could specify this with a SinglePeriodModifier, as in the example below
Or to create an outcome variable modifier called enhanced_testing during which the case detection rate double ;
method
: SinglePeriodModifier
parameter
: The name of the parameter that will be modified. This could be a parameter defined for the transmission model in seir::parameters
or for the observational model in outcomes
. If the parameter is used in multiple transitions in the model then all those transitions will be modified by this amount ;
period_start_date
: The date when the modification starts, in YYYY-MM-DD format. The modification will only reduce the value of the parameter after (inclusive of) this date.
period_end_date
: The date when the modification ends, in YYYY-MM-DD format. The modification will only reduce the value of the parameter before (inclusive of) this date.
subpop:
A list of subpopulation names/ids in which the specified modification will be applied. This can be a single subpop
, a list, or the word "all"
(specifying the modification applies to all existing subpopulations in the model). The modification will do nothing for any subpopulations not listed here.
value:
The fractional reduction of the parameter during the time period the modification is active. This can be a scalar number, or a distribution using the notation described in the Distributions section. The new parameter value will be
subpop_groups:
An optional list of lists specifying which subsets of subpopulations in subpop should share parameter values; when parameters are drawn from a distribution or fit to data. See subpop_groups
section below for more details ;
MultiPeriodModifier
interventions enable the user to specify a multiplicative reduction to the parameter
of interest by value
(new = (1-value
) * old) for the subpopulations listed in subpop
during multiple different time intervals each defined by a start_date
and end_date.
For example, if you would like to describe the impact that transmission in schools has on overall disease spread, you could create a modifier that increases transmission by 30% during the dates that K-12 schools are in session in different regions (e.g., Massachusetts and Florida):
method: MultiPeriodModifier
parameter
: The name of the parameter that will be modified. This could be a parameter defined for the transmission model in seir::parameters
or for the observational model in outcomes
. If the parameter is used in multiple transitions in the model then all those transitions will be modified by this amount ;
groups:
A list of subpopulations (subpops
) or groups of them, and time periods the modification will be active in each of them
groups:subpop
A list of subpopulation names/ids in which the specified modification will be applied. This can be a single subpop
, a list, or the word "all" (
specifying the modification applies to all existing subpopulations in the model). The modification will do nothing for any subpopulations not listed here.
groups: periods
A list of time periods, each defined by a start and end date, when the modification will be applied
groups:periods:start_date
The date when the modification starts, in YYYY-MM-DD format. The modification will only reduce the value of the parameter after (inclusive of) this date.
groups:periods:end_date
The date when the modification ends, in YYYY-MM-DD format. The modification will only reduce the value of the parameter before (inclusive of) this date.
value:
The fractional reduction of the parameter during the time period the modification is active. This can be a scalar number, or a distribution using the notation described in the Distributions section. The new parameter value will be
subpop_groups:
An optional list of lists specifying which subsets of subpopulations in subpop should share parameter values; when parameters are drawn from a distribution or fit to data. See subpop_groups
section below for more details ;
ModifierModifier
interventions allow the user to specify an intervention that acts to modify the value of another intervention, as opposed to modifying a baseline parameter value. The intervention multiplicatively reduces the modifier
of interest by value
(new = (1-value
) * old) for the subpopulations listed in subpop
during the time interval [period_start_date
, period_end_date
].
For example, ModifierModifier
could be used to describe a social distancing policy that is in effect between two dates and reduces transmission by 60% if followed by the whole population, but part way through this period, adherence to the policy drops to only 50% of in one of the subpopulations population:
Note that this configuration is identical to the following alternative specification
However, there are situations when the ModiferModifier
notation is more convenient, especially when doing parameter fitting. ;
method: ModifierModifier
baseline_modifier:
The name of the original parameter modification which will be further modified.
parameter
: The name of the parameter in the baseline_scenario
that will be modified ;
period_start_date
: The date when the intervention modifier starts, in YYYY-MM-DD format. The intervention modifier will only reduce the value of the other intervention after (inclusive of) this date.
period_end_date
: The date when the intervention modifier ends, in YYYY-MM-DD format. The intervention modifier will only reduce the value of the other intervention before (inclusive of) this date.
subpop:
A list of subpopulation names/ids in which the specified intervention modifier will be applied. This can be a single subpop
, a list, or the word "all"
(specifying the interventions applies to all existing subpopulations in the model). The intervention will do nothing for any subpopulations not listed here.
value:
The fractional reduction of the baseline intervention during the time period the modifier intervention is active. This can be a scalar number, or a distribution using the notation described in the Distributions section. The new parameter value will be
and so the value of the underlying parameter that was modified by the baseline intervention will be
subpop_groups:
An optional list of lists specifying which subsets of subpopulations in subpop should share parameter values; when parameters are drawn from a distribution or fit to data. See subpop_groups
section below for more details ;
Combine two or more modifiers into a scenario, so that they can easily be singled out to be run together without the other modifiers. If multiply modifiers act during the same time period in the same subpopulation, their effects are combined multiplicatively. Modifiers of different types (i.e. SinglePeriodModifier, MultiPeriodModifier, ModifierModifier, other StackedModifiers) can be combined ;
or
method
: StackedModifier
modifiers
: A list of names of the other modifiers (specified above) that will be combined to create the new modifier (which we typically refer to as a "scenario")
subpop_groups:
For any of the modifier types, subpop_groups
is an optional list of lists specifying which subsets of subpopulations in subpop
should share parameter values; when parameters are drawn from a distribution or fit to data. All other subpopulations not listed will have unique intervention values unlinked to other areas. If the value is 'all',
then all subpopulations will be assumed to have the same modifier value. When the subpop_groups
option is not specified, all subpopulations will be assumed to have unique values of the modifier ;
For example, for a model of disease spread in Canada where we want to specify that the (to be varied) value of a modification to the transmission rate should be the same in all the Atlantic provinces (Nova Scotia, Newfoundland, Prince Edward Island, and New Brunswick), the same in all the prairie provinces (Manitoba, Saskatchewan, Alberta), the same in the three territories (Nunavut, Northwest Territories, and Yukon), and yet take unique values in Ontario, Quebec, and British Columbia, we could write
flepiMop is set up so that all parameters and other options for running the pipeline can be specified in a single "configuration" file (aka "config"). Users do not need to edit any other code files, or even be aware of their contents, to create and run complex model scenarios. Configuration files also provide a convenient record of model options and promote reproducibility of model results.
We use the YAML
language syntax to write config files, which are typically named something like config.yml
. The file has simple plain text contents and follows a tabbed outline structure. When config files are read by the model code, a data structure encoding the model options is created.
Comments can be added to the config file by starting with the hash key (#
) then a space. Comments can start anywhere on a line and continue until the end, but if they run over to a new line, a new # must be used at the start of the new line.
(give a simple configuration for a toy model with two subpopulations, SEIR, single "cases" outcome, single seeded infection, single NPI that starts after some time? this page is currently under development, please see our example repo _for some simple configurations) ;
When referring to config items (individual parameters), we use their full position in the outline. For example, in the sample config file above, we denote
as subpop_setup::geodata
having a value of minimal
Parameters and other options specified in the configuration files can take on a variety of types of values, using the following notations:
dates are specified as [year]-[month]-[day]. (e.g., 2020-01-31)
boolean values are either "TRUE" or "FALSE"
files names are strings
probability is a float between 0 and 1
distribution is a probability distribution from which a random value for the parameter is drawn each time a new simulation is run (or chain, if doing inference). See here for the require schema.
Required section
These global configuration options typically sit at the top of the configuration file.
name
required
string
Name of this configuration. Will be used in file names created to store model output.
start_date
required
date
model simulation start date
end_date
required
date
model simulation end date
start_date_groundtruth
optional for non-inference runs, required for inference runs
date
start date for comparing model to data
end_date_groundtruth
optional for non-inference runs, required for inference runs
date
end date for comparing model to data
nslots
optional (can also be defined by an environmental variable)
int
number of independent simulations to run
setup_name
optional
string
setup name used to describe the run, used in setting up file names
model_output_dirname
optional
folder path
path to folder where all the outputs created by the model are stored, if not specified, default is model_output
For example, for a configuration file to simulate the spread of COVID-19 in the US during 2020 and compare to data from March 1 onwards, with 1000 independent simulations, the header of the config might read:
subpop_setup
sectionRequired section
This section specifies the population structure on which the model will be simulated, including the names and sizes of each subpopulation and the connectivity between them. More details here.
compartments
sectionRequired section
This section is where users can specify the variables (infection states) that will be tracked in the infectious disease transmission model. More details can be found here. The other details of the model are specified in the seir
section, including transitions between these compartments (seir::transitions
), the names of the parameters governing the transitions (seir::parameters
), and the numerical method used to simulate the equations over time (seir::integration
). The initial conditions of the model can be specified in the initial_conditions
section, and any other inputs into the model from external populations or instantaneous transitions between states that occur at later times can be specified in the seeding
section. ;
seir
sectionRequired section
This section is where users can specify the details of the infectious disease transmission model they wish to simulate (e.g., SEIR). This model describes the allowed transitions (seir::transitions
) between the compartments that were specified in the compartments
section, the values of the parameters involved in these transitions (seir::parameters
), and the numerical method used to simulate the equations over time (seir::integration
). More details here. The initial conditions of the model can be specified in the separate initial_conditions
section, and any other inputs into the model from external populations or instantaneous transitions between states that occur at later times can be specified in the seeding
section. ;
initial_conditions
sectionOptional section
This section is used to specify the initial conditions of the model, which define how individuals are distributed between the model compartments at the time the model simulation begins. Importantly, the initial conditions specify the time and location where infection is first introduced. If this section is omitted, default values are used. If users want to add infections to the population at later times, or add or remove individuals from compartments separately from the model rules, they can do so via the related seeding
section. More details here ;
seeding
sectionOptional section
This section is used to specify how individuals are instantaneously "seeded" from one compartment to another, where they then continue to be governed by the model equations. For example, this seeding could be used to represent importations of infected individuals from an outside population, mutation events that create new strains, or vaccinations that alter disease susceptibility. Seeding events can occur at any time in the simulation. The seeding section specifies the numeric values added to or removed from any compartment of the model. More details here ;
outcomes
sectionOptional section
This section is where users can define new variables representing the observed quantities and how they are related to the underlying state variables in the model (e.g., the fraction of infections that are detected as cases). More details here ;
interventions
sectionRequired section
This section is where users can specify time-varying changes to parameters governing either the infectious disease model or the observational model. More details here ;
inference
sectionOptional section
This section is where users can specify the details of how the model is fit to data, including what data streams they will be included and which outcome variables they represent and the likelihood functions describing the probability of the data given the model. More details here. ;
This page describes the configuration schema for specifying distributions
fixed
value
Any real number
Draws all values exactly equal to value
uniform
low
Any real number
Draws all values randomly from a uniform distribution with range [low, high]
high
Any real number greater than low
poisson
lam
Any positive real number
Draws all values randomly from a Poisson distribution with rate parameter (mean) lam
(lambda)
binomial
size
Any non-negative integer
Draws all values randomly from a binomial distribution with number of trials (n) = size
and probability of success on each trial (p) = prob
prob
Any number in [0,1]
lognormal
meanlog
Any real number
Draws all values randomly from a lognormal distribution (natural log, base e) with mean on a log scale of meanlog
and standard deviation on a log scale of sdlog
sdlog
Any non-negative real number
truncnorm
mean
Any real number
Draws all values randomly from a truncated normal distribution with mean mean
and standard deviation sd
, truncated to have a maximum value of a
and a minimum value of b
sd
Any non-negative real number
a
Any real number, or -Inf
b
Any real number greater than a
, or Inf
This page describes how to specify the outcomes section of the configuration file
outcomes
variablesOur pipeline allows users to encode state variables describing the infection status of individuals in the population in two different ways. The first way is via the state variables and transitions of the compartmental model of disease transmission, which are specified in the compartments
and seir
sections of the config. This model should include all variables that influence the natural course of the epidemic (i.e., all variables that feed back into the model by influencing the rate of change of other variables). For example, the number of infected individuals influences the rate at which new infections occur, and the number of immune individuals influences the number of individuals at risk of acquiring infection.
However, these intrinsic model variables may be difficult to observe in the real world and so directly comparing model predictions about the values of these variables to data might not make sense. Instead, the observable outcomes of infection may include only a subset of individuals in any state, and may only be observed with a time delay. Thus, we allow users to define new outcome
variables that are functions of the underlying model variables. Commonly used examples include detected cases or hospitalizations ;
Variables should not be included as outcomes if they influence the infection trajectory. The choice of what variables to include in the compartmental disease model vs. the outcomes section may be very model specific. For example, hospitalizations due to infection could be encoded as an outcome variable that is some fraction of infections, but if we believe hospitalized individuals are isolated from the population and don't contribute to onward infection, or that the number of hospitalizations feeds back into the population's perception of risk of infection and influences everyone's contact behavior, this would not be the best choice. Similarly, we could include deaths due to infection as an outcome variable that is also some fraction of infections, but unless death is a very rare outcome of infection and we aren't worried about actually removing deceased individuals from the modeled populations, deaths should be in the compartmental model instead.
The outcomes
section is not required in the config. However, there are benefits to including it, even if the only outcome variable is set to be equivalent to one of the infection model variables. If the compartmental model is complicated but you only want to visualize a few output variables, the outcomes output file will be much easier to work with. Outcome variables always occur with some fixed delay from their source infection model variable, which can be more convenient than the exponential distribution underlying the infection model. Outcome variables can be created to automatically sum over multiple compartments of the infection model, removing the need for post-processing code to do this. If the model is being fit to data, then the outcomes
section is required, as only outcome variables can be compared to data.
As an example, imagine we are simulating an SIR-style model and want to compare it to real epidemic data in which cases of infection and death from infection are reported. Our model doesn't explicitly include death, but suppose we know that 1% of all infections eventually lead to hospitalization, and that hospitalization occurs on average 1 week after infection. We know that not all infections are reported as cases, and assume that only 50% are detected and are reported 2 days after infection begins. The model and outcomes
section of the config for these outcomes, which we call incidC
(daily incidence of cases) and incidH
(daily incidence of hospital admission) would be
in the following sections we describe in more detail how this specification works
outcomes
in the configuration fileThe outcomes
config section consists of a list of defined outcome variables (observables), which are defined by a user-created name (e.g., "incidH
"). For each of these outcome variables, the user defines the source
compartment(s) in the infectious disease model that they draw from and whether they draw from the incidence
(new individuals entering into that compartment) or prevalence
(total current individuals in that compartment). Each new outcome variable is always associated with two mandatory parameters ;
probability
of being counted in this outcome variable if in the source compartment
;delay
between when an individual enters the source
compartment and when they are counted in the outcome variable
and one optional parameter
duration
after entering that an individual is counted as part of the outcome variable
The value
of the probability
, delay
, and duration
parameters can be a single value or come from distribution ;
Outcome model parameters probability
, delay
, and distribution
can have an additional attribute beyond value
called modifier_key
. This value is explained in the section on coding time-dependent parameter modifications
(also known as "modifiers") as it provides a way to have the same modifier act on multiple different outcomes ;
Just like the case for compartment model parameters, when outcome parameters are drawn from a distribution, each time the model is run, a different value for this parameter will be drawn from this distribution, but that value will be used for all calculations within this model run. Note that understanding when a new parameter values from this distribution is drawn becomes more complicated when the model is run in Inference mode. In Inference mode, we distinguish model runs as occurring in different "slots" – i.e., completely independent model instances that could be run on different processing cores in a parallel computing environment – and different "iterations" of the model that occur sequentially when the model is being fit to data and update fitted parameters each time based on the fit quality found in the previous iteration. A new parameter values is only drawn from the above distribution once per slot. Within a slot, at each iteration during an inference run, the parameter is only changed if it is being fit and the inference algorithm decides to perturb it to test a possible improved fit. Otherwise, it would maintain the same value no matter how many times the model was run within a slot.
Example
source
Yes
Varies
The infection model variable or outcome variable from which the named outcome variable is created
probability
Yes, unless sum option is used instead
value or distribution
The probability that an individual in the source
variable appears in the named outcome variable
delay
Yes, unless sum option is used instead
value or distribution
The time delay between individual's appearance in source
variable and appearance in named outcome variable
duration
No
value or distribution
The duration of time an individual remains counted within the named outcome variablet
sum
No
List
A list of other outcome variables to sum into the current outcome variable
Required, unless sum
option is used instead. This sub-section describes the compartment(s) in the infectious disease model from which this outcome variable is drawn. Outcome variables can be drawn from the incidence
of a variable - meaning that some fraction of new individuals entering the infection model state each day are chosen to contribute to the outcome variable - or from the prevalence
, meaning that each day some fraction of individuals currently in the infection state are chosen to contribute to the outcome variable. Note that whatever the source type, the named outcome variable itself is always a measure of incidence ;
To specify which compartment(s) contribute the user must specify the state(s) within each model stratification. For stratifications not mentioned, the outcome will sum over that states in all strata ;
For example, consider a configuration in which the compartmental model was constructed to track infection status stratified by vaccination status and age group. The following code would be used to create an outcome called incidH_child
(incidence of hospitalization for children) and incidH_adult
(incidence of hospitalization for adults) where some fraction of infected individuals would become hospitalized and we wanted to track separately track pediatric vs adult hospitalizations, but did not care about tracking the vaccination status of hospitalized individuals as in reality it was not tracked by the hospitals ;
to instead create an outcome variable for cases where on each day of infection there is some probability of testing positive (for example, for the situation of an asymptomatic infection where testing is administered totally randomly), the following code would be used
The source of an outcome variable can also be a previous defined outcome variable. For example, t to create a new variable for the number of individuals recruited to be part of a contact tracing program (incidT), which is just some fraction of diagnosed cases ;
Required, unless sum
option is used instead. Probability
is the fraction of individuals in the source compartment who are counted as part of this outcome variable (if the source is incidence; if the source is prevalence it is the fraction of individuals per day). It must be between 0 and 1 ;
Specifying the probability creates a parameter called outcome_name::probability
that can be referred to in the outcome_modifiers
section of the config. The value of this parameter can be changed using the probability::intervention_param_name
option ;
For example, to track the incidence of hospitalization when 5% of children but only 1% of adults infected require hospitalization, and to create a modifier_key
such that both of these rates could be modified by the same amount during some time period using the outcomes_modifier
section:
To track the incidence of diagnosed cases iterating over uncertainty in the case detection rate (ranging 20% to 30%), and naming this parameter "case_detect_rate"
Each time the model is run a new random value for the probability of case detection will be chosen ;
Required, unless sum
option is used instead. delay
is the time delay between when individuals are chosen from the source compartment and when they are counted as part of this outcome variable ;
For example, to track the incidence of hospitalization when 5% of children are hospitalized and hospitalization occurs 7 days after infection:
To iterate over uncertainty in the exact delay time, we could include some variation between simulations in the delay time using a normal distribution with standard deviation of 2 (truncating to make sure the delay does not become negative). Note that a delay distribution here does not mean that the delay time varies between individuals - it is identical) ;
By default, all outcome variables describe incidence (new individuals entering each day). However, they can also track an associated "prevalence" if the user specifies how long individuals will stay classified as the outcome state the outcome variable describes. This is the duration
parameter ;
When the duration parameter is set, a new outcome variable is automatically created and named with the name of the original outcome variable + "_curr". This name can be changed using the duration::name
option ;
For example, to track the incidence and prevalence of hospitalization when 5% of children are hospitalized, hospitalization occurs 7 days after infection, and the duration of hospitalization is 3 days:
which creates the variable "incidH_child_curr" to track all currently hospitalized children. Since it doesn't make sense to call this new outcome variable an incidence, as it is a prevalence, we could instead rename it:
Optional. sum
is used to create new outcome variables that are sums over other previously defined outcome variables ;
If sum
is included, source
, probability
, delay
, and duration
will be ignored ;
For example, to track new hospital admissions and current hospitalizations separately for children and adults, as well as for all ages combined
There are other required and optional configuration items for the outcomes
section which can be specified under outcomes::settings
:
method
: delayframe.
This is the mathematical method used to create the outcomes variable values from the transmission model variables. Currently, the only model supported is delayframe
, which .. ;
param_from_file:
Optional, TRUE
or FALSE
. It is possible to allow any of the outcomes variables to have values that vary across the subpopulations. For example, disease severity rates or diagnosis rates may differ by demographic group. In this case, all the outcome parameter values defined in outcomes::outcomes will represent baseline values, and then you can define a relative change from this baseline for any particular subpopulation using the paths section. If params_from_file: TRUE
is specified, then these relative values will be read from the params_subpop_file
. Otherwise, if params_from_file: FALSE
or is not listed at all, all subpopulations will have the same values for the outcome parameters, defined below ;
param_subpop_file
: Required if params_from_file: TRUE
. The path to a .csv or .parquet file that contains the relative amount by which a given outcome variable is shifted relative to baseline in each subpopulation. File must contain the following columns:
subpop
: The subpopulation for which the parameter change applies. Must be a subpopulation defined in the geodata
file. For example, small_province
parameter: The outcomes parameter which will be altered for this subpopulation. For example, incidH_child: probability
value: The amount by which the baseline value will be multiplied, for example, 0.75 or 1.1
Consider a disease described by an SIR model in a population that is divided into two age groups, adults and children, which experience the disease separately. We are interested in comparing the predictions of the model to real world data, but we know we cannot observe every infected individual. Instead, we have two types of outcomes that are observed.
First, via syndromic surveillance, we have a database that records how many individuals in the population are experiencing symptoms from the disease at any given time. Suppose careful cohort studies have shown that 50% of infected adults and 80% of infected children will develop symptoms, and that symptoms occur in both age groups around 3 days after infection (following a log-normal distribution with log mean X and log standard deviation of Y). The duration that symptoms persist is also a variable, following a ...
Secondly, via laboratory surveillance we have a database of every positive test result for the infection. We assume the test is 100% sensitive and specific. Only individuals with symptoms are tested, and they are always tested exactly 1 day after their symptom onset. We are unsure what portion of symptomatic individuals are seeking out testing, but are interested in considering two extreme scenarios: 95% of symptomatic individuals are tested, or only 75% of individuals are tested.
The configuration file we could use to model this situation includes
Aka “magic numbers” - fixed parameters that may or may not be in config, like MCMC step size, dt, etc . . .
MCMC step size
Numerical integration step size
Mobility proportion
flepiMoP allows some input parameters/options to be specified in the command line at the time of model submission, in addition to or instead of in the configuration file. This can be helpful for users who want to quickly run different versions of the model – typically a different number of simulations or a different intervention scenario from among all those specified in the config – without having to edit or create a new configuration file every time. In addition, some arguments can only be specified via the command line.
In addition to the configuration file and the command line, the inputs described below can also be specified as environmental variables.
In all cases, command line arguments override configuration file entries which override environmental variables. The order of command line arguments does not matter.
Details on how to run the model, including how to add command line arguments or environmental variables, are in the section How to Run.
-c
or --config
CONFIG_PATH
file path
Name of configuration file. Must be located in the current working directory, or else relative or absolute file path must be provided.
Yes
NA
-i
or --first_sim_index
FIRST_SIM_INDEX
The index of the first simulation
No
1
-j
or --jobs
FLEPI_NJOBS
Number of parallel processors used to run the simulation. If there are more slots that jobs, slots will be divided up between processors and run in series on each.
No
Number of processors on the computer used to run the simulation
--interactive
or --batch
NA
Choose either option
Run simulation in interactive or batch mode
No
batch
--write-csv
or --no-write-csv
NA
Choose either option
Whether model output will be saved as .csv files
No
no_write_csv
--write-parquet
or --no-write-parquet
NA
Choose either option
No
write_parquet
-s
or --npi_scenario
interventions: scenarios
FLEPI_NPI_SCENARIOS
list of strings
Names of the intervention scenarios described in the config file that will be run. Must be a subset of scenarios defined.
No
All scenarios described in config
-n
or --nslots
nslots
FLEPI_NUM_SLOTS
Number of independent simulations of the model to be run
No
Config value
--stochastic
or --non-stochastic
seir: integration: method
FLEPI_STOCHASTIC_RUN
choose either option
Whether the model will be run stochastically or non-stochastically (deterministic numerical integration of equations using the RK4 algorithm)
No
Config value
--in-id
FLEPI_RUN_INDEX
string
Unique ID given to the model runs. If the same config is run multiple times, you can avoid the output being overwritten by using unique model run IDs.
No
Constructed from current date and time as YYYY.MM.DD.HH/MM/SS
--out-id
FLEPI_RUN_INDEX
string
Unique ID given to the model runs. If the same config is run multiple times, you can avoid the output being overwritten by using unique model run IDs.
No
Constructed from current date and time as YYYY.MM.DD.HH/MM/SS
As an example, consider running the following configuration file
To run this model directly in Python (it can alternatively be run from R, for all details see section How to Run), we could use the command line entry
Alternatively, to run 100 simulations using only 4 of the available processors on our computer, but only running the "" scenario with a deterministic model, and to save the files as .csv (since the model is relatively simple), we could call the model using the command line entry
TBA
Things below here are very out of date. Put here as place holder but not updated recently.
global: smh_round, setup_name, disease
spatial_setup: census_year, modeled_states, state_level
For creating US-based population structures using the helper script build_US_setup.R
which is run before the main model simulation script, the following extra parameters can be specified
census_year
optional
integer (year)
Determines the year for which census population size data is pulled.
state_level
optional
boolean
Determines whether county-level population-size data is instead grouped into state-level data (TRUE). Default FALSE
modeled_states
optional
list of location codes
A vector of locations that will be modeled; others will be ignored
To simulate an epidemic across all 50 states of the US or a subset of them, users can take advantage of built in machinery to create geodata and mobility files for the US based on the population size and number of daily commuting trips reported in the US Census.
Before running the simulation, the script build_US_setup.R
can be run to get the required population data files from online census data and filter out only states/territories of interest for the model. More details are provided in the How to Run section.
This example simulates COVID-19 in the New England states, assuming no transmission from other states, using 2019 census data for the population sizes and a pre-created file for estimated interstate commutes during the 2011-2015 period.
geodata.csv
contains
mobility_2011-2015_statelevel.csv
contains
importation
section (optional)This section is optional. It is used by the covidImportation package to import global air importation data for seeding infections into the United States.
If you wish to include it, here are the options.
census_api_key
required
string
travel_dispersion
required
number
ow dispersed daily travel data is; default = 3.
maximum_destinations
required
integer
number of airports to limit importation to
dest_type
required
categorical
location type
dest_country
required
string (Country)
ISO3 code for country of importation. Currently only USA is supported
aggregate_to
required
categorical
location type to aggregate to
cache_work
required
boolean
whether to save case data
update_case_data
required
boolean
deprecated; whether to update the case data or used saved
draw_travel_from_distribution
required
boolean
whether to add additional stochasticity to travel data; default is FALSE
print_progress
required
boolean
whether to print progress of importation model simulations
travelers_threshold
required
integer
include airports with at least the travelers_threshold
mean daily number of travelers
airport_cluster_distance
required
numeric
cluster airports within airport_cluster_distance
km
param_list
required
See section below
see below
importation::param_list
incub_mean_log
required
numeric
incubation period, log mean
incub_sd_log
required
numeric
incubation period, log standard deviation
inf_period_nohosp_mean
required
numeric
infectious period, non-hospitalized, mean
inf_period_nohosp_sd
required
numeric
infectious period, non-hospitalized, sd
inf_period_hosp_mean_log
required
numeric
infectious period, hospitalized, log-normal mean
inf_period_hosp_sd_log
required
numeric
infectious period, hospitalized, log-normal sd
p_report_source
required
numeric
reporting probability, Hubei and elsewhere
shift_incid_days
required
numeric
mean delay from infection to reporting of cases; default = -10
delta
required
numeric
days per estimations period
report
sectionThe report
section is completely optional and provides settings for making an R Markdown report. For an example of a report, see the Supplementary Material of our preprint
If you wish to include it, here are the options.
data_settings::pop_year
integer
plot_settings::plot_intervention
boolean
formatting::scenario_labels_short
list of strings; one for each scenario in interventions::scenarios
formatting::scenario_labels
list of strings; one for each scenario in interventions::scenarios
formatting::scenario_colors
list of strings; one for each scenario in interventions::scenarios
formatting::pdeath_labels
list of strings
formatting::display_dates
list of dates
formatting::display_dates2
optional
list of dates
a 2nd string of display dates that can optionally be supplied to specific report functions
iterations_per_slot
do_inference
gt_data_path
With inference model runs, the number of simulations nsimulations
refers to the number of final model simulations that will be produced. The filtering$simulations_per_slot
setting refers to the number of iterative simulations that will be run in order to produce a single final simulation (i.e., number of simulations in a single MCMC chain).
iterations_per_slot
required
Number of iterations in a single MCMC inference chain
do_inference
required
TRUE/FALSE
TRUE if inference should be performed. If FALSE, just runs a single run per slot, without perturbing parameters
gt_data_path
required
file path
Path to files containing "ground truth" data to which model output will be compared
statistics
required
config subsection
Specifies details of how each model output variable will be compared to data during fitting. See inference::statistics section.
hierarchical_stats_geo
optional
config subsection
Specifies whether a hierarchical structure should be applied the likelihood function for any of the fitted parameters. See inference::hierarchical_stats_geo
for details.
priors
optional
config subsection
Specifies prior distributions on fitted parameters. See inference::priors
for details
f
name
aggregator
period
sim_var
data_var
likelihood
The statistics specified here are used to calibrate the model to empirical data. If multiple statistics are specified, this inference is performed jointly and they are weighted in the likelihood according to the number of data points and the variance of the proposal distribution.
name
required
string
name of statistic, user defined
period
required
days
, weeks
, or months
Duration of time over which data and model output should be aggregated before being used in the likelihood. If weeks
, epiweeks
are used
aggregator
required
string, name of any R function
Function used to aggregate data over theperiod
, usually sum
or mean
sim_var
required
string
Name of the outcome variable - as defined inoutcomes
section of the config - that will be compared to data when calculating the likelihood. This will also be the column name of this variable in the hosp
files in the model_output
directory
data_var
required
string
Name of the data variable that will be compared to the model output variable when calculating the likelihood. This should be the name of a column in the
file specified in inference::gt_data_path
config option
remove_na
required
logical
if TRUE if FALSE
add_one
required
logical
if TRUE if FALSE Will be overwritten to TRUE if the likelihood distribution is chosen to be log
likelihood::dist
required
Distribution of the likelihood
likelihood::param
required
parameter value(s) for the likelihood distribution. These differ by distribution so check the code in inference/R/functions.R/logLikStat
function.
f
remove_na
add_one
gt_start_date
gt_end_date
Optional sections
inference::hierarchical_stats_geo
The hierarchical settings specified here are used to group the inference of certain parameters together (similar to inference in "hierarchical" or "fixed/group effects" models). For example, users may desire to group all counties in a given state because they are geograhically proximate and impacted by the same statewide policies. The effect should be to make these inferred parameters follow a normal distribution and to observe shrinkage among the variance in these grouped estimates.
scenario name
required
name of hierarchical scenario, user defined
name
required
name of the estimated parameter that will be grouped (e.g., the NPI scenario name or a standardized, combined health outcome name like probability_incidI_incidC
)
module
required
name of the module where this parameter is estimated (important for finding the appropriate files)
geo_group_col
required
geodata column name that should be used to group parameter estimation
transform
required
type of transform that should be applied to the likelihood: "none" or "logit"
inference::priors
It is now possible to specify prior values for inferred parameters. This will have the effect of speeding up model convergence.
scenario name
required
name of prior scenario, user defined
name
required
name of NPI scenario or parameter that will have the prior
module
required
name of the module where this parameter is estimated
likelihood
required
specifies the distribution of the prior
name
module
geo_group_col
transform
inference:::priors
inference::
The pipeline uses files to communicate between different iterations. Currently, the following file types exist:
seed
init
snpi
spar
seir
hpar
hnpi
hosp
llik
During each iteration, inference uses these files to communicate with the compartmental model and outcomes. The intent is that inference should only need to read and write these files, and that the compartmental model can handle everything else. In addition to the global
versions of these files actually passed to the compartmental/reporting model, there exist chimeric
versions used internally by inference and stored in memory. These copies are what inference interacts with when it needs to perturb values. While this design was chosen primarily to support modularity (a fixed communication boundary makes it easy to swap out the compartmental model), it has had a number of additional benefits.
The first iteration of an MCMC algorithm is a special case, because we need to pull initial conditions for our parameters. We originally developed the model without inference in mind, so the compartmental model is already set up to read parameter distributions from the configuration file, and to draw values from those distributions, and record those parameters to file. We take advantage of this to bootstrap our MCMC parameters by running the model one time, and reading the parameters it generated from file.
We can, instead of bootstrapping our first iteration, read in final values of a previous iteration. This allows us to resume from runs to save computational time and effectively continue iterating on the same chain. We call these resumes: inferred parameters are taken from a previous run and allowed to continue being inferred ;
Resumes take the following files (if they exist) from previous runs and uses them as the starting point of a new run:
hnpi
snpi
seed
(This section describes the location and contents of the additional output files produced during an inference model run)
During inference runs, an additional file type, llik
, is created, which is described in the section ;
These files contain the log-likelihoods of the model simulation for each subpopulation, as well as some diagnostics on acceptance.
The meanings of the columns are:
ll
- These values are the log-likelihoods of data given the model and parameter values for a single subpopulation (in subpop
column) ;
filename
- ...
subpop
- The values of this column are the names of the nodes from the geodata
file.
accept
- Either 0 or 1, depending on whether the parameters during this iteration of the simulation were accepted (1) or rejected (0) in that subpopulation ;
accept_avg
;
accept_prob
;
For inference runs, ...
flepiMoP produces one file per parallel slot, for both global and chimeric outputs...
Need to add MultiPeriodModifier and hospitalization interventions
This documentation describes the new YAML configuration file options that may be used when performing inference on model runs. As compared to previous model releases, there are additions to the seeding
and interventions
sections, the outcomes
section replaces the hospitalization
section, and the filtering
section added to the file.
Importantly, we now name our pipeline modules: seeding
, seir
, hospitalization
and this becomes relevant to some of the new filtering
specifications.
Models may be calibrated to any available time series data that is also an outcome of the model (COVID-19 confirmed cases, deaths, hospitalization or ICU admissions, hospital or ICU occupancy, and ventilator use). Our typical usage has calibrated the model to deaths, confirmed cases, or both. We can also perform inference on intervention effectiveness, county-specific baseline R0, and the risk of specific health outcomes.
We describe these options below and present default values in the example configuration sections.
seeding
The model can perform inference on the seeding date and initial number of seeding infections in each subpop. An example of this new config section is:
The method for determining the proposal distribution for the seeding amount is hard-coded in the inference package (R/pkgs/inference/R/functions/perturb_seeding.R
). It is pertubed with a normal distribution where the mean of the distribution 10 times the number of confirmed cases on a given date and the standard deviation is 1.
interventions
The model can perform inference on the effectiveness of interventions as long as there is at least some calibration health outcome data that overlaps with the intervention period. For example, if calibrating to deaths, there should be data from time points where it would be possible to observe deaths from infections that occurred during the intervention period (e.g., assuming 10-18 day delay between infection and death, on average).
An example configuration file where inference is performed on scenario planning interventions is as follows:
interventions::settings::[setting_name]
Interventions may be specified in the same way as before, or with an added perturbation
section that indicates that inference should be performed on a given intervention's effectiveness. As previously, interventions with perturbations may be specified for all modeled locations or for explicit subpop.
In this setup, both the prior distribution and the range of the support of the final inferred value are specified by the value
section. In the configuration above, the inference algorithm will search 0 to 0.9 for all subpops to estimate the effectiveness of the stayhome
intervention period. The prior distribution on intervention effectiveness follows a truncated normal distribution with a mean of 0.6 and a standard deviation of 0.3. The perturbation
section specifies the perturbation/step size between the previously-accepted values and the next proposal value.
outcomes
sectionThis section is now structured more like the interventions
section of the config, in that it has scenarios and settings. We envision that separate scenarios will be specified for each IFR assumption.
outcomes::settings::[setting_name]
The settings for each scenario correspond to a set of different health outcome risks, most often just differences in the probability of death given infection (Pr(incidD|incidI)) and the probability of hospitalization given infection (Pr(incidH|incidI)). Each health outcome risk is referenced in relation to the outcome indicated in source.
For example, the probability and delay in becoming a confirmed case (incidC) is most likely to be indexed off of the number and timing of infection (incidI).
Importantly, we note that incidI is automatically defined from the SEIR transmission model outputs, while the other compartment sources must be defined in the config before they are used.
Users must specific two metrics for each health outcome, probability and delay, while a duration is optional (e.g., duration of time spent in the hospital). It is also optional to specify a perturbation section (similar to perturbations specified in the NPI section) for a given health outcome and metric. If you want to perform inference (i.e., if perturbation
is specified) on a given metric, that metric must be specified as a distribution (i.e., not fixed
) and the range of support for the distribution represents the range of parameter space explored in the inference.
filtering
sectionThis section configures the settings for the inference algorithm. The below example shows the settings for some typical default settings, where the model is calibrated to the weekly incident deaths and weekly incident confirmed cases for each subpop. Statistics, hierarchical_stats_geo, and priors each have scenario names (e.g., sum_deaths,
local_var_hierarchy,
and local_var_prior,
respectively).
filtering
settingsWith inference model runs, the number of simulations nsimulations
refers to the number of final model simulations that will be produced. The filtering$simulations_per_slot
setting refers to the number of iterative simulations that will be run in order to produce a single final simulation (i.e., number of simulations in a single MCMC chain).
filtering::statistics
The statistics specified here are used to calibrate the model to empirical data. If multiple statistics are specified, this inference is performed jointly and they are weighted in the likelihood according to the number of data points and the variance of the proposal distribution.
filtering::hierarchical_stats_geo
The hierarchical settings specified here are used to group the inference of certain parameters together (similar to inference in "hierarchical" or "fixed/group effects" models). For example, users may desire to group all counties in a given state because they are geograhically proximate and impacted by the same statewide policies. The effect should be to make these inferred parameters follow a normal distribution and to observe shrinkage among the variance in these grouped estimates.
filtering::priors
It is now possible to specify prior values for inferred parameters. This will have the effect of speeding up model convergence.
This section describes how to specify the values of each model state at the time the simulation starts, and how to make instantaneous changes to state values at other times (e.g., due to importations)
In order for the models specified previously to be dynamically simulated, the user must provide initial conditions, in addition to the model structure and parameter values. Initial conditions describe the value of each variable in the model at the time point that the simulation is to start. For example, on day zero of an outbreak, we may assume that the entire population is susceptible except for one single infected individual. Alternatively, we could assume that some portion of the population already has prior immunity due to vaccination or previous infection. Different initial conditions lead to different model trajectories.
The initial_conditions
section of the configuration file is detailed below. Note that in some cases, can replace or complement the initial condition, the table below provides a quick comparison of these sections.
The configuration items in the initial_conditions
section of the config file are
initial_conditions:method
Must be either "Default"
, "SetInitialConditions"
, or "FromFile".
initial_conditions:initial_conditions_file
Required for methods “SetInitialConditions
” and “FromFile
” . Path to a .csv or .parquet file containing the list of initial conditions for each compartment.
initial_conditions:initial_file_type
Only required for method: “FolderDraw”
. Description TBA
initial_conditions::allow_missing_subpops
Optional for all methods, determines what will happen if initial_conditions_file
is missing values for some subpopulations. If FALSE, the default behavior, or unspecified, an error will occur if subpopulations are missing. If TRUE, then for subpopulations missing from the initial_conditions
file, it will be assumed that all individuals begin in the first compartment (the “first” compartment depends on how the model was specified, and will be the compartment that contains the first named category in each compartment group), unless another compartment is designated to hold the rest of the individuals ;
initial_conditions::allow_missing_compartments
Optional for all methods. If FALSE, the default behavior, or unspecified, an error will occur if any compartments are missing for any subpopulation. If TRUE, then it will be assumed there are zero individuals in compartments missing from the initial_conditions file
.
initial_conditions::proportional
If TRUE, assume that the user has specified all input initial conditions as fractions of the population, instead of numbers of individuals (the default behavior, or if set to FALSE). Code will check that initial values in all compartments sum to 1.0 and throw an error if not, and then will multiply all values by the total population size for that subpopulation ;
Details on implementing each initial conditions method and the options that go along with it are below.
initial_conditions::method
The default initial conditions are that the initial value of all compartments for each subpopulation will be zero, except for the first compartment, whose value will be the population size. The “first” compartment depends on how the model was specified, and will be the compartment that contains the first named category in each compartment group.
For example, a model with the following compartments
with the accompanying geodata file
will be started with 1000 individuals in the S_child_unvaxxed in the "small province" and 10,000 in that compartment in the "large province".
With this method users can specify arbitrary initial conditions in a convenient formatted input .csv or .parquet file.
For example, for a model with the following compartments
and initial_conditions
sections
with the accompanying geodata file
where initial_conditions.csv
contains
the model will be started with half of the population of both subpopulations, consisting of children and the other half of adults, everyone unvaccinated, and 5 infections (in exposed-but-not-yet-infectious class) among the unvaccinated adults in the large province, with the remaining individuals susceptible (4995). All other compartments will contain zero individuals initially ;
initial_conditions::initial_conditions_file
must contain the following columns:
subpop
– the name of the subpopulation for which the initial condition is being specified. By default, all subpopulations must be listed in this file, unless the allow_missing_subpops
option is set to TRUE.
mc_name
– the concatenated name of the compartment for which an initial condition is being specified. The order of the compartment groups in the name must be the same as the order in which these groups are defined in the config for the model, e.g., you cannot say unvaccinated_S
.
amount
– the value of the initial condition; either a numeric value or the string "rest".
For each subpopulation, if there are compartments that are not listed in SetInitialConditions
, an error will be thrown unless allow_missing_compartments
is set to TRUE, in which case it will be assumed there are zero individuals in them. If the sum of the values of the initial conditions in all compartments in a location does not add up to the total population of that location (specified in the geodata file), an error will be thrown. To allocate all remaining individuals in a subpopulation (the difference between the total population size and those allocated by defined initial conditions) to a single pre-specified compartment, include this compartment in the initial_conditions_file
but instead of a number in the amount
column, put the word "rest" ;
If allow_missing_subpops
is FALSE or unspecified, an error will occur if initial conditions for some subpopulations are missing. If TRUE, then for subpopulations missing from the initial_conditions
file, it will be assumed that all individuals begin in the first compartment. (The “first” compartment depends on how the model was specified, and will be the compartment that contains the first named category in each compartment group.)
For example, for an input configuration file containing
with the accompanying geodata file
where initial_conditions_from_previous.csv
contains
The simulation would be initiated on 2021-06-01 with these values in each compartment (no children vaccinated, only adults in the small province vaccinated, some past and current infection in both compartments but ).
initial_conditions::initial_conditions_file
must contain the following columns:
mc_value_type
– in model output files, this is either prevalence
or incidence
. Prevalence values only are selected to be used as initial conditions, since compartmental models described the prevalence (number of individuals at any given time) in each compartment. Prevalence is taken to be the value measured instantaneously at the start of the day
mc_name
– The name of the compartment for which the value is reported, which is a concatenation of the compartment status in each state type, e.g. "S_adult_unvaxxed" and must be in the same order as these groups are defined in the config for the model, e.g., you cannot say unvaxxed_S_adult
.
subpop_1
, subpop_2
, etc. – one column for each different subpopulation, containing the value of the number of individuals in the described compartment in that subpopulation at the given date. Note that these are named after the nodenames defined by the user in the geodata
file.
date
– The calendar date in the simulation, in YYYY-MM-DD format. Only values with a date that matches to the simulation start_date
will be used ;
The way that initial conditions is specified with SetInitialConditions
and FromFile
results in a single value for each compartment and does not easily allow the user to instead specify a distribution (like is possible for compartmental or outcome model parameters). If a user wants to use different possible initial condition values each time the model is run, the way to do this is to instead specify a folder containing a set of file with initial condition values for each simulation that will be run. The user can do this using files with the format described in initial_conditions::method::SetInitialConditions
using instead method::SetInitialConditionsFolder
draw. Similarly, to provide a folder of initial condition files with the format described in initial_conditions::method:FromFile
using instead method::FromFileFolderDraw
;
Each file in the folder needs to be named according to the same naming conventions as the model output files: run_number.runID.file_type.[csv or parquet] where ....[DESCRIBE] as it is now taking the place of the seeding files the model would normally outpu ;
Only one additional config argument is needed to use a FolderDraw method for initial conditions:
initial_file_type
: either seir
or seed
When using FolderDraw methods, initial_conditions_file
should now be the path to the directory that contains the folder with all the initial conditions files. For example, if you are using output from another model run and so the files are in an seir folder within a model_output folder which is in within your project directory, you would use initial_conditions_file: model_outpu ;
The model needs the configurations file to run (described in previous sections). These configs become lengthy and sometimes difficult to type manually. The config writer helps to generate configs provided the relevant files are present.
These functions are used to print specific sections of the configuration files.
Used to generate the global header. For more information on global headers click .
Used to generate the spatial setup section of the configuration. For more information on spatial setup click .
Used to generate the compartment list for each way a population can be divided.
census year: year of geodata files
modeled states (sim_states): This has US state abbreviations. Do we include the names of the sub-populations in the geodata file? Eg: small_province, large_province
state_level: Specifies if the runs are run for US states
filtering
sectionThe filtering
section configures the settings for the inference algorithm. The below example shows the settings for some typical default settings, where the model is calibrated to the weekly incident deaths and weekly incident confirmed cases for each subpop. Statistics, hierarchical_stats_geo, and priors each have scenario names (e.g., sum_deaths,
local_var_hierarchy,
and local_var_prior,
respectively).
filtering
settingsWith inference model runs, the number of simulations nsimulations
refers to the number of final model simulations that will be produced. The filtering$simulations_per_slot
setting refers to the number of iterative simulations that will be run in order to produce a single final simulation (i.e., number of simulations in a single MCMC chain).
filtering::statistics
The statistics specified here are used to calibrate the model to empirical data. If multiple statistics are specified, this inference is performed jointly and they are weighted in the likelihood according to the number of data points and the variance of the proposal distribution.
filtering::hierarchical_stats_geo
The hierarchical settings specified here are used to group the inference of certain parameters together (similar to inference in "hierarchical" or "fixed/group effects" models). For example, users may desire to group all counties in a given state because they are geograhically proximate and impacted by the same statewide policies. The effect should be to make these inferred parameters follow a normal distribution and to observe shrinkage among the variance in these grouped estimates.
filtering::priors
It is now possible to specify prior values for inferred parameters. This will have the effect of speeding up model convergence.
Current branch: main
This repository contains all the code underlying the mathematical model and the data fitting procedure, as well as ...
To actually run the model, this repository folder must be located inside a location folder (e.g. COVID19_USA
) which contains additional files describing the specifics of the model to be run (i.e. the config file), all the necessary input data (i.e. the population structure), and any data to which the model will be fit (i.e. cases and death counts each day)
This directory contains the core Python code that creates and simulates generic compartmental models and additionally simulates observed variables. This code is called gempyor
for General Epidemics Modeling Pipeline with Yterventions and Outcome Reporting. The code in gempyor is called from R scripts (see /main_scripts and /R sections below) that read the config, run the model simulation via gempyor as required, read in data, and run the model inference algorithms.
pyproject.toml
- contains the build system requirements and dependencies for the gempyor package; used during package installation
setup.cfg
- contains information used by Python's setuptools
to build the gempyor
package. Contains the definitions of command line shortcuts for running simulations directly from gempyor
(bypassing R interface) if desired
seir.py - Contains the core code for simulating the mathematical model. Takes in the model definition and parameters from the config, and outputs a file with a timeseries of the value of each state variable (# of individuals in each compartment)
simulate_seir.py -
steps_rk.py -
steps_source.py -
outcomes.py - Contains the core code for generating the outcome variables. Takes in the output of the mathematical model and parameters from the config, and outputs a file with a timeseries of the value of each outcome (observed) variable
simulate_outcomes.py -
setup.py
file_paths.py -
compartments.py
parameters.py
results.py
seeding_ic.py
/NPI/
base.py -
SinglePeriodModifier.py -
MultiPeriodModifier.py -
SinglePeriodModifierInterven.py -
/dev - contains functions that are still in development
/data - ?
Contains notebooks with some gempyor
-specific documentation and examples
Rinterface.Rmd - And R notebook that provides some background on gempyor
and describes how to run it as a standalone package in python, without the R wrapper scripts or the Docker.
Rinterface.html - HTML output of Rinterface.Rmd
This directory contains the R scripts that takes the specifications in the configuration file and sets up the model simulation, reads the data, and performs inference.
inference_main.R - This is the master R script used to run the model. It distributes the model runs across computer cores, setting up runs for all the scenarios specified in the config, and for each model iteration used in the parameter inference. Note that despite the name "inference" in this file, this script must be used to run the model even if no parameter inference is conducted
inference_slot.R - This script contains the main code of the inference algorithm.
create_seeding.R -
This directory contains the core R code - organized into functions within packages - that handle the model setup, data pulling and processing, conducting parameter inference for the model, and manipulating model output.
flepicommon
config.R
DataUtils.R
file_paths.R
safe_eval.R
compartments.R
inference - contains code to
groundtruth.R - contains functions for pulling ground truth data from various sources. Calls functions in the flepicommon
package
functions.R - contains many functions used in running the inference algorithm
inference_slot_runner_funcs.R - contains many functions used in running the inference algorithm
inference_to_forecast.R -
documentation.Rmd - Summarizes the documentation relevant to the inference package, including the configuration file options relevant to model fitting
InferenceTest.R -
/tests/ -
config.writer
create_config_data.R
process_npi_list.R
yaml_utils.R
report.generation
DataLoadFuncs.R
ReportBuildUtils.R
ReportLoadData.R
setup_testing_environment.R
Depreciated? Should be removed
Depreciated? Should be removed
Depreciated? Should be removed
Current branch: main
Contains R scripts for generating model input parameters from data, writing config files, or processing model output. Most of the files in here are historic (specific to a particular model run) and not frequently used. Important scripts include:
get_vacc_rate_and_outcomes_R13.R - this pulls vaccination coverage and variant prevalence data specific to rounds (either empirical, or specified by the scenario), and adjusts these data to the formats required for the model. Several data files are created in this process: variant proportions for each scenario, vaccination rates by age and dose. A file is also generated that defines the outcome ratios (taking in to account immune escape, cross protection and VE).
Scripts to generate config files for particular submissions to the Scenario Modeling Hub. Most of this functionality has now been replaced by the config writer package ()
Scripts to process the output of model runs into data formats and plots used for Scenario Modeling Hub and Forecast Hub. These scripts pull runs from AWS S3 buckets and processes and formats them to specifications for submissions to Scenario Modeling Hubs, Forecast Hubs and FluSight. These formatted files are saved and the results visualized. This script uses functions defined in /COVIDScenarioPipeline/R/scripts/postprocess.
run_sum_processing.R
Contains data files used in parameterizing the model for COVID-19 in the US (such as creating the population structure, describing vaccine efficacy, describing parameter alterations due to variants, etc). Some data files are re-downloaded frequently using scripts in the pipeline (us_data.csv) while others are more static (geodata, mobility)
Important files and folders include
geodata.csv
geodata_2019_statelevel.csv
mobility.csv
mobility_territories_2011-2015_statelevel.csv
outcomes_ratios.csv
US_CFR_shift_dates_v3.csv
US_hosp_ratio_corrections.cs
seeding_agestrat_RX.csv
"Shape-files" (.shp) that .....
usa-subpop-params-output_V2.parquet
/data/intervention_tracking
Data files containing the dates that different non pharmaceutical interventions (like mask mandates, stay-at-home orders, school closures) were implemented by state
Files used to create the config elements related to vaccination, such as vaccination rates by state by age and vaccine efficacy by dose
/data/variant
Files created in the process of downloading and analyzing data on variant proportions
Contains files for scientific manuscripts using results from the pipeline. Not up to date
Contains an archive of configuration files used for previous model runs
Same as above. Contains an archive of configuration files used for previous model runs
Depreciated - to be removed? - contains rarely used scripts
Depreciated - to be removed? - contains rarely used notebooks to check model input. Might be used in some unit tests?
empty?
Depreciated - to be removed?
These scripts are run automatically after an inference run
Some information to consider if you'd like your script to be run automatically after an inference run ;
Most R/python packages are installed already installed. Try to run your script on the conda environment defined on the (or easier if you are not set up on MARCC, ask me)
There will be some variables set in the environment. These variables are:
$CONFIG_PATH
the path to the configuration fil ;
$FLEPI_RUN_INDEX
the run id for this run (e.g `CH_R3_highVE_pesImm_2022_Jan29
`
$JOB_NAME
this job name (e.g USA-20230130T163847_inference_med
)
$FS_RESULTS_PATH
the path where lies the model results. It's a folder that contains the model_ouput/ as a subfolder
$FLEPI_PATH
path of the flepiMoP repository.
$DATA_PATH
path of the Data directory (e.g Flu_USA or COVID19_USA).
Anything you ask can theoretically be provided here.
The script must run without any user intervention.
The script is run from $DATA_PATH.
Your script lies in the flepiMoP directory (preferably) or it's ok if it is in a data directory if it makes sense ;
It is run on a 64Gb of RAM multicore machine. All scripts combined must complete under 4 hours, and you can use multiprocessing (48 cores)
Outputs (pdf, csv, html, txt, png ...) must be saved in a directory named pplot/
(you can assume that it exists) in order to be sent to slack by FlepiBot 🤖 after the run.
an example postprocessing script (in python) is .
You can test your script on MARCC on a run that is already saved in /data/struelo1/flepimop-runs
or I can do it for you.
Once your script works, add (or ask to add) the command line to run in file batch/postprocessing_scripts.sh
between the START and END lines, with a little comment about what your script does.
For now this only work from branch emcee_batch
You need, under inference, to add method: emcee
and modify the statistics:
as shown in the diff below (basically: all resampling goes to one subsection, with some minor changes to names).
To see which llik options and regularization (e.g do you want to weigh more the last weeks for forecasts, or do you want to add the sum of all subpop) see files statistics.py.
Install gempyor from branch emcee_batch . Test your config by running:
on your laptop. If it works, it should produce:
plots of simulation directly from your config
plots after the fits with the fits and the parameter chains
and h5 file with all the chains
and in model_output, the final hosp/snpi/seir/... files in the flepiMoP structure.
It will output something like
```
Here, it says the config fits 92 parameters, we'll keep that in mind and choose a number of walkers greater than (ideally 2 times) this number of parameters.
Install gempyor on the cluster. test it with the above line, then modify this script:
so you need to have:
-c
(number of core) equal to roughly half the number of walkers (slots/parallel chains)
mem to be around two times the number of walkers. Look at the computes nodes you have access to and make something that can be prioritized fast enough.
nsamples is the number of final results you want, but it's fine not to care about it, I rerun the sampling from my computer.
To resume from an existing run, add the previous line --resume
and it 'll start from the last parameter values in the h5 files.
To analyze run postprocessing/emcee_postprocess.ipynb
First, this plots the chains and then it runs nsamples (you can choose it) projection with the end of the chains and does the plot of the fit, with and without projections
You need to interact with Github to run and edit flepimop
code. is a web platform for people to share and manage software, and it is based on a 'version control' software called git
that helps programmers keep track of changes to code. Flepimop core code as well as example projects using flepimop code are all stored on Github, and frequently being updated. The first step to using flepimop for your own project is making sure you're set up to interact with code shared on Github.
If you are totally new to Github, navigate to and Sign Up for a new account. Read about the .
To work with flepimop
code, you can do some tasks from the Github website, but you'll also need a way to 'clone' the code to your own local computer and keep it up to date with versions hosted online. You can do this either using a user interface like , or, using commands from the command line. Make sure you have one or both installed.
If you are a veteran user, make sure you're signed in on Github.com and through whatever method you use locally on your computer to interact with Github.
In order to run any model with flepiMoP, you need access to two separate directories: One containing the flepiMoP code (code directory), and another containing the specific input files to run the model of your choosing (and to save the output from that model) (project directory). The is available in a public repository on Github which can be pulled locally to serve as the code directory. We highly recommend also using Github to create your project directory. To get familiar with the code, we recommend starting with our example configurations by making a fork of . If you need to create your own project repository from scratch, see instructions .
For both the project repository and flepiMoP code repository, make sure you're on the correct branch, then pull updates from Github. Take note of the local file path to each directory.
These directories can be located on your computer wherever you prefer, since you can tell flepiMoP where they are, but we recommend you clone these flat, e.g.
To get access to the flepiMoP model code - stored as a - you need to copy it to your local computer (called "" in git lingo).
To clone the flepimop
code repository
If you're using the command line in a terminal, first navigate to your local directory you'll use as the parent directory for all these files. Then, use the command:
git clone https://github.com/HopkinsIDD/flepiMoP
If you're using Github Desktop, go File -> Clone Repository, switch to the "URL" tab and copy the URL https://github.com/HopkinsIDD/flepiMoP
there. For the "Local Path" option, make sure you choose your desired parent directory.
flepimop_sample
The flepimop_sample repository contains example configuration files you can use to run simple models, as well as structured model inputs (e.g., population sizes, initial conditions) organized as we recommend organizing your own project repositories. A good way to start out with flepimop is to try running these simple models, or use them as a template to make more complex ones ;
Clone the sample project repository locally.
If you're using the command line in a terminal, first navigate to your local directory you'll use as the parent directory for all these files. Then, use the command:
git clone <my flepimop_sample repository URL>
If you're using Github Desktop, go File -> Clone Repository and either find the repository name under the Github.com list, or switch to the "URL" tab and copy the URL there. For the "Local Path" option, make sure you choose your desired parent directory.
In either case, make you are cloning your forked version of the repository, not the version owned by HopkinsIDD
Make sure the sample project repository files are up to date
To make sure that changes in the core flepimop code are always in sync with our example configuration files, we keep the newest versions of the sample code in the flepimop repository (in the examples
directory). We try to keep flepimop_sample repository up to date, but in case we haven't kept up, it's best to copy the most up to date files over yourself
Copy all the contents of the examples/tutorials
directory into your local version of flepimop_sample
. You can do this by copying and pasting the files, or, by running the following at the command line in your terminal (assuming you have navigated to the parent directory that contains both your repositories):
cp -a ./flepiMoP/examples/tutorials/. ./flepimop_sample/
You will see if there are any changes to flepimop_sample files by looking at Github's change tracking feature locally ;
Create a repository for your project on Github, naming it something other than flepiMoP. This repository will eventually contain the configuration file specifying your model, any other input files or data, and will be where the model output will be stored. These files are always kept completely separately from the universal flepimop
code that runs the model.
Clone the repository locally (as above), either before or after populating it with files described below.
Put your model configuration file(s) directly in this repository.
Now you area ready to run the code using your desired method (see below)!
Since you will be editing files in your project repository frequently, get in the habit of using the git workflow - committing those changes when you've completed a concrete task, pushing your changes to the remote (online) version of your repository on Github.com, and making sure to fetch changes from the remote version to download to your local version before you start a new task (if you share your project with others or switch computers).
Short tutorial on running FlepiMop on your personal computer using a "Docker" container
See the section to ensure you have access to the correct files needed to run. On your local machine, determine the file paths to:
the directory containing the flepimop code (likely the folder you cloned from Github), which we'll call <dir1>
the directory containing your project code including input configuration file and population structure (again likely from Github), which we'll call <dir2>
For example, if you clone your Github repositories into a local folder called Github and are using the flepimop_sample as a project repository, your directory names could be _On Mac: ;
<dir1> = /Users/YourName/Github/flepiMoP
<dir2> = /Users/YourName/Github/flepimop_sample On Windows: <dir1> = C:\Users\YourName\Github\flepiMoP
<dir2> = C:\Users\YourName\Github\flepimop_sample\
(hint: if you navigate to a directory like C:\Users\YourName\Github
using cd C:\Users\YourName\Github
, modify the above <dir1>
paths to be .\flepiMoP
and .\flepimop_sample)
\
Note that Docker file and directory names are case sensitive
is a software platform that allows you to build, test, and deploy applications quickly. Docker packages software into standardized units called containers that have everything the software needs to run including libraries, system tools, code, and runtime. This means you can run and install software without installing the dependencies in the local operating system.
A Docker container is an environment which is isolated from the rest of the operating system i.e. you can create files, programs, delete and everything but that will not affect your OS. It is a local virtual OS within your OS ;
For flepiMoP, we have a Docker container that will help you get running quickly ;
Make sure you have the Docker software installed, and then open your command prompt or terminal application ;
Helpful tools
To find the Apple Terminal, type "Terminal" in the search bar or go to Applications -> Utilities -> Terminal ;
First, make sure you have the latest version of the flepimop Docker (hopkinsidd/flepimop)
downloaded on your machine by opening your terminal application and entering:
Next, run the Docker image by entering the following, replace <dir1>
and <dir2>
with the path names for your machine (no quotes or brackets, just the path text):
On Windows: If you get an error, you may need to delete the "\" line breaks and submit as a single continuous line of code.
In this command, we run the Docker container, creating a volume and mounting (-v
) your code and project directories into the container. Creating a volume and mounting it to a container basically allocates space in Docker for it to mirror - and have read and write access - to files on your local machine ;
The folder with the flepiMoP code <dir2>
will be on the path flepimop
within the Docker environment, while the project folder will be at the path `drp. ;
You now have a local Docker container installed, which includes the R and Python versions required to run flepiMop with all the required packagers already installed ;
You don't need to re-run the above steps every time you want to run the model. When you're done using Docker for the day, you can simply "detach" from the container and pause it, without deleting it from your machine. Then you can re-attach to it when you next want to run the model ;
Create environmental variables for the paths to the flepimop code folder and the project folder:
Go into the code directory and do the installation the R and Python code packages
Each installation step may take a few minutes to run.
Note: These installations take place in the Docker container and not the local operating system. They must be made once while starting the container and need not be done for every time you run a model, provided they have been installed once. You will need an active internet connection for pulling the Docker image and installing the R packages (since some are hosted online), but not for other steps of running the model
Everything is now ready 🎉 The next step depends on what sort of simulation you want to run: One that includes inference (fitting model to data) or only a forward simulation (non-inference). Inference is run from R, while forward-only simulations are run directly from the Python package gempyor
.
In either case, navigate to the project folder and make sure to delete any old model output files that are there
An inference run requires a configuration file that has the inference
section. Stay in the $DATA_PATH
folder, and run the inference script, providing the name of the configuration file you want to run (ex. config.yml
;
This will run the model and create a lot of output files in $DATA_PATH/model_output/
;
The last few lines visible on the command prompt should be:
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
NULL
If you want to quickly do runs with options different from those encoded in the configuration file, you can do that from the command line, for example
where:
n
is the number of parallel inference slots,
j
is the number of CPU cores to use on your machine (if j
> n
, only n
cores will actually be used. If j
<n
, some cores will run multiple slots in sequence)
k
is the number of iterations per slots.
You can put all of this together into a single script that can be run all at once ;
Stay in the $DATA_PATH
folder, and run a simulation directly from forward-simulation Python package gempyor,
call gempyor-simulate
providing the name of the configuration file you want to run (ex. config.yml
;
It is currently required that all configuration files have an interventions
section. There is currently no way to simulate a model with no interventions, though this functionality is expected soon. For now, simply create an intervention that has value zero ;
You can put all of this together into a single script that can be run all at once ;
You can avoid repeating all the above steps every time you want to run the code. When the docker run
command creates an container, it is stored locally on your computer with all the installed packages/variables/etc you created. You can leave this container and come back to it whenever you want, without having to redo all this set up ;
When you're in the Docker container, figure out the name Docker has given to the container you created by typing
the output will be something silly like
write this down for later reference. You can also see the container name in the Docker Desktop app's Containers tab ;
To "detach" from the Docker container and stop it, type CTLR
+ c
The command prompt for your terminal application is now just running locally, not in the Docker container ;
Next time you want to re-start and "attach" the container, type
at the command line or hit the play button ▶️ beside the container's name in the Docker app. Replace container_name with the name for your old container ;
Then "attach" to the container by typing
The reason that stopping/starting a container is separate from detaching/attaching is that technically you can leave a container (and any processes within it) running in the background and exit it. In case you want to do that, detach and leave it running by typing CTRL
+ p
then quickly CTRL
+ q
. Then when you want to attach to it again, you don't need to do the part about starting the container ;
If you the core model code within the flepimop repository (flepimop/flepimop/gempyor_pkg/
or flepimop/flepimop/R_packages
) has been edited since you created the contained, or if the R or Python package requirements have changed, then you'll have to re-run the steps to install the packages, but otherwise, you can just start running model code!
integar 1
integar 1
Whether model output will be saved as .parquet files (a compressed representation that can be opened and manipulated with minimal memory. May be required for large simulations). Read more about .
integar 1
Integer 1
In addition to resuming parameters (above), we can also perform a continuation resume. In addition to resuming parameters and seeding, continuations also use the compartmental fits from previous runs. For a config starting at time continuing and resuming from a previous run, the compartmental states of the previous run at time are used as the initial conditions of the continuation resume ;
This configuration allows us to infer subpop-level baseline R0 estimates by adding a local_variance
intervention. The baseline subpop-specific R0 estimate may be calculated as where R0 is the baseline simulation R0 value, and local_variance is an estimated subpop-specific value.
Similar to "SetInitialConditions"
, with this method users can specify arbitrary initial conditions in a formatted .csv or .parquet input file. However, the format of the input file is different. The required file format is consistent with the from the compartmental model, so the user could take output from one simulation and use it as input into another simulation with the same model structure ;
In order to create a sample project repository from the repository you can follow these steps:
Fork the sample project repository, , to your desired Github account and give it a repository name. Instructions for forking a repository are available . Copy the URL of your forked version of the repository.
How to create a repository on Github:
This folder (which can have any name, but for simplicity can just be called model_input) should contain your files specifying the , , and optional input such as time-series parameters.
If you have any trouble or questions while trying to run flepimop
, please report them on the .
The code is written in a combination of and . The Python part of the model is a package called , and includes all the code to simulate the epidemic model and the observational model and apply time-dependent interventions. The R component conducts the (optional) parameter inference, and all the (optional) provided pre and post processing scripts are also written in R. Most uses of the code require interacting with components written in both languages, and thus making sure that both are installed along with a set of required packages. However, Python alone can be used to do forward simulations of the model using gempyor
.
Because of the need for multiple software packages and dependencies, we describe different ways you can run the model, depending on the requirements of your model setup. See for a quick introduction to using gempyor
and flepiMoP
. We also provide some more ways to run our model, particularly for doing more complex model inference tasks.
The setup described above assumes that a typical user will not be editing the core flepimop
user code. If however you are involved in the project in a way that you do plan on editing code, or if you want to add your own enhancements, please consider forking the repository and create a version in your own account, instead of just cloning our (user:HopkinsIDD) version. Set your with the HopkinsIDD version though, so that you get notified of code updates or bug fixes that may also impact your fork.
To understand the basics of Docker, refer . The following may also be helpful ;
To install Docker for Mac, refer to the following link: . Pay special attention to the specific chip your Mac has (Apple Silicon vs Intel), as installation files and directions differ
To install Docker for Windows, refer to the following link:
To find the Windows Command Prompt, type “Command Prompt" in the search bar and open it. This may be helpful for new users ;
template
Required
"SinglePeriodModifierR0" or "StackedModifier"
period_start_date
optional for SinglePeriodModifierR0
date between global start_date
and end_date
; default is global start_date
period_end_date
optional for SinglePeriodModifierR0
date between global start_date
and end_date
; default is global end_date
value
required for SinglePeriodModifierR0
specifies both the prior distribution and range of support for the final inferred values
perturbation
optional for SinglePeriodModifierR0
this option indicates whether inference will be performed on this setting and how the proposal value will be identified from the last accepted value
subpop
optional for SinglePeriodModifierR0
list of subpops, which must be in geodata
method
required
"delayframe"
param_from_file
required
if TRUE, will look for param_subpop_file
param_subpop_file
optional
path to subpop-params parquet file, which indicates location specific risk values. Values in this file will override values in the config if there is overlap.
scenarios
required
user-defined scenario name
settings
required
See details below
(health outcome metric)
required
"incidH", "incidD", "incidICU", "incidVent", "incidC", corresponding to variable names
source
required
name of health outcome metric that is used as the reference point
probability
required
health outcome risk
probability::value
required
specifies whether the value is fixed or distributional and the parameters specific to that metric and distribution
probability::perturbation
optional
inference settings for the probability metric
delay
required
time delay between source
and the specified health outcome
delay::value
required
specifies whether the value is fixed or distributional and the parameters specific to that metric and distribution
delay::perturbation
optional
inference settings for the time delay metric (coming soon)
duration
optional
duration that health outcome status endures
duration::value
required
specifies whether the value is fixed or distributional and the parameters specific to that metric and distribution
duration::perturbation
optional
inference settings for the duration metric (coming soon)
simulations_per_slot
required
number of iterations in a single MCMC inference chain
do_filtering
required
TRUE if inference should be performed
data_path
required
file path where observed data are saved
likelihood_directory
required
folder path where likelihood evaluations will be stored as the inference algorithm runs
statistics
required
specifies which data will be used to calibrate the model. see filtering::statistics
for details
hierarchical_stats_geo
optional
specifies whether a hierarchical structure should be applied to any inferred parameters. See filtering::hierarchical_stats_geo
for details.
priors
optional
specifies prior distributions on inferred parameters. See filtering::priors
for details
name
required
name of statistic, user defined
aggregator
required
function used to aggregate data over the period
, usually sum or mean
period
required
duration over which data should be aggregated prior to use in the likelihood, may be specified in any number of days
, weeks
, months
sim_var
required
column name where model data can be found, from the hospitalization outcomes files
data_var
required
column where data can be found in data_path file
remove_na
required
logical
add_one
required
logical, TRUE if evaluating the log likelihood
likelihood::dist
required
distribution of the likelihood
likelihood::param
required
parameter value(s) for the likelihood distribution. These differ by distribution so check the code in inference/R/functions.R/logLikStat
function.
scenario name
required
name of hierarchical scenario, user defined
name
required
name of the estimated parameter that will be grouped (e.g., the NPI scenario name or a standardized, combined health outcome name like probability_incidI_incidC
)
module
required
name of the module where this parameter is estimated (important for finding the appropriate files)
geo_group_col
required
geodata column name that should be used to group parameter estimation
transform
required
type of transform that should be applied to the likelihood: "none" or "logit"
scenario name
required
name of prior scenario, user defined
name
required
name of NPI scenario or parameter that will have the prior
module
required
name of the module where this parameter is estimated
likelihood
required
specifies the distribution of the prior
census_year
Optional (2019)
The year of data uses to generate the geodata files for US simulations ?? [Unsure about this]
sim_states
Required
Vector of locations that will be modeled (US Specific?)
geodata_file
Optional (geodata.csv)
Name of the geodata file which is imported
mobility_file
Optional (mobility.csv)
Name of the mobility file which is imported
popnodes
Optional (pop2019est)
Name of a column in the geodata file that specifies the population of every subpopulation column
nodenames
Optional (subpop)
Name of a column in the geodata file that specifies the name of the subpopulation
state_level
Optional (TRUE)
Specifies if the subpopulations are US states
inf_stages
Optional (S,E,I1,I2,I3,R,W)
Various infection stages an individual can be in
vaccine_compartments
Optional (unvaccinated, 1dose, 2dose, waned)
Various levels of vaccinations an individual can have
variant_compartments
Optional (WILD, ALPHA, DELTA, OMICRON)
Variants of the pathogen
age_strata
Optional (age0to17, age18to64, age65to100)
Different age groups, the population has been stratified in
simulations_per_slot
required
number of iterations in a single MCMC inference chain
do_filtering
required
TRUE if inference should be performed
data_path
required
file path where observed data are saved
likelihood_directory
required
folder path where likelihood evaluations will be stored as the inference algorithm runs
statistics
required
specifies which data will be used to calibrate the model. see filtering::statistics
for details
hierarchical_stats_geo
optional
specifies whether a hierarchical structure should be applied to any inferred parameters. See filtering::hierarchical_stats_geo
for details.
priors
optional
specifies prior distributions on inferred parameters. See filtering::priors
for details
name
required
name of statistic, user defined
aggregator
required
function used to aggregate data over the period
, usually sum or mean
period
required
duration over which data should be aggregated prior to use in the likelihood, may be specified in any number of days
, weeks
, months
sim_var
required
column name where model data can be found, from the hospitalization outcomes files
data_var
required
column where data can be found in data_path file
remove_na
required
logical
add_one
required
logical, TRUE if evaluating the log likelihood
likelihood::dist
required
distribution of the likelihood
likelihood::param
required
parameter value(s) for the likelihood distribution. These differ by distribution so check the code in inference/R/functions.R/logLikStat
function.
scenario name
required
name of hierarchical scenario, user defined
name
required
name of the estimated parameter that will be grouped (e.g., the NPI scenario name or a standardized, combined health outcome name like probability_incidI_incidC
)
module
required
name of the module where this parameter is estimated (important for finding the appropriate files)
geo_group_col
required
geodata column name that should be used to group parameter estimation
transform
required
type of transform that should be applied to the likelihood: "none" or "logit"
scenario name
required
name of prior scenario, user defined
name
required
name of NPI scenario or parameter that will have the prior
module
required
name of the module where this parameter is estimated
likelihood
required
specifies the distribution of the prior
method
required
"FolderDraw"
seeding_file_type
required for FolderDraw
"seed" or "impa"
indicates which seeding file type the SEIR model will look for, "seed", which is generated from create_seeding.R, or "impa", which refers to importation
folder_path
required
path to folder where importation inference files will be saved
lambda_file
required
path to seeding file
perturbation_sd
required
standard deviation for the proposal value of the seeding date, in number of days
Config section optional or required?
Optional
Optional
Function of section
Specify number of individuals in each compartment at time zero
Allow for instantaneous changes in individuals' states
Default
Entire population in first compartment, zero in all other compartments
No seeding events
Requires input file?
Yes, .csv
Yes, .csv
Input description
Input is a list of compartment names, location names, and amounts of individuals in that compartment location. All compartments must be listed unless a setting to default missing compartments to zero is turned on.
Input is list of seeding events defined by source compartment, destination compartment, number of individuals transitioning, and date of movement. Compartments without seeding events don't need to be listed.
Specifies an incidence or prevalence?
Amounts specified are prevalence values
Amounts specified are instantaneous incidence values
Useful for?
Specifying initial conditions, especially if simulation does not start with a single infection introduced into a naive population.
Modeling importations, evolution of new strains, and specifying initial conditions
sim_name
Required
Name of the configuration file to be generated. Generally based on the type of simulation
setup_name
Optional (SMH)
Type of run - a Scenario Modeling Hub ("SMH") or Forecasting Hub ("FCH") Simulation.
disease
Optional (covid19)
Pathogen or disease being simulated
smh_round
Optional (NA)
Round number for Scenario Modeling Hub Submission
data_path
Optional (data)
Folder path which contains where population data (size, mobility, etc) and ground truth data files are stored
model_output_dir_name
Optional (model_output)
Folder path where the outputs of the simulated model is stored
sim_start_date
Required
Start date for model simulation
sim_end_date
Required
End date for model simulation
start_date_groundtruth
Optional (NA)
Start date for fitting data for inference runs
end_date_groundtruth
Optional (NA)
End date for fitting data for inference runs
nslots
Required
number of independent simulations to run
using Docker container
Spin up an Ubuntu submission box if not already running. To do this, log onto AWS Console and start the EC2 instance.
Update IP address in .ssh/config file. To do this, open a terminal and type the command below. This will open your config file where you can change the IP to the IP4 assigned to the AWS EC2 instance (see AWS Console for this):
SSH into the box. In the terminal, SSH into your box. Typically we name these instances "staging", so usually the command is:
Now you should be logged onto the AWS submission box. If you haven't yet, set up your directory structure.
Type the following commands:
Note that the repository is cloned nested, i.e the flepiMoP
repository is INSIDE the data repository.
Have your Github ssh key passphrase handy so you can paste it when prompted (possibly multiple times) with the git pull command. Alternatively, you can add your github key to your batch box so you don't have to enter your token 6 times per day.
Start up and log into the docker container, and run setup scripts to setup the environment. This setup code links the docker directories to the existing directories on your box. As this is the case, you should not run job submission simultaneously using this setup, as one job submission might modify the data for another job submission.
To set up the environment for your run, run the following commands. These are specific to your run, i.e., change VALIDATION_DATE
, FLEPI_RUN_INDEX
and RESUME_LOCATION
as required. If submitting multiple jobs, it is recommended to split jobs between 2 queues: Compartment-JQ-1588569569
and Compartment-JQ-1588569574
.
NOTE: If you are not running a resume run, DO NOT export the environmental variable RESUME_LOCATION
.
Additionally, if you want to profile how the model is using your memory resources during the run, run the following commands
Then prepare the pipeline directory (if you have already done that and the pipeline hasn't been updated (git pull
says it's up to date). You need to set $DATA_PATH to your data folder. For a COVID-19 run, do:
for Flu do:
Now for any type of run:
For now, just in case: update the arrow
package from 8.0.0 in the docker to 11.0.3 ;
Now flepiMoP is ready 🎉 ;
Do some clean-up before your run. The fast way is to restore the $DATA_PATH
git repository to its blank states (⚠️ removes everything that does not come from git):
Then run the preparatory data building scripts and you are good
Now you may want to test that it works :
If this fails, you may want to investigate this error. In case this succeeds, then you can proceed by first deleting the model_output:
Assuming that the initial test simulation finishes successfully, you will now enter credentials and submit your job onto AWS batch. Enter the following command into the terminal:
You will be prompted to enter the following items. These can be found in a file you received from Shaun called new_user_credentials.csv
.
Access key ID when prompted
Secret access key when prompted
Default region name: us-west-2
Default output: Leave blank when this is prompted and press enter (The Access Key ID and Secret Access Key will be given to you once in a file)
Now you're fully set to go 🎉
To launch the whole inference batch job, type the following command:
This command infers everything from you environment variables, if there is a resume or not, what is the run_id, etc., and the default is to carry seeding if it is a resume (see below for alternative options).
If you'd like to have more control, you can specify the arguments manually:
We allow for a number of different jobs, with different setups, e.g., you may not want to carry seeding. Some examples of appropriate setups are given below. No modification of these code chunks should be required ;
NOTE: Resume and Continuation Resume runs are currently submitted the same way, resuming from an S3 that was generated manually. Typically we will also submit any Continuation Resume run specifying
--resume-carry-seeding
as starting seeding conditions will be manually constructed and put in the S3.
Carrying seeding (do this to use seeding fits from resumed run):
Discarding seeding (do this to refit seeding again):
Single Iteration + Carry seeding (do this to produce additional scenarios where no fitting is required):
After the job is successfully submitted, you will now be in a new branch of the data repo. Commit the ground truth data files to the branch on github and then return to the main branch:
Send the submission information to slack so we can identify the job later. Example output:
Instructions to get started with using gempyor and flepiMoP, using some provided example configs to help you.
Follow all the steps in the Before any run section to ensure you have access to the correct files needed to run your custom model or a sample model with flepiMoP.
Take note of the location of the directory on your local computer where you cloned the flepiMoP model code (which we'll call FLEPI_PATH
), as well as where you cloned your project files (which we'll call PROJECT_PATH
).
For example, if you cloned your Github repositories into a local folder called Github
and are using flepimop_sample as a project repository, your directory names could be
On Mac:
/Users/YourName/Github/flepiMoP
/Users/YourName/Github/flepimop_sample On Windows: C:\Users\YourName\Github\flepiMoP
C:\Users\YourName\Github\flepimop_sample
Since you'll be navigating frequently between the folder that contains your project code and the folder that contains the core flepiMoP model code, it's helpful to define shortcuts for these file paths. You can do this by creating environmental variables that you can then quickly call instead of writing out the whole file path.
If you're on a Mac or Linux/Unix based operating system, define the FLEPI_PATH and PROJECT_PATH environmental variables to be your directory locations, for example
or, if you have already navigated to your parent directory
You can check that the variables have been set by either typing env
to see all defined environmental variables, or typing echo $FLEPI_PATH
to see the value of FLEPI_PATH
.
If you're on a Windows machine
or, if you have already navigated to your parent directory
You can check that the variables have been set by either typing set
to see all defined environmental variables, or typing echo $FLEPI_PATH$
to see the value of FLEPI_PATH
.
If you don't want to bother defining the environmental variables, it's no problem, just remember to use the full or relative path names for navigating to the right files or folders in future steps
The code is written in a combination of R and Python. The Python part of the model is a package called gempyor, and includes all the code to simulate the epidemic model and the observational model and apply time-dependent interventions. The R component conducts the (optional) parameter inference, and all the (optional) provided pre and post processing scripts are also written in R. Most uses of the code require interacting with components written in both languages, and thus making sure that both are installed along with a set of required packages. However, Python alone can be used to do forward simulations of the model using gempyor.
First, ensure you have python and R installed. You need a working python3.7+ installation. We recommend using the latest stable python release (python 3.12) to benefit from huge speed-ups and future-proof your installation. We also recommend installing Rstudio to interact with the R code and for exploring your model outputs.
On Mac 🍏
Python 3 is installed by default on recent MacOS installation. If it is not, you might want to check homebrew and install the appropriate installation.
However, this may result in two versions of Python being installed on your computer. If there are multiple versions of Python (e.g., multiple versions of Python 3), you may need to specify which version to use in the installation. This can be done by following the instructions for using a conda environment, in which case the version of Python to use can be specified in the creation of the virtual environment, e.g., conda create -c conda-forge -n flepimop-env python=3.12 numba pandas numpy seaborn tqdm matplotlib click confuse pyarrow sympy dask pytest scipy graphviz emcee xarray boto3 slack_sdk
. The conda environment will be activated in the same way and when installing gempyor, the version of pip used in the installation will reflect the Python version used in the conda environment (e.g., 3.12), so you can use pip install -e flepimop/gempyor_pkg/
in this case.
There is also the possibility that multiple versions of gempyor have been installed on your computer in the various iterations of Python. You will only want to have gempyor installed on the latest version of Python (e.g., Python 3.8+) that you have. You can remove a gempyor iteration installed for a given version of Python using pip[version] uninstall gempyor
e.g., pip3.7 uninstall gempyor
. Then, you will need to specify which version of Python to install gempyor on during that step (see above).
To install the python portions of the code (gempyor ) and all the necessary dependencies, go to the flepiMoP directory and run the installation, using the following commands:
A warning for Windows
Once gempyor is successfully installed locally, you will need to make sure the executable file gempyor-seir.exe
is runnable via command line. To do this, you will need to add the directory where it was created to PATH. Follow the instructions here to add the directory where this .exe file is located to PATH. This can be done via GUI or CLI.
If you would like to install gempyor directly from GitHub, go to the flepiMoP directory and use the following command:
If you just want to run a forward simulation, installing python's gempyor is all you need.
To run an inference run and to explore your model outputs using provided post-processing functionality, there are some packages you'll need to install in R. Open your R terminal (at the bottom of RStudio, or in the R IDE), and run the following command to install the necessary R packages:
On Linux
The R packages "sf"
and "ggraph"
require you to have libgdal-dev
and libopenblas-dev
installed on your local linux machine.
This step does not need to be repeated unless you use a new computer or delete and reinstall R.
Now return to your system terminal. To install flepiMop-internal R packages, run the following from command line:
After installing the flepiMoP R packages, we need to do one more step to install the command line tools for the inference package. If you are not running in a conda environment, you need to point this installation step to a location that is on your executable search path (i.e., whenever you call a command from the terminal, the places that are searched to find that executable). To find a consistent location, type
The location that is returned will be of the form EXECUTABLE_SEARCH_PATH/gempyor-simulate
. Then run the following in an R terminal:
To install the inference package's CLI tools.
Each installation step may take a few minutes to run.
Note: These installations take place on your local operating system. You will need an active internet connection for installation, but not for other steps of running the model. If you are concerned about disrupting your base environment that you use for other projects, try using Docker or conda instead.
Everything is now ready 🎉 .
The next step depends on what sort of simulation you want to run: One that includes inference (fitting model to data) or only a forward simulation (non-inference). Inference is run from R, while forward-only simulations are run directly from the Python package gempyor
.
First, navigate to the project folder and make sure to delete any old model output files that are there.
For the following examples we use an example config from flepimop_sample, but you can provide the name of any configuration file you want.
To get started, let's start with just running a forward simulation (non-inference).
Stay in the PROJECT_PATH
folder, and run a simulation directly from forward-simulation Python package gempyor. Call gempyor-simulate
providing the name of the configuration file you want to run. For example here, we use config_sample_2pop.yml
from flepimop_sample.
This will produce a model_output
folder, which you can look using provided post-processing functions and scripts.
We recommend using model_output_notebook.Rmd
from flepimop_sample as a starting point to interact with your model outputs. First, modify the yaml preamble in the notebook, then knit this markdown. This will produce some nice plots of the prevalence of infection states over time. You can edit this markdown to produce any figures you'd like to explore your model output.
The first time you run all this, it's , it's better to run each command individually as described above to be sure each exits successfully. However, eventually you can put all these steps together in a script, like below
Note that you only have to re-run the installation steps once each time you update any of the files in the flepimop repository (either by pulling changes made by the developers and stored on Github, or by changing them yourself). If you're just running the same or different configuration file, just repeat the final steps
An inference run requires a configuration file that has the inference
section. Stay in the $PROJECT_PATH
folder, and run the inference script, providing the name of the configuration file you want to run. For example here, we use config_sample_2pop_inference.yml
from flepimop_sample.
This will run the model and create a lot of output files in $PROJECT_PATH/model_output/
.
The last few lines visible on the command prompt should be:
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
NULL
If you want to quickly do runs with options different from those encoded in the configuration file, you can do that from the command line, for example
where:
n
is the number of parallel inference slots,
j
is the number of CPU cores to use on your machine (if j
> n
, only n
cores will actually be used. If j
<n
, some cores will run multiple slots in sequence)
k
is the number of iterations per slots.
Again, it is helpful to run the model output notebook (model_output_notebook.Rmd
from flepimop_sample) to explore your model outputs. Knitting this file for an inference run will also provide an analysis of your fits: the acceptance probabilities, likelihoods overtime, and the fits against the provided ground truth.
The first time you run all this, it's , it's better to run each command individually as described above to be sure each exits successfully. However, eventually you can put all these steps together in a script, like below
Note that you only have to re-run the installation steps once each time you update any of the files in the flepimop repository (either by pulling changes made by the developers and stored on Github, or by changing them yourself). If you're just running the same or different configuration file, just repeat the final steps
If your run is successful, you should see your output files in the model_output folder. The structure of the files in this folder is described in the Model Output section. By default, all the output files are .parquet format (a compressed format which can be imported as dataframes using R's arrow package arrow::read_parquet
or using the free desktop application Tad for quick viewing). However, you can add the option --write-csv
to the end of the commands to run the code (e.g., > gempyor-simulate -c config.yml --write-csv)
to have everything saved as .csv files instead ;
These configs and notebooks should be a good starting point for getting started with flepiMoP. To explore other running options, see How to run: Advanced.
How to plug-in your code/data directly into flepiMoP
Sometimes, the default modules, such as seeding, or initial condition, do not provide the desired functionality. Thankfully, it is possible to replace a gempyor module with your own code, using plug-ins. This works only for initial conditions and seeding at the moment, reach out to us if you are interested in having it works on parameters, modifiers, ...
Here is an example, to set a random initial condition, where each subpopulation a random proportion of individuals is infected. For this, simply set the method
of a block to plugin
and provide the path of your file.
This file contains a class that inherits from a gempyor class, which means that everything already defined in gempyor is available but you can overwrite any single method. Here, we will rewrite the load and draw methods of the initial conditions methods
You can use any code within these functions, as long as the return object has the shape and type that gempyor expect (and that is undocumented and still subject to change, but as you see in this case gempyor except an array (a matrix) of shape: number of compartments X number of subpopulations). You can e.g call bash functions or excute R scripts such as below
Tutorial on how to install and run flepiMoP on a supported HPC with slurm.
These details cover how to install and initialize flepiMoP
on an HPC environment and submit a job with slurm.
Currently only JHU's Rockfish and UNC's Longleaf HPC clusters are supported. If you need support for a new HPC cluster please file an issue in the flepiMoP
GitHub repository.
flepiMoP
This task needs to be ran once to do the initial install of flepiMoP
.
On JHU's Rockfish you'll need to run these steps in a slurm interactive job. This can be launched with /data/apps/helpers/interact -n 4 -m 12GB -t 4:00:00
, but please consult the Rockfish user guide for up to date information.
Obtain a temporary clone of the flepiMoP
repository. The install script will place a permanent clone in the correct location once ran. You may need to take necessary steps to setup git on the HPC cluster being used first before running this step.
Run the hpc_install_or_update.sh
script, substituting <cluster-name>
with either rockfish
or longleaf
. This script will prompt the user asking for the location to place the flepiMoP
clone and the name of the conda environment that it will create. If this is your first time using this script accepting the defaults is the quickest way to get started. Also, expect this script to take a while the first time that you run it.
Remove the temporary clone of the flepiMoP
repository created before. This step is not required, but does help alleviate confusion later.
flepiMoP
Updating flepiMoP
is designed to work just the same as installing flepiMoP
. Make sure that your clone of the flepiMoP
repository is set to the branch your working with (if doing development or operations work) and then run the hpc_install_or_update.sh
script, substituting <cluster-name>
with either rockfish
or longleaf
.
flepiMoP
EnvironmentThese steps to initialize the environment need to run on a per run or as needed basis.
Change directory to where a full clone of the flepiMoP
repository was placed (it will state the location in the output of the script above). And then run the hpc_init.sh
script, substituting <cluster-name>
with either rockfish
or longleaf
. This script will assume the same defaults as the script before for where the flepiMoP
clone is and the name of the conda environment. This script will also ask about a project directory and config, if this is your first time initializing flepiMoP
it might be helpful to clone the flepimop_sample
GitHub repository to the same directory to use as a test.
Upon completing this script it will output a sample set of commands to run to quickly test if the installation/initialization has gone okay.
When an inference batch job is launched, a few post processing scripts are called to run automatically postprocessing-scripts.sh.
You can manually change what you want to run by editing this script.
A batch job can can be submitted after this by running the following:
This launches a batch job to your HPC, with each slot on a separate node. This command attempts to infer the required arguments from your environment variables (i.e. if there is a resume or not, what is the run_id, etc.). The part after the "2" makes sure this file output is redirected to a script for logging, but has no impact on your submission.
If you'd like to have more control, you can specify the arguments manually:
More detailed arguments and advanced usage of the inference_job_launcher.py
script please refer to the --help
.
After the job is successfully submitted, you will now be in a new branch of the project repository. For documentation purposes, we recommend committing the ground truth data files to the branch on GitHub substituting <your-commit-message>
with a description of the contents:
During an inference batch run, log files will show the progress of each array/slot. These log files will show up in your project directory and have the file name structure:
To view these as they are being written, type:
or your file viewing command of choice. Other commands that are helpful for monitoring the status of your runs (note that <Job ID>
here is the SLURM job ID, not the JOB_NAME
set by flepiMoP):
squeue -u $USER
Displays the names and statuses of all jobs submitted by the user. Job status might be: R: running, P: pending.
seff <Job ID>
Displays information related to the efficiency of resource usage by the job
sacct
Displays accounting data for all jobs and job steps
scancel <Job ID>
This cancels a job. If you want to cancel/kill all jobs submitted by a user, you can type scancel -u $USER
Often you'll need to move files back and forth between your HPC and your local computer. To do this, your HPC might suggest Filezilla or Globus file manager. You can also use commands scp
or rsync
(check what works for your HPC).
If your system is approaching a file number quota, you can find subfolders that contain a large number of files by typing:
Type the following line so git remembers your credential and you don't have to enter your token 6 times per day:
We use ntfy.sh for notification. Install ntfy on your Iphone or Android device. Then subscribe to the channel ntfy.sh/flepimop_alerts
where you'll receive notifications when runs are done.
End of job notifications goes as urgent priority.
Within included example postprocessing scripts, we include a helper script that sends a slack message with some output snapshots of our model output. So our 🤖-friend can send us some notifications once a run is done.
If you are using the Delph Epidata API, first register for a key. Once you have a key, add that below where you see [YOUR API KEY]. Alternatively, you can put that key in your config file in the inference
section as gt_api_key: "YOUR API KEY"
.
TODO: add how to run test, and everything
Don't paste them if you don't know what they do
in configs with a setup name: USA
where, eg:
the index is 1
the run_id is 2021.12.14.23:56:12.CET
the prefix is USA/inference/med/2021.12.14.23:56:12.CET/global/intermediate/000000001.
where:
is slots
is core
is iteration per slot
because a big file get changed and added automatically. Since Git 2.13 (Q2 2017), you can stash individual files, with git stash push. One of these should work.
The python code will call your R scripts, setting some variable in the environment:
from_python
: truthy boolean, test for this to know if your code is run automatically.
ti_str, tf_str
model start and end as a string
foldername
the folder that contains everything related to the setup. You'll have to load geodata.csv
from there. It include the /
at the end.
The code is run from the root folder of the repository.
A setup has a name
, and this name
is a also folder that contains file geodata.csv
(see below).
(and status if the current R
implementation respect the specification)
From R: dataframe named mobility
with columns: from, to, amount
. Relationships not specified will be set to zero. You can set different value for A -> B and B -> A (if you only specified A -> B, we'll assume B -> A = 0).
From file: matrix to be imported with numpy as it is. Dimension: (nnodes, nnnodes)
(may have a third dimension if time varying). First index is from, second is to, diagonal is zero (mobility[ori, dest]
)
From python: numpy matrix as file.
From file: geodata.csv : specification of the spatial nodes, with at least column for the zero based index, the geoid or name, the population.
From R: dataframe named importation
with column date, to, amount
where date is a string, to
contains a geoid and amount contains an integer.
Different R scripts define the Nonpharmaceutical Intervention (NPI) to apply in the simulation. Based on the following system arguments, an R script will be called that generates the appropriate intervention. The start and end dates for each NPI needs to be specified (YYYY-MM-DD).
None: No intervention, R0 reduction is 0
SchoolClosure: School closure, counties randomly assigned an R0 reduction ranging from 16-30% (Jackson, M. et al., medRxiv, 2020)
Influenza1918: Influenza social distancing as observed in 1918 Influenza. Counties are randomly assigned an R reduction value ranging from 44-65% (the most intense social distancing R0 reduction values from Milwaukee) (Bootsma & Ferguson, PNAS, 2007)
Wuhan: Counties randomly assigned an R0 reduction based on values reported in Wuhan before and after travel ban during COVID-19 outbreak (R0 reduction of 81-88%) (Zhang, B., Zhou, H., & Zhou F. medRxiv, 2020; Mizumoto, R., Kagaya, K., & Chowell, G., medRxiv, 2020)
TestIsolate: This intervention represents rapid testing and isolation of cases, similar to what was done in Wuhan at the beginning of the outbreak. It reduces R0 by 45-96%.
Mild: This intervention has two sequential interventions: School closures, followed by a period of Wuhan-style lockdown followed by nothing.
Mid: This intervention has three sequential interventions: School closures, followed by a period of Wuhan-style lockdown, followed by social distancing practices used during the 1918 Influenza pandemic
Severe: This intervention has three sequential interventions: School closures, followed by a Wuhan-style lockdown, followed by rapid testing and isolation.
All the little things to save you time on the clusters
model_output/
(or any big folder) is too long on the clusterYes, it takes ages because IO can be so slow, and there are many small files. If you are in a hurry, you can do
The first command rename/move model_output
, it is instantaneous. You can now re-run something. To delete the renamed folder, run the second command. the &
at the end makes it execute in the background.
seff
to analyze a jobAfter a job has run (either to completion or got terminated/fail), you may run:
to know how much ressources your job used in your node, what was the cause for termination and so on. If you don't remember the JOB_ID
, look for the number in the filename of the slurm log (slurm_{JOB_ID}.out
).
Short internal tutorial on running locally using a "Docker" container.
There are more comprehensive directions in the How to run -> Running with Docker locally section, but this section has some specifics required to do US-specific, COVID-19 and flu-specific runs
Run Docker Image
Current Docker image: /hopkinsidd/flepimop:latest-dev
Docker is a software platform that allows you to build, test, and deploy applications quickly. Docker packages software into standardized units called containers that have everything the software needs to run including libraries, system tools, code, and runtime. This means you can run and install software without installing the dependencies in the system.
A docker container is an environment which is isolated from the rest of the operating system i.e. you can create files, programs, delete and everything but that will not affect your OS. It is a local virtual OS within your OS ;
For flepiMoP, we have a docker container that will help you get running quickly ;
In this command we run the docker image hopkinsidd/flepimop
. The -v
command is used to allocate space from Docker and mount it at the given location ;
This mounts the data folder <dir1>
to a path called drp
within the docker environment, and the COVIDScenarioPipeline <dir2>
in flepimop
;
First, populate the folder name variables:
Then, export variables for some flags and the census API key (you can use your own):
Go into the Pipeline repo (making sure it is up to date on your favorite branch) and do the installation required of the repository:
Note: These installations take place in the docker container and not the Operating System. They must be made once while starting the container and need not be done for every time you are running tests, provided they have been installed once.
Everything is now ready. 🎉 Let's do some clean-up in the data folder (these files might not exist, but it's good practice to make sure your simulation isn't re-using some old files) ;
Stay in $DATA_PATH
, select a config, and build the setup. The setup creates the population seeding file (geodata) and the population mobility file (mobility). Then, run inference:
where:
n
is the number of parallel inference slots,
j
is the number of CPU cores it'll use in your machine,
k
is the number of iterations per slots.
It should run successfully and create a lot of files in model_output/
;
The last few lines visible on the command prompt should be:
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
NULL
Other helpful tools
To understand the basics of docker refer to the following: Docker Basics
To install docker for windows refer to the following link: Installing Docker
The following is a good tutorial for introduction to docker: Docker Tutorial
To run the entire pipeline we use the command prompt. To open the command prompt type “Command Prompt" in the search bar and open the command prompt. Here is a tutorial video for navigating through the command prompt: Command Prompt Tutorial
To test, we use the test folder (test_documentation_inference_us in this case) in the CovidScenariPipeline as the data repository folder. We run the docker container and set the paths.
All are welcome to contribute to flepiMoP! The easiest way is to open an issue on GitHub if you encounter a bug or if you have an issue with the framework. We would be very happy to help you out.
If you want to contribute code, fork the flepiMoP repository, modify it, and submit your Pull Request (PR). In order to be merged, a pull request need:
the approval of two reviewers AND
the continuous integration (CI) tests passing.
The "heart" of the pipeline, gempyor, is written in Python taking advantage of just-in-time compilation (via numba
) and existing optimized libraries (numpy
, pandas
). If you would like to help us build gempyor, here is some useful information.
We make extensive use of the following packages:
click for managing the command-line arguments
confuse for accessing the configuration file
numba to just-in-time compile the core model
sympy to parse the model equations
pyarrow as parquet is our main data storage format
xarray, which provides labels in the form of dimensions, coordinates and attributes on top of raw NumPy multidimensional arrays, for performance and convenience ;
emcee for inference, as an option
graphviz to export transition graph between compartments
pandas, numpy, scipy, seaborn, matplotlib and tqdm like many Python projects
One of the current focus is to switch internal data types from dataframes and numpy array to xarrays!
To run the tests suite locally, you'll need to install the gempyor package with build dependencies:
which installs the pytest
and mock
packages in addition to all other gempyor dependencies so that one can run tests.
If you are running from a conda environment and installing with `--no-deps`, then you should make sure that these two packages are installed.
Now you can try to run the gempyor test suite by running, from the flepimop/gempyor_pkg
folder:
If that works, then you are ready to develop gempyor. Feel free to open your first pull request.
If you want more output on tests, e.g capturing standard output (print), you can use:
and to run just some subset of the tests (e.g here just the outcome tests), use:
For more details on how to use pytest
please refer to their usage guide.
We try to remain close to Python conventions and to follow the updated rules and best practices. For formatting, we use black, the Uncompromising Code Formatter before submitting pull requests. It provides a consistent style, which is useful when diffing. To get started with black please refer to their Getting Started guide. We use a custom length of 92 characters as the baseline is short for scientific code. Here is the line to use to format your code:
For those using a Mac or Linux system for development this command is also available for use by calling ./bin/lint
. Similarly, you can take advantage of the formatting pre-commit hook found at bin/pre-commit
. To start using it copy this file to your git hooks folder:
The code is structured so that each of the main classes owns a config segment, and only this class should parse and build the related object. To access this information, other classes first need to build the object.
Below, this page is still underconstruction
The main classes are:
Coordinates:
this is a light class that stores all the coordinates needed by every other class (e.g the time serie
Parameter
Compartments
Modifers
Seeding
,
InitialConditions
a writeDF
function to plot
(TODO: detail pipeline internal API)
Here are some notes useful to improve the batch submission:
Setup site wide Rprofile.
SLURM copies your environment variables by default. You don't need to tell it to set a variable on the command line for sbatch. Just set the variable in your environment before calling sbatch.
There are two useful environment variables that SLURM sets up when you use job arrays:
SLURM_ARRAY_JOB_ID, specifies the array's master job ID number. SLURM_ARRAY_TASK_ID, specifies the job array index number. https://help.rc.ufl.edu/doc/Using_Variables_in_SLURM_Jobs
SLURM does not support using variables in the #SBATCH lines within a job script (for example, #SBATCH -N=$REPS will NOT work). A very limited number of variables are available in the #SBATCH just as %j for JOB ID. However, values passed from the command line have precedence over values defined in the job script. and you could use variables in the command line. For example, you could set the job name and output/error files can be passed on the sbatch command line:
However note in this example, the output file doesn't have the job ID which is not available from the command line, only inside the sbatch shell script.
launch_job.py and runner.py for non inference job
inference_job.py launch a slurm or aws job, where it uses
`inference_runner.sh` and inference_copy.sh for aws
;batch/inference_job.run for slurm
This page, along with the other AWS run guides, are not deprecated in case we need to run flepiMoP
on AWS again in the future, but also are not maintained as other platforms (such as longleaf and rockfish) are preferred for running production jobs.
As a computational environment, you can use an RStudio Server integrated AWS EC2 instance for either your personal space or shared usages among multiple users, via GUI as well as CLI using ssh. The EC2 instance-type was selected to be appropriate one for running programs as of now (2023/1), in views of both computational resources and finances, so that you can use a cloud-based computing environment which you can access with GUI including from Web, without any difficulties to set it up. The details hereinafter may be able to change.
The current installed versions of software or additional information related to AWS EC2 are as follows:
R/RStudio Server
R version: 4.2.2
RStudio Server version: v2022.07.02+576
AWS EC2 instance configurations
instance-type: r6i.4xlarge (16 cores, 128GB mem ;
Storage: 2TB x 1 (gp3)
OS: ubuntu 22.04 (Jammy)
To be written/ Talk to someone who would be able to do that.
EC2 instance initialization with specfic AMI
Configured network related including ports openings
registration of the user in the EC2 instance
Configuring shared directory via SMB and accoun ;
The procedure is same as a normal ec2 instance starting. One way is to select the ec2 instance and start it in EC2 Management Console ;
Once the instance started, RStudio Server can be accessed without invoking manually ;
By default RStudio Server runs on port 8787 and accepts connections from all remote clients. After invoking an EC2 box you should therefore be able to navigate a web browser to the following address to access the server:
http://<ip-addr>:8787/
Then the authentication dialog will be shown, try to log in by inputting your username and password which are already registered in the box and pushing the "Sign In " button:
RStudio view can be appeared as below:
To access the linux server with GUI, RDP software can be applicable, in addition to the usual way, via ssh with command line.
By using "Remote Desktop Connection" app in Windows, you can log in to the Linux server box from remote environment.
For Mac users, the below RDP software is recommented:
As a shared space, the directory named:
is deployed among multiple server boxes using EFS(Elastic File System) which covers NFSv4 protocol. ;
In the linux box, Samba(SMB) service has been on for file exchanging by default. The area in which can be readable and writable under the specific user privileages is:
When accessing the area via SMB, you can input username and its password in a dialog window which will be shown. The username is:
(ask password for above user in advance, if you want to access via SMB)
By inputting the form such as \\<ip-addr>\share
in Windows Explorer
From Finder you can access the shared space using SMB.
From Finder Menu, choose "MOVE" then "Connect to Server"
When a dialog appears, fill username and password out as a registered user ;
After pushing "connect" button, the designated area will be shown in Finder if no errors happen ;
When you are inside of the university networks, e.g. in labs or in office, you will not access to the server box with SMB because the networks may be blocking the ports related to the services.
If you are using MAC as a local pc, there is a workaround to avoid the situation but for Windows it has not been clear there is a solution (now under investigation). If you want to know the related information, currently even for Mac user only though, please try to make a contact. In case of a Windows user, I recommend using "Local devices and resources" setting of Remote Desktop Connection.\
For running the model locally, especially for testing, non-inference runs, and short chains, we provide a guide for setting up and running in a conda environment, and provide a Docker container for use. A Docker container is an environment which is isolated from the rest of the operating system i.e. you can create files, programs, delete and everything but that will not affect your OS. It is a local virtual OS within your OS. We recommend Docker for users who are not familiar with setting up environments and seek a containerized environment to quickly launch jobs ;
For longer inference runs across multiple slots, we provide instructions and scripts for two methods to launch on SLURM HPC and on AWS using Docker. These methods are best for launching large jobs (long inference chains, multi-core and computationally expensive model runs), but not the best methods for debugging model setups.
Short tutorial on running locally using an "Anaconda" environment.
As is the case for any run, first see the Before any run section to ensure you have access to the correct files needed to run. On your local machine, determine the file paths to:
the directory containing the flepimop code (likely the folder you cloned from Github), which we'll call FLEPI_PATH
the directory containing your project code including input configuration file and population structure (again likely from Github), which we'll call DATA_PATH
For example, if you clone your Github repositories into a local folder called Github and are using the flepimop_sample as a project repository, your directory names could be On Mac:
<dir1> = /Users/YourName/Github/flepiMoP
<dir2> = /Users/YourName/Github/flepimop_sample On Windows: <dir1> = C:\Users\YourName\Github\flepiMoP
<dir2> = C:\Users\YourName\Github\flepimop_sample\
(hint: if you navigate to a directory like C:\Users\YourName\Github
using cd C:\Users\YourName\Github
, modify the above <dir1>
paths to be .\flepiMoP
and .\flepimop_sample)
Note again that these are best cloned flat.
conda
environmentOne of simplest ways to get everything to work is to build an Anaconda environment. Install (or update) Anaconda on your computer. We find that it is easiest to create your conda environment by installing required python packages, then installing R packages separately once your conda environment has been built as not all R packages can be found on conda.
You can either use the command line (here) or the graphical user interface (you just tick the packages you want). With the command line it's this one-liner:
Anaconda will take some time, to come up with a proposal that works with all dependencies. This creates a conda
environment named flepimop-env
that has all the necessary python packages.
The next step in preparing your environment is to install the necessary R packages. First, activate your environment, launch R and then install the following packages.
If you'd like, you can install rstudio
as a package as well.
Activate your conda environment, which we built above.
In this conda
environment, commands with R and python will uses this environment's R and python.
First, you'll need to fill in some variables that are used by the model. This can be done in a script (an example is provided at the end of this page). For your first time, it's better to run each command individually to be sure it exits successfully.
First, in myparentfolder
populate the folder name variables for the paths to the flepimop code folder and the project folder:
Go into the code directory (making sure it is up to date on your favorite branch) and do the installation required of the repository:
Each installation step may take a few minutes to run.
Note: These installations take place in your conda environment and not the local operating system. They must be made once while in your environment and need not be done for every time you run a model, provided they have been installed once. You will need an active internet connection for installing the R packages (since some are hosted online), but not for other steps of running the model.
Other environmental variables can be set at any point in process of setting up your model run. These options are listed in ... ADD ENVAR PAGE
For example, some frequently used environmental variables which we recommend setting are:
Everything is now ready. 🎉
The next step depends on what sort of simulation you want to run: One that includes inference (fitting model to data) or only a forward simulation (non-inference). Inference is run from R, while forward-only simulations are run directly from the Python package gempyor
.
In either case, navigate to the project folder and make sure to delete any old model output files that are there.
An inference run requires a configuration file that has an inference
section. Stay in the $DATA_PATH
folder, and run the inference script, providing the name of the configuration file you want to run (ex. config.yml
). In the example data folder (flepimop_sample), try out the example config XXX.
This will run the model and create a lot of output files in $DATA_PATH/model_output/
.
The last few lines visible on the command prompt should be:
[[1]]
[[1]][[1]]
[[1]][[1]][[1]]
NULL
If you want to quickly do runs with options different from those encoded in the configuration file, you can do that from the command line, for example
where:
n
is the number of parallel inference slots,
j
is the number of CPU cores to use on your machine (if j
> n
, only n
cores will actually be used. If j
< n
, some cores will run multiple slots in sequence)
k
is the number of iterations per slots.
Stay in the $DATA_PATH
folder, and run a simulation directly from forward-simulation Python package gempyor
. To do this, call gempyor-simulate
providing the name of the configuration file you want to run (ex. config.yml
). An example config is provided in flepimop_sample/config_sample_2pop_interventions.yml.
It is currently required that all configuration files have an interventions
section. There is currently no way to simulate a model with no interventions, though this functionality is expected soon. For now, simply create an intervention that has value zero.
You can also try to knit the Rmd file in flepiMoP/flepimop/gempyor_pkg/docs
which will show you how to analyze these files.
The following script does all the above commands in an easy script. Save it in myparentfolder
as quick_setup.sh
. Then, just go to myparentfolder
and type source quick_setup_flu.sh
and it'll do everything for you!
This page, along with the other AWS run guides, are not deprecated in case we need to run flepiMoP
on AWS again in the future, but also are not maintained as other platforms (such as longleaf and rockfish) are preferred for running production jobs.
see Building a configuration file
Spin up an Ubuntu submission box if not already running. To do this, log onto AWS Console and start the EC2 instance.
Update IP address in .ssh/config file. To do this, open a terminal and type the command below. This will open your config file where you can change the IP to the IP4 assigned to the AWS EC2 instance (see AWS Console for this):
SSH into the box. In the terminal, SSH into your box. Typically we name these instances "staging", so usually the command is:
Now you should be logged onto the AWS submission box.
Update the github repositories. In the below example we assume you are running main
branch in Flu_USA andmain
branch in COVIDScenarioPipeline. This assumes you have already loaded the appropriate repositories on your EC2 instance. Have your Github ssh key passphrase handy so you can paste it when prompted (possibly multiple times) with the git pull command. Alternatively, you can add your github key to your batch box so you do not have to log in repeated (see X).
Initiate the docker. Start up and log into the docker container, pull the repos from Github, and run setup scripts to setup the environment. This setup code links the docker directories to the existing directories on your box. As this is the case, you should not run job submission simultaneously using this setup, as one job submission might modify the data for another job submission.
To run the via AWS, we first run a setup run locally (in docker on the submission EC2 box) ;
Setup environment variables. Modify the code chunk below and submit in the terminal. We also clear certain files and model output that get generated in the submission process. If these files exist in the repo, they may not get cleared and could cause issues. You need to modify the variable values in the first 4 lines below. These include the SCENARIO
, VALIDATION_DATE
, COVID_MAX_STACK_SIZE
, and COMPUTE_QUEUE
. If submitting multiple jobs, it is recommended to split jobs between 2 queues: Compartment-JQ-1588569569
and Compartment-JQ-1588569574
.
If not resuming off previous run:
If resuming from a previous run, there are an additional couple variables to set. This is the same for a regular resume or continuation resume. Specifically:
RESUME_ID
- the COVID_RUN_INDEX
from the run resuming from.
RESUME_S3
- the S3 bucket where this previous run is stored
Preliminary model run. We do a setup run with 1 to 2 iterations to make sure the model runs and setup input data. This takes several minutes to complete, depending on how complex the simulation will be. To do this, run the following code chunk, with no modification of the code required:
Configure AWS. Assuming that the simulations finish successfully, you will now enter credentials and submit your job onto AWS batch. Enter the following command into the terminal ;
You will be prompted to enter the following items. These can be found in a file called new_user_credentials.csv
;
Access key ID when prompted
Secret access key when prompted
Default region name: us-west-2
Default output: Leave blank when this is prompted and press enter (The Access Key ID and Secret Access Key will be given to you once in a file)
Launch the job. To launch the job, use the appropriate setup based on the type of job you are doing. No modification of these code chunks should be required.
NOTE: Resume and Continuation Resume runs are currently submitted the same way, resuming from an S3 that was generated manually. Typically we will also submit any Continuation Resume run specifying
--resume-carry-seeding
as starting seeding conditions will be manually constructed and put in the S3.
Carrying seeding (do this to use seeding fits from resumed run):
Discarding seeding (do this to refit seeding again):
Single Iteration + Carry seeding (do this to produce additional scenarios where no fitting is required):
Commit files to GitHub. After the job is successfully submitted, you will now be in a new branch of the population repo. Commit the ground truth data files to the branch on GitHub and then return to the main branch:
Save submission info to slack. We use a slack channel to save the submission information that gets outputted. Copy this to slack so you can identify the job later. Example output:
This page, along with the other AWS run guides, are not deprecated in case we need to run flepiMoP
on AWS again in the future, but also are not maintained as other platforms (such as longleaf and rockfish) are preferred for running production jobs.
Click on below:
Sign in as IAM user with your given Accound ID, username and Password
Then the next view appears, check "regeon" as "Oregon" by default and "user@Accond ID" as you expeced.
If you have already accessed AWS console, these kinds of view can be seen. In the case select "EC2" to go to "EC2 Dashboard"(if not, skip it).
In this EC2 Dashboard, we can maintain the EC2 boxes from creation to deletion. In this section, how to create an EC2 instance from the AMI image which has already been registered is shown.
Select "Images>AMIs" in the right pane(Navigation pain) ;
Select an AMI name which name is "IDD Staging AMI" in the "Amazon Machine Images (AMIs)" by clicking the responding AMI checkbox on the left, then push the "Launch instance from AMI" button (colored in orange).
To create an EC2 instance, fill out the items as below (example):
Name and tags
input an appropriate name (e.g., "sample_box01")
Application and OS image
check whether "AMI from catalog" is _"IDD Staging AMI" (for example; select one as you want) ;
Instance type
as you selected by drop-down list(e.g., m5.xlarge)
Key pair(login ;
you can generate new key pair if you want to connect to the instance securely (by clicking "Create new key pair" on the right side), but usually select "ams__ks_ED25519__keypair" by drop-down list so that you can be helped when local client setup (recommended).
In case that you use your own key, you will be the only person to log in, of course. you should be careful of handling key management ;
Network settings (push the button "Edit" on the right to extend configuration; see below)
VPC - required
select "HPC VPC" item by drop-down menu
Subnet
select "HPC Public Subnet among _"us-west-2*" ;
Firewall (security groups)
select "Select existing security grous" toggle, then
Common security groups
select "dvc_usa" and "dvc__usa2" by drop-down menu
Advanced details
"EC2S3FullAccess" should be setected in IAM instance profile, but to do it an authentication (IAM role or policy) must be set on to the working IAM account
then push "Launch Instance" button which is located at the bottom right side of the scree ;
or any HPC using the slurm workload manager
Rockfish administrators provided with different properties. For our needs (storage intensive and shared environment), we work in the /scratch4/struelo1/
partition, where we have 20T of space. Our folders are organized as:
code-folder: /scratch4/struelo1/flepimop-code/
where each user has its own subfolder, from where the repos are cloned and the runs are launched. e.g for user chadi, we'll find:
/scratch4/struelo1/flepimop-code/chadi/covidsp/Flu_USA
/scratch4/struelo1/flepimop-code/chadi/COVID19_USA
/scratch4/struelo1/flepimop-code/chadi/flepiMoP
...
(we keep separated repositories by users so that different versions of the pipeline are not mixed where we run several runs in parallel. Don't hesitate to create other subfolders in the code folder (/scratch4/struelo1/flepimop-code/chadi-flusight
, ...) if you need them.
Note that the repository is cloned flat, i.e the flepiMoP
repository is at the same level as the data repository, not inside it!
output folder:/scratch4/struelo1/flepimop-runs
stores the run outputs. After an inference run finishes, it's output and the logs files are copied from the $DATA_PATH/model_output
to /scratch4/struelo1/flepimop-runs/THISRUNJOBNAME
where the jobname is usually of the form USA-DATE.
When logging on you'll see two folders data_struelo1
and scr4_struelo1
, which are shortcuts to /data/struelo1
and /scratch4/struelo1
. We don't use data/struelo1
.
Using ssh from your terminal, type in:
and enter your password when prompted. You'll be into rockfish's login node, which is a remote computer whose only purpose is to prepare and launch computations on so-called compute nodes.
Load the right modules for the setup:
Now, type the following line so git remembers your credential and you don't have to enter your token 6 times per day:
Now you need to create the conda environment. You will create the environment in two shorter commands, installing the python and R stuff separately. This can be extremely long if done in one command, so doing it in two helps. This command is quite long you'll have the time to brew some nice coffee ☕️:
Use the following commands to have git clone the FlepiMoP repository and any other model repositories you'd like to work on through https
. In the code below, $USER is a variable that contains your username.
scp -r <username>@rfdtn1.rockfish.jhu.edu:/home/<username>/.ssh/<key_name.pub> .
Press 'esc' to exit INSERT model followed by ':x' to save and exit the file. By adding this configuration file, you make sure Rockfish doesn't forget your ssh key when you log out. Now clone the github repositories as follows,
and you will not be prompted for credentials.
This can be done in a second step -- but is necessary in order to push and pull data to Amazon Simple Storage Service (S3). Setup AWS by running,
Then run ./aws-cli/bin/aws configure
to set up your credentials,
To get the (secret) access key, ask the AWS administrator (Shaun Truelove) to generate them for you.
log-in to rockfish via ssh, then type:
which will prepare the environment and setup variables for the validation date (choose as day after end_date_groundtruth
), the resume location and the run index for this run. If you don't want to set a variable, just hit enter.
Note that now the run-id of the run we resume from is automatically inferred by the batch script :)
Check that the conda environment is activated: you should see(flepimop-env)
on the left of your command-line prompt.
Then prepare the pipeline directory (if you have already done that and the pipeline hasn't been updated (git pull
says it's up to date) then you can skip these steps
Now flepiMoP is ready 🎉. If the R
command doesn't work, try r
and if that doesn't work run module load
r/4.0.2`.
For a COVID-19 run, do:
for Flu do:
Now for any type of run:
Do some clean-up before your run. The fast way is to restore the $DATA_PATH
git repository to its blank states (⚠️ removes everything that does not come from git):
Run the preparatory script for the data and you are good,
If you want to profile how the model is using your memory resources during the run:
Now you may want to test that it works :
If this fails, you may want to investigate this error. In case this succeeds, then you can proceed by first deleting the model_output:
When an inference batch job is launched, a few post processing scripts are called to run automatically postprocessing-scripts.sh.
You can manually change what you want to run by editing this script.
Now you're fully set to go 🎉
To launch the whole inference batch job, type the following command:
This command infers everything from you environment variables, if there is a resume or not, what is the run_id, etc. The part after the "2" makes sure this file output is redirected to a script for logging, but has no impact on your submission.
If you'd like to have more control, you can specify the arguments manually:
If you want to send any post-processing outputs to #flepibot-test
instead of csp-production
, add the flag --slack-channel debug
Commit files to Github. After the job is successfully submitted, you will now be in a new branch of the data repo. Commit the ground truth data files to the branch on github and then return to the main branch:
but DO NOT finish up by git checking main like the aws instructions, as the run will use data in the current folder.
TODO JPSEH WRITE UP TO HERE
Two types of logfiles: in `$DATA_PATH`: slurm-JOBID_SLOTID.out and and filter_MC logs:
```tail -f /scratch4/struelo1/flepimop-runs/USA-20230130T163847/log_FCH_R16_lowBoo_modVar_ContRes_blk4_Jan29_tsvacc_100.txt
```
When approching the file number quota, type
to find which subfolders contains how many files
Check that the python comes from conda with which python
if some weird package missing errors arrive. Sometime conda magically disappears.
Don't use ipython
as it breaks click's flags
cleanup:
End of job notifications goes as urgent priority.
Check your running jobs:
where job_id has your full array job_id and each slot after the under-score. You can see their status (R: running, P: pending), how long they have been running and soo on.
To cancel a job
To check your code prior to submitting a large batch job, it's often helpful to run an interactive session to debug your code and check everything works as you want. On 🪨🐠 this can be done using interact
like the below line, which requests an interactive session with 4 cores, 24GB of memory, for 12 hours.
Often you'll need to move files back and forth between Rockfish and your local computer. To do this, you can use Open-On-Demand, or any other command line tool.
scp -r <user>@rfdtn1.rockfish.jhu.edu:"<file path of what you want>" <where you want to put it in your local>
These steps are already done an affects all users, but might be interesting in case you'd like to run on another cluster
So our 🤖-friend can send us some notifications once a run is done.
This page, along with the other AWS run guides, are not deprecated in case we need to run flepiMoP
on AWS again in the future, but also are not maintained as other platforms (such as longleaf and rockfish) are preferred for running production jobs.
For large simulations, running the model on a cluster or cloud computing is required. AWS provides a good solution for this, if funding or credits are available (AWS can get very expensive).
This document contains instructions for setting up and running the two different kinds of SEIR modeling jobs supported by the COVIDScenarioPipeline repository on AWS:
Inference jobs, using AWS Batch to coordinate hundreds/thousands of jobs across a fleet of servers, and
Planning jobs, using a single relatively large EC2 instance (usually an r5.24xlarge
) to run one or more planning scenarios on a single high-powered machine.
Most of the steps required to setup and run the two different types of jobs on AWS are identical, and I will explicitly call out the places where different steps are required. Throughout the document, we assume that your client machine is a UNIX-like environment (e.g., OS X, Linux, or WSL).
I need a few things to be true about the local machine that you will be using to connect to AWS that I'll outline here:
You have created and downloaded a .pem
file for connecting to an EC2 instance to your ~/.ssh
directory. When we provision machines, you'll need to use the .pem
file as a secret key for connecting. You may need to change the permission of the .pem file:
You have created a ~/.ssh/config
file that contains an entry that looks like this so we can use staging
as an alias for your provisioned EC2 instance in the rest of the runbook:
You can This is important because we will need to use your Github SSH key to interact with private repositories from the staging
server on EC2.
If you are running an Inference job, you should use a small instance type for your staging server (e.g., an m5.xlarge
will be more than enough.) If you are running a Planning job, you should provision a beefy instance type (I am especially partial to the memory-and-CPU heavy r5.24xlarge
, but given how fast the planning code has become, an r5.8xlarge
should be perfectly adequate.)
If you are having connection timeout issues when trying to ssh into the AWS machine, you should check that you have SSH TCP Port 22 permissions in the dcv_usa
/ security group.
If you do not have access to the jh-covid
account, you should walk through the regular EC2 Launch Wizard flow and be sure to choose the Amazon Linux 2 AMI (HVM), SSD Volume Type (ami-0e34e7b9ca0ace12d
, the 64-bit x86 version) AMI. Once the machine is up and running and you can SSH to it, you will need to run the following code to install the software you will need for the rest of the run:
Once your staging server is provisioned and you can connect to it, you should scp
the private key file that you use for connecting to Github to the /home/ec2-user/.ssh
directory on the staging server (e.g., if the local file is named ~/.ssh/id_rsa
, then you should run scp ~/.ssh/id_rsa staging:/home/ec2-user/.ssh
to do the copy). For convenience, you should create a /home/ec2-user/.ssh/config
file on the staging server that has the following entry:
This way, the git clone
, git pull
, etc. operations that you run on the staging server will use your SSH key without constantly prompting you to login. Be sure to chmod 600 ~/.ssh/config
to give the new file the correct permissions. You should now be able to clone a COVID19 data repository into your home directory on the staging server to do work against. For this example, to use the COVID19_Minimal
repo, run:
to get it onto the staging server. By convention, we do runs with the COVIDScenarioPipeline
repository nested inside of the data repository, so we then do:
to clone the modeling code itself into a child directory of the data repository.
The previous section is only for getting a minimal set of dependencies setup on your staging server. To do an actual run, you will need to download the Docker container that contains the more extensive set of dependencies we need for running the code in the COVIDScenarioPipeline
repository. To get the development container on your staging server, please run:
There are multiple versions of the container published on DockerHub, but latest-dev
contains the latest-and-greatest dependencies and can support both Inference and Planning jobs. In order to launch the container and run a job, we need to make our local COVID19_Minimal
directory visible to the container's runtime. For Inference jobs, we do this by running:
The -v
option to docker run
maps a file in the host filesystem (i.e., the path on the left side of the colon) to a file in the container's filesystem. Here, we are mapping the /home/ec2-user/COVID19_Minimal
directory on the staging server where we checked out our data repo to the /home/app/src
directory in the container (by convention, we run commands inside of the container as a user named app
.) We also map our .ssh
directory from the host filesystem into the container so that we can interact with Github if need be using our SSH keys. Once the container is launched, we can cd src; ls -ltr
to look around and ensure that our directory mapping was successful and we see the data and code files that we are expecting to run with.
Once you are in the src
directory, there are a few final steps required to install the R packages and Python modules contained within the COVIDScenarioPipeline
repository. First, checkout the correct branch of COVIDScenarioPipeline
. Then, assuming that you created a COVIDScenarioPipeline
directory within the data repo in the previous step, you should be able to run:
to install the local R packages and then install the Python modules.
Once this step is complete, your machine is properly provisioned to run Planning jobs using the tools you normally use (e.g., make_makefile.R
or running simulate.py
and hospdeath.R
directly, depending on the situation.) Running Inference jobs requires some extra steps that are covered in the next two sections.
Once the container is setup from the previous step, we are ready to test out and then launch an inference job against a configuration file (I will use the example of config.yml
for the rest of this document.) First, I setup and run the build_US_setup.R
script against my configuration file to ensure that the mobility data is up to date:
Next, I kick off a small local run of the full_filter.R
script. This serves two purposes: first, we can verify that the configuration file is in good shape and can support a few small iterations of the inference calculations before we kick off hundreds/thousands of jobs via AWS Batch. Second, it downloads the case data that we need for inference calculations to the staging server so that it can be cached locally and used by the batch jobs on AWS- if we do not have a local cache of this data at the start of the run, then every job will try to download the data itself, which will force the upstream server to deny service to the worker jobs, which will cause all of the jobs to fail. My small runs usually look like:
This will run two sequential simulations (-k 2
) for a single slot (-n 1
) using a single CPU core (-j 1
), looking for the modeling source code in the COVIDScenarioPipeline
directory (-p COVIDScenarioPipeline
). (We need to use the command line arguments here to explicitly override the settings of these parameters inside of config.yml
since this run is only for local testing.) Assuming that this run succeeds, we are ready to kick off a batch job on the cluster.
The simplest way to launch an inference job is to simply run
This will use the contents of the config file to determine how many slots to run, how many simulations to run for each slot, and how to break those simulations up into blocks of batch jobs that run sequentially. If you need to override any of those settings at the command line, you can run
to see the full list of command line arguments the script takes and how to set them.
One particular type of command line argument cannot be specified in the config: arguments to resume a run from a previously submitted run. This takes two arguments based on the previous run:
Both the s3 bucket and run id are printed as part of the output for the previous submission. We store that information on a slack channel #csp-production, and suggest other groups find similar storage.
which will show you the running status of the jobs in each of the queues.
By default, the AWS Batch system will usually run around 50% of your desired simultaneously executable jobs concurrently for a given inference run. For example, if you are running 300 slots, Batch will generally run about 150 of those 300 tasks at a given time. If you need to force Batch to run more tasks concurrently, this section provides instructions for how to cajole Batch into running harder.
If you want to force new tasks to come online ASAP, you should consider increasing the Minimum CPU for the Compute Environment as well as the Desired CPU (the Desired CPU is not allowed to be lower than the Minimum CPU, so if you increase the Minimum you must increase the Desired as well to match it.) This will cause Batch to spin new containers up quickly and get them populated with running tasks. There are two downsides to doing this: first, it overrides the allocation algorithm that makes cost/performance tradeoff decisions in favor of spending more money in order to get more tasks running. Second, you must remember to update the Compute Environment towards the end of the job run to set the Minimum CPU to zero again so that the ECS cluster can spin down when the job is finished; if you do not do this, ECS will simply leave the machines up and running, wasting money without doing any actual work. (Note that you should never manually try to lower the value of the Desired CPU setting for the Compute Environment- the Batch system will throw an error if you attempt to do this.)
This is just a place to play around with different inference algorithms. Gitbook markdown is very application-specific so can't copy this algorithm text into other apps to play around with!
For
, where is the number of parallel MCMC chains (also known as slots)
Generate initial state
Generate an initial set of parameters , and copy this to both the global () and chimeric () parameter chain (sequence ;
Generate an initial epidemic trajectory
Calculate and record the initial likelihood for each subpopulation, $$\mathcal{L_i}(D_i|Z_i(\Theta_{m,0}))$ ;
For
where is the length of the MCMC chain, add to the sequence of parameter values :
Generate a proposed set of parameters from the current chimeric parameters using the proposal distribution $$g(\Theta^*|\Theta^C_{m,k-1})$ ;
Generate an epidemic trajectory with these proposed parameters,
Calculate the likelihood of the data given the proposed parameters for each subpopulation,
Calculate the overall likelihood with the proposed parameters,
Make "global" decision about proposed parameters
Generate a uniform random number
Calculate the overall likelihood with the current global parameters,
Calculate the acceptance ratio
If
: ACCEPT the proposed parameters to the global and chimeric parameter chains
Set
Set
Update the recorded subpopulation-specific likelihood values (chimeric and global) with the likelihoods calculated using the proposed parameter ;
Else
: REJECT the proposed parameters for the global chain and make subpopulation-specific decisions for the chimeric chain
Set
Make "chimeric" decision:
For
Generate a uniform random number
Calculate the acceptance ratio
If
: ACCEPT the proposed parameters to the chimeric parameter chain for this location
Set
Update the recorded chimeric likelihood value for subpopulation to that calculated with the proposed parameter
Else
: REJECT the proposed parameters for the chimeric parameter chain for this location
Set
`End if ;
End for
subpopulations
End making chimeric decisions
End if
End making global decision
End for
iterations of each MCMC chain
End for
parallel MCMC chains
Collect the final global parameter values for each parallel chain
This page, along with the other AWS run guides, are not deprecated in case we need to run flepiMoP
on AWS again in the future, but also are not maintained as other platforms (such as longleaf and rockfish) are preferred for running production jobs.
see Building a configuration file
Spin up an Ubuntu submission box if not already running. To do this, log onto AWS Console and start the EC2 instance.
Update IP address in .ssh/config file. To do this, open a terminal and type the command below. This will open your config file where you can change the IP to the IP4 assigned to the AWS EC2 instance (see AWS Console for this):
SSH into the box. In the terminal, SSH into your box. Typically we name these instances "staging", so usually the command is:
Now you should be logged onto the AWS submission box.
Update the github repositories. In the below example we assume you are running main
branch in Flu_USA andmain
branch in COVIDScenarioPipeline. This assumes you have already loaded the appropriate repositories on your EC2 instance. Have your GitHub ssh key passphrase handy so you can paste it when prompted (possibly multiple times) with the git pull command. Alternatively, you can add your github key to your batch box so you do not have to log in repeated (see X).
Initiate the docker. Start up and log into the docker container, pull the repos from GitHub, and run setup scripts to setup the environment. This setup code links the docker directories to the existing directories on your box. As this is the case, you should not run job submission simultaneously using this setup, as one job submission might modify the data for another job submission.
To run the via AWS, we first run a setup run locally (in docker on the submission EC2 box) ;
Setup environment variables. Modify the code chunk below and submit in the terminal. We also clear certain files and model output that get generated in the submission process. If these files exist in the repo, they may not get cleared and could cause issues. You need to modify the variable values in the first 4 lines below. These include the SCENARIO
, VALIDATION_DATE
, COVID_MAX_STACK_SIZE
, and COMPUTE_QUEUE
. If submitting multiple jobs, it is recommended to split jobs between 2 queues: Compartment-JQ-1588569569
and Compartment-JQ-1588569574
.
If not resuming off previous run:
If resuming from a previous run, there are an additional couple variables to set. This is the same for a regular resume or continuation resume. Specifically:
RESUME_ID
- the COVID_RUN_INDEX
from the run resuming from.
RESUME_S3
- the S3 bucket where this previous run is stored
Preliminary model run. We do a setup run with 1 to 2 iterations to make sure the model runs and setup input data. This takes several minutes to complete, depending on how complex the simulation will be. To do this, run the following code chunk, with no modification of the code required:
Configure AWS. Assuming that the simulations finish successfully, you will now enter credentials and submit your job onto AWS batch. Enter the following command into the terminal ;
You will be prompted to enter the following items. These can be found in a file called new_user_credentials.csv
;
Access key ID when prompted
Secret access key when prompted
Default region name: us-west-2
Default output: Leave blank when this is prompted and press enter (The Access Key ID and Secret Access Key will be given to you once in a file)
Launch the job. To launch the job, use the appropriate setup based on the type of job you are doing. No modification of these code chunks should be required.
NOTE: Resume and Continuation Resume runs are currently submitted the same way, resuming from an S3 that was generated manually. Typically we will also submit any Continuation Resume run specifying
--resume-carry-seeding
as starting seeding conditions will be manually constructed and put in the S3.
Carrying seeding (do this to use seeding fits from resumed run):
Discarding seeding (do this to refit seeding again):
Single Iteration + Carry seeding (do this to produce additional scenarios where no fitting is required):
NOTE: A Resume and Continuation Resume are currently submitted the same way, but with
--resume-carry-seeding
specified and resuming from an S3 that was generated manually.
Commit files to Github. After the job is successfully submitted, you will now be in a new branch of the population repo. Commit the ground truth data files to the branch on github and then return to the main branch:
Save submission info to slack. We use a slack channel to save the submission information that gets outputted. Copy this to slack so you can identify the job later. Example output:
(This section describes the location and contents of each of the output files produced during a non-inference model run)
The model will output 2–6 different types of files depending on whether the configuration file contains optional sections (such , , and outcomes interventions) and whether is conducted ;
These files contain the values of the variables for both the infection and (if included) observational model at each point in time and for each subpopulation. A new file of the same type is produced for each independent simulation and each intervention scenario. Other files report the values of the initial conditions, seeding, and model parameters for each subpopulation and independent simulation (since parameters may be chosen to vary randomly between simulations). When is run, there are also file types reporting the model likelihood (relative to the provided data) and files for each iteration of the inference algorithm.
Within the model_output
directory in the project's directory, the files will be organized into folders named for the file types: seir
, spar
, snpi
, hpar
, hnpi
, seed
, init
, or llik
(see descriptions below). Within each file type folder, files will further be organized by the simulation name (setup_name
in config), the modifier scenario names - if scenarios exist for either seir
or outcome
parameters (specified with seir_modifiers::scenarios
and outcome_modifiers::scenarios
in config), and the run_id
(the date and time of the simulation, by default). For example:
The name of each individual file contains (in order) the slot, run_id and file type. The first index indicates the slot (chain, in MCMC language). If multiple iterations or blocks are run, the filename will look like 000000001.000000001.000000001.run_id.seir.parquet
indicating slot.block.iteration ;
Each file is a data table that is by default saved as a (a compressed representation that can be opened and manipulated with minimal memory) but can alternatively be saved as a csv
file. See options for specifying output type in
The example files outputs we show were generated with the following configuration file
The types and contents of the model output files changes slightly depending on whether the model is run as a forward simulation only, or is run in inference mode, in which parameter values are estimated by comparing the model to data. Output specific to model inference is described in a ;
Files in the seir
folder contain the output of the infection model over time. They contain the value of every variable for each day of the simulation for every subpopulation.
For the example configuration file shown above, the seir
file is
The meanings of the columns are:
mc_value_type
– either prevalence
or incidence
. Variable values are reported both as a prevalence (number of individuals in that state measured instantaneously at the start of the day, equivalent to the meaning of the S, I, or R variable in the differential equations or their stochastic representation) and as incidence (total number of individuals who newly entered this state, from all other states, over the course of the 24-hour period comprising that calendar day).
mc_infection_stage
, mc_vaccination_status
, etc. – The name of the compartment for which the value is reported, broken down into the infection stage for each state type (eg. vaccination, age).
mc_name
– The name of the compartment for which the value is reported, which is a concatenation of the compartment status in each state type.
subpop_1
, subpop_2
, etc. – one column for each different subpopulation, containing the value of the number of individuals in the described compartment in that subpopulation at the given date. Note that these are named after the nodenames defined by the user in the geodata file.
date
– The calendar date in the simulation, in YYYY-MM-DD format.
The files in the spar
folder contain the parameters that define the transitions in the compartmental model of disease transmission, defined in the seir::parameters
section of the config ;
The value
column gives the numerical values of the parameters defined in the corresponding column parameter
.
Files in the snpi
folder contain the time-dependent modifications to the transmission model parameter values (defined in seir_modifiers
section of the config) for each subpopulation. They contain the modifiers that apply to a given subpopulation and the dates within which they apply, and the value of the reduction to the given parameter.
The meanings of the columns are:
subpop
– The subpopulation to which this intervention parameter applies.
modifier_name
– The name of the intervention parameter.
start_date
– The start date of this intervention, as defined in the configuration file.
end_date
– The end date of this intervention, as defined in the configuration file.
parameter
– The parameter to which the intervention applies, as defined in the configuration file.
value
– The size of the modifier to the parameter either from the config, or fit by inference if that is run.
Files in the hpar
folder contain the output parameters of the observational model. They contain the values of the probabilities, delays or durations for each outcome in a given subpopulation.
The meanings of the columns are:
subpop
– Values in this column are the names of the nodes as defined in the geodata
file given by the user.
quantity
– The values in this column are the types of parameter values described in the config. The options are probability
, delay
, and duration
. These are the quantities to which there is some parameter defined in the config.
outcome
– The values here are the outcomes to which this parameter applies. These are names of the outcome compartments defined in the model.
value
– The values in this column are the parameter values of the quantity that apply to the given subpopulation and outcome.
Files in the hosp
folder contain the output of the infection model over time. They contain the value of every outcome variable for each day of the simulation for every subpopulation.
Columns are:
date
– The calendar date in the simulation, in YYYY-MM-DD format.
subpop
– Values in this column are the names of the nodes as defined in the geodata
file given by the user.
outcome_variable_1, outcome_variable_2, ...
- one column for each different outcome variable as defined in the config, containing the value of the number of individuals in the described compartment in that subpopulation at the given date ;
Files in the hnpi
folder contain any parameter modifier values that apply to the outcomes model, defined in the outcome_modifiers
section of the config. They contain the values of the outcome parameter modifiers, and the dates to which they apply in a given subpopulation.
The meanings of the columns are:
subpop
– The values of this column are the names of the nodes from the geodata
file.
modifier_name
– The names/labels of the modifier parameters, defined by the user in the config file, which applies to the given node and time period.
start_date
– The start date of this intervention, as defined in the configuration file.
end_date
– The end date of this intervention, as defined in the configuration file.
parameter
– The outcome parameter to which the intervention applies.
value
– The values in this column are the modifier values of the intervention parameters, which apply to the given parameter in a given subpopulation. Note that these are strictly reductions; thus a negative value corresponds to an increase in the parameter, while a positive value corresponds to a decrease in the parameter.
Files in the seed
folder contain the seeded values of the infection model. They contain the amounts seeded into each variable, the variable they are seeded from, and the time at which the seeding occurs. The user can provide a single seeding file (which will be used across all simulations), or, if multiple simulations are being run the user can provide a separate file for each simulation ;
The meanings of the columns are:
subpop
- The values of this column are the names of the nodes from the geodata
file.
date
- The values in this column are the dates of seeding.
amount
- The amount seeded in the given subpopulation from source variables to destination variables, at the given date ;
source_infection_stage
, source_vaccination_status
, etc. - The name of the compartment from which the amount is seeded, broken down into the infection stage for each state type (eg. vaccination, age).
destination_infection_stage
, destination_vaccination_status
, etc. - The name of the compartment into which the amount is seeded, broken down into the infection stage for each state type (eg. vaccination, age).
no_perturb
- The values in this column can be either true
or false
. If true, then the amount and/or date can be perturbed if running an inference run. Whether the amount or date is perturbed is defined in the config using perturb_amount
and perturb_date
;
Files in the init
folder contain the initial values of the infection model. Either seed or init files will be present, depending on the configuration of the model . These files contain the initial conditions of the infection model at the start date defined in the configuration file. As with seeding, the user can provide a single initial conditions file (which will be used across all simulations), or, if multiple simulations are being run the user can provide a separate file for each simulation ;
The meanings of the columns are:
subpop
- The values of this column are the names of the nodes from the geodata
file.
mc_infection_stage
, mc_vaccination_status
, etc. - The name of the compartment for which the value is reported, broken down into the infection stage for each state type (eg. vaccination, age).
amount
- The amount initialized seeded in the given subpopulation at the start date defined in the configuration file ;
Within flepiMoP, gempyor is an open-source Python package that constructs and simulates compartmental infectious disease dynamics models. gempyor is meant to be used within flepiMoP, where it integrates with parameter inference and data processing scripts, but can also be run standalone with a command-line interface, generating simulations of disease incidence under different scenario assumptions.
To simulate an infectious disease dynamics problem, the following building blocks needs to be defined:
The over which the disease is transmitted
The , defining the compartments and the transitions between compartments
An , defining different observable outcomes (serology, hospitalization, deaths, cases) from the transmission model
The parameters and modifiers that apply to them
At the core of our pipeline is a dynamic mathematical model that categorizes individuals in the population into a discrete set of states ('compartments') and describes the rates at which transitions between states can occur. Our modeling approach was developed to describe classic infectious disease transmission models, like the SIR model, but is much more general. It can encode any compartmental model in which transitions between states are of the form
where , , and are time-dependent variables describing the number of individuals in each state, is a rate parameter (units of time) and is a scaling parameter (unitless). may be , , a different variable, or 1, and the rate may also be the sum of terms of this form. Rates that involve non-linear functions or more than two variables are currently not possible. For simplicity, we omitted the time dependencies on parameters (e.g is in fact and , are ,).
The model can be simulated as a continuous-time, deterministic process (i.e., a set of ordinary differential equations), which in this example would be in the form
and as a stochastic process, it is
A common COVID-19 model is a variation of this SEIR model that incorporates:
multiple identical stages of the infectious period, which allows us to model gamma-distributed durations of infectiousness, and
A three-stage infectious period model is given by
The flepiMoP model structure is specifically designed to make it simple to encode the type of more complex "stratified'' models that often arise in infectious disease dynamics. The following are some examples of possible stratifications.
To describe an SEIR-type disease that spreads and progresses differently among children versus adults, one may want to repeat each compartment of the model for each of the two age groups (C – Children, A – Adults), creating an age-stratified model
Vaccination status could influence disease progression and infectiousness, and could also change over time as individuals choose to get the vaccine (V – vaccinated, U – unvaccinated)
Another common stratification would be pathogen strain, such as COVID-19 variants. Individuals may be infected with one of several variants, strains, or serotypes. Our framework can easily create multistrain models, for example
The pipeline allows for an additional type of dynamic state variable beyond those included in the mathematical model. We refer to these extra variables as "Outcomes" or "Observations". Outcome variables can be functions of model variables, but do not feed back into the model by influencing other state variables. Typically, we use outcome variables to describe the process through which some subset of individuals in a compartment are "observed'' and become part of the data to which models are compared and attempt to predict. For example, in the context of a model for an infectious disease like COVID-19, outcome variables include reported cases, hospitalizations, and deaths.
In addition to single values (drawn from a distribution), the duration and delay can be inputted as distributions, producing a convolution of the output.
Formally, for a deterministic, continuous-time model
For a discrete-time, stochastic model
Outcomes can also be constructed as functions of other outcomes. For example, a fraction of hospitalized patients may end up in the intensive care unit (ICU).
There are several benefits to separating outcome variables from the mathematical model. Firstly, these variables can be calculated after the model is run, and only at the timepoints of interest, which can dramatically reduce the memory needed during model simulation. Secondly, outcome variables can be fully stochastic even when the mathematical model is simulated deterministically. This becomes useful when an infection might be at high enough prevalence that a deterministic simulation is appropriate, but when there is a rare and therefore quite stochastic outcome reported in the data (e.g., severe cases) that the model is tasked with predicting. Thirdly, outcome variables can have arbitrary delay distributions, to take into account the complexities of health reporting practices, whereas our mathematical modeling framework is designed mainly for exponentially distributed delays and only easily permits extensions to gamma-distributed delays. Finally, this separation keeps the pipeline modular and allow for easy editing of one component of the model without disrupting the other.
The pipeline was designed specifically to simulate infection dynamics in a set of connected subpopulations. These subpopulations could represent geographic divisions, like countries, states, provinces, or neighborhoods, or demographic groups, or potentially even different host species. The equations and parameters of the transmission and outcomes models are repeated for each subpopulation, but the values of the parameters can differ by location. Within each subpopulation, infection is equally likely to spread between any pair of susceptible/infected individuals after accounting for their infection class, whereas between subpopulations there may be varying levels of mixing.
Formally, this type of population structure is often referred to as a “metapopulation”, and each subpopulation may be called a “deme”.
The following properties may be different between subpopulations:
the population size
the parameters of the transmission model (see LINK)
the parameters of the outcomes model (see LINK)
the amount of transmission that occurs within this subpopulation versus from any other subpopulation (see LINK)
the timing and extent of any interventions that modify these parameters (see LINK)
the initial timing and number of external introductions of infections into the population (see LINK)
the ground truth timeseries data used to compare to model output and infer model parameters (see LINK)
Currently, the following properties must be the same across all subpopulations:
the compartmental model structure
the form of the likelihood function used to estimate parameters by fitting the model to data (LINK)
...
The generalized compartmental model allows for second order “interaction” terms that describe transitions between model states that depend on interactions between pairs of individuals. For example, in the context of a classical SIR model, the rate of new infections depends on interactions between susceptible and infectious individuals and the transmission rate
For a model with multiple subpopulations, each of these interactions can occur either between individuals in the same or different subpopulations, with specific rate parameters for each combination of individual locations
The transmission matrix is then
If an alternative compartmental disease model is created that has other interactions (second order terms), then the same mobility values are used to determine the degree of interaction between each pair of subpopulations.
It might also be necessary to model instantaneous changes in values of model variables at any time during a simulation. We call this 'seeding'. For example, individuals may import infection from other external populations, or instantaneous mutations may occur, leading to new variants of the pathogen. These processes can be modeled with seeding, allowing individuals to change state at specified times independently of model equations.
We also note that seeding can also be used as a convenient way to specify initial conditions, particularly ealy in an outbreak where the outbreak is triggered by a few 'seedings'.
Parameters in the disease transmission model or the observation model may change over time. These changes could be, for example: environmental drivers of disease seasonality; “non-pharmaceutical interventions” like social distancing, isolation policies, or wearing of personal protective equipment; “pharmaceutical interventions” like vaccination, prophylaxis, or therapeutics; changes in healthcare seeking behavior like testing and diagnosis; changes in case reporting, etc.
The model allows for any parameter of the disease transmission model or the observation model to change to a new value for a time interval specified by start and end times (or multiple start and end times, for interventions that are recurring). Each change may be subpopulation-specific or apply to the entire population. Changes may be overlapping in time.
StackedModifier
- TBA
You will be prompted to provide your GitHub username and password. Note that from 2021, GitHub has changed the use of passwords to the use of , so the prompted "password" is not the password you use to login. Instead, we recommend using the more safe ssh
protocol to clone GitHub repositories. To do so, first on the Rockfish cluster and then copy the generated public key from the Rockfish cluster to your local computer by opening a terminal and prompting,
Then to your GitHub account. Next, make a file ~/.ssh/config
by using the command
vi ~/.ssh/config`. Press 'I' to go into insert mode and paste the following chunck of code,
Next step is to setup the data. First $DATA_PATH to your data folder, and set any data options. If you are using the Delph Epidata API, first register for a key here: . Once you have a key, add that below where you see [YOUR API KEY]. Alternatively, you can put that key in your config file in the inference
section as gt_api_key: "YOUR API KEY"
.
If you still want to use git to clean the repo but want finer control or to understand how dangerous is the command, .
We use for notification. Install ntfy on your Iphone or Android device. Then subscribe to the channel ntfy.sh/flepimop_alerts
where you'll receive notifications when runs are done.
The options here are [-n tasks or cores]
, [-t walltime]
, [-p partition]
and [-m memory]
, though other options can also be included or modified to your requirements. More details can be found on the .
If you have access to the jh-covid
account, you should use the IDD Staging AMI (ami-03641dd0c8554e5d0
) to provision and launch new staging servers; it is already setup with all of the dependencies described in this section, however you will need to alter it's default network settings, iam role and security group(Please refer in details). You can find the AMI , select it, and press the Launch button to walk you through the Launch Wizard to choose your instance type and .pem
file to provision your staging server. When going through the Launch Wizard, be sure to select Next: Configure Instance details
instead of Review and Launch
. You will need to continue selecting the option that is not Review and Launch
until you have selected a security group. In these screens, most of the default options are fine, but you will want to set the HPC VPC network, choose a public subnet (it will say public or private in the name), and set the iam role to EC2S3FullAccess on the first screen. You can also name the machine by providing a Name
tag in the tags screen. Finally, you will need to set your security group to dcv_usa
and/or dcv_usa2
. You can then finalize the machine initialization with Review and Launch
. Once your instance is provisioned, be sure to put its IP address into the HostName
section of the ~/.ssh/config
file on your local client so that you can connect to it from your client by simply typing ssh staging
in your terminal window.
The COVIDScenarioPipeline/batch/inference_job.py
script will use the contents of the current directory and the values of the config file and any commandline arguments we pass it to launch a run on AWS Batch via the AWS API. To run this script, you need to have access to your so that you can enable access to the API by running aws configure
at the command line, which will prompt you to enter your access key, secret, and preferred region, which should always be us-west-2
for jh-covid
runs. (You can leave the Default format
entry blank by simply hitting Enter.) IMPORTANT REMINDER: (Do not give anyone your access key and secret. If you lose it, deactivate it on the AWS console and create a new one. Keeep it safe.)
Inference jobs are parallelized by NPI scenarios and hospitalization rates, so if your config file defines more than one top-level scenario or more than one set of hospitalization parameters, the inference_job.py
script will kick off a separate batch job for the cross product of scenarios * hospitalizations. The script will announce that it is launching each job and will print out the path on S3 where the final output for the job will be written. You can monitor the progress of the running jobs using either the or by running:
You can see how many tasks are running within each of the different corresponding to the via the . There is a one-to-one correspondence between Job Queues, Compute Environments, and ECS Clusters (the matching ones all end with the same numeric identifier.) You can force Batch to scale up the number of CPUs available for running tasks by selecting the radio button corresponding to the compute environment that you want to scale on the , clicking Edit, increasing the Desired CPU (and possibly the Minimum CPU, see below), and clicking the Save button. You will be able to see new containers and tasks coming online via the ECS Dashboard after a few minutes.
There will be a separate seir
file output for each slot (independent simulation) and for each iteration of the simulation if is conducted.
Details on the numerical integration procedure for simulating such an equation is given in the section.
Alternatively, the model can be simulated as a discrete-time stochastic process, where the number of individuals transitioning between states and at time is a binomial random variable
where the second term is the expected fraction of individuals in the state at time who would transition to by time if there were no other changes to in this time, and time step is a chosen parameter that must be small for equivalence between continuous- and discrete-time versions of the model.
For example, an SEIR model – which describes an infection for which susceptible individuals () who are infected first pass through a latent or exposed () phase before becoming infectious () and that confers perfect lifelong immunity after recovery () – could be encoded as
where is the transmission rate (rate of infectious contact per infectious individual), is the rate of progression ( is the average latent/incubation period), and is the recovery rate ( is the average duration of the infectious period), and is the total population size (). In differential equation form, this model is
an infection rate modified by a 'mixing coefficient', , which is a rough heuristic for the slowdown in disease spread that occurs in realistically heterogeneous populations where more well-connected individuals are infected first.
where is the transmission rate between age X and Y, and we have assumed individuals do not age on the timescale relevant to the model.
where is the vaccination rate (we assume that individuals do not receive the vaccine while they are exposed or infectious) and is the vaccine efficacy against infection. Similar structures could be used for other sources of prior immunity or other dynamic risk groups.
where is the immune cross-protection conferred from infection with strain A to subsequent infection with strain B. Co-infection is ignored. All individuals are assumed to be initially equally susceptible to both infections and are just categorized as (vs ) for convenience.
All combinations of these situations can be quickly specified in flepiMoP. Details on how to encode these models is provided in the section, with examples given in the section.
An outcome variable can be generated from a state variable of the mathematical model using the following properties:
The proportion of all individuals in who will be observed as ,
The delay between when an individual enters state and when they are observed as , which can follow a class of probability distributions where is the parameters of the distribution (e.g., the mean and standard deviation of a normal distribution)
(optional) the duration spent in observable , in which case the output will also contain the prevalence (number of individuals currently in in addition to the incidence into
The number of individuals in at time who become part of the outcome variable is a random variable, and individuals who are observed in at time could have entered at different times in the past.
Note that outcomes constructed in this way always represent incidence values; meaning they describe the number of individuals newly entering this state at time . If the model state is also an incidence, then is a unitless probability, whereas if is a prevalence (number of individuals currently in state at time ), then is instead a probability per time unit.
Details on how to specify these outcomes in the model configuration files is provided in the section, with examples given in the section.
where is the per-contact per-time rate of disease transmission between an infected individual residing in subpopulation and a susceptible individual from subpopulation .
In general for infection models in connected subpopulations, the transmission rates can take on arbitrary values. In this pipeline, however, we impose an additional structure on these terms. We assume that interactions between subpopulations occur when individuals temporarily relocate to another subpopulation, where they interact with locals. We call this movement “mobility”, and it could be due to regular commuting, special travel, etc. There is a transmission rate () associated with each subpopulation , and individuals physically in that subpopulation – permanently or temporarily – are exposed and infected with this local rate whenever they encounter local susceptible individuals.
where is the onward transmission rate from infected individuals in subpopulation , is the number of individuals in subpopulation i who are interacting with individuals in subpopulation at any given time (for example, fraction who commute each day), and is a fractional scaling factor for the strength of inter-population contacts (for example, representing the fraction of hours in a day commuting individuals spend outside vs. inside their subpopulation).
The list of all pairwise mobility values and the interaction scaling factor are model input parameters. Details on how to specify them are given in the section.
Initial conditions can be specified by setting the values of the compartments in the disease transmission model at time zero, or the start of the simulation. For example, we might assume that for day zero of an outbreak the whole population is susceptible except for one single infected individual, i.e. and . Alternatively, we might assume that a certain proportion of the population has prior immunity from previous infection or vaccination.
The magnitude of these changes are themselves model parameters, and thus may along with other parameters when the model is fit to data. Currently, the start and end times of interventions must be fixed and cannot be varied or inferred.
For example, the rate of transmission in subpopulation , , may be reduced by an intervention that acts between times and , and another intervention that acts between times and
In this case, and are both considered simple SinglePeriodModifier
interventions. There are four possible types of interventions that can be included in the model
SinglePeriodModifier
- an intervention that leads to a fractional reduction in a parameter value in subpopulation (i.e., ) between two timepoints
MultiPeriodModifier
- an intervention that leads to a fractional reduction in a parameter value in subpopulation (i.e., ) value between multiple sets of timepoints
ModifierModifier
- an intervention that leads to a fractional reduction in the value of another intervention between two timepoints
This section describes how to specify the values of each model state at the time the simulation starts, and how to make instantaneous changes to state values at other times (e.g., due to importations)
flepiMoP allows users to specify instantaneous changes in values of model variables, at any time during the simulation. We call this "seeding". For example, some individuals in the population may travel or otherwise acquire infection from outside the population throughout the epidemic, and this importation of infection could be specified with the seeding option. As another example, new genetic variants of the pathogen may arise due to mutation and selection that occurs within infected individuals, and this generation of new strains can also be modeled with seeding. Seeding allows individuals to change state at specified times in ways that do not depend on the model equations. In the first example, the individuals would be "seeded" into the infected compartment from the susceptible compartment, and in the second example, individuals would be seeded into the "infected with new variant" compartment from the "infected with wild type" compartment.
The seeding option can also be used as a convenient alternative way to specify initial conditions. By default, flepiMoP initiates models by putting the entire population size (specified in the geodata
file) in the first model compartment. If the desired initial condition is only slightly different than the default state, it may be more convenient to specify it with a few "seedings" that occur on the first day of the simulation. For example, for a simple SIR model where the desired initial condition is just a small number of infected individuals, this could be specified by a single seeding into the infected compartment from the susceptible compartment at time zero, instead of specifying the initial values of three separate compartments. For larger models, the difference becomes more relevant.
The configuration items in the seeding
section of the config file are
seeding:method
Must be either "NoSeeding"
, "FromFile"
, "PoissonDistributed"
, "NegativeBinomialDistributed"
, or "FolderDraw".
seeding::seeding_file
Only required for method: “FromFile”.
Path to a .csv file containing the list of seeding events
seeding::lambda_file
Only required for methods "PoissonDistributed"
or "NegativeBinomialDistributed".
Path to a .csv file containing the list of the events from which the actual seeding will be randomly drawn.
seeding::seeding_file_type
Only required for method "FolderDraw".
Either seir
or seed
Details on implementing each seeding method and the options that go along with it are below.
If there is no seeding, then the amount of individuals in each compartment will be initiated using the values specified in theinitial_conditions
section and will only be changed at later times based on the equations defined in the seir
section. No other arguments are needed in the seeding section in this case
Example
This seeding method reads in a user-defined file with a list of seeding events (instantaneous transitions of individuals between compartments) including the time of the event and subpopulation where it occurs, and the source and destination compartment of the individuals. For example, for the simple two-subpopulation SIR model where the outbreak starts with 5 individuals in the small province being infected from a source outside the population, the seeding section of the config could be specified as
Where seeding.csv contains
seeding::seeding_file
must contain the following columns:
subpop
– the name of the subpopulation in which the seeding event takes place. Seeding cannot move individuals between different subpopulations.
date
– the date the seeding event occurs, in YYYY-MM-DD format
amount
– an integer value for the amount of individuals who transition between states in the seeding event
source_*
and destination_*
– For each compartment group (i.e., infection stage, vaccination stage, age group), a different column describes the status of individuals before and after the transition described by the seeding event. For example, for a model where individuals are stratified by age and vaccination status, and a 1-day vaccination campaign for young children and the elderly moves a large number of individuals into a vaccinated state, this file could be something like
These methods are very similar to FromFile, except the seeding value used in the simulation is randomly drawn from the seeding value specified in the file, with an average value equal to the file value. These methods can be useful when the true seeded value is unknown, and only an observed value is available which is assumed to be observed with some uncertainty. The input requirements are the same for both distributions
or
and the lambda_file
has the same format requirements as the seeding_file
for the FromFile method described above.
For method::PoissonDistributed
, the seeding value for each seeding event is drawn from a Poisson distribution with mean and variance equal to the value in the amount
column. Formethod::NegativeBinomialDistributed
, seeding is drawn from a negative binomial distribution with mean amount
and variance amount+5
(so identical to "PoissonDistributed"
for large values of amount
but has higher variance for small values).
TB ;
Methods for fitting model to data
flepiMoP can be used to conduct forward simulations of a model with user-defined parameter values, or, it can be used to iteratively run a model with some unknown parameters, compare the model output to ground truth data, and find parameter values that optimize the fit of the model to data (i.e., conduct model "inference"). We have developed a custom model inference method that is based on standard Markov Chain Monte Carlo (MCMC)-based approaches to Bayesian inference for dynamic models, but is adapted to deal with some of the particular challenges of large-scale epidemic models, including i) long times and high computational resources required to simulate single model runs, ii) multiple subpopulations with location-specific parameters but inter-location transmission, iii) a high-dimensional parameter space, iv) the need to produce real-time epidemic projections, and v) the availability of parallel computing resources.
– A set of unknown model parameters to be estimated by fitting the model output to data. For a model with subpopulations each with their own parameters, this set includes all location-specific parameters .
– The timeseries output of one or more of the state variables of the model under parameters For simplicity, we will often just use the notation . The value at a timepoint is . For a model with subpopulations for which there are different state variables, this becomes . (Note that for the general case when the dynamics in one location can effect the dynamics in another, the model state in one location depends on the full set of parameters, not just the location-specific parameters.)
– The timeseries for the observed data (also referred to as "ground truth") that the model attempts to recreate. For a model with subpopulations each with their own observed data for variable , this becomes .
– The likelihood of the observed data being produced by the model for an input parameter set . This is a probability density function over all possible values of the data being produced by the model, conditional on a fixed model parameter value ;
– The prior probability distribution, which in Bayesian inference encodes beliefs about the possible values of the unknown parameter before any observed data is formally compared to the model.
– The posterior probability distribution, which in Bayesian inference describes the updated probability of the parameters conditional on the observed data .
– The proposal density, used in Metropolis-Hastings algorithms for Markov Chain Monte Carlo (MCMC) techniques for sampling the posterior distribution, describes the probability of proposing a new parameter set from a current accepted parameter set .
This section can be skipped by those familiar with Markov Chain Monte Carlo approaches to Bayesian inference.
Our model fitting framework is based on the principles of Bayesian inference. Instead of estimating a single "best-fit" value of the unknown model parameters, our goal is to evaluate the consistency of every possible parameter value with the observed data, or in other words, to construct a distribution that describes the probability that a parameter has a certain value given the observations. This output is referred to as the posterior probability. This framework assumes that the model structure accurately describes the underlying generative process which created the data, but that the underlying parameters are unknown and that there can be some error in the observation of the data.
Bayes' Rule states that the posterior probability of a set of model parameters given observed data can be expressed as a function of the likelihood of observing the data under the model with those parameters () and the prior probability ascribed to those parameters before any data was observed ()
where the denominator is a constant factor – independent of – that only serves to normalize the posterior and thus can be ignored ;
The likelihood function can be defined for a model/data combination based on an understanding of both a) the distribution of model outcomes for a given set of input parameters (if output is stochastic), and b) the nature of the measurement error in observing the data (if relevant) ;
For complex models with many parameters like those used to simulate epidemic spread, it is generally impossible to construct the full posterior distribution either analytically or numerically. Instead, we rely on a class of methods called "Markov Chain Monte Carlo" (MCMC) that allows us to draw a random sample of parameters from the posterior distribution. Ideally, the statistics of the parameters drawn from this sample should be an unbiased estimate of those from the complete posterior.
In many Bayesian inference problems that arise in scientific model fitting, it is impossible to directly evaluate the full posterior distribution, since there are many parameters to be inferred (high dimensionality) and it is computationally costly to evaluate the model at any individual parameter set. Instead, it is common to employ Markov Chain Monte Carlo (MCMC) methods, which provide a way to iteratively construct a sequence of values that when taken together represent a sample from a desired probability distribution. In the limit of infinitely long sequences ("chains") of values, these methods are mathematically proven to converge to an unbiased sample from the distribution. There are many different MCMC algorithms, but each of them relies on some type of rule for generating a new "sampled" parameter set from an existing one. Our parameter inference method is based on the popular Metropolis-Hastings algorithm. Briefly, at every step of this iterative algorithm, a new set of parameters is jointly proposed, the model is evaluated at that proposed set, the value of the posterior (e.g., likelihood and prior) is evaluated at the proposed set, and if the posterior is improved compared to the previous step, the proposed parameters are "accepted" and become the next entry in the sequence, whereas if the value of the posterior is decreased, the proposed parameters are only accepted with some probability and otherwise rejected (in which case the next entry in the sequences becomes a repeat of the previous parameter set).
The full algorithm for Metropolis-Hastings Markov Chain Monte Carlo is:
Generate initial set of parameters
Evaluate the likelihood () and prior () at this parameter set
For
where is the length of the MCMC chain, add to the sequence of parameter values :
Generate a proposed set of parameters based on an arbitrary proposal distribution
Evaluate the likelihood and prior at the proposed parameter set
Generate a uniform random number
Calculate the acceptance ratio
If
, ACCEPT the proposed parameters to the parameter chain. Set ;
Else,
REJECT the proposed parameters for the chimeric parameter chain. Set
In our algorithm, model fitting involves comparing timeseries of variables produced by the model (either transmission model state variables or observable outcomes constructed from those variables) to timeseries of observed "ground truth" data with the same time points. For timeseries data that arises from a deterministic, dynamic model, then the overall likelihood can be calculated as the product of the likelihood of the model output at each timepoint (since we assume the data at each timepoint was measured independently). If there are multiple observed datastreams corresponding to multiple model outputs (e.g., cases and deaths) ;
For each subpopulation in the model, the likelihood of observing the "ground truth" data given the model parameters is
where describes the process by which the data is assumed to be observed/measured from the underlying true vales. For example, observations may be assumed to be normally distributed around the truth with a known variance, or, count data may be assumed to be generated by a Poisson process ;
And the overall likelihood taking into account all subpopulations, is the product of the individual likelihoods
Note that the likelihood for each subpopulation depends not only on the parameter values that act within that subpopulation, but on the entire parameter set , since in general the infection dynamics in one subpopulation are also affected by those in each other region. Also note that we assume that the parameters only impact the likelihood through the single model output timeseries . While this is exactly true for a deterministic model, we make the simplifying assumption that it is also true for stochastic models, instead of attempting to calculate the full distribution of possible trajectories for a given parameter set and include that in the likelihood as well.
The method we use for estimating model parameters is based on the Metropolis-Hastings algorithm, which is a class of Markov Chain Monte Carlo (MCMC) methods for obtaining samples from a posterior probability distribution. We developed a custom version of this algorithm to deal with some of the particular mathematical properties and computational challenges of fitting large disease transmission models ;
There are to major unique features of our adapted algorithm:
Parallelization – Generally MCMC methods starting from a single initial parameter set and generating an extremely long sequence of parameter samples such that the Markov process is acceptably close to a stationary state where it represents an unbiased sample from the posterior. Instead, we simulate multiple shorter chains in parallel, starting from different initial conditions, and pool the results. Due to the computational time required to simulate the epidemic model, and the timescale on which forecasts of epidemic trajectories are often needed (~weeks), it is not possible to sequentially simulate the model millions of times. However, modern supercomputers allow massively parallel computation. The hope of this algorithm is that the parallel chains sample different subspaces of the posterior distribution, and together represent a reasonable sample from the full posterior. To maximize the chance of at least local stationarity of these subsamples, we pool only the final values of each of the parallel chains.
Multi-level – Our pipeline, and the fitting algorithm in particular, were designed to be able to simulate disease dynamics in a collection of linked subpopulations. This population structure creates challenges for model fitting. We want the model to be able to recreate the dynamics in each subpopulation, not just the overall summed dynamics. Each subpopulation has unique parameters, but due to the coupling between them (), the model outcomes in one subpopulation also depend on the parameter values in other subpopulations. For some subpopulations (), this coupling may effectively be weak and have little impact on dynamics, but for others (), spillover from another closely connected subpopulation may be the primary driver of the local dynamics. Thus, the model cannot be separately fit to each subpopulation, but must consider the combined likelihood. However, such an algorithm may be very slow to find parameters that optimize fits in all locations simultaneously, and may be predominantly drawn to fitting to the largest/most connected subpopulations. The avoid these issues, we simultaneously generate two communicating parameter chains: a "chimeric" chain that allows the parameters for each subpopulation to evolve quasi-independently based on local fit quality, and a "global" chain that evolves only based on the overall fit quality (for all subpopulations combined).
Note that while the traditional Metropolis-Hastings algorithm for MCMC will provably converge to a stationary distribution where the sequence of parameters represents a sample from the posterior distribution, no such claim has been mathematically proven for our method.
For
, where is the number of parallel MCMC chains (also known as slots)
Generate initial state
Generate an initial set of parameters , and copy this to both the global () and chimeric () parameter chain (sequence ;
Generate an initial epidemic trajectory
Calculate and record the initial likelihood for each subpopulation, $$\mathcal{L_i}(D_i|Z_i(\Theta_{m,0}))$ ;
For
where is the length of the MCMC chain, add to the sequence of parameter values :
Generate a proposed set of parameters from the current chimeric parameters using the proposal distribution $$g(\Theta^*|\Theta^C_{m,k-1})$ ;
Generate an epidemic trajectory with these proposed parameters,
Calculate the likelihood of the data given the proposed parameters for each subpopulation,
Calculate the overall likelihood with the proposed parameters,
Make "global" decision about proposed parameters
Generate a uniform random number
Calculate the overall likelihood with the current global parameters,
Calculate the acceptance ratio
If
: ACCEPT the proposed parameters to the global and chimeric parameter chains
Set \Theta^G_{m,k} =$$$$\Theta^*
Set
Update the recorded subpopulation-specific likelihood values (chimeric and global) with the likelihoods calculated using the proposed parameter ;
Else
: REJECT the proposed parameters for the global chain and make subpopulation-specific decisions for the chimeric chain
Set
Make "chimeric" decision:
For
Generate a uniform random number
Calculate the acceptance ratio
If
: ACCEPT the proposed parameters to the chimeric parameter chain for this location
Set
Update the recorded chimeric likelihood value for subpopulation to that calculated with the proposed parameter
Else
: REJECT the proposed parameters for the chimeric parameter chain for this location
Set
`End if ;
End for
subpopulations
End making chimeric decisions
End if
End making global decision
End for
iterations of each MCMC chain
End for
parallel MCMC chains
Collect the final global parameter values for each parallel chain
We consider the sequence to represent a sample from the posterior probability distribution, and use it to calculate statistics about the inferred parameter values and the epidemic trajectories resulting from them (e.g., mean, median, 95% credible intervals).
There are a few important notes/limitations about our method currently:
All parameters to be fit must be location-specific. There is currently no way to fit a parameter that has the identical value across all locations
The pipeline currently does not allow for fitting of the basic parameters of the compartmental epidemic model. Instead, these must be fixed, and the value of location-specific "interventions" acting to increase/reduce these parameters can be fit. All parameters related to the observational/outcomes model can be fit, as well as "interventions" acting to increase or reduce them ;
At no point is the parameter fitting optimizing the fit of the summed total population data to total population model predictions. The "overall" likelihood function used to make "global" parameter acceptance decisions is the product of the individual subpopulations likelihoods (which are based on comparing location-specific data to location-specific model output), which is not equivalent to likelihood for the total population. For example, if overestimates of the model in some subpopulations were exactly balanced by underestimates in others, the total population estimate could be very accurate and the total population likelihood high, but the overall likelihood we use here would still be low.
There is no model simulation run or record that corresponds to the combined parameters recorded in the chimeric parameter chain (). For entry in the chain, some of these parameter values were recently accepted from the last proposal and were used in the simulation produced by that proposal, while for other subpopulations, the most recent proposed parameters were rejected so contains parameters accepted – and part of the simulations produced – in a previous iteration.
It is currently not possible to infer parameters of the measurement process encoded in the likelihood function. For example, if the likelihood is chosen to be a normal distribution, which implies an assumption that the observed data is generated from the underlying truth according to a normal distribution with mean zero, then the standard deviation must be specified, and cannot be inferred along with the other model parameters ;
There is an option to use a slightly different version of our algorithm, in which globally accepted parameter values are not pushed back into the chimeric likelihood, but the chimeric likelihood is instead allowed to continue to evolve independently. In this variation, the chimeric acceptance decision is always made, not only if a global rejection happens ;
The proposal distribution for generating new parameter sets is currently constrained to be a joint distribution in which the the value of each new proposed parameter is chosen independently of any other parameters.
While in general in Metropolis-Hasting algorithms the formula for the the acceptance ratio includes the proposal distribution , those terms cancel out if the proposal distribution is symmetrical. Our algorithm assumes such symmetry and thus does not include in the formula, so the user must be careful to only select symmetric distributions.
The baseline likelihood function used in the fitting algorithm described above allows for parameter values to differ arbitrarily between different subpopulations. However, it may be desired to instead impose constraints on the best-fit parameters, such that subpopulations that are similar in some way, or belong to some pre-defined group, have parameters that are close to one another. Formally, this is typically done with group-level or hierarchical models that fit meta-parameters from which individual subpopulation parameters are assumed to draw. Here, we instead impose this group-level structure by adding an additional term to the likelihood that describes the probability that the set of parameters proposed for a group of subpopulations comes from a normal distribution. This term of the likelihood will be larger when the variance of this parameter set is smaller. Formally
where is a group of subpopulations, is one of the parameters in the set , is the probability density function of the normal distribution, and are the mean and standard deviation of all values of the parameter in the group . There is also the option to use a logit-normal distribution instead of a standard normal, which may be more appropriate if the parameter is a proportion bounded in [0,1].
Welcome to flepiMoP documentation!
The “FLexible EPIdemic MOdeling Pipeline” (flepiMoP; formerly known as the COVID Scenario Modeling Pipeline or CSP) is an open-source software suite designed by researchers in the Johns Hopkins Infectious Disease Dynamics Group and at UNC Chapel Hill to simulate a wide range of compartmental models of infectious disease transmission. The disease transmission and observation models are defined by a no-code configuration file, which allows models of varying complexity to be specified quickly and consistently, from simple problems described by SIR-style models in a single population to more complicated models of multiple pathogen strains transmitting between thousands of connected spatial divisions and age groups.
It was initially designed in early 2020 and was routinely used to provide projections of the emerging COVID-19 epidemic to health authorities worldwide. Currently, flepiMoP provides COVID-19 projections to the US CDC-funded model aggregation sites, the COVID-19 Forecast Hub and the COVID-19 Scenario Modeling Hub, influenza projections to FluSight and to the Flu Scenario Modeling Hub, and RSV projections to the RSV Scenario Modeling Hub.
However, the pipeline is much more general and can be used to simulate the dynamics of any infection that can be expressed as a compartmental epidemic model. These include applications in chemical reaction kinetics, pharmacokinetics, within-host disease dynamics, or applications in the social sciences.
In addition to producing forward simulations given a specified model and parameter values, the pipeline can also attempt to optimize unknown parameters (e.g., transmission rate, case detection rate, intervention efficacy) to fit the model to datasets the user provides (e.g., hospitalizations due to severe disease) using a Bayesian inference framework. This feature allows the pipeline to be utilized for short-term forecasting or longer-term scenario projections for ongoing epidemics, since it can simultaneously be fit to data for dates in the past and then use best-fit parameters to make projections into the future.
The main features of flepiMoP are:
Open-source (GPL v3.0) infectious dynamics modeling software, written in R and Python
Versatile, no-code design applicable for most compartmental models and outcome observation models, allowing for quick iteration in reaction to epidemic events (e.g., emergence of new variants, vaccines, non-pharmaceutical interventions (NPIs))
Powerful, just-in-time compiled disease transmission model and distributed inference engine ready for large scale simulations on high-performance computing clusters or cloud workflows
Adapted to small- and large-scale problems, from a simple SIR model to a complex model structure with hundreds of compartments on thousands of connected populations
Strong emphasis on mechanistic processes, with a design aimed at leveraging domain knowledge in conjunction with statistical inference
Portable for Windows WSL, MacOS, and Linux with the provided Docker image and an Anaconda environment
The mathematical model within the pipeline is a compartmental epidemic model embedded within a well-mixed metapopulation. A compartmental epidemic model is a model that divides all individuals in a population into a discrete set of states (e.g. “infected”, “recovered”) and tracks – over time – the number of individuals in each state and the rates at which individuals transition between these states. The well-known SIR model is a classic example of such a model, and much more complex versions of this model type have been simulated with this framework (for example, an SEIR-style model in which individuals are further subdivided into multiple age groups and vaccination statuses).
The structure of the desired model, as well as the parameter values and initial conditions, can be specified flexibly by the user in a no-code fashion. The pipeline allows for parameter values to change over time at discrete intervals, which can be used to specify time-dependent aspects of disease transmission and control (such as seasonality or vaccination campaigns).
The model is embedded within a meta-population structure, which consists of a series of distinct subpopulations (e.g. states, provinces, or other communities) in which the model structure is repeated, albeit with potentially different parameter values. The subpopulations can interact, either through the movement of individuals or the influence of individuals in one subpopulation on the transition rate of individuals in another ;
Within each subpopulation, the population is assumed to be well-mixed, meaning that interactions are assumed to be equally likely between any pair of individuals (since unique identities of individuals are not explicitly tracked). The same model structure can be simulated in a continuous-time deterministic or discrete-time stochastic manner ;
In addition to the variables described by the compartmental model, the model can track other observable variables (“outcomes”) that are functions of the basic model variables but do not themselves influence the dynamics (i.e., some portion of infections are reported as cases, depending on a testing rate). The model can be run iteratively to tune the values of certain parameters so that these outcome variables best match timeseries data provided by the user for a certain time period ;
Fitting is done using a Bayesian-like framework, where the user can specify the likelihood of observed outcomes in data given modeled outcomes, and the priors on any parameters to be fit. Multiple data streams (e.g., cases and deaths) can be fit simultaneously. A custom Markov Chain Monte Carlo method is used to sequentially propose and accept or reject parameter values based on the model fit to data, in a way that balances fit quality within each individual subpopulation with that of the total aggregate population, and that takes advantage of parallel computing environments.
The code is written in a combination of R and Python, and the vast majority of users only need to interact with the pipeline via the components written in R. It is structured in a modular fashion, such that individual components – such as the epidemic model, the observable variables, the population structure, or the parameters – can be edited or completely replaced without any handling of other parts of the code ;
When model simulation is combined with fitting to data, the code is designed to run most efficiently on a supercomputing cluster with many cores. We most commonly run the code on Amazon Web Services or on high-performance computers using SLURM. However, even relatively large models can be run efficiently on most personal computers. Typically, the memory of the machine will limit the number of compartments (i.e., variables) that can be included in the epidemic model, while the machine’s CPU will determine the speed at which each model run is completed and the number of iterations of the model that can be run during parameter searches when fitting the model to data. While the pipeline can be installed on any computer, it is sometime easier to use an Anaconda environment or the provided Docker container, where all the software dependencies (e.g., standardized R and Python versions along with required packages) are included, independent of the user’s local machine. All the code is maintained on our GitHub and shared with the GNU General Public License v3.0 license. It is build on top of a fully open-source software stack.
This documentation is organized as follows. The Model Description section describes the mathematical framework for the compartmental epidemic models that can be simulated forward in time by the pipeline. The Model Inference section describes the statistical framework for fitting the model to data. The Data and Parameter section describes the inputs the user must provide to the pipeline, in terms of the model structure and parameters, the population characteristics, the initial conditions, time-varying interventions, data to be fit, and more. The How to Run section provides concrete guidance on setting up and running the model and analyzing the output. The Quick Start Guide provides a simple example model setup. The Advanced section goes into more detail on specific features of the model and the code that are likely to only be of interest to users who want to run more complex models or data fitting routines or substantially edit the code. It includes a subsection describing each file and package used in the pipeline and their interactions during a model run.
Users who wish to jump to running the model themselves can see Quick Start Guide.
For questions about the pipeline or to report a bug, please use the “Issues” or "Discussions" feature on our GitHub.
flepiMoP is actively developed by its current contributors, including Joseph C Lemaitre, Sara L Loo, Emily Przykucki, Clifton McKee, Claire Smith, Sung-mok Jung, Koji Sato, Pengcheng Fang, Erica Carcelen, Alison Hill, Justin Lessler, and Shaun Truelove, affiliated with the ;
Department of Epidemiology, Gillings School of Global Public Health, University of North Carolina at Chapel Hill, Chapel Hill, NC, USA for (JCL, JL)
Johns Hopkins University International Vaccine Access Center, Department of International Health, Baltimore, MD, USA for (SLL, KJ, EC, ST)
Department of Epidemiology, Johns Hopkins Bloomberg School of Public Health, Baltimore, Maryland, USA for (CM, CS, JL, ST)
Carolina Population Center, University of North Carolina at Chapel Hill, Chapel Hill, NC, USA for (S-m.J, JL)
Institute for Computational Medicine, Johns Hopkins University, Baltimore, MD, USA for (AH).
The development of this model was supported by from funds the National Science Foundation (2127976
; ST, CPS, JK, ECL, AH), Centers for Disease Control and Prevention (200-2016-91781
; ST, CPS, JK, AH, JL, JCL, SL, CM, EC, KS, S-m.J), US Department of Health and Human Services / Department of Homeland Security (ST, CPS, JK, ECL, AH, JL), California Department of Public Health (ST, CPS, JK, ECL, JL), Johns Hopkins University (ST, CPS, JK, ECL, JL), Amazon Web Services (ST, CPS, JK, ECL, AH, JL, JCL), National Institutes of Health (R01GM140564
; JL, 5R01AI102939
; JCL), and the Swiss National Science Foundation (200021-172578
; JCL)
We need to also acknowledge past contributions to the development of the COVID Scenario Pipeline, which evolved into flepiMoP. These include contributions by Heramb Gupta, Kyra H. Grantz, Hannah R. Meredith, Stephen A. Lauer, Lindsay T. Keegan, Sam Shah, Josh Wills, Kathryn Kaminsky, Javier Perez-Saez, Joshua Kaminsky, and Elizabeth C. Lee.
We provide helper scripts to aid users in understanding model outputs and diagnosing simulations and iterations. These scripts may be set to run automatically after a model run, and are dependent on the model defined in the user's defined config file ;
The script postprocess_snapshot.R
requires the following command line inputs:
a user-defined config, $CONFIG_PATH
a run index, $FLEPI_RUN_INDEX
a path to the model output results, $FS_RESULTS_PATH
a path to the flepiMoP repository, $FLEPI_PATH
; an ;
a list of outputs to plot, $OUTPUTS
, by default the script provides diagnostics for the following model output file ;
Plots of hosp
output files show confidence intervals of model runs, against the provided ground truth data for inference runs, for each metapopulation node. hnpi
and snpi
plots provide violin plots of parameter values for each slot ;
Other scripts are included as more specific examples of post-processing, used for diagnostic tools. processing_diagnostics.R
scripts provides a detailed diagnosis of inference model runs and fits ;