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

Implement interventions on model rates #91

Merged
merged 62 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
1ab7208
WIP interventions on rates
pratikunterwegs Aug 18, 2023
ca435c5
Use unordered_map, temp params map for efficient access
pratikunterwegs Aug 21, 2023
d1dded0
Document and add constructor for C++ intervention class
pratikunterwegs Aug 21, 2023
ec54e17
C++ fn to convert interventions from R
pratikunterwegs Aug 21, 2023
252f9f2
Update fn for applying interventions on rate params
pratikunterwegs Aug 21, 2023
4b246fb
Remove infection param fn, superseded by translate_intervention
pratikunterwegs Aug 21, 2023
020e5b2
Fn check_args_default adds dummy interv on beta for null
pratikunterwegs Aug 21, 2023
39fd190
Update intervention checking default args
pratikunterwegs Aug 21, 2023
6f29e9c
Update intervention prep for default args
pratikunterwegs Aug 21, 2023
ba4bef5
Update .epidemic_default_cpp()
pratikunterwegs Aug 21, 2023
00c7f5c
Update epidemic_default_cpp and RcppExports
pratikunterwegs Aug 21, 2023
0094d7f
R implementation, intervention on rates
pratikunterwegs Aug 21, 2023
edfef6c
Add checks for args to default model
pratikunterwegs Aug 21, 2023
f76ed20
Update test files
pratikunterwegs Aug 21, 2023
61acf16
Update vignettes and docs for interventions on rates
pratikunterwegs Aug 21, 2023
138240d
Automatic readme update
actions-user Aug 21, 2023
679d7ce
Intervention constructor allows sub-classes
pratikunterwegs Aug 22, 2023
07b6f03
Constructors for contacts and rate interventions
pratikunterwegs Aug 22, 2023
6f1e372
Update fn intervention() with type and reduction arg
pratikunterwegs Aug 22, 2023
301d370
Validator for contacts intervention
pratikunterwegs Aug 22, 2023
7c4cf43
Validator for rate interventions
pratikunterwegs Aug 22, 2023
842e595
Remove redundant example for is_intervention
pratikunterwegs Aug 22, 2023
cc01dd3
Fns to check for contacts and rate interventions
pratikunterwegs Aug 22, 2023
f653026
Rename no_intervention() to no_contacts_intervention()
pratikunterwegs Aug 22, 2023
4763c9e
Print methods for rate and contacts interventions
pratikunterwegs Aug 22, 2023
0ffd744
Update format method for intervention subclasses
pratikunterwegs Aug 22, 2023
0009a90
Update as.intervention() for intervention subclasses
pratikunterwegs Aug 22, 2023
cc7201a
Update `c()` method for contacts interventions
pratikunterwegs Aug 22, 2023
1dce52a
Add `c()` method for rate interventions
pratikunterwegs Aug 22, 2023
437f97c
Rename cumulative_intervention() to cumulative_contacts_intervention()
pratikunterwegs Aug 22, 2023
3b11756
Call cumulative_contacts_intervention() in CM interv
pratikunterwegs Aug 22, 2023
3f8b8a8
Add fn for cumulative rate interventions
pratikunterwegs Aug 22, 2023
339014f
Update fn for interventions on rates
pratikunterwegs Aug 22, 2023
8504a9c
Fn for null intervention on rates
pratikunterwegs Aug 22, 2023
4a78923
Update fns to account for intervention subclasses
pratikunterwegs Aug 22, 2023
440cd11
Update tests for new intervention subclasses
pratikunterwegs Aug 22, 2023
c5bfd87
Update vignettes with default model for interv subclasses
pratikunterwegs Aug 22, 2023
0805983
Update NAMESPACE, WORDLIST, and Rd files
pratikunterwegs Aug 22, 2023
51ca290
Update assert_intervention() for subclasses
pratikunterwegs Aug 22, 2023
ff5384e
Fn check_args_default handles missing contact interv
pratikunterwegs Aug 22, 2023
4f094c7
Fns for is_*() updated to remove intervention expectation
pratikunterwegs Aug 22, 2023
9db6d45
WIP vignette on modelling rate interventions
pratikunterwegs Aug 22, 2023
f1f64c7
Remove unnecessary concat
pratikunterwegs Aug 22, 2023
def43eb
C++ rate_intervention struct holds double vectors
pratikunterwegs Aug 23, 2023
fb98e27
Rename C++ translate_intervs() to rate_intervs_cpp()
pratikunterwegs Aug 23, 2023
40f5483
Rename cumulative_intervs to cumulative_contacts_intervs()
pratikunterwegs Aug 23, 2023
eca6d04
C++ fn for cumulative rate interventions
pratikunterwegs Aug 23, 2023
017f03b
Update C++ fn intervention_on_rates()
pratikunterwegs Aug 23, 2023
b2ed175
Update vacamole model header with rate interventions
pratikunterwegs Aug 23, 2023
768e39f
Update default model header with rate interventions
pratikunterwegs Aug 23, 2023
3e56e43
Update check_args_vacamole for rate interventions
pratikunterwegs Aug 23, 2023
8ab3d7f
Update epidemic_vacamole_x() for rate interventions
pratikunterwegs Aug 23, 2023
09cbad6
Update .epidemic_vacamole_cpp() for rate interventions
pratikunterwegs Aug 23, 2023
f1a5750
Update .epidemic_default_cpp for rate interventions
pratikunterwegs Aug 23, 2023
0832278
Update Vacamole tests with rate interventions allowed
pratikunterwegs Aug 23, 2023
fdafe3a
Add pkdown article in index, update docs and RcppExports
pratikunterwegs Aug 23, 2023
4da5445
C++ linting and formatting
pratikunterwegs Aug 23, 2023
9b18713
Remove type choices from default args
pratikunterwegs Aug 24, 2023
e8a8f31
Correct intervention calls in vignettes and tests
pratikunterwegs Aug 24, 2023
7956d63
Update intervention docs, remove extra message
pratikunterwegs Aug 24, 2023
ad016de
Correct intervention calls in vignettes
pratikunterwegs Aug 24, 2023
de4ee5a
Update rate interventions vignette
pratikunterwegs Aug 24, 2023
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
8 changes: 6 additions & 2 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Generated by roxygen2: do not edit by hand

S3method(c,intervention)
S3method(c,contacts_intervention)
S3method(c,rate_intervention)
S3method(c,vaccination)
S3method(print,infection)
S3method(print,intervention)
Expand All @@ -20,13 +21,16 @@ export(get_model_names)
export(get_parameter)
export(infection)
export(intervention)
export(is_contacts_intervention)
export(is_infection)
export(is_intervention)
export(is_population)
export(is_rate_intervention)
export(is_vaccination)
export(model_library)
export(new_infections)
export(no_intervention)
export(no_contacts_intervention)
export(no_rate_intervention)
export(no_vaccination)
export(population)
export(vaccination)
Expand Down
8 changes: 4 additions & 4 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
#' as specified in the initial conditions matrix (see [population()]).
#' The second list element is a vector of timesteps.
#' @keywords internal
.epidemic_default_cpp <- function(initial_state, beta, alpha, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, time_end = 100.0, increment = 0.1) {
.Call(`_epidemics_epidemic_default_cpp_internal`, initial_state, beta, alpha, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, time_end, increment)
.epidemic_default_cpp <- function(initial_state, beta, alpha, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, rate_interventions, time_end = 100.0, increment = 0.1) {
.Call(`_epidemics_epidemic_default_cpp_internal`, initial_state, beta, alpha, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, rate_interventions, time_end, increment)
}

#' @title Run an SEIR model with Erlang passage times
Expand Down Expand Up @@ -132,8 +132,8 @@
#' as specified in the initial conditions matrix (see [population()]).
#' The second list element is a vector of timesteps.
#' @keywords internal
.epidemic_vacamole_cpp <- function(initial_state, beta, beta_v, alpha, omega, omega_v, eta, eta_v, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, time_end = 100.0, increment = 0.1) {
.Call(`_epidemics_epidemic_vacamole_cpp_internal`, initial_state, beta, beta_v, alpha, omega, omega_v, eta, eta_v, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, time_end, increment)
.epidemic_vacamole_cpp <- function(initial_state, beta, beta_v, alpha, omega, omega_v, eta, eta_v, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, rate_interventions, time_end = 100.0, increment = 0.1) {
.Call(`_epidemics_epidemic_vacamole_cpp_internal`, initial_state, beta, beta_v, alpha, omega, omega_v, eta, eta_v, gamma, contact_matrix, npi_time_begin, npi_time_end, npi_cr, vax_time_begin, vax_time_end, vax_nu, rate_interventions, time_end, increment)
}

#' @title Compute the discrete probability of the truncated Erlang distribution
Expand Down
59 changes: 53 additions & 6 deletions R/check_args_default.R
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,52 @@
# add null intervention and vaccination if these are missing
# if not missing, check that they conform to expectations
if (!"intervention" %in% names(mod_args)) {
mod_args[["intervention"]] <- no_intervention(
mod_args[["population"]]
# add as a list element named "contacts", and one named "beta"
mod_args[["intervention"]] <- list(
contacts = no_contacts_intervention(
mod_args[["population"]]
),
# a dummy intervention on the rate parameter beta
beta = no_rate_intervention()
)
} else {
assert_intervention(mod_args[["intervention"]], mod_args[["population"]])
# if interventions are passed, check for the types and names
stopifnot(
"`intervention` must be a list of <intervention>s" =
checkmate::test_list(
mod_args[["intervention"]],
types = c("contacts_intervention", "rate_intervention"),
names = "unique"
)
)

# check for any other intervention list element names
checkmate::assert_names(
names(mod_args[["intervention"]]),
subset.of = c("beta", "gamma", "alpha", "contacts")
)

# if a contacts intervention is passed, check it
if ("contacts" %in% names(mod_args[["intervention"]])) {
# check the intervention on contacts
assert_intervention(
mod_args[["intervention"]][["contacts"]], "contacts",
mod_args[["population"]]
)
} else {
# if not contacts intervention is passed, add a dummy one
mod_args[["intervention"]]$contacts <- no_contacts_intervention(
mod_args[["population"]]
)
}

# if there is only an intervention on contacts, add a dummy intervention
# on the transmission rate beta
if (identical(names(mod_args[["intervention"]]), "contacts")) {
mod_args[["intervention"]]$beta <- no_rate_intervention()
}
}

if (!"vaccination" %in% names(mod_args)) {
mod_args[["vaccination"]] <- no_vaccination(
mod_args[["population"]]
Expand Down Expand Up @@ -125,9 +165,15 @@
get_parameter(mod_args[["infection"]], "infectious_period")

# get NPI related times and contact reductions
npi_time_begin <- get_parameter(mod_args[["intervention"]], "time_begin")
npi_time_end <- get_parameter(mod_args[["intervention"]], "time_end")
npi_cr <- get_parameter(mod_args[["intervention"]], "contact_reduction")
contact_interventions <- mod_args[["intervention"]][["contacts"]]
npi_time_begin <- get_parameter(contact_interventions, "time_begin")
npi_time_end <- get_parameter(contact_interventions, "time_end")
npi_cr <- get_parameter(contact_interventions, "reduction")

# get other interventions if any
rate_interventions <- mod_args[["intervention"]][
setdiff(names(mod_args[["intervention"]]), "contacts")
]

# get vaccination related times and rates
vax_time_begin <- get_parameter(mod_args[["vaccination"]], "time_begin")
Expand All @@ -143,6 +189,7 @@
npi_cr = npi_cr,
vax_time_begin = vax_time_begin, vax_time_end = vax_time_end,
vax_nu = vax_nu,
rate_interventions = rate_interventions,
time_end = mod_args$time_end,
increment = mod_args$increment
)
Expand Down
61 changes: 55 additions & 6 deletions R/check_args_vacamole.R
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,53 @@
# add null intervention if this is missing
# if not missing, check that it conforms to expectations
if (!"intervention" %in% names(mod_args)) {
mod_args[["intervention"]] <- no_intervention(
mod_args[["population"]]
# add as a list element named "contacts", and one named "beta"
mod_args[["intervention"]] <- list(
contacts = no_contacts_intervention(
mod_args[["population"]]
),
# a dummy intervention on the rate parameter beta
beta = no_rate_intervention()
)
} else {
assert_intervention(mod_args[["intervention"]], mod_args[["population"]])
# if interventions are passed, check for the types and names
stopifnot(
"`intervention` must be a list of <intervention>s" =
checkmate::test_list(
mod_args[["intervention"]],
types = c("contacts_intervention", "rate_intervention"),
names = "unique"
)
)

# check for any other intervention list element names
checkmate::assert_names(
names(mod_args[["intervention"]]),
subset.of = c(
"beta", "beta_v", "gamma", "alpha", "eta", "eta_v",
"omega", "omega_v", "contacts"
)
)

# if a contacts intervention is passed, check it
if ("contacts" %in% names(mod_args[["intervention"]])) {
# check the intervention on contacts
assert_intervention(
mod_args[["intervention"]][["contacts"]], "contacts",
mod_args[["population"]]
)
} else {
# if not contacts intervention is passed, add a dummy one
mod_args[["intervention"]]$contacts <- no_contacts_intervention(
mod_args[["population"]]
)
}

# if there is only an intervention on contacts, add a dummy intervention
# on the transmission rate beta
if (identical(names(mod_args[["intervention"]]), "contacts")) {
mod_args[["intervention"]]$beta <- no_rate_intervention()
}
}

# return arguments invisibly
Expand Down Expand Up @@ -158,9 +200,15 @@
(1.0 - get_parameter(mod_args[["infection"]], "hosp_reduction_vax"))

# get NPI related times and contact reductions
npi_time_begin <- get_parameter(mod_args[["intervention"]], "time_begin")
npi_time_end <- get_parameter(mod_args[["intervention"]], "time_end")
npi_cr <- get_parameter(mod_args[["intervention"]], "contact_reduction")
contact_interventions <- mod_args[["intervention"]][["contacts"]]
npi_time_begin <- get_parameter(contact_interventions, "time_begin")
npi_time_end <- get_parameter(contact_interventions, "time_end")
npi_cr <- get_parameter(contact_interventions, "reduction")

# get other interventions if any
rate_interventions <- mod_args[["intervention"]][
setdiff(names(mod_args[["intervention"]]), "contacts")
]

# get vaccination related times and rates
vax_time_begin <- get_parameter(mod_args[["vaccination"]], "time_begin")
Expand All @@ -179,6 +227,7 @@
npi_cr = npi_cr,
vax_time_begin = vax_time_begin, vax_time_end = vax_time_end,
vax_nu = vax_nu,
rate_interventions = rate_interventions,
time_end = mod_args$time_end,
increment = mod_args$increment
)
Expand Down
22 changes: 17 additions & 5 deletions R/epidemic_default.R
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ epidemic_default_cpp <- function(population,

# check class add intervention and vaccination if not NULL
if (!is.null(intervention)) {
checkmate::assert_class(intervention, "intervention")
checkmate::assert_list(intervention, types = "intervention")
model_arguments[["intervention"]] <- intervention
}
if (!is.null(vaccination)) {
Expand Down Expand Up @@ -142,16 +142,25 @@ epidemic_default_cpp <- function(population,
cr = params[["npi_cr"]]
)

# modify parameters
infection_params <- params[c("beta", "alpha", "gamma")]

infection_params <- intervention_on_rates(
t = t,
interventions = params[["rate_interventions"]],
parameters = infection_params
)

# modify the vaccination rate depending on the regime
# the number of doses is already checked before passing
current_nu <- params[["vax_nu"]] *
((params[["vax_time_begin"]] < t) &
(params[["vax_time_end"]] > t))

# calculate transitions
sToE <- (params[["beta"]] * y[, 1] * contact_matrix_ %*% y[, 3])
eToI <- params[["alpha"]] * y[, 2]
iToR <- params[["gamma"]] * y[, 3]
sToE <- (infection_params[["beta"]] * y[, 1] * contact_matrix_ %*% y[, 3])
eToI <- infection_params[["alpha"]] * y[, 2]
iToR <- infection_params[["gamma"]] * y[, 3]
sToV <- current_nu * y[, 1]

# define compartmental changes
Expand Down Expand Up @@ -194,7 +203,10 @@ epidemic_default_r <- function(population,

# check class add intervention and vaccination if not NULL
if (!is.null(intervention)) {
checkmate::assert_class(intervention, "intervention")
checkmate::assert_list(
intervention,
types = c("intervention", "list")
)
model_arguments[["intervention"]] <- intervention
}
if (!is.null(vaccination)) {
Expand Down
24 changes: 22 additions & 2 deletions R/epidemic_vacamole.R
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ epidemic_vacamole_cpp <- function(population,

# check class add intervention and vaccination if not NULL
if (!is.null(intervention)) {
checkmate::assert_class(intervention, "intervention")
checkmate::assert_list(
intervention,
types = c("contacts_intervention", "rate_intervention")
)
model_arguments[["intervention"]] <- intervention
}

Expand Down Expand Up @@ -181,6 +184,20 @@ epidemic_vacamole_cpp <- function(population,
cr = params[["npi_cr"]]
)

# modify parameters
infection_params <- params[
c(
"beta", "beta_v", "alpha", "eta", "eta_v",
"omega", "omega_v", "gamma"
)
]

infection_params <- intervention_on_rates(
t = t,
interventions = params[["rate_interventions"]],
parameters = infection_params
)

# modify the vaccination rate depending on the regime
# the number of doses is already checked before passing
# columns are: 1: rate of first dose, 2: rate of second dose
Expand Down Expand Up @@ -276,7 +293,10 @@ epidemic_vacamole_r <- function(population,

# check class add intervention and vaccination if not NULL
if (!is.null(intervention)) {
checkmate::assert_class(intervention, "intervention")
checkmate::assert_list(
intervention,
types = c("contacts_intervention", "rate_intervention")
)
model_arguments[["intervention"]] <- intervention
}

Expand Down
42 changes: 29 additions & 13 deletions R/input_check_helpers.R
Original file line number Diff line number Diff line change
Expand Up @@ -209,31 +209,47 @@ assert_vaccination <- function(x, doses, population) {
#' function is for internal use in argument checking functions.
#'
#' @param x A [intervention] object.
#' @param type A string for the type of intervention to check for. May be one of
#' `"contacts"` or `"rate"`.
#' @param population An optional argument which is a [population] object.
#' When present, this is used to check whether the intervention object `x` has
#' corresponding values of `contact_reduction` for each demographic group in
#' corresponding values of `reduction` for each demographic group in
#' `population`.
#'
#' @keywords internal
#'
#' @return Silently returns the `intervention` object `x`.
#' Primarily called for its side effects of throwing errors when `x` does not
#' meet certain requirements.
assert_intervention <- function(x, population) {
assert_intervention <- function(x, type = c("contacts", "rate"),
population) {
# check for input class
checkmate::assert_class(x, "intervention")
type <- match.arg(type, several.ok = FALSE)
switch(type,
contacts = checkmate::assert_class(x, "contacts_intervention"),
rate = checkmate::assert_class(x, "rate_intervention")
)

# check that the length of contact_reduction is the same as the number
# of demographic groups
n_demo_groups <- NULL
if (!missing(population)) {
n_demo_groups <- length(get_parameter(population, "demography_vector"))
if (type == "contacts") {
# check the population
# check that the length of reduction is the same as the number
# of demographic groups
n_demo_groups <- NULL
if (!missing(population)) {
n_demo_groups <- length(get_parameter(population, "demography_vector"))
}
checkmate::assert_matrix(
get_parameter(x, "reduction"),
mode = "numeric",
nrows = n_demo_groups
)
} else if (type == "rate") {
checkmate::assert_numeric(
get_parameter(x, "reduction"),
lower = 0.0, upper = 1.0,
len = length(get_parameter(x, "time_begin"))
)
}
checkmate::assert_matrix(
get_parameter(x, "contact_reduction"),
mode = "numeric",
nrows = n_demo_groups
)

# invisibly return x
invisible(x)
Expand Down
Loading
Loading