Skip to content

Commit f036ac7

Browse files
committed
differences for PR #145
1 parent 23ccc48 commit f036ac7

10 files changed

Lines changed: 212 additions & 165 deletions

.DS_Store

-6 KB
Binary file not shown.

compare-interventions.md

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ exercises: 30 # exercise time in minutes
2727

2828
Learners should familiarise themselves with following concept dependencies before working through this tutorial:
2929

30-
**Outbreak response** : [Intervention types](https://www.cdc.gov/nonpharmaceutical-interventions/).
30+
**Outbreak response**: [Intervention types](https://www.cdc.gov/nonpharmaceutical-interventions/).
3131
:::::::::::::::::::::::::::::::::
3232

3333

@@ -213,7 +213,7 @@ There is no vaccination scheme in place
213213

214214
::::::::::::::::: hint
215215

216-
### HINT : Running the model with default parameter values
216+
### HINT: Running the model with default parameter values
217217

218218
We can run the Vacamole model with [default parameter values](https://epiverse-trace.github.io/epidemics/articles/model_vacamole.html#model-epidemic-using-vacamole) by just specifying the population object and number of time steps to run the model for:
219219

@@ -236,19 +236,25 @@ output <- epidemics::model_vacamole(
236236

237237

238238
``` r
239-
polymod <- socialmixr::polymod
240-
contact_data <- socialmixr::contact_matrix(
241-
survey = polymod,
239+
survey_files_2 <- contactsurveys::download_survey(
240+
survey = "https://doi.org/10.5281/zenodo.3874557",
241+
verbose = FALSE
242+
)
243+
survey_load_2 <- socialmixr::load_survey(files = survey_files_2)
244+
245+
contacts_byage_2 <- socialmixr::contact_matrix(
246+
survey = survey_load_2,
242247
countries = "United Kingdom",
243-
age.limits = c(0, 20, 40),
244-
symmetric = TRUE
248+
age_limits = c(0, 20, 40),
249+
symmetric = TRUE,
250+
return_demography = TRUE
245251
)
246252
# prepare contact matrix
247-
contact_matrix <- t(contact_data$matrix)
253+
contacts_byage_matrix_2 <- t(contacts_byage_2$matrix)
248254

249255
# extract demography vector
250-
demography_vector <- contact_data$demography$population
251-
names(demography_vector) <- rownames(contact_matrix)
256+
demography_vector <- contacts_byage_2$demography$population
257+
names(demography_vector) <- rownames(contacts_byage_matrix_2)
252258

253259
# prepare initial conditions
254260
initial_i <- 1e-6
@@ -266,12 +272,12 @@ initial_conditions_vacamole <- rbind(
266272
initial_conditions_vacamole,
267273
initial_conditions_vacamole
268274
)
269-
rownames(initial_conditions_vacamole) <- rownames(contact_matrix)
275+
rownames(initial_conditions_vacamole) <- rownames(contacts_byage_matrix_2)
270276

271277
# prepare population object
272278
uk_population_vacamole <- epidemics::population(
273279
name = "UK",
274-
contact_matrix = contact_matrix,
280+
contact_matrix = contacts_byage_matrix_2,
275281
demography_vector = demography_vector,
276282
initial_conditions = initial_conditions_vacamole
277283
)
@@ -415,9 +421,9 @@ output_baseline <- epidemics::model_default(
415421

416422
Then, we create a list of all the interventions we want to include in our comparison. We define our scenarios as follows:
417423

418-
+ scenario 1 : close schools
419-
+ scenario 2 : mask mandate
420-
+ scenario 3 : close schools and mask mandate.
424+
+ scenario 1: close schools
425+
+ scenario 2: mask mandate
426+
+ scenario 3: close schools and mask mandate.
421427

422428
In R we specify this as:
423429

@@ -480,7 +486,7 @@ head(output)
480486

481487
Now that we have our model output for all of our scenarios, we want to compare the outputs of the interventions to our baseline.
482488

483-
We can do this using `outcomes_averted()` in `{epidemics}`. This function calculates the final epidemic size for each scenario, and then calculates the number of infections averted in each scenario compared to the baseline. To use this function we specify the :
489+
We can do this using `outcomes_averted()` in `{epidemics}`. This function calculates the final epidemic size for each scenario, and then calculates the number of infections averted in each scenario compared to the baseline. To use this function we specify the:
484490

485491
+ output of the baseline scenario
486492
+ outputs of the intervention scenario(s).
@@ -542,9 +548,9 @@ We recommend to read the vignette on [Modelling responses to a stochastic Ebola
542548

543549
::::::::::::::::::::::::::::::::::::: challenge
544550

545-
## Challenge : Ebola outbreak analysis
551+
## Challenge: Ebola outbreak analysis
546552

547-
You have been tasked to investigate the potential impact of an intervention on an Ebola outbreak in Guinea (e.g. a reduction in risky contacts with cases). Using `model_ebola()` and the the information detailed below, find the number of infections averted when :
553+
You have been tasked to investigate the potential impact of an intervention on an Ebola outbreak in Guinea (e.g. a reduction in risky contacts with cases). Using `model_ebola()` and the the information detailed below, find the number of infections averted when:
548554

549555
+ an intervention is applied to reduce the transmission rate by 50% from day 60 and,
550556
+ an intervention is applied to reduce transmission by 10% from day 30.
@@ -553,11 +559,11 @@ For both interventions, we assume there is some uncertainty about the baseline t
553559

554560
*Note: Depending on the number of replicates used, this simulation may take several minutes to run.*
555561

556-
+ Population size : 14 million
557-
+ Initial number of exposed individuals : 10
558-
+ Initial number of infectious individuals : 5
559-
+ Time of simulation : 120 days
560-
+ Parameter values :
562+
+ Population size: 14 million
563+
+ Initial number of exposed individuals: 10
564+
+ Initial number of infectious individuals: 5
565+
+ Time of simulation: 120 days
566+
+ Parameter values:
561567
+ $R_0$ (`r0`) = 1.1,
562568
+ $p^I$ (`infectious_period`) = 12,
563569
+ $p^E$ (`preinfectious_period`) = 5,

contact-matrices.md

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,10 @@ Some groups of individuals have more contacts than others; the average schoolchi
3636

3737

3838
``` r
39+
library(contactsurveys)
3940
library(socialmixr)
4041
```
4142

42-
43-
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: instructor
44-
45-
46-
47-
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
48-
4943
## The contact matrix
5044

5145
The basic contact matrix represents the amount of contact or mixing within and between different subgroups of a population. The subgroups are often age categories but can also be:
@@ -63,40 +57,64 @@ $$
6357
\end{bmatrix}
6458
$$
6559

66-
In this example, we would use this to represent that children meet, on average, 2 other children and 2 adult per day (first row), and adults meet, on average, 1 child and 3 other adults per day (second row). We can use this kind of information to account for the role heterogeneity in contact plays in infectious disease transmission.
60+
In this example, we would use this to represent that children meet, on average, 2 other children and 2 adult per day (first row), and adults meet, on average, 1 child and 3 other adults per day (second row). We can use this kind of information to account for the role that heterogeneity in contact plays in infectious disease transmission.
6761

6862
::::::::::::::::::::::::::::::::::::: callout
6963

7064
### A Note on Notation
71-
For a contact matrix with rows $i$ and columns $j$:
65+
In a contact matrix, the entry $C[i,j]$, at row $i$ and column $j$:
7266

73-
- $C[i,j]$ represents the average number of contacts that individuals in group $i$ have with individuals in group $j$
74-
- This average is calculated as the total number of contacts between groups $i$ and $j$, divided by the number of individuals in group $i$
67+
- Represents the average number of contacts an individual in group $i$ has with individuals in group $j$
68+
- This is calculated by dividing the total number of contacts between groups $i$ and $j$ by the size of group $i$
7569
::::::::::::::::::::::::::::::::::::::::::::::::
7670

7771
## Using `socialmixr`
7872

7973
Contact matrices are commonly estimated from studies that use diaries to record interactions. For example, the POLYMOD survey measured contact patterns in 8 European countries using data on the location and duration of contacts reported by the study participants [(Mossong et al. 2008)](https://doi.org/10.1371/journal.pmed.0050074).
8074

81-
The R package `{socialmixr}` contains functions which can estimate contact matrices from POLYMOD and other surveys. We can load the POLYMOD survey data:
75+
The R package `{socialmixr}` contains functions which can estimate contact matrices from POLYMOD and other surveys. We can download and load the POLYMOD survey data directly from Zenodo using `{contactsurveys}` and `{socialmixr}`:
76+
77+
78+
``` r
79+
survey_files <- contactsurveys::download_survey(
80+
survey = "https://doi.org/10.5281/zenodo.3874557",
81+
verbose = FALSE
82+
)
83+
84+
survey_load <- socialmixr::load_survey(files = survey_files)
85+
```
86+
87+
::::::::::::::::::::::::::::::::::::: callout
88+
### Specify the country name
8289

90+
A single survey file can contain data from multiple countries. You can inspect the available countries with:
8391

8492

8593
``` r
86-
polymod <- socialmixr::polymod
94+
levels(survey_load$participants$country)
95+
```
96+
97+
``` output
98+
[1] "Belgium" "Finland" "Germany" "Italy"
99+
[5] "Luxembourg" "Netherlands" "Poland" "United Kingdom"
87100
```
88101

89-
Then we can obtain the contact matrix for the age categories we want by specifying `age_limits`.
102+
Always pass the `countries =` argument to `contact_matrix()` to make sure you use data from the intended country only.
103+
104+
::::::::::::::::::::::::::::::::::::::::::::::::
105+
106+
Then we can obtain the contact matrix for the age categories we want by specifying `age_limits`. We also add `return_demography = TRUE` to include demographic information in the output, which is required when using the contact matrix with `{epidemics}`.
90107

91108

92109
``` r
93-
contact_data <- socialmixr::contact_matrix(
94-
survey = polymod,
110+
contacts_byage <- socialmixr::contact_matrix(
111+
survey = survey_load,
95112
countries = "United Kingdom",
96113
age_limits = c(0, 20, 40),
97-
symmetric = TRUE
114+
symmetric = TRUE,
115+
return_demography = TRUE
98116
)
99-
contact_data
117+
contacts_byage
100118
```
101119

102120
``` output
@@ -124,9 +142,9 @@ $participants
124142

125143

126144

127-
**Note: although the contact matrix `contact_data$matrix` is not itself mathematically symmetric, it satisfies the condition that the total number of contacts of one group with another is the same as the reverse. In other words:
128-
`contact_data$matrix[j,i]*contact_data$demography$proportion[j] = contact_data$matrix[i,j]*contact_data$demography$proportion[i]`.
129-
For the mathematical explanation see [the corresponding section in the socialmixr documentation](https://epiforecasts.io/socialmixr/articles/socialmixr.html#symmetric-contact-matrices).**
145+
**Note**: although the contact matrix `contacts_byage$matrix` is not itself mathematically symmetric, it satisfies the condition that the total number of contacts of one group with another is the same as the reverse. In other words:
146+
`contacts_byage$matrix[j,i]*contacts_byage$demography$proportion[j] = contacts_byage$matrix[i,j]*contacts_byage$demography$proportion[i]`.
147+
For the mathematical explanation see [the corresponding section in the socialmixr documentation](https://epiforecasts.io/socialmixr/articles/socialmixr.html#symmetric-contact-matrices).
130148

131149

132150
::::::::::::::::::::::::::::::::::::: callout
@@ -145,14 +163,17 @@ If `symmetric` is set to TRUE, the `contact_matrix()` function will internally u
145163

146164
::::::::::::::::::::::::::::::::::::::::::::::::
147165

148-
The example above uses the POLYMOD survey. There are a number of surveys available in `socialmixr`. To list the available surveys, use `socialmixr::list_surveys()`. To download a survey, we can use `socialmixr::get_survey()`
166+
The example above uses the POLYMOD survey. There are a number of surveys available in `socialmixr`. To list the available surveys, use `socialmixr::list_surveys()`. To download a survey from Zenodo and load it, we use `contactsurveys::download_survey()` followed by `socialmixr::load_survey()`:
149167

150168

151169
``` r
152-
# Access the contact survey data from Zenodo
153-
zambia_sa_survey <- socialmixr::get_survey(
154-
"https://doi.org/10.5281/zenodo.3874675"
170+
# Download and load the contact survey data for Zambia from Zenodo
171+
zambia_survey_files <- contactsurveys::download_survey(
172+
survey = "https://doi.org/10.5281/zenodo.3874675",
173+
verbose = FALSE
155174
)
175+
176+
zambia_sa_survey <- socialmixr::load_survey(files = zambia_survey_files)
156177
```
157178

158179
:::::::::::::::::: spoiler
@@ -211,11 +232,12 @@ Similar to the code above, to access vector values within a dataframe, you can u
211232

212233
``` r
213234
# Generate the contact matrix for Zambia only
214-
contact_data_zambia <- socialmixr::contact_matrix(
235+
contacts_byage_zambia <- socialmixr::contact_matrix(
215236
survey = zambia_sa_survey,
216237
countries = "Zambia", # key argument
217238
age_limits = c(0, 20),
218-
symmetric = TRUE
239+
symmetric = TRUE,
240+
return_demography = TRUE
219241
)
220242
```
221243

@@ -228,7 +250,7 @@ participants).
228250

229251
``` r
230252
# Print the contact matrix for Zambia only
231-
contact_data_zambia
253+
contacts_byage_zambia
232254
```
233255

234256
``` output
@@ -253,7 +275,7 @@ $participants
253275

254276
``` r
255277
# Print the vector of population size for {epidemics}
256-
contact_data_zambia$demography$population
278+
contacts_byage_zambia$demography$population
257279
```
258280

259281
``` output
@@ -269,8 +291,6 @@ Contact matrices can be estimated from data obtained from diary (such as POLYMOD
269291
::::::::::::::::::::::::::::::::::::::::::::::::
270292

271293

272-
273-
274294
## Analyses with contact matrices
275295

276296
Contact matrices can be used in a wide range of epidemiological analyses, they can be used:
@@ -293,7 +313,7 @@ Whereas a contact matrix gives the average number of contacts that one groups ma
293313

294314
### In mathematical models
295315

296-
Consider the SIR model where individuals are categorized as either susceptible $S$, infected but not yet infectious $E$, infectious $I$ or recovered $R$. The schematic below shows the processes which describe the flow of individuals between the disease states $S$, $I$ and $R$ and the key parameters for each process.
316+
Consider the SIR model where individuals are categorized as either susceptible $S$, infected $I$ and recovered $R$. The schematic below shows the processes which describe the flow of individuals between the disease states $S$, $I$ and $R$ and the key parameters for each process.
297317

298318
<img src="fig/contact-matrices-rendered-diagram-1.png" alt="" style="display: block; margin: auto;" />
299319

@@ -308,11 +328,11 @@ $$
308328
\end{aligned}
309329
$$
310330

311-
To add age structure to our model, we need to add additional equations for the infection states $S$, $I$ and $R$ for each age group $i$. If we want to assume that there is heterogeneity in contacts between age groups then we must adapt the transmission term $\beta SI$ to include the contact matrix $C$ as follows :
331+
To add age structure to our model, we need to add additional equations for the infection states $S$, $I$ and $R$ for each age group $i$. If we want to assume that there is heterogeneity in contacts between age groups then we must adapt the transmission term $\beta SI$ to include the contact matrix $C$ as follows:
312332

313333
$$ \beta S_i \sum_j C_{i,j} I_j/N_j. $$
314334

315-
Susceptible individuals in age group $i$ become infected dependent on their rate of contact with individuals in each age group. For each disease state ($S$, $E$, $I$ and $R$) and age group ($i$), we have a differential equation describing the rate of change with respect to time.
335+
Susceptible individuals in age group $i$ become infected dependent on their rate of contact with individuals in each age group. For each disease state ($S$, $I$ and $R$) and age group ($i$), we have a differential equations describing the rate of change with respect to time.
316336

317337
$$
318338
\begin{aligned}
@@ -329,13 +349,13 @@ When simulating an epidemic, we often want to ensure that the average number of
329349

330350
Rather than just using the raw number of contacts, we can instead normalise the contact matrix to make it easier to work in terms of $R_0$. In particular, we normalise the matrix by scaling it so that if we were to calculate the average number of secondary cases based on this normalised matrix, the result would be 1 (in mathematical terms, we are scaling the matrix so the largest eigenvalue is 1). This transformation scales the entries but preserves their relative values.
331351

332-
In the case of the above model, we want to define $\beta C_{i,j}$ so that the model has a specified valued of $R_0$. If the entry of the contact matrix $C[i,j]$ represents the contacts of population $i$ with $j$, it is equivalent to `contact_data$matrix[i,j]`, and the maximum eigenvalue of this matrix represents the typical magnitude of contacts, not typical magnitude of transmission. We must therefore normalise the matrix $C$ so the maximum eigenvalue is one; we call this matrix $C_{normalised}$. Because the rate of recovery is $\gamma$, individuals will be infectious on average for $1/\gamma$ days. So $\beta$ as a model input is calculated from $R_0$, the scaling factor and the value of $\gamma$ (i.e. mathematically we use the fact that the dominant eigenvalue of the matrix $R_0 \times C_{normalised}$ is equal to $\beta / \gamma$).
352+
In the case of the above model, we want to define $\beta C_{i,j}$ so that the model has a specified valued of $R_0$. If the entry of the contact matrix $C[i,j]$ represents the contacts of population $i$ with $j$, it is equivalent to `contacts_byage$matrix[i,j]`, and the maximum eigenvalue of this matrix represents the typical magnitude of contacts, not typical magnitude of transmission. We must therefore normalise the matrix $C$ so the maximum eigenvalue is one; we call this matrix $C_{normalised}$. Because the rate of recovery is $\gamma$, individuals will be infectious on average for $1/\gamma$ days. So $\beta$ as a model input is calculated from $R_0$, the scaling factor and the value of $\gamma$ (i.e. mathematically we use the fact that the dominant eigenvalue of the matrix $R_0 \times C_{normalised}$ is equal to $\beta / \gamma$).
333353

334354

335355
``` r
336-
contact_matrix <- t(contact_data$matrix)
337-
scaling_factor <- 1 / max(eigen(contact_matrix)$values)
338-
normalised_matrix <- contact_matrix * scaling_factor
356+
contacts_byage_matrix <- t(contacts_byage$matrix)
357+
scaling_factor <- 1 / max(eigen(contacts_byage_matrix)$values)
358+
normalised_matrix <- contacts_byage_matrix * scaling_factor
339359
```
340360

341361
As a result, if we multiply the scaled matrix by $R_0$, then converting to the number of expected secondary cases would give us $R_0$, as required.
@@ -363,7 +383,7 @@ Normalisation can be performed by the function `contact_matrix()` in `{socialmix
363383

364384
``` r
365385
contact_data_split <- socialmixr::contact_matrix(
366-
survey = polymod,
386+
survey = survey_load,
367387
countries = "United Kingdom",
368388
age_limits = c(0, 20, 40),
369389
symmetric = TRUE,

0 commit comments

Comments
 (0)