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

Cpp model for IfG workshop #54

Draft
wants to merge 33 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c08fb14
Rcpp-Boost implementation
pratikunterwegs Dec 6, 2024
7a14730
Rcpp-Boost implementation p2
pratikunterwegs Dec 6, 2024
72bb1a7
WIP daedalus_rtm
pratikunterwegs Dec 6, 2024
b6f18ed
Update with workplace within sector infections
pratikunterwegs Dec 6, 2024
96aa412
Simple fun to apply npi to Eigen array or double
pratikunterwegs Dec 7, 2024
11cf5e1
Time-dependent closures on workplaces, WIP
pratikunterwegs Dec 7, 2024
b3a48c1
Basic test for daedalus C++
pratikunterwegs Dec 7, 2024
3b4f657
Update daedalus_cpp with internal looping over params
pratikunterwegs Dec 9, 2024
4cbf500
WIP daedalus_rtm() using internal Cpp model
pratikunterwegs Dec 9, 2024
7634817
Fn to prepare output from daedalus_rtm
pratikunterwegs Dec 9, 2024
eb96d9a
Excess mortality and age-varying params
pratikunterwegs Dec 9, 2024
637f89e
`daedalus_rtm()` compatible with daedalus_class output
pratikunterwegs Dec 9, 2024
deb36da
`prepare_output_cpp()` compatible with downstream funs
pratikunterwegs Dec 9, 2024
3a370e5
Code formatting after linting
pratikunterwegs Dec 10, 2024
5b0d858
Correct within workplace infected calculation
pratikunterwegs Dec 10, 2024
e897056
Allow external community transmission redn mandate
pratikunterwegs Dec 10, 2024
0d36871
Add consumer-worker infections
pratikunterwegs Dec 10, 2024
cb2a1ea
Add econ sector names
pratikunterwegs Dec 10, 2024
560494e
Add `daedalus_rtm()` tests
pratikunterwegs Dec 10, 2024
e2de4c7
Update misc documentation
pratikunterwegs Dec 10, 2024
4936d98
Rm {epidemics} dependency
pratikunterwegs Dec 10, 2024
29c0d44
Normalise desc, add RcppEigen
pratikunterwegs Dec 11, 2024
01878eb
Add RcppExports to linter exceptions
pratikunterwegs Dec 11, 2024
feb20ab
Correct closure duration calculations
pratikunterwegs Dec 11, 2024
133db05
Add tests for closures costs
pratikunterwegs Dec 11, 2024
3afdd43
Rm extra non-portable flags
pratikunterwegs Dec 11, 2024
e109e87
Correct closure duration logging for future closures
pratikunterwegs Dec 13, 2024
947a828
Add per-sector GVA losses from closures and absences
pratikunterwegs Dec 18, 2024
99fd2c7
Export life expectancy values in country objs
pratikunterwegs Dec 18, 2024
cc26f6d
`get_costs()` returns life years lost
pratikunterwegs Dec 18, 2024
fd66549
Correct placement of flag and distancing coef calc
pratikunterwegs Jan 6, 2025
e0efb6e
Costs include life years
pratikunterwegs Jan 13, 2025
e63975b
Fn to get life-years lost
pratikunterwegs Jan 13, 2025
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
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@
^data-raw$
^doc$
^Meta$
^.*_cpp.sh$
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ pkgdown
scratch*
/doc/
/Meta/
*_cpp.sh
3 changes: 2 additions & 1 deletion .lintr
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ exclusions: list(
missing_package_linter = Inf,
namespace_linter = Inf
),
"R/cpp11.R"
"R/cpp11.R",
"R/RcppExports.R"
)
6 changes: 6 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Imports:
cli,
data.table,
deSolve,
Rcpp,
RcppEigen,
rlang
Suggests:
countrycode,
Expand All @@ -46,6 +48,10 @@ Suggests:
spelling,
testthat (>= 3.0.0),
tidyr
LinkingTo:
BH,
Rcpp,
RcppEigen
VignetteBuilder:
knitr
Config/Needs/website: jameel-institute/jameelinst.rpkg.theme
Expand Down
5 changes: 5 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ S3method(set_data,daedalus_vaccination)
export(daedalus)
export(daedalus_country)
export(daedalus_infection)
export(daedalus_rtm)
export(daedalus_vaccination)
export(get_costs)
export(get_data)
export(get_epidemic_summary)
export(get_incidence)
export(get_life_years_lost)
export(get_new_vaccinations)
export(is_daedalus_country)
export(is_daedalus_infection)
export(is_daedalus_vaccination)
export(set_data)
import(RcppEigen)
importFrom(Rcpp,sourceCpp)
importFrom(data.table,":=")
importFrom(data.table,.BY)
importFrom(data.table,.EACHI)
Expand All @@ -33,3 +37,4 @@ importFrom(data.table,.N)
importFrom(data.table,.NGRP)
importFrom(data.table,.SD)
importFrom(data.table,data.table)
useDynLib(daedalus, .registration = TRUE)
7 changes: 7 additions & 0 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

