ramp.xds
X-How_To_Add_Model.Rmd
This vignette discusses how to add a new model family to ramp.library
that can be used by ramp.xds
.
This vignette covers models of parasite infection dynamics and immunity
in humans or other hosts – the dynamical components we have denoted
$\cal X$ and $\cal H.$
We have written this vignette to produce a new template file using
knitr::purl,
which can be modified to build a new model.
Simply execute the following command, to create
Xmod-newXname.R.
Then, rename Xmod-newXname.R
by replacing newXname
in the filename. Then open the file
and do a global search for newXname
and replace it with
your new name.
knitr::purl("X-How_To_Add_Model.Rmd",
output = "Xmod-newXname.R",
documentation = 0,
quiet=TRUE)
This is a good start, but there’s more work to do. For more details, read the text that follows.
This basic introduction is lacking some information that typical users might find useful. In particular, we have defined best practices encoding the $\cal H$ component of models. A vignette is planned.
This package – ramp.library
– contains reusable code
that has been rigorously tested and that implements a large number of
dynamical model families and other algorithms taken from the literature
describing malaria and other mosquito-transmitted pathogens (see Reiner,
et al. 2013)1. The supporting code was designed to be
modular, and plug-and-play. The modular design makes it possible to
break down published models to serve as the dynamical components in new
models for malaria. The model families in ramp.library
supports nimble model building that can be used by:
ramp.xds
implements a modular, flexible, and extensible framework for building
systems of ordinary and delay differential equations models for malaria
and other mosquito-transmitted pathogens. The mathematic framework for
ramp.xds
was explained in Spatial Dynamics of Malaria Transmission 2
ramp.dts
implements a modular, flexible, and extensible framework for building
discrete time systems, including both deterministic and stochastic
difference equations for malaria and other mosquito-transmitted
pathogens.
This vignette was written to help add new models to
ramp.xds.
In planned companion to this vignette, we show how to add models of
$\cal XH$ to ramp.dts
.
A new model family of class $\cal
XH$ – human infection dynamics, including immunity – has 17
required functions encoded using a standard template. Some of these
required functions are S3
class functions in human-interface.R, and several examples are posted
in the ramp.xds
github repository, including the
SIS
model human-SIS.R.
To configure a new model, you must choose a string called
newXname
. The only rule for choosing newXname
is that it must be unique. No other ${\cal
XH}$ class model in ramp.xds
or
ramp.library
can be using that string already. All the
S3
functions get dispatched by the string that replaces
newXname.
The 17 required functions are:
Derivatives
dXdt.newXname
- differential equations are defined by a
system of differential equations. in ramp.xds
these are
encoded in a function called dXdt
that computes and returns
the derivatives. The function is set up so that the
system can be solved by deSolve::ode
or
deSolve::dede.
Variables - A set of functions is set up that document the variables by name and assign each one an index, to store, assign and update initial values. These functions streamline setup, and guarantee consistency.
create_Xinits_newXname
- each model requires a
function that documents the variables by name and assigns initial
values
make_Xinits.newXname
- is a wrapper, that gets
called by ramp.xds::xde_setup.
It gets called by
create_Xinits_newXname,
and for the
host, the initial values are stored as
pars$Xinits[[i]].
make_indices_X.newXname
- is the function that
assigns an index to each variable in the model, and stores it as
pars$ix$X[[i]].
The indices are returned as a named
list.
list_Xvars.newXname
- retrieves the value of
variables at a point in time and returns the values by name in a list;
the function gets called by dXdt
and by
update_Xinits
and it can be useful in other
contexts.
get_inits_X.newXname
- retrieves the stored initial
values in the same order that they are returned by
dXdt.newXname
update_Xinits.newXname
- a utility that makes it
possible to extract and store a new set of initial values for
newXname
from a vector
holding all the variables in a model.
Parameters
create_Xpar_newXname
returns a formatted list:
the parameter values are stored by name
class(pars)
= newXname
make_Xpar.newXname
is a wrapper that calls
create_Xpar_newXname
Dynamical Terms are Computed using a Standard Set of Functions
F_X.newXname
- compute the effective infective
density of the vertebrate hosts
F_H.newXname
- compute the human population density
for the host strata
F_b.newXname
- compute the probability a most will
become infected after receiving an infective bite, which combines
elements of this $\cal X$ model with a
model of environmental heterogeneity in Exposure.
Outputs
parse_deout_X.newXname
- this function parses the
output of deSolve
and returns a named list that is either a
vector or a matrix holding the values of the variables at each point in
time. It works like list_Xvars,
which accepts a vector
holding
,
the values of the variables at a single point in time.
F_pr.newXname
- this function takes
HTC.newXname
Outputs
xds_lines_X.newXname
xds_plot_X.newXname
is a wrapper that calls
xds_lines_X
We recommend that new models conform to a set of style guidelines:
All the names of the variables by name using the indices attached
to Xpar
All documentation is written in roxygen2
Functions should use with(*,{...})
to make the code
easier to read.
A vignette should accompany each model, including citations to the relevant publications, and proposed tests of the code.
The functions should easy to relate to the equations defining a model, following notation defined in an accompanying vignette.
The function dXdt
is established as a generic function
that dispatches on Xpar.
Since there might be many host
species, it actually dispatches on the
element in a list, pars$Xpar[[i]].
#' @title Derivatives for human population
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param t current simulation time
#' @param y state vector
#' @param pars a list
#' @param i the host species index
#' @return a [numeric] vector
#' @export
dXdt <- function(t, y, pars, i) {
UseMethod("dXdt", pars$Xpar[[i]])
}
This is a version of the SIS
model in
ramp.xds
with demographics. If a model has any demographic
processes (e.g. aging, migration, births and deaths), then each
variable’s derivative must be transformed by the same matrix as the
human population density, H
. Any disease induced mortality
should be included in a matrix that computes changes in human population
density, dHdt
.
In the following, we use the with()
function to expose
parameter names attached to lists to make the code easy to read.
#' @title Derivatives for human population
#' @description Implements [dXdt] for the SIS model, no demography.
#' @inheritParams dXdt
#' @return a [numeric] vector
#' @export
dXdt.SIS <- function(t, y, pars, i) {
foi <- pars$FoI[[i]]
with(list_Xvars(y, pars, i),{
H <- F_H(t, y, pars, i)
with(pars$Xpar[[i]], {
dS <- Births(t, H, pars, i) - foi*S + r*I + dHdt(t, S, pars, i)
dI <- foi*S - r*I + dHdt(t, I, pars, i)
return(c(dS, dI))
})
})
}
This should be straightforward, but there’s one very
important wrinkle. If you want to be able to use the
ramp.xds
capabilities for cohort dynamics and vital
dynamics, then the dynamics must be extended carefully to call the
demographic matrix function dHdt.
This can become tricky,
so we handle it elsewhere. When writing the code:
The foi gets computed in Exposure
and stored as
pars$FoI[[i]]
for the
host species.
In the next step, the variables are extracted from the variable
vector, y
, using the indices, which are stored in
pars$ix$X[[i]]
We compute the derivatives.
We return the variables in order. Be sure to establish and then maintain a convention for ordering the variables in your model, and then maintain that order in every function. In particular:
set up the initial values in that order
return the derivatives in that order
Be careful about how you nest the with(*, ...)
calls.
#' @title Compute the derivatives for parasite infection dynamics in human population strata
#' @description Implements [dXdt] for the newXname model
#' @inheritParams ramp.xds::dXdt
#' @return a [numeric] vector
#' @export
dXdt.newXname <- function(t, y, pars, i) {
# do not change this
foi <- pars$FoI[[i]]
# attach the variables by name
with(list_Xvars(y, pars, i),{
# compute H (if it isn't one of the variables)
H <- F_H(t, y, pars, i)
# expose the parameters (see create_Xpar_Xname)
with(pars$Xpar[[i]], {
# compute the derivatives
dX1 <- ...
dX2 <- ...
...
# concatenate the derivatives
derivs = c(dX1, dX2, ...)
# return the derivatives
return(derivs)
})
})
}
#' @title Make initial values for the SIS human model, with defaults
#' @param nStrata the number of strata in the model
#' @param Xopts a [list] to overwrite defaults
#' @param H0 the initial human population density
#' @param S0 the initial values of the parameter S
#' @param I0 the initial values of the parameter I
#' @return a [list]
#' @export
create_Xinits_SIS = function(nStrata, Xopts = list(), H0=NULL, S0=NULL, I0=1){with(Xopts,{
if(is.null(S0)) S0 = H0 - I0
stopifnot(is.numeric(S0))
S = checkIt(S0, nStrata)
I = checkIt(I0, nStrata)
return(list(S=S, I=I))
})}
#' @title Make initial values for the Xname human model, with defaults
#' @param nStrata the number of strata in the model
#' @param Xopts a [list] to overwrite defaults
#' @param X10 the initial value for X1
#' @param X20 the initial value for X1
#' @return a [list]
#' @export
create_Xinits_newXname = function(nStrata, Xopts = list(), X10=NULL, X20=1){with(Xopts,{
stopifnot(is.numeric(X10))
stopifnot(is.numeric(X20))
X1 = checkIt(X10, nStrata)
X2 = checkIt(X20, nStrata)
return(list(X1=X1, X2=X2, ...))
})}
In the xde_setup
family of setup functions, initial
values for a model fulfilling the dynamical component $\cal X,$ called newXname
is set
up by the function make_Xinits.
The make_Xinits.SIS
calls
create_Xinits_SIS
#' @title Setup Xinits.SIS
#' @description Implements [make_Xinits] for the SIS model
#' @inheritParams make_Xinits
#' @return a [list] vector
#' @export
make_Xinits.SIS = function(pars, i, Xopts=list()){
pars$Xinits[[i]] = with(pars, create_Xinits_SIS(pars$Hpar[[i]]$nStrata, Xopts, H0=Hpar[[i]]$H))
return(pars)
}
To modify, replace newXname
#' @title Setup Xinits.newXname
#' @description Implements [make_Xinits] for the newXname model
#' @inheritParams ramp.xds::make_Xinits
#' @return a [list] vector
#' @export
make_Xinits.newXname = function(pars, i, Xopts=list()){
pars$Xinits[[i]] = with(pars, create_Xinits_newXname(pars$Hpar[[i]]$nStrata, Xopts, H0=Hpar[[i]]$H))
return(pars)
}
#' @title Add indices for human population to parameter list
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param pars a [list]
#' @param i the host species index
#' @return a [list]
#' @export
make_indices_X <- function(pars, i) {
UseMethod("make_indices_X", pars$Xpar[[i]])
}
#' @title Add indices for human population to parameter list
#' @description Implements [make_indices_X] for the SIS model.
#' @inheritParams ramp.xds::make_indices_X
#' @return none
#' @importFrom utils tail
#' @export
make_indices_X.SIS <- function(pars, i) {with(pars,{
S_ix <- seq(from = max_ix+1, length.out=Hpar[[i]]$nStrata)
max_ix <- tail(S_ix, 1)
I_ix <- seq(from = max_ix+1, length.out=Hpar[[i]]$nStrata)
max_ix <- tail(I_ix, 1)
pars$max_ix = max_ix
pars$ix$X[[i]] = list(S_ix=S_ix, I_ix=I_ix)
return(pars)
})}
#' @title Add indices for human population to parameter list
#' @description Implements [make_indices_X] for the newXname model.
#' @inheritParams make_indices_X
#' @return none
#' @importFrom utils tail
#' @export
make_indices_X.newXname <- function(pars, i) {with(pars,{
X1_ix <- seq(from = max_ix+1, length.out=Hpar[[i]]$nStrata)
max_ix <- tail(X1_ix, 1)
X2_ix <- seq(from = max_ix+1, length.out=Hpar[[i]]$nStrata)
max_ix <- tail(X2_ix, 1)
...
pars$max_ix = max_ix
pars$ix$X[[i]] = list(X1_ix=X1_ix, X2_ix=X2_ix, ...)
return(pars)
})}
#' @title Return the variables as a list
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param y the variables
#' @param pars a [list]
#' @param i the host species index
#' @return a [list]
#' @export
list_Xvars <- function(y, pars, i) {
UseMethod("list_Xvars", pars$Xpar[[i]])
}
#' @title Return the variables as a list
#' @description This method dispatches on the type of `pars$Xpar`
#' @inheritParams ramp.xds::list_Xvars
#' @return a [list]
#' @export
list_Xvars.newXname <- function(y, pars, i) {
with(pars$ix$X[[i]],{
X1 = y[X1_ix]
X2 = y[X2_ix]
...
H = X1+X2+...
return(list(X1=X1,X2=X2,...,H=H))})
}
By now the pattern should be obvious.
#' @title Return initial values as a vector
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param pars a [list]
#' @param i the host species index
#' @return none
#' @export
get_inits_X <- function(pars, i) {
UseMethod("get_inits_X", pars$Xpar[[i]])
}
Pass a vector y
, extract the values of the variables,
and modify the initial values.
#' @title Set the initial values from a vector of states
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param pars a [list]
#' @param y0 a vector of initial values
#' @param i the host species index
#' @return none
#' @export
update_Xinits <- function(pars, y0, i) {
UseMethod("update_Xinits", pars$Xpar[[i]])
}
#' @title Update inits for the SIS human model from a vector of states
#' @inheritParams update_Xinits
#' @return none
#' @export
update_Xinits.SIS <- function(pars, y0, i) {
with(list_Xvars(y0, pars, i),{
pars$Xinits[[i]] = create_Xinits_SIS(pars, list(), S0=S, I0=I)
return(pars)
})}
#' @title Update inits for the newXname human model from a vector of states
#' @inheritParams ramp.xds::update_Xinits
#' @return none
#' @export
update_Xinits.newXname <- function(pars, y0, i) {
with(list_Xvars(y0, pars, i),{
pars = create_Xinits_newXname(pars, list(), X10=X1, X20=X2, ...)
return(pars)
})}
The second function sets up a list Xpar
that dispatches
dXdt
and that has the parameter values.
There is no S3
definition for the
create_Xpar_*
class of functions. Instead, we write a
generic S3
function called make_Xpar
that
calls a function make_Xpar_*
There is, nevertheless, a
reasonably standard formula for make_Xpar_*
The first argument is nStrata
the number of
population strata for the species.
The first argument is Xopts().
Notice that
Xopts()
is an empty list by default, but if a non-empty
list is passed, the values overwrite the defaults.
The parameters are attached by name. These parameter names must
be the same ones used in dXdt
By default, they should have
length(*)= nStrata
The last part of the function name is the string that dispatches
the S3
functions. In create_Xpar_SIS,
we write
class(Xpar) <- "SIS"
#' @title Make parameters for SIS human model, with defaults
#' @param nStrata is the number of population strata
#' @param Xopts a [list] that could overwrite defaults
#' @param b transmission probability (efficiency) from mosquito to human
#' @param c transmission probability (efficiency) from human to mosquito
#' @param r recovery rate
#' @return a [list]
#' @export
create_Xpar_SIS = function(nStrata, Xopts=list(),
b=0.55, r=1/180, c=0.15){
with(Xopts,{
Xpar = list()
class(Xpar) <- "SIS"
Xpar$b = checkIt(b, nStrata)
Xpar$c = checkIt(c, nStrata)
Xpar$r = checkIt(r, nStrata)
return(Xpar)
})}
To format this for a new function, do a search and replace on
newXname
and replace the parmeter names and values
,
,
#' @title Make parameters for newXname human model, with defaults
#' @param nStrata is the number of population strata
#' @param Xopts a [list] that could overwrite defaults
#' @param p1 the first parameter
#' @param p2 the second parameter
#' @param p3 the third parameter
#' @return a [list]
#' @export
create_Xpar_newXname = function(nStrata, Xopts=list(),
p1=1, p2=2, p3=3){
with(Xopts,{
Xpar = list()
class(Xpar) <- c("newXname")
Xpar$p1 = checkIt(p1, nStrata)
Xpar$p2 = checkIt(p2, nStrata)
Xpar$p3 = checkIt(p3, nStrata)
return(Xpar)
})}
In the xde_setup
family of setup functions, setup for a
model fulfilling the dynamical component $\cal
X,$ called newXname
is set up by the function
make_Xpar.
This function must set up Xpar
and it must also set up
the initial values. By convention, the functions that get called are not
S3
class functions.
The make_Xpar
functions assigns to Xname
the class(Xname)
and dispatches on Xname
#' @title A function to set up Xpar
#' @description This method dispatches on `Xname`.
#' @param Xname a [character] string
#' @param pars a [list]
#' @param i the host species index
#' @param Xopts a [list]
#' @return a [list]
#' @export
make_Xpar = function(Xname, pars, i, Xopts=list()){
class(Xname) <- Xname
UseMethod("make_Xpar", Xname)
}
To use this, simply to a search and replace on
newXname.
#' @title Setup Xpar.newXname
#' @description Implements [make_Xpar] for the newXname model
#' @inheritParams ramp.xds::make_Xpar
#' @return a [list] vector
#' @export
make_Xpar.newXname = function(newXname, pars, i, Xopts=list()){
pars$Xpar[[i]] = create_Xpar_newXname(pars$Hpar[[i]]$nStrata, Xopts)
return(pars)
}
All models in ramp.xds
the modular design dictates that
we must define a few functions that compute a few key quantities:
X
is defined to be the effective density of
infectious humans, retrieved by F_X
H
is defined to be the size of each population
stratum, retrieved by F_H
b
is defined to be the fraction of infective bites
that cause an infection, retrieved by F_b
The function F_X
returns the effective density of
infectious humans for each stratum. The notion is that
is proportional to
,
where the constant is the fraction of bites on the strata that would
infect a mosquito.
#' @title Size of effective infectious human population
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param y state vector
#' @param pars a list
#' @param i the host species index
#' @return a [numeric] vector of length `nStrata`
#' @export
F_X <- function(y, pars, i) {
UseMethod("F_X", pars$Xpar[[i]])
}
As an example, we include the
model from ramp.xds.
In the SIS
model, the
returned value is
where
is the density of infected individuals; the prevalence of infection is
.
The constant
is the probability a mosquito would become infected after blood feeding
on an infected human. Two things to note:
ramp.xds
holds the indices by component under
pars$ix,
so pars$ix$X
holds the indices for
all the variables for all species, and pars$ix$X[[i]]
holds
the indices for the
species. Putting them under X
helps to avoid conflicts if,
for example, another dynamical component happened to use the same
variable name.
#' @title Size of effective infectious human population
#' @description Implements [F_X] for the SIS model.
#' @inheritParams F_X
#' @return a [numeric] vector of length `nStrata`
#' @export
F_X.SIS <- function(y, pars, i) {
I = y[pars$ix$X[[i]]$I_ix]
X = with(pars$Xpar[[i]], c*I)
return(X)
}
The commented code relevant code that must be changed is commented out. The preferred style is to extract the relevant variables by name, then compute the effective infectious density,or individuals in this stratum, then return the value. In the manuscript, this quantity was called X.
The following is a template for new model. The declaration of
inheritParams
from the SIS
model in
ramp.xds
works naturally. The namespace from
ramp.xds
is needed, so our newXname function (above) has
ramp.xds::F_X.
The steps are to extract the variables in
#' @title Size of effective infectious human population
#' @description Implements [F_X] for the SIS model.
#' @inheritParams ramp.xds::F_X
#' @return a [numeric] vector of length `nStrata`
#' @export
F_X.newXname <- function(y, pars, i) {
########################
# extract:
# VAR <- y[pars$ix$X$...]
########################
with(pars$Xpar[[i]],
########################
# compute:
# X <- ... F(VAR)
########################
)
return(X)
}
The total population size, , is often important, so we write a function that computes it.
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param y state vector
#' @param pars a list
#' @param i the host species index
#' @return a [numeric] vector of length `nStrata`
#' @export
F_H <- function(y, pars, i) {
UseMethod("F_H", pars$Xpar[[i]])
}
This is the function that computes
for the SIS
model.
#' @title Size of effective infectious human population
#' @description Implements [F_H] for the SIS model.
#' @inheritParams F_H
#' @return a [numeric] vector of length `nStrata`
#' @export
F_H.SIS <- function(y, pars, i){
with(list_Xvars(y, pars, i), return(H))
}
The function F_X
returns the effective density of
infectious humans for each stratum. The following is a template for a
model, assuming
is computed in list_Xvars
:
#' @title Size of effective infectious human population
#' @description Implements [F_H] for the newXname model.
#' @inheritParams ramp.xds::F_H
#' @return a [numeric] vector of length `nStrata`
#' @export
F_H.newXname <- function(y, pars, i){
with(list_Xvars(y, pars, i), return(H))
}
We use the short parameter name b
to denote the fraction
of infective bites by mosquitoes that cause an infection. This is
computed in another function, called Exposure
under a model
for environmental heterogeneity that computes a local FoI based on the
local daily EIR. Then, the total FoI is computed from a travel
model.
#' @title Infection blocking pre-erythrocytic immunity
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param y state vector
#' @param pars a list
#' @param i the host species index
#' @return a [numeric] vector of length `nStrata`
#' @export
F_b <- function(y, pars, i) {
UseMethod("F_b", pars$Xpar[[i]])
}
F_b.SIS
In ramp.xds,
we recognize the problem of translating the
local EIR into the FoI. The local EIR is computed as one of the core
model terms for each one of the model strata.
The function F_b
returns the model-defined probability
an infective bite by a mosquito would cause an infection. This could
include the combined effects of inefficient transmission,
pre-erytrocytic immunity, and perhaps some effects of blood stage
immunity. In a model with no effect, the return value would be
.
Once again, we provide the SIS
model from
ramp.xds
as our example:
Depending on the model, the value of b
is either
retrieved or it is computed from other variables in the model, and it is
expected that length(b) = nStrata
#' @title Infection blocking pre-erythrocytic immunity
#' @description Implements [F_b] for the newXname model.
#' @inheritParams ramp.xds::F_b
#' @return a [numeric] vector of length `nStrata`
#' @export
F_b.newXname <- function(y, pars, i) {
with(pars$Xpar[[i]],{
########################
# retrieve or compute it
########################
b = pars$Xpar[[i]]$b
########################
# return it
########################
return(b)
})
}
To make ramp.xds
easy to use, we provide some functions
that parse the outputs and compute some standard metrics.
parse_deout_X
parse_deout_X
takes the output of deSolve,
parses the outputs using the variable indices, and returns the variables
by name as a list.
#' @title Parse the output of deSolve and return the variables by name in a list
#' @description This method dispatches on the type of `pars$Xpar`. Adds the variables
#' from the X model to a list and returns it
#' @param deout a [matrix] of outputs from deSolve
#' @param pars a [list] that defines a model
#' @param i the host species index
#' @export
parse_deout_X <- function(deout, pars, i) {
UseMethod("parse_deout_X", pars$Xpar[[i]])
}
#' @title Parse the output of deSolve and return variables for the SIS model
#' @description Implements [parse_deout_X] for the SIS model
#' @inheritParams parse_deout_X
#' @return none
#' @export
parse_deout_X.SIS <- function(deout, pars, i) {
time = deout[,1]
with(pars$ix$X[[i]],{
S = deout[,S_ix+1]
I = deout[,I_ix+1]
H = S+I
return(list(time=time, S=S, I=I, H=H))
})}
#' @title Parse the output of deSolve and return variables for the newXname model
#' @description Implements [parse_deout_X] for the newXname model
#' @inheritParams ramp.xds::parse_deout_X
#' @return none
#' @export
parse_deout_X.newXname <- function(deout, pars, i) {
time = deout[,1]
with(pars$ix$X[[i]],{
X1 = deout[,X1_ix+1]
X2 = deout[,X2_ix+1]
...
H = X1 + X2 + ...
return(list(time=time, X1=X1, X2=X2, ..., H=H))
})}
We require each model to compute the true PR.
#' @title Compute the *true* prevalence of infection / parasite rate
#' @description This method dispatches on the type of `pars$Xpar[[i]]`.
#' @param vars a list with the variables attached by name
#' @param Xpar a list defining a model for human
#' @return a [numeric] vector of length `nStrata`
#' @export
F_pr <- function(vars, Xpar) {
UseMethod("F_pr", Xpar)
}
#' @title Compute the "true" prevalence of infection / parasite rate
#' @description Implements F_pr for the SIS model.
#' @inheritParams F_pr
#' @return a [numeric] vector of length `nStrata`
#' @export
F_pr.SIS <- function(vars, Xpar) {
pr = with(vars, I/H)
return(pr)
}
The function F_pr
computes the models true
prevalence using the variable names. It is passed the
varslist
that is created by parse_deout
(see
above).
#' @title Compute the true prevalence of infection / parasite rate
#' @description Implements F_pr for the newXname model.
#' @inheritParams F_pr
#' @return a [numeric] vector of length `nStrata`
#' @export
F_pr.newXname <- function(vars, Xpar) {
pr = with(vars, with(Xpar,(return(X1/H))))
return(pr)
}
Similarly, we require each function to return the human transmitting
capacity, or HTC
#' @title Compute the human transmitting capacity
#' @description This method dispatches on the type of `pars$Xpar`.
#' @param pars a [list]
#' @param i the host species index
#' @return none
#' @export
HTC <- function(pars, i) {
UseMethod("get_inits_X", pars$Xpar[[i]])
}
#' Add lines for the density of infected individuals for the SIS model
#'
#' @param XH a list with the outputs of parse_deout_X_SIS
#' @param nStrata the number of population strata
#' @param clrs a vector of colors
#' @param llty an integer (or integers) to set the `lty` for plotting
#'
#' @export
xds_lines_X_SIS = function(XH, nStrata, clrs=c("darkblue","darkred"), llty=1){
with(XH,{
if(nStrata==1) {
lines(time, S, col=clrs[1], lty = llty[1])
lines(time, I, col=clrs[2], lty = llty[1])
}
if(nStrata>1){
if (length(clrs)==2) clrs=matrix(clrs, 2, nStrata)
if (length(llty)==1) llty=rep(llty, nStrata)
for(i in 1:nStrata){
lines(time, S[,i], col=clrs[1,i], lty = llty[i])
lines(time, I[,i], col=clrs[2,i], lty = llty[i])
}
}
})}
#' Add lines for the density of infected individuals for the newXname model
#'
#' @param XH a list with the outputs of parse_deout_X_newXname
#' @param nStrata the number of population strata
#' @param clrs a vector of colors
#' @param llty an integer (or integers) to set the `lty` for plotting
#'
#' @export
xds_lines_X_newXname = function(XH, nStrata, clrs=c("darkblue","darkred"), llty=1){
with(XH,{
if(nStrata==1) {
lines(time, S, col=clrs[1], lty = llty[1])
lines(time, I, col=clrs[2], lty = llty[1])
}
if(nStrata>1){
if (length(clrs)==2) clrs=matrix(clrs, 2, nStrata)
if (length(llty)==1) llty=rep(llty, nStrata)
for(i in 1:nStrata){
lines(time, S[,i], col=clrs[1,i], lty = llty[i])
lines(time, I[,i], col=clrs[2,i], lty = llty[i])
}
}
})}
We provide a basic plotting function. The function
xds_lines_X_*
does not have an S3
version.
Instead, it is called by the S3
function
xds_plot_X
#' Basic plotting for epidemiological models
#'
#' @param pars a list that defines an `ramp.xds` model (*e.g.*, generated by `xde_setup()`)
#' @param i the host species index
#' @param clrs a vector of colors
#' @param llty an integer (or integers) to set the `lty` for plotting
#' @param stable a logical: set to FALSE for `orbits` and TRUE for `stable_orbits`
#' @param add_axes a logical: plot axes only if TRUE
#'
#' @export
xds_plot_X = function(pars, i=1, clrs="black", llty=1, stable=FALSE, add_axes=TRUE){
UseMethod("xds_plot_X", pars$Xpar[[i]])
}
#' Plot the density of infected individuals for the newXname model
#'
#' @inheritParams ramp.xds::xds_plot_X
#' @export
xds_plot_X.SIS = function(pars, i=1, clrs=c("darkblue","darkred"), llty=1, stable=FALSE, add_axes=TRUE){
vars=with(pars$outputs,if(stable==TRUE){stable_orbits}else{orbits})
if(add_axes==TRUE)
with(vars$XH[[i]],
plot(time, 0*time, type = "n", ylim = c(0, max(H)),
ylab = "# Infected", xlab = "Time"))
xds_lines_X_SIS(vars$XH[[i]], pars$Hpar[[i]]$nStrata, clrs, llty)
}
#' Plot the density of infected individuals for the newXname model
#'
#' @inheritParams ramp.xds::xds_plot_X
#' @export
xds_plot_X.newXname = function(pars, i=1, clrs=c("darkblue","darkred"), llty=1, stable=FALSE, add_axes=TRUE){
vars=with(pars$outputs,if(stable==TRUE){stable_orbits}else{orbits})
if(add_axes==TRUE)
with(vars$XH[[i]],
plot(time, 0*time, type = "n", ylim = c(0, max(H)),
ylab = "# Infected", xlab = "Time"))
xds_lines_X_newXname(vars$XH[[i]], pars$Hpar[[i]]$nStrata, clrs, llty)
}
Reiner RC Jr, Perkins TA, Barker CM, Niu T, Chaves LF, Ellis AM, et al. A systematic review of mathematical models of mosquito-borne pathogen transmission: 1970-2010. J R Soc Interface. 2013;10: 20120921.↩︎
Wu SL, Henry JM, Citron DT, Mbabazi Ssebuliba D, Nakakawa Nsumba J, Sánchez C. HM, et al. (2023) Spatial dynamics of malaria transmission. PLoS Comput Biol 19(6): e1010684. https://doi.org/10.1371/journal.pcbi.1010684↩︎