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

Replace contact interval with infectious period #96

Merged
merged 7 commits into from
Apr 5, 2024
Merged
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
4 changes: 2 additions & 2 deletions R/checkers.R
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
#' @keywords internal
.check_sim_input <- function(sim_type = c("linelist", "contacts", "outbreak"),
contact_distribution,
contact_interval,
infect_period,
prob_infect,
outbreak_start_date,
outbreak_size,
Expand All @@ -133,7 +133,7 @@

checkmate::assert_number(prob_infect, lower = 0, upper = 1)
.check_func_req_args(contact_distribution)
.check_func_req_args(contact_interval)
.check_func_req_args(infect_period)
checkmate::assert_date(outbreak_start_date)
checkmate::assert_integerish(outbreak_size, lower = 1, len = 2)

Expand Down
16 changes: 8 additions & 8 deletions R/sim_contacts.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,20 @@
#' prob_distribution_params = c(mean = 2)
#' )
#'
#' contact_interval <- epiparameter::epidist(
#' infect_period <- epiparameter::epidist(
#' disease = "COVID-19",
#' epi_dist = "contact interval",
#' epi_dist = "infectious period",
#' prob_distribution = "gamma",
#' prob_distribution_params = c(shape = 1, scale = 1)
#' )
#'
#' contacts <- sim_contacts(
#' contact_distribution = contact_distribution,
#' contact_interval = contact_interval,
#' infect_period = infect_period,
#' prob_infect = 0.5
#' )
sim_contacts <- function(contact_distribution,
contact_interval,
infect_period,
prob_infect,
outbreak_start_date = as.Date("2023-01-01"),
outbreak_size = c(10, 1e4),
Expand All @@ -47,17 +47,17 @@ sim_contacts <- function(contact_distribution,
# check and convert distribution to func if needed before .check_sim_input()
stopifnot(
"Input delay distributions need to be either functions or <epidist>" =
inherits(contact_interval, c("function", "epidist"))
inherits(infect_period, c("function", "epidist"))
)
contact_distribution <- as.function(
contact_distribution, func_type = "density"
)
contact_interval <- as.function(contact_interval, func_type = "generate")
infect_period <- as.function(infect_period, func_type = "generate")

.check_sim_input(
sim_type = "contacts",
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = prob_infect,
outbreak_start_date = outbreak_start_date,
outbreak_size = outbreak_size,
Expand All @@ -75,7 +75,7 @@ sim_contacts <- function(contact_distribution,
contacts <- .sim_internal(
sim_type = "contacts",
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = prob_infect,
outbreak_start_date = outbreak_start_date,
outbreak_size = outbreak_size,
Expand Down
4 changes: 2 additions & 2 deletions R/sim_internal.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#' @keywords internal
.sim_internal <- function(sim_type = c("linelist", "contacts", "outbreak"),
contact_distribution,
contact_interval,
infect_period,
prob_infect,
onset_to_hosp = NULL,
onset_to_death = NULL,
Expand All @@ -36,7 +36,7 @@
while (num_cases < min(outbreak_size)) {
.data <- .sim_network_bp(
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = prob_infect,
max_outbreak_size = max(outbreak_size),
config = config
Expand Down
30 changes: 16 additions & 14 deletions R/sim_linelist.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
#' the contact distribution. This is any discrete density function that
#' produces non-negative integers (including zero, \eqn{\mathbb{N}_0}) for the
#' number of contacts per infection.
#' @param contact_interval An `<epidist>` object or anonymous function for
#' the contact interval. This is analogous to the serial interval or generation
#' time, but defines the time interval between an individual being
#' infected/infectious (in the simulation the latency period is assumed to be
#' zero) and having contact with another susceptible individual.
#' @param infect_period An `<epidist>` object or anonymous function for
#' the infectious period. This defines the duration from becoming infectious
#' to no longer infectious. In the simulation, individuals are assumed to
#' become infectious immediately after being infected (the latency period is
#' assumed to be zero). The time intervals between an infected individual and
#' their contacts are assumed to be uniformly distributed within the
#' infectious period.
#' @param prob_infect A single `numeric` for the probability of a secondary
#' contact being infected by an infected primary contact.
#' @param onset_to_hosp An `<epidist>` object or anonymous function for
Expand Down Expand Up @@ -93,9 +95,9 @@
#' prob_distribution_params = c(mean = 2)
#' )
#'
#' contact_interval <- epiparameter::epidist(
#' infect_period <- epiparameter::epidist(
#' disease = "COVID-19",
#' epi_dist = "contact interval",
#' epi_dist = "infectious period",
#' prob_distribution = "gamma",
#' prob_distribution_params = c(shape = 1, scale = 1)
#' )
Expand All @@ -116,7 +118,7 @@
#' # example with single hospitalisation risk for entire population
#' linelist <- sim_linelist(
#' contact_distribution = contact_distribution,
#' contact_interval = contact_interval,
#' infect_period = infect_period,
#' prob_infect = 0.5,
#' onset_to_hosp = onset_to_hosp,
#' onset_to_death = onset_to_death,
Expand All @@ -134,15 +136,15 @@
#' )
#' linelist <- sim_linelist(
#' contact_distribution = contact_distribution,
#' contact_interval = contact_interval,
#' infect_period = infect_period,
#' prob_infect = 0.5,
#' onset_to_hosp = onset_to_hosp,
#' onset_to_death = onset_to_death,
#' hosp_risk = age_dep_hosp_risk
#' )
#' head(linelist)
sim_linelist <- function(contact_distribution,
contact_interval,
infect_period,
prob_infect,
onset_to_hosp,
onset_to_death,
Expand All @@ -164,21 +166,21 @@ sim_linelist <- function(contact_distribution,
stopifnot(
"Input delay distributions need to be either functions or <epidist>" =
inherits(contact_distribution, c("function", "epidist")) &&
inherits(contact_interval, c("function", "epidist")) &&
inherits(infect_period, c("function", "epidist")) &&
inherits(onset_to_hosp, c("function", "epidist")) &&
inherits(onset_to_death, c("function", "epidist"))
)
contact_distribution <- as.function(
contact_distribution, func_type = "density"
)
contact_interval <- as.function(contact_interval, func_type = "generate")
infect_period <- as.function(infect_period, func_type = "generate")
onset_to_hosp <- as.function(onset_to_hosp, func_type = "generate")
onset_to_death <- as.function(onset_to_death, func_type = "generate")

.check_sim_input(
sim_type = "linelist",
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = prob_infect,
outbreak_start_date = outbreak_start_date,
outbreak_size = outbreak_size,
Expand Down Expand Up @@ -226,7 +228,7 @@ sim_linelist <- function(contact_distribution,
linelist <- .sim_internal(
sim_type = "linelist",
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = prob_infect,
onset_to_hosp = onset_to_hosp,
onset_to_death = onset_to_death,
Expand Down
20 changes: 14 additions & 6 deletions R/sim_network_bp.R
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
#' Simulate a branching process on a infinite network where the contact
#' distribution provides a function to sample the number of contacts of each
#' individual in the simulation. Each contact is then infected with the
#' probability of infection. The time between each infection is determined
#' by the contact interval function.
#' probability of infection. The time between each contact is assumed to be
#' evenly distributed across the infectious period of the infected individual,
#' and is independent of whether the contact becomes infected.
#'
#' @details
#' The contact distribution sampled takes the network effect
Expand All @@ -22,7 +23,7 @@
#' @return A `<data.frame>` with the contact and transmission chain data.
#' @keywords internal
.sim_network_bp <- function(contact_distribution,
contact_interval,
infect_period,
prob_infect,
max_outbreak_size,
config) {
Expand Down Expand Up @@ -92,9 +93,16 @@
infect <- stats::rbinom(n = contacts[i], size = 1, prob = prob_infect)
infected[vec_idx] <- as.numeric(infect)

# add delay time
time[vec_idx] <- contact_interval(length(vec_idx)) +
time[ancestor_idx[i]]
# compute infectious period for ancestor
contact_infect_period <- infect_period(1)

# assume contacts are evenly distributed across the infectious period
contact_times <- stats::runif(
n = length(vec_idx),
min = 0,
max = contact_infect_period
)
time[vec_idx] <- contact_times + time[ancestor_idx[i]]
}
}
ancestor_idx <- setdiff(which(infected == 1), prev_ancestors)
Expand Down
16 changes: 8 additions & 8 deletions R/sim_outbreak.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
#' prob_distribution_params = c(mean = 2)
#' )
#'
#' contact_interval <- epiparameter::epidist(
#' infect_period <- epiparameter::epidist(
#' disease = "COVID-19",
#' epi_dist = "serial interval",
#' epi_dist = "infectious period",
#' prob_distribution = "gamma",
#' prob_distribution_params = c(shape = 1, scale = 1)
#' )
Expand All @@ -48,13 +48,13 @@
#'
#' outbreak <- sim_outbreak(
#' contact_distribution = contact_distribution,
#' contact_interval = contact_interval,
#' infect_period = infect_period,
#' prob_infect = 0.5,
#' onset_to_hosp = onset_to_hosp,
#' onset_to_death = onset_to_death
#' )
sim_outbreak <- function(contact_distribution,
contact_interval,
infect_period,
prob_infect,
onset_to_hosp,
onset_to_death,
Expand All @@ -81,21 +81,21 @@ sim_outbreak <- function(contact_distribution,
stopifnot(
"Input delay distributions need to be either functions or <epidist>" =
inherits(contact_distribution, c("function", "epidist")) &&
inherits(contact_interval, c("function", "epidist")) &&
inherits(infect_period, c("function", "epidist")) &&
inherits(onset_to_hosp, c("function", "epidist")) &&
inherits(onset_to_death, c("function", "epidist"))
)
contact_distribution <- as.function(
contact_distribution, func_type = "density"
)
contact_interval <- as.function(contact_interval, func_type = "generate")
infect_period <- as.function(infect_period, func_type = "generate")
onset_to_hosp <- as.function(onset_to_hosp, func_type = "generate")
onset_to_death <- as.function(onset_to_death, func_type = "generate")

.check_sim_input(
sim_type = "outbreak",
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = prob_infect,
outbreak_start_date = outbreak_start_date,
outbreak_size = outbreak_size,
Expand Down Expand Up @@ -144,7 +144,7 @@ sim_outbreak <- function(contact_distribution,
outbreak <- .sim_internal(
sim_type = "outbreak",
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = prob_infect,
onset_to_hosp = onset_to_hosp,
onset_to_death = onset_to_death,
Expand Down
16 changes: 8 additions & 8 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ library(simulist)
library(epiparameter)
```

The line list simulation requires that we define a contact distribution, contact interval, onset-to-hospitalisation delay, and onset-to-death delay. We can load these from the library of epidemiological parameters in the `{epiparameter}` R package if available, or if these are not in the database yet (such as the contact interval for COVID-19) we can define them ourselves.
The line list simulation requires that we define a contact distribution, period of infectiousness, onset-to-hospitalisation delay, and onset-to-death delay. We can load these from the library of epidemiological parameters in the `{epiparameter}` R package if available, or if these are not in the database yet (such as the contact distribution for COVID-19) we can define them ourselves.

```{r create-epidists}
# create COVID-19 contact distribution
Expand All @@ -61,10 +61,10 @@ contact_distribution <- epiparameter::epidist(
prob_distribution_params = c(mean = 2)
)

# create COVID-19 contact interval
contact_interval <- epiparameter::epidist(
# create COVID-19 infectious period
infect_period <- epiparameter::epidist(
disease = "COVID-19",
epi_dist = "contact interval",
epi_dist = "infectious period",
prob_distribution = "gamma",
prob_distribution_params = c(shape = 1, scale = 1)
)
Expand Down Expand Up @@ -92,7 +92,7 @@ To simulate a line list for COVID-19 with an Poisson contact distribution with a
set.seed(1)
linelist <- sim_linelist(
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = 0.5,
onset_to_hosp = onset_to_hosp,
onset_to_death = onset_to_death
Expand All @@ -105,7 +105,7 @@ In this example, the line list is simulated using the default values (see `?sim_
```{r sim-linelist-diff-args}
linelist <- sim_linelist(
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = 0.5,
onset_to_hosp = onset_to_hosp,
onset_to_death = onset_to_death,
Expand All @@ -120,7 +120,7 @@ To simulate a table of contacts of cases (i.e. to reflect a contact tracing data
```{r, sim-contacts}
contacts <- sim_contacts(
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = 0.5
)
head(contacts)
Expand All @@ -131,7 +131,7 @@ If both the line list and contacts table are required, they can be jointly simul
```{r, sim-outbreak}
outbreak <- sim_outbreak(
contact_distribution = contact_distribution,
contact_interval = contact_interval,
infect_period = infect_period,
prob_infect = 0.5,
onset_to_hosp = onset_to_hosp,
onset_to_death = onset_to_death
Expand Down
Loading
Loading