.model_daedalus_cpp <- function(initial_state, params, contact_matrix, contacts_work, contacts_consumers, openness, hospital_capacity, t_start, t_end, auto_social_distancing = FALSE, social_distancing_mandate = 1.0, time_end = 100.0, increment = 1.0) {
.Call(`_daedalus_model_daedalus_internal`, initial_state, params, contact_matrix, contacts_work, contacts_consumers, openness, hospital_capacity, t_start, t_end, auto_social_distancing, social_distancing_mandate, time_end, increment)
}

12 changes: 10 additions & 2 deletions R/class_country.R
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ daedalus_country <- function(country,
params$workers <- params$workers + 1

# add value of statistical life (VSL)
life_expectancy <- daedalus::life_expectancy[[name]]
vsl <- daedalus::life_value[[name]]
gni <- daedalus::country_gni[[name]]

Expand All @@ -180,7 +181,8 @@ daedalus_country <- function(country,
contacts_between_sectors =
daedalus::economic_contacts[["contacts_between_sectors"]],
vsl = vsl,
gni = gni
gni = gni,
life_expectancy = life_expectancy
)
)
parameters <- Filter(parameters, f = function(x) !is.null(x))
Expand Down Expand Up @@ -216,7 +218,7 @@ validate_daedalus_country <- function(x) {
"name", "demography", "contact_matrix",
"contacts_workplace", "contacts_consumer_worker",
"contacts_between_sectors", "workers", "gva",
"vsl", "hospital_capacity", "gni"
"vsl", "hospital_capacity", "gni", "life_expectancy"
)
has_invariants <- checkmate::test_names(
attributes(x)$names,
Expand Down Expand Up @@ -308,6 +310,12 @@ validate_daedalus_country <- function(x) {
checkmate::test_count(
x$gni,
positive = TRUE
),
"Country `life_expectancy` must be a 4-element vector of positive values" =
checkmate::test_numeric(
x$life_expectancy,
len = N_AGE_GROUPS, any.missing = FALSE,
lower = 0, upper = 100 # reasonable upper limit
)
)

Expand Down
13 changes: 13 additions & 0 deletions R/closure_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,16 @@
#' @source Multiple sources; to be updated shortly. See processing details in
#' `data-raw/closure_data.R
"closure_data"

#' @title Economic sector names
#'
#' @description Names or descriptions of openness of economic sectors modelled
#' in _daedalus_, to which closures apply.
#'
#' @format ## `econ_sector_names`
#' A character vector of length `N_ECON_SECTORS` (45).
#' @source Multiple sources; to be updated shortly. See processing details in
#' `data-raw/closure_data.R
#' @examples
#' econ_sector_names
"econ_sector_names"
36 changes: 25 additions & 11 deletions R/costs.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,20 @@
#' (`education_cost_closures`), and pandemic-related absences due to illness and
#' death (`education_cost_absences`).
#'
#' ## Life-years lost
#' ## Life-value lost
#'
#' A four-element vector (for the number of age groups) giving the value of
#' life-years lost per age group. This is calculated as the life-expectancy of
#' each age group times the value of a statistical life, with all years assumed
#' to have the same value.
#'
#' ## Life-years lost
#'
#' A four-element vector (for the number of age groups) giving the value of
#' life-years lost per age group. This is calculated as the life-expectancy of
#' each age group times the number of deaths in that age group. No quality
#' adjustment is applied.
#'
#' @examples
#' output <- daedalus("Canada", "influenza_1918")
#'
Expand All @@ -61,10 +68,9 @@ get_costs <- function(x, summarise_as = c("none", "total", "domain")) {
vsd <- vsd / 1e6 # for uniformity with daily GVA
n_students <- x$country_parameters$demography[i_SCHOOL_AGE]

# cost of closures
economic_cost_closures <- sum(
gva * (1 - openness) * closure_duration
)
# cost of closures, per sector and total
sector_cost_closures <- gva * (1 - openness) * closure_duration
economic_cost_closures <- sum(sector_cost_closures)

education_cost_closures <- sum(
vsd * n_students * (1 - openness[i_EDUCATION_SECTOR]) *
Expand All @@ -85,8 +91,9 @@ get_costs <- function(x, summarise_as = c("none", "total", "domain")) {
)
workforce <- x$country_parameters$workers

# calculate daily GVA loss; scale GVA loss by openness when closures are
# active
# calculate daily GVA loss due to illness-related absencees;
# scale GVA loss by openness when closures are active
# assuming no working from home
gva_loss <- worker_absences %*% diag(gva / workforce)

gva_loss[seq(closure_start, closure_end), ] <-
Expand All @@ -113,22 +120,29 @@ get_costs <- function(x, summarise_as = c("none", "total", "domain")) {
levels = unique(total_deaths$age_group)
)
total_deaths <- tapply(total_deaths$value, total_deaths$age_group, sum)
life_years_lost <- x$country_parameters$life_expectancy * total_deaths

# NOTE: in million $s
life_years_lost <- x$country_parameters$vsl * total_deaths / 1e6
life_value_lost <- x$country_parameters$vsl * total_deaths / 1e6

cost_list <- list(
total_cost = NA,
economic_costs = list(
economic_cost_total = economic_cost_closures + economic_cost_absences,
economic_cost_closures = economic_cost_closures,
economic_cost_absences = economic_cost_absences
economic_cost_absences = economic_cost_absences,
sector_cost_closures = sector_cost_closures,
sector_cost_absences = gva_loss
),
education_costs = list(
education_cost_total = education_cost_closures + education_cost_absences,
education_cost_closures = education_cost_closures,
education_cost_absences = education_cost_absences
),
life_value_lost = list(
life_value_lost_total = sum(life_value_lost),
life_value_lost_age = life_value_lost
),
life_years_lost = list(
life_years_lost_total = sum(life_years_lost),
life_years_lost_age = life_years_lost
Expand All @@ -138,7 +152,7 @@ get_costs <- function(x, summarise_as = c("none", "total", "domain")) {
# probably a neater way of doing this
cost_list$total_cost <- economic_cost_closures + economic_cost_absences +
education_cost_closures + education_cost_absences +
sum(life_years_lost)
sum(life_value_lost)

# return summary if requested, defaults to no summary
summarise_as <- rlang::arg_match(summarise_as)
Expand All @@ -149,7 +163,7 @@ get_costs <- function(x, summarise_as = c("none", "total", "domain")) {
domain = {
cost_list[["total_cost"]] <- NULL
vec_costs <- vapply(cost_list, `[[`, 1L, FUN.VALUE = numeric(1))
names(vec_costs) <- c("economic", "education", "life_years")
names(vec_costs) <- c("economic", "education", "life_value", "life_years")

vec_costs
}
Expand Down
3 changes: 3 additions & 0 deletions R/daedalus-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"_PACKAGE"

## usethis namespace: start
#' @import RcppEigen
#' @importFrom data.table :=
#' @importFrom data.table .BY
#' @importFrom data.table .EACHI
Expand All @@ -11,5 +12,7 @@
#' @importFrom data.table .NGRP
#' @importFrom data.table .SD
#' @importFrom data.table data.table
#' @importFrom Rcpp sourceCpp
#' @useDynLib daedalus, .registration = TRUE
## usethis namespace: end
NULL
Loading
Loading