Skip to content

Commit 0be1934

Browse files
committed
differences for PR #126
1 parent 6a74d2d commit 0be1934

File tree

3 files changed

+77
-60
lines changed

3 files changed

+77
-60
lines changed

.DS_Store

-6 KB
Binary file not shown.

md5sum.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"episodes/contact-matrices.Rmd" "19856620d33f9b7f4e8ee312460494f1" "site/built/contact-matrices.md" "2025-11-11"
88
"episodes/simulating-transmission.Rmd" "3e3ecf82148896a33189045d704f9606" "site/built/simulating-transmission.md" "2025-11-20"
99
"episodes/model-choices.Rmd" "aa195e66455fb6a97b4930fd08c08001" "site/built/model-choices.md" "2025-11-11"
10-
"episodes/modelling-interventions.Rmd" "4ddf2a3e860dc11ba7a29ad20228eb3a" "site/built/modelling-interventions.md" "2025-11-11"
10+
"episodes/modelling-interventions.Rmd" "a1119009b98b1e9541790d43b27e3c74" "site/built/modelling-interventions.md" "2025-11-22"
1111
"episodes/compare-interventions.Rmd" "2ef6697bbad9bcfb843ab9d50469123b" "site/built/compare-interventions.md" "2025-11-11"
1212
"episodes/vaccine-comparisons.Rmd" "bb9110b17b2b5cdc915df3f17eae15df" "site/built/vaccine-comparisons.md" "2025-11-11"
1313
"episodes/disease-burden.Rmd" "9deead362349c98be8f1d9380a7b975a" "site/built/disease-burden.md" "2025-11-11"

modelling-interventions.md

Lines changed: 76 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
title: 'Modelling interventions'
33
teaching: 45 # teaching time in minutes
44
exercises: 30 # exercise time in minutes
5-
65
---
76

87

@@ -51,60 +50,96 @@ In this tutorial different types of intervention and how they can be modelled ar
5150

5251
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
5352

54-
## Non-pharmaceutical interventions
53+
## A baseline model
5554

