Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0d5eaee
fix link to Lloyd-Smith et al. in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
8dafa10
change citation name in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
a8fb2cf
fix spelling in callout in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
167975e
add pkg install info to callout in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
eb089f6
fix typo in superspreading-estimate.Rmd header
joshwlambert Mar 23, 2026
7b18a87
grammar fix in dropdown in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
3c3f075
wording fix in dropdown in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
96e12ae
clarify wording of callout in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
be2f9d8
consistent in-text citation style in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
b977c58
fix typo in figure legend in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
61b2feb
fix typo in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
08b0f6f
fix wording in superspreading-estimate.Rmd
joshwlambert Mar 23, 2026
9bd59d0
update The double-colon callout in superspreading-simulate.Rmd to mat…
joshwlambert Mar 23, 2026
45986ed
consistent formatting of bullet points in supersperading-simulate.Rmd
joshwlambert Mar 23, 2026
70b8024
fix definition of set.seed() in superspreading-simulate.Rmd
joshwlambert Mar 23, 2026
b3aeade
change wording in challenge box in superspreading-simulate.Rmd
joshwlambert Mar 23, 2026
5dcff3e
update wording in superspreading-simulate.Rmd
joshwlambert Mar 23, 2026
dfc48ef
Minor edits to superspreading text from code review
joshwlambert Mar 23, 2026
01385ab
review and update delays-access.Rmd
joshwlambert Jun 6, 2026
85abfec
review and update delays-functions.Rmd
joshwlambert Jun 6, 2026
63e7859
review and update quantify-transmissibility.Rmd
joshwlambert Jun 6, 2026
cb6b451
review and update severity-static.Rmd
joshwlambert Jun 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions episodes/delays-access.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Look at the [glossary](../learners/reference.md) for the definitions of all the

:::::::::::::::::::::::::

