Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalise distributions input into functions #84

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Generated by roxygen2: do not edit by hand

export(detect_extinct)
export(dist_setup)
export(extinct_prob)
export(inf_fn)
export(outbreak_model)
Expand All @@ -18,7 +17,6 @@ importFrom(future.apply,future_lapply)
importFrom(purrr,map2)
importFrom(purrr,map2_dbl)
importFrom(purrr,map_lgl)
importFrom(purrr,partial)
importFrom(purrr,safely)
importFrom(sn,rsn)
importFrom(stats,as.formula)
Expand Down
30 changes: 4 additions & 26 deletions R/aux_functions.R
Original file line number Diff line number Diff line change
@@ -1,25 +1,3 @@
#' Create partial function to sample from gamma distributions
#' @author Joel Hellewell
#' @param dist_shape a positive `numeric` scalar: shape parameter of Weibull
#' distribution
#' @param dist_scale a positive `numeric` scalar: scale parameter of Weibull
#' distribution
#'
#' @return partial function that takes a numeric argument for number of samples
#' @export
#' @importFrom purrr partial
#'
#' @examples
#' incfn <- dist_setup(dist_shape = 2.32, dist_scale = 6.49)
#' incfn(5)
dist_setup <- function(dist_shape = NULL, dist_scale = NULL) {
out <- purrr::partial(rweibull,
shape = dist_shape,
scale = dist_scale)
return(out)
}


