43  SEIR/SEIRS Lab

In the tutorial you built the SEIR extension by hand to learn the module API. In this lab you turn that SEIR model into an SEIRS model (recovered individuals lose immunity and return to susceptible), but instead of rebuilding it from scratch, you will read, run, and modify a maintained, parameterized version from the EpiModel Gallery.

The Gallery example SEIR/SEIRS Model: Adding an Exposed State provides both SEIR and SEIRS from a single module: setting one parameter, the waning-immunity rate rs.rate, above zero adds the R-to-S transition. That is exactly the extension the old version of this lab had you write by hand, so here we use it as the object of study rather than re-derive it.

Note

This lab works directly with the Gallery’s standalone scripts. It is the maintained, CI-tested version of the SEIR/SEIRS code; the tutorial’s hand-built copy exists to teach the API, and this is the copy you would actually reuse in your own work.

43.1 Setup

Each Gallery example is a folder under examples/<slug>/ holding two scripts:

  • model.R: the network estimation and the epidemic run.
  • module-fx.R: the custom infect and progress module functions.

Clone the whole Gallery repository and run from the repository root, not from inside the example folder:

git clone https://github.com/EpiModel/EpiModel-Gallery.git
cd EpiModel-Gallery

Then, from that repository root:

# from the EpiModel-Gallery repo root
source("examples/seir-exposed-state/model.R")

Running from the root is not a preference, it is required: model.R loads its module functions with source("examples/seir-exposed-state/module-fx.R"), a path written relative to the repository root. Downloading the two scripts into a folder of their own, or setting your working directory to the example folder, will fail at that line. Open the two scripts side by side with the rendered example page.

43.2 Lab Steps

NoteStep 1: Read the module functions

Before running anything, read module-fx.R against the compartment diagram on the example page (S to E to I to R, with the dashed R-to-S waning arrow). For each of the two module functions, write one line answering: what does it read off dat, what does it do, and what does it write back? These are the three API rules from the tutorial. Note specifically where rs.rate is used and which transition it controls.

NoteStep 2: Run the SEIR model

Run model.R unchanged. Confirm that with rs.rate = 0 the epidemic behaves as an SEIR model: it burns through the susceptible pool and then fades, because recovered individuals stay immune. Plot the compartment counts and note the shape of the i.num curve.

NoteStep 3: Turn SEIR into SEIRS, predict first

Now the one-parameter change. Before you run it: predict how raising rs.rate above zero (waning immunity) will change the long-run behavior of i.num. Then set rs.rate to a positive value (start around 0.01), re-run, and check your prediction. Over the run, the SEIR version (rs.rate = 0) tends to rise, peak, and then decline toward extinction as permanent immunity depletes the susceptible pool, while the SEIRS version tends to level off at a nonzero count as recovered nodes return to being susceptible. Because these are stochastic runs in a finite, closed population, read the contrast across replicates and over the whole time window rather than from a single curve: even with waning immunity a run can go extinct by chance, so “endemic” here means sustained-on-average, not a guaranteed equilibrium. Try a second, larger rs.rate and describe how the typical level responds.

NoteStep 4: Make one genuine extension

Pick one small structural change of your own and implement it in module-fx.R, running in browser mode to step through your new code as in the tutorial. Two good starting options, each a small edit to the progression module:

  • split progression into two exposed sub-stages (E1 to E2 to I) for a more realistic latent period,
  • or add a second infectious state with a different inf.prob.

A harder option, best attempted only if you have time: add disease-induced mortality from the I state. This is the most involved change because it is a departure, not just a status change: the departing node must have active set to 0 and exitTime set to the current step, and the run needs resimulate.network = TRUE so the network drops departed nodes. Reach for the two options above first.

The point is to make a real edit to a module you did not write, which is what extending someone else’s Gallery model looks like in practice.

43.3 Lab Questions

NoteQuestions
  1. In Step 3, how did waning immunity change the epidemic? Explain, in terms of the flows, why a nonzero rs.rate moves the epidemic from tending to burn out toward sustained (on-average endemic) transmission, and why, in a finite closed population, this is a shift in persistence rather than a guaranteed equilibrium.
  2. Reading the module functions in Step 1: which lines would you have to touch to add your Step 4 extension, and which parts of the API contract (get_/set_ accessors, the read-process-write pattern) did your edit rely on?
  3. What did read-run-modify of a maintained example give you that building from scratch would not, and where is building from scratch still the better way to learn?

43.4 Worked solution

A self-contained worked solution is in the course repository as mod9-Lab-Solution.R. It runs the SEIR and SEIRS models, implements one Step 4 extension (splitting the exposed state into two latent sub-stages, E1 to E2 to I), and answers the questions above in comments. Work through the lab yourself first; you will get much more from the questions if you have already formed your own answers.