From 96ab826326e5ccf4a5d3e0934132afcf2148b948 Mon Sep 17 00:00:00 2001 From: cazodi <cazodi@svi.edu.au> Date: Fri, 3 Apr 2020 14:54:15 +1100 Subject: [PATCH] add code for setting up time sensitive experiments where parameter values change over time --- R/results-parse.R | 12 ++++--- R/time_experiments.R | 68 +++++++++++++++++++++++++++++++++++++ vignettes/sirplus_intro.Rmd | 45 +++++++++++++++--------- 3 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 R/time_experiments.R diff --git a/R/results-parse.R b/R/results-parse.R index 843e6c9..80ac246 100644 --- a/R/results-parse.R +++ b/R/results-parse.R @@ -153,7 +153,8 @@ plot_models <- function(sims = baseline_sim, scale_x_date(date_breaks = "1 week", date_labels = "%m-%d") + scale_colour_manual(values = compcols, labels = complabels) + labs(title = plot_title, x = x_axis, y = "Prevalence") + - theme_bw() + theme_bw() + + theme(axis.text.x = element_text(angle = 90)) } else ( plot_df %>% ggplot(aes(x = Date, y = count, colour = compartment, linetype = sim)) + @@ -162,7 +163,8 @@ plot_models <- function(sims = baseline_sim, geom_line(size = 1.5, alpha = 0.8) + scale_colour_manual(values = compcols, labels = complabels) + labs(title = plot_title, x = x_axis, y = "Prevalence") + - theme_bw() + theme_bw() + + theme(axis.text.x = element_text(angle = 90)) ) }else{ if(length(sim_id) == 1){ @@ -173,7 +175,8 @@ plot_models <- function(sims = baseline_sim, geom_line(size = 1.5, alpha = 0.8) + scale_colour_manual(values = compcols, labels = complabels) + labs(title = plot_title, x = x_axis, y = "Prevalence") + - theme_bw() + theme_bw() + + theme(axis.text.x = element_text(angle = 90)) } else ( plot_df %>% ggplot(aes(x = Date, y = count+1, colour = compartment, linetype = sim)) + @@ -183,7 +186,8 @@ plot_models <- function(sims = baseline_sim, geom_line(size = 1.5, alpha = 0.8) + scale_colour_manual(values = compcols, labels = complabels) + labs(title = plot_title, x = x_axis, y = "Prevalence") + - theme_bw() + theme_bw() + + theme(axis.text.x = element_text(angle = 90)) ) } } diff --git a/R/time_experiments.R b/R/time_experiments.R new file mode 100644 index 0000000..5b2afac --- /dev/null +++ b/R/time_experiments.R @@ -0,0 +1,68 @@ +#' Generating time-dependent parameters +#' +#' Function to generate parameter values for the time range of the simulation +#' that can change over time. +#' +#' @param nstep Number of time steps to generate parameter values for. +#' @param vals List of parameter values to include over the nsteps. +#' @param timing List of the step numbers at which to start changes, with the +#' last number reflecting when to hit the last parameter value in vals. +#' +#' @return list of parameter values for length t +#' +vary_param <- function(nstep = nstep, vals = vals, timing = timing) { + + stopifnot(length(vals) == length(timing)) + y <- list() + + for(t in seq(1:nstep)){ + if(t <= timing[1]){ # If before first jump set to val[1] + y.t <- vals[1] + }else if(t > tail(timing, n=1)){ # If after last jump set to val[-1] + y.t <- tail(vals, n=1) + }else{ # If intermediate step, calculate... + for(j in (2:length(timing))){ + if(t > timing[j - 1] & t <= timing[j]){ + start <- vals[j - 1] + end <- vals[j] + start_t <- timing[j - 1] + end_t <- timing[j] + y.t <- start - (t-start_t)*(start - end)/(end_t - start_t) + } + } + } + y <- append(y, y.t) + } + + return(unlist(y)) + +} + + +vary_fun <- function(t,start_t=1,start_val, + end_t = 9, + end_val, + end_t2=22, end_val2, + do_relax = FALSE, + relax_start = NULL, + relax_end = NULL, + relax_val = NULL) { + stopifnot(start_t < end_t) + + if(do_relax){ + stopifnot(relax_start <= relax_end) + stopifnot(end_t < relax_start) + + y <- ifelse(t <= start_t, start_val, + ifelse(t <= end_t, start_val - (t-start_t)*(start_val - end_val)/(end_t - start_t), + ifelse(t <= end_t2,end_val - (t - end_t)*(end_val - end_val2)/(end_t2 - end_t), + ifelse(t<=relax_start, end_val2, + ifelse(t <= relax_end, end_val2 - (t-relax_start)*(end_val2 - relax_val)/(relax_end - relax_start), relax_val))))) + } else { + y <- ifelse(t <= start_t, start_val, + ifelse(t <= end_t, start_val - (t-start_t)*(start_val - end_val)/(end_t - start_t), + ifelse(t <= end_t2,end_val - (t - end_t)*(end_val - end_val2)/(end_t2 - end_t),end_val2))) + } + return(round(y,4)) + +} diff --git a/vignettes/sirplus_intro.Rmd b/vignettes/sirplus_intro.Rmd index 150233f..6dec74f 100644 --- a/vignettes/sirplus_intro.Rmd +++ b/vignettes/sirplus_intro.Rmd @@ -56,11 +56,12 @@ default parameters for disease spread (i.e. no additional interventions). ```{r simulate baselines} s.num <- 2000 # number susceptible -i.num <- 50 # number infected -q.num <- 10 # number in self-isolation +i.num <- 15 # number infected +q.num <- 5 # number in self-isolation h.num <- 1 # number in the hospital +nstep <- 90 # number of steps (e.g. days) to simulate -baseline_sim <- simulate_seiqhrf(s.num = s.num, i.num = i.num, +baseline_sim <- simulate_seiqhrf(nstep = nstep, s.num = s.num, i.num = i.num, q.num = q.num, h.num = h.num) head(baseline_sim$df) @@ -86,7 +87,6 @@ over time in each compartment. ```{r viz prevalence} plot_models(sims = baseline_sim, - time_lim = 50, start_date = lubridate::ymd("2020-01-01"), comp_remove = c('s.num', 'r.num'), plot_title = 'Baseline Model') @@ -94,22 +94,35 @@ plot_models(sims = baseline_sim, ## Run an experiment -With the sirplus package you can also set up experiments. For example, let's say that one week after the beginning of the epidemic, schools and non-essential businesses are closed to encourage social distancing. We can model the impacts that policies may have and compare to our baseline model. In this example, we model a policy-based increase in social distancing by ramping down the act.rate.e (# of exposure events, or acts, between individuals in the E and S compartment, per day) after 7 days and plot this model next to our baseline. +With the sirplus package you can also set up experiments. We will set up two +experiments here: -```{r experiment 1} -closures_RampOnday7 <- function(t) { - ifelse(t < 7, 10, ifelse(t <= 14, 10 - (t-7)*(10 - 5)/7, 5)) -} +- Experiment #1: One week after the beginning of the epidemic, schools and non-essential businesses are closed to encourage social distancing. This causes the act.rate to gradually drop from 10 to 6 over the course of the next week. In this experiment, we imagine these policies are never lifted, so act.rate remains at 6 for the duration of the simulation. +- Experiment #2: Again, one week after the beginning of the epidemic, social distancing policies are put into place resulting in act.rate dropping from 10 to 6 over the next week. But after two weeks these policies are lifted and the act.rate returns to normal within the next week. +```{r Experiment example with act.rate} +# Experiment #1 +vals <- c(10, 7) +timing <- c(7, 14) +act_rate <- vary_param(nstep = nstep, vals = vals, timing = timing) -closures_sim <- simulate_seiqhrf(s.num = s.num, i.num = i.num, - q.num = q.num, h.num = h.num, - act.rate.e = closures_RampOnday7(1:366), - act.rate.i = closures_RampOnday7(1:366)) +sim_exp <- simulate_seiqhrf(nstep = nstep, s.num = s.num, i.num = i.num, + q.num = q.num, h.num = h.num, act.rate.e = act_rate, + act.rate.i = act_rate * 0.5) -plot_models(sims = c(baseline_sim, closures_sim), - sim_id = c('Baseline', 'Closures (d14)'), - time_lim = 50, +# Experiment #2 +vals <- c(10, 7, 7, 10) +timing <- c(7, 14, 21, 28) +act_rate_relax <- vary_param(nstep, vals = vals, timing = timing) + +sim_exp_relax <- simulate_seiqhrf(nstep = nstep, s.num = s.num, i.num = i.num, + q.num = q.num, h.num = h.num, + act.rate.e = act_rate_relax, + act.rate.i = 0.5 * act_rate_relax) + +# Compare experiments 1 and 2 to the baseline simulation +plot_models(sims = c(baseline_sim, sim_exp, sim_exp_relax), + sim_id = c('Baseline', 'Closures', 'Closures (2 mo)'), start_date = lubridate::ymd("2020-01-01"), comp_remove = c('s.num', 'r.num'), plot_title = 'Closures Experiment') -- GitLab