52  Appendix: Model-Running APIs: Partners, Trackers, and Scenarios

Building a research-level model is rarely just writing the disease modules. You also need to query who partnered whom to model contact tracing, extract the exact output statistic your paper reports, and vary parameters over time to represent an intervention. EpiModel has a dedicated interface for each. This chapter is a tour of the three you will reach for most: what each concept is, a small illustration, and where the complete reference lives. Each is documented in full in the EpiModel package vignettes at epimodel.org; here we give you the concept and the “when.”

52.1 Partnership histories: who partnered whom, over time

A current edgelist tells you who is partnered right now. Many research questions need the history: who has this person ever partnered, and when. Contact tracing, partner notification, and reachability analysis all depend on it. EpiModel records this as the cumulative edgelist, every partnership with the time steps it started and stopped, keyed by a node’s permanent unique_id so that partners who have since departed the population are still findable.

You turn it on in control.net():

control <- control.net(type = "SI", nsteps = 100,
                       cumulative.edgelist = TRUE,       # track during the run
                       save.cumulative.edgelist = TRUE)  # keep it on the output

Inside a module, the workhorse is get_partners(), which returns the partners of a set of index nodes from that history:

# In a contact-tracing module: find the partners of the newly diagnosed
partners <- get_partners(dat, index_posit_ids = newly_diagnosed_ids)

The result lists each index node and its partner (by unique_id), which a tracing module then acts on, notifying, testing, or treating them. Related helpers extract the raw history (get_cumulative_edgelist()), count distinct lifetime partners (get_cumulative_degree()), and trace chains of transmission forward or backward in time (get_forward_reachable(), get_backward_reachable()).

NoteSee it in the Gallery

Two Gallery examples are built directly on this interface: SEIR with Contact Tracing traces and quarantines the recent partners of diagnosed cases, and Partner Notification for an Endemic STI notifies and treats them. Read either as the worked realization of get_partners(). The full partnership-history and reachability API is in the Working with Network Objects vignette.

52.2 Getting the output your research question needs

By default a netsim run records compartment counts (s.num, i.num, …) and flows (si.flow, …). Your paper almost always reports something else, prevalence, an incidence rate, an outcome stratified by subgroup, a cost. EpiModel gives you three levels of tool, cheapest first.

Stratify automatically. The epi.by argument in control.net() breaks every compartment count out by a nodal attribute:

control <- control.net(type = "SI", nsteps = 50, epi.by = "risk")
# output now includes i.num.risk0, i.num.risk1, num.risk0, ...

Derive after the fact. mutate_epi() computes new time series from existing ones without re-running the model, exactly like dplyr::mutate():

sim <- mutate_epi(sim, prev = i.num / num)
sim <- mutate_epi(sim, ir = (si.flow / s.num) * 100)   # incidence rate per 100

Track anything, per step. For a quantity the built-ins do not provide, compute it inside a module and record it with set_epi(). This is the same read-process-write pattern from Module 9: read the attributes you need, compute the summary, and write it to the epidemic output. For example, a module that records the proportion infected at each step:

prop_infected <- function(dat, at) {
  status <- get_attr(dat, "status")
  active <- get_attr(dat, "active")
  prop   <- sum(status == "i" & active == 1) / sum(active == 1)
  dat    <- set_epi(dat, "prop_infected", at, prop)
  return(dat)
}

Wire it in through a control.net() module slot as in Module 9, and prop_infected appears in the output alongside i.num and the rest.

NoteFull reference

set_epi(), epi.by, mutate_epi(), and the related attribute-history tools are documented in the Working with Custom Attributes and Summary Statistics vignette. Record a statistic with set_epi() in a module whenever you catch yourself wanting to re-run the model just to add one more number.

52.3 Time-varying parameters and scenarios

Parameters need not be constant. An intervention that rolls out partway through an epidemic, a behavioral shift, a policy that switches on and off, all of these are parameters that change over time. The recommended interface is scenarios: named sets of parameter changes applied at chosen time steps, which double as the natural way to compare policy alternatives.

A scenario set is a data.frame with two reserved columns, .scenario.id and .at (the time step, 0 for changes before the run), plus one column per parameter:

library(dplyr)
scenarios.df <- tribble(
  ~.scenario.id,       ~.at, ~inf.prob, ~rec.rate,
  "base",                 0,       0.9,      0.01,
  "intervention",         0,       0.9,      0.01,
  "intervention",       100,       0.3,      0.01   # transmission drops at step 100
)
scenarios.list <- create_scenario_list(scenarios.df)

You then loop over the scenarios, applying each to the base parameters with use_scenario() and running the model:

for (scenario in scenarios.list) {
  sc.param <- use_scenario(param, scenario)
  sim <- netsim(est, sc.param, init, control)
  # ... collect and label the output ...
}

The "intervention" scenario above runs at baseline until step 100, when inf.prob drops, letting you read the counterfactual straight off the overlaid curves.

NoteSee it in the Gallery, and the fuller toolkit

SIR with Time-Varying (Phased) Vaccination is a worked campaign that switches on and off over time. Beyond scenarios, the same interface supports random parameters (draw values from distributions for uncertainty analysis, via random.params), parameter tables (manage many parameters from a spreadsheet, via data.frame.params), and low-level updaters for relative or function-based changes. All are in the Working with Model Parameters vignette. Scenarios are the right default; reach for the others only when scenarios cannot express what you need.

For epidemic parameters more broadly, note the division of labor across this course: Module 10 is about parameterizing the network structure from data, while this section is about managing the epidemic parameters that run on top of it. They are two different senses of “parameterization,” and a full model needs both.