#' Samples the serial interval for given incubation period samples
#'
#' @param inc_samp a positive `numeric` vector: samples from the incubation
Expand Down Expand Up @@ -63,8 +41,8 @@ inf_fn <- function(inc_samp = NULL, k = NULL) {
#' r0community = 2.5,
#' disp.com = 0.16,
#' disp.iso = 1,
#' delay_shape = 1.65,
#' delay_scale = 4.28,
#' onset_to_isolation = \(x) stats::rweibull(n = x, shape = 1.65, scale = 4.28),
#' incubation_period = \(x) stats::rweibull(n = x, shape = 2.322737, scale = 6.492272),
#' k = 0,
#' quarantine = FALSE
#' )
Expand Down Expand Up @@ -107,8 +85,8 @@ extinct_prob <- function(outbreak_df_week = NULL, cap_cases = NULL, week_range
#' r0community = 2.5,
#' disp.com = 0.16,
#' disp.iso = 1,
#' delay_shape = 1.65,
#' delay_scale = 4.28,
#' onset_to_isolation = \(x) stats::rweibull(n = x, shape = 1.65, scale = 4.28),
#' incubation_period = \(x) stats::rweibull(n = x, shape = 2.322737, scale = 6.492272),
#' k = 0,
#' quarantine = FALSE
#' )
Expand Down
38 changes: 16 additions & 22 deletions R/outbreak_model.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@
#' `TRUE` then traced contacts are isolated before symptom onset
#' @param prop.asym a nonnegative `numeric` scalar: proportion of cases that
#' are completely asymptomatic (sublinical) (between 0 and 1)
#' @param delay_shape a positive `numeric` scalar: shape parameter of delay
#' distribution
#' @param delay_scale a positive `numeric` scalar: scale parameter of delay
#' distribution
#' @param onset_to_isolation a `function`: a random number generating
#' `function` that accepts a single `integer` argument specifying the
#' length of the `function` output.
#' @param incubation_period a `function`: a random number generating
#' `function` that samples from incubation period distribution, the
#' `function` accepts a single `integer` argument specifying the number of
#' times to sample the incubation period (i.e. length of the `function`
#' output).
#' @param num.initial.cases a nonnegative `integer` scalar: number of initial
#' or starting cases which are all assumed to be missed.
#' @param cap_cases a positive `integer` scalar: number of cumulative cases at
Expand Down Expand Up @@ -59,8 +63,8 @@
#' disp.com = 0.16,
#' disp.subclin = 0.16,
#' k = 0,
#' delay_shape = 1.65,
#' delay_scale = 4.28,
#' onset_to_isolation = \(x) stats::rweibull(n = x, shape = 1.65, scale = 4.28),
#' incubation_period = \(x) stats::rweibull(n = x, shape = 2.32, scale = 6.49),
#' prop.asym = 0,
#' quarantine = FALSE
#' )
Expand All @@ -70,18 +74,8 @@ outbreak_model <- function(num.initial.cases = NULL, prop.ascertain = NULL,
r0isolated = NULL, r0community = NULL,
r0subclin = NULL, disp.iso = NULL,
disp.com = NULL, disp.subclin = NULL,
k, delay_shape = NULL,
delay_scale = NULL, prop.asym = NULL,
quarantine = NULL) {

# Set up functions to sample from distributions
# incubation period sampling function
incfn <- dist_setup(dist_shape = 2.322737,
dist_scale = 6.492272)
# incfn <- dist_setup(dist_shape = 3.303525,dist_scale = 6.68849) # incubation function for ECDC run
# onset to isolation delay sampling function
delayfn <- dist_setup(delay_shape,
delay_scale)
k, onset_to_isolation, incubation_period,
prop.asym = NULL, quarantine = NULL) {

# Set initial values for loop indices
total.cases <- num.initial.cases
Expand All @@ -90,9 +84,9 @@ outbreak_model <- function(num.initial.cases = NULL, prop.ascertain = NULL,

# Initial setup
case_data <- outbreak_setup(num.initial.cases = num.initial.cases,
incfn = incfn,
incubation_period = incubation_period,
prop.asym = prop.asym,
delayfn = delayfn,
onset_to_isolation = onset_to_isolation,
k = k)

# Preallocate
Expand All @@ -110,8 +104,8 @@ outbreak_model <- function(num.initial.cases = NULL, prop.ascertain = NULL,
r0isolated = r0isolated,
r0community = r0community,
r0subclin = r0subclin,
incfn = incfn,
delayfn = delayfn,
incubation_period = incubation_period,
onset_to_isolation = onset_to_isolation,
prop.ascertain = prop.ascertain,
k = k,
quarantine = quarantine,
Expand Down
14 changes: 7 additions & 7 deletions R/outbreak_setup.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@
#'
#' @examples
#' # incubation period sampling function
#' incfn <- dist_setup(dist_shape = 2.32, dist_scale = 6.49)
#' incubation_period <- \(x) stats::rweibull(n = x, shape = 2.32, scale = 6.49)
#' # delay distribution sampling function
#' delayfn <- dist_setup(dist_shape = 1.65, dist_scale = 4.28)
#' onset_to_isolation <- \(x) stats::rweibull(n = x, shape = 1.65, scale = 4.28)
#' out <- outbreak_setup(
#' num.initial.cases = 1,
#' incfn = incfn,
#' delayfn = delayfn,
#' incubation_period = incubation_period,
#' onset_to_isolation = onset_to_isolation,
#' k = 1.95,
#' prop.asym = 0
#' )
#' out
outbreak_setup <- function(num.initial.cases, incfn, delayfn, k, prop.asym) {
outbreak_setup <- function(num.initial.cases, incubation_period, onset_to_isolation, k, prop.asym) {
# Set up table of initial cases
inc_samples <- incfn(num.initial.cases)
inc_samples <- incubation_period(num.initial.cases)

case_data <- data.table(exposure = rep(0, num.initial.cases), # Exposure time of 0 for all initial cases
asym = as.logical(rbinom(num.initial.cases, 1, prop.asym)),
Expand All @@ -45,7 +45,7 @@ outbreak_setup <- function(num.initial.cases, incfn, delayfn, k, prop.asym) {
new_cases = NA)

# set isolation time for cluster to minimum time of onset of symptoms + draw from delay distribution
case_data <- case_data[, isolated_time := onset + delayfn(1)
case_data <- case_data[, isolated_time := onset + onset_to_isolation(1)
][, isolated := FALSE]

case_data$isolated_time[case_data$asym] <- Inf
Expand Down
31 changes: 15 additions & 16 deletions R/outbreak_step.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
#' @param case_data a `data.table`: cases in outbreak so far; initially
#' generated by [outbreak_setup()]
#' @inheritParams outbreak_model
#' @param incfn a `function` that samples from incubation period Weibull
#' distribution; generated using [dist_setup()]
#' @param delayfn a `function` that samples from the onset-to-hospitalisation
#' delay Weibull distribution; generated using [dist_setup()]
#' @param onset_to_isolation a `function` that samples from the
#' onset-to-hospitalisation delay Weibull distribution
#'
#' @importFrom data.table data.table rbindlist
#' @importFrom purrr map2 map2_dbl map_lgl
Expand All @@ -24,14 +22,14 @@
#'
#' @examples
#' # incubation period sampling function
#' incfn <- dist_setup(dist_shape = 2.32, dist_scale = 6.49)
#' incubation_period <- \(x) stats::rweibull(n = x, shape = 2.32, scale = 6.49)
#' # delay distribution sampling function
#' delayfn <- dist_setup(dist_shape = 1.65, dist_scale = 4.28)
#' onset_to_isolation <- \(x) stats::rweibull(n = x, shape = 1.65, scale = 4.28)
#' # generate initial cases
#' case_data <- outbreak_setup(
#' num.initial.cases = 5,
#' incfn = incfn,
#' delayfn = delayfn,
#' incubation_period = incubation_period,
#' onset_to_isolation = onset_to_isolation,
#' k = 1.95,
#' prop.asym = 0
#' )
Expand All @@ -46,8 +44,8 @@
#' r0subclin = 1.25,
#' r0community = 2.5,
#' prop.asym = 0,
#' incfn = incfn,
#' delayfn = delayfn,
#' incubation_period = incubation_period,
#' onset_to_isolation = onset_to_isolation,
#' prop.ascertain = 0,
#' k = 1.95,
#' quarantine = FALSE
Expand All @@ -56,9 +54,10 @@
#' case_data
outbreak_step <- function(case_data = NULL, disp.iso = NULL, disp.com = NULL,
r0isolated = NULL, r0community = NULL,
prop.asym = NULL, incfn = NULL, delayfn = NULL,
prop.ascertain = NULL, k = NULL, quarantine = NULL,
r0subclin = NULL, disp.subclin = NULL) {
prop.asym = NULL, incubation_period = NULL,
onset_to_isolation = NULL, prop.ascertain = NULL,
k = NULL, quarantine = NULL, r0subclin = NULL,
disp.subclin = NULL) {

# For each case in case_data, draw new_cases from a negative binomial distribution
# with an R0 and dispersion dependent on if isolated=TRUE
Expand Down Expand Up @@ -91,7 +90,7 @@ outbreak_step <- function(case_data = NULL, disp.iso = NULL, disp.com = NULL,
}

# Compile a data.table for all new cases, new_cases is the amount of people that each infector has infected
inc_samples <- incfn(total_new_cases)
inc_samples <- incubation_period(total_new_cases)

prob_samples <- data.table(
# time when new cases were exposed, a draw from serial interval based on infector's onset
Expand Down Expand Up @@ -137,11 +136,11 @@ outbreak_step <- function(case_data = NULL, disp.iso = NULL, disp.com = NULL,
prob_samples[, isolated_time := ifelse(vect_isTRUE(asym), Inf,
# If you are not asymptomatic, but you are missed,
# you are isolated at your symptom onset
ifelse(vect_isTRUE(missed), onset + delayfn(1),
ifelse(vect_isTRUE(missed), onset + onset_to_isolation(1),
# If you are not asymptomatic and you are traced,
# you are isolated at max(onset,infector isolation time) # max(onset,infector_iso_time)
ifelse(!vect_isTRUE(rep(quarantine, total_new_cases)),
pmin(onset + delayfn(1), pmax(onset, infector_iso_time)),
pmin(onset + onset_to_isolation(1), pmax(onset, infector_iso_time)),
infector_iso_time)))]


Expand Down
9 changes: 5 additions & 4 deletions R/parameter_sweep.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#' expand.grid(
#' delay_group = list(data.table(
#' delay = c("SARS", "Wuhan"),
#' delay_shape = c(1.651524, 2.305172),
#' delay_scale = c(4.287786, 9.483875)
#' onset_to_isolation = c(
#' \(x) stats::rweibull(n = x, shape = 1.651524, scale = 4.287786),
#' \(x) stats::rweibull(n = x, shape = 2.305172, scale = 9.483875)
#' )
#' )),
#' k_group = list(data.table(
#' theta = c("<1%", "15%", "30%"),
Expand Down Expand Up @@ -96,8 +98,7 @@ parameter_sweep <- function(scenarios = NULL, samples = 1,
r0subclin = ifelse(
"subclin_R0" %in% names(scenarios), x$subclin_R0, x$index_R0),
k = x$k,
delay_shape = x$delay_shape,
delay_scale = x$delay_scale,
onset_to_isolation = x$onset_to_isolation,
prop.ascertain = x$control_effectiveness,
quarantine = x$quarantine,
prop.asym = x$prop.asym
Expand Down
13 changes: 7 additions & 6 deletions R/scenario_sim.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,17 @@
#' disp.iso = 1,
#' disp.com = 0.16,
#' k = 0.7,
#' delay_shape = 2.5,
#' delay_scale = 5,
#' onset_to_isolation = \(x) stats::rweibull(n = x, shape = 2.5, scale = 5),
#' incubation_period = \(x) stats::rweibull(n = x, shape = 2.32, scale = 6.49),
#' prop.asym = 0,
#' prop.ascertain = 0
#' )
#' res
scenario_sim <- function(n.sim, prop.ascertain, cap_max_days, cap_cases,
r0isolated, r0community, disp.iso, disp.com, k,
delay_shape, delay_scale, num.initial.cases, prop.asym,
quarantine, r0subclin = NULL, disp.subclin = NULL) {
onset_to_isolation, incubation_period,
num.initial.cases, prop.asym, quarantine,
r0subclin = NULL, disp.subclin = NULL) {

# Set infectiousness of subclinical cases to be equal to clinical cases unless specified otherwise
if(is.null(r0subclin)) {
Expand All @@ -65,8 +66,8 @@ scenario_sim <- function(n.sim, prop.ascertain, cap_max_days, cap_cases,
disp.subclin = disp.subclin,
disp.iso = disp.iso,
disp.com = disp.com,
delay_shape = delay_shape,
delay_scale = delay_scale,
onset_to_isolation = onset_to_isolation,
incubation_period = incubation_period,
k = k,
prop.asym = prop.asym,
quarantine = quarantine))
Expand Down
4 changes: 2 additions & 2 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ res <- scenario_sim(
r0community = 2.5, ## non-isolated individuals have R0 of 2.5
disp.com = 0.16, ## dispersion parameter in the community
disp.iso = 1, ## dispersion parameter of those isolated
delay_shape = 1.651524, ## shape parameter of time from onset to isolation
delay_scale = 4.287786, ## scale parameter of time from onset to isolation
onset_to_isolation = \(x) stats::rweibull(n = x, shape = 1.651524, scale = 4.287786), ## time from onset to isolation
incubation_period = \(x) stats::rweibull(n = x, shape = 2.322737, scale = 6.492272), ## incubation period
k = 0, ## skew of generation interval to be beyond onset of symptoms
quarantine = FALSE ## whether quarantine is in effect
)
Expand Down
1 change: 0 additions & 1 deletion _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ reference:
- title: Helper functions
- subtitle: Probability distribution manipulation
contents:
- dist_setup
- inf_fn
- subtitle: Loop wrappers for scenario modelling
contents:
Expand Down
4 changes: 2 additions & 2 deletions man/detect_extinct.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 0 additions & 28 deletions man/dist_setup.Rd

This file was deleted.

4 changes: 2 additions & 2 deletions man/extinct_prob.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading