generated from epiverse-trace/packagetemplate
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
218aecb
commit c0d1344
Showing
7 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
# Helper function | ||
#' Get model arguments as a list, including default arguments | ||
#' | ||
#' @description | ||
#' Internal function intended to be called inside a call to `model_*_*()` to | ||
#' capture values passed to function arguments, including default values. | ||
#' @param f A function or a function name as a string. | ||
#' | ||
#' @keywords internal | ||
.get_model_parameters <- function(f) { | ||
# NOTE: match.call() does not capture default values | ||
# get values in a frame one level up | ||
mget( | ||
names(formals(f)), | ||
sys.frame(sys.nframe() - 1L) | ||
) | ||
} | ||
|
||
#' Constructor for the `<epidemic>` class | ||
#' | ||
#' @param model_fn A string giving the name of the model function. | ||
#' @param data A `<data.frame>` of the model output. Must have four columns | ||
#' named "time", "demography_group", "compartment", and value. | ||
#' @param parameters A named list of model parameters used in a model run. These | ||
#' may of atomic or more complex types, such as `<intervention>`, or NULL for | ||
#' unused, optional arguments. | ||
#' @param hash A string for the SHA-1 remote hash associated with the installed | ||
#' version of `{epidemics}`. For named release versions, this is a version | ||
#' number with semantic meaning such as `"0.1.0"`. For versions installed from | ||
#' the remote, this is the latest commit hash on the installation branch. | ||
#' This is typically auto-generated by the external constructor [epidemic()]. | ||
#' | ||
#' @return An object of the `<epidemic>` class. | ||
#' @noRd | ||
new_epidemic <- function(model_fn, data, parameters, hash) { | ||
# create and return epidemic class | ||
# input checking in external constructor | ||
x <- list( | ||
model_fn = model_fn, | ||
hash = hash, | ||
data = data, | ||
parameters = parameters | ||
) | ||
class(x) <- c(class, "epidemic") | ||
|
||
x | ||
} | ||
|
||
#' Create an `<epidemic>` object | ||
#' | ||
#' @description | ||
#' A simple class to hold the output of epidemic models along with the model | ||
#' parameters and any composable elements, such as interventions, applied. | ||
#' | ||
#' @param model_fn A string giving the name of the model function. | ||
#' @param data A `<data.frame>` of the model output. Must have four columns | ||
#' named "time", "demography_group", "compartment", and value. | ||
#' @param parameters A named list of model parameters used in a model run. These | ||
#' may of atomic or more complex types, such as `<intervention>`, or NULL for | ||
#' unused, optional arguments. | ||
#' | ||
#' @name epidemic_class | ||
#' @rdname epidemic_class | ||
#' | ||
#' @examples | ||
#' # Run a model to get an <epidemic> class output | ||
#' uk_population <- population( | ||
#' name = "UK population", | ||
#' contact_matrix = matrix(1), | ||
#' demography_vector = 67e6, | ||
#' initial_conditions = matrix( | ||
#' c(0.9999, 0.0001, 0, 0, 0), | ||
#' nrow = 1, ncol = 5L | ||
#' ) | ||
#' ) | ||
#' | ||
#' # run epidemic simulation with no vaccination or intervention | ||
#' output <- model_default_cpp( | ||
#' population = uk_population | ||
#' ) | ||
#' | ||
#' output | ||
#' | ||
#' # access parameters | ||
#' get_parameter(output, "transmissibility") | ||
#' @export | ||
epidemic <- function(model_fn, data, parameters) { | ||
# check input | ||
checkmate::assert_string(model_fn) | ||
checkmate::assert_data_frame( | ||
data, | ||
any.missing = FALSE, min.rows = 1, ncols = 4 | ||
) | ||
# allow some missing values as interventions and vaccinations may be | ||
# NULL by default | ||
# DO NOT expect unique values as rates and NULLs may repeat | ||
checkmate::assert_list( | ||
parameters, | ||
any.missing = TRUE, all.missing = FALSE, min.len = 1L, | ||
names = "unique" | ||
) | ||
|
||
# get package version or hash | ||
# NOTE: is NULL when installed from local version | ||
hash <- utils::packageDescription("epidemics")[["RemoteSha"]] | ||
|
||
# return epidemic class | ||
new_epidemic(model_fn, data, parameters, hash) | ||
} | ||
|
||
#' Validate <epidemic> class objects | ||
#' | ||
#' @name validate_epidemic | ||
#' @rdname validate_epidemic | ||
#' | ||
#' @param x An `<epidemic>` object. | ||
#' | ||
#' @return Invisibly returns the input `x`. Called primarily for its | ||
#' input checking as a validator. | ||
#' @keywords internal | ||
validate_epidemic <- function(x) { | ||
# check for class and class invariants | ||
stopifnot( | ||
"`x` should be of class <epidemic>" = | ||
(is_epidemic(x)), | ||
"<epidemic> does not contain the correct attributes" = | ||
(c( | ||
"data", "parameters" | ||
) %in% attributes(x)$names) | ||
) | ||
|
||
# check epidemic class members | ||
checkmate::assert_string(x[["model_fn"]]) | ||
checkmate::assert_data_frame( | ||
x[["data"]], | ||
any.missing = FALSE, min.rows = 1, ncols = 4 | ||
) | ||
# allow some missing values as interventions and vaccinations may be | ||
# NULL by default | ||
# DO NOT expect unique values as rates and NULLs may repeat | ||
checkmate::assert_list( | ||
x[["parameters"]], | ||
any.missing = TRUE, all.missing = FALSE, min.len = 1L, | ||
names = "unique" | ||
) | ||
checkmate::assert_string(x[["hash"]], null.ok = TRUE) | ||
|
||
# invisibly return x | ||
invisible(x) | ||
} | ||
|
||
#' Check whether an object is an `<epidemic>` | ||
#' | ||
#' @param x An object to be checked as belonging to the `<epidemic>` class. | ||
#' | ||
#' @name epidemic | ||
#' @rdname epidemic | ||
#' @export | ||
is_epidemic <- function(x) { | ||
inherits(x, "epidemic") | ||
} | ||
|
||
#' Print an object of the `<epidemic>` class | ||
#' | ||
#' @name print_epidemic | ||
#' @rdname print_epidemic | ||
#' | ||
#' @param x An `<epidemic>` class object. | ||
#' @param ... Other parameters passed to [print()]. | ||
#' @return Invisibly returns the object `x`. Called for printing side-effects. | ||
#' @export | ||
print.epidemic <- function(x, ...) { | ||
format(x, ...) | ||
} | ||
|
||
#' Format an `<epidemic>` object | ||
#' | ||
#' @param x A `<epidemic>` object. | ||
#' @param ... Other arguments passed to [format()]. | ||
#' | ||
#' @return Invisibly returns the [`<epidemic>`] object `x`. | ||
#' Called for printing side-effects. | ||
#' @keywords internal | ||
#' @noRd | ||
format.epidemic <- function(x, ...) { | ||
validate_epidemic(x) | ||
|
||
# NOTE: WORK IN PROGRESS | ||
model_fn <- x[["model_fn"]] | ||
model_fn <- glue::glue("Model function: {model_fn}") | ||
|
||
compartments <- x[["parameters"]][["compartments"]] | ||
compartments <- glue::glue_collapse( | ||
glue::double_quote(compartments), | ||
sep = ", " | ||
) | ||
compartments <- glue::glue("Compartments: {compartments}") | ||
hash <- x[["hash"]] | ||
if (is.null(hash)) { | ||
hash <- "Local version" | ||
} | ||
hash <- glue::glue("{{epidemics}} version: {hash}") | ||
|
||
# header | ||
header <- "Head of model data:" | ||
writeLines( | ||
c( | ||
"<epidemic>", | ||
model_fn, | ||
compartments, | ||
hash, | ||
header | ||
) | ||
) | ||
|
||
print(head(x[["data"]])) | ||
|
||
invisible(x) | ||
} | ||
|
||
# NOTE: an as.epidemic() method was considered and suspended pending questions | ||
# around how to ensure sensible entries for the model function name and the hash | ||
# as ideally it should NOT be possible for users to provide or modify these | ||
# to guard against errors. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# <epidemic> class basic expectations | ||
|
||
Code | ||
output | ||
Output | ||
<epidemic> | ||
Model function: model_default_cpp | ||
Compartments: "susceptible", "exposed", "infectious", "recovered", "vaccinated" | ||
{epidemics} version: Local version | ||
Head of model data: | ||
time demography_group compartment value | ||
1 0 [0,20) susceptible 14797810 | ||
2 0 [20,40) susceptible 16524649 | ||
3 0 40+ susceptible 28958263 | ||
4 0 [0,20) exposed 0 | ||
5 0 [20,40) exposed 0 | ||
6 0 40+ exposed 0 | ||
|