| Title: | Simulate and Evaluate Targeted Interventions in Infectious Disease Outbreaks |
|---|---|
| Description: | Branching process simulation model of infectious disease transmission with flexible parameterisation of epidemiology and targeted interventions, including isolation, contact tracing and quarantine, to reduce transmission, together with functions to evaluate outbreak control. Introduced in Hellewell et al. (2020) <doi:10.1016/S2214-109X(20)30074-7>. |
| Authors: | Joel Hellewell [aut] (ORCID: <https://orcid.org/0000-0003-2683-0849>), Sam Abbott [aut] (ORCID: <https://orcid.org/0000-0001-8057-8037>), Amy Gimma [aut], Tim Lucas [aut], Sebastian Funk [aut], Adam Kucharski [aut], Hugo Gruson [ctb] (ORCID: <https://orcid.org/0000-0002-4094-1476>), Carl A. B. Pearson [aut, rev] (ORCID: <https://orcid.org/0000-0003-0701-7860>), Joshua W. Lambert [aut, cre] (ORCID: <https://orcid.org/0000-0001-5218-3046>) |
| Maintainer: | Joshua W. Lambert <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 1.0.0 |
| Built: | 2026-06-15 16:02:41 UTC |
| Source: | https://github.com/cran/ringbp |
Create a list of delay distributions to run the ringbp model
delay_opts( incubation_period, onset_to_isolation, latent_period = 0, onset_to_self_isolation = function(n) rep(Inf, n) )delay_opts( incubation_period, onset_to_isolation, latent_period = 0, onset_to_self_isolation = function(n) rep(Inf, n) )
incubation_period |
a |
onset_to_isolation |
a |
latent_period |
a non-negative If |
onset_to_self_isolation |
a By default |
A list with class <ringbp_delay_opts>.
delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) )delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) )
Create a list of event probabilities to run the ringbp model
event_prob_opts( asymptomatic, presymptomatic_transmission, symptomatic_traced, symptomatic_self_isolate = 0 )event_prob_opts( asymptomatic, presymptomatic_transmission, symptomatic_traced, symptomatic_self_isolate = 0 )
asymptomatic |
a |
presymptomatic_transmission |
a |
symptomatic_traced |
a A scalar is treated as a constant contact-tracing probability over the
whole simulation. A Only contacts whose infector is symptomatic are eligible for tracing
(see |
symptomatic_self_isolate |
a If |
A list with class <ringbp_event_prob_opts>.
event_prob_opts( asymptomatic = 0.1, presymptomatic_transmission = 0.5, symptomatic_traced = 0.2 ) # time-varying contact tracing ascertainment: programme activates # on day 30 and ascertains 50% event_prob_opts( asymptomatic = 0.1, presymptomatic_transmission = 0.5, symptomatic_traced = \(t) ifelse(t < 30, 0, 0.5) )event_prob_opts( asymptomatic = 0.1, presymptomatic_transmission = 0.5, symptomatic_traced = 0.2 ) # time-varying contact tracing ascertainment: programme activates # on day 30 and ascertains 50% event_prob_opts( asymptomatic = 0.1, presymptomatic_transmission = 0.5, symptomatic_traced = \(t) ifelse(t < 30, 0, 0.5) )
extinct_prob(): Calculate proportion of runs that have controlled outbreak
detect_extinct(): Calculate whether outbreaks went extinct or not
extinct_prob(scenario, extinction_week = NULL) detect_extinct(scenario, extinction_week = NULL)extinct_prob(scenario, extinction_week = NULL) detect_extinct(scenario, extinction_week = NULL)
scenario |
a |
extinction_week |
By default
If extinction occurs before the |
The data passed to scenario has to be produced by scenario_sim().
It cannot be produced by outbreak_model() as it requires the sim column,
which is only appended in scenario_sim().
Warning: the output from scenario_sim() contains an cap_cases
attribute which is used by extinct_prob() and detect_extinct(),
therefore if you modify the output of scenario_sim() before passing
to extinct_prob() be careful not to drop the attribute (e.g.
from subsetting the data.table).
extinct_prob(): a single numeric with the probability of extinction
detect_extinct(): a data.table, with two columns sim and extinct, for a binary
classification of whether the outbreak went extinct in each simulation
replicate. 1 is an outbreak that went extinct, 0 if not.
res <- scenario_sim( n = 10, initial_cases = 1, offspring = offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0.5, size = 1) ), delays = delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ), event_probs = event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.5, symptomatic_traced = 0.2 ), interventions = intervention_opts(quarantine = FALSE), sim = sim_opts(cap_max_days = 350, cap_cases = 4500) ) # calculate probability of extinction extinct_prob(res) # determine if each outbreak simulation replicate has gone extinct detect_extinct(res) # calculate extinction in the last 2 weeks of the simulated outbreak # (i.e. the penultimate and last week of the outbreak) extinct_prob(res, extinction_week = max(res$week) - 1) # calculate extinction as no new cases between weeks 12 and 16 of the outbreak extinct_prob(res, extinction_week = 12:16)res <- scenario_sim( n = 10, initial_cases = 1, offspring = offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0.5, size = 1) ), delays = delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ), event_probs = event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.5, symptomatic_traced = 0.2 ), interventions = intervention_opts(quarantine = FALSE), sim = sim_opts(cap_max_days = 350, cap_cases = 4500) ) # calculate probability of extinction extinct_prob(res) # determine if each outbreak simulation replicate has gone extinct detect_extinct(res) # calculate extinction in the last 2 weeks of the simulated outbreak # (i.e. the penultimate and last week of the outbreak) extinct_prob(res, extinction_week = max(res$week) - 1) # calculate extinction as no new cases between weeks 12 and 16 of the outbreak extinct_prob(res, extinction_week = 12:16)
Samples generation times from a skew-normal distribution based on relative
symptom onset times (symptom_onset_time - exposure_time), ensuring all
generation times are at least latent_period. The location parameter of the
skew-normal distribution is set to the relative symptom onset times.
incubation_to_generation_time( symptom_onset_time, exposure_time = rep(0, length(symptom_onset_time)), alpha, latent_period = 0 )incubation_to_generation_time( symptom_onset_time, exposure_time = rep(0, length(symptom_onset_time)), alpha, latent_period = 0 )
symptom_onset_time |
a positive |
exposure_time |
a non-negative |
alpha |
a |
latent_period |
a non-negative If |
a numeric vector of generation times of equal length to the vector
input to symptom_onset_time: the i-th element of the vector contains a
sample from the generation time distribution of an individual with
incubation period given by the i-th element of the symptom_onset_time
vector. The lower bound of the output generation time vector is set by the
latent_period, to prevent transmission before becoming infectious.
incubation_to_generation_time( symptom_onset_time = c(1, 2, 3, 4, 1), alpha = 2 )incubation_to_generation_time( symptom_onset_time = c(1, 2, 3, 4, 1), alpha = 2 )
Create a list of intervention settings to run the ringbp model
intervention_opts(quarantine = FALSE, test_sensitivity = 1)intervention_opts(quarantine = FALSE, test_sensitivity = 1)
quarantine |
a |
test_sensitivity |
a A scalar is treated as a constant test sensitivity over the whole
simulation. A Only symptomatic individuals that do not self-isolate are tested; a
false-negative result means the case is not isolated via the testing
pathway (see |
A list with class <ringbp_intervention_opts>.
# quarantine is not active (default) intervention_opts(quarantine = FALSE) # quarantine is active intervention_opts(quarantine = TRUE) # 20% of tests return a false-negative intervention_opts(test_sensitivity = 0.8) # time-varying test sensitivity, in the first 30 days of the outbreak # sensitivity is 0.5, then after 30 days, sensitivity improves to 0.8 intervention_opts( test_sensitivity = \(t) ifelse(t > 30, yes = 0.8, no = 0.5) )# quarantine is not active (default) intervention_opts(quarantine = FALSE) # quarantine is active intervention_opts(quarantine = TRUE) # 20% of tests return a false-negative intervention_opts(test_sensitivity = 0.8) # time-varying test sensitivity, in the first 30 days of the outbreak # sensitivity is 0.5, then after 30 days, sensitivity improves to 0.8 intervention_opts( test_sensitivity = \(t) ifelse(t > 30, yes = 0.8, no = 0.5) )
Create a list of offspring distributions to run the ringbp model
offspring_opts(community, isolated, asymptomatic = community)offspring_opts(community, isolated, asymptomatic = community)
community |
a |
isolated |
a |
asymptomatic |
a |
If asymptomatic is not provided it will be specified as the same as
community meaning transmission of subclinical cases to be equal to
clinical cases unless specified otherwise.
A list with class <ringbp_offspring_opts>.
# Negative binomial offspring distributions with: # Community R0 of 2.5 and dispersion of 0.16 # Isolated R0 of 0.5 and dispersion of 1 # Asymptomatic R0 of 2.5 and dispersion of 0.16 offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0.5, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 2.5, size = 0.16) )# Negative binomial offspring distributions with: # Community R0 of 2.5 and dispersion of 0.16 # Isolated R0 of 0.5 and dispersion of 1 # Asymptomatic R0 of 2.5 and dispersion of 0.16 offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0.5, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 2.5, size = 0.16) )
Run a single instance of the branching process model
outbreak_model( initial_cases, offspring, delays, event_probs, interventions, sim )outbreak_model( initial_cases, offspring, delays, event_probs, interventions, sim )
initial_cases |
a non-negative |
offspring |
a |
delays |
a |
event_probs |
a |
interventions |
a |
sim |
a |
data.table of cases by week, cumulative cases, and the effective
reproduction number of the outbreak. data.table columns are:
$week: numeric
$weekly_cases: numeric
$cumulative: numeric
$effective_r0: numeric
$cases_per_gen: list
set.seed(1) offspring <- offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0.5, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 2.5, size = 0.16) ) delays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.5, symptomatic_traced = 0.2 ) interventions <- intervention_opts(quarantine = FALSE) out <- outbreak_model( initial_cases = 1, offspring = offspring, delays = delays, event_probs = event_probs, interventions = interventions, sim = sim_opts() ) outset.seed(1) offspring <- offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0.5, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 2.5, size = 0.16) ) delays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.5, symptomatic_traced = 0.2 ) interventions <- intervention_opts(quarantine = FALSE) out <- outbreak_model( initial_cases = 1, offspring = offspring, delays = delays, event_probs = event_probs, interventions = interventions, sim = sim_opts() ) out
Set up initial cases for branching process
outbreak_setup(initial_cases, delays, event_probs, interventions)outbreak_setup(initial_cases, delays, event_probs, interventions)
initial_cases |
a non-negative |
delays |
a |
event_probs |
a |
interventions |
a |
data.table of cases in outbreak so far. data.table columns are:
$exposure: numeric
$asymptomatic: logical
$caseid: integer
$infector: numeric
$traced: logical
$onset: numeric
$new_cases: integer
$self_isolate: logical
$isolated_time: numeric
$sampled: logical
delays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.15, symptomatic_traced = 0 ) interventions <- intervention_opts() # generate initial cases case_data <- outbreak_setup( initial_cases = 5, delays = delays, event_probs = event_probs, interventions = interventions ) case_datadelays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.15, symptomatic_traced = 0 ) interventions <- intervention_opts() # generate initial cases case_data <- outbreak_setup( initial_cases = 5, delays = delays, event_probs = event_probs, interventions = interventions ) case_data
Move forward one generation in the branching process
outbreak_step(case_data, offspring, delays, event_probs, interventions)outbreak_step(case_data, offspring, delays, event_probs, interventions)
case_data |
a |
offspring |
a |
delays |
a |
event_probs |
a |
interventions |
a |
Each new case is assigned an isolation time (isolated_time) as the
earliest of up to three pathways; a case to which no pathway applies is
never isolated (isolated_time is Inf):
Self-isolation: a symptomatic case self-isolates with probability
symptomatic_self_isolate (from event_prob_opts()), entering isolation
an onset_to_self_isolation delay (from delay_opts()) after symptom
onset. Self-isolating cases are not tested.
Testing: a symptomatic case that does not self-isolate is tested and
returns a positive result with probability test_sensitivity (from
intervention_opts()), entering isolation an onset_to_isolation delay
after symptom onset. A false-negative result does not isolate the case
via this pathway.
Tracing: a case whose infector is symptomatic is traced with
probability symptomatic_traced (from event_prob_opts()). When
quarantine is active (from intervention_opts()) tracing is
exposure-based: a traced case is isolated when its infector is isolated,
regardless of its own symptom status. Without quarantine, only a traced
symptomatic case is isolated, and no earlier than its own symptom onset.
Self-isolation and testing are symptom-based, so asymptomatic cases are
isolated only via the tracing pathway, and only when quarantine is active.
A list with three elements:
$cases: a data.table with case data
$effective_r0: a numeric with the effective reproduction number
$cases_in_gen: a numeric with the number of new cases in that
generation
offspring <- offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 1.25, size = 0.16) ) delays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.15, symptomatic_traced = 0 ) interventions <- intervention_opts(quarantine = FALSE) # generate initial cases case_data <- outbreak_setup( initial_cases = 5, delays = delays, event_probs = event_probs, interventions = interventions ) case_data # generate next generation of cases out <- outbreak_step( case_data = case_data, offspring = offspring, delays = delays, event_probs = event_probs, interventions = interventions ) case_data <- out[[1]] case_dataoffspring <- offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 1.25, size = 0.16) ) delays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 1.65, scale = 4.28) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.15, symptomatic_traced = 0 ) interventions <- intervention_opts(quarantine = FALSE) # generate initial cases case_data <- outbreak_setup( initial_cases = 5, delays = delays, event_probs = event_probs, interventions = interventions ) case_data # generate next generation of cases out <- outbreak_step( case_data = case_data, offspring = offspring, delays = delays, event_probs = event_probs, interventions = interventions ) case_data <- out[[1]] case_data
Run a specified number of simulations with identical parameters
scenario_sim( n, initial_cases, offspring, delays, event_probs, interventions, sim )scenario_sim( n, initial_cases, offspring, delays, event_probs, interventions, sim )
n |
a positive |
initial_cases |
a non-negative |
offspring |
a |
delays |
a |
event_probs |
a |
interventions |
a |
sim |
a |
A data.table object returning the results for multiple simulations
using the same set of parameters. The table has columns
week: The week in the simulation.
weekly_cases: The number of new cases that week.
cumulative: The cumulative cases.
effective_r0: The effective reproduction rate for the whole simulation
cases_per_gen: A list column with the cases per generation. This is repeated each row.
sim: Index column for which simulation.
offspring <- offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 2.5, size = 0.16) ) delays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 2.5, scale = 5) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.3, symptomatic_traced = 0 ) interventions <- intervention_opts(quarantine = TRUE) sim <- sim_opts( cap_max_days = 365, cap_cases = 2000 ) res <- scenario_sim( n = 5, initial_cases = 5, offspring = offspring, delays = delays, event_probs = event_probs, interventions = interventions, sim = sim ) resoffspring <- offspring_opts( community = \(n) rnbinom(n = n, mu = 2.5, size = 0.16), isolated = \(n) rnbinom(n = n, mu = 0, size = 1), asymptomatic = \(n) rnbinom(n = n, mu = 2.5, size = 0.16) ) delays <- delay_opts( incubation_period = \(n) rweibull(n = n, shape = 2.32, scale = 6.49), onset_to_isolation = \(n) rweibull(n = n, shape = 2.5, scale = 5) ) event_probs <- event_prob_opts( asymptomatic = 0, presymptomatic_transmission = 0.3, symptomatic_traced = 0 ) interventions <- intervention_opts(quarantine = TRUE) sim <- sim_opts( cap_max_days = 365, cap_cases = 2000 ) res <- scenario_sim( n = 5, initial_cases = 5, offspring = offspring, delays = delays, event_probs = event_probs, interventions = interventions, sim = sim ) res
Create a list of simulation control options for the ringbp model
sim_opts(cap_max_days = 350, cap_cases = 5000)sim_opts(cap_max_days = 350, cap_cases = 5000)
cap_max_days |
a positive |
cap_cases |
a positive |
A list with class <ringbp_sim_opts>.
# default simulation control options sim_opts() # specifying custom simulation control options sim_opts( cap_max_days = 140, cap_cases = 1000 )# default simulation control options sim_opts() # specifying custom simulation control options sim_opts( cap_max_days = 140, cap_cases = 1000 )