Scenario modelling#

Note

If you are not familiar with pypfilt, you may want to begin with the Getting Started tutorial.

What is scenario modelling?#

Scenario modelling involves predicting future outcomes that would occur if specific circumstances (“scenarios”) were met. Key differences between scenario modelling and forecasting include:

  • Scenario modelling produces conditional predictions — each scenario represents a plausible, but hypothetical, set of circumstances. In contrast, forecasts characterise the expected future based on current circumstances.

  • Scenario modelling produces long-term predictions — often spanning months or years. In contrast, forecasts typically involve shorter horizons of days to weeks.

See also

See Coronavirus Disease Model to Inform Transmission-Reducing Measures and Health System Preparedness, Australia (Moss et al., 2020) for an example of scenario modelling that informed Australia’s emergency response to COVID-19.

Scenario modelling with pypfilt#

Scenario modelling is straightforward to implement in pypfilt. The key is to use different model prior distributions to characterise each scenario.

  • Implement a simulation model (see, e.g., the tutorial example).

  • Define a different prior distribution for each scenario.

  • Provide no observations, so that the results only reflect the choice of prior distribution.

  • Use observation models to simulate observations, if desired.

  • Generate results for each scenario with pypfilt.fit(). Alternatively, you can use pypfilt.forecast() to generate forecasts from \(t = 0\) for each scenario.

Deterministic parameter sampling#

The Latin Hypercube sampler returns deterministic parameter samples, based on the order in which the distributions are defined. This allows for pair-wise comparisons between particles in different scenarios.

For example, you may wish to predict the impact of different interventions on a system. To do so, you could define a “baseline” scenario (no interventions) and one or more “intervention” scenarios, and create a summary table that records relevant outputs for each particle. This would allow you to compare output distributions between each intervention scenario and the baseline scenario.

However, with deterministic parameter sampling, you can also obtain the distribution of the relative impact of each intervention, by calculating the difference in output between (a) each particle in an intervention scenario; and (b) each corresponding particle in the baseline scenario.

We will now present an example that demonstrates how to do this.

Interventions in an SIRV model#

We will use an SIRV ODE model to compare the impact of different interventions on an infectious disease epidemic. This model divides the population into four compartments: Susceptible \(S(t)\), Infectious \(I(t)\), Recovered \(R(t)\), and Vaccinated \(V(t)\).

Note

The simulation model and interventions presented here are intended for illustrative purposes, rather than characterising real-world applications of scenario modelling.

Simulation model#

The model equations are:

\[\begin{split}S(0) &= N - 1 \qquad & \frac{dS}{dt} &= - \beta(t) \cdot I \cdot \frac{S}{N} - v(t) \\ I(0) &= 1 & \frac{dI}{dt} &= \beta(t) \cdot I \cdot \frac{S}{N} - \gamma \cdot I \\ R(0) &= 0 & \frac{dR}{dt} &= \gamma \cdot I \\ V(0) &= 0 & \frac{dV}{dt} &= v(t)\end{split}\]

The model supports two types of intervention.

  • Reducing transmission by a proportion \(e_R\) once daily incidence exceeds a threshold \(i_R\), representing non-pharmaceutical interventions such as wearing masks and social distancing measures:

    \[\begin{split}\beta(t) &= [1 - e_R(t)] \cdot R_0 \cdot \gamma \\ e_R(t) &= \begin{cases} 0 & \text{if daily incidence } < i_R \\ e_R & \text{otherwise} \\ \end{cases}\end{split}\]
  • Reducing the susceptible population at some rate \(v\) beginning at time \(t_V\), representing a vaccination program with a vaccine that confers immediate, complete, and permanent protection.

    \[\begin{split}v(t) &= \begin{cases} 0 & \text{if } t < t_V \\ v & \text{otherwise} \\ \end{cases}\end{split}\]

Note

In the model implementation (below) we have used descriptive variable names for the intervention parameters, rather than the symbols listed in the equations above.

Observing daily incidence#

We need to calculate daily incidence in order to reduce transmission at the appropriate time. However, daily incidence is also a useful measure for characterising each particle trajectory and calculating quantities such as the peak size, peak time, and epidemic duration.

We can define an observation model for daily incidence, and record the simulated observations in a SimulatedObs summary table. For this purpose, we may not want to introduce any observation error, and so we can define a “perfect” observation model (i.e., zero variance); see the highlighted line in the observation model implementation below.

Measuring impact#

