library(ramp.xds)
library(Matrix)
library(expm)
library(ramp.library)
library(ramp.control)
library(ramp.work)
Evaluation
Routine Evaluation of Vector Control
::load_all("~/git/ramp.control") devtools
ℹ Loading ramp.control
::load_all("~/git/ramp.work") devtools
ℹ Loading ramp.work
Routine evaluation of vector control for malaria presents enormous challenges. This vignette considers the challenge of evaluating the impact of mass bed net distributions and mass indoor house spraying (i.e. indoor residual spraying, or IRS).
To evaluate vector control, we need to do the following tasks:
Build a model
Set up model fitting
Set up vector control
Fit the model to data
Construct a counterfactual baseline
Compute the impact
Build a Model
We want to understand malaria as a changing baseline that has been modified by vector control. The malaria baseline is affected by mosquito ecology. To get started, we build a model to understand malaria prevalence in relation to exposure. We set up a model that is forced by the EIR:
<- xds_setup_eir(Xname = "SIP") sip
Set Up Fitting
The functions that set up model fitting in ramp.work
use xds_scaling
to make some initial guesses about the mean forcing parameters and the seasonal phase.
<- xds_scaling(sip)
sip xds_plot_eirpr(sip)
After fitting the model and getting the seasonal pattern right, it might be worth it to run xds_scaling
again.
To set up model fitting, we need some data. We use a time series we have saved locally:
<- read.table("./data/pfpr_time_series.tbl")
prts with(prts, {
plot(jdates, pfpr, ylim = c(0,0.65), main = "Example", xlab = "Julian Date (day 1 is Jan 1, 2015)", ylab = "PR", xlim = range(0, jdates))
lines(jdates, pfpr)
})
<- setup_fitting(sip, prts$pfpr, prts$jdate) sip
Set Up Vector Control Events
To set up vector control for IRS, we use setup_irs_events
and pass it the Julian dates, the pesticides, and the coverage (% of houses sprayed).
<- c(2861, 3256, 3622)
irs_jdates <- c("fludora_fusion", "actellic", "actellic")
irs_type <- c(.95, .95, .95)
frac_sprayed <- setup_irs_events(sip, irs_jdates, irs_type, frac_sprayed) sip
To set up vector control for bed nets, we use setup_bednet_events
and pass it the Julian dates, the net types, and peak access:
<- c(-200, 776, 2176, 3240)
bednet_jdates <- rep("pbo", 4)
bednet_type <- rep(0.95, 4)
bednet_peak <- setup_bednet_events(sip, bednet_jdates, bednet_type, bednet_peak) sip
Before we do any fitting, we want to take a look at the \(t\)-values of the interpolation points. The default spacing is once a year, but if we want to evaluate vector control, we might want values at sensible points before and after the mass distribution events. There’s a lot going on in the following:
The PfPR time series is a set of squares
The line shows the model with preliminary guesses
The vertical lines show the timing of mass distribution / spraying events:
irs is in blue
bednets is in red
the # describes the round (there’s a bednet found before our data start)
the text describes the round
the \(\oplus\) symbols show the original spline \(t\)-values
the purple squares are an alternative spacing for the \(t\)-values returned by
event_chop_spline_t
show_fit(sip)
show_events(sip, mx=0.4)
<- event_chop_spline_t(sip, fu=200, b4=20, mngp=120)
ti points(ti, 0*ti, pch = 15, col = "purple")
To set the stage for evaluating, we’ll shift the spacing of the time points to the purple squares.
<- fitting_replace_spline_t(ti, sip) sip
Fit the Model
Now we fit the model to the data.
<- pr2history_xm(sip) sip
show_fit(sip)
show_events(sip, mx=0.4)
Counterfactual Baseline
To evaluate vector control, we have to grapple with the problem of understanding malaria transmission as a changing baseline that has been modified by control. The challenge for malaria is that every place is different, so we have to learn about each place. The information we have about malaria is limited. What would have happened in the absence of any control?
If all we have is a time series that describes a reality that has been modified by control, what information do we have about the unmodified baseline?
To construct a spline-based counterfactual, there are three steps:
Get information about the baseline
Impute new \(y\)-values for the spline interpolation points
Simulation the baseline
Information about the Baseline
Above, we used show_events
to visualize the history of malaria and the model set up.
In this time series, we note the large gaps between mass distribution events. Perhaps we can use these gaps to make some good guesses about the baseline. We use a function time_since_event
to get a measure of the number of days elapsed since the last event.
time_since_event(sip)
[1] 0 578 956 200 790 1380 200 665 200 375 200 346
If we use the arbitrary cutoff of a year, we find a set of five values for the interpolation points that we trust.
which(time_since_event(sip)>365) -> my_ix
my_ix
[1] 2 3 5 6 8 10
We’re going to modify the object to model a counterfactual. Here, we create models to evaluate bed net rounds 2 and 3.
Impute
Having decided where to get information about the baseline, we need to use it to impute a new baseline value for the \(y\)-values that follow the mass vector control event.
For round 2, we want to impute a new value for the \(4^{th}\) interpolation point, the one that follows the 2nd round (set as impute_ix
in the code block below).
get_yix_after_bednet_round(2, sip)
[1] 4
A somewhat arbitrary decision about what values to trust is to choose the ones that come just before the event, and one that comes just after (trusted_ix
in the code block below). We pull the \(y\)-values and take their mean (set as new_y
) in the block below).
Finally, we impute it (we replace it with new_y
)
= c(4)
impute_ix = c(2,3,5)
trusted_ix fitting_get_spline_ty(sip)$yy[trusted_ix] -> trusted_y
= mean(trusted_y)
new_y fitting_change_spline_y(new_y, impute_ix, sip) -> sip1
There is a function that automates this:
<- impute_spline_y(impute_ix, trusted_ix, sip1, "mean") sip1a
The last argument is an option:
“mean” is the default
Other options are “median,” “min,” “max,” “first,” & “last”
An option called “subsamp” subsamples the variates
An option called “gam” fits a gamma distribution and returns random variates
Compute Impact
<- max(prts$jdates)
last_day <- min(prts$jdates)
first_day <- c(first_day:last_day)
tm <- xds_solve(sip, times = tm) sip
<- xds_solve(sip1, times = tm)
sip1 xds_plot_PR(sip1, clrs="darkred")
xds_plot_PR(sip, clrs="darkblue", add = T)
<- sip$events_obj$bednet$jdate[2]
round_start = round_start + 1:365
eval_period <- get_PR(sip)[eval_period]
pr <- get_PR(sip1)[eval_period]
pr1 = mean(pr1-pr)
impact plot(eval_period, pr1-pr, type = "l", ylab = "PR Difference", main = round(impact*1000)/1000)
To make all this easier, we wrote a wrapper to compute measures of impact:
<- sip$events_obj$bednet$jdate[2]
round_start = compute_impact(sip, sip1, event_date=round_start)
impact names(impact)
[1] "pr_hist" "pr_base" "pr_averted_ts" "d_pr_max"
[5] "d_pr_mean" "t_eval" "event_date"
with(impact, {
plot(pr_base, type ="l", col = "darkred")
lines(pr_hist, col = "darkblue")
segments(event_date,0, event_date, max(pr_base))
})
with(impact, {
plot(pr_averted_ts, type ="l", col = "purple4")
})
<- impute_spline_y(7, c(5,6), sip)
sip2 <- sip$events_obj$bednet$jdate[3]
round_start <- compute_impact(sip, sip2, event_date=round_start) impact2
with(impact2, {
plot(pr_base, type ="l", col = "darkred")
lines(pr_hist, col = "darkblue")
segments(event_date,0, event_date, max(pr_base))
})
with(impact2, {
plot(pr_averted_ts, type ="l", col = "purple4")
})