diff --git a/config.yaml b/config.yaml index 1e8b76f1..c62ee29f 100644 --- a/config.yaml +++ b/config.yaml @@ -14,17 +14,17 @@ carpentry: 'incubator' title: 'Outbreak analytics with R' # Date the lesson was created (YYYY-MM-DD, this is empty by default) -created: ~ +created: # Comma-separated list of keywords for the lesson -keywords: 'forecasts, epidemic models, interventions' #FIXME +keywords: 'forecasts, epidemic models, interventions' # Life cycle stage of the lesson # possible values: pre-alpha, alpha, beta, stable life_cycle: 'pre-alpha' -# License of the lesson -license: 'CC-BY 4.0' #FIXME +# License of the lesson materials (recommended CC-BY 4.0) +license: 'CC-BY 4.0' # Link to the source repository for this lesson source: 'https://github.com/epiverse-trace/tutorials' @@ -33,7 +33,7 @@ source: 'https://github.com/epiverse-trace/tutorials' branch: 'main' # Who to contact if there are any issues -contact: 'andree.valle-campos@lshtm.ac.uk' #FIXME +contact: 'andree.valle-campos@lshtm.ac.uk' # Navigation ------------------------------------------------ # @@ -59,6 +59,8 @@ contact: 'andree.valle-campos@lshtm.ac.uk' #FIXME # Order of episodes in your lesson episodes: +- introduction.Rmd +- read-delays.Rmd - quantify-transmissibility.Rmd - create-forecast.Rmd - simulating-transmission.Rmd @@ -79,6 +81,7 @@ profiles: # # This space below is where custom yaml items (e.g. pinning # sandpaper and varnish versions) should live + varnish: epiverse-trace/varnish@epiversetheme # this is carpentries/sandpaper#533 in our fork so we can keep it up to date with main sandpaper: epiverse-trace/sandpaper@patch-renv-github-bug diff --git a/episodes/fig/disease-reporting.jpg b/episodes/fig/disease-reporting.jpg new file mode 100644 index 00000000..709b07ad Binary files /dev/null and b/episodes/fig/disease-reporting.jpg differ diff --git a/episodes/fig/fig5a-normaldistribution.png b/episodes/fig/fig5a-normaldistribution.png new file mode 100644 index 00000000..c6bcbb86 Binary files /dev/null and b/episodes/fig/fig5a-normaldistribution.png differ diff --git a/episodes/fig/incubation-period-serial-interval.jpg b/episodes/fig/incubation-period-serial-interval.jpg new file mode 100644 index 00000000..896c7e92 Binary files /dev/null and b/episodes/fig/incubation-period-serial-interval.jpg differ diff --git a/episodes/fig/infectiousness-covid19.jpg b/episodes/fig/infectiousness-covid19.jpg new file mode 100644 index 00000000..48385dce Binary files /dev/null and b/episodes/fig/infectiousness-covid19.jpg differ diff --git a/episodes/fig/pkgs-hexlogos.png b/episodes/fig/pkgs-hexlogos.png new file mode 100644 index 00000000..c5515d57 Binary files /dev/null and b/episodes/fig/pkgs-hexlogos.png differ diff --git a/episodes/fig/reproduction-generation-time.png b/episodes/fig/reproduction-generation-time.png new file mode 100644 index 00000000..06b3978f Binary files /dev/null and b/episodes/fig/reproduction-generation-time.png differ diff --git a/episodes/fig/reproduction-number-pre-symptomatic.png b/episodes/fig/reproduction-number-pre-symptomatic.png new file mode 100644 index 00000000..379580ab Binary files /dev/null and b/episodes/fig/reproduction-number-pre-symptomatic.png differ diff --git a/episodes/fig/rt-adjusting-delays.png b/episodes/fig/rt-adjusting-delays.png new file mode 100644 index 00000000..7d1e19c1 Binary files /dev/null and b/episodes/fig/rt-adjusting-delays.png differ diff --git a/episodes/fig/seria-interval-fitted-distributions.jpg b/episodes/fig/seria-interval-fitted-distributions.jpg new file mode 100644 index 00000000..58138c55 Binary files /dev/null and b/episodes/fig/seria-interval-fitted-distributions.jpg differ diff --git a/episodes/fig/serial-interval-covid-sars.jpg b/episodes/fig/serial-interval-covid-sars.jpg new file mode 100644 index 00000000..e76bc073 Binary files /dev/null and b/episodes/fig/serial-interval-covid-sars.jpg differ diff --git a/episodes/fig/serial-interval-observed.jpeg b/episodes/fig/serial-interval-observed.jpeg new file mode 100644 index 00000000..acec2e44 Binary files /dev/null and b/episodes/fig/serial-interval-observed.jpeg differ diff --git a/episodes/fig/serial-interval-pairs.jpg b/episodes/fig/serial-interval-pairs.jpg new file mode 100644 index 00000000..c6f4fd5a Binary files /dev/null and b/episodes/fig/serial-interval-pairs.jpg differ diff --git a/episodes/fig/time-periods.jpg b/episodes/fig/time-periods.jpg new file mode 100644 index 00000000..63ef3b0b Binary files /dev/null and b/episodes/fig/time-periods.jpg differ diff --git a/episodes/introduction.Rmd b/episodes/introduction.Rmd new file mode 100644 index 00000000..bf059f68 --- /dev/null +++ b/episodes/introduction.Rmd @@ -0,0 +1,179 @@ +--- +title: 'Outbreak analytics pipelines' +teaching: 10 +exercises: 2 +editor_options: + chunk_output_type: console +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- Why use R packages for Outbreak analytics? +- What can we do to analyse our outbreak data? +- How can I start doing Outbreak Analytics with R? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Explain our vision on the need for outbreak analytics R packages. +- Share our strategy to create R packages into an outbreak analytics pipeline. +- Define our plan to start your learning path in outbreak analytics with R. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Prerequisites + +This episode requires you to be familiar with: + +**Data science** : Basic programming with R. + +**Epidemic theory** : Reproduction number. + +::::::::::::::::::::::::::::::::: + +## Why to use R packages for Outbreak analytics? + +Outbreaks appear with different diseases and in different contexts, but what all of them have in common are the key public health questions ([Cori et al. 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371#d1e605)). + +Is the epidemic going to take off? Is it under control? How much effort will be needed to control it? We can answer them by _quantifying the transmissibility_ of the disease. The most used parameter for this is the reproduction number ($R$), the average number of secondary infections caused by a typical primary case in the population +of interest ([Prism, 2016](http://prism.edu.au/publications/prism-modeling-guideline/)). We can intuitively interpret it as: + +- if $R>1$, the epidemic is likely to grow, +- if $R<1$, the epidemic is likely to decline. + +We can estimate the reproduction number by initially using two __data inputs__: the incidence of reported cases and the [generation time](../learners/reference.md#generationtime) distribution. But to calculate it, we must apply the appropriate mathematical models written in code with the required computational methods. That is not enough! Following _good practices_, the code we write should be peer-reviewed and contain internal tests to double-check that we are getting the estimates we expect. Imagine rewriting all of it during a health emergency! + +In R, the fundamental unit of shareable code is the _package_. A package bundles together code, data, documentation, and tests and is easy to share with others ([Wickham and Bryan, 2023](https://r-pkgs.org/introduction.html)). We, as epidemiologists, can contribute to their collaborative maintenance as a community to perform less error-prone data analysis pipelines. + +::::::::::::::::::::::::::::::::: discussion + +### Questions to think about + +Remember your last experience with outbreak data and reflect on these questions: + +- What data sources did you need to understand the outbreak? +- How did you get access to that data? +- Is that analysis pipeline you followed reusable for the next response? + +Reflect on your experiences. + +::::::::::::::::::::::::::::::::::::::::::: + + +## Example: Quantify transmission + +The `{EpiNow2}` package provides a three-step solution to _quantify the transmissibility_. Let's see how to do this with a minimal example. First, load the package: + +```{r,warning=FALSE} +library(EpiNow2) +``` + +### First, get your case data + +Case incidence data must be stored in a data frame with the observed number of cases per day. We can read an example from the package: + +```{r} +example_confirmed +``` + +### Then, set the generation time + +Not all primary cases have the same probability of generating a secondary case. The onset and cessation of [infectiousness](../learners/reference.md#infectiousness) may occur gradually. For `{EpiNow2}`, we can specify it as a probability `distribution` with `mean`, standard deviation `sd`, and maximum value `max`: + +```{r} +generation_time <- dist_spec( + mean = 3.6, + sd = 3.1, + max = 20, + distribution = "lognormal" +) +``` + +### Let's calculate the reproduction number! + +In the `epinow()` function we can add: + +- the `reported_cases` data frame, +- the `generation_time` delay distribution, and +- the computation `stan` parameters for this calculation: + +```{r,message=FALSE,warning=FALSE} +epinow_estimates <- epinow( + # cases + reported_cases = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(generation_time), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) +``` + +As an output, we get the time-varying (or [effective](../learners/reference.md#effectiverepro)) reproduction number, as well as the cases by date of report and date of infection: + +```{r} +base::plot(epinow_estimates) +``` + +::::::::::::::::: callout + +### Is this $Rt$ estimation biased? + +Review [Gostic et al., 2020](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409) about what additional adjustments this estimation requires to avoid false precision in $Rt$. + +::::::::::::::::::::::::: + +## The problem! + +However, _quantifying the transmissibility_ during a real-life outbreak response is more challenging than this example! + +Usually, we receive outbreak data in non-standard formats, requiring specific steps and taking the most time to prepare usable data inputs. Some of them are: + +- Read delay distributions from the literature +- Read and clean case data +- Validate your line list +- Describe case data + +And this is not the end. After _quantifying transmissibility_ we need to answer more key public health questions like: What is the attack rate we expect? What would be the impact of a given intervention? We can use the reproduction number and other outputs as new inputs for complementary tasks. For example: + +- Estimate severity +- Create short-term forecast +- Simulate transmission scenarios +- Compare interventions + +So, all these tasks can be interconnected in a pipeline: + +![The outbreak analytics pipeline.](https://epiverse-trace.github.io/task_pipeline-minimal.svg) + +## What can we do? + +Our strategy is gradually incorporating specialised R packages into our traditional analysis pipeline. These packages should fill the gaps in these epidemiology-specific tasks in response to outbreaks. + +Epiverse-TRACE's aim is to provide a software ecosystem for outbreak analytics. We support the development of software pieces, make the existing ones interoperable for the user experience, and stimulate a community of practice. + +![](fig/pkgs-hexlogos.png) + +## How can I start? + +Our plan for these tutorials is to introduce key solutions from packages in all the tasks before and after the _Quantify transmission_ task, plus the required theory concepts to interpret modelling outputs and make rigorous conclusions. + +- In the first set of episodes, you will learn how to optimise the reading of delay distributions and cleaning of case data to input them into the _Quantify transmission_ task. These preliminary tasks are the __Early tasks__. These include packages like `{readepi}`, `{cleanepi}`, `{linelist}`, `{epiparameter}`, and `{episoap}`. + +- Then, we will get deeper into the packages and required theory to _Quantify transmission_ and perform more real-time analysis tasks next to it. These are the __Middle tasks__. This includes `{EpiNow2}`, `{cfr}`, `{epichains}`, and `{superspreading}`. + +- Lastly, we will use _Quantify transmission_ data outputs to compare it to other indicators and simulate epidemic scenarios as part of the __Late tasks__. This includes `{finalsize}`, `{epidemics}`, and `{scenarios}`. + + +::::::::::::::::::::::::::::::::::::: keypoints + +- Our vision is to have pipelines of R packages for outbreak analytics. +- Our strategy is to create interconnected tasks to get relevant outputs for public health questions. +- We plan to introduce package solutions and theory bits for each of the tasks in the outbreak analytics pipeline. + +:::::::::::::::::::::::::::::::::::::::::::::::: + diff --git a/episodes/read-delays.Rmd b/episodes/read-delays.Rmd new file mode 100644 index 00000000..90e6c8e3 --- /dev/null +++ b/episodes/read-delays.Rmd @@ -0,0 +1,1380 @@ +--- +title: 'Read delays' +teaching: 10 +exercises: 2 +editor_options: + chunk_output_type: console +--- + +:::::::::::::::::::::::::::::::::::::: questions + +- How to get delay distributions from a systematic review? +- How to connect reused delays with my existing analysis pipeline? +- When should delays be reused from a systematic review? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objectives + +- Get delays from a systematic review with `{epiparameter}`. +- Get statistical summaries and distribution parameters of delay distributions. +- Use distribution functions from delay distributions. +- Convert a continuous to a discrete delay distribution. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: prereq + +## Prerequisites + +This episode requires you to be familiar with: + +**Data science** : Basic programming with R. + +**Epidemic theory** : Epidemiological parameters. Time periods. + +::::::::::::::::::::::::::::::::: + +## Introduction + +The [natural history](../learners/reference.md#naturalhistory) of an infectious disease shows that its development has a regularity from stage to stage. The time periods from an infectious disease inform about the timing of transmission and interventions. + +![Definition of key time periods. From [Xiang et al, 2021](https://www.sciencedirect.com/science/article/pii/S2468042721000038)](fig/time-periods.jpg) + + +::::::::::::::::: callout + +### Definitions + +Look at the [glossary](../learners/reference.md) for the definitions of all the time periods of the figure above! + +::::::::::::::::::::::::: + +However, early in an epidemic, modelling efforts can be delayed by the lack of a centralized resource that summarises input 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 systematic review protocols that can help build models faster for coming outbreaks and epidemics from known pathogens and unknown ones related to known families of viruses. + + + +To exemplify how to use `{epiparameter}` in your analysis pipeline, our goal in this episode will be to replace the `generation_time` input that we can use for `EpiNow2::epinow()`. + +```r +epinow_estimates <- epinow( + # cases + reported_cases = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(generation_time), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) +``` + +To do this replacement, instead of plug-in numeric values to `EpiNow2::dist_spec()` to manually specify the delay distribution parameters, we are going to collect them from the library of epidemiological parameters provided by `{epiparameter}`: + +```r +generation_time <- dist_spec( + mean = 3.6, + sd = 3.1, + max = 20, + distribution = "lognormal" +) +``` + +Let's explore how we can access this and other time delays using `{epiparameter}`. We'll use the pipe `%>%` to connect some of their functions, so let's also call to the `{tidyverse}` package: + +```{r,warning=FALSE,message=FALSE} +library(epiparameter) +library(EpiNow2) +library(tidyverse) +``` + +## Find a Generation time + +The generation time, jointly with the $R$, can inform about the speed of spread and its feasibility of control. Given a $R>1$, with a shorter generation time, cases can appear more quickly. + +![Video from the MRC Centre for Global Infectious Disease Analysis, Ep 76. Science In Context - Epi Parameter Review Group with Dr Anne Cori (27-07-2023) at ](fig/reproduction-generation-time.png) + +In calculating the effective reproduction number ($R_{t}$), the *generation time* distribution is often approximated by the [serial interval](../learners/reference.md#serialinterval) distribution. +This frequent approximation is because it is easier to observe and measure the onset of symptoms than the onset of infectiousness. + +![A schematic of the relationship of different time periods of transmission between an infector and an infectee in a transmission pair. Exposure window is defined as the time interval having viral exposure, and transmission window is defined as the time interval for onward transmission with respect to the infection time ([Chung Lau et al. 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)).](fig/serial-interval-observed.jpeg) + +However, using the *serial interval* as an approximation of the *generation time* is primarily valid for diseases in which infectiousness starts after symptom onset ([Chung Lau et al. 2021](https://academic.oup.com/jid/article/224/10/1664/6356465)). In cases where infectiousness starts before symptom onset, the serial intervals can have negative values, which is the case of a pre-symptomatic transmission ([Nishiura et al. (2020)](https://www.ijidonline.com/article/S1201-9712(20)30119-3/fulltext#gr2)). + +Additionally, even if the *generation time* and *serial interval* have the same mean, their variance usually differs, propagating bias to the $R_{t}$ estimation. $R_{t}$ estimates are sensitive not only to the mean generation time but also to the variance and form of the generation interval distribution [(Gostic et al., 2020)](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409). + +::::::::::::::::: callout + +### From time periods to probability distributions. + +When we calculate the *serial interval*, we see that not all case pairs have the same time length. We will observe this variability for any case pair and individual time period, including the [incubation period](../learners/reference.md#incubation) and [infectious period](../learners/reference.md#infectiousness). + +![Serial intervals of possible case pairs in (a) COVID-19 and (b) MERS-CoV. Pairs represent a presumed infector and their presumed infectee plotted by date of symptom onset ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#fig6)).](fig/serial-interval-pairs.jpg) + +To summarize these data from individual and pair time periods, we can find the **statistical distributions** that best fit the data ([McFarland et al., 2023](https://www.eurosurveillance.org/content/10.2807/1560-7917.ES.2023.28.27.2200806)). + + + +![Fitted serial interval distribution for (a) COVID-19 and (b) MERS-CoV based on reported transmission pairs in Saudi Arabia. We fitted three commonly used distributions, Lognormal, Gamma, and Weibull distributions, respectively ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#fig5)).](fig/seria-interval-fitted-distributions.jpg) + +Statistical distributions are summarized in terms of their **summary statistics** like the *location* (mean and percentiles) and *spread* (variance or standard deviation) of the distribution, or with their **distribution parameters** that inform about the *form* (shape and rate/scale) of the distribution. These estimated values can be reported with their **uncertainty** (95% confidence intervals). + +| Gamma | mean | shape | rate/scale | +|:--------------|:--------------|:--------------|:--------------| +| MERS-CoV | 14.13(13.9–14.7) | 6.31(4.88–8.52) | 0.43(0.33–0.60) | +| COVID-19 | 5.1(5.0–5.5) | 2.77(2.09–3.88) | 0.53(0.38–0.76) | + +| Weibull | mean | shape | rate/scale | +|:--------------|:--------------|:--------------|:--------------| +| MERS-CoV | 14.2(13.3–15.2) | 3.07(2.64–3.63) | 16.1(15.0–17.1) | +| COVID-19 | 5.2(4.6–5.9) | 1.74(1.46–2.11) | 5.83(5.08–6.67) | + +| Log normal | mean | mean-log | sd-log | +|:--------------|:--------------|:--------------|:--------------| +| MERS-CoV | 14.08(13.1–15.2) | 2.58(2.50–2.68) | 0.44(0.39–0.5) | +| COVID-19 | 5.2(4.2–6.5) | 1.45(1.31–1.61) | 0.63(0.54–0.74) | + +Table: Serial interval estimates using Gamma, Weibull, and Log normal distributions. 95% confidence intervals for the shape and scale (logmean and sd for Log normal) parameters are shown in brackets ([Althobaity et al., 2022](https://www.sciencedirect.com/science/article/pii/S2468042722000537#tbl3)). + +::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Serial interval + +Assume that COVID-19 and SARS have similar reproduction number values and that the serial interval approximates the generation time. + +Given the Serial interval of both infections in the figure below: + +- Which one would be harder to control? +- Why do you conclude that? + +![Serial interval of novel coronavirus (COVID-19) infections overlaid with a published distribution of SARS. ([Nishiura et al, 2020](https://www.ijidonline.com/article/S1201-9712(20)30119-3/fulltext))](fig/serial-interval-covid-sars.jpg) + +::::::::::::::::: hint + +The peak of each curve can inform you about the location of the mean of each distribution. The larger the mean, the larger the serial interval. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +Which one would be harder to control? + +- COVID-19 + +Why do you conclude that? + +- COVID-19 has the lowest mean serial interval. The approximate mean value for the serial interval of COVID-19 is around four days, and SARS is about seven days. Thus, COVID-19 will likely have newer generations in less time than SARS, assuming similar reproduction numbers. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +:::::::::::::::::::::: instructor + +The objective of the assessment above is to assess the interpretation of a larger or shorter generation time. + +:::::::::::::::::::::: + +## Extract epidemiological parameters + +First, let's assume that the data set `example_confirmed` has COVID-19 observed cases. So, we need to find a reported generation time for COVID-19 or any other useful parameter for this aim. + +Let's start by looking at how many parameters we have in the epidemiological distributions database (`epidist_db`) for the `disease` named `covid`-19: + +```{r} +epiparameter::epidist_db( + disease = "covid" +) +``` + +From the `{epiparameter}` package, we can use the `epidist_db()` function to ask for any `disease` and also for a specific epidemiological distribution (`epi_dist`). + +Let's ask now how many parameters we have in the epidemiological distributions database (`epidist_db`) with the generation time using the string `generation`: + +```{r} +epiparameter::epidist_db( + epi_dist = "generation" +) +``` + +Currently, in the library of epidemiological parameters, we have one `generation` time entry for Influenza. Considering the abovementioned considerations, we can look at the `serial` intervals for `COVID`-19. + +```{r} +epiparameter::epidist_db( + disease = "COVID", + epi_dist = "serial" +) +``` + +::::::::::::::::: callout + +### CASE-INSENSITIVE + +`epidist_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. + +::::::::::::::::::::::::: + +We get more than one epidemiological delay. To summarize this view and get the column names from the underlying parameter dataset, we can add the `epiparameter::list_distributions()` function to the previous code using the pipe `%>%`: + +```{r} +epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial" +) %>% + epiparameter::list_distributions() +``` + +::::::::::::::::::::::::::::::::: challenge + +### Ebola's incubation periods + +Take 5 minutes: + +- How many delay distributions are for the Ebola disease? + +- How many delay distributions are for the incubation period of Ebola? + +- Explore the library and find the disease with the delay distribution of your interest! Do you recognize the paper? + +::::::::::::::::: hint + +The `{epiparameter}` combo of `epidist_db()` plus `list_distributions()` list all the entries by: + +- disease, +- epidemiological distribution, +- the type of the probability distribution, +- author of the study, and +- year of study. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE} +# 16 delays distributions +epiparameter::epidist_db( + disease = "ebola" +) + +# 5 delay distributions are for the incubation period +epiparameter::epidist_db( + disease = "ebola", + epi_dist = "incubation" +) +``` + +Now, from the output of `epiparameter::epidist_db()`, What is an [offspring distribution](../learners/reference.md#offspringdist)? + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + + +## Select a single distribution + +The `epiparameter::epidist_db()` function works as a filtering or subset function. Let's use the `author` argument to filter `Hiroshi Nishiura` parameters: + +```{r} +epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Hiroshi" +) %>% + epiparameter::list_distributions() +``` + +We still get more than one epidemiological parameter. We can set the `single_epidist` argument to `TRUE` to only one: + +```{r} +epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Hiroshi", + single_epidist = TRUE +) +``` + +::::::::::::::::: callout + +### How does `single_epidist` works? + +Looking at the help documentation for `?epiparameter::epidist_db()`: + +- If multiple entries match the arguments supplied and `single_epidist = TRUE`, +- Then, the parameterised `⁠`⁠ with the largest sample size will be returned. +- If multiple entries are equal after this sorting, the first entry will be returned. + +What does a parametrised `` is? Look at `?is_parameterised`. + +::::::::::::::::::::::::: + +Now, we have an epidemiological parameter we can reuse! We can replace the numbers we plug into `EpiNow2::dist_spec()`. + +Let's assign this `` class object to the `covid_serialint` object. + +```{r} +covid_serialint <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Nishiura", + single_epidist = TRUE + ) + +covid_serialint +``` + +::::::::::::::::::::::::::::::::: challenge + +### Ebola's incubation period + +Take 2 minutes: + +- What type of distribution has the incubation period of Ebola with the highest sample size? +- How would you access to the sample size of the other studies in the `` class object? + +::::::::::::::::: hint + +The `{epiparameter}` combo of `epidist_db()` plus `list_distributions()` list all the entries by: + +- disease, +- epidemiological distribution, +- the type of the probability distribution, +- author of the study, and +- year of study. + +This is a `` class object: + +```{r,eval=FALSE} +epiparameter::epidist_db( + disease = "ebola", + epi_dist = "incubation" +) +``` + + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE} +# the distribution with the highest sample size has a gamma distribution +epiparameter::epidist_db( + disease = "ebola", + epi_dist = "incubation", + single_epidist = TRUE +) +``` + +To access the `sample_size`, review an [issue reported in the GitHub repository](https://github.com/epiverse-trace/epiparameter/issues/227) of the `{epiparameter}` package. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## Extract the summary statistics + +We can get the `mean` and standard deviation (`sd`) from this `` diving into the `summary_stats` object: + +```{r} +# get the mean +covid_serialint$summary_stats$mean +``` + +:::::::::::::::::::::::::::::: challenge + +### How to get the `sd` and other nested elements? + +Take 1 minute to: + +1. Get the `sd` of the epidemiological distribution. + +2. Find the `sample_size` used in the study. + +3. Explore all the other nested elements within the `` object. + +Share about: + +- What elements do you find useful for your analysis? +- What other elements would you like to see in this object? How? + +::::::::: hint + +Use the `$` operator plus the tab keyboard button to explore them as an expandable list: + +```r +covid_serialint$ +``` + +Use the `str()` to display the structure of the `` R object. + +:::::::::::::::::: + +:::::::::: solution + +```{r,eval=FALSE} +# get the sd +covid_serialint$summary_stats$sd + +# get the sample_size +covid_serialint$metadata$sample_size +``` + +:::::::::::::::::::: + +:::::::::::::::::::::::::::::::: + +:::::::::::::::::::: intructor + +An interesting element is the `method_assess` nested entry, which refers to the methods used by the study authors to assess for bias while estimating the serial interval distribution. + +```{r} +covid_serialint$method_assess +``` + +We will explore these concepts at the end! + +:::::::::::::::::::::::::::::: + + +::::::::::::::::::::::::::::::::: challenge + +### Ebola's severity parameter + +A severity parameter like the duration of hospitalization could add to the information needed about the bed capacity in response to an outbreak ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +For Ebola: + +- what is a reported point estimate and uncertainty of the mean duration of health-care and case isolation? + +::::::::::::::::: hint + +An informative delay measures the time from symptom onset to recovery or death. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE} +# one way to get the list of all the available parameters +epidist_db(disease = "all") %>% + list_distributions() %>% + as_tibble() %>% + distinct(epi_distribution) + +ebola_severity <- epidist_db( + disease = "ebola", + epi_dist = "onset to discharge" +) + +# point estimate +ebola_severity$summary_stats$mean +# 95% confidence intervals +ebola_severity$summary_stats$mean_ci +# limits of the confidence intervals +ebola_severity$summary_stats$mean_ci_limits +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + + +## Continuous distributions + +The following output has four entries with different content in the **probability distribution** (`prob_distribution`) column: + +```{r} +distribution <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "serial" + ) + +distribution %>% + list_distributions() +``` + +Entries with a missing value (``) in the `prob_distribution` column are *non-parameterised* entries. They have summary statistics but no probability distribution. Compare these two outputs: + +```{r,eval=FALSE} +distribution[[1]]$summary_stats +distribution[[1]]$prob_dist +``` + +::::::::::::::::: spoiler + +### 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`: + +```{r,eval=FALSE} +distribution[[1]]$metadata$inference_method +distribution[[2]]$metadata$inference_method +distribution[[4]]$metadata$inference_method +``` + +::::::::::::::::::::::::: + +In the `epiparameter::list_distributions()` output, we can also find different types of probability distributions (e.g., Log-normal, Weibull, Normal). + +```{r} +distribution %>% + list_distributions() +``` + +In `{epiparameter}`, you will mostly find **continuous** distributions like these. You can visualize any of them with the `plot()` function and access to: + +- the *Probability Density Function (PDF)* and +- the *Cumulative Distribution Function (CDF)*. + +```{r} +plot(distribution[[2]]) +``` + +With the `day_range` argument, you can change the length or number of days in the `x` axis. Explore what it look like: + +```{r,eval=FALSE} +plot(distribution[[2]], day_range = 0:20) +``` + +::::::::::::::::: discussion + +### The distribution Zoo + +Explore this shinyapp called **The Distribution Zoo**! + +Follow these steps to reproduce the form of the `covid_serialint` distribution: + +1. Access to shinyapp website, +2. Go to the left panel, +3. Keep the *Category of distribution*: `Continuous Univariate`, +4. Select a new *Type of distribution*: `Log-Normal`, +5. Move the **sliders**, i.e. the graphical control element that allows you to adjust a value by moving a handle along a horizontal track or bar to the `covid_serialint` parameters. + +Replicate these with the `distribution` object and all its list elements: `2`, `3`, and `4`. Explore how the shape of a distribution changes when its parameters change. + +Share about: + +- What other features of the website do you find helpful? + +::::::::::::::::::::::::: + + + +## Distribution functions + +In R, all the statistical distributions have functions to access the: + +- Probability **Density** function (PDF), +- Cumulative Distribution function (**CDF**), +- **Quantile** function, and +- **Random** values from the given distribution. + +:::::::::::: spoiler + +### Functions for the Normal distribution + +If you need it, read in detail about the [R probability functions for the normal distribution](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc), each of its definitions and identify in which part of a distribution they are located! + +![The four probability functions for the normal distribution ([Jack Weiss, 2012](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc))](fig/fig5a-normaldistribution.png) + +:::::::::::::::::::: + +If you look at `?stats::Distributions`, each type of distribution has a unique set of functions. However, `{epiparameter}` gives you the same four functions to access each of the values above for any `` object you want! + +```{r,eval=FALSE} +# plot this to have a visual reference +plot(covid_serialint, day_range = 0:20) +``` + +```{r} +# the density value at quantile value of 10 (days) +density(covid_serialint, at = 10) + +# the cumulative probability at quantile value of 10 (days) +cdf(covid_serialint, q = 10) + +# the quantile value (day) at a cumulative probability of 60% +quantile(covid_serialint, p = 0.6) + +# generate 10 random values (days) given +# the distribution family and its parameters +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:::` + +- `?epiparameter:::density.epidist()` +- `?epiparameter:::cdf.epidist()` +- `?epiparameter:::quantile.epidist()` +- `?epiparameter:::generate.epidist()` + +:::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### Window for contact tracing and the Serial interval + +The **serial interval** is important in the optimization of contact tracing since it provides a time window for the containment of a disease spread ([Fine, 2003](https://academic.oup.com/aje/article/158/11/1039/162725)). Depending on the serial interval, we can evaluate the need to expand the number of days pre-onset to consider in the contact tracing to include more backwards contacts ([Davis et al., 2020](https://assets.publishing.service.gov.uk/media/61e9ab3f8fa8f50597fb3078/S0523_Oxford_-_Backwards_contact_tracing.pdf)). + +With the COVID-19 serial interval (`covid_serialint`) calculate: + +- How much more of the backward cases could be captured if the contact tracing method considered contacts up to 6 days pre-onset compared to 2 days pre-onset? + +::::::::::::::::: hint + +In Figure 5 from the [R probability functions for the normal distribution](https://sakai.unc.edu/access/content/group/3d1eb92e-7848-4f55-90c3-7c72a54e7e43/public/docs/lectures/lecture13.htm#probfunc), the shadowed section represents a cumulative probability of `0.997` for the quantile value at `x = 2`. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE} +plot(covid_serialint) +``` + +```{r,eval=FALSE} +cdf(covid_serialint, q = 2) +cdf(covid_serialint, q = 6) +``` + +Given the COVID-19 serial interval: + +- A contact tracing method considering contacts up to 2 days pre-onset will capture around 11.1% of backward cases. + +- If this period is extended to 6 days pre-onset, this could include 76.2% of backward contacts. + +:::::::::::::::::::::::::: + +::::::::::::::::: solution + +### What if + +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? + +```{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. + +:::::::::::::::::::::::::: + + +::::::::::::::::::::::::::::::::::::::::::: + + +## Discretize a continuous distribution + +We are getting closer to the end! `EpiNow2::dist_spec()` still needs a maximum value (`max`). + +One way to do this is to get the quantile value for the distribution's 99.9th percentile or `0.999` cumulative probability. For this, we need access to the set of distribution functions for our `` object. + +We can use the set of distribution functions for a _continuous_ distribution (as above). However, these values will be _continuous_ numbers. We can **discretize** the continuous distribution stored in our `` object to get discrete values from a continuous distribution. + +When we `epiparameter::discretise()` the continuous distribution we get a **discrete**(-ized) distribution: + +```{r} +covid_serialint_discrete <- + epiparameter::discretise(covid_serialint) + +covid_serialint_discrete +``` + +We identify this change in the `Distribution:` output line of the `` object. Take a double check to this line: + +``` +Distribution: discrete lnorm +``` + +While for a **continuous** distribution, we plot the *Probability Density Function (PDF)*, for a **discrete** distribution, we plot the *Probability Mass Function (PMF)*: + +```{r,eval=FALSE} +# continuous +plot(covid_serialint) + +# discrete +plot(covid_serialint_discrete) +``` + +To finally get a `max` value, let's access the quantile value of the 99.9th percentile or `0.999` probability of the distribution with the `prob_dist$q` notation, similarly to how we access the `summary_stats` values. + +```{r} +covid_serialint_discrete_max <- + covid_serialint_discrete$prob_dist$q(p = 0.999) +``` + +::::::::::::::::::::::::::::::::: challenge + +### Lenght of quarantine and Incubation period + +The **incubation period** distribution is a useful delay to assess the length of active monitoring or quarantine ([Lauer et al., 2020](https://www.acpjournals.org/doi/10.7326/M20-0504)). Similarly, delays from symptom onset to recovery (or death) will determine the required duration of health-care and case isolation ([Cori et al., 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + +Calculate: + +- Within what exact time frame do 99% of individuals who develop COVID-19 symptoms exhibit them after infection? + +::::::::::::::::: hint + +What delay distribution measures the time between infection and the onset of symptoms? + +The probability function for `` **discrete** distributions differ from the *continuous* ones! + +```{r,eval=FALSE} +# plot to have a visual reference +plot(covid_serialint_discrete, day_range = 0:20) + +# density value at quantile value 10 (day) +covid_serialint_discrete$prob_dist$d(10) + +# cumulative probability at quantile value 10 (day) +covid_serialint_discrete$prob_dist$cdf(10) + +# In what quantile value (days) do we have the 60% cumulative probability? +covid_serialint_discrete$prob_dist$q(0.6) + +# generate random values +covid_serialint_discrete$prob_dist$r(10) +``` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE} +covid_incubation <- + epiparameter::epidist_db( + disease = "covid", + epi_dist = "incubation", + single_epidist = TRUE + ) + +covid_incubation_discrete <- epiparameter::discretise(covid_incubation) + +covid_incubation_discrete$prob_dist$q(0.99) +``` + +99% of those who develop COVID-19 symptoms will do so within 16 days of infection. + +Now, _Is this result expected in epidemiological terms?_ + +:::::::::::::::::::::::::: + +::::::::::::::::: solution + +### how to create a distribution plot? + +From a maximum value with `$prob_dist$q()`, we can create a sequence of quantile values as a numeric vector and map density values for each: + +```{r,eval=FALSE} +# create a discrete distribution visualization +# from a maximum value from the distribution +covid_serialint_discrete$prob_dist$q(0.999) %>% + # generate quantile values + # as a sequence for each natural number + seq(1L, to = ., by = 1L) %>% + # coerce numeric vector to data frame + as_tibble_col(column_name = "quantile_values") %>% + mutate( + # map density values + # for each quantile in the density function + density_values = + covid_serialint_discrete$prob_dist$d(quantile_values) + ) %>% + # create plot + ggplot( + aes( + x = quantile_values, + y = density_values + ) + ) + + geom_col() +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + + +## Plug-in `{epiparameter}` to `{EpiNow2}` + +Now we can plug everything into the `EpiNow2::dist_spec()` function! + +```{r} +serial_interval_covid <- + dist_spec( + mean = covid_serialint$summary_stats$mean, + sd = covid_serialint$summary_stats$sd, + max = covid_serialint_discrete_max, + distribution = "lognormal" + ) + +serial_interval_covid +``` + +:::::::::: callout + +### Warning + +Using the serial interval instead of the generation time is an alternative that can propagate bias in your estimates, even more so in diseases with reported pre-symptomatic transmission. + +:::::::::::::::::: + +Let's replace the `generation_time` input we used for `EpiNow2::epinow()`. + +```{r,eval=FALSE} +epinow_estimates <- epinow( + # cases + reported_cases = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(serial_interval_covid), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) + +base::plot(epinow_estimates) +``` + +::::::::::::::::::::::::::::::::: challenge + +### Ebola's effective reproduction number + +Download and read the [Ebola dataset](data/ebola_cases.csv): + +- Reuse one epidemiological parameter to estimate the effective reproduction number for the Ebola dataset. +- Why did you choose that parameter? + +::::::::::::::::: hint + +To calculate the $R_t$, we need: + +- data set with confirmed cases per day and +- one key delay distribution + +Key functions we applied in this episode are: + +- `epidist_db()` +- `list_distributions()` +- `discretise()` +- probability functions for continuous and discrete distributions + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE,echo=FALSE} +# read data from the tutorial repository R project +ebola_confirmed <- + read_csv(file.path("episodes", "data", "ebola_cases.csv")) +``` + +```{r,message=FALSE,warning=FALSE,eval=FALSE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +ebola_confirmed <- + read_csv(here::here("data", "raw-data", "ebola_cases.csv")) + +# list distributions +epidist_db(disease = "ebola") %>% + list_distributions() + +# subset one distribution +ebola_serial <- epidist_db( + disease = "ebola", + epi_dist = "serial", + single_epidist = TRUE +) + +ebola_serial_discrete <- discretise(ebola_serial) + +serial_interval_ebola <- + dist_spec( + mean = ebola_serial$summary_stats$mean, + sd = ebola_serial$summary_stats$sd, + max = ebola_serial_discrete$prob_dist$q(p = 0.999), + distribution = "gamma" + ) + +# name of the type of distribution +# only for the discretised distribution +ebola_serial_discrete$prob_dist$name + +epinow_estimates <- epinow( + # cases + reported_cases = ebola_confirmed, + # delays + generation_time = generation_time_opts(serial_interval_ebola), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) + +plot(epinow_estimates) + +``` + +:::::::::::::::::::::::::: + + +::::::::::::::::::::::::::::::::::::::::::: + +## Adjusting for reporting delays + +Estimating $R_t$ requires data on the daily number of new infections. Due to lags in the development of detectable viral loads, symptom onset, seeking care, and reporting, these numbers are not readily available. All observations reflect transmission events from some time in the past. In other words, if $d$ is the delay from infection to observation, then observations at time $t$ inform $R_{t−d}$, not $R_t$. [(Gostic et al., 2020)](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409#sec007) + +![Timeline for chain of disease reporting, the Netherlands. Lab, laboratory; PHA, public health authority. From [Marinović et al., 2015](https://wwwnc.cdc.gov/eid/article/21/2/13-0504_article)](fig/disease-reporting.jpg) + +The **delay distribution** could be inferred jointly with the underlying times of infection or estimated as the sum of the **[incubation period](../learners/reference.md#incubation)** distribution and the distribution of delays from symptom onset to observation from line list data **([reporting delay](../learners/reference.md#reportingdelay))**. + +For `{EpiNow2}`, we can specify these two complementary delay distributions in the `delays` argument. + +![Rt is a measure of transmission at time t. Observations after time t must be adjusted. ICU, intensive care unit. From [Gostic et al., 2020](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409#sec007)](fig/rt-adjusting-delays.png) + +::::::::::::::::::::::::::::::::: challenge + +### Reuse an Incubation period for COVID-19 + +Use `{epiparameter}` to: + +- Find an incubation period for COVID-19. +- Add our last `epinow()` code chunk using the `delays` argument and the `delay_opts()` helper function. + +::::::::::::::::: hint + +The `delays` argument and the `delay_opts()` helper function are analogous to the `generation_time` argument and the `generation_time_opts()` helper function. + +```r +epinow_estimates <- epinow( + # cases + reported_cases = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(serial_interval_covid), + delays = delay_opts(incubation_time_covid), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) +``` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE} +covid_incubation <- epiparameter::epidist_db( + disease = "covid", + epi_dist = "incubation", + author = "Natalie", + single_epidist = TRUE +) + +covid_incubation + +covid_incubation_discrete <- epiparameter::discretise(covid_incubation) + +incubation_time_covid <- dist_spec( + mean = covid_incubation$summary_stats$mean, + sd = covid_incubation$summary_stats$sd, + max = covid_incubation_discrete$prob_dist$q(p = 0.999), + distribution = "lognormal" +) + +epinow_estimates <- epinow( + # cases + reported_cases = example_confirmed[1:60], + # delays + generation_time = generation_time_opts(serial_interval_covid), + delays = delay_opts(incubation_time_covid), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) + +base::plot(epinow_estimates) +``` + +:::::::::::::::::::::::::: + +:::::::::::::: solution + +### How much has it changed? + +After adding the incubation period, discuss: + +- Does the retrospective trend of forecast change? +- Has the uncertainty changed? +- How would you explain or interpret any of these changes? + +:::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + + +::::::::::::::::::::::::::::::::: challenge + +### Ebola's effective reproduction number was adjusted by reporting delays + +Using the same [Ebola dataset](data/ebola_cases.csv): + +- Reuse one additional epidemiological parameter for the `delays` argument in `EpiNow2::epinow()`. +- Estimate the effective reproduction number using `EpiNow2::epinow()`. +- Why did you choose that parameter? + +::::::::::::::::: hint + +We can use two complementary delay distributions to estimate the $R_t$ at time $t$. + +:::::::::::::::::::::: + +::::::::::::::::: solution + +```{r,eval=FALSE,echo=FALSE} +# read data from the tutorial repository R project +ebola_confirmed <- + read_csv(file.path("episodes", "data", "ebola_cases.csv")) +``` + +```{r,message=FALSE,warning=FALSE,eval=FALSE} +# read data +# e.g.: if path to file is data/raw-data/ebola_cases.csv then: +ebola_confirmed <- + read_csv(here::here("data", "raw-data", "ebola_cases.csv")) + +# list distributions +epidist_db(disease = "ebola") %>% + list_distributions() + +# subset one distribution for the generation time +ebola_serial <- epidist_db( + disease = "ebola", + epi_dist = "serial", + single_epidist = TRUE +) + +ebola_serial_discrete <- discretise(ebola_serial) + +serial_interval_ebola <- + dist_spec( + mean = ebola_serial$summary_stats$mean, + sd = ebola_serial$summary_stats$sd, + max = ebola_serial_discrete$prob_dist$q(p = 0.999), + distribution = "gamma" + ) + +# subset one distribution for delay of the incubation period +ebola_incubation <- epidist_db( + disease = "ebola", + epi_dist = "incubation", + single_epidist = TRUE +) + +ebola_incubation_discrete <- discretise(ebola_incubation) + +incubation_period_ebola <- + dist_spec( + mean = ebola_incubation$summary_stats$mean, + sd = ebola_incubation$summary_stats$sd, + max = ebola_incubation_discrete$prob_dist$q(p = 0.999), + distribution = "gamma" + ) + +epinow_estimates <- epinow( + # cases + reported_cases = ebola_confirmed, + # delays + generation_time = generation_time_opts(serial_interval_ebola), + delays = delay_opts(incubation_period_ebola), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) + +plot(epinow_estimates) + +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + + +::::::::::::::::::::::::::::::::: challenge + +### Extract parameters + +Use the `influenza_england_1978_school` from the `{outbreaks}` package to calculate the effective reproduction number. + +::::::::::::::::: hint + +How to get the mean and standard deviation from a generation time with median and quantiles as summary statistics? + +- Look at how to extract parameters from `{epiparameter}` vignette on [parameter extraction and conversion](https://epiverse-trace.github.io/epiparameter/articles/extract_convert.html) + +:::::::::::::::::::::: + +::::::::::::::::: solution + + + +```{r,eval=FALSE} +# What parameters are available for Influenza? +epidist_db(disease = "influenza") %>% + list_distributions() %>% + as_tibble() %>% + count(epi_distribution) + +influenza_generation <- + epidist_db( + disease = "influenza", + epi_dist = "generation" + ) + +influenza_generation_discrete <- + discretise(influenza_generation) + +# problem +# the summary statistics do not have mean and sd +influenza_generation$summary_stats +influenza_generation$summary_stats$median +influenza_generation$summary_stats$quantiles + +# solution +# extract parameters from percentiles +influenza_extracted <- extract_param( + type = "percentiles", + values = c(influenza_generation$summary_stats$quantiles[1], + influenza_generation$summary_stats$quantiles[2]), + distribution = "lnorm", + percentiles = c(0.05, 0.95) +) + +influenza_extracted + +generation_time_influenza <- + dist_spec( + mean = influenza_extracted[1], + sd = influenza_extracted[2], + max = influenza_generation_discrete$prob_dist$q(p = 0.999), + distribution = "lognormal" + ) + +influenza_cleaned <- + outbreaks::influenza_england_1978_school %>% + select(date, confirm = in_bed) + +epinow_estimates <- epinow( + # cases + reported_cases = influenza_cleaned, + # delays + generation_time = generation_time_opts(generation_time_influenza), + # computation + stan = stan_opts( + cores = 4, samples = 1000, chains = 3, + control = list(adapt_delta = 0.99) + ) +) + +plot(epinow_estimates) +``` + + + + + + + + + + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + +## When to reuse? When to estimate? + +In the early stage of an outbreak, we can rely on reusing parameters for known pathogens to unknown ones, like for the [Disease X](https://en.wikipedia.org/wiki/Disease_X), a pathogen currently unknown to cause human disease and potentially cause a serious international epidemic ([WHO, 2018](https://www.who.int/activities/prioritizing-diseases-for-research-and-development-in-emergency-contexts)). + +But when data from **lines list paired with contact tracing** is available, we can estimate the key delay distributions that best fit our data. These will help us to inform, compare and update any previous estimate about questions like: + +- How long should contacts be followed? +- What is the required duration of contact tracing? +- How long should cases be isolated to reduce transmission? + +However, the methods to accurately estimate delays like the generation interval from contact tracing data involve adjusting for biases like **[censoring](../learners/reference.md#censoring)**, **[right truncation](../learners/reference.md#truncation)** and **[epidemic phase bias](../learners/reference.md#phasebias)**. [(Gostic et al., 2020)](https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1008409) + +We can identify what entries in the `{epiparameter}` library assessed for these biases in their methodology with the `method_assess` nested entry: + +```{r} +covid_serialint$method_assess +``` + +::::::::::::::::: testimonial + +### How to estimate delay distributions for Disease X? + +Refer to this excellent tutorial on estimating the serial interval and incubation period of Disease X accounting for *censoring* using Bayesian inference with packages like `{rstan}` and `{coarseDataTools}`. + +- Tutorial in English: +- Tutorial en Español: + +::::::::::::::::::::::::::::: + +:::::::::::::::::::::::::: spoiler + +### How to assess for pre-symptomatic infection? + +The lengths of the Serial interval and Incubation period determine the type of disease transmission. + +![The relationship between the incubation period and serial interval. From [Nishiura 2020](https://www.ijidonline.com/article/S1201-9712(20)30119-3/fulltext)](fig/incubation-period-serial-interval.jpg) + +Estimating the proportion of pre-symptomatic infections, or the extent to which infectiousness precedes symptom onset will determine the effectiveness of contact tracing and the feasibility of controlling an outbreak ([Fraser et al., 2004](https://www.pnas.org/doi/full/10.1073/pnas.0307506101) and [Hellewell et al., 2020](https://www.thelancet.com/article/S2214-109X(20)30074-7/fulltext)). + + + +![Parameter estimates. Plausible ranges for the key parameters R0 and θ (read the main text for sources) for four viral infections of public concern are shown as shaded regions. The size of the shaded area reflects the uncertainties in the parameter estimates. [Fraser et al., 2004](https://www.pnas.org/doi/10.1073/pnas.0307506101)](fig/reproduction-number-pre-symptomatic.png) + +Meta-analysis on the proportion of pre-symptomatic and asymptomatic transmission in SARS-CoV-2 found limitations of the evidence given high heterogeneity and high risk of selection and information bias between studies ([Buitrago-Garcia et al., 2022](https://journals.plos.org/plosmedicine/article/figure?id=10.1371/journal.pmed.1003987.g003)). This is a call to action to improve the Outbreak Analytic pipelines to use and reuse in the early phase of an outbreak. + +::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::: challenge + +### What type of transmission? + +Compare the serial interval and incubation period of Influenza and MERS: + +- What type of transmission has Influenza? +- What type of transmission has MERS? +- Do these results correlate with the available evidence? + +::::::::::::::::: hint + +For types of transmission, we refer to infections with symptomatic or pre-symptomatic transmission. + +Key functions: + +- `epidist_db()` +- `epidist$summary_stats$` + +:::::::::::::::::::::: + +::::::::::::::::: solution + +In this solution we use `purrr::pluck()` to extract elements within the `summary_stats` object which is of class `list`. + +```{r,eval=FALSE} +# pre-symptomatic transmission +epidist_db( + disease = "influenza", + epi_dist = "incubation", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("mean") + +epidist_db( + disease = "influenza", + epi_dist = "serial", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("mean") + +# symptomatic transmission +epidist_db( + disease = "mers", + epi_dist = "incubation", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("median") + +epidist_db( + disease = "mers", + epi_dist = "serial", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("mean") +``` + +```{r,eval=FALSE} +# pre-symptomatic transmission +epidist_db( + disease = "covid", + epi_dist = "incubation", + author = "Stephen", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("mean") + +epidist_db( + disease = "covid", + epi_dist = "serial", + author = "Nishiura", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("mean") + +# symptomatic transmission +epidist_db( + disease = "ebola", + epi_dist = "incubation", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("mean") + +epidist_db( + disease = "ebola", + epi_dist = "serial", + single_epidist = TRUE +) %>% + pluck("summary_stats") %>% + pluck("mean") +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::: + + + + +::::::::::::::::::::::::::::::::::::: keypoints + +- Use `{epiparameter}` to access the systematic review catalogue of epidemiological delay distributions. +- Use `epidist_db()` to select single delay distributions. +- Use `list_distributions()` for an overview of multiple delay distributions. +- Use `discretise()` to convert continuous to discrete delay distributions. +- Use `{epiparameter}` probability functions for any delay distributions. + +:::::::::::::::::::::::::::::::::::::::::::::::: + diff --git a/learners/reference.md b/learners/reference.md index 1b73c9d5..a82bc12c 100644 --- a/learners/reference.md +++ b/learners/reference.md @@ -23,6 +23,10 @@ title: 'Glossary of Terms: Epiverse-TRACE' [C++]{#cplusplus} : C++ is a high-level programming language that can be used within R to speed up sections of code. To learn more about C++ check out these [tutorials](https://cplusplus.com/doc/tutorial/) and learn more about the integration of C++ and R [here](https://www.rcpp.org/). +[Censoring]{#censoring} +: +Means that we know an event happened, but we do not know exactly when it happened. Most epidemiological data are “doubly censored” because there is uncertainty surrounding both primary and secondary event times. Not accounting for censoring can lead to biased estimates of the delay’s standard deviation ([Park et al., in progress](https://github.com/parksw3/epidist-paper)). +Different sampling approaches can generate biases given left and right censoring in the estimation of the serial interval that can propagate bias to the estimation of the [incubation period](#incubation) and generation time ([Chen et al., 2022](https://www.nature.com/articles/s41467-022-35496-8/figures/2)) ## D @@ -32,11 +36,20 @@ title: 'Glossary of Terms: Epiverse-TRACE' [Direct transmission]{#direct} : Individuals become infected via direct contact with other infected humans. Airborne transmitted infections are often modelled as directly transmitted infections as they require close contact with infected individuals for successful transmission. - +## E + +[Effective reproduction number]{#effectiverepro} +: The time-varying or effective reproduction number ($Rt$) is similar to the [Basic reproductive number](#basic) ($R0$), but $Rt$ measures the number of persons infected by infectious person when some portion of the population has already been infected. Read more about the [etymology of Reproduction number by Sharma et al, 2023](https://wwwnc.cdc.gov/eid/article/29/8/22-1445_article). ## G +[Generation time]{#generationtime} +: Time between the onset of infectiousness of an index case and its secondary case. This always needs to be positive. +The generation time distribution is commonly estimated from data on the [serial interval](#serialinterval) distribution of an infection ([Cori et al. 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). + + + [Growth rate]{#growth} : The exponential growth rate tells us how much cases are increasing or decreasing at the start of an epidemic. It gives us a measure of speed of transmission, see [Dushoff & Park, 2021](https://royalsocietypublishing.org/doi/full/10.1098/rspb.2020.1556). @@ -45,7 +58,10 @@ title: 'Glossary of Terms: Epiverse-TRACE' ## I [Incubation period]{#incubation} -: The time between becoming infected and the onset of symptoms. [More information on the incubation period](https://en.wikipedia.org/wiki/Latent_period_(epidemiology)#Incubation_period). +: The time between becoming infected and the onset of symptoms. +[More information on the incubation period](https://en.wikipedia.org/wiki/Latent_period_(epidemiology)#Incubation_period). +This can be different to the [latent period](#latent) as shown in Figure 4 from ([Xiang et al. (2021)](https://www.sciencedirect.com/science/article/pii/S2468042721000038#fig4)). +The relationship between the incubation period and the [serial interval](#serialinterval) helps to define the type of infection transmission (symptomatic or pre-symptomatic) ([Nishiura et al. (2020)](https://www.ijidonline.com/article/S1201-9712(20)30119-3/fulltext#gr2)). [Indirect transmission]{#indirect} : Indirectly transmitted infections are passed on to humans via contact with vectors, animals or contaminated environment. Vector-borne infections, zoonoses and water-borne infections are modelled as indirectly transmitted. @@ -53,6 +69,9 @@ title: 'Glossary of Terms: Epiverse-TRACE' [Initial conditions]{#initial} : In [ODEs](#ordinary), the initial conditions are the values of the state variables at the start of the model simulation (at time 0). For example, if there is one infectious individual in a population of 1000 in an Susceptible-Infectious-Recovered model, the initial conditions would be $S(0) = 999$, $I(0) = 1$, $R(0) = 0$. +[Infectious period]{#infectiousness} +: Also known as Duration of infectiousness. Time period between the onset and end of infectious [viral shedding](#viralshedding). +Viral load and detection of infectious virus are the two key parameters for estimating infectiousness ([Puhach et al., 2022](https://www.nature.com/articles/s41579-022-00822-w) and [Hakki et al, 2022](https://www.thelancet.com/journals/lanres/article/PIIS2213-2600(22)00226-0/fulltext)](fig/infectiousness-covid19.jpg)). @@ -61,7 +80,8 @@ title: 'Glossary of Terms: Epiverse-TRACE' ## L [Latent period]{#latent} -: The time between becoming infected and the onset of infectiousness. [More information on the latent period](https://en.wikipedia.org/wiki/Latent_period_(epidemiology)). +: The time between becoming infected and the onset of infectiousness. +This can be different to the [incubation period](#incubation) as shown in Figure 4 from ([Xiang et al, 2021](https://www.sciencedirect.com/science/article/pii/S2468042721000038#fig4)) ## M [Model parameters (ODEs)]{#parsode} @@ -75,23 +95,46 @@ title: 'Glossary of Terms: Epiverse-TRACE' ## O [Ordinary differential equations]{#ordinary} : Ordinary differential equations (ODEs) can be used to represent the rate of change of one variable (e.g. number of infected individuals) with respect to another (e.g. time). Check out this introduction to [ODEs](https://mathinsight.org/ordinary_differential_equation_introduction). ODEs are widely used in infectious disease modelling to model the flow of individuals between different disease states. +[Natural history of disease]{#naturalhistory} +: Refers to the development of disease from beginning to end without any treatment or intervention. In fact, given the harmfulness of an epidemic, treatment or intervention measures are inevitable. Therefore, it is difficult for the natural history of a disease to be unaffected by the various coupling factors. ([Xiang et al, 2021](https://www.sciencedirect.com/science/article/pii/S2468042721000038)) + +## O + +[Offspring distribution]{#offspringdist} +: Distribution of the number of secondary cases caused by a particular infected individual. ([Lloyd-Smith et al., 2005](https://www.nature.com/articles/nature04153), [Endo et al., 2020](https://wellcomeopenresearch.org/articles/5-67/v3)) - +## P + +[(Dynamical or Epidemic) Phase bias]{#phasebias} +: Accounts for population susceptibility at the times transmission pairs are observed. +It is a type of sampling bias. It affects backward-looking data and is related to the phase of the epidemic: during the exponential growth phase, cases that developed symptoms recently are over-represented in the observed data, while during the declining phase, these cases are underrepresented, leading to the estimation of shorter and longer delay intervals, respectively. ([Park et al., in progress](https://github.com/parksw3/epidist-paper)) - +## R + +[Reporting delay]{#reportingdelay} +: Delay or lag between the time an event occurs (e.g. symptom onset) and the time it is reported ([Lawless, 1994](https://www.jstor.org/stable/3315820)). We can quantify it by comparing the linelist with successive versions of it or up-to-date reported aggregated case counts ([Cori et al. 2017](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). ## S [State variables]{#state} : The state variables in a model represented by [ordinary differential equations](#ordinary) are the disease states that individuals can be in e.g. if individuals can be susceptible, infectious or recovered the state variables are $S$, $I$ and $R$. There is an ordinary differential equation for each state variable. +[Serial interval]{#serialinterval} +: The time delay between the onset of symptoms between a primary case and a secondary case. +This can be negative when pre-symptomatic infection occurs. +Most commonly, the serial interval distribution of an infection is used to estimate the [generation time](#generationtime) distribution ([(Cori et al., 2017)](https://royalsocietypublishing.org/doi/10.1098/rstb.2016.0371)). +The relationship between the serial interval and the [incubation period](#incubation) helps to define the type of infection transmission (symptomatic or pre-symptomatic) ([Nishiura et al. (2020)](https://www.ijidonline.com/article/S1201-9712(20)30119-3/fulltext#gr2)). + [Stochastic model]{#stochastic} : A model that includes some stochastic process resulting in variation in model simulations for the same initial conditions and parameter values. Examples include stochastic differential equations and branching process models. For more detail see [Allen (2017)](https://doi.org/10.1016/j.idm.2017.03.001). - +## T + +[(Right) Truncation]{#truncation} +: Type of sampling bias related to the data collection process. It arises because only cases that have been reported can be observed. Not accounting for right truncation during the growth phase of an epidemic can lead to underestimation of the mean delay ([Park et al., in progress](https://github.com/parksw3/epidist-paper)). @@ -100,6 +143,9 @@ title: 'Glossary of Terms: Epiverse-TRACE' [Vector-borne transmission]{#vectorborne} : Vector-borne transmission means an infection can be passed from a vector (e.g. mosquitoes) to humans. Examples of vector-borne diseases include malaria and dengue. The World Health Organization have a [Fact sheet about Vector-borne diseases](https://www.who.int/news-room/fact-sheets/detail/vector-borne-diseases) with key information and a list of them according to their vector. +[Viral shedding]{#viralshedding} +: The process of releasing a virus from a cell or body into the environment where it can infect other people. ([Cambridge Dictionary, 2023](https://dictionary.cambridge.org/us/dictionary/english/shedding)) + diff --git a/renv/profiles/lesson-requirements/renv.lock b/renv/profiles/lesson-requirements/renv.lock index b7a0a655..be78e40d 100644 --- a/renv/profiles/lesson-requirements/renv.lock +++ b/renv/profiles/lesson-requirements/renv.lock @@ -1,6 +1,6 @@ { "R": { - "Version": "4.3.2", + "Version": "4.2.2", "Repositories": [ { "Name": "carpentries", @@ -23,21 +23,21 @@ "Packages": { "BH": { "Package": "BH", - "Version": "1.81.0-1", + "Version": "1.84.0-0", "Source": "Repository", "Repository": "CRAN", - "Hash": "68122010f01c4dcfbe58ce7112f2433d" + "Hash": "a8235afbcd6316e6e91433ea47661013" }, "DBI": { "Package": "DBI", - "Version": "1.2.0", + "Version": "1.2.1", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "methods" ], - "Hash": "3e0051431dff9acfe66c23765e55c556" + "Hash": "9b4993e98e0e19da84c168460c032fef" }, "DiagrammeR": { "Package": "DiagrammeR", @@ -104,7 +104,7 @@ }, "MASS": { "Package": "MASS", - "Version": "7.3-60", + "Version": "7.3-60.0.1", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -115,11 +115,11 @@ "stats", "utils" ], - "Hash": "a56a6365b3fa73293ea8d084be0d9bb0" + "Hash": "b765b28387acc8ec9e9c1530713cb19c" }, "Matrix": { "Package": "Matrix", - "Version": "1.6-4", + "Version": "1.6-5", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -132,11 +132,11 @@ "stats", "utils" ], - "Hash": "d9c655b30a2edc6bb2244c1d1e8d549d" + "Hash": "8c7115cd3a0e048bda2a7cd110549f7a" }, "QuickJSR": { "Package": "QuickJSR", - "Version": "1.0.7", + "Version": "1.1.0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -144,7 +144,7 @@ "Rcpp", "jsonlite" ], - "Hash": "1160fb7afae2eebb5f24939590956cdf" + "Hash": "c2d96d1e0499a9f7e1e56d2d1dde0fa6" }, "R.methodsS3": { "Package": "R.methodsS3", @@ -159,7 +159,7 @@ }, "R.oo": { "Package": "R.oo", - "Version": "1.25.0", + "Version": "1.26.0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -168,11 +168,11 @@ "methods", "utils" ], - "Hash": "a0900a114f4f0194cf4aa8cd4a700681" + "Hash": "4fed809e53ddb5407b3da3d0f572e591" }, "R.utils": { "Package": "R.utils", - "Version": "2.12.2", + "Version": "2.12.3", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -183,7 +183,7 @@ "tools", "utils" ], - "Hash": "325f01db13da12c04d8f6e7be36ff514" + "Hash": "3dc2829b790254bfba21e60965787651" }, "R6": { "Package": "R6", @@ -207,14 +207,14 @@ }, "Rcpp": { "Package": "Rcpp", - "Version": "1.0.11", + "Version": "1.0.12", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "methods", "utils" ], - "Hash": "ae6cbbe1492f4de79c45fce06f967ce8" + "Hash": "5ea2700d21e038ace58269ecdbeb9ec0" }, "RcppEigen": { "Package": "RcppEigen", @@ -241,7 +241,7 @@ }, "StanHeaders": { "Package": "StanHeaders", - "Version": "2.26.28", + "Version": "2.32.5", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -249,7 +249,7 @@ "RcppEigen", "RcppParallel" ], - "Hash": "35b5aee9ec9507aca2e021997a9e557e" + "Hash": "b8d6850ef3e330bc108e712679e79443" }, "askpass": { "Package": "askpass", @@ -409,14 +409,14 @@ }, "cli": { "Package": "cli", - "Version": "3.6.2", + "Version": "3.6.1", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "utils" ], - "Hash": "1216ac65ac55ec0058a6f75d7ca0fd52" + "Hash": "89e6d8219950eac806ae0c489052048a" }, "clipr": { "Package": "clipr", @@ -509,14 +509,14 @@ }, "data.table": { "Package": "data.table", - "Version": "1.14.10", + "Version": "1.14.8", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "methods" ], - "Hash": "6ea17a32294d8ca00455825ab0cf71b9" + "Hash": "b4c06e554f33344e044ccd7fdca750a9" }, "dbplyr": { "Package": "dbplyr", @@ -653,14 +653,14 @@ }, "digest": { "Package": "digest", - "Version": "0.6.33", + "Version": "0.6.34", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "utils" ], - "Hash": "b18a9cf3c003977b0cc49d5e76ebe48d" + "Hash": "7ede2ee9ea8d3edbf1ca84c1e333ad1a" }, "distcrete": { "Package": "distcrete", @@ -768,11 +768,11 @@ "Version": "0.0.0.9000", "Source": "GitHub", "RemoteType": "github", - "RemoteHost": "api.github.com", "RemoteUsername": "epiverse-trace", "RemoteRepo": "epidemics", "RemoteRef": "main", - "RemoteSha": "5f6825d7ee9fbd162b26db95bc2f3e0d3054f452", + "RemoteSha": "14b38b8ffbda1ddfdf1d90b2d26d6570e1830d89", + "RemoteHost": "api.github.com", "Requirements": [ "BH", "Rcpp", @@ -785,7 +785,7 @@ "stats", "utils" ], - "Hash": "5abca47c2b33eb1a73a412a045823a8f" + "Hash": "8dd3418be52e67270b62ae55a5ef6b6c" }, "epiparameter": { "Package": "epiparameter", @@ -820,7 +820,7 @@ }, "fansi": { "Package": "fansi", - "Version": "1.0.6", + "Version": "1.0.5", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -828,7 +828,7 @@ "grDevices", "utils" ], - "Hash": "962174cf2aeb5b9eea581522286a911f" + "Hash": "3e8583a60163b4bc1a80016e63b9959e" }, "farver": { "Package": "farver", @@ -951,7 +951,7 @@ }, "future": { "Package": "future", - "Version": "1.33.0", + "Version": "1.33.1", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -962,11 +962,11 @@ "parallelly", "utils" ], - "Hash": "8e92c7bc53e91b9bb1faf9a6ef0e8514" + "Hash": "e57e292737f7a4efa9d8a91c5908222c" }, "future.apply": { "Package": "future.apply", - "Version": "1.11.0", + "Version": "1.11.1", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -976,7 +976,7 @@ "parallel", "utils" ], - "Hash": "ba4be138fe47eac3e16a6deaa4da106e" + "Hash": "455e00c16ec193c8edcf1b2b522b3288" }, "gargle": { "Package": "gargle", @@ -1049,14 +1049,14 @@ }, "glue": { "Package": "glue", - "Version": "1.6.2", + "Version": "1.7.0", "Source": "Repository", - "Repository": "RSPM", + "Repository": "CRAN", "Requirements": [ "R", "methods" ], - "Hash": "4f2596dfb05dac67b9dc558e5c6fba2e" + "Hash": "e0b3a53876554bd45879e596cdb10a52" }, "googledrive": { "Package": "googledrive", @@ -1273,6 +1273,16 @@ ], "Hash": "eef74fe28b747e52288ea9e1d3600034" }, + "inline": { + "Package": "inline", + "Version": "0.3.19", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "1deaf1de3eac7e1d3377954b3a283652" + }, "isoband": { "Package": "isoband", "Version": "0.2.7", @@ -1347,13 +1357,13 @@ }, "jsonlite": { "Package": "jsonlite", - "Version": "1.8.8", + "Version": "1.8.7", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "methods" ], - "Hash": "e1b9c55281c5adc4dd113652d9e26768" + "Hash": "266a20443ca13c65688b2116d5220f76" }, "knitr": { "Package": "knitr", @@ -1382,6 +1392,17 @@ ], "Hash": "b64ec208ac5bc1852b285f665d6368b3" }, + "lambda.r": { + "Package": "lambda.r", + "Version": "1.2.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "formatR" + ], + "Hash": "b1e925c4b9ffeb901bacf812cbe9a6ad" + }, "lattice": { "Package": "lattice", "Version": "0.22-5", @@ -1447,6 +1468,30 @@ ], "Hash": "b8552d117e1b808b09a832f589b79035" }, + "listenv": { + "Package": "listenv", + "Version": "0.9.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4fbd3679ec8ee169ba28d4b1ea7d0e8f" + }, + "loo": { + "Package": "loo", + "Version": "2.6.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "checkmate", + "matrixStats", + "parallel", + "stats" + ], + "Hash": "e5c8f41731502a0e98f353da23f7ca30" + }, "lubridate": { "Package": "lubridate", "Version": "1.9.3", @@ -1521,13 +1566,13 @@ }, "matrixStats": { "Package": "matrixStats", - "Version": "1.1.0", + "Version": "1.2.0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R" ], - "Hash": "68d317093459a3f0852b1dd52d9e1ea6" + "Hash": "33a3ca9e732b57244d14f5d732ffc9eb" }, "memoise": { "Package": "memoise", @@ -1670,7 +1715,7 @@ }, "patchwork": { "Package": "patchwork", - "Version": "1.1.3", + "Version": "1.2.0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -1684,7 +1729,7 @@ "stats", "utils" ], - "Hash": "c5754106c02e8e019941100c81149431" + "Hash": "9c8ab14c00ac07e9e04d1664c0b74486" }, "pillar": { "Package": "pillar", @@ -1731,6 +1776,27 @@ ], "Hash": "01f28d4278f15c76cddbea05899c5d6f" }, + "pkgload": { + "Package": "pkgload", + "Version": "1.3.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "crayon", + "desc", + "fs", + "glue", + "methods", + "pkgbuild", + "rlang", + "rprojroot", + "utils", + "withr" + ], + "Hash": "876c618df5ae610be84356d5d7a5d124" + }, "plyr": { "Package": "plyr", "Version": "1.8.9", @@ -1754,7 +1820,7 @@ }, "processx": { "Package": "processx", - "Version": "3.8.3", + "Version": "3.8.2", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -1763,7 +1829,7 @@ "ps", "utils" ], - "Hash": "82d48b1aec56084d9438dbf98087a7e9" + "Hash": "3efbd8ac1be0296a46c55387aeace0f3" }, "progress": { "Package": "progress", @@ -1793,14 +1859,14 @@ }, "ps": { "Package": "ps", - "Version": "1.7.5", + "Version": "1.7.6", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "utils" ], - "Hash": "709d852d33178db54b17c722e5b1e594" + "Hash": "dd2b9319ee0656c8acf45c7f40c59de7" }, "purrr": { "Package": "purrr", @@ -1821,7 +1887,7 @@ "Package": "ragg", "Version": "1.2.7", "Source": "Repository", - "Repository": "RSPM", + "Repository": "https://carpentries.r-universe.dev", "Requirements": [ "systemfonts", "textshaping" @@ -1840,7 +1906,7 @@ }, "readr": { "Package": "readr", - "Version": "2.1.4", + "Version": "2.1.5", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -1859,7 +1925,7 @@ "utils", "vroom" ], - "Hash": "b5047343b3825f37ad9d3b5d89aa1078" + "Hash": "9de96463d2117f6ac49980577939dfb3" }, "readxl": { "Package": "readxl", @@ -1895,7 +1961,7 @@ }, "reprex": { "Package": "reprex", - "Version": "2.0.2", + "Version": "2.1.0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -1913,18 +1979,18 @@ "utils", "withr" ], - "Hash": "d66fe009d4c20b7ab1927eb405db9ee2" + "Hash": "1425f91b4d5d9a8f25352c44a3d914ed" }, "rlang": { "Package": "rlang", - "Version": "1.1.2", + "Version": "1.1.3", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "utils" ], - "Hash": "50a6dbdc522936ca35afc5e2082ea91b" + "Hash": "42548638fae05fd9a9b5f3f437fbbbe2" }, "rmarkdown": { "Package": "rmarkdown", @@ -1952,17 +2018,17 @@ }, "rprojroot": { "Package": "rprojroot", - "Version": "2.0.3", + "Version": "2.0.4", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R" ], - "Hash": "1de7ab598047a87bba48434ba35d497d" + "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" }, "rstan": { "Package": "rstan", - "Version": "2.32.3", + "Version": "2.32.5", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -1981,7 +2047,7 @@ "pkgbuild", "stats4" ], - "Hash": "4ac5b7639d28cd4fab19baaf46f33c6a" + "Hash": "378a10b6373822761ec78021c105b059" }, "rstantools": { "Package": "rstantools", @@ -2174,16 +2240,16 @@ }, "stringi": { "Package": "stringi", - "Version": "1.8.3", + "Version": "1.8.2", "Source": "Repository", - "Repository": "RSPM", + "Repository": "CRAN", "Requirements": [ "R", "stats", "tools", "utils" ], - "Hash": "058aebddea264f4c99401515182e656a" + "Hash": "e68c45f81639001af5f1b15cd3599bbd" }, "stringr": { "Package": "stringr", @@ -2253,7 +2319,7 @@ }, "tidyr": { "Package": "tidyr", - "Version": "1.3.0", + "Version": "1.3.1", "Source": "Repository", "Repository": "CRAN", "Requirements": [ @@ -2272,7 +2338,7 @@ "utils", "vctrs" ], - "Hash": "e47debdc7ce599b070c8e78e8ac0cfcf" + "Hash": "915fb7ce036c22a6a33b5a8adb712eb1" }, "tidyselect": { "Package": "tidyselect", @@ -2332,14 +2398,14 @@ }, "timechange": { "Package": "timechange", - "Version": "0.2.0", + "Version": "0.3.0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "cpp11" ], - "Hash": "8548b44f79a35ba1791308b61e6012d7" + "Hash": "c5f3c201b931cd6474d17d8700ccb1c8" }, "sys": { "Package": "sys", @@ -2388,6 +2454,16 @@ ], "Hash": "5ac22900ae0f386e54f1c307eca7d843" }, + "truncnorm": { + "Package": "truncnorm", + "Version": "1.0-9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ef5b32c5194351ff409dfb37ca9468f1" + }, "tzdb": { "Package": "tzdb", "Version": "0.4.0", @@ -2411,13 +2487,13 @@ }, "uuid": { "Package": "uuid", - "Version": "1.1-1", + "Version": "1.2-0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R" ], - "Hash": "3d78edfb977a69fc7a0341bee25e163f" + "Hash": "303c19bfd970bece872f93a824e323d9" }, "truncnorm": { "Package": "truncnorm", @@ -2535,16 +2611,15 @@ }, "withr": { "Package": "withr", - "Version": "2.5.2", + "Version": "3.0.0", "Source": "Repository", "Repository": "CRAN", "Requirements": [ "R", "grDevices", - "graphics", - "stats" + "graphics" ], - "Hash": "4b25e70111b7d644322e9513f403a272" + "Hash": "d31b6c62c10dcf11ec530ca6b0dd5d35" }, "wpp2017": { "Package": "wpp2017", @@ -2606,7 +2681,7 @@ "Package": "xml2", "Version": "1.3.6", "Source": "Repository", - "Repository": "RSPM", + "Repository": "https://carpentries.r-universe.dev", "Requirements": [ "R", "cli", @@ -2628,10 +2703,10 @@ }, "yaml": { "Package": "yaml", - "Version": "2.3.8", + "Version": "2.3.7", "Source": "Repository", "Repository": "CRAN", - "Hash": "29240487a071f535f5e5d5a323b7afbd" + "Hash": "0d0056cc5383fbc240ccd0cb584bf436" } } }