However, early in an epidemic, efforts to understand the epidemic and implications for control can be delayed by the lack of an easy way to access key parameters for the disease of interest ([Nash et al., 2023](https://mrc-ide.github.io/epireview/)). Projects like `{epiparameter}` and `{epireview}` are building online catalogues following literature synthesis protocols that can help inform analysis and parametrise models by providing a library of previously estimated epidemiological parameters from past outbreaks.
However, early in an epidemic, efforts to understand the epidemic and implications for control can be delayed by the lack of an easy way to access key parameters for the disease of interest ([Nash et al., 2023](https://mrc-ide.github.io/epireview/)). Projects like `{epiparameter}` and [epireview](https://mrc-ide.github.io/epireview/) are building online catalogues following literature synthesis protocols that can help inform analysis and parametrise models by providing a library of previously estimated epidemiological parameters from past outbreaks.

:::::::::::::::::: instructor

Expand All @@ -58,7 +58,7 @@ To illustrate how to use the `{epiparameter}` R package in your analysis pipelin

<!-- In this episode, we'll learn how to access one specific set of epidemiological parameters from the literature and then get their **summary statistics** using `{epiparameter}`. -->

Let's start loading the `{epiparameter}` package. We'll use the pipe `%>%` to connect some of its functions, some `{tibble}` and `{dplyr}` functions, so let's also call to the `{tidyverse}` package:
Let's start by loading the `{epiparameter}` package. We'll use the pipe `%>%` to connect some of its functions, some `{tibble}` and `{dplyr}` functions, so let's also load the `{tidyverse}` package:

```{r,warning=FALSE,message=FALSE}
library(epiparameter)
Expand All @@ -80,7 +80,7 @@ This helps us remember package functions and avoid namespace conflicts.

## The problem

If we want to estimate the transmissibility of an infection, it's common to use a package such as `{EpiEstim}` or `{EpiNow2}`. The `{EpiEstim}` package allows real-time estimation of the reproduction number using case data over time, reflecting how transmission changes based on when symptoms appear. For estimating transmission based on when people were actually infected (rather than symptom onset), the `{EpiNow2}` package extends this idea by combining it with a model that accounts for delays in observed data. Both packages require some epidemiological information as an input. For example, in `{EpiNow2}` we use `EpiNow2::Gamma()` to specify a [generation time](../learners/reference.md#generationtime) as a probability distribution adding its `mean`, standard deviation (`sd`), and maximum value (`max`).
If we want to estimate the transmissibility of an infection, it's common to use a package such as `{EpiEstim}` or `{EpiNow2}`. The `{EpiEstim}` package allows real-time estimation of the reproduction number using case data over time, reflecting how transmission changes based on when symptoms appear. For estimating transmission based on when people were actually infected (rather than symptom onset), the `{EpiNow2}` package extends this idea by combining it with a model that accounts for delays in observed data. Both packages require some epidemiological information as an input. For example, in `{EpiNow2}` we use `EpiNow2::Gamma()` to specify a [generation time](../learners/reference.md#generationtime) as a Gamma probability distribution adding its `mean`, standard deviation (`sd`), and maximum value (`max`).

To specify a `generation_time` that follows a _Gamma_ distribution with mean $\mu = 4$, standard deviation $\sigma = 2$, and a maximum value of 20, we write:

Expand All @@ -95,7 +95,7 @@ generation_time <-

It is a common practice for analysts to manually search the available literature and copy and paste the **summary statistics** or the **distribution parameters** from scientific publications. A challenge that is often faced is that the reporting of different statistical distributions is not consistent across the literature (e.g. a paper may only report the mean, rather than the full underlying distribution). `{epiparameter}`'s objective is to facilitate the access to reliable estimates of distribution parameters for a range of infectious diseases, so that they can easily be implemented in outbreak analytic pipelines.

In this episode, we will *access* the summary statistics of generation time for COVID-19 from the library of epidemiological parameters provided by `{epiparameter}`. These metrics can be used to estimate the transmissibility of this disease using `{EpiNow2}` in subsequent episodes.
In this episode, we will *access* the summary statistics of a generation time for COVID-19 from the library of epidemiological parameters provided by `{epiparameter}`. These metrics can be used to estimate the transmissibility of this disease using `{EpiNow2}` in subsequent episodes.

Let's start by looking at how many entries are currently available in the **epidemiological distributions database** in `{epiparameter}` using `epiparameter_db()` for the epidemiological distribution `epi_name` called generation time with the string `"generation"`:

Expand All @@ -111,7 +111,7 @@ In the library of epidemiological parameters, we may not have a `"generation"` t

### Systematic review data for priority pathogens

The [`{epireview}` R package](https://mrc-ide.github.io/epireview/) has parameters on Ebola, Marburg and Lassa from recent systematic reviews, with more priority pathogens planned for future releases. Have a look at [this vignette](https://epiverse-trace.github.io/epiparameter/articles/data_from_epireview.html) for more information on how to use these parameters with `{epiparameter}`.
The [`{epireview}` R package](https://mrc-ide.github.io/epireview/) has parameters on Ebola, Marburg, Lassa, SARS, Zika and Nipah from recent systematic reviews, with more priority pathogens planned for future releases. Have a look at [this vignette](https://epiverse-trace.github.io/epiparameter/articles/data_from_epireview.html) for more information on how to use these parameters with `{epiparameter}`.

:::::::::::::::::::::::::

Expand Down Expand Up @@ -208,7 +208,7 @@ The objective of the assessment above is to assess the interpretation of a large

In this section, we will use `{epiparameter}` to obtain the serial interval for COVID-19, as an alternative to the generation time.

First, let's see how many parameters we have in the epidemiological distributions database (`epiparameter_db()`) with the `disease` named `covid`-19. Run this code:
First, let's see how many parameters we have in the epidemiological distributions database (`epiparameter_db()`) with the `disease` named `covid`. Run this code:

```{r,eval=FALSE}
epiparameter::epiparameter_db(
Expand All @@ -225,13 +225,13 @@ epiparameter::epiparameter_db(
)
```

With this query combination, we get more than one delay distribution (because the database has multiple entries). This output is an `<epiparameter>` class object.
With this query combination, we get more than one delay distribution (because the database has multiple entries). When several entries match, the output is a list of `<epiparameter>` objects.

::::::::::::::::: callout

### CASE-INSENSITIVE

`epiparameter_db` is [case-insensitive](https://dillionmegida.com/p/case-sensitivity-vs-case-insensitivity/#case-insensitivity). This means that you can use strings with letters in upper or lower case indistinctly. Strings like `"serial"`, `"serial interval"` or `"serial_interval"` are also valid.
`epiparameter_db` is [case-insensitive](https://dillionmegida.com/p/case-sensitivity-vs-case-insensitivity/#case-insensitivity). This means that you can use strings with letters in upper or lower case interchangeably. Strings like `"serial"`, `"serial interval"` or `"serial_interval"` are also valid.

:::::::::::::::::::::::::

Expand Down Expand Up @@ -276,7 +276,7 @@ distribution %>%
is_parameterised()
```

### Parameterised entries have an Inference method
### Parameterised entries have an inference method

As detailed in `?is_parameterised`, a parameterised distribution is the entry that has a probability distribution associated with it provided by an `inference_method` as shown in `metadata`:

Expand All @@ -299,9 +299,9 @@ Take 2 minutes to explore the `{epiparameter}` library.

Find:

- How many delay distributions are for that disease?
- How many delay distributions are there for that disease?

- How many types of probability distribution (e.g., gamma, log normal) are for a given delay in that disease?
- How many types of probability distribution (e.g., gamma, log normal) are there for a given delay in that disease?

Ask:

Expand Down Expand Up @@ -334,15 +334,15 @@ The combo of `epiparameter_db()` plus `parameter_tbl()` gets a data frame of all
We choose to explore Ebola's delay distributions:

```{r}
# we expect 16 delay distributions for Ebola
# we expect 17 delay distributions for Ebola
epiparameter::epiparameter_db(
disease = "ebola"
)
```

Now, from the output of `epiparameter::epiparameter_db()`, What is an [offspring distribution](../learners/reference.md#offspringdist)?
Now, from the output of `epiparameter::epiparameter_db()`, what is an [offspring distribution](../learners/reference.md#offspringdist)?

We choose to find Ebola's incubation periods. This output lists all the papers and parameters found. Run this locally if needed:
We choose to search for incubation period estimates for Ebola. This output lists all the papers and parameters found. Run this locally if needed:

```{r, eval=FALSE}
epiparameter::epiparameter_db(
Expand Down Expand Up @@ -374,7 +374,7 @@ How does `{epiparameter}` do the collection and review of peer-reviewed literatu

## Select a single distribution

The `epiparameter::epiparameter_db()` function works as a filtering or subset function. We can use the `author` argument to keep `Hiroshi Nishiura` parameters, or the `subset` argument to keep parameters from studies with a sample size higher than 10:
The `epiparameter::epiparameter_db()` function works as a filtering or subset function. We can use the `author` argument to keep parameters reported in papers where the first author is `Nishiura`, or the `subset` argument to keep parameters from studies with a sample size higher than 10:

```{r, eval = FALSE}
epiparameter::epiparameter_db(
Expand Down Expand Up @@ -445,7 +445,7 @@ This only seems to work in code chunks and R console!

-->

You can use `plot()` to `<epiparameter>` objects to visualise:
You can use `plot()` on `<epiparameter>` objects to visualise:

- the *Probability Density Function (PDF)* and
- the *Cumulative Distribution Function (CDF)*.
Expand All @@ -465,7 +465,7 @@ plot(covid_serialint, xlim = c(1, 60))

## Extract the summary statistics

We can get the `mean` and standard deviation (`sd`) from this `<epiparameter>` diving into the `summary_stats` object:
We can get the `mean` and standard deviation (`sd`) from this `<epiparameter>` object by diving into the `summary_stats` element:

```{r}
# get the mean
Expand All @@ -483,7 +483,7 @@ generation_time <-
)
```

In the next episode we'll learn how to use `{EpiNow2}` to correctly specify distributions, estimate transmissibility. Then, how to use **distribution functions** to get a maximum value (`max`) for `EpiNow2::LogNormal()` and use `{epiparameter}` in your analysis.
In the next episode we'll learn how to use `{EpiNow2}` to correctly specify distributions and estimate transmissibility. We'll also learn how to use **distribution functions** to get a maximum value (`max`) for `EpiNow2::LogNormal()` and use `{epiparameter}` in your analysis.

:::::::::::::::::::::::::::::: callout

Expand All @@ -500,7 +500,7 @@ covid_serialint_parameters

This gets a vector of class `<numeric>` ready to use as input for any other package!

Consider that {EpiNow2} functions also accept distribution parameters as inputs. Run `?EpiNow2::LogNormal` to read the [Probability distributions](https://epiforecasts.io/EpiNow2/reference/Distributions.html) reference manual.
Consider that `{EpiNow2}` functions also accept distribution parameters as inputs. Run `?EpiNow2::LogNormal` to read the [Probability distributions](https://epiforecasts.io/EpiNow2/reference/Distributions.html) reference manual.

::::::::::::::::::::::::::::::

Expand All @@ -525,10 +525,10 @@ Answer:
Use the `$` operator plus the <kbd>tab</kbd> or <kbd>↹</kbd> keyboard button to explore them as an expandable list:

```r
covid_serialint$
ebola_serial$
```

Use the `str()` to display the structure of the `<epiparameter>` R object.
Use `str()` to display the structure of the `<epiparameter>` R object.

::::::::::::::::::

Expand Down Expand Up @@ -575,7 +575,7 @@ An interesting element is the `method_assess` nested entry, which refers to the
covid_serialint$method_assess
```

We will explore these concepts following episodes!
We will explore these concepts in the following episodes!

::::::::::::::::::::::::::::::

Expand Down
42 changes: 21 additions & 21 deletions episodes/delays-functions.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ editor_options:

::::::::::::::::::::::::::::::::::::: objectives

- Use distribution functions to continuous and discrete distributions stored as `<epiparameter>` objects.
- Use distribution functions with continuous and discrete distributions stored as `<epiparameter>` objects.
- Convert a continuous to a discrete distribution with `{epiparameter}`.
- Connect `{epiparameter}` outputs with `{EpiNow2}` inputs.

Expand Down Expand Up @@ -59,7 +59,7 @@ library(EpiNow2)
library(tidyverse)
```

To recap, we learned that `{epiparameter}` help us to *choose* one specific set of epidemiological parameters from the literature, instead of copy/pasting them *by hand*:
To recap, we learned that `{epiparameter}` helps us to *choose* one specific set of epidemiological parameters from the literature, instead of copy/pasting them *by hand*:

```{r,message=FALSE}
covid_serialint <-
Expand Down Expand Up @@ -144,7 +144,7 @@ epiparameter::generate(covid_serialint, times = 10)

::::::::: instructor

Access to the reference documentation (Help files) for these functions is accessible with the three double-colon notation: `epiparameter:::`
You can access the reference documentation (help files) for these functions with the triple-colon notation: `epiparameter:::`

- `?epiparameter:::density.epiparameter()`
- `?epiparameter:::cdf.epiparameter()`
Expand Down Expand Up @@ -183,13 +183,13 @@ plot(covid_serialint)

```{r,eval=TRUE}
# calculate probability of finding backward cases
# with contact traicing window of 2 days
# with contact tracing window of 2 days
window_2 <- epiparameter::cdf(covid_serialint, q = 2)

window_2

# calculate probability of finding backward cases
# with contact traicing window of 6 days
# with contact tracing window of 6 days
window_6 <- epiparameter::cdf(covid_serialint, q = 6)

window_6
Expand All @@ -214,15 +214,15 @@ Given the COVID-19 serial interval:

If we exchange the question between days and cumulative probability to:

- When considering secondary cases, how many days following the symptom onset of primary cases can we expect 55% of symptom onset to occur?
- When considering secondary cases, within how many days following the symptom onset of primary cases can we expect 55% of secondary symptom onset to occur?

```{r,eval=FALSE}
quantile(covid_serialint, p = 0.55)
```

An interpretation could be:

- The 55% percent of the symptom onset of secondary cases will happen after 4.2 days after the symptom onset of primary cases.
- 55% of secondary cases will have their symptom onset within around 4.3 days of symptom onset in the primary case.

::::::::::::::::::::::::::

Expand Down Expand Up @@ -260,7 +260,7 @@ While for a **continuous** distribution, we plot the *Probability Density Functi
plot(covid_serialint_discrete)
```

To finally get a `max` value, let's access the quantile value of the 99th percentile or `0.99` probability of the distribution with the `prob_dist$q` notation, similarly to how we access the `summary_stats` values.
To finally get a `max` value, let's access the quantile value of the 99th percentile or `0.99` cumulative probability of the distribution using the `quantile()` function, as we did above for the continuous distribution.

```{r}
covid_serialint_discrete_max <-
Expand Down Expand Up @@ -303,18 +303,18 @@ covid_incubation <-

covid_incubation

# to get an integer as a response, discretize the distribution
# to get an integer as a response, discretise the distribution
covid_incubation_discrete <- epiparameter::discretise(covid_incubation)

covid_incubation_discrete

# calculate the quantile or value at the percertile 99th from the distribution
# calculate the quantile or value at the 99th percentile from the distribution
quantile(covid_incubation_discrete, p = 0.99)
```

99% of those who develop COVID-19 symptoms will do so within `r quantile(covid_incubation_discrete, p = 0.99)` days of infection.

Now, Is this result consistent with the duration of quarantine recommended in practice during the COVID-19 pandemic?
Now, is this result consistent with the duration of quarantine recommended in practice during the COVID-19 pandemic?

::::::::::::::::::::::::::

Expand Down Expand Up @@ -405,11 +405,11 @@ The `{epiparameter}` will give you access to the parameter estimated from histor
Follow these steps:

- Get access to the `serial interval` distribution of `Ebola` using `{epiparameter}`.
- Access to one entry from the study with the highest sample size.
- Access one entry from the study with the highest sample size.
- Print the output and read the description.
- Identify which probability distribution (e.g., Gamma, Lognormal, etc.) was used by authors to model the delay.
- Identify which probability distribution (e.g., Gamma, Lognormal, etc.) was used by the authors to model the delay.
- Extract the distribution parameters for the corresponding probability distribution.
- Calculate an exact maximum value for the delay distribution (e.g., the 99th percentile).
- Calculate an exact maximum value for the delay distribution (e.g., the 99th percentile).
- Plug-in the distribution parameters from the `<epiparameter>` to the corresponding probability distribution function in `{EpiNow2}`
(e.g., `EpiNow2::Gamma()`, `EpiNow2::LogNormal()`, etc.).

Expand Down Expand Up @@ -468,7 +468,7 @@ ebola_serialint_max <- ebola_serialint %>%
ebola_serialint_max


# 4. adapt {epiparameter} to {EpiNow2} distribution inferfase
# 4. adapt {epiparameter} to the {EpiNow2} distribution interface
ebola_generationtime <- EpiNow2::Gamma(
shape = ebola_serialint_params["shape"],
scale = ebola_serialint_params["scale"],
Expand All @@ -484,12 +484,12 @@ plot(ebola_serialint)
```

```{r}
# plot the `EpiNow2` class object
# plot the `dist_spec` class object from {EpiNow2}
plot(ebola_generationtime)
```

Plotting distributions from the `{EpiNow2}` interface always gives a discretized output.
From the legend: `PMF` stants for Probability Mass Function and `CMF` stants for Cummulative Mass Function.
Plotting distributions from the `{EpiNow2}` interface always gives a discretised output.
From the legend: `PMF` stands for Probability Mass Function and `CMF` stands for Cumulative Mass Function.

::::::::::::::::::::

Expand Down Expand Up @@ -520,7 +520,7 @@ The `delays` argument and the `delay_opts()` helper function are analogous to th
```r
epinow_estimates <- EpiNow2::epinow(
# cases
reported_cases = example_confirmed[1:60],
data = example_confirmed[1:60],
# delays
generation_time = EpiNow2::generation_time_opts(covid_serial_interval),
delays = EpiNow2::delay_opts(covid_incubation_time)
Expand Down Expand Up @@ -740,7 +740,7 @@ incubation_period_ebola <-
EpiNow2::Gamma(
mean = ebola_incubation$summary_stats$mean,
sd = ebola_incubation$summary_stats$sd,
max = quantile(ebola_serial_discrete, p = 0.99)
max = quantile(ebola_incubation_discrete, p = 0.99)
)

# epinow ------------------------------------------------------------------
Expand Down Expand Up @@ -826,7 +826,7 @@ influenza_incubation <-
single_epiparameter = TRUE
)

# Discretize incubation period
# Discretise incubation period
influenza_incubation_discrete <-
epiparameter::discretise(influenza_incubation)

Expand Down
Loading
Loading