We define the impact of each intervention as the number of infections that were prevented, relative to the baseline (no intervention) scenario. We can measure this by recording the epidemic final size (i.e., the total number of infections) for each particle. This is simply the value of \(R(t)\) at the end of the simulation. We can then calculate by comparing the epidemic final sizes between each intervention scenario and the baseline scenario.

Defining scenarios#

We define three scenarios:

  • "baseline": no interventions, the reference against which to calculate intervention impact;

  • "Reduce R0": reduce transmission by 33% once incidence reaches 100 infections per day.

  • "Vaccination": beginning on day 28, vaccinate up to 1000 susceptible people per day.

For all scenarios, we use the same prior distributions for the pathogen parameters:

\[\begin{split}R_0 &\sim \mathcal{U}(2, 3) \\ \gamma &\sim \mathcal{U}(0.25, 0.35)\end{split}\]

The intervention parameters differ between scenarios:

\[\begin{split}e_R &= \begin{cases} 0.33 & \text{when reducing transmission} \\ 0 & \text{otherwise} \\ \end{cases} \\ i_R &= \begin{cases} 100 & \text{when reducing transmission} \\ 0 & \text{otherwise} \\ \end{cases} \\ v &= \begin{cases} 1000 & \text{when vaccinating} \\ 0 & \text{otherwise} \\ \end{cases} \\ t_V &= \begin{cases} 28 & \text{when vaccinating} \\ 0 & \text{otherwise} \\ \end{cases}\end{split}\]

We run each scenario for 80 days, and record summary tables for daily incidence ("daily_inc") and epidemic final size ("final_sizes"). See the scenario definitions below for complete details.

Running scenario simulations#

The scenario definitions are provided by the sirv_toml_data() function.

Note that we record each simulation context, in addition to the simulation results. This allows us to inspect the parameter values sampled from the prior distributions for each scenario, so that we can confirm that the pathogen parameters — \(\gamma\) and \(R_0\) — are identical for each scenario, and that the intervention parameters differ between scenarios.

Simulation results#

We can plot the daily incidence curves, and observe the following features:

  • As expected, the baseline epidemics span rapid outbreaks with large peaks, and slower outbreaks with lower peaks;

  • Reducing transmission noticeably slows the epidemics and reduces the peak height; and

  • Vaccination occurs quite late, and only has a noticeable impact on the slowest epidemics.

../_images/scenario-sirv-epi-curves.png

Daily incidence curves for each scenario.#

We can plot the distribution of epidemic final sizes , and observe the following features:

  • Reducing transmission substantially reduces the number of infections; and

  • Vaccination is less consistent in its impact, sometimes having little effect, but also capable of greater reductions in final size than the reducing transmission intervention.

../_images/scenario-sirv-final-sizes.png

Epidemic final size distributions, reported as medians (points) and 95% credible intervals (lines).#

For each intervention, we can calculate the number of prevented infections separately for each particle, and plot the distribution of prevented infections. The results are consistent with those shown in the previous figure.

Important

We can calculate numbers of prevented infections for each particle, because we have identical samples for \(R_0\) and \(\gamma\) in each scenario. Without this guarantee, it would not be sensible to calculate the difference in epidemic final size between individual particles in different scenarios, and attribute this difference to the intervention alone.

../_images/scenario-sirv-prevented-infections.png

The distribution of prevented infections (relative to the baseline scenario), reported as medians (points) and 95% credible intervals (lines).#

Finally, we can plot the correlations between prevented infections and pathogen parameters, and observe the following features:

  • The impact of reducing transmission is, unsurprisingly, strongly correlated with \(R_0\) and barely correlated with \(\gamma\);

  • The impact of vaccination is correlated with \(R_0\), and also with \(\gamma\), because larger values of \(\gamma\) produce shorter epidemics, generating more infections prior to the start of vaccination; and

  • The daily force of infection \(\beta = R_0 \cdot \gamma\) is more strongly correlated with the impact of vaccination than with the impact of reducing transmission, because the impact of vaccination strongly depends on the number of infections that have occurred prior to the start of vaccination.

../_images/scenario-sirv-correlations.png

Spearman rank correlation coefficients between (a) the number of prevented infections (relative to the baseline scenario); and (b) model parameters that characterise the pathogen.#

We can also display these correlations as a bar plot, which may be more useful for visual comparisons between individual parameters and/or scenarios.

../_images/scenario-sirv-correlations-bars.png

Spearman rank correlation coefficients between (a) the number of prevented infections (relative to the baseline scenario); and (b) model parameters that characterise the pathogen.#

Further details#

The code to run these simulations and plot the results can be found in tests/test_sirv.py. The contents of this file are provided below.