56-
[Non-pharmaceutical interventions](../learners/reference.md#NPIs) (NPIs) are measures put in place to reduce transmission that do not include the administration of drugs or vaccinations. NPIs aim at reducing contacts between infectious and susceptible individuals by closure of schools and workplaces, and other measures to prevent the spread of the disease, for example, washing hands and wearing masks.
55+
We will investigate the effect of interventions on a COVID-19 outbreak using an SEIR model (`model_default()` in the R package `{epidemics}`). To be able to see the effect of our intervention, we will run a baseline variant of the model, i.e, without intervention.
5756

58-
We will investigate the effect of interventions on a COVID-19 outbreak using an SEIR model (`model_default()` in the R package `{epidemics}`). The SEIR model divides the population into four compartments: Susceptible (S), Exposed (E), Infectious (I), and Recovered (R). We will set the following parameters for our model: $R_0 = 2.7$ (basic reproduction number), latent period or pre-infectious period $= 4$ days, and the infectious period $= 5.5$ days (parameters adapted from [Davies et al. (2020)](https://doi.org/10.1016/S2468-2667(20)30133-X)). We adopt a contact matrix with age bins 0-18, 18-65, 65 years and older using `{socialmixr}`, and assume that one in every 1 million individuals in each age group is infectious at the start of the epidemic.
57+
The SEIR model divides the population into four compartments: Susceptible (S), Exposed (E), Infectious (I), and Recovered (R). We will set the following parameters for our model: $R_0 = 2.7$ (basic reproduction number), latent period or pre-infectious period $= 4$ days, and the infectious period $= 5.5$ days (parameters adapted from [Davies et al. (2020)](https://doi.org/10.1016/S2468-2667(20)30133-X)). We adopt a contact matrix with age bins 0-18, 18-65, 65 years and older using `{socialmixr}`, and assume that one in every 1 million individuals in each age group is infectious at the start of the epidemic.
5958

6059

6160
``` r
62-
polymod <- socialmixr::polymod
63-
contact_data <- socialmixr::contact_matrix(
64-
polymod,
61+
# load survey data
62+
survey_data <- socialmixr::polymod
63+
64+
# generate contact matrix
65+
cm_results <- socialmixr::contact_matrix(
66+
survey = survey_data,
6567
countries = "United Kingdom",
6668
age.limits = c(0, 15, 65),
6769
symmetric = TRUE
6870
)
6971

70-
# prepare contact matrix
71-
contact_matrix <- t(contact_data$matrix)
72+
# transpose contact matrix
73+
cm_matrix <- t(cm_results$matrix)
7274

7375
# prepare the demography vector
74-
demography_vector <- contact_data$demography$population
75-
names(demography_vector) <- rownames(contact_matrix)
76+
demography_vector <- cm_results$demography$population
77+
names(demography_vector) <- rownames(cm_matrix)
7678

7779
# initial conditions: one in every 1 million is infected
7880
initial_i <- 1e-6
7981
initial_conditions <- c(
80-
S = 1 - initial_i, E = 0, I = initial_i, R = 0, V = 0
82+
S = 1 - initial_i,
83+
E = 0,
84+
I = initial_i,
85+
R = 0,
86+
V = 0
8187
)
8288

8389
# build for all age groups
84-
initial_conditions <- matrix(
85-
rep(initial_conditions, dim(contact_matrix)[1]),
86-
ncol = 5, byrow = TRUE
90+
initial_conditions <- base::rbind(
91+
initial_conditions,
92+
initial_conditions,
93+
initial_conditions
8794
)
88-
rownames(initial_conditions) <- rownames(contact_matrix)
95+
rownames(initial_conditions) <- rownames(cm_matrix)
8996

9097
# prepare the population to model as affected by the epidemic
9198
uk_population <- epidemics::population(
9299
name = "UK",
93-
contact_matrix = contact_matrix,
100+
contact_matrix = cm_matrix,
94101
demography_vector = demography_vector,
95102
initial_conditions = initial_conditions
96103
)
97104
```
98105

99-
#### Effect of school closures on COVID-19 spread
106+
We run the model with a transmission rate $= 2.7/5.5$ (remember that [transmission rate = $R_0$* recovery rate](../episodes/simulating-transmission.md#the-basic-reproduction-number-r_0)), infectiousness rate $1/= 4$ and the recovery rate $= 1/5.5$ as follows:
107+
108+
109+
``` r
110+
# time periods
111+
preinfectious_period <- 4.0
112+
infectious_period <- 5.5
113+
basic_reproduction <- 2.7
114+
115+
# rates
116+
infectiousness_rate <- 1.0 / preinfectious_period
117+
recovery_rate <- 1.0 / infectious_period
118+
transmission_rate <- basic_reproduction * recovery_rate
119+
120+
# run baseline simulation with no intervention
121+
output_baseline <- epidemics::model_default(
122+
population = uk_population,
123+
transmission_rate = transmission_rate,
124+
infectiousness_rate = infectiousness_rate,
125+
recovery_rate = recovery_rate,
126+
time_end = 300, increment = 1.0
127+
)
128+
```
129+
130+
## Non-pharmaceutical interventions
131+
132+
[Non-pharmaceutical interventions](../learners/reference.md#NPIs) (NPIs) are measures put in place to reduce transmission that do not include the administration of drugs or vaccinations. NPIs aim at reducing contacts between infectious and susceptible individuals by closure of schools and workplaces, and other measures to prevent the spread of the disease, for example, washing hands and wearing masks.
133+
134+
### Effect of school closures on COVID-19 spread
100135

101136
The first NPI we will consider is the effect of school closures on reducing the number of individuals infected with COVID-19 over time. We assume that a school closure will reduce the frequency of contacts within and between different age groups. Based on empirical studies, we assume that school closures will reduce the contacts between school-aged children (aged 0-15) by 50%, and will cause a small reduction (1%) in the contacts between adults (aged 15 and over).
102137

103138
To include an intervention in our model we must create an `intervention` object. The inputs are the name of the intervention (`name`), the type of intervention (`contacts` or `rate`), the start time (`time_begin`), the end time (`time_end`) and the reduction (`reduction`). The values of the reduction matrix are specified in the same order as the age groups in the contact matrix.
104139

105140

106141
``` r
107-
rownames(contact_matrix)
142+
rownames(cm_matrix)
108143
```
109144

110145
``` output
@@ -115,7 +150,7 @@ Therefore, we specify ` reduction = matrix(c(0.5, 0.01, 0.01))`. We assume that
115150

116151

117152
``` r
118-
close_schools <- intervention(
153+
close_schools <- epidemics::intervention(
119154
name = "School closure",
120155
type = "contacts",
121156
time_begin = 50,
@@ -149,25 +184,11 @@ The contacts within group 1 are reduced by 50% twice to accommodate for a 50% re
149184

150185
::::::::::::::::::::::::::::::::::::::::::::::::
151186

152-
Using transmission rate $= 2.7/5.5$ (remember that [transmission rate = $R_0$/ infectious period](../episodes/simulating-transmission.md#the-basic-reproduction-number-r_0)), infectiousness rate $1/= 4$ and the recovery rate $= 1/5.5$ we run the model with ` intervention = list(contacts = close_schools)` as follows:
187+
We run the model with ` intervention = list(contacts = close_schools)` as follows:
153188

154189

155190
``` r
156-
# time periods
157-
preinfectious_period <- 4.0
158-
infectious_period <- 5.5
159-
basic_reproduction <- 2.7
160-
161-
# rates
162-
infectiousness_rate <- 1.0 / preinfectious_period
163-
recovery_rate <- 1.0 / infectious_period
164-
transmission_rate <- basic_reproduction / infectious_period
165-
```
166-
167-
168-
169-
``` r
170-
output_school <- model_default(
191+
output_school <- epidemics::model_default(
171192
# population
172193
population = uk_population,
173194
# rate
@@ -182,25 +203,14 @@ output_school <- model_default(
182203
```
183204

184205

185-
To be able to see the effect of our intervention, we also run a baseline variant of the model, i.e, without intervention, combine the two outputs into one data frame, and then plot the output. Here we plot the total number of infectious individuals in all age groups using `ggplot2::stat_summary()` function:
206+
To observe the effect of our intervention, we will combine the baseline and intervention outputs into a single data frame and then plot the results. Here we plot the total number of infectious individuals in all age groups using `ggplot2::stat_summary()` function:
186207

187208

188209
``` r
189-
# run baseline simulation with no intervention
190-
output_baseline <- model_default(
191-
population = uk_population,
192-
transmission_rate = transmission_rate,
193-
infectiousness_rate = infectiousness_rate,
194-
recovery_rate = recovery_rate,
195-
time_end = 300, increment = 1.0
196-
)
197-
198210
# create intervention_type column for plotting
199211
output_school$intervention_type <- "school closure"
200212
output_baseline$intervention_type <- "baseline"
201-
output <- rbind(output_school, output_baseline)
202-
203-
library(tidyverse)
213+
output <- base::rbind(output_school, output_baseline)
204214

205215
output %>%
206216
filter(compartment == "infectious") %>%
@@ -234,11 +244,12 @@ output %>%
234244
```
235245

236246
<img src="fig/modelling-interventions-rendered-baseline-1.png" style="display: block; margin: auto;" />
247+
237248
We can see that with the intervention in place, the infection still spreads through the population and hence accumulation of immunity contributes to the eventual peak-and-decline. However, the peak number of infectious individuals is smaller (green dashed line) than the baseline with no intervention in place (red solid line), showing a reduction in the absolute number of cases.
238249

239250

240251

241-
#### Effect of mask wearing on COVID-19 spread
252+
### Effect of mask wearing on COVID-19 spread
242253

243254
We can also model the effect of other NPIs by reducing the value of the relevant parameters. For example, investigating the effect of mask wearing on the number of individuals infected with COVID-19 over time.
244255

@@ -248,7 +259,7 @@ We create an intervention object with `type = rate` and `reduction = 0.161`. Usi
248259

249260

250261
``` r
251-
mask_mandate <- intervention(
262+
mask_mandate <- epidemics::intervention(
252263
name = "mask mandate",
253264
type = "rate",
254265
time_begin = 40,
@@ -261,7 +272,7 @@ To implement this intervention on the transmission rate $\beta$, we specify `int
261272

262273

263274
``` r
264-
output_masks <- model_default(
275+
output_masks <- epidemics::model_default(
265276
# population
266277
population = uk_population,
267278
# rate
@@ -281,7 +292,7 @@ output_masks <- model_default(
281292
# create intervention_type column for plotting
282293
output_masks$intervention_type <- "mask mandate"
283294
output_baseline$intervention_type <- "baseline"
284-
output <- rbind(output_masks, output_baseline)
295+
output <- base::rbind(output_masks, output_baseline)
285296

286297
output %>%
287298
filter(compartment == "infectious") %>%
@@ -332,7 +343,8 @@ Pharmaceutical interventions (PIs) are measures such as vaccination and mass tre
332343

333344
The diagram below shows the SEIRV model implemented using `model_default()` where susceptible individuals are vaccinated and then move to the $V$ class.
334345

335-
<img src="fig/modelling-interventions-rendered-diagram_SEIRV-1.png" style="display: block; margin: auto;" />
346+
<!--html_preserve--><div class="grViz html-widget html-fill-item" id="htmlwidget-1afabff0cd9170311eb4" style="width:504px;height:504px;"></div>
347+
<script type="application/json" data-for="htmlwidget-1afabff0cd9170311eb4">{"x":{"diagram":"digraph {\n\n # graph statement\n ################\n graph [layout = dot,\n rankdir = LR,\n overlap = true,\n fontsize = 10]\n\n # nodes\n #######\n node [shape = square,\n fixedsize = true\n width = 1.3]\n\n S\n E\n I\n R\n V\n\n # edges\n #######\n S -> E [label = \" infection (&beta;)\"]\n S -> V [label = \" vaccination (&nu;)\"]\n E -> I [label = \" onset of \ninfectiousness (&alpha;)\"]\n I -> R [label = \" recovery (&gamma;)\"]\n\n}","config":{"engine":"dot","options":null}},"evals":[],"jsHooks":[]}</script><!--/html_preserve-->
336348

337349

338350

@@ -356,10 +368,10 @@ Here we will assume all age groups are vaccinated at the same rate 0.01 and that
356368

357369
``` r
358370
# prepare a vaccination object
359-
vaccinate <- vaccination(
371+
vaccinate <- epidemics::vaccination(
360372
name = "vaccinate all",
361-
time_begin = matrix(40, nrow(contact_matrix)),
362-
time_end = matrix(40 + 150, nrow(contact_matrix)),
373+
time_begin = matrix(40, nrow(cm_matrix)),
374+
time_end = matrix(40 + 150, nrow(cm_matrix)),
363375
nu = matrix(c(0.01, 0.01, 0.01))
364376
)
365377
```
@@ -368,7 +380,7 @@ We pass our vaccination object into the model using the argument `vaccination =
368380

369381

370382
``` r
371-
output_vaccinate <- model_default(
383+
output_vaccinate <- epidemics::model_default(
372384
# population
373385
population = uk_population,
374386
# rate
@@ -396,7 +408,12 @@ Plot the three interventions vaccination, school closure and mask mandate and th
396408
``` r
397409
# create intervention_type column for plotting
398410
output_vaccinate$intervention_type <- "vaccination"
399-
output <- rbind(output_school, output_masks, output_vaccinate, output_baseline)
411+
output <- base::rbind(
412+
output_school,
413+
output_masks,
414+
output_vaccinate,
415+
output_baseline
416+
)
400417

401418
output %>%
402419
filter(compartment == "infectious") %>%

0 commit comments

Comments
 (0)