From 338d817d82392b935c59bd3c197b664c2071e42b Mon Sep 17 00:00:00 2001 From: Sam Abbott Date: Wed, 3 Jul 2024 13:38:38 +0100 Subject: [PATCH 1/5] Reorganise documentation (#320) * reorg and fix linting in getting started with Julia * more rearrangement * clean up API exposure * final reorg * fix doc issue * catch missing , * add build instructions for subdirectories manually * change folder structuree * ET find home * make ET's life easier * experiment with paths * ET continues to look for home * revert build * fix replication typo * revert build * include submodules in make.jl * fix duplication of base docs * fix EpiInference typo * improve reference structure of docs and add index pages * debug doc builds * updatre internals * fix path to changelog * rename tutorials to explainners and flesh out proposed tutorials * turn pluto building back on --- EpiAware/README.md | 88 +------------------ EpiAware/docs/make.jl | 14 ++- EpiAware/docs/pages.jl | 70 +++++++++++---- .../docs/src/{ => developer}/checklist.md | 0 .../src/{man => developer}/contributing.md | 10 +-- EpiAware/docs/src/developer/index.md | 3 + .../getting-started/explainers/inference.md | 1 + .../getting-started/explainers/interfaces.md | 25 ++++++ .../src/getting-started/explainers/intro.md | 68 ++++++++++++++ .../explainers/julia.md} | 42 +++++---- .../explainers/latent-models.md | 1 + .../explainers/modelling-infections.md | 1 + .../explainers/observation-models.md | 1 + EpiAware/docs/src/getting-started/faq.md | 11 +++ EpiAware/docs/src/getting-started/index.md | 3 + .../docs/src/getting-started/installation.md | 7 ++ .../docs/src/getting-started/quickstart.md | 3 + .../multiple-infection-processes.md} | 0 .../tutorials/multiple-observation-models.md | 0 .../getting-started/tutorials/nowcasting.md | 0 .../tutorials/partial-pooling.md | 0 .../tutorials/simple-renewal-with-delays.md | 0 EpiAware/docs/src/index.md | 41 ++------- EpiAware/docs/src/lib/EpiAwareBase/index.md | 9 ++ .../docs/src/lib/EpiAwareBase/internals.md | 23 +++++ EpiAware/docs/src/lib/EpiAwareBase/public.md | 25 ++++++ EpiAware/docs/src/lib/EpiAwareUtils/index.md | 9 ++ .../docs/src/lib/EpiAwareUtils/internals.md | 23 +++++ EpiAware/docs/src/lib/EpiAwareUtils/public.md | 25 ++++++ EpiAware/docs/src/lib/EpiInfModels/index.md | 9 ++ .../docs/src/lib/EpiInfModels/internals.md | 23 +++++ EpiAware/docs/src/lib/EpiInfModels/public.md | 25 ++++++ EpiAware/docs/src/lib/EpiInference/index.md | 9 ++ .../docs/src/lib/EpiInference/internals.md | 23 +++++ EpiAware/docs/src/lib/EpiInference/public.md | 25 ++++++ .../docs/src/lib/EpiLatentModels/index.md | 9 ++ .../docs/src/lib/EpiLatentModels/internals.md | 23 +++++ .../docs/src/lib/EpiLatentModels/public.md | 25 ++++++ EpiAware/docs/src/lib/EpiObsModels/index.md | 9 ++ .../docs/src/lib/EpiObsModels/internals.md | 23 +++++ EpiAware/docs/src/lib/EpiObsModels/public.md | 25 ++++++ EpiAware/docs/src/lib/index.md | 3 + EpiAware/docs/src/lib/internals.md | 2 +- EpiAware/docs/src/overview.md | 33 +++++++ EpiAware/docs/src/showcase/index.md | 3 + .../docs/src/showcase/replications/.gitignore | 1 + .../replications/mishra-2020}/get_data.R | 0 .../replications/mishra-2020/index.jl} | 4 +- .../mishra-2020}/south_korea_data.csv2 | 0 EpiAware/src/EpiAware.jl | 33 ------- 50 files changed, 613 insertions(+), 197 deletions(-) rename EpiAware/docs/src/{ => developer}/checklist.md (100%) rename EpiAware/docs/src/{man => developer}/contributing.md (62%) create mode 100644 EpiAware/docs/src/developer/index.md create mode 100644 EpiAware/docs/src/getting-started/explainers/inference.md create mode 100644 EpiAware/docs/src/getting-started/explainers/interfaces.md create mode 100644 EpiAware/docs/src/getting-started/explainers/intro.md rename EpiAware/docs/src/{man/getting-started-julia.md => getting-started/explainers/julia.md} (86%) create mode 100644 EpiAware/docs/src/getting-started/explainers/latent-models.md create mode 100644 EpiAware/docs/src/getting-started/explainers/modelling-infections.md create mode 100644 EpiAware/docs/src/getting-started/explainers/observation-models.md create mode 100644 EpiAware/docs/src/getting-started/faq.md create mode 100644 EpiAware/docs/src/getting-started/index.md create mode 100644 EpiAware/docs/src/getting-started/installation.md create mode 100644 EpiAware/docs/src/getting-started/quickstart.md rename EpiAware/docs/src/{man/guide.md => getting-started/tutorials/multiple-infection-processes.md} (100%) create mode 100644 EpiAware/docs/src/getting-started/tutorials/multiple-observation-models.md create mode 100644 EpiAware/docs/src/getting-started/tutorials/nowcasting.md create mode 100644 EpiAware/docs/src/getting-started/tutorials/partial-pooling.md create mode 100644 EpiAware/docs/src/getting-started/tutorials/simple-renewal-with-delays.md create mode 100644 EpiAware/docs/src/lib/EpiAwareBase/index.md create mode 100644 EpiAware/docs/src/lib/EpiAwareBase/internals.md create mode 100644 EpiAware/docs/src/lib/EpiAwareBase/public.md create mode 100644 EpiAware/docs/src/lib/EpiAwareUtils/index.md create mode 100644 EpiAware/docs/src/lib/EpiAwareUtils/internals.md create mode 100644 EpiAware/docs/src/lib/EpiAwareUtils/public.md create mode 100644 EpiAware/docs/src/lib/EpiInfModels/index.md create mode 100644 EpiAware/docs/src/lib/EpiInfModels/internals.md create mode 100644 EpiAware/docs/src/lib/EpiInfModels/public.md create mode 100644 EpiAware/docs/src/lib/EpiInference/index.md create mode 100644 EpiAware/docs/src/lib/EpiInference/internals.md create mode 100644 EpiAware/docs/src/lib/EpiInference/public.md create mode 100644 EpiAware/docs/src/lib/EpiLatentModels/index.md create mode 100644 EpiAware/docs/src/lib/EpiLatentModels/internals.md create mode 100644 EpiAware/docs/src/lib/EpiLatentModels/public.md create mode 100644 EpiAware/docs/src/lib/EpiObsModels/index.md create mode 100644 EpiAware/docs/src/lib/EpiObsModels/internals.md create mode 100644 EpiAware/docs/src/lib/EpiObsModels/public.md create mode 100644 EpiAware/docs/src/lib/index.md create mode 100644 EpiAware/docs/src/overview.md create mode 100644 EpiAware/docs/src/showcase/index.md create mode 100644 EpiAware/docs/src/showcase/replications/.gitignore rename EpiAware/docs/src/{examples => showcase/replications/mishra-2020}/get_data.R (100%) rename EpiAware/docs/src/{examples/getting_started.jl => showcase/replications/mishra-2020/index.jl} (99%) rename EpiAware/docs/src/{examples => showcase/replications/mishra-2020}/south_korea_data.csv2 (100%) diff --git a/EpiAware/README.md b/EpiAware/README.md index e0550a7b0..08c014c0a 100644 --- a/EpiAware/README.md +++ b/EpiAware/README.md @@ -5,90 +5,8 @@ [![Test EpiAware](https://github.com/CDCgov/Rt-without-renewal/actions/workflows/test-EpiAware.yaml/badge.svg)](https://github.com/CDCgov/Rt-without-renewal/actions/workflows/test-EpiAware.yaml) [![codecov](https://codecov.io/gh/CDCgov/Rt-without-renewal/graph/badge.svg?token=IX4GIA8F0H)](https://codecov.io/gh/CDCgov/Rt-without-renewal) -A `Julia` package for flexible and composable modeling and inference of the effective reproduction number (Rt) and other situational awareness signals in the presence of different latent generative processes and observation models. +*An infectious disease situational awareness modelling toolkit for Julia.* -## Installation instruction +**Websites**: [Organization Website](https://cdcgov.github.io/Rt-without-renewal/dev/) | [Documentation](https://cdcgov.github.io/Rt-without-renewal/dev/) -Eventually, `EpiAware` is likely to be added to the Julia registry. Until then, you can install it from the `/EpiAware` sub-directory of this repository by running the following command in the Julia REPL: - -```julia -using Pkg; Pkg.add(url="https://github.com/CDCgov/Rt-without-renewal", subdir="EpiAware") -``` - -## Model Diagram - -- Solid lines indicate implemented features/analysis. -- Dashed lines indicate planned features/analysis. - -## Current `EpiAware` model diagram -```mermaid -flowchart LR - -A["Underlying GI -Bijector"] - -EpiModel["AbstractTuringEpiModel ----------------------- -Choice of target -for latent process: - -DirectInfections - ExpGrowthRate - Renewal"] - -InitModel["Priors for -initial scale of incidence"] - -DataW[Data wrangling and QC] - - -ObsData["Observational Data ---------------------- -Obs. cases y_t"] - -LatentProcPriors["Latent process priors"] - -LatentProc["AbstractTuringLatentModel ---------------------- -RandomWalk"] - -ObsModelPriors["Observation model priors -choice of delayed obs. model"] - -ObsModel["AbstractObservationModel ---------------------- -DelayObservations"] - -E["Turing model constructor ---------------------- -generate_epiaware"] - -G[Posterior draws] -H[Posterior checking] -I[Post-processing] - - - -A --> EpiData -EpiData --> EpiModel -InitModel --> EpiModel -EpiModel -->E -ObsData-->E -DataW-.->ObsData -LatentProcPriors-->LatentProc -LatentProc-->E -ObsModelPriors-->ObsModel -ObsModel-->E - - -E-->|sample...NUTS...| G -G-.->H -H-.->I -``` - -## Pluto scripts - -We use [`Pluto.jl`](https://plutojl.org/) scripts as part of our documentation and testing. The scripts are located in `docs/src/examples` and can be run using the `Pluto.jl` package. We recommend using the version of `Pluto` that is pinned in the `Project.toml` file defining the documentation environment. An entry point to running or developing this documentation is the `docs/pluto-scripts.sh` bash shell script. Run this from the root directory of this repository. - -## Opinionated guide to using Julia for project development -Some user and potential contributors may not be familiar with using Julia for, or part of, project development. In documentation we give our opinions on how to use Julia for project development focussing on Julia version control with the command line tool `juliaup`, typical patterns for using stacked environments and useful settings for development using the Julia extension of VS-Code as an interactive development environment (IDE) for Julia project. Please find the documentation [here](https://cdcgov.github.io/Rt-without-renewal/dev/man/getting-started-julia/). +EpiAware Organization Stats: ![EpiAware Stars](https://img.shields.io/github/stars/EpiAware?style=social) diff --git a/EpiAware/docs/make.jl b/EpiAware/docs/make.jl index b51b4e872..7e1f3d5ef 100644 --- a/EpiAware/docs/make.jl +++ b/EpiAware/docs/make.jl @@ -1,5 +1,11 @@ using Documenter using EpiAware +using EpiAware.EpiAwareBase +using EpiAware.EpiAwareUtils +using EpiAware.EpiInference +using EpiAware.EpiInfModels +using EpiAware.EpiLatentModels +using EpiAware.EpiObsModels using Pluto: Configuration.CompilerOptions using PlutoStaticHTML @@ -7,13 +13,17 @@ include("changelog.jl") include("pages.jl") include("build.jl") -build("examples") +build("getting-started") +build("getting-started/tutorials") +build("showcase/replications/mishra-2020") makedocs(; sitename = "EpiAware.jl", authors = "Samuel Brand, Zachary Susswein, Sam Abbott, and contributors", clean = true, doctest = true, linkcheck = true, warnonly = [:docs_block, :missing_docs, :linkcheck, :autodocs_block], - modules = [EpiAware], + modules = [ + EpiAware, EpiAware.EpiAwareBase, EpiAware.EpiAwareUtils, EpiAware.EpiInference, + EpiAware.EpiInfModels, EpiAware.EpiLatentModels, EpiAware.EpiObsModels], pages = pages, format = Documenter.HTML( prettyurls = get(ENV, "CI", nothing) == "true", diff --git a/EpiAware/docs/pages.jl b/EpiAware/docs/pages.jl index 848ac79eb..0ebf47b97 100644 --- a/EpiAware/docs/pages.jl +++ b/EpiAware/docs/pages.jl @@ -1,18 +1,58 @@ -pages = [ - "EpiAware.jl: Real-time epidemic monitoring" => "index.md", - "Manual" => Any[ - "Getting Started with using Julia in Projects" => "man/getting-started-julia.md", - "Examples" => [ - "Getting started" => "examples/getting_started.md" - ] - ], - "Reference" => Any[ - "Public API" => "lib/public.md" - ], - "Developers" => [ - "Contributing" => "man/contributing.md", - "Release checklist" => "checklist.md", - "Internals" => "lib/internals.md" +getting_started_pages = Any[ + "Installation" => "getting-started/installation.md", + "Quickstart" => "getting-started/quickstart.md", + "Frequently asked questions" => "getting-started/faq.md", + "Explainers" => [ + "Working with Julia" => "getting-started/explainers/julia.md", + "Introduction to EpiAware" => "getting-started/explainers/intro.md", + "Modelling infections" => "getting-started/explainers/modelling-infections.md", + "Inference" => "getting-started/explainers/inference.md", + "Latent models" => "getting-started/explainers/latent-models.md", + "Observation models" => "getting-started/explainers/observation-models.md" ], + "Tutorials" => [ + "Simple renewal with delays" => "getting-started/tutorials/simple-renewal-with-delays.md", + "Nowcasting" => "getting-started/tutorials/nowcasting.md", + "Multiple observation models" => "getting-started/tutorials/multiple-observation-models.md", + "Multiple infection processes" => "getting-started/tutorials/multiple-infection-processes.md", + "Partial pooling" => "getting-started/tutorials/partial-pooling.md" + ] +] + +showcase_pages = [ + "Replication" => [ + "On the derivation of the renewal equation from an age-dependent branching process: an epidemic modelling perspective" => "showcase/replications/mishra-2020/index.md" +] +] + +what_is_pages = [ + "Overview" => "overview.md" +] + +module_pages = Any[ + "EpiAwareBase" => "lib/EpiAwareBase/index.md", + "EpiAwareUtils" => "lib/EpiAwareUtils/index.md", + "EpiInference" => "lib/EpiInference/index.md", + "EpiInfModels" => "lib/EpiInfModels/index.md", + "EpiLatentModels" => "lib/EpiLatentModels/index.md", + "EpiObsModels" => "lib/EpiObsModels/index.md", + "EpiAware" => [ + "Public API" => "lib/public.md", + "Internal API" => "lib/internals.md" + ] +] + +developer_pages = [ + "Contributing" => "developer/contributing.md", + "Release checklist" => "developer/checklist.md" +] + +pages = [ + "EpiAware.jl: Real-time infectious disease monitoring" => "index.md", + "Getting started" => getting_started_pages, + "Showcase" => showcase_pages, + "What is EpiAware?" => what_is_pages, + "Modules" => module_pages, + "Developers" => developer_pages, "release-notes.md" ] diff --git a/EpiAware/docs/src/checklist.md b/EpiAware/docs/src/developer/checklist.md similarity index 100% rename from EpiAware/docs/src/checklist.md rename to EpiAware/docs/src/developer/checklist.md diff --git a/EpiAware/docs/src/man/contributing.md b/EpiAware/docs/src/developer/contributing.md similarity index 62% rename from EpiAware/docs/src/man/contributing.md rename to EpiAware/docs/src/developer/contributing.md index d54426632..342bd419b 100644 --- a/EpiAware/docs/src/man/contributing.md +++ b/EpiAware/docs/src/developer/contributing.md @@ -16,11 +16,11 @@ Feel free to nominate commits that should be backported by opening an issue. Req ### `release-*` branches - * Each new minor version `x.y.0` gets a branch called `release-x.y` (a [protected branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches)). - * New versions are usually tagged only from the `release-x.y` branches. - * For patch releases, changes get backported to the `release-x.y` branch via a single PR with the standard name "Backports for x.y.z" and label ["Type: Backport"](https://github.com/JuliaDocs/Documenter.jl/pulls?q=label%3A%22Type%3A+Backport%22). The PR message links to all the PRs that are providing commits to the backport. The PR gets merged as a merge commit (i.e. not squashed). - * The old `release-*` branches may be removed once they have outlived their usefulness. - * Patch version [milestones](https://github.com/CDCgov/Rt-without-renewal/milestones) are used to keep track of which PRs get backported etc. +* Each new minor version `x.y.0` gets a branch called `release-x.y` (a [protected branch](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches)). +* New versions are usually tagged only from the `release-x.y` branches. +* For patch releases, changes get backported to the `release-x.y` branch via a single PR with the standard name "Backports for x.y.z" and label ["Type: Backport"](https://github.com/JuliaDocs/Documenter.jl/pulls?q=label%3A%22Type%3A+Backport%22). The PR message links to all the PRs that are providing commits to the backport. The PR gets merged as a merge commit (i.e. not squashed). +* The old `release-*` branches may be removed once they have outlived their usefulness. +* Patch version [milestones](https://github.com/CDCgov/Rt-without-renewal/milestones) are used to keep track of which PRs get backported etc. ## Style Guide diff --git a/EpiAware/docs/src/developer/index.md b/EpiAware/docs/src/developer/index.md new file mode 100644 index 000000000..41ebf9d6d --- /dev/null +++ b/EpiAware/docs/src/developer/index.md @@ -0,0 +1,3 @@ +# [Developer documentation](@id developer) + +Welcome to the `EpiAware` developer documentation! This section is designed to help you get started with developing the package. diff --git a/EpiAware/docs/src/getting-started/explainers/inference.md b/EpiAware/docs/src/getting-started/explainers/inference.md new file mode 100644 index 000000000..405b720a7 --- /dev/null +++ b/EpiAware/docs/src/getting-started/explainers/inference.md @@ -0,0 +1 @@ +# Inference diff --git a/EpiAware/docs/src/getting-started/explainers/interfaces.md b/EpiAware/docs/src/getting-started/explainers/interfaces.md new file mode 100644 index 000000000..9501721ce --- /dev/null +++ b/EpiAware/docs/src/getting-started/explainers/interfaces.md @@ -0,0 +1,25 @@ +# Interfaces + +We support two primary workflows for using the package: + +- `EpiProblem`: A high-level interface for defining and fitting models to data. This is the recommended way to use the package. +- `Turing` interface: A lower-level interface for defining and fitting models to data. This is the more flexible way to use the package and may also be more familiar to users of `Turing.jl`. + +See the getting started section for tutorials on each of these workflows. + +## EpiProblem + +Each module of the overall epidemiological model we are interested in is a `Turing` `Model` in its own right. In this section, we compose the individual models into the full epidemiological model using the `EpiProblem` struct. + +The constructor for an `EpiProblem` requires: + +- An `epi_model`. +- A `latent_model`. +- An `observation_model`. +- A `tspan`. + +The `tspan` set the range of the time index for the models. + +## Turing interface + +The `Turing` interface is a lower-level interface for defining and fitting models to data. This is the more flexible way to use the package and may also be more familiar to users of `Turing.jl`. diff --git a/EpiAware/docs/src/getting-started/explainers/intro.md b/EpiAware/docs/src/getting-started/explainers/intro.md new file mode 100644 index 000000000..5f6d32c6e --- /dev/null +++ b/EpiAware/docs/src/getting-started/explainers/intro.md @@ -0,0 +1,68 @@ +# Introduction + +The diagram below shows the relationship between the modules in the package for a typical workflow. + +```mermaid +flowchart LR + +A["Underlying GI +Bijector"] + +EpiModel["AbstractTuringEpiModel +---------------------- +Choice of target +for latent process: + +DirectInfections + ExpGrowthRate + Renewal"] + +InitModel["Priors for +initial scale of incidence"] + +DataW[Data wrangling and QC] + + +ObsData["Observational Data +--------------------- +Obs. cases y_t"] + +LatentProcPriors["Latent process priors"] + +LatentProc["AbstractTuringLatentModel +--------------------- +RandomWalk"] + +ObsModelPriors["Observation model priors +choice of delayed obs. model"] + +ObsModel["AbstractObservationModel +--------------------- +DelayObservations"] + +E["Turing model constructor +--------------------- +generate_epiaware"] + +G[Posterior draws] +H[Posterior checking] +I[Post-processing] + + + +A --> EpiData +EpiData --> EpiModel +InitModel --> EpiModel +EpiModel -->E +ObsData-->E +DataW-.->ObsData +LatentProcPriors-->LatentProc +LatentProc-->E +ObsModelPriors-->ObsModel +ObsModel-->E + + +E-->|sample...NUTS...| G +G-->H +H-->I +``` diff --git a/EpiAware/docs/src/man/getting-started-julia.md b/EpiAware/docs/src/getting-started/explainers/julia.md similarity index 86% rename from EpiAware/docs/src/man/getting-started-julia.md rename to EpiAware/docs/src/getting-started/explainers/julia.md index 246bb5eb7..9304477aa 100644 --- a/EpiAware/docs/src/man/getting-started-julia.md +++ b/EpiAware/docs/src/getting-started/explainers/julia.md @@ -1,19 +1,17 @@ -# Getting Started with using Julia in Projects +# Julia for EpiAware -Julia is a programming language aimed at technical computing. This guide is aimed at helping you set up Julia on your system according to our recommended best practices. +Julia is a programming language aimed at technical computing. This guide is aimed at helping you set up Julia on your system and pointing towards resources for learning more. -If you are familar with other languages with tooling for technical computing (e.g. `R`, `MATLAB`, `Python`) these [noteworthy differences](https://docs.julialang.org/en/v1/manual/noteworthy-differences/) may be useful. +> [!NOTE] +> If you are familar with other languages with tooling for technical computing (e.g. `R`, `MATLAB`, `Python`) these [noteworthy differences](https://docs.julialang.org/en/v1/manual/noteworthy-differences/) may be useful. -**Table of Contents** -- [Julia Installation with Juliaup](#julia-installation-with-juliaup) -- [Basic usage of Juliaup](#basic-usage-of-juliaup) -- [Basic usage for Julia environments](#basic-usage-for-julia-environments) -- [Using the Julia REPL in projects](#using-the-julia-repl-in-projects) -- [Recommended packages for the "global" Julia version environment](#recommended-packages-for-the-global-julia-version-environment) -- [Developing a Julia project from VS-Code](#developing-a-julia-project-from-vs-code) -- [Literate programming with Julia](#literate-programming-with-julia) +```@contents +Pages = ["getting-started/tutorials/julia.md"] +Depth = 3 +``` ## What this guide is and isn't + This isn't a guide to learning the Julia programming language. Instead we providing an opinionated guide to setting up your system to use Julia effectively in project workflows aimed at people with familiarity with Julia but have maybe only developed projects in other languages (e.g. `R`, `MATLAB`, `Python`). If you want to learn more about the Julia programming language, we recommend the following resources: @@ -30,12 +28,11 @@ If you want to learn more about the Julia programming language, we recommend the 1. **Download Juliaup**: This is a cross-platform installer/updater for the Julia programming language. It simplifies the process of installing and managing Julia versions. Go to the [Juliaup GitHub repository](https://github.com/JuliaLang/juliaup) or to the [official Julia website](https://julialang.org/downloads/) for installation instructions. 2. **Verify Installation**: Open a terminal (or Command Prompt on Windows) and type `julia` to start the Julia REPL (Read-Eval-Print Loop). You should see a Julia prompt `julia>`. - ## Basic usage of Juliaup Juliaup is a tool for managing Julia installations on your system. It allows you to install, update, and switch between different versions of Julia. Details are available at the [Juliaup GitHub repository](https://github.com/JuliaLang/juliaup), but here are some examples of common commands: -### Add a specfic version of Julia +### Add a specific version of Julia Juliaup default installs the latest release version of Julia. To install a specific version, use the `add` command followed by the version number. For example, to install Julia version 1.9.3, use the following command: @@ -62,13 +59,14 @@ To see a list of all the versions of Julia installed on your system, use the fol ``` ### Update Julia (all versions installed) + This will update all versions of Julia installed on your system to their latest release versions. ```bash % juliaup update ``` -## Basic usage for Julia environments +## Usage of Julia environments The [_environment_](https://docs.julialang.org/en/v1/manual/code-loading/#Environments-1) of a Julia project determines which packages, and their version, are available to the project. This is useful when you want to ensure that a project uses a specific version of a package, or when you want to isolate the project from other projects on your system. As per other languages, Julia environments are useful for managing dependencies and ensuring reproducibility. @@ -146,7 +144,6 @@ In our view these packages are useful for your Julia version environment, e.g. ` - `TestEnv`: For easy use of test environments for package testing. - `UnicodePlots`: For simple and quick plotting in the REPL without needing to install a fully featured plotting package. - ### `startup.jl` recommendation `Revise` and `Term` useful to have available in every Julia session. It is convenient to have these packages loaded automatically when you start a Julia session by adding a `startup.jl` file. This file should be located in the `~/.julia/config` directory. Here is an example of a `startup.jl` file that loads the `Revise` and `Term`: @@ -171,12 +168,14 @@ end ``` -## Developing a Julia project from VS-Code +## Developing a EpiAware-project from VS-Code ### Julia extension for VS-Code + Visual Studio Code (VS-Code) is a popular code editor that supports Julia development. The [Julia extension for VS-Code](https://www.julia-vscode.org/) provides an interactive development environment that will be familiar to users of other scientific IDEs (e.g. developing `R` projects in RStudio or using the `MATLAB` application). ### Features of the Julia extension for VS-Code + It is worth reading both the [VS-Code documentation](https://code.visualstudio.com/docs/languages/julia) and the [Julia extension documentation](https://www.julia-vscode.org/docs/stable/), however, here are some highlights: - **Julia REPL**: The Julia extension provides an integrated REPL in the `TERMINAL` pane that allows you to interact with Julia code directly from the editor. For example, you can run code snippets from highlighting or code blocks defined by `##` comments in the scripts. @@ -216,12 +215,11 @@ These settings set basic code formatting and whitespace settings for Julia files The `VS-Code` command `Julia: Start REPL` will start a REPL in `TERMINAL` tab in the editor with the environment set to the project directory and the `Testing` tab will detect the defined tests for the project. +## Literate programming with Julia in EpiAware -## Literate programming with Julia - -Its common to develop technical computing projects using a literate programming style, where code and documentation are interwoven. Julia supports this style of programming through a number of packages: +Its common to develop technical computing projects using a literate programming style, where code and documentation are interwoven. Julia supports this style of programming through a number of packages. In `EpiAware` we recommend the following: - `Pluto`: A native Julia notebook for interactive development. `Pluto` notebooks are reactive, meaning that the output of all cells are updated as input changes. Installation instructions are available [here](https://github.com/fonsp/Pluto.jl). Pluto notebook files have the extension `.jl` and can be run as scripts. -- `IJulia`: A Julia kernel for Jupyter notebooks. Installation instructions are available [here](https://github.com/JuliaLang/IJulia.jl). A useful package for integrating `.ipynb` into a workflow is [`NBInclude.jl`](https://github.com/JuliaInterop/NBInclude.jl) which allows you to include the variables/output of a `.ipynb` notebook into a Julia script. -- `Quarto`: [A multi-language scientific publishing system](https://quarto.org/). Quarto interfaces with Julia via `IJulia` kernel for jupyter. Julia code blocks are executed and the output is included with the markdown output in document generation. Installation instructions are available [here](https://quarto.org/docs/get-started/index.html). -- `Weave`: A package for literate programming in Julia. `Weave` allows you to write a `.jmd` file that contains both markdown and Julia code. The Julia code is executed and the output is included in the markdown output. In our view, `Weave` is superceded by Quarto usage. +- `Quarto`: A literate programming tool that allows you to write documents in markdown with embedded Julia code. Installation instructions are available [here](https://quarto.org/). Quarto files have the extension `.qmd`. + +We use `Pluto` for interactive development and `Quarto` for generating reports and academic articles. Both tools are useful for developing reproducible workflows. diff --git a/EpiAware/docs/src/getting-started/explainers/latent-models.md b/EpiAware/docs/src/getting-started/explainers/latent-models.md new file mode 100644 index 000000000..72647b74e --- /dev/null +++ b/EpiAware/docs/src/getting-started/explainers/latent-models.md @@ -0,0 +1 @@ +# Latent models diff --git a/EpiAware/docs/src/getting-started/explainers/modelling-infections.md b/EpiAware/docs/src/getting-started/explainers/modelling-infections.md new file mode 100644 index 000000000..8270824ee --- /dev/null +++ b/EpiAware/docs/src/getting-started/explainers/modelling-infections.md @@ -0,0 +1 @@ +# Modelling infections diff --git a/EpiAware/docs/src/getting-started/explainers/observation-models.md b/EpiAware/docs/src/getting-started/explainers/observation-models.md new file mode 100644 index 000000000..b1e5da1c4 --- /dev/null +++ b/EpiAware/docs/src/getting-started/explainers/observation-models.md @@ -0,0 +1 @@ +# Observation models diff --git a/EpiAware/docs/src/getting-started/faq.md b/EpiAware/docs/src/getting-started/faq.md new file mode 100644 index 000000000..767a6181f --- /dev/null +++ b/EpiAware/docs/src/getting-started/faq.md @@ -0,0 +1,11 @@ +# Frequently asked questions + +This page contains a list of frequently asked questions about the EpiAware package. If you have a question that is not answered here, please open a discussion on the GitHub repository. + +```@contents +Pages = ["lib/getting-started/faq.md"] +``` + +## Pluto scripts + +We use [`Pluto.jl`](https://plutojl.org/) scripts as part of our documentation and testing. The scripts are located in `docs/src/examples` and can be run using the `Pluto.jl` package. We recommend using the version of `Pluto` that is pinned in the `Project.toml` file defining the documentation environment. An entry point to running or developing this documentation is the `docs/pluto-scripts.sh` bash shell script. Run this from the root directory of this repository. diff --git a/EpiAware/docs/src/getting-started/index.md b/EpiAware/docs/src/getting-started/index.md new file mode 100644 index 000000000..25e8082a8 --- /dev/null +++ b/EpiAware/docs/src/getting-started/index.md @@ -0,0 +1,3 @@ +# [Getting started](@id getting-started) + +Welcome to the `EpiAware` documentation! This section is designed to help you get started with the package. diff --git a/EpiAware/docs/src/getting-started/installation.md b/EpiAware/docs/src/getting-started/installation.md new file mode 100644 index 000000000..5fe4f6dfa --- /dev/null +++ b/EpiAware/docs/src/getting-started/installation.md @@ -0,0 +1,7 @@ +# Installation + +Eventually, `EpiAware` is likely to be added to the Julia registry. Until then, you can install it from the `/EpiAware` sub-directory of this repository by running the following command in the Julia REPL: + +```julia +using Pkg; Pkg.add(url="https://github.com/CDCgov/Rt-without-renewal", subdir="EpiAware") +``` diff --git a/EpiAware/docs/src/getting-started/quickstart.md b/EpiAware/docs/src/getting-started/quickstart.md new file mode 100644 index 000000000..7de815ab3 --- /dev/null +++ b/EpiAware/docs/src/getting-started/quickstart.md @@ -0,0 +1,3 @@ +# Quickstart + +Get up and running with EpiAware in just a few minutes using this quickstart guide. diff --git a/EpiAware/docs/src/man/guide.md b/EpiAware/docs/src/getting-started/tutorials/multiple-infection-processes.md similarity index 100% rename from EpiAware/docs/src/man/guide.md rename to EpiAware/docs/src/getting-started/tutorials/multiple-infection-processes.md diff --git a/EpiAware/docs/src/getting-started/tutorials/multiple-observation-models.md b/EpiAware/docs/src/getting-started/tutorials/multiple-observation-models.md new file mode 100644 index 000000000..e69de29bb diff --git a/EpiAware/docs/src/getting-started/tutorials/nowcasting.md b/EpiAware/docs/src/getting-started/tutorials/nowcasting.md new file mode 100644 index 000000000..e69de29bb diff --git a/EpiAware/docs/src/getting-started/tutorials/partial-pooling.md b/EpiAware/docs/src/getting-started/tutorials/partial-pooling.md new file mode 100644 index 000000000..e69de29bb diff --git a/EpiAware/docs/src/getting-started/tutorials/simple-renewal-with-delays.md b/EpiAware/docs/src/getting-started/tutorials/simple-renewal-with-delays.md new file mode 100644 index 000000000..e69de29bb diff --git a/EpiAware/docs/src/index.md b/EpiAware/docs/src/index.md index 0e6373eae..37a399f6c 100644 --- a/EpiAware/docs/src/index.md +++ b/EpiAware/docs/src/index.md @@ -2,35 +2,12 @@ *Infectious disease situational awareness modelling toolkit for Julia.* -A package for building and fitting situational awareness models for infectious diseases. The package is designed to be flexible and extensible, and to provide a consistent interface for fitting and simulating models. - -## Package Features - -- **Flexible**: The package is designed to be flexible and extensible, and to provide a consistent interface for fitting and simulating models. -- **Modular**: The package is designed to be modular, with a clear separation between the model and the data. -- **Extensible**: The package is designed to be extensible, with a clear separation between the model and the data. -- **Consistent**: The package is designed to provide a consistent interface for fitting and simulating models. -- **Efficient**: The package is designed to be efficient, with a clear separation between the model and the data. - -See the [Index](@ref main-index) for the complete list of documented functions and types. - -## Manual Outline - -```@contents -Pages = [ - "man/getting-started-julia.md", -] -Depth = 1 -``` - -## Library Outline - -```@contents -Pages = ["lib/public.md", "lib/internals.md"] -``` - -### [Index](@id main-index) - -```@index -Pages = ["lib/public.md"] -``` +## Where to start + +- Want to get started running code? Check out the [Getting Started Tutorials](@ref getting-started). +- What is `EpiAware`? Check out our [Overview](@ref overview). +- Want to see some end-to-end examples? Check out our [`EpiAware` showcase](@ref showcase). +- Want to understand the API? Check out our [API Reference](@ref api-reference). +- Want to chat with someone about `EpiAware`? Post on our [GitHub Discussions](https://github.com/CDCgov/Rt-without-renewal/discussions). +- Want to contribute to `EpiAware`? Check out our [Developer documentation](@ref developer). +- Want to see our code? Check out our [GitHub Repository](https://github.com/CDCgov/Rt-without-renewal/tree/main/EpiAware). diff --git a/EpiAware/docs/src/lib/EpiAwareBase/index.md b/EpiAware/docs/src/lib/EpiAwareBase/index.md new file mode 100644 index 000000000..38647b4c4 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiAwareBase/index.md @@ -0,0 +1,9 @@ +# EpiAwareBase.jl + +This package provides the core functionality for the EpiAware ecosystem. It is a dependency of all other EpiAware packages. + +## API + +```@contents +Pages = ["lib/EpiAwareBase/public.md", "lib/EpiAwareBase/internals.md"] +``` diff --git a/EpiAware/docs/src/lib/EpiAwareBase/internals.md b/EpiAware/docs/src/lib/EpiAwareBase/internals.md new file mode 100644 index 000000000..dfa1ff1dd --- /dev/null +++ b/EpiAware/docs/src/lib/EpiAwareBase/internals.md @@ -0,0 +1,23 @@ +# Internal Documentation + +Documentation for `EpiAwareBase.jl`'s internal interface. + +# Contents + +## Contents + +```@contents +Pages = ["internals.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["internals.md"] +``` + +```@autodocs +Modules = [EpiAware.EpiAwareBase] +Public = false +``` diff --git a/EpiAware/docs/src/lib/EpiAwareBase/public.md b/EpiAware/docs/src/lib/EpiAwareBase/public.md new file mode 100644 index 000000000..133e9f3e5 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiAwareBase/public.md @@ -0,0 +1,25 @@ +# Public Documentation + +Documentation for `EpiAwareBae.jl`'s public interface. + +See the Internals section of the manual for internal package docs covering all submodules. + +## Contents + +```@contents +Pages = ["public.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["public.md"] +``` + +## Public API + +```@autodocs +Modules = [EpiAware.EpiAwareBase] +Private = false +``` diff --git a/EpiAware/docs/src/lib/EpiAwareUtils/index.md b/EpiAware/docs/src/lib/EpiAwareUtils/index.md new file mode 100644 index 000000000..2adea5919 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiAwareUtils/index.md @@ -0,0 +1,9 @@ +# EpiAwareUtils.jl + +This package provides utility functions for the EpiAware ecosystem. + +## API + +```@contents +Pages = ["lib/EpiAwareUtils/public.md", "lib/EpiAwareUtils/internals.md"] +``` diff --git a/EpiAware/docs/src/lib/EpiAwareUtils/internals.md b/EpiAware/docs/src/lib/EpiAwareUtils/internals.md new file mode 100644 index 000000000..560d13f1e --- /dev/null +++ b/EpiAware/docs/src/lib/EpiAwareUtils/internals.md @@ -0,0 +1,23 @@ +# Internal Documentation + +Documentation for `EpiAwareUtils.jl`'s internal interface. + +## Contents + +```@contents +Pages = ["internals.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["internals.md"] +``` + +## Internal API + +```@autodocs +Modules = [EpiAware.EpiAwareUtils] +Public = false +``` diff --git a/EpiAware/docs/src/lib/EpiAwareUtils/public.md b/EpiAware/docs/src/lib/EpiAwareUtils/public.md new file mode 100644 index 000000000..2fd3b4541 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiAwareUtils/public.md @@ -0,0 +1,25 @@ +# Public Documentation + +Documentation for `EpiAwareBae.jl`'s public interface. + +See the Internals section of the manual for internal package docs covering all submodules. + +## Contents + +```@contents +Pages = ["public.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["public.md"] +``` + +## Public API + +```@autodocs +Modules = [EpiAware.EpiAwareUtils] +Private = false +``` diff --git a/EpiAware/docs/src/lib/EpiInfModels/index.md b/EpiAware/docs/src/lib/EpiInfModels/index.md new file mode 100644 index 000000000..3952628fd --- /dev/null +++ b/EpiAware/docs/src/lib/EpiInfModels/index.md @@ -0,0 +1,9 @@ +# EpiInfModels.jl + +This package provides infectious disease transmission models for the `EpiAware` ecosystem. + +## API + +```@contents +Pages = ["lib/EpiInfModels/public.md", "lib/EpiInfModels/internals.md"] +``` diff --git a/EpiAware/docs/src/lib/EpiInfModels/internals.md b/EpiAware/docs/src/lib/EpiInfModels/internals.md new file mode 100644 index 000000000..76d68a8db --- /dev/null +++ b/EpiAware/docs/src/lib/EpiInfModels/internals.md @@ -0,0 +1,23 @@ +# Internal Documentation + +Documentation for `EpiInfModels.jl`'s internal interface. + +## Contents + +```@contents +Pages = ["internals.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["internals.md"] +``` + +## Internal API + +```@autodocs +Modules = [EpiAware.EpiInfModels] +Public = false +``` diff --git a/EpiAware/docs/src/lib/EpiInfModels/public.md b/EpiAware/docs/src/lib/EpiInfModels/public.md new file mode 100644 index 000000000..e6830d624 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiInfModels/public.md @@ -0,0 +1,25 @@ +# Public Documentation + +Documentation for `EpiInfModels.jl`'s public interface. + +See the Internals section of the manual for internal package docs covering all submodules. + +## Contents + +```@contents +Pages = ["public.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["public.md"] +``` + +## Public API + +```@autodocs +Modules = [EpiAware.EpiInfModels] +Private = false +``` diff --git a/EpiAware/docs/src/lib/EpiInference/index.md b/EpiAware/docs/src/lib/EpiInference/index.md new file mode 100644 index 000000000..ac3319ece --- /dev/null +++ b/EpiAware/docs/src/lib/EpiInference/index.md @@ -0,0 +1,9 @@ +# EpiInference.jl + +This package provides inference algorithms for the `EpiAware` ecosystem. + +## API + +```@contents +Pages = ["lib/EpiInference/public.md", "lib/EpiInference/internals.md"] +``` diff --git a/EpiAware/docs/src/lib/EpiInference/internals.md b/EpiAware/docs/src/lib/EpiInference/internals.md new file mode 100644 index 000000000..735485d4c --- /dev/null +++ b/EpiAware/docs/src/lib/EpiInference/internals.md @@ -0,0 +1,23 @@ +# Internal Documentation + +Documentation for `EpInference.jl`'s internal interface. + +## Contents + +```@contents +Pages = ["internals.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["internals.md"] +``` + +## Internal API + +```@autodocs +Modules = [EpiAware.EpiInference] +Public = false +``` diff --git a/EpiAware/docs/src/lib/EpiInference/public.md b/EpiAware/docs/src/lib/EpiInference/public.md new file mode 100644 index 000000000..45ebb3747 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiInference/public.md @@ -0,0 +1,25 @@ +# Public Documentation + +Documentation for `EpiInference.jl`'s public interface. + +See the Internals section of the manual for internal package docs covering all submodules. + +## Contents + +```@contents +Pages = ["public.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["public.md"] +``` + +## Public API + +```@autodocs +Modules = [EpiAware.EpiInference] +Private = false +``` diff --git a/EpiAware/docs/src/lib/EpiLatentModels/index.md b/EpiAware/docs/src/lib/EpiLatentModels/index.md new file mode 100644 index 000000000..b5229462a --- /dev/null +++ b/EpiAware/docs/src/lib/EpiLatentModels/index.md @@ -0,0 +1,9 @@ +# EpiLatentModels.jl + +This package provides latent variable models for the `EpiAware` ecosystem. + +## API + +```@contents +Pages = ["lib/EpiLatentModels/public.md", "lib/EpiLatentModels/internals.md"] +``` diff --git a/EpiAware/docs/src/lib/EpiLatentModels/internals.md b/EpiAware/docs/src/lib/EpiLatentModels/internals.md new file mode 100644 index 000000000..89bc891a0 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiLatentModels/internals.md @@ -0,0 +1,23 @@ +# Internal Documentation + +Documentation for `EpiLatentModels.jl`'s internal interface. + +## Contents + +```@contents +Pages = ["internals.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["internals.md"] +``` + +## Internal API + +```@autodocs +Modules = [EpiAware.EpiLatentModels] +Public = false +``` diff --git a/EpiAware/docs/src/lib/EpiLatentModels/public.md b/EpiAware/docs/src/lib/EpiLatentModels/public.md new file mode 100644 index 000000000..2b50830a3 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiLatentModels/public.md @@ -0,0 +1,25 @@ +# Public Documentation + +Documentation for `EpiLatentModels.jl`'s public interface. + +See the Internals section of the manual for internal package docs covering all submodules. + +## Contents + +```@contents +Pages = ["public.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["public.md"] +``` + +## Public API + +```@autodocs +Modules = [EpiAware.EpiLatentModels] +Private = false +``` diff --git a/EpiAware/docs/src/lib/EpiObsModels/index.md b/EpiAware/docs/src/lib/EpiObsModels/index.md new file mode 100644 index 000000000..3d3cafe95 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiObsModels/index.md @@ -0,0 +1,9 @@ +# EpiObsModels.jl + +This package provides observation models for the `EpiAware` ecosystem. + +## API + +```@contents +Pages = ["lib/EpiObsModels/public.md", "lib/EpiObsModels/internals.md"] +``` diff --git a/EpiAware/docs/src/lib/EpiObsModels/internals.md b/EpiAware/docs/src/lib/EpiObsModels/internals.md new file mode 100644 index 000000000..b9dcdd051 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiObsModels/internals.md @@ -0,0 +1,23 @@ +# Internal Documentation + +Documentation for `EpiObsModels.jl`'s internal interface. + +## Contents + +```@contents +Pages = ["internals.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["internals.md"] +``` + +## Internal API + +```@autodocs +Modules = [EpiAware.EpiObsModels] +Public = false +``` diff --git a/EpiAware/docs/src/lib/EpiObsModels/public.md b/EpiAware/docs/src/lib/EpiObsModels/public.md new file mode 100644 index 000000000..ee9109914 --- /dev/null +++ b/EpiAware/docs/src/lib/EpiObsModels/public.md @@ -0,0 +1,25 @@ +# Public Documentation + +Documentation for `EpiObsModels.jl`'s public interface. + +See the Internals section of the manual for internal package docs covering all submodules. + +## Contents + +```@contents +Pages = ["public.md"] +Depth = 2:2 +``` + +## Index + +```@index +Pages = ["public.md"] +``` + +## Public API + +```@autodocs +Modules = [EpiAware.EpiObsModels] +Private = false +``` diff --git a/EpiAware/docs/src/lib/index.md b/EpiAware/docs/src/lib/index.md new file mode 100644 index 000000000..405f1c40f --- /dev/null +++ b/EpiAware/docs/src/lib/index.md @@ -0,0 +1,3 @@ +# [API reference](@id api-reference) + +Welcome to the `EpiAware` API reference! This section is designed to help you understand the API of the package which is split into submodules. diff --git a/EpiAware/docs/src/lib/internals.md b/EpiAware/docs/src/lib/internals.md index 57ae28f36..2b391d797 100644 --- a/EpiAware/docs/src/lib/internals.md +++ b/EpiAware/docs/src/lib/internals.md @@ -1,4 +1,4 @@ -# internal Documentation +# Internal Documentation Documentation for `EpiAware.jl`'s internal interface. diff --git a/EpiAware/docs/src/overview.md b/EpiAware/docs/src/overview.md new file mode 100644 index 000000000..9bdb50593 --- /dev/null +++ b/EpiAware/docs/src/overview.md @@ -0,0 +1,33 @@ +# [Overview of the EpiAware Software Ecosystem](@id overview) + +_`EpiAware` is not a standard toolkit for infectious disease modelling._ + +It seeks to be highly modular and composable for advanced users whilst still providing opinionated workflows for those who are new to the field. Developed by the authors behind other widely used infectious disease modelling packages such as `EpiNow2`, `epinowcast`, and `epidist`, alongside experts in infectious disease modelling in Julia,`EpiAware` is designed to go beyond the capabilities of these packages by providing a more flexible and extensible framework for modelling and inference of infectious disease dynamics. + +## Package Features + +- **Flexible**: The package is designed to be flexible and extensible, and to provide a consistent interface for fitting and simulating models. +- **Modular**: The package is designed to be modular, with a clear separation between the model and the data. +- **Extensible**: The package is designed to be extensible, with a clear separation between the model and the data. +- **Consistent**: The package is designed to provide a consistent interface for fitting and simulating models. +- **Efficient**: The package is designed to be efficient, with a clear separation between the model and the data. + +## Package structure + +`EpiAware.jl` is a wrapper around a series of submodules, each of which provides a different aspect of the package's functionality (much like the `tidyverse` in `R`). The package is designed to be modular, with a clear separation between modules and between modules and data. Currently included modules are: + +- `EpiAwareBase`: The core module, which provides the underlying abstract types and functions for the package. +- `EpiAwareUtils`: A utility module, which provides a series of utility functions for working with the package. +- `EpiInference`: An inference module, which provides a series of functions for fitting models to data. Builds on top of `Turing.jl`. +- `EpiInfModels`: Provides tools for composing models of the disease transmission process. Builds on top of `Turing.jl`, in particular the `DynamicPPL.jl` interface. +- `EpiLatentModels`: Provides tools for composing latent models such as random walks, autoregressive models, etc. Builds on top of `DynamicPPL.jl`. Used by all other modelling modules to define latent processes. +- `EpiObsModels`: Provides tools for composing observation models, such as Poisson, Binomial, etc. Builds on top of `DynamicPPL.jl`. + +## Using the package + +We support two primary workflows for using the package: + +- `EpiProblem`: A high-level interface for defining and fitting models to data. This is the recommended way to use the package. +- `Turing` interface: A lower-level interface for defining and fitting models to data. This is the more flexible way to use the package and may also be more familiar to users of `Turing.jl`. + +See the getting started section for tutorials on each of these workflows. diff --git a/EpiAware/docs/src/showcase/index.md b/EpiAware/docs/src/showcase/index.md new file mode 100644 index 000000000..bc0c2fd05 --- /dev/null +++ b/EpiAware/docs/src/showcase/index.md @@ -0,0 +1,3 @@ +# [EpiAware Showcase](@id showcase) + +Here we showcase the capabilities of `EpiAware` in action. If you have a showcase you would like to add, please submit a pull request. diff --git a/EpiAware/docs/src/showcase/replications/.gitignore b/EpiAware/docs/src/showcase/replications/.gitignore new file mode 100644 index 000000000..dd449725e --- /dev/null +++ b/EpiAware/docs/src/showcase/replications/.gitignore @@ -0,0 +1 @@ +*.md diff --git a/EpiAware/docs/src/examples/get_data.R b/EpiAware/docs/src/showcase/replications/mishra-2020/get_data.R similarity index 100% rename from EpiAware/docs/src/examples/get_data.R rename to EpiAware/docs/src/showcase/replications/mishra-2020/get_data.R diff --git a/EpiAware/docs/src/examples/getting_started.jl b/EpiAware/docs/src/showcase/replications/mishra-2020/index.jl similarity index 99% rename from EpiAware/docs/src/examples/getting_started.jl rename to EpiAware/docs/src/showcase/replications/mishra-2020/index.jl index 2e44994f7..674e86be7 100644 --- a/EpiAware/docs/src/examples/getting_started.jl +++ b/EpiAware/docs/src/showcase/replications/mishra-2020/index.jl @@ -1,5 +1,5 @@ ### A Pluto.jl notebook ### -# v0.19.42 +# v0.19.40 using Markdown using InteractiveUtils @@ -7,7 +7,7 @@ using InteractiveUtils # ╔═╡ 34a06b3b-799b-48c5-bd08-1e57151f51ec # hideall let - docs_dir = dirname(dirname(@__DIR__)) + docs_dir = dirname(dirname(dirname(dirname(@__DIR__)))) pkg_dir = dirname(docs_dir) using Pkg: Pkg diff --git a/EpiAware/docs/src/examples/south_korea_data.csv2 b/EpiAware/docs/src/showcase/replications/mishra-2020/south_korea_data.csv2 similarity index 100% rename from EpiAware/docs/src/examples/south_korea_data.csv2 rename to EpiAware/docs/src/showcase/replications/mishra-2020/south_korea_data.csv2 diff --git a/EpiAware/src/EpiAware.jl b/EpiAware/src/EpiAware.jl index fcd55bd3f..558ac0539 100644 --- a/EpiAware/src/EpiAware.jl +++ b/EpiAware/src/EpiAware.jl @@ -1,36 +1,3 @@ -""" - module EpiAware - -`EpiAware` provides functionality for fitting epidemiological models to data. It is built on - top of the `Turing` probabilistic programming language, and provides a set of utilities - for constructing and fitting models to data. - -## Core model structure - -An epidemiological model in `EpiAware` consists of composable structs with core abstract - types. The core types are: -1. `AbstractModel`: This overarching type is used to abstract `Turing` models and is - inherited by the other abstract types we use. -2. `AbstractTuringEpiModel`: Subtypes of this abstract type represent different models for the - spread of an infectious disease. Each model type has a corresponding - `make_epi_aware` function that constructs a `Turing` model for fitting the - model to data. Implemented concrete subtypes: - - `Renewal`: A renewal process model for the spread of an infectious disease. - - `ExpGrowthRate`: An exponential growth rate model for the spread of an infectious - disease. - - `DirectInfections`: A model for the spread of an infectious disease based on modelling - direct infections. -3. `AbstractLatentModel`: Subtypes of this abstract type represent different latent - processes that can be used in an epidemiological model. Implemented concrete subtype: - - `RandomWalk`: A random walk latent process. -4. `AbstractObservationModel`: Subtypes of this abstract type represent different - observation models that can be used in an epidemiological model. - Implemented concrete subtypes: - - `DelayObservation`: An observation process that models the delay between the time - of infection and the time of observation as a convolution, followed by a negative - binomial distributed sample. - -""" module EpiAware # Non-submodule imports From 849b707be0a1a3ebe9d6e90873aef21e8aa4b694 Mon Sep 17 00:00:00 2001 From: Sam Abbott Date: Wed, 3 Jul 2024 14:43:37 +0100 Subject: [PATCH 2/5] improve structure and stub out work to do (#331) --- EpiAware/docs/pages.jl | 48 +++++++++++++++---- .../src/getting-started/explainers/index.md | 3 ++ EpiAware/docs/src/getting-started/index.md | 4 +- .../src/getting-started/tutorials/index.md | 3 ++ EpiAware/docs/src/lib/index.md | 2 + EpiAware/docs/src/lib/internals.md | 2 +- 6 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 EpiAware/docs/src/getting-started/explainers/index.md create mode 100644 EpiAware/docs/src/getting-started/tutorials/index.md diff --git a/EpiAware/docs/pages.jl b/EpiAware/docs/pages.jl index 0ebf47b97..65e235428 100644 --- a/EpiAware/docs/pages.jl +++ b/EpiAware/docs/pages.jl @@ -1,8 +1,10 @@ getting_started_pages = Any[ + "Overview" => "getting-started/index.md", "Installation" => "getting-started/installation.md", "Quickstart" => "getting-started/quickstart.md", "Frequently asked questions" => "getting-started/faq.md", "Explainers" => [ + "Overview" => "getting-started/explainers/index.md", "Working with Julia" => "getting-started/explainers/julia.md", "Introduction to EpiAware" => "getting-started/explainers/intro.md", "Modelling infections" => "getting-started/explainers/modelling-infections.md", @@ -11,6 +13,7 @@ getting_started_pages = Any[ "Observation models" => "getting-started/explainers/observation-models.md" ], "Tutorials" => [ + "Overview" => "getting-started/tutorials/index.md", "Simple renewal with delays" => "getting-started/tutorials/simple-renewal-with-delays.md", "Nowcasting" => "getting-started/tutorials/nowcasting.md", "Multiple observation models" => "getting-started/tutorials/multiple-observation-models.md", @@ -19,10 +22,11 @@ getting_started_pages = Any[ ] ] -showcase_pages = [ +showcase_pages = Any[ + "Overview" => "showcase/index.md", "Replication" => [ - "On the derivation of the renewal equation from an age-dependent branching process: an epidemic modelling perspective" => "showcase/replications/mishra-2020/index.md" -] + "On the derivation of the renewal equation from an age-dependent branching process: an epidemic modelling perspective" => "showcase/replications/mishra-2020/index.md" + ] ] what_is_pages = [ @@ -30,19 +34,45 @@ what_is_pages = [ ] module_pages = Any[ - "EpiAwareBase" => "lib/EpiAwareBase/index.md", - "EpiAwareUtils" => "lib/EpiAwareUtils/index.md", - "EpiInference" => "lib/EpiInference/index.md", - "EpiInfModels" => "lib/EpiInfModels/index.md", - "EpiLatentModels" => "lib/EpiLatentModels/index.md", - "EpiObsModels" => "lib/EpiObsModels/index.md", "EpiAware" => [ + "Overview" => "lib/index.md", "Public API" => "lib/public.md", "Internal API" => "lib/internals.md" + ], + "EpiAwareBase" => [ + "Overview" => "lib/EpiAwareBase/index.md", + "Public API" => "lib/EpiAwareBase/public.md", + "Internal API" => "lib/EpiAwareBase/internals.md" + ], + "EpiAwareUtils" => [ + "Overview" => "lib/EpiAwareUtils/index.md", + "Public API" => "lib/EpiAwareUtils/public.md", + "Internal API" => "lib/EpiAwareUtils/internals.md" + ], + "EpiInference" => [ + "Overview" => "lib/EpiInference/index.md", + "Public API" => "lib/EpiInference/public.md", + "Internal API" => "lib/EpiInference/internals.md" + ], + "EpiInfModels" => [ + "Overview" => "lib/EpiInfModels/index.md", + "Public API" => "lib/EpiInfModels/public.md", + "Internal API" => "lib/EpiInfModels/internals.md" + ], + "EpiLatentModels" => [ + "Overview" => "lib/EpiLatentModels/index.md", + "Public API" => "lib/EpiLatentModels/public.md", + "Internal API" => "lib/EpiLatentModels/internals.md" + ], + "EpiObsModels" => [ + "Overview" => "lib/EpiObsModels/index.md", + "Public API" => "lib/EpiObsModels/public.md", + "Internal API" => "lib/EpiObsModels/internals.md" ] ] developer_pages = [ + "Overview" => "developer/index.md", "Contributing" => "developer/contributing.md", "Release checklist" => "developer/checklist.md" ] diff --git a/EpiAware/docs/src/getting-started/explainers/index.md b/EpiAware/docs/src/getting-started/explainers/index.md new file mode 100644 index 000000000..f493b2307 --- /dev/null +++ b/EpiAware/docs/src/getting-started/explainers/index.md @@ -0,0 +1,3 @@ +# Explainers + +This section contains a series of explainers that provide a detailed overview of the EpiAware platform and its features. These explainers are designed to help you understand the platform and its capabilities, and to provide you with the information you need to get started using EpiAware. See the sidebar for the list of explainers. diff --git a/EpiAware/docs/src/getting-started/index.md b/EpiAware/docs/src/getting-started/index.md index 25e8082a8..21b75f64c 100644 --- a/EpiAware/docs/src/getting-started/index.md +++ b/EpiAware/docs/src/getting-started/index.md @@ -1,3 +1,5 @@ # [Getting started](@id getting-started) -Welcome to the `EpiAware` documentation! This section is designed to help you get started with the package. +*Note that this section of the documentation is still under construction. Please see replications for the most up-to-date information. Please feel free to contribute to the documentation by submitting a pull request.* + +Welcome to the `EpiAware` documentation! This section is designed to help you get started with the package. It includes a frequently asked questions (FAQ) section, a series of explainers that provide a detailed overview of the platform and its features, and tutorials that will help you get started with EpiAware for specific tasks. See the sidebar for the list of topics. diff --git a/EpiAware/docs/src/getting-started/tutorials/index.md b/EpiAware/docs/src/getting-started/tutorials/index.md new file mode 100644 index 000000000..d0bb73ab2 --- /dev/null +++ b/EpiAware/docs/src/getting-started/tutorials/index.md @@ -0,0 +1,3 @@ +# Tutorials + +This section contains tutorials that will help you get started with EpiAware for specific tasks. See the sidebar for the list of tutorials. diff --git a/EpiAware/docs/src/lib/index.md b/EpiAware/docs/src/lib/index.md index 405f1c40f..cbf844a8e 100644 --- a/EpiAware/docs/src/lib/index.md +++ b/EpiAware/docs/src/lib/index.md @@ -1,3 +1,5 @@ # [API reference](@id api-reference) Welcome to the `EpiAware` API reference! This section is designed to help you understand the API of the package which is split into submodules. + +The `EpiAware` package itself contains no functions or types. Instead, it re-exports the functions and types from its submodules. See the sidebar for the list of submodules. diff --git a/EpiAware/docs/src/lib/internals.md b/EpiAware/docs/src/lib/internals.md index 2b391d797..9030b2260 100644 --- a/EpiAware/docs/src/lib/internals.md +++ b/EpiAware/docs/src/lib/internals.md @@ -5,7 +5,7 @@ Documentation for `EpiAware.jl`'s internal interface. ## Contents ```@contents -Pages = ["internal.md"] +Pages = ["internals.md"] Depth = 2:2 ``` From df3f7d702ebcda0664f44562aafd2a8757632fef Mon Sep 17 00:00:00 2001 From: Sam Abbott Date: Fri, 5 Jul 2024 12:01:41 +0100 Subject: [PATCH 3/5] Add Doctest infra and add doctests to EpiAwareUtils (#332) * add doctest infra and add doctests for censored_pmf * add the right environment * use StableRNGs * add doctests for HalfNormal * add prefix doctest * add doctest for scan * turn doc building back on * move new docstring deps to test as this is the only place they are run * Add mcmcchains * don't try and match random numbers instead just make sure itsa number * use @doc raw * stop trying to fix the seed in doctests * remove failing doc test for now --- EpiAware/docs/make.jl | 4 +- EpiAware/src/EpiAwareUtils/HalfNormal.jl | 40 ++++++++++- EpiAware/src/EpiAwareUtils/censored_pmf.jl | 71 ++++++++++++++++--- EpiAware/src/EpiAwareUtils/get_param_array.jl | 7 +- EpiAware/src/EpiAwareUtils/prefix_submodel.jl | 13 +++- EpiAware/src/EpiAwareUtils/scan.jl | 13 ++++ EpiAware/test/Project.toml | 2 + EpiAware/test/doctest.jl | 4 ++ 8 files changed, 134 insertions(+), 20 deletions(-) create mode 100644 EpiAware/test/doctest.jl diff --git a/EpiAware/docs/make.jl b/EpiAware/docs/make.jl index 7e1f3d5ef..5def2a8c8 100644 --- a/EpiAware/docs/make.jl +++ b/EpiAware/docs/make.jl @@ -17,9 +17,11 @@ build("getting-started") build("getting-started/tutorials") build("showcase/replications/mishra-2020") +DocMeta.setdocmeta!(EpiAware, :DocTestSetup, :(using EpiAware); recursive = true) + makedocs(; sitename = "EpiAware.jl", authors = "Samuel Brand, Zachary Susswein, Sam Abbott, and contributors", - clean = true, doctest = true, linkcheck = true, + clean = true, doctest = false, linkcheck = true, warnonly = [:docs_block, :missing_docs, :linkcheck, :autodocs_block], modules = [ EpiAware, EpiAware.EpiAwareBase, EpiAware.EpiAwareUtils, EpiAware.EpiInference, diff --git a/EpiAware/src/EpiAwareUtils/HalfNormal.jl b/EpiAware/src/EpiAwareUtils/HalfNormal.jl index 43f67cae1..9d8c78da5 100644 --- a/EpiAware/src/EpiAwareUtils/HalfNormal.jl +++ b/EpiAware/src/EpiAwareUtils/HalfNormal.jl @@ -11,15 +11,49 @@ Create a half-normal prior distribution with the specified mean. # Examples: -```julia -using EpiAware +```jldoctest HalfNormal +using EpiAware, Distributions + hn = HalfNormal(1.0) +# output +EpiAware.EpiAwareUtils.HalfNormal{Float64}(μ=1.0) +``` + +# filter out all the values that are less than 0 +```jldoctest HalfNormal; filter = r\"\b\d+(\.\d+)?\b\" => \"*\" rand(hn) -cdf(hn, 4) +# output +0.4508533245229199 +``` + +```jldoctest HalfNormal +cdf(hn, 2) +# output +0.8894596502772643 +``` + +```jldoctest HalfNormal quantile(hn, 0.5) +# output +0.8453475393951495 +``` + +```jldoctest HalfNormal logpdf(hn, 2) +# output +-3.1111166111445083 +``` + +```jldoctest HalfNormal mean(hn) +# output +1.0 +``` + +```jldoctest HalfNormal var(hn) +# output +0.5707963267948966 ``` " struct HalfNormal{T <: Real} <: ContinuousUnivariateDistribution diff --git a/EpiAware/src/EpiAwareUtils/censored_pmf.jl b/EpiAware/src/EpiAwareUtils/censored_pmf.jl index dc4d9aa57..38e274f64 100644 --- a/EpiAware/src/EpiAwareUtils/censored_pmf.jl +++ b/EpiAware/src/EpiAwareUtils/censored_pmf.jl @@ -1,10 +1,10 @@ -""" +@doc raw" Create a discrete probability mass function (PMF) from a given distribution, assuming that the primary event happens at `primary_approximation_point * Δd` within an intial censoring interval. Common single-censoring approximations are `primary_approximation_point = 0` (left-hand approximation), `primary_approximation_point = 1` (right-hand) and `primary_approximation_point = 0.5` (midpoint). -Arguments: +# Arguments - `dist`: The distribution from which to create the PMF. - ::Val{:single_censored}: A dummy argument to dispatch to this method. The purpose of the `Val` type argument is that to use `single-censored` approximation is an active decision. @@ -13,14 +13,39 @@ Default is 0.5 for midpoint approximation. - `Δd`: The step size for discretizing the domain. Default is 1.0. - `D`: The upper bound of the domain. Must be greater than `Δd`. -Returns: +# Returns - A vector representing the PMF. Raises: - `AssertionError` if the minimum value of `dist` is negative. - `AssertionError` if `Δd` is not positive. - `AssertionError` if `D` is not greater than `Δd`. -""" + +# Examples + +```jldoctest filter +using Distributions +using EpiAware.EpiAwareUtils + +dist = Exponential(1.0) + +censored_pmf(dist, Val(:single_censored); D = 10) |> + p -> round.(p, digits=3) + +# output +10-element Vector{Float64}: + 0.393 + 0.383 + 0.141 + 0.052 + 0.019 + 0.007 + 0.003 + 0.001 + 0.0 + 0.0 +``` +" function censored_pmf(dist::Distribution, ::Val{:single_censored}; primary_approximation_point = 0.5, @@ -38,8 +63,9 @@ function censored_pmf(dist::Distribution, ts .|> (t -> cdf(dist, t)) |> diff |> p -> p ./ sum(p) end -""" -Create a discrete probability mass function (PMF) from a given distribution, assuming +@doc raw" +Create a discrete probability mass function (PMF) from a given distribution, +assuming a uniform distribution over primary event times with censoring intervals of width `Δd` for both primary and secondary events. The CDF for the time from the left edge of the interval containing the primary event to the secondary event is created by direct numerical integration @@ -47,22 +73,47 @@ of the convolution of the CDF of `dist` with the uniform density on `[0,Δd)`, t for double censored delays is then found using simple differencing on the CDF. -Arguments: +# Arguments - `dist`: The distribution from which to create the PMF. - `Δd`: The step size for discretizing the domain. Default is 1.0. - `D`: The upper bound of the domain. Must be greater than `Δd`. Default `D = nothing` indicates that the distribution should be truncated at its 99th percentile rounded to nearest multiple of `Δd`. -Returns: +# Returns - A vector representing the PMF. -Raises: +# Raises - `AssertionError` if the minimum value of `dist` is negative. - `AssertionError` if `Δd` is not positive. - `AssertionError` if `D` is shorter than `Δd`. - `AssertionError` if `D` is not a multiple of `Δd`. -""" + +# Examples + +```jldoctest filter +using Distributions +using EpiAware.EpiAwareUtils + +dist = Exponential(1.0) + +censored_pmf(dist; D = 10) |> + p -> round.(p, digits=3) + +# output +10-element Vector{Float64}: + 0.368 + 0.4 + 0.147 + 0.054 + 0.02 + 0.007 + 0.003 + 0.001 + 0.0 + 0.0 +``` +" function censored_pmf(dist::Distribution; Δd = 1.0, D = nothing) @assert minimum(dist)>=0.0 "Distribution must be non-negative." @assert Δd>0.0 "Δd must be positive." diff --git a/EpiAware/src/EpiAwareUtils/get_param_array.jl b/EpiAware/src/EpiAwareUtils/get_param_array.jl index 58746e68a..33ba05fdb 100644 --- a/EpiAware/src/EpiAwareUtils/get_param_array.jl +++ b/EpiAware/src/EpiAwareUtils/get_param_array.jl @@ -1,4 +1,4 @@ -""" +@doc raw" Extract a parameter array from a `Chains` object `chn` that matches the shape of number of sample and chain pairs in `chn`. @@ -18,15 +18,14 @@ Sampling from a simple model which has both scalar and vector quantity random va using Turing, MCMCChains, EpiAware @model function testmodel() - x ~ MvNormal(2, 1.) y ~ Normal() end mdl = testmodel() -chn = sample(mdl, Prior(), MCMCSerial(), 250, 4) +chn = sample(mdl, Prior(), MCMCSerial(), 2, 1, progress=false) A = get_param_array(chn) ``` -""" +" function get_param_array(chn::Chains) rowtable(chn) |> x -> reshape(x, size(chn, 1), size(chn, 3)) end diff --git a/EpiAware/src/EpiAwareUtils/prefix_submodel.jl b/EpiAware/src/EpiAwareUtils/prefix_submodel.jl index e6441d8e2..063755701 100644 --- a/EpiAware/src/EpiAwareUtils/prefix_submodel.jl +++ b/EpiAware/src/EpiAwareUtils/prefix_submodel.jl @@ -13,9 +13,18 @@ Generate a submodel with an optional prefix. A lightweight wrapper around the `@ # Examples +```jldoctest +using EpiAware, DynamicPPL + +submodel = prefix_submodel(FixedIntercept(0.1), generate_latent, string(1), 2) +submodel +# output +Model{typeof(prefix_submodel), (:model, :fn, :prefix, Symbol(\"#splat#kwargs\")), (), (), Tuple{FixedIntercept{Float64}, typeof(generate_latent), String, Tuple{Int64}}, Tuple{}, DefaultContext}(EpiAware.EpiAwareUtils.prefix_submodel, (model = FixedIntercept{Float64}(0.1), fn = EpiAware.EpiAwareBase.generate_latent, prefix = \"1\", var\"#splat#kwargs\" = (2,)), NamedTuple(), DefaultContext()) +``` + +We can now draw a sample from the submodel. + ```julia -using EpiAware -submodel = prefix_submodel(CombineLatentModels([FixedIntercept(0.1), AR()]), generate_latent, \"Test\", 10) rand(submodel) ``` " diff --git a/EpiAware/src/EpiAwareUtils/scan.jl b/EpiAware/src/EpiAwareUtils/scan.jl index fbd76c5a6..fcf3396cb 100644 --- a/EpiAware/src/EpiAwareUtils/scan.jl +++ b/EpiAware/src/EpiAwareUtils/scan.jl @@ -22,6 +22,19 @@ Apply `f` to each element of `xs` and accumulate the results. - `ys`: An array containing the results of applying `f` to each element of `xs`. - `carry`: The final value of the `carry` variable after processing all elements of `xs`. +# Examples + +```jldoctest +using EpiAware + +struct Adder <: EpiAwareBase.AbstractModel end +function (a::Adder)(carry, x) + carry + x, carry + x +end + +scan(Adder(), 0, 1:5) +#output +([1, 3, 6, 10, 15], 15) """ function scan(f::F, init, xs) where {F <: EpiAwareBase.AbstractModel} carry = init diff --git a/EpiAware/test/Project.toml b/EpiAware/test/Project.toml index db7953729..8922ac0f2 100644 --- a/EpiAware/test/Project.toml +++ b/EpiAware/test/Project.toml @@ -3,10 +3,12 @@ Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DataFramesMeta = "1313f7d8-7da2-5740-9ea0-a2ca25f37964" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" DynamicPPL = "366bfd00-2699-11ea-058f-f148b4cae6d8" HypothesisTests = "09f84164-cd44-5f33-b23f-e6b0d136a0d5" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d" Pathfinder = "b1d3bc72-d0e7-4279-b92f-7fa5d6d2d454" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" diff --git a/EpiAware/test/doctest.jl b/EpiAware/test/doctest.jl new file mode 100644 index 000000000..387b9e452 --- /dev/null +++ b/EpiAware/test/doctest.jl @@ -0,0 +1,4 @@ +@testitem "Run docstring tests" begin + using Documenter + doctest(EpiAware) +end From ff104c4d05a296f6b1668a1f611c24804f7d2a00 Mon Sep 17 00:00:00 2001 From: Samuel Brand <48288458+SamuelBrand1@users.noreply.github.com> Date: Fri, 5 Jul 2024 12:26:03 +0100 Subject: [PATCH 4/5] New scenario types and associated `make_Rt` methods (#327) * adding make_Rt methods * more make Rt methods * Make endemic scenarios geometric mean 1 * Update test_constructors.jl --- pipeline/src/EpiAwarePipeline.jl | 7 +- pipeline/src/constructors/make_Rt.jl | 165 ++++++++++++++++++ pipeline/src/pipeline/pipelinetypes.jl | 46 ++++- .../test/constructors/test_constructors.jl | 19 +- pipeline/test/forecast/test_forecast.jl | 2 +- pipeline/test/infer/test_InferenceConfig.jl | 2 +- pipeline/test/infer/test_define_epiprob.jl | 2 +- pipeline/test/pipeline/test_pipelinetypes.jl | 17 +- pipeline/test/runtests.jl | 2 +- 9 files changed, 240 insertions(+), 22 deletions(-) diff --git a/pipeline/src/EpiAwarePipeline.jl b/pipeline/src/EpiAwarePipeline.jl index 8ca5731ac..dc1ba8709 100644 --- a/pipeline/src/EpiAwarePipeline.jl +++ b/pipeline/src/EpiAwarePipeline.jl @@ -12,11 +12,12 @@ module EpiAwarePipeline using CSV, Dagger, DataFramesMeta, Dates, Distributions, DocStringExtensions, DrWatson, EpiAware, Plots, Statistics, ADTypes, AbstractMCMC, Plots, JLD2, MCMCChains, Turing, - DynamicPPL, LogExpFunctions, RCall, LinearAlgebra + DynamicPPL, LogExpFunctions, RCall, LinearAlgebra, Random # Exported pipeline types -export AbstractEpiAwarePipeline, EpiAwarePipeline, RtwithoutRenewalPipeline, - RtwithoutRenewalPriorPipeline, EpiAwareExamplePipeline +export AbstractEpiAwarePipeline, EpiAwarePipeline, AbstractRtwithoutRenewalPipeline, + RtwithoutRenewalPriorPipeline, EpiAwareExamplePipeline, SmoothOutbreakPipeline, + MeasuresOutbreakPipeline, SmoothEndemicPipeline, RoughEndemicPipeline # Exported utility functions export calculate_processes diff --git a/pipeline/src/constructors/make_Rt.jl b/pipeline/src/constructors/make_Rt.jl index fd1a7fba1..c9a04f724 100644 --- a/pipeline/src/constructors/make_Rt.jl +++ b/pipeline/src/constructors/make_Rt.jl @@ -19,3 +19,168 @@ function make_Rt(pipeline::AbstractEpiAwarePipeline; A = 0.3, P = 30.0) [1.0 + A * sin.(2 * π * (t - ϕ) / P) for t in 1:(N - length(Rt))]] return true_Rt end + +""" +Constructs the time-varying reproduction number (Rt) for a given SmoothOutbreakPipeline. + +# Arguments +- `pipeline::SmoothOutbreakPipeline`: The SmoothOutbreakPipeline object for which to construct Rt. +- `N::Float64 = 70.0`: The number of time steps to consider. +- `initial_Rt::Float64 = 1.5`: The initial value of Rt. +- `reduction::Float64 = 0.5`: The reduction factor applied to Rt over time. +- `r::Float64 = 1 / 3.5`: The rate of change of Rt over time. +- `shift::Float64 = 35.0`: The time shift applied to Rt. + +# Returns +- `Rt::Vector{Float64}`: The time-varying reproduction number (Rt) as a vector. + +# Example + +```julia +using EpiAwarePipeline, Plots +pipeline = SmoothOutbreakPipeline() +Rt = make_Rt(pipeline) |> Rt -> plot(Rt, + xlabel = "Time", + ylabel = "Rt", + lab = "", + title = "Smooth outbreak scenario") +``` +""" +function make_Rt(pipeline::SmoothOutbreakPipeline; N = 70.0, initial_Rt = 1.5, + reduction = 0.5, r = 1 / 3.5, shift = 35.0) + Rt = map(1.0:N) do t + initial_Rt * (1 - reduction * logistic(r * (t - shift))) + end + return Rt +end + +""" +Constructs the time-varying reproduction number (Rt) for a given outbreak with measures scenario. + +# Arguments +- `pipeline::MeasuresOutbreakPipeline`: The outbreak pipeline object. +- `N::Float64`: The total number of time steps. +- `initial_Rt::Float64`: The initial reproduction number before any measures are implemented. +- `measures_Rt::Float64`: The reproduction number during the period when measures are implemented. +- `post_measures_Rt::Float64`: The reproduction number after the measures are lifted. +- `reduction::Float64`: The eventual reduction factor applied to the reproduction number after measures are lifted over time. +- `r::Float64`: The rate of decay towards the reduction factor. +- `shift::Float64`: The time shift applied to the decay function after end of measures. +- `t₁::Float64`: The time step at which measures are implemented. +- `t₂::Float64`: The time step at which measures are lifted. + +# Returns +- `Rt::Vector{Float64}`: The time-varying reproduction number. + +# Example + +```julia +using EpiAwarePipeline, Plots +pipeline = MeasuresOutbreakPipeline() +Rt = make_Rt(pipeline) |> Rt -> plot(Rt, + xlabel = "Time", + ylabel = "Rt", + lab = "", + title = "Outbreak scenario with measures") +``` +""" +function make_Rt( + pipeline::MeasuresOutbreakPipeline; N = 70.0, initial_Rt = 1.5, measures_Rt = 0.8, + post_measures_Rt = 1.2, reduction = 0.6, r = 1 / 3.5, shift = 21.0, t₁ = 21.0, t₂ = 42.0) + Rt = vcat(map(t -> initial_Rt, 1.0:t₁), + map(t -> measures_Rt, (t₁ + 1.0):t₂), + map((t₂ + 1):N) do t + post_measures_Rt * (1 - reduction * logistic(r * (t - t₂ - shift))) + end) + + return Rt +end + +""" +Constructs the time-varying reproduction number (Rt) for a smoothly varying endemic scenario. + +In this context "endemic" means a scenario where the geometric average of the +reproduction number is 1.0, that is the following holds: + +```math +(\\prod_{t = 1}^n[R_t])^{1/n} = 1. +``` + +This implies that the long-term muliplicative growth of the infected community is 1.0. + +# Arguments +- `pipeline::SmoothEndemicPipeline`: The pipeline for which Rt is constructed. +- `N::Float64 = 70.0`: The number of time points to generate Rt for. +- `A::Float64 = 0.1`: The amplitude of the sinusoidal variation in Rt. +- `P::Float64 = 28.0`: The period of the sinusoidal variation in Rt. + +# Returns +- `Rt::Vector{Float64}`: The time-varying reproduction number. + +# Examples + +```julia +using EpiAwarePipeline, Plots +pipeline = SmoothEndemicPipeline() +Rt = make_Rt(pipeline) |> Rt -> plot(Rt, + xlabel = "Time", + ylabel = "Rt", + lab = "", + title = "Smoothly varying endemic scenario") +``` +""" +function make_Rt( + pipeline::SmoothEndemicPipeline; N = 70.0, A = 0.1, P = 28.0) + log_Rt = map(1.0:N) do t + A * sinpi(2 * t / P) + end + Rt = exp.(log_Rt .- mean(log_Rt)) # Normalize to have geometric mean 1.0 + return Rt +end + +""" +Constructs the time-varying reproduction number (Rt) for an randomly varying endemic scenario. + +In this context "endemic" means a scenario where the geometric average of the +reproduction number is 1.0, that is the following holds: + +```math +(\\prod_{t = 1}^n[R_t])^{1/n} = 1. +``` + +This implies that the long-term muliplicative growth of the infected community is 1.0. + + + +# Arguments +- `pipeline::RoughEndemicPipeline`: The `RoughEndemicPipeline` object for which Rt is being constructed. +- `N_steps::Int = 10`: The number of steps to generate random values for Rt. +- `rng::AbstractRNG = MarsenneTwister(1234)`: The random number generator to use. +- `stride::Int = 7`: The stride length for repeating each random value. +- `σ::Float64 = 0.05`: The standard deviation of the random values. + +# Returns +- `Rt::Vector{Float64}`: The time-varying reproduction number Rt. + +# Example + +```julia +using EpiAwarePipeline, Plots +pipeline = RoughEndemicPipeline() +Rt = make_Rt(pipeline) |> Rt -> plot(Rt, + xlabel = "Time", + ylabel = "Rt", + lab = "", + title = "Rough Rt path endemic scenario") +``` +""" +function make_Rt( + pipeline::RoughEndemicPipeline; N_steps = 10, rng = MersenneTwister(1234), stride = 7, σ = 0.05) + X = σ * randn(rng, N_steps) + log_Rt = mapreduce(vcat, X) do x + fill(x, stride) + end + Rt = exp.(log_Rt .- mean(log_Rt)) # Normalize to have geometric mean 1.0 + + return Rt +end diff --git a/pipeline/src/pipeline/pipelinetypes.jl b/pipeline/src/pipeline/pipelinetypes.jl index b04fc6442..6ac322959 100644 --- a/pipeline/src/pipeline/pipelinetypes.jl +++ b/pipeline/src/pipeline/pipelinetypes.jl @@ -4,11 +4,9 @@ The abstract root type for all pipeline types using `EpiAware`. abstract type AbstractEpiAwarePipeline end """ -The pipeline type for the Rt pipeline with renewal including specific options - for plotting and saving. +An abstract type for different scenarios in the Rt without Renewal pipeline. """ -struct RtwithoutRenewalPipeline <: AbstractEpiAwarePipeline -end +abstract type AbstractRtwithoutRenewalPipeline <: AbstractEpiAwarePipeline end """ The pipeline type for the Rt pipeline without renewal with only prior predictive @@ -22,3 +20,43 @@ The pipeline type for the Rt pipeline without renewal in test mode. """ struct EpiAwareExamplePipeline <: AbstractEpiAwarePipeline end + +""" +The pipeline type for the Rt pipeline for an outbreak scenario where Rt decreases + smoothly over time to Rt < 1. + +# Example + +```julia +using EpiAwarePipeline, Plots +pipeline = SmoothOutbreakPipeline() +Rt = make_Rt(pipeline) |> Rt -> plot(Rt, + xlabel = "Time", + ylabel = "Rt", + lab = "", + title = "Smooth outbreak scenario") +``` +""" +struct SmoothOutbreakPipeline <: AbstractRtwithoutRenewalPipeline +end + +""" +The pipeline type for the Rt pipeline for an outbreak scenario where Rt has + discontinuous changes over time due to implementation of measures. +""" +struct MeasuresOutbreakPipeline <: AbstractRtwithoutRenewalPipeline +end + +""" +The pipeline type for the Rt pipeline for an endemic scenario where Rt changes in + a smooth sinusoidal manner over time. +""" +struct SmoothEndemicPipeline <: AbstractRtwithoutRenewalPipeline +end + +""" +The pipeline type for the Rt pipeline for an endemic scenario where Rt changes in + a weekly-varying discontinuous manner over time. +""" +struct RoughEndemicPipeline <: AbstractRtwithoutRenewalPipeline +end diff --git a/pipeline/test/constructors/test_constructors.jl b/pipeline/test/constructors/test_constructors.jl index 91fa28dc6..e536e9bed 100644 --- a/pipeline/test/constructors/test_constructors.jl +++ b/pipeline/test/constructors/test_constructors.jl @@ -17,10 +17,12 @@ end @testset "make_Rt: returns an array" begin using EpiAwarePipeline - pipeline = EpiAwareExamplePipeline() - Rt = make_Rt(pipeline) - @test Rt isa Array + map([EpiAwareExamplePipeline(), SmoothOutbreakPipeline(), + MeasuresOutbreakPipeline(), SmoothEndemicPipeline(), RoughEndemicPipeline()]) do pipeline + Rt = make_Rt(pipeline) + @test Rt isa Array + end end @testset "default_tspan: returns an Tuple{Integer, Integer}" begin @@ -85,7 +87,7 @@ end @testset "make_truth_data_configs" begin using EpiAwarePipeline - pipeline = RtwithoutRenewalPipeline() + pipeline = SmoothOutbreakPipeline() example_pipeline = EpiAwareExamplePipeline() @testset "make_truth_data_configs should return a dictionary" begin config_dicts = make_truth_data_configs(pipeline) @@ -107,7 +109,7 @@ end @testset "default inference configurations" begin using EpiAwarePipeline - pipeline = RtwithoutRenewalPipeline() + pipeline = SmoothOutbreakPipeline() example_pipeline = EpiAwareExamplePipeline() @testset "make_inference_configs should return a vector of dictionaries" begin @@ -133,7 +135,7 @@ end @testset "make_default_params" begin using EpiAwarePipeline - pipeline = RtwithoutRenewalPipeline() + pipeline = SmoothOutbreakPipeline() # Expected default parameters expected_params = Dict( @@ -151,7 +153,8 @@ end end @testset "make_delay_distribution" begin - pipeline = RtwithoutRenewalPipeline() + using EpiAwarePipeline, Distributions + pipeline = SmoothOutbreakPipeline() delay_distribution = make_delay_distribution(pipeline) @test delay_distribution isa Distribution @test delay_distribution isa Gamma @@ -162,7 +165,7 @@ end @testset "make_observation_model" begin using EpiAware # Mock pipeline object - pipeline = RtwithoutRenewalPipeline() + pipeline = SmoothOutbreakPipeline() default_params = make_default_params(pipeline) obs = make_observation_model(pipeline) diff --git a/pipeline/test/forecast/test_forecast.jl b/pipeline/test/forecast/test_forecast.jl index c428b9232..ef1f1d227 100644 --- a/pipeline/test/forecast/test_forecast.jl +++ b/pipeline/test/forecast/test_forecast.jl @@ -1,6 +1,6 @@ @testset "define_forecast_epiprob" begin using EpiAwarePipeline - pipeline = RtwithoutRenewalPipeline() + pipeline = SmoothOutbreakPipeline() inference_configs = make_inference_configs(pipeline) diff --git a/pipeline/test/infer/test_InferenceConfig.jl b/pipeline/test/infer/test_InferenceConfig.jl index bdb2bd7ef..b49139fe9 100644 --- a/pipeline/test/infer/test_InferenceConfig.jl +++ b/pipeline/test/infer/test_InferenceConfig.jl @@ -41,7 +41,7 @@ end @testset "construct from config dictionary" begin - pipeline = RtwithoutRenewalPipeline() + pipeline = SmoothOutbreakPipeline() inference_configs = make_inference_configs(pipeline) @test [InferenceConfig(ic; case_data, tspan, epimethod) isa InferenceConfig for ic in inference_configs] |> all diff --git a/pipeline/test/infer/test_define_epiprob.jl b/pipeline/test/infer/test_define_epiprob.jl index 61db6bbd2..de541ba80 100644 --- a/pipeline/test/infer/test_define_epiprob.jl +++ b/pipeline/test/infer/test_define_epiprob.jl @@ -1,6 +1,6 @@ @testset "test define_epiprob" begin using EpiAwarePipeline - pipeline = RtwithoutRenewalPipeline() + pipeline = SmoothOutbreakPipeline() inference_configs = make_inference_configs(pipeline) diff --git a/pipeline/test/pipeline/test_pipelinetypes.jl b/pipeline/test/pipeline/test_pipelinetypes.jl index f25cecdbd..d36f8332d 100644 --- a/pipeline/test/pipeline/test_pipelinetypes.jl +++ b/pipeline/test/pipeline/test_pipelinetypes.jl @@ -3,9 +3,20 @@ @testset "AbstractEpiAwarePipeline" begin @test_throws MethodError AbstractEpiAwarePipeline() end - @testset "RtwithoutRenewalPipeline" begin - @test isa(RtwithoutRenewalPipeline(), RtwithoutRenewalPipeline) - @test RtwithoutRenewalPipeline <: AbstractEpiAwarePipeline + @testset "AbstractEpiAwarePipeline" begin + @test_throws MethodError AbstractRtwithoutRenewalPipeline() + end + + @testset "RtwithoutRenewalPipeline subtypes" begin + concrete_scenario_pipes = [ + SmoothOutbreakPipeline(), + MeasuresOutbreakPipeline(), + SmoothEndemicPipeline(), + RoughEndemicPipeline() + ] + map(concrete_scenario_pipes) do pipeline + @test pipeline isa AbstractRtwithoutRenewalPipeline + end end @testset "RtwithoutRenewalPriorPipeline" begin @test isa(RtwithoutRenewalPriorPipeline(), RtwithoutRenewalPriorPipeline) diff --git a/pipeline/test/runtests.jl b/pipeline/test/runtests.jl index d7c8200d9..a6343eb8a 100644 --- a/pipeline/test/runtests.jl +++ b/pipeline/test/runtests.jl @@ -3,7 +3,7 @@ quickactivate(@__DIR__(), "EpiAwarePipeline") # Run tests include("pipeline/test_pipelinetypes.jl"); -include("pipeline/test_pipelinefunctions.jl"); +# include("pipeline/test_pipelinefunctions.jl"); include("utils/test_calculate_processes.jl"); include("constructors/test_constructors.jl"); include("simulate/test_TruthSimulationConfig.jl"); From 26822f44f4bbf9f6aeaac0aa6cbe4edd1ba2132a Mon Sep 17 00:00:00 2001 From: Samuel Brand <48288458+SamuelBrand1@users.noreply.github.com> Date: Fri, 5 Jul 2024 13:53:11 +0100 Subject: [PATCH 5/5] Fix random seed for _apply_method test (#334) --- EpiAware/test/EpiInference/NUTSampler.jl | 3 ++- EpiAware/test/Project.toml | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/EpiAware/test/EpiInference/NUTSampler.jl b/EpiAware/test/EpiInference/NUTSampler.jl index a5558e602..eec593903 100644 --- a/EpiAware/test/EpiInference/NUTSampler.jl +++ b/EpiAware/test/EpiInference/NUTSampler.jl @@ -8,7 +8,8 @@ end @testitem "NUTSampler __apply_method" begin - using Turing, Suppressor, HypothesisTests + using Turing, Suppressor, HypothesisTests, Random + Random.seed!(1234) @model function test_mdl() x ~ Normal(0, 1) end diff --git a/EpiAware/test/Project.toml b/EpiAware/test/Project.toml index 8922ac0f2..f944a2595 100644 --- a/EpiAware/test/Project.toml +++ b/EpiAware/test/Project.toml @@ -10,6 +10,7 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688" MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d" Pathfinder = "b1d3bc72-d0e7-4279-b92f-7fa5d6d2d454" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"