diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 000000000..3dd262291 --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,19 @@ +^.*\.Rproj$ +^\.Rproj\.user$ +^LICENSE\.md$ +^\.github$ +^codecov\.yml$ +^README\.Rmd$ +^_pkgdown\.yml$ +^docs$ +^pkgdown$ +^CODE_OF_CONDUCT\.md$ +^doc$ +^Meta$ +^.lintr$ +^CITATION\.cff$ +^data-raw$ +^tools$ +^vignettes/*.orig$ +^vignettes/figure$ +^vignettes/articles$ diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..13d495acb --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.bib -linguist-detectable diff --git a/.github/.gitignore b/.github/.gitignore new file mode 100644 index 000000000..2d19fc766 --- /dev/null +++ b/.github/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml new file mode 100644 index 000000000..62b0eff0b --- /dev/null +++ b/.github/workflows/R-CMD-check.yaml @@ -0,0 +1,94 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +# +# Reproduce locally by running: +# ```r +# pak::pak(c("any::rcmdcheck", "."), dependencies = "Config/Needs/check") +# rcmdcheck::rcmdcheck() +# ``` +on: + push: + branches: [main, master] + paths: + - 'data/**' + - 'R/**' + - 'inst/**' + - 'man/**' + - 'src/**' + - 'tests/**' + - 'vignettes/**' + - 'DESCRIPTION' + - 'NAMESPACE' + - 'LICENSE' + - '.Rbuildignore' + - '.github/workflows/R-CMD-check.yaml' + merge_group: + pull_request: + paths: + - 'data/**' + - 'R/**' + - 'inst/**' + - 'man/**' + - 'src/**' + - 'tests/**' + - 'vignettes/**' + - 'DESCRIPTION' + - 'NAMESPACE' + - 'LICENSE' + - '.Rbuildignore' + - '.github/workflows/R-CMD-check.yaml' + +name: R-CMD-check + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - {os: macOS-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 + id: rcmdcheck + with: + upload-snapshots: true + error-on: '"note"' + + # fail-fast but only if rcmdcheck step fails + - name: Manual fail-fast + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: always() && steps.rcmdcheck.outcome == 'failure' + run: gh run cancel ${{ github.run_id }} diff --git a/.github/workflows/dependency-change.yaml b/.github/workflows/dependency-change.yaml new file mode 100644 index 000000000..90eb1bd00 --- /dev/null +++ b/.github/workflows/dependency-change.yaml @@ -0,0 +1,82 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + pull_request: + paths: + - 'DESCRIPTION' + +name: Analyze dependency changes + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + pull-requests: write + +jobs: + dependency-changes: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Setup R + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - name: Install dependencies + uses: r-lib/actions/setup-r-dependencies@v2 + with: + packages: any::pak, glue, gh + + - name: Analyze dependency changes + shell: Rscript {0} + run: | + deps_base <- pak::pkg_deps("${{ github.repository }}@${{ github.base_ref }}", dependencies = TRUE) |> + subset(!directpkg) |> + subset(is.na(priority)) + # We install from PR number rather than branch to deal with the case + # of PR coming from forks + deps_head <- pak::pkg_deps("${{ github.repository }}#${{ github.event.number }}", dependencies = TRUE) |> + subset(!directpkg) |> + subset(is.na(priority)) + + deps_added <- deps_head |> + subset(!ref %in% deps_base$ref) + + deps_removed <- deps_base |> + subset(!ref %in% deps_head$ref) + + if (nrow(deps_added) + nrow(deps_removed) > 0) { + + message("Dependencies have changed! Analyzing...") + + if (nrow(deps_added) > 0) { + nudge <- "Reach out on slack (`#code-review` or `#help` channels) to double check if there are base R alternatives to the new dependencies.\n" + } else { + nudge <- "" + } + + msg <- glue::glue( + .sep = "\n", + "This pull request:", + "- Adds {nrow(deps_added)} new dependencies (direct and indirect)", + "- Adds {length(unique(deps_added$sysreqs))} new system dependencies", + "- Removes {nrow(deps_removed)} existing dependencies (direct and indirect)", + "- Removes {length(unique(deps_removed$sysreqs))} existing system dependencies", + "", + nudge, + "(Note that results may be inaccurate if you branched from an outdated version of the target branch.)" + ) + + message("Posting results as a pull request comment.") + + gh::gh( + "POST /repos/{repo}/issues/{issue_number}/comments", + repo = "${{ github.repository }}", + issue_number = "${{ github.event.number }}", + body = msg + ) + + } \ No newline at end of file diff --git a/.github/workflows/lint-changed-files.yaml b/.github/workflows/lint-changed-files.yaml new file mode 100644 index 000000000..cf5c34b63 --- /dev/null +++ b/.github/workflows/lint-changed-files.yaml @@ -0,0 +1,53 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + workflow_dispatch: + pull_request: + branches: [main, master] + paths: + - '**.R' + - '**.Rmd' + - '**/.lintr' + - '**/.lintr.R' + +name: lint-changed-files + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint-changed-files: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: | + any::gh + any::lintr + any::purrr + any::cyclocomp + epiverse-trace/etdev + needs: check + + - name: Install package + run: R CMD INSTALL . + + - name: Extract and lint files changed by this PR + run: | + files <- gh::gh("/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files") + changed_files <- purrr::map_chr(files, "filename") + all_files <- list.files(recursive = TRUE) + exclusions_list <- as.list(setdiff(all_files, changed_files)) + lintr::lint_package(exclusions = exclusions_list) + shell: Rscript {0} + env: + LINTR_ERROR_ON_LINT: true diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml new file mode 100644 index 000000000..fc9784378 --- /dev/null +++ b/.github/workflows/pkgdown.yaml @@ -0,0 +1,90 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +# +# Reproduce locally by running: +# ```r +# pak::pak(c("any::pkgdown", "."), dependencies = "Config/Needs/website") +# pkgdown::build_site() +# ``` +on: + push: + branches: [main, master] + paths: + - 'README.Rmd' + - 'README.md' + - 'index.Rmd' + - 'index.md' + - 'man/**' + - 'vignettes/**' + - '_pkgdown.yml' + - 'pkgdown/**' + - 'DESCRIPTION' + - '.Rbuildignore' + - '.github/**' + merge_group: + pull_request: + paths: + - 'README.Rmd' + - 'README.md' + - 'index.Rmd' + - 'index.md' + - 'man/**' + - 'vignettes/**' + - '_pkgdown.yml' + - 'pkgdown/**' + - 'DESCRIPTION' + - '.Rbuildignore' + - '.github/**' + release: + types: [published] + workflow_dispatch: + +name: pkgdown + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write + +jobs: + pkgdown: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::pkgdown, local::. + needs: website + + - name: Build site + run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) + shell: Rscript {0} + + - name: Check website links + uses: untitaker/hyperlink@0.1.32 + with: + args: docs/ + + - name: Deploy to GitHub pages 🚀 + if: github.event_name != 'merge_group' && github.event_name != 'pull_request' + uses: JamesIves/github-pages-deploy-action@v4.6.1 + with: + # We clean on releases because we want to remove old vignettes, + # figures, etc. that have been deleted from the `main` branch. + # But we clean ONLY on releases because we want to be able to keep + # both the 'stable' and 'dev' websites. + # Also discussed in https://github.com/r-lib/actions/issues/484 + clean: ${{ github.event_name == 'release' }} + branch: gh-pages + folder: docs diff --git a/.github/workflows/render_readme.yml b/.github/workflows/render_readme.yml new file mode 100644 index 000000000..10f5eaadf --- /dev/null +++ b/.github/workflows/render_readme.yml @@ -0,0 +1,96 @@ +# Reproduce locally by running: +# ```r +# pak::pak(c("any::rmarkdown", "any::usethis", ".")) +# writeLines( +# knitr::knit_expand( +# "README.Rmd", +# packagename = read.dcf("DESCRIPTION", "Package"), +# gh_repo = usethis:::github_remote_list()$repo_spec +# ), +# "README_expanded.Rmd" +# ) +# rmarkdown::render( +# "README_expanded.Rmd", +# output_file = "README.md", +# output_dir = "." +# ) +# unlink("README_expanded.Rmd") +# ``` +name: render-readme + +# Controls when the action will run. Triggers include: +# +# - button trigger from github action page +# - on changes to readme.Rmd + +on: + workflow_dispatch: + push: + branches: + # This may seem like a no-op but it prevents triggering on tags + # We use '**' rather '*' to accomodate names like 'dev/branch-1' + - '**' + paths: + - 'README.Rmd' + - '.github/workflows/render_readme.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + render-readme: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout repos + uses: actions/checkout@v4 + + - name: Setup R + uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - name: Setup pandoc + uses: r-lib/actions/setup-pandoc@v2 + + - name: Install dependencies + uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rmarkdown, local::. + + - name: Compile the readme + run: | + writeLines( + knitr::knit_expand( + "README.Rmd", + packagename = read.dcf("DESCRIPTION", "Package"), + gh_repo = Sys.getenv("GITHUB_REPOSITORY") + ), + "README_expanded.Rmd" + ) + rmarkdown::render( + "README_expanded.Rmd", + output_file = "README.md", + output_dir = "." + ) + shell: Rscript {0} + + - name: Commit files + run: | + git config --local user.email "action@github.com" + git config --local user.name "GitHub Action" + git add README.md + # Also add README figures if they exist + if [ -d man/figures ] + then + git add man/figures/ + fi + git diff-index --quiet HEAD || git commit -m "Automatic readme update" + git pull --rebase origin ${{ github.ref.name }} + git push origin || echo "No changes to push" diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml new file mode 100644 index 000000000..afd8f0417 --- /dev/null +++ b/.github/workflows/test-coverage.yaml @@ -0,0 +1,85 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +# +# Reproduce locally by running: +# ```r +# pak::pak("any::covr", dependencies = "Config/Needs/coverage") +# covr::codecov(quiet = FALSE) +# ``` +on: + push: + branches: [main, master] + paths: + - 'R/**' + - 'src/**' + - 'tests/**' + - 'inst/**' + - 'DESCRIPTION' + - '.github/workflows/test-coverage.yaml' + merge_group: + pull_request: + paths: + - 'R/**' + - 'src/**' + - 'tests/**' + - 'inst/**' + - 'DESCRIPTION' + - '.github/workflows/test-coverage.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +name: test-coverage + +permissions: read-all + +jobs: + test-coverage: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::covr, any::xml2 + needs: coverage + + - name: Test coverage + run: | + cov <- covr::package_coverage( + quiet = FALSE, + clean = FALSE, + install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") + ) + covr::to_cobertura(cov) + shell: Rscript {0} + + - uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: ${{ github.event_name != 'pull_request' && true || false }} + file: ./cobertura.xml + plugin: noop + disable_search: true + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Show testthat output + if: always() + run: | + ## -------------------------------------------------------------------- + find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true + shell: bash + + - name: Upload test results + if: failure() + uses: actions/upload-artifact@v4 + with: + name: coverage-test-failures + path: ${{ runner.temp }}/package diff --git a/.github/workflows/update-citation-cff.yaml b/.github/workflows/update-citation-cff.yaml new file mode 100644 index 000000000..6c841b04d --- /dev/null +++ b/.github/workflows/update-citation-cff.yaml @@ -0,0 +1,59 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/master/examples +# The action runs when: +# - The DESCRIPTION or inst/CITATION are modified +# - Can be run manually +# For customizing the triggers, visit https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows +on: + push: + branches: + - main + paths: + - DESCRIPTION + - inst/CITATION + - .github/workflows/update-citation-cff.yaml + workflow_dispatch: + +name: Update CITATION.cff +permissions: + contents: write + pull-requests: write + +jobs: + update-citation-cff: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + - uses: r-lib/actions/setup-r@v2 + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: | + any::cffr + any::V8 + + - name: Update CITATION.cff + run: | + + library(cffr) + + # Customize with your own code + # See https://docs.ropensci.org/cffr/articles/cffr.html + + # Write your own keys + mykeys <- list() + + # Create your CITATION.cff file + cff_write(keys = mykeys) + + shell: Rscript {0} + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + commit-message: Update `CITATION.cff` + title: Update `CITATION.cff` + body: | + This pull request updates the citation file, ensuring all authors are credited and there are no discrepancies. + + Please verify the changes before merging. + branch: update-citation-cff diff --git a/.github/workflows/update-copyright-year.yml b/.github/workflows/update-copyright-year.yml new file mode 100644 index 000000000..0d7d346dc --- /dev/null +++ b/.github/workflows/update-copyright-year.yml @@ -0,0 +1,37 @@ +name: Update copyright year(s) in license file + +on: + workflow_dispatch: + schedule: + - cron: '0 3 1 1 *' + +permissions: + contents: write + pull-requests: write + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: FantasticFiasco/action-update-license-year@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + path: | + LICENSE.md + prBody: > + This PR updates the copyright license for this new year! If you're reading this while you're celebrating, enjoy! Don't worry about this one :blush: + + ![Happy new year!](https://media.giphy.com/media/HyDfNCZlTn5iU/giphy.gif?cid=ecf05e4777yl7dbo1xfha6bx1z5lrl13uq7biv6rs9dqsyoh&ep=v1_gifs_search&rid=giphy.gif&ct=g) + - uses: FantasticFiasco/action-update-license-year@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + path: | + LICENSE + prBody: > + This PR updates the copyright license for this new year! If you're reading this while you're celebrating, enjoy! Don't worry about this one :blush: + + ![Happy new year!](https://media.giphy.com/media/HyDfNCZlTn5iU/giphy.gif?cid=ecf05e4777yl7dbo1xfha6bx1z5lrl13uq7biv6rs9dqsyoh&ep=v1_gifs_search&rid=giphy.gif&ct=g) + transform: (?<=YEAR:\s)(?\d{4})?-?(\d{4})? diff --git a/.github/workflows/validate-json.yaml b/.github/workflows/validate-json.yaml new file mode 100644 index 000000000..1c18b4f41 --- /dev/null +++ b/.github/workflows/validate-json.yaml @@ -0,0 +1,47 @@ +name: Validate JSONs + +on: + push: + branches: [main, master] + paths: + - 'R/sysdata.rda' + - 'inst/extdata/**' + - 'data-raw/parameters.R' + - '.github/workflows/validate-json.yaml' + merge_group: + pull_request: + paths: + - 'R/sysdata.rda' + - 'inst/extdata/**' + - 'data-raw/parameters.R' + - '.github/workflows/validate-json.yaml' + +jobs: + validate-json: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + packages: + any::jsonvalidate + + - name: Validate JSON + run: | + jsonvalidate::json_validate( + json = file.path("inst", "extdata", "parameters.json"), + schema = file.path("inst", "extdata", "data_dictionary.json"), + engine = "ajv", + verbose = TRUE, + greedy = TRUE, + strict = FALSE, + error = TRUE + ) + shell: Rscript {0} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..310a47d8b --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +# History files +.Rhistory +.Rapp.history + +# Session Data files +.RData +.RDataTmp + +# User-specific files +.Ruserdata + +# Example code in package build process +*-Ex.R + +# Output files from R CMD build +/*.tar.gz + +# Output files from R CMD check +/*.Rcheck/ + +# RStudio files +.Rproj.user/ + +# vignette building +/doc/ +/Meta/ + +# produced vignettes +vignettes/*.html +vignettes/*.pdf + +# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 +.httr-oauth + +# knitr and R markdown default cache directories +*_cache/ +/cache/ + +# Temporary files created by R markdown +*.utf8.md +*.knit.md + +# R Environment Variables +.Renviron + +# pkgdown site +docs/ + +# translation temp files +po/*~ + +# RStudio Connect folder +rsconnect/ + +# macOS hidden files +.DS_Store +inst/doc diff --git a/.lintr b/.lintr new file mode 100644 index 000000000..5f69e9d88 --- /dev/null +++ b/.lintr @@ -0,0 +1,40 @@ +linters: all_linters( + packages = c("lintr", "etdev"), + object_name_linter = NULL, + implicit_integer_linter = NULL, + extraction_operator_linter = NULL, + todo_comment_linter = NULL, + library_call_linter = NULL, + undesirable_function_linter( + modify_defaults( + default_undesirable_functions, + citEntry = "use the more modern bibentry() function", + library = NULL, # too many false positive in too many files + structure = NULL, # used for class constructor functions + par = NULL # used with on.exit() and {withrs} is not a dependency + ) + ), + function_argument_linter = NULL, + indentation_linter = NULL, # unstable as of lintr 3.1.0 + # Use minimum R declared in DESCRIPTION or fall back to current R version. + # Install etdev package from https://github.com/epiverse-trace/etdev + backport_linter(if (length(x <- etdev::extract_min_r_version())) x else getRversion()) + ) +exclusions: list( + "tests/testthat.R" = list( + unused_import_linter = Inf + ), + "tests" = list( + undesirable_function_linter = Inf + ), + "data-raw" = list( + missing_package_linter = Inf, + namespace_linter = Inf + ), + # RcppExports.R is auto-generated and will not pass many linters. In + # particular, it can create very long lines. + "R/RcppExports.R", + # R/stanmodels.R is auto-generated and will not pass many linters. In + # particular, it uses `sapply()`. + "R/stanmodels.R" + ) diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..e280c660c --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,437 @@ +# -------------------------------------------- +# CITATION file created with {cffr} R package +# See also: https://docs.ropensci.org/cffr/ +# -------------------------------------------- + +cff-version: 1.2.0 +message: 'To cite package "epiparameter" in publications use:' +type: software +license: MIT +title: 'epiparameter: Library of Epidemiological Parameters with Helper Functions + and Classes' +version: 0.2.0.9000 +doi: 10.5281/zenodo.11110881 +identifiers: +- type: url + value: https://epiverse-trace.github.io/epiparameter/ +abstract: Library of epidemiological parameters for infectious diseases and a set + of classes and helper functions. +authors: +- family-names: Lambert + given-names: Joshua W. + email: joshua.lambert@lshtm.ac.uk + orcid: https://orcid.org/0000-0001-5218-3046 +- family-names: Kucharski + given-names: Adam + email: adam.kucharski@lshtm.ac.uk + orcid: https://orcid.org/0000-0001-8814-9421 +- family-names: Tamayo + given-names: Carmen + email: carmen.tamayo-cuartero@lshtm.ac.uk + orcid: https://orcid.org/0000-0003-4184-2864 +preferred-citation: + type: manual + title: 'epiparameter: Library of Epidemiological Parameters with Helper Functions + and Classes' + authors: + - family-names: Lambert + given-names: Joshua W. + email: joshua.lambert@lshtm.ac.uk + orcid: https://orcid.org/0000-0001-5218-3046 + - family-names: Kucharski + given-names: Adam + email: adam.kucharski@lshtm.ac.uk + orcid: https://orcid.org/0000-0001-8814-9421 + - family-names: Tamayo + given-names: Carmen + email: carmen.tamayo-cuartero@lshtm.ac.uk + orcid: https://orcid.org/0000-0003-4184-2864 + year: '2024' + doi: 10.5281/zenodo.11110881 + url: https://epiverse-trace.github.io/epiparameter +repository-code: https://github.com/epiverse-trace/epiparameter +url: https://github.com/epiverse-trace/epiparameter/ +contact: +- family-names: Lambert + given-names: Joshua W. + email: joshua.lambert@lshtm.ac.uk + orcid: https://orcid.org/0000-0001-5218-3046 +keywords: +- data-access +- data-package +- epidemiology +- epiverse +- probability-distribution +- r +- r-package +references: +- type: software + title: 'R: A Language and Environment for Statistical Computing' + notes: Depends + url: https://www.R-project.org/ + authors: + - name: R Core Team + institution: + name: R Foundation for Statistical Computing + address: Vienna, Austria + year: '2024' + version: '>= 4.1.0' +- type: software + title: checkmate + abstract: 'checkmate: Fast and Versatile Argument Checks' + notes: Imports + url: https://mllg.github.io/checkmate/ + repository: https://CRAN.R-project.org/package=checkmate + authors: + - family-names: Lang + given-names: Michel + email: michellang@gmail.com + orcid: https://orcid.org/0000-0001-9754-0393 + year: '2024' + doi: 10.32614/CRAN.package.checkmate +- type: software + title: cli + abstract: 'cli: Helpers for Developing Command Line Interfaces' + notes: Imports + url: https://cli.r-lib.org + repository: https://CRAN.R-project.org/package=cli + authors: + - family-names: Csárdi + given-names: Gábor + email: csardi.gabor@gmail.com + year: '2024' + doi: 10.32614/CRAN.package.cli +- type: software + title: distcrete + abstract: 'distcrete: Discrete Distribution Approximations' + notes: Imports + url: https://github.com/reconhub/distcrete + repository: https://CRAN.R-project.org/package=distcrete + authors: + - family-names: FitzJohn + given-names: Rich + email: rich.fitzjohn@gmail.com + - family-names: Cori + given-names: Anne + - family-names: Jombart + given-names: Thibaut + year: '2024' + doi: 10.32614/CRAN.package.distcrete +- type: software + title: distributional + abstract: 'distributional: Vectorised Probability Distributions' + notes: Imports + url: https://pkg.mitchelloharawild.com/distributional/ + repository: https://CRAN.R-project.org/package=distributional + authors: + - family-names: O'Hara-Wild + given-names: Mitchell + email: mail@mitchelloharawild.com + orcid: https://orcid.org/0000-0001-6729-7695 + - family-names: Kay + given-names: Matthew + orcid: https://orcid.org/0000-0001-9446-0419 + - family-names: Hayes + given-names: Alex + orcid: https://orcid.org/0000-0002-4985-5160 + - family-names: Hyndman + given-names: Rob + orcid: https://orcid.org/0000-0002-2140-5352 + year: '2024' + doi: 10.32614/CRAN.package.distributional +- type: software + title: graphics + abstract: 'R: A Language and Environment for Statistical Computing' + notes: Imports + authors: + - name: R Core Team + institution: + name: R Foundation for Statistical Computing + address: Vienna, Austria + year: '2024' +- type: software + title: lifecycle + abstract: 'lifecycle: Manage the Life Cycle of your Package Functions' + notes: Imports + url: https://lifecycle.r-lib.org/ + repository: https://CRAN.R-project.org/package=lifecycle + authors: + - family-names: Henry + given-names: Lionel + email: lionel@posit.co + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + orcid: https://orcid.org/0000-0003-4757-117X + year: '2024' + doi: 10.32614/CRAN.package.lifecycle +- type: software + title: pillar + abstract: 'pillar: Coloured Formatting for Columns' + notes: Imports + url: https://pillar.r-lib.org/ + repository: https://CRAN.R-project.org/package=pillar + authors: + - family-names: Müller + given-names: Kirill + email: kirill@cynkra.com + orcid: https://orcid.org/0000-0002-1416-3412 + - family-names: Wickham + given-names: Hadley + year: '2024' + doi: 10.32614/CRAN.package.pillar +- type: software + title: rlang + abstract: 'rlang: Functions for Base Types and Core R and ''Tidyverse'' Features' + notes: Imports + url: https://rlang.r-lib.org + repository: https://CRAN.R-project.org/package=rlang + authors: + - family-names: Henry + given-names: Lionel + email: lionel@posit.co + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + year: '2024' + doi: 10.32614/CRAN.package.rlang +- type: software + title: stats + abstract: 'R: A Language and Environment for Statistical Computing' + notes: Imports + authors: + - name: R Core Team + institution: + name: R Foundation for Statistical Computing + address: Vienna, Austria + year: '2024' +- type: software + title: utils + abstract: 'R: A Language and Environment for Statistical Computing' + notes: Imports + authors: + - name: R Core Team + institution: + name: R Foundation for Statistical Computing + address: Vienna, Austria + year: '2024' +- type: software + title: bookdown + abstract: 'bookdown: Authoring Books and Technical Documents with R Markdown' + notes: Suggests + url: https://pkgs.rstudio.com/bookdown/ + repository: https://CRAN.R-project.org/package=bookdown + authors: + - family-names: Xie + given-names: Yihui + email: xie@yihui.name + orcid: https://orcid.org/0000-0003-0645-5666 + year: '2024' + doi: 10.32614/CRAN.package.bookdown +- type: software + title: DT + abstract: 'DT: A Wrapper of the JavaScript Library ''DataTables''' + notes: Suggests + url: https://github.com/rstudio/DT + repository: https://CRAN.R-project.org/package=DT + authors: + - family-names: Xie + given-names: Yihui + - family-names: Cheng + given-names: Joe + email: joe@posit.co + - family-names: Tan + given-names: Xianying + year: '2024' + doi: 10.32614/CRAN.package.DT +- type: software + title: ggplot2 + abstract: 'ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics' + notes: Suggests + url: https://ggplot2.tidyverse.org + repository: https://CRAN.R-project.org/package=ggplot2 + authors: + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + orcid: https://orcid.org/0000-0003-4757-117X + - family-names: Chang + given-names: Winston + orcid: https://orcid.org/0000-0002-1576-2126 + - family-names: Henry + given-names: Lionel + - family-names: Pedersen + given-names: Thomas Lin + email: thomas.pedersen@posit.co + orcid: https://orcid.org/0000-0002-5147-4711 + - family-names: Takahashi + given-names: Kohske + - family-names: Wilke + given-names: Claus + orcid: https://orcid.org/0000-0002-7470-9261 + - family-names: Woo + given-names: Kara + orcid: https://orcid.org/0000-0002-5125-4188 + - family-names: Yutani + given-names: Hiroaki + orcid: https://orcid.org/0000-0002-3385-7233 + - family-names: Dunnington + given-names: Dewey + orcid: https://orcid.org/0000-0002-9415-4582 + - family-names: Brand + given-names: Teun + name-particle: van den + orcid: https://orcid.org/0000-0002-9335-7468 + year: '2024' + doi: 10.32614/CRAN.package.ggplot2 +- type: software + title: RColorBrewer + abstract: 'RColorBrewer: ColorBrewer Palettes' + notes: Suggests + repository: https://CRAN.R-project.org/package=RColorBrewer + authors: + - family-names: Neuwirth + given-names: Erich + email: erich.neuwirth@univie.ac.at + year: '2024' + doi: 10.32614/CRAN.package.RColorBrewer +- type: software + title: jsonlite + abstract: 'jsonlite: A Simple and Robust JSON Parser and Generator for R' + notes: Suggests + url: https://jeroen.r-universe.dev/jsonlite + repository: https://CRAN.R-project.org/package=jsonlite + authors: + - family-names: Ooms + given-names: Jeroen + email: jeroenooms@gmail.com + orcid: https://orcid.org/0000-0002-4035-0289 + year: '2024' + doi: 10.32614/CRAN.package.jsonlite +- type: software + title: knitr + abstract: 'knitr: A General-Purpose Package for Dynamic Report Generation in R' + notes: Suggests + url: https://yihui.org/knitr/ + repository: https://CRAN.R-project.org/package=knitr + authors: + - family-names: Xie + given-names: Yihui + email: xie@yihui.name + orcid: https://orcid.org/0000-0003-0645-5666 + year: '2024' + doi: 10.32614/CRAN.package.knitr +- type: software + title: rmarkdown + abstract: 'rmarkdown: Dynamic Documents for R' + notes: Suggests + url: https://pkgs.rstudio.com/rmarkdown/ + repository: https://CRAN.R-project.org/package=rmarkdown + authors: + - family-names: Allaire + given-names: JJ + email: jj@posit.co + - family-names: Xie + given-names: Yihui + email: xie@yihui.name + orcid: https://orcid.org/0000-0003-0645-5666 + - family-names: Dervieux + given-names: Christophe + email: cderv@posit.co + orcid: https://orcid.org/0000-0003-4474-2498 + - family-names: McPherson + given-names: Jonathan + email: jonathan@posit.co + - family-names: Luraschi + given-names: Javier + - family-names: Ushey + given-names: Kevin + email: kevin@posit.co + - family-names: Atkins + given-names: Aron + email: aron@posit.co + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + - family-names: Cheng + given-names: Joe + email: joe@posit.co + - family-names: Chang + given-names: Winston + email: winston@posit.co + - family-names: Iannone + given-names: Richard + email: rich@posit.co + orcid: https://orcid.org/0000-0003-3925-190X + year: '2024' + doi: 10.32614/CRAN.package.rmarkdown +- type: software + title: spelling + abstract: 'spelling: Tools for Spell Checking in R' + notes: Suggests + url: https://ropensci.r-universe.dev/spelling + repository: https://CRAN.R-project.org/package=spelling + authors: + - family-names: Ooms + given-names: Jeroen + email: jeroenooms@gmail.com + orcid: https://orcid.org/0000-0002-4035-0289 + - family-names: Hester + given-names: Jim + email: james.hester@rstudio.com + year: '2024' + doi: 10.32614/CRAN.package.spelling +- type: software + title: testthat + abstract: 'testthat: Unit Testing for R' + notes: Suggests + url: https://testthat.r-lib.org + repository: https://CRAN.R-project.org/package=testthat + authors: + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + year: '2024' + doi: 10.32614/CRAN.package.testthat + version: '>= 3.0.0' +- type: software + title: vdiffr + abstract: 'vdiffr: Visual Regression Testing and Graphical Diffing' + notes: Suggests + url: https://vdiffr.r-lib.org/ + repository: https://CRAN.R-project.org/package=vdiffr + authors: + - family-names: Henry + given-names: Lionel + email: lionel@posit.co + - family-names: Pedersen + given-names: Thomas Lin + email: thomas.pedersen@posit.co + orcid: https://orcid.org/0000-0002-5147-4711 + - family-names: Luciani + given-names: T Jake + email: jake@apache.org + - family-names: Decorde + given-names: Matthieu + email: matthieu.decorde@ens-lyon.fr + - family-names: Lise + given-names: Vaudor + email: lise.vaudor@ens-lyon.fr + year: '2024' + doi: 10.32614/CRAN.package.vdiffr + version: '>= 1.0.7' +- type: software + title: visNetwork + abstract: 'visNetwork: Network Visualization using ''vis.js'' Library' + notes: Suggests + url: https://datastorm-open.github.io/visNetwork/ + repository: https://CRAN.R-project.org/package=visNetwork + authors: + - name: Almende B.V. and Contributors + website: https://visjs.org/ + - family-names: Thieurmel + given-names: Benoit + email: bthieurmel@gmail.com + year: '2024' + doi: 10.32614/CRAN.package.visNetwork + diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 000000000..6c9fe29e5 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,60 @@ +Package: epiparameter +Title: Library of Epidemiological Parameters with Helper Functions and + Classes +Version: 0.2.0.9000 +Authors@R: c( + person("Joshua W.", "Lambert", , "joshua.lambert@lshtm.ac.uk", role = c("aut", "cre", "cph"), + comment = c(ORCID = "0000-0001-5218-3046")), + person("Adam", "Kucharski", , "adam.kucharski@lshtm.ac.uk", role = c("aut", "cph"), + comment = c(ORCID = "0000-0001-8814-9421")), + person("Carmen", "Tamayo", , "carmen.tamayo-cuartero@lshtm.ac.uk", role = "aut", + comment = c(ORCID = "0000-0003-4184-2864")), + person("Hugo", "Gruson", , "hugo.gruson@data.org", role = c("ctb", "rev"), + comment = c(ORCID = "0000-0002-4094-1476")), + person("Sebastian", "Funk", , "sebastian.funk@lshtm.ac.uk", role = "ctb", + comment = c(ORCID = "0000-0002-2842-3406")), + person("Pratik", "Gupte", , "pratik.gupte@lshtm.ac.uk", role = "rev", + comment = c(ORCID = "0000-0001-5294-7819")) + ) +Description: Library of epidemiological parameters for infectious diseases + and a set of classes and helper functions. +License: MIT + file LICENSE +URL: https://github.com/epiverse-trace/epiparameter/, + https://epiverse-trace.github.io/epiparameter/ +BugReports: https://github.com/epiverse-trace/epiparameter/issues +Depends: + R (>= 4.1.0) +Imports: + checkmate, + cli, + distcrete, + distributional, + graphics, + lifecycle, + pillar, + rlang, + stats, + utils +Suggests: + bookdown, + DT, + ggplot2, + RColorBrewer, + jsonlite, + knitr, + rmarkdown, + spelling, + testthat (>= 3.0.0), + vdiffr (>= 1.0.7), + visNetwork +VignetteBuilder: + knitr +Config/Needs/check: mrc-ide/epireview +Config/Needs/website: epiverse-trace/epiversetheme, mrc-ide/epireview +Config/potools/style: explicit +Config/testthat/edition: 3 +Encoding: UTF-8 +Language: en-GB +LazyData: true +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.3.2 diff --git a/LICENSE b/LICENSE index 69c2e1834..b8493407d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,6 @@ -MIT License - -Copyright (c) 2022 epiverse-trace - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +YEAR: 2024 +COPYRIGHT HOLDER: epiparameter authors +DATA LICENSE: All data included in the epiparameter R package is licensed under CC0 + (https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt). This includes the parameter + database (extdata/parameters.json) and data in the data/ folder. Please cite the individual + parameter entries in the database when used. \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..44380f13c --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) 2024 epiparameter authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 000000000..2409665f4 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,71 @@ +# Generated by roxygen2: do not edit by hand + +S3method(aggregate,multi_epiparameter) +S3method(as.data.frame,epiparameter) +S3method(as.data.frame,multi_epiparameter) +S3method(as.function,epiparameter) +S3method(as_epiparameter,data.frame) +S3method(c,epiparameter) +S3method(c,multi_epiparameter) +S3method(cdf,epiparameter) +S3method(convert_params_to_summary_stats,character) +S3method(convert_params_to_summary_stats,epiparameter) +S3method(convert_summary_stats_to_params,character) +S3method(convert_summary_stats_to_params,epiparameter) +S3method(density,epiparameter) +S3method(discretise,default) +S3method(discretise,epiparameter) +S3method(family,epiparameter) +S3method(format,epiparameter) +S3method(generate,epiparameter) +S3method(get_citation,epiparameter) +S3method(get_citation,multi_epiparameter) +S3method(get_parameters,epiparameter) +S3method(get_parameters,multi_epiparameter) +S3method(is_parameterised,epiparameter) +S3method(is_parameterised,multi_epiparameter) +S3method(mean,epiparameter) +S3method(plot,epiparameter) +S3method(print,epiparameter) +S3method(print,multi_epiparameter) +S3method(print,parameter_tbl) +S3method(quantile,epiparameter) +S3method(tbl_sum,p_tbl) +export(as_epiparameter) +export(assert_epiparameter) +export(calc_disc_dist_quantile) +export(cdf) +export(convert_params_to_summary_stats) +export(convert_summary_stats_to_params) +export(create_citation) +export(create_metadata) +export(create_method_assess) +export(create_prob_distribution) +export(create_region) +export(create_summary_stats) +export(create_uncertainty) +export(discretise) +export(discretize) +export(epidist_db) +export(epiparameter) +export(epiparameter_db) +export(extract_param) +export(generate) +export(get_citation) +export(get_parameters) +export(is_continuous) +export(is_epiparameter) +export(is_epiparameter_params) +export(is_parameterised) +export(is_parameterized) +export(is_truncated) +export(parameter_tbl) +export(test_epiparameter) +importFrom(distributional,cdf) +importFrom(distributional,generate) +importFrom(lifecycle,deprecated) +importFrom(pillar,tbl_sum) +importFrom(stats,aggregate) +importFrom(stats,density) +importFrom(stats,family) +importFrom(stats,quantile) diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 000000000..ce595d781 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,110 @@ +# epiparameter (development version) + +The third minor release of the {epiparameter} R package contains a range of updates and improvements to the package. The principal aim of this release is to simplify, clarify and enhance the classes and class methods when working with epidemiological parameters in R. + +The are a large number of ***breaking changes*** in this release, primarily functions and function arguments being renamed or restructured, see the _Breaking changes_ section for an overview. + +## New features + +* The library of epidemiological parameters has been updated to include 3 new Chikungunya parameter entries. The Mpox parameters previously missing from the Guzzetta et al. entry have been added (PR #346 & #374). +* A `c()` method has been added for `` and `` objects. +* An `aggregate()` method has been added for `` to enable consensus distributions to be built utilising the mixture distribution class from [{distributional}](https://cran.r-project.org/web/packages/distributional/index.html) (PR #388). +* Infrastructure has been added to the package to allow translations of messages/warnings/errors printed to the console. (@Bisaloo, PR #367). +* `convert_summary_stats_to_params()` can now convert from median and dispersion for a lognormal distribution (PR #378). +* The `data_dictionary.json` has been enhanced to improve validation of the library of epidemiological parameters (`parameters.json`) (PR #379). +* An interactive network showing all of the `` S3 methods has been added to the `design_principles.Rmd` vignette (PR #383). +* The `data_from_epireview.Rmd` article has been improved and updated with new changes from {epireview} (@CarmenTamayo & @cm401 & @kellymccain28, PR #305 & #373). +* Parameter units have been added to every entry in the {epiparameter} library (`parameters.json`) and to the `$metadata` element in `` objects. The `create_metadata()` function now has a `units` argument to construct metadata lists (PR #391). +* Improved `database.Rmd` vignette by adding a short citation to the reference column (@jamesmbaazam, PR #348). + +## Breaking changes + +* The `` class has been renamed `` to avoid confusion with the similar R package [{epidist}](https://github.com/epinowcast/epidist) (PR #360). +* Many functions that used `epidist` in their names have been renamed to use `epiparameter` due to the renaming of the class (PR #360). +* The function signatures of `epiparameter()` and `new_epiparameter()` functions (previously `epidist()` and `new_epidist()`) have been updated to collapse the `prob_dist`, `prob_dist_params`, `discretise` and `truncation` arguments into `prob_distribution`, which accepts the output of `create_prob_distribution()` (PR #381). +* The `epi_dist` argument has been renamed `epi_name`. This is to clarify that {epiparameter} can work with epidemiological parameters that take a variety of forms (e.g. point estimates, ranges, probability distributions, etc.) (PR #390). +* The `` class and it's methods have been removed from the package. It was not being used and was increasing the complexity and maintenance load of the package (PR #359). +* `create_prob_dist()` has been renamed to `create_prob_distribution()` (PR #381). +* `validate_epiparameter()` (previously `validate_epidist()`) has been renamed `assert_epiparameter()`, and `test_epiparameter()` has been added, with the aim to harmonise design with [{contactmatrix}](https://github.com/socialcontactdata/contactmatrix) (PR #366). +* The minimum version of R required by the package is now 4.1.0 due to the use of the base R pipe (`|>`) in dependencies (PR #384). + +## Bug fixes + +* Epidemiological parameter entries in the library stored with lognormal distributions, parameterised as median and dispersion are now converted to meanlog and sdlog correctly when creating an `` (when `auto_calc_params = TRUE`) (PR #381). + +## Deprecated and defunct + +* `epidist_db()` has been deprecated. It is replaced by `epiparameter_db()`. + +# epiparameter 0.2.0 + +The second release of the {epiparameter} R package focuses on interoperability with the [{epireview} R package](https://mrc-ide.github.io/epireview/). Several functions have been refactored and enhanced. + +This release benefited from feedback from the participants of an [EpiParameter Community workshop hosted by the World Health Organisation](https://who-collaboratory.github.io/collaboratory-epiparameter-community/#/pages/news). + +## New features + +* The `as_epidist()` S3 generic has been added to the package for the coercion of other R objects into `` objects. The `as_epidist.data.frame()` method is added, as well as the internal functions `is_epireview()` which determines if a `` is from {epireview}, and `epireview_to_epidist()` performs the conversion (#298, #334 & #335) + +* The `epireview_core_cols.rda` data is added to the package. This is used to determine whether the input to `as_epidist.data.frame()` is a parameter table from {epireview} as these objects do not have a recognisable class attribute (#298). + +* A new website only vignette (i.e. [article](https://r-pkgs.org/vignettes.html#sec-vignettes-article)) `data_from_epireview.Rmd` is added that explains how to use `as_epidist()` with data from {epireview} (#298 & #335). + +* A new vignette `database.Rmd` is added to the package to provide a web interface to the {epiparameter} library of epidemiological parameters. Contributed by @sbfnk (#311). + +* The plotting method for `` objects (`plot.epidist()`) has been improved to better differentiate continuous from discrete or discretised distributions (#315). + +* `epidist_db(..., single_epidist = TRUE)` now prioritises parameter entries that account for right truncation (#323). + +* `create_epidist_prob_dist()` (previously named `create_prob_dist()`) is now exported and enables more control of discretisation settings by allowing arguments to be passed to `distcrete::distcrete()` via `...` (#324). + +* The `` print method (`print.multi_epidist()`) has been improved to provides object information in the print header, the first few elements of the list or all elements if list is short, and some extra links and advice in the print footer. The design of the print method follows the design pattern of [{pillar}](https://pillar.r-lib.org/index.html) (#326). + +* `` objects and functions that work with `` objects now work with exponential distributions (#333). + +* The package now has an explicit data license: [CC0](https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt) in the `LICENSE` file. + +## Breaking changes + +* `list_distributions()` has been replaced by `parameter_tbl()` which enhances the printing by leveraging {pillar} (#321). + +* The `` plotting method (`plot.vb_epidist()`) has been removed from the package. This provided minimal functionality and was unnecessarily complicating the function signature of `plot.epidist()` (#315). + +## Bug fixes + +* DOI and PMID are lowercase throughout the package to resolve issues with older versions of R (see issue #301) (#317). + +## Deprecated and defunct + +* None + +# epiparameter 0.1.0 + +Initial release of the {epiparameter} R package. {epiparameter} provides: + +1. A library of epidemiological parameters extracted from the literature for a range of diseases. + +2. Functions and classes (with class methods) to work with epidemiological parameters and distributions. + +## New features + +* A library of 122 epidemiological parameter set from the epidemiological literature. This is accessible from the package as system data (`sysdata.rda`, as `epiparameter::multi_epidist`) or as internal data (`inst/extdata/parameters.json`). +* The `epidist_db()` function loads epidemiological parameters from the library. +* Distribution parameter conversion and extraction functions (`convert_params_to_summary_stats()` & `convert_summary_stats_to_params()`, and `extract_param()`). +* An S3 class to work with epidemiological parameters ``. This class has S3 methods to aid users easily work with these data structures. These include printing, plotting, and distribution functions for PDF/PMF, CDF, random number generation and distribution quantiles. The `` class has a constructor function, a validator function, accessors (`get_*()`), checkers (`is_*()`). There is also a `` S3 class for vector-borne parameters, and an internal `` class for improved printing of lists of `` objects. +* The package contains a few utility functions. `list_distributions()` is a helper function to provide information from a list of `` objects in tabular form. `calc_disc_dist_quantile()` calculates the quantiles of a probability distribution based on the vector of probabilities and time data. +* Five vignettes are included in this initial release. One as an introduction to the package (`epiparameter.Rmd`), one as an tutorial on converting and extracting parameters (`extract_convert.Rmd`), one on the protocol used to collect entries for the library of epidemiological parameters (`data_protocol.Rmd`), a design vignette (`design_principles.Rmd`), and a supplementary vignette which quantifies the bias from using the parameter extraction (`extract_param()`) from {epiparameter} (`extract-bias.Rmd`). +* Unit tests and documentation files. +* Continuous integration workflows for R package checks, rendering the README.md, calculating test coverage, deploying the pkgdown website, updates the package citation, linting package code, checking package or system dependency changes, updating copyright year, and validating the parameter library JSON file. + +## Breaking changes + +* None + +## Bug fixes + +* None + +## Deprecated and defunct + +* None diff --git a/R/accessors.R b/R/accessors.R new file mode 100644 index 000000000..ebf06ed1e --- /dev/null +++ b/R/accessors.R @@ -0,0 +1,171 @@ +#' Get parameters from an object +#' +#' Extract the parameters stored in an \R object. +#' +#' @inheritParams base::print +#' @param ... [dots] Extra arguments to be passed to the method. +#' +#' @export +get_parameters <- function(x, ...) { + UseMethod("get_parameters") +} + +#' Get parameters from an `` object +#' +#' Extract the parameters of the distribution stored in an `` +#' object. +#' +#' @details The `` object can be unparameterised in which it lacks +#' a probability distribution or parameters of a probability distribution, +#' in this case the `get_parameters.epiparameter()` method will return `NA`. +#' +#' @inheritParams print.epiparameter +#' @param ... [dots] Not used, extra arguments supplied will cause a warning. +#' +#' @return A named vector of parameters or `NA` when the `` +#' object is unparameterised. +#' @export +#' +#' @examples +#' ep <- epiparameter_db( +#' disease = "COVID-19", +#' epi_name = "serial interval", +#' single_epiparameter = TRUE +#' ) +#' get_parameters(ep) +get_parameters.epiparameter <- function(x, ...) { + chkDots(...) + # extract parameters depending on prob distribution class + if (inherits(x$prob_distribution, "distcrete")) { + params <- unlist(x$prob_distribution$parameters) + } else if (inherits(x$prob_distribution, "distribution")) { + params <- unlist(distributional::parameters(x$prob_distribution)) + + # if dist is truncated clean names + if (is_truncated(x)) { + names(params) <- gsub( + pattern = "dist.", + replacement = "", + x = names(params), + fixed = TRUE + ) + } + + # convert to meanlog and sdlog names + params <- .clean_params( + prob_distribution = family(x), + prob_distribution_params = params + ) + } else { + return(NA) + } + + # return parameters + params +} + +#' @export +get_parameters.multi_epiparameter <- function(x, ...) { + params <- lapply(x, get_parameters) + # return list of parameters + params +} + +#' Get citation from an object +#' +#' Extract the citation stored in an \R object. +#' +#' @inheritParams base::print +#' @param ... [dots] Extra arguments to be passed to the method. +#' +#' @export +get_citation <- function(x, ...) { + UseMethod("get_citation") +} + +#' Get citation from an `` object +#' +#' Extract the citation stored in an `` object. +#' +#' @inheritParams print.epiparameter +#' @param ... [dots] Not used, extra arguments supplied will cause a warning. +#' +#' @return A `` object. +#' @export +#' +#' @examples +#' # example with +#' ep <- epiparameter_db(single_epiparameter = TRUE) +#' get_citation(ep) +#' +#' # example returning bibtex format +#' ep <- epiparameter_db(disease = "COVID-19", single_epiparameter = TRUE) +#' cit <- get_citation(ep) +#' format(cit, style = "bibtex") +get_citation.epiparameter <- function(x, ...) { + chkDots(...) + if (!inherits(x$citation, "bibentry")) { + stop("Citation should be a ", call. = FALSE) + } + + # return citation + x$citation +} + +#' Get citation from a list of `` objects +#' +#' Extract the citation stored in a list of `` objects. +#' +#' @inheritParams print.epiparameter +#' @param ... [dots] Not used, extra arguments supplied will cause a warning. +#' +#' @return A `` object containing multiple references. The length of +#' output `` is equal to the length of the list of `` +#' objects supplied. +#' @export +#' +#' @examples +#' # example with list of +#' db <- epiparameter_db() +#' get_citation(db) +get_citation.multi_epiparameter <- function(x, ...) { + chkDots(...) + # dispatches to get_citation.epiparameter method + citation_list <- lapply(x, get_citation) + # dispatches to c.bibentry method + multi_bibentry <- Reduce(f = c, x = citation_list) + # return + multi_bibentry +} + +#' Gets the distributions names from a mixture distribution +#' [distributional::dist_mixture()] +#' +#' @param x An `` object. +#' +#' @return A `character` vector. +#' @keywords internal +#' @noRd +.get_mixture_family <- function(x) { + assert_epiparameter(x) + fam <- vapply( + unclass(unclass(x$prob_distribution)[[1]])[[1]], + family, + FUN.VALUE = character(1) + ) + fam <- vapply( + fam, function(x) { + switch(x, + lognormal = "lnorm", + negbin = "nbinom", + geometric = "geom", + poisson = "pois", + normal = "norm", + exponential = "exp", + x + ) + }, + FUN.VALUE = character(1) + ) + return(unname(fam)) +} diff --git a/R/aggregate.R b/R/aggregate.R new file mode 100644 index 000000000..de10e1879 --- /dev/null +++ b/R/aggregate.R @@ -0,0 +1,180 @@ +#' Aggregate multiple `` objects into a single `` +#' object. +#' +#' @description +#' Combine a list of `` objects into a single `` +#' with a mixture distribution [see [distributional::dist_mixture()]]. +#' +#' The aggregated `` returned from `aggregate()` can then be used +#' with the `density()`, `cdf()`, `quantile()` and `generate()` methods for the +#' combined distributions. +#' +#' @details +#' The `aggregate()` method requires that all `` objects are +#' parameterised with `` objects (from the \pkg{distributional} +#' package). This means that unparameterised (see [is_parameterised()]) or +#' discretised (see [discretise()]) distributions cannot be aggregated and the +#' function will error. +#' +#' @param x A `` object. +#' @param weighting A `character` string with the type of weighting to use to +#' create the mixture distribution. Options are: `"equal"` for equal weighting +#' across distributions, `"sample_size"` for using the sample size in each +#' `` object to weight the distribution (the sample sizes are +#' normalised), or `"custom"` allows a vector of weights to be passed to the +#' `weights` argument for a custom weighting. +#' @param weights A `numeric` vector of equal length the number of +#' `` objects passed to `x`. `weights` is only required if +#' `weighting = "custom"`. +#' @param ... [dots] Not used, will warn if extra arguments are passed to +#' function. +#' +#' @return An `` object +#' @importFrom stats aggregate +#' @export +#' +#' @examples +#' ebola_si <- epiparameter_db(epi_name = "serial interval", disease = "ebola") +#' aggregate(ebola_si) +aggregate.multi_epiparameter <- function(x, + weighting = c( + "equal", "sample_size", "custom"), + ..., + weights) { + chkDots(...) + weighting <- match.arg(weighting) + + # ensure contains the same pathogen and epi_name + disease <- unique(vapply(x, `[[`, FUN.VALUE = character(1), "disease")) + pathogen <- unique(vapply(x, `[[`, FUN.VALUE = character(1), "pathogen")) + epi_name <- unique(vapply(x, `[[`, FUN.VALUE = character(1), "epi_name")) + stopifnot( + "All s in x must contain the same disease" = + length(disease) == 1, + "All s in x must contain the same pathogen" = + length(pathogen) == 1, + "All s in x must contain the same type of epi_name" = + length(epi_name) == 1 + ) + + if (!all(vapply(x, is_parameterised, FUN.VALUE = logical(1)))) { + stop( + "aggregate() requires all objects to be parameterised", + call. = FALSE + ) + } + + is_distributional <- vapply( + x, + function(y) inherits(y$prob_distribution, "distribution"), + FUN.VALUE = logical(1) + ) + + if (!all(is_distributional)) { + stop( + "`aggregate()` only works with distributions that are not discretised", + call. = FALSE + ) + } + + if (weighting == "custom") { + if (missing(weights)) { + stop( + "`weights` are required for each distribution when ", + "`weighting = custom`.", + call. = FALSE + ) + } + if (length(weights) != length(x)) { + stop( + "The number of weights must equal the number of ", + "objects.", + call. = FALSE + ) + } + } else if (weighting == "equal") { + weights <- rep(1 / length(x), times = length(x)) + } else if (weighting == "sample_size") { + weights <- vapply( + lapply(x, `[[`, "metadata"), `[[`, FUN.VALUE = numeric(1), "sample_size" + ) + weights <- weights / sum(weights, na.rm = TRUE) + if (anyNA(weights)) { + cit <- get_citation(x) + cit <- unique(.citet(cit[is.na(weights)])) + warning( + cli::pluralize( + "Input distribution{?s} {cit} {?has/have} been dropped ", + "because they don't report sample size and ", + "`weighing = 'sample_size'`." + ), + call. = FALSE + ) + x <- x[!is.na(weights)] + if (length(x) == 0) { + stop("No input distributions have sample sizes.", call. = FALSE) + } + weights <- weights[!is.na(weights)] + } + } + + dists <- lapply(x, `[[`, "prob_distribution") + # weights summing to 1 and negative weights is checked in dist_mixture() + # dist_mixture() accepts dynamic dots + prob_dist <- distributional::dist_mixture(!!!dists, weights = weights) + + # combine summary statistics + ss <- create_summary_stats() + ss_empty <- vector(mode = "list", length = length(ss)) + names(ss_empty) <- names(ss) + metadata <- create_metadata() + metadata_empty <- vector(mode = "list", length = length(metadata)) + names(metadata_empty) <- names(metadata) + method_assess <- create_method_assess() + method_assess_empty <- vector(mode = "list", length = length(method_assess)) + names(method_assess_empty) <- names(method_assess) + for (i in seq_along(x)) { + # add list elements not in to keep consistent struct + ss_ <- c( + x[[i]]$summary_stats, + ss[!names(ss) %in% names(x[[i]]$summary_stats)] + ) + metadata_ <- c( + x[[i]]$metadata, + metadata[!names(metadata) %in% names(x[[i]]$metadata)] + ) + method_assess_ <- c( + x[[i]]$method_assess, + method_assess[!names(method_assess) %in% names(x[[i]]$method_assess)] + ) + # bind empty summary status in first iteration to avoid extra NAs + if (i == 1) { + aggr_ss <- Map(f = c, ss_empty, ss_) + aggr_metadata <- Map(f = c, metadata_empty, metadata_) + aggr_method_assess <- Map(f = c, method_assess_empty, method_assess_) + } else { + aggr_ss <- Map(f = c, aggr_ss, ss_) + aggr_metadata <- Map(f = c, aggr_metadata, metadata_) + aggr_method_assess <- Map(f = c, aggr_method_assess, method_assess_) + } + } + + citations <- lapply(x, `[[`, "citation") + notes <- paste( + "This is an aggregated distribution using", length(x), "", + "objects. The citation for each input can be found in", + "$citation." + ) + + epiparameter( + disease = disease, + pathogen = pathogen, + epi_name = epi_name, + prob_distribution = prob_dist, + citation = Reduce(f = c, x = citations), + summary_stats = aggr_ss, + metadata = aggr_metadata, + method_assess = aggr_method_assess, + notes = notes + ) +} diff --git a/R/calc_dist_params.R b/R/calc_dist_params.R new file mode 100644 index 000000000..9d43b85cd --- /dev/null +++ b/R/calc_dist_params.R @@ -0,0 +1,142 @@ +#' Calculate the parameters of a probability distribution from a list of +#' summary statistics +#' +#' @description If parameters of a probability distribution are not +#' provided (e.g. when describing the distribution in the literature) and +#' instead summary statistics of a distribution are provided, the parameters +#' can usually be calculated from the summary statistics. +#' +#' This function can provide a convenient wrapper around +#' [convert_summary_stats_to_params()] and [extract_param()] +#' when it is not known which summary statistics can be used to +#' calculate the parameters of a distribution. +#' +#' @details The hierarchy of methods is: +#' +#' 1. Conversion is prioritised if the mean and standard deviation are +#' available as these are mostly analytical conversions (except for one of the +#' Weibull conversions). +#' 2. Next method if possible is extraction from percentiles. This method +#' requires a lower percentile (between(0-50]) and an upper percentile +#' (between (50-100)). If multiple percentiles in each of these ranges is +#' provided the lowest value is used for the calculation. +#' 3. The last method is the extraction using a median and range of the data. +#' +#' @inheritParams new_epiparameter +#' @inheritParams epiparameter +#' @param sample_size The sample size of the data. Only needed when falling back +#' on using the median-range extraction calculation. +#' +#' @return A named `numeric` vector with parameters. +#' @keywords internal +.calc_dist_params <- function(prob_distribution, # nolint cyclocomp + summary_stats, + sample_size) { + if (is.na(prob_distribution)) { + message( + "No adequate summary statistics available to calculate the parameters ", + "of the ", prob_distribution, " distribution" + ) + return(NA) + } + + is_percentiles <- checkmate::test_numeric( + summary_stats$quantiles, + all.missing = FALSE, + names = "unique", + null.ok = FALSE + ) + if (is_percentiles) { + # convert percentile names to numbers + percentiles <- .get_percentiles(summary_stats$quantiles) + } else { + percentiles <- NA + } + + # extract median and range to calculate parameters as third choice + median_range <- c( + median = summary_stats$median, + unlist(summary_stats$range) + ) + + # extract mean and sd + mean_sd <- c(summary_stats$mean, summary_stats$sd) + + is_mean_sd <- checkmate::test_numeric( + mean_sd, any.missing = FALSE, len = 2, finite = TRUE + ) + + is_median_disp <- checkmate::test_number( + summary_stats$median, + finite = TRUE + ) && checkmate::test_number( + summary_stats$dispersion, + finite = TRUE + ) + + is_median_range <- checkmate::test_numeric( + median_range, len = 3, finite = TRUE + ) && checkmate::test_count(sample_size, positive = TRUE) + # convert from mean and sd + if (is_mean_sd) { + summary_stats_ <- unlist(summary_stats) + summary_stats_ <- summary_stats_[!is.na(summary_stats_)] + # remove name prefixes from unlisting + names(summary_stats_) <- gsub( + pattern = ".*\\.", + replacement = "", + x = names(summary_stats_) + ) + # drop summary stats not used in conversion + idx <- names(summary_stats_) %in% c( + "mean", "median", "mode", "var", "sd", "cv", + "skewness", "ex_kurtosis", "dispersion" + ) + summary_stats_ <- summary_stats_[idx] + # create flat list structure to be passed to ... in conversion + args <- unlist( + list(prob_distribution, as.list(summary_stats_)), + recursive = FALSE + ) + prob_distribution_params <- unlist(do.call( + convert_summary_stats_to_params, + args = args + )) + } else if (is_median_disp) { + args <- list( + x = prob_distribution, + median = summary_stats$median, + dispersion = summary_stats$dispersion + ) + prob_distribution_params <- do.call( + convert_summary_stats_to_params, + args = args + ) + prob_distribution_params <- unlist(prob_distribution_params) + } else if (!anyNA(percentiles)) { + # calculate the parameters from the percentiles + # percentiles required to be [0, 1] so divide by 100 + prob_distribution_params <- extract_param( + type = "percentile", + values = percentiles, + distribution = prob_distribution, + percentiles = as.numeric(names(percentiles)) / 100 + ) + } else if (is_median_range) { + prob_distribution_params <- extract_param( + type = "range", + values = median_range, + distribution = prob_distribution, + samples = sample_size + ) + } else { + message( + "No adequate summary statistics available to calculate the parameters ", + "of the ", prob_distribution, " distribution" + ) + return(NA) + } + + # return params + prob_distribution_params +} diff --git a/R/checkers.R b/R/checkers.R new file mode 100644 index 000000000..6347deebf --- /dev/null +++ b/R/checkers.R @@ -0,0 +1,57 @@ +#' Check if `` or list of `` objects contains a +#' distribution and distribution parameters +#' +#' @param x An `` or list of `` objects. +#' @param ... [dots] Extra arguments to be passed to the method. +#' +#' @return A single boolean `logical` for `` or vector of +#' `logical`s equal in length to the list of `` objects input. +#' If the `` object is missing either a probability distribution +#' or parameters for the probability distribution returns `FALSE`, otherwise it +#' returns `TRUE`. +#' @export +#' +#' @examples +#' # parameterised +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' is_parameterised(ep) +#' +#' # unparameterised +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation" +#' ) +#' is_parameterised(ep) +#' +#' # list of +#' db <- epiparameter_db() +#' is_parameterised(db) +is_parameterised <- function(x, ...) { + UseMethod("is_parameterised") +} + +#' @rdname is_parameterised +#' @export +is_parameterized <- is_parameterised + +#' @export +is_parameterised.epiparameter <- function(x, ...) { + chkDots(...) + # probability distribution object + return(is.object(x$prob_distribution)) +} + +#' @export +is_parameterised.multi_epiparameter <- function(x, ...) { + chkDots(...) + + # return logical vector + vapply(x, is_parameterised, FUN.VALUE = logical(1)) +} diff --git a/R/coercion.R b/R/coercion.R new file mode 100644 index 000000000..727e5e226 --- /dev/null +++ b/R/coercion.R @@ -0,0 +1,509 @@ +#' [as.function()] method for `` class +#' +#' @description Converts an `` object to a distribution function +#' (see [epiparameter_distribution_functions]), either probability density/mass +#' function, (`density`), cumulative distribution function (`cdf`), random +#' number generator (`generate`), or quantile (`quantile`). +#' +#' @details The function returned takes a single required argument `x`. +#' +#' @inheritParams print.epiparameter +#' @inheritParams base::as.function +#' @param func_type A single `character` string specifying which distribution to +#' convert `` object into. Default is `"density"`. Other options +#' are `"cdf"`, `"generate"`, or `"quantile"`. +#' +#' @return A [function] object. +#' @export +as.function.epiparameter <- function(x, + func_type = c( + "density", "cdf", "generate", "quantile" + ), + ...) { + chkDots(...) + func_type <- match.arg(func_type) + if (!is_parameterised(x)) { + stop( + "Cannot convert unparameterised to distribution function", + call. = FALSE + ) + } + epiparameter <- x + # return distribution function + switch(func_type, + density = function(x) density(x = epiparameter, at = x), + cdf = function(x) epiparameter::cdf(x = epiparameter, q = x), + generate = function(x) epiparameter::generate(x = epiparameter, times = x), + quantile = function(x) quantile(x = epiparameter, p = x) + ) +} + + +#' [as.data.frame()] method for `` class +#' +#' @details +#' The `` returned will contain some atomic columns (i.e. one +#' object per row), and other columns that are lists (i.e. multiple objects per +#' row). The list columns can contain lists or S3 objects (e.g. `` +#' object in the `citation` column). +#' +#' +#' @inheritParams print.epiparameter +#' @param ... [dots] Not used, extra arguments supplied will cause a warning. +#' +#' @return A `` with a single row. +#' @export +as.data.frame.epiparameter <- function(x, ...) { + chkDots(...) + # check object as could be invalidated by user + assert_epiparameter(x) + + data.frame( + disease = x$disease, + pathogen = x$pathogen, + epi_name = x$epi_name, + prob_distribution = I(list(prob_distribution = x$prob_distribution)), + uncertainty = I(list(uncertainty = x$uncertainty)), + summary_stats = I(list(summary_stats = x$summary_stats)), + citation = I(list(citation = x$citation)), + metadata = I(list(metadata = x$metadata)), + method_assess = I(list(method_assess = x$method_assess)), + notes = x$notes, + row.names = NULL + ) +} + +#' [as.data.frame()] method for `` class +#' +#' @inherit as.data.frame.epiparameter details +#' +#' @inheritParams print.multi_epiparameter +#' @param ... [dots] Not used, extra arguments supplied will cause a warning. +#' +#' @return A `` with as many rows as length of input list. +#' @export +as.data.frame.multi_epiparameter <- function(x, ...) { + chkDots(...) + do.call(rbind, lapply(x, as.data.frame)) +} + +#' Convert to an `` object +#' +#' Convert from an \R object to an `` object. If conversion is not +#' possible the function will error. +#' +#' @details +#' To create the full citation the information from the article table from the +#' \pkg{epireview} package of the corresponding entry will need to be passed +#' to function via the `...` argument. The argument should be called `article`, +#' as it will be matched by name by `$`. +#' +#' To specify a probability distribution pass a `character` string to the +#' function via the `...` argument. The argument should be called +#' `prob_distribution`. For example, to specify a gamma distribution: +#' `as_epiparameter(x, prob_distribution = "gamma")`. +#' +#' ***Warning***: distributions specified via the `prob_dist` argument will +#' overwrite the probability distribution specified in the `x` argument. For +#' example, if the probability distribution is given in an \pkg{epireview} +#' entry and the `prob_dist` argument is specified then the function may error +#' or return an unparameterised `` if the parameterisation becomes +#' incompatible. +#' +#' Valid probability distributions are: `"gamma"`, `"lnorm"`, `"weibull"`, +#' `"nbinom"`, `"geom"`, `"pois"`, `"norm"`, `"exp"`. +#' +#' @inheritParams base::print +#' @param ... [dots] Extra arguments to be passed to the method. +#' +#' @inherit epiparameter_db return +#' @export +as_epiparameter <- function(x, ...) { + UseMethod("as_epiparameter") +} + +#' Convert `` to an `` object +#' +#' Convert the tabular information in `` to an ``. +#' If the information in the `` cannot be converted into an +#' `` the function will error. +#' +#' @param x A ``. +#' @param ... [dots] Not used, extra arguments supplied will cause a warning. +#' +#' @inherit epiparameter_db return +#' @export +as_epiparameter.data.frame <- function(x, ...) { + if (is_epiparameter_df(x)) { + epiparameter <- .epiparameter_df_to_epiparameter(x, ...) + } else if (.is_epireview(x)) { + epiparameter <- .epireview_to_epiparameter(x, ...) + } else { + stop( + " input into as_epiparameter() cannot be converted to ", + "", + call. = FALSE + ) + } + # return + epiparameter +} + +#' Check if `` input is from [as.data.frame.epiparameter()] +#' +#' @param x A ``. +#' +#' @return A single `logical` boolean. +#' @keywords internal +is_epiparameter_df <- function(x) { + valid_colnames <- identical( + colnames(x), + c( + "disease", "pathogen", "epi_name", "prob_distribution", + "uncertainty", "summary_stats", "citation", "metadata", "method_assess", + "notes" + ) + ) + # return logical + valid_colnames +} + +#' Check if `` input is from \pkg{epireview} +#' +#' @param x A ``. +#' +#' @return A single `logical` boolean. +#' @keywords internal +.is_epireview <- function(x) { + valid_colnames <- all(epiparameter::epireview_core_cols %in% colnames(x)) + # return logical + valid_colnames +} + +#' Convert `` from [as.data.frame.epiparameter()] to +#' `` +#' +#' @param x A ``. +#' @param ... [dots] Extra arguments to pass to [epiparameter()]. +#' +#' @inherit epiparameter return +#' @keywords internal +.epiparameter_df_to_epiparameter <- function(x, ...) { # nolint object_length_linter + # extract probability distribution from list and extract parameters + # and truncation if available + prob_dist <- x$prob_distribution[[1]] + if (inherits(prob_dist, "distribution")) { + prob_distribution_params <- unlist( + distributional::parameters(x$prob_distribution[[1]]) + ) + } + if (identical(stats::family(prob_dist), "truncated")) { + truncation <- distributional::parameters(x$prob_distribution)$upper + } else { + truncation <- NA_real_ + } + # create uncertainty list of parameters if not provided + if (all(unlist(lapply(x$uncertainty$uncertainty, is.na)))) { + uncertainty <- x$uncertainty$uncertainty + } else { + uncertainty <- lapply( + prob_distribution_params, + function(x) create_uncertainty() + ) + } + + # remove from citation + class(x$citation) <- setdiff(class(x$citation), "AsIs") + + # return from class constructor + epiparameter( + disease = x$disease, + pathogen = x$pathogen, + epi_name = x$epi_name, + prob_distribution = create_prob_distribution( + prob_distribution = family(x$prob_distribution[[1]]), + prob_distribution_params = prob_distribution_params, + discretise = inherits(x$prob_distribution[[1]], "distcrete"), + truncation = truncation + ), + uncertainty = uncertainty, + summary_stats = x$summary_stats$summary_stats, + citation = x$citation, + metadata = x$metadata, + method_assess = x$method_assess, + notes = x$notes + ) +} + +#' Convert `` from \pkg{epireview} to `` +#' +#' @param x A ``. +#' @param ... [dots] Extra arguments to pass to [epiparameter()]. +#' +#' @inherit epiparameter return +#' @keywords internal +#' @noRd +.epireview_to_epiparameter <- function(x, ...) { # nolint cyclocomp_linter + # capture dots and extract article info if supplied + dots <- list(...) + article <- dots$article + prob_dist_in <- dots$prob_distribution + # validate multi-row entries + if (nrow(x) > 1) { + stopifnot( + "Multiple entries passed to as_epiparameter() do not have the same ID" = + length(unique(x$id)) == 1L + ) + } + + pathogen <- .unique(x$pathogen, var_name = "pathogen") + # get disease from pathogen lookup + disease <- switch( + pathogen, + "Marburg virus" = "Marburg Virus Disease", + "Lassa mammarenavirus" = "Lassa fever", + "Ebola virus" = "Ebola Virus Disease", + stop("Pathogen in epireview not recognised", call. = FALSE) + ) + epi_name <- .unique(x$parameter_type, var_name = "parameter types") + prob_dist <- .unique(x$distribution_type, var_name = "distribution types") + sd_ <- NULL + if (rlang::is_na(prob_dist)) { + prob_dist_params <- NA_real_ + uncertainty <- list(uncertainty = create_uncertainty()) + } else { + prob_dist <- switch( + prob_dist, + Gamma = "gamma", + "Negative-Binomial" = "nbinom", + Normal = "norm", + Exponential = "exp", + "Normal-Log" = NA_character_, + Weibull = "weibull", + stop( + "Probability distribution in epireview not recognised", + call. = FALSE + ) + ) + if (rlang::is_chr_na(prob_dist)) { + stop( + "epireview entry has Normal-log distribution, this is not currently ", + "supported in {epiparameter}.\n Cannot convert to ", + call. = FALSE + ) + } + prob_dist_params <- list( + x$distribution_par1_value, + x$distribution_par2_value + ) + prob_dist_params <- prob_dist_params[!is.na(prob_dist_params)] + prob_dist_params_names <- c( + x$distribution_par1_type, + x$distribution_par2_type + ) + prob_dist_params_names <- + prob_dist_params_names[!is.na(prob_dist_params_names)] + # {epireview} uses "Standard deviation" or "Mean sd" for sd + prob_dist_params_names <- gsub( + pattern = "Standard deviation|Mean sd", + replacement = "sd", + x = prob_dist_params_names + ) + prob_dist_params_names <- .clean_string(prob_dist_params_names) + names(prob_dist_params) <- prob_dist_params_names + + # overwrite prob_dist with user specified if given to make use of conversion + if (!is.null(prob_dist_in)) { + prob_dist <- prob_dist_in + # remove user specified to not trigger overwriting prob_dist below + prob_dist_in <- NULL + } + + if (all(c("mean", "sd") %in% names(prob_dist_params))) { + sd_ <- prob_dist_params[["sd"]] + prob_dist_params <- do.call( + convert_summary_stats_to_params, + c(prob_dist, prob_dist_params) + ) + } + prob_dist_params <- unlist(prob_dist_params) + uncertainty <- lapply( + prob_dist_params, + function(x) create_uncertainty() + ) + names(uncertainty) <- names(prob_dist_params) + } + # overwrite prob_dist with user specified if given + if (!is.null(prob_dist_in)) { + prob_dist <- prob_dist_in + # erase uncertainty, new prob_dist will likely have different param names + uncertainty <- create_uncertainty() + } + # vectorise switch (cannot use vapply due to various return FUN.VALUE) + param_type <- sapply( # nolint undesirable_function_linter + x$parameter_value_type, + switch, + Mean = "mean", + "Standard Deviation" = "sd", + Median = "median", + Other = NA_character_, + "NA" = NULL, + stop("Parameter value type not recognised", call. = FALSE) + ) + # ensure param_type is unnamed vector as it is used for list subsetting + param_type <- unlist(unname(param_type)) + is_other <- vapply( + param_type, + rlang::is_chr_na, + FUN.VALUE = logical(1) + ) + if (any(is_other)) { + warning( + "Parameter value type specified as 'Other'.\n", + "Parameter value will not be input into .", + call. = FALSE + ) + param_type <- NULL + } + summary_stats <- create_summary_stats() + summary_stats[param_type] <- x$parameter_value + uncertainty_type <- .unique( + x$parameter_uncertainty_type, + var_name = "uncertainty types" + ) + if (grepl(pattern = "Range", x = uncertainty_type, fixed = TRUE)) { + summary_stats$range <- c(x$parameter_lower_bound, x$parameter_upper_bound) + inference_method <- NA + } else if (grepl(pattern = "CI", x = uncertainty_type, fixed = TRUE)) { + summary_stats <- .ss_ci(x, summary_stats, param_type) + inference_method <- "Maximum likelihood" + } else if (grepl(pattern = "CrI", x = uncertainty_type, fixed = TRUE)) { + summary_stats <- .ss_ci(x, summary_stats, param_type) + inference_method <- "Bayesian" + } else { + inference_method <- NA + } + # underscore to prevent mix-up with variable and sd() + if (!is.null(sd_)) { + summary_stats$sd <- sd_ + } + metadata <- create_metadata() + metadata$units <- .unique(x$parameter_unit, var_name = "units") + metadata$sample_size <- .unique(x$population_sample_size) + metadata$inference_method <- inference_method + location <- .unique(x$population_location) + if (rlang::is_na(location)) location <- NULL + country <- .unique(x$population_country) + if (rlang::is_na(country)) country <- NULL + # NULL get removed from vector + region <- c(location, country) + if (length(region) > 1) { + region <- toString(region) + } + metadata$region <- region + if (is.null(article)) { + citation <- create_citation( + author = .unique(x$first_author_surname, var_name = "citation authors"), + year = .unique(x$year_publication, var_name = "citation years"), + title = "", + journal = "<journal not available>" + ) + warning( + "Cannot create full citation for epidemiological parameters without ", + "bibliographic information \n see ?as_epiparameter for help.", + call. = FALSE + ) + } else { + if (!identical(x$id, article$id)) { + stop( + "ID of epidemiological parameter does not match ID of article info", + call. = FALSE + ) + } + citation <- create_citation( + author = article$first_author_surname, + year = article$year_publication, + title = article$article_title, + journal = article$journal, + doi = article$doi + ) + } + # <epiparameter> constructor and return + epiparameter( + disease = disease, + pathogen = pathogen, + epi_name = epi_name, + prob_distribution = create_prob_distribution( + prob_distribution = prob_dist, + prob_distribution_params = prob_dist_params + ), + uncertainty = uncertainty, + summary_stats = summary_stats, + citation = citation, + metadata = metadata + ) +} + +#' Check vector has a single unique value if not error +#' +#' @param x A vector. +#' @param var_name A `character` to paste into the error message. +#' +#' @return A \R object of length 1. +#' @keywords internal +#' @noRd +.unique <- function(x, var_name) { + x <- unique(x) + if (length(x) != 1) { + stop( + "epireview parameters contains multiple different ", var_name, "\n", + "Cannot convert to <epiparameter>", + call. = FALSE + ) + } + x +} + +#' Input summary statistic uncertainty +#' +#' @param x A `<data.frame>` from \pkg{epireview}. +#' @param summary_stats A list returned from [create_summary_stats()]. +#' @param summary_stat_type A `character` string with the name of the summary +#' statistic type (e.g., `"mean"`, `"median"`). +#' +#' @return A modified summary statistic list. +#' @keywords internal +#' @noRd +.ss_ci <- function(x, summary_stats, summary_stat_type) { + summary_stat_type_uncertainty <- paste0(summary_stat_type, "_ci_limits") + summary_stat_uncertainty <- list( + x$parameter_uncertainty_lower_value, + x$parameter_uncertainty_upper_value + ) + ss_uncertainty <- vector( + mode = "list", + length = length(summary_stat_type_uncertainty) + ) + for (i in seq_along(ss_uncertainty)) { + ss_uncertainty[[i]] <- vapply( + summary_stat_uncertainty, + "[[", + FUN.VALUE = numeric(1), + i + ) + } + summary_stats[summary_stat_type_uncertainty] <- ss_uncertainty + interval <- as.numeric(gsub( + pattern = "[[:alpha:][:punct:]]", + replacement = "", + x = x$parameter_uncertainty_type + )) + summary_stat_interval <- gsub( + pattern = "_limits", + replacement = "", + x = summary_stat_type_uncertainty, + fixed = TRUE + ) + summary_stats[summary_stat_interval] <- interval + summary_stats +} diff --git a/R/convert_params.R b/R/convert_params.R new file mode 100644 index 000000000..f4a2beea0 --- /dev/null +++ b/R/convert_params.R @@ -0,0 +1,823 @@ +#' Convert the summary statistics of a distribution to parameters +#' +#' @description Convert the summary statistics for a range of distributions to +#' the distribution's parameters. Most summary statistics are calculated +#' analytically given the parameters. An exception is the Weibull distribution +#' which uses a root finding numerical method. +#' +#' @details Summary statistics should be named accordingly (case-sensitive): +#' +#' * mean: `mean` +#' * median: `median` +#' * mode: `mode` +#' * variance: `var` +#' * standard deviation: `sd` +#' * coefficient of variation: `cv` +#' * skewness: `skewness` +#' * excess kurtosis: `ex_kurtosis` +#' +#' **Note**: Not all combinations of summary statistics can be converted into +#' distribution parameters. In this case the function will error stating that +#' the parameters cannot be calculated from the given input. +#' +#' The distribution names and parameter names follow the style of +#' distributions in \R, for example the lognormal distribution is `lnorm`, +#' and its parameters are `meanlog` and `sdlog`. +#' +#' @param x An \R object. +#' @param ... <[`dynamic-dots`][rlang::dyn-dots]> `Numeric` named summary +#' statistics used to convert to parameter(s). An example is the `mean` +#' and `sd` summary statistics for the lognormal (`lnorm`) distribution. +#' +#' @seealso [convert_params_to_summary_stats()] +#' +#' @return A list of either one or two elements (depending on how many +#' parameters the distribution has). +#' @export +#' +#' @examples +#' # examples using characters +#' convert_summary_stats_to_params("lnorm", mean = 1, sd = 1) +#' convert_summary_stats_to_params("weibull", mean = 2, var = 2) +#' convert_summary_stats_to_params("geom", mean = 2) +#' +#' # examples using <epiparameter> +#' epiparameter <- epiparameter_db(single_epiparameter = TRUE) +#' convert_summary_stats_to_params(epiparameter) +#' +#' # example using <epiparameter> and specifying summary stats +#' epiparameter$summary_stats <- list() +#' convert_summary_stats_to_params(epiparameter, mean = 10, sd = 2) +convert_summary_stats_to_params <- function(x, ...) { # nolint object_length_linter + UseMethod("convert_summary_stats_to_params") +} + +#' @rdname convert_summary_stats_to_params +#' @export +convert_summary_stats_to_params.character <- function(x = c("lnorm", "gamma", + "weibull", "nbinom", + "geom"), + ...) { + # check input + x <- match.arg(x) + # capture dynamic dots + dots <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + if (!checkmate::test_list(dots, min.len = 1, names = "unique")) { + stop( + "Summary statistics need to be named and supplied to the function ", + "through `...`", + call. = FALSE + ) + } + + # dispatch to function based on distribution specified + func <- switch(x, + lnorm = .convert_summary_stats_lnorm, + gamma = .convert_summary_stats_gamma, + weibull = .convert_summary_stats_weibull, + nbinom = .convert_summary_stats_nbinom, + geom = .convert_summary_stats_geom + ) + + # call selected function + out <- do.call(func, dots) + + # return output + out +} + +#' @rdname convert_summary_stats_to_params +#' @export +convert_summary_stats_to_params.epiparameter <- function(x, ...) { + # check input + x <- assert_epiparameter(x) + # capture dynamic dots + dots <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + numeric_ss <- names(x$summary_stats)[!is.na(x$summary_stats)] + # warn for modification + if (any(names(dots) %in% numeric_ss)) { + warning( + "One or more summary statistics in <epiparameter> are being overwritten ", + "by those supplied through `...`", + call. = FALSE + ) + } + summary_stats <- utils::modifyList(x$summary_stats, dots) + + # remove <epiparameter> summary stats not accepted by internal conversion + summary_stats_set <- names(summary_stats) %in% + c("mean", "median", "mode", "var", "sd", "cv", + "skewness", "ex_kurtosis", "dispersion") + summary_stats <- summary_stats[summary_stats_set] + + if (!checkmate::test_list(summary_stats, min.len = 1, names = "unique")) { + stop( + "Summary statistics need to be named and supplied to the function ", + "or in <epiparameter>", + call. = FALSE + ) + } + + # get and check distribution name + distribution <- match.arg( + family(x), + choices = c("lnorm", "gamma", "weibull", "nbinom", "geom") + ) + + # dispatch to function based on distribution specified + func <- switch(distribution, + lnorm = .convert_summary_stats_lnorm, + gamma = .convert_summary_stats_gamma, + weibull = .convert_summary_stats_weibull, + nbinom = .convert_summary_stats_nbinom, + geom = .convert_summary_stats_geom + ) + + # call selected function + out <- do.call(func, summary_stats) + + # return output + out +} + +#' Convert the parameter(s) of a distribution to summary statistics +#' +#' @description Convert the parameters for a range of distributions to a +#' number of summary statistics. All summary statistics are calculated +#' analytically given the parameters. +#' +#' @details The distribution names and parameter names follow the style of +#' distributions in \R, for example the lognormal distribution is `lnorm`, +#' and its parameters are `meanlog` and `sdlog`. +#' +#' @inheritParams convert_summary_stats_to_params +#' @param ... <[`dynamic-dots`][rlang::dyn-dots]> `Numeric` named parameter(s) +#' used to convert to summary statistics. An example is the `meanlog` and +#' `sdlog` parameters of the lognormal (`lnorm`) distribution. +#' +#' @seealso [convert_summary_stats_to_params()] +#' +#' @return A list of eight elements including: mean, median, mode, +#' variance (`var`), standard deviation (`sd`), coefficient of variation (`cv`), +#' skewness, and excess kurtosis (`ex_kurtosis`). +#' @export +#' +#' @examples +#' # example using characters +#' convert_params_to_summary_stats("lnorm", meanlog = 1, sdlog = 2) +#' convert_params_to_summary_stats("gamma", shape = 1, scale = 1) +#' convert_params_to_summary_stats("nbinom", prob = 0.5, dispersion = 2) +#' +#' # example using <epiparameter> +#' epiparameter <- epiparameter_db(single_epiparameter = TRUE) +#' convert_params_to_summary_stats(epiparameter) +#' +#' # example using <epiparameter> and specifying parameters +#' epiparameter <- epiparameter_db( +#' disease = "Influenza", +#' author = "Virlogeux", +#' subset = prob_dist == "weibull" +#' ) +#' convert_params_to_summary_stats(epiparameter[[2]], shape = 1, scale = 1) +convert_params_to_summary_stats <- function(x, ...) { # nolint object_length_linter + UseMethod("convert_params_to_summary_stats") +} + +#' @rdname convert_params_to_summary_stats +#' @export +convert_params_to_summary_stats.character <- function(x = c("lnorm", "gamma", + "weibull", "nbinom", + "geom"), + ...) { + # check input + x <- match.arg(x) + # capture dynamic dots + dots <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + if (!checkmate::test_list(dots, min.len = 1, names = "unique")) { + stop( + "Parameter(s) need to be named and supplied to the function ", + "through `...`", + call. = FALSE + ) + } + + # dispatch to function based on distribution specified + func <- switch(x, + lnorm = .convert_params_lnorm, + gamma = .convert_params_gamma, + weibull = .convert_params_weibull, + nbinom = .convert_params_nbinom, + geom = .convert_params_geom + ) + + # call selected function + out <- do.call(func, dots) + + # return output + out +} + +#' @rdname convert_params_to_summary_stats +#' @export +convert_params_to_summary_stats.epiparameter <- function(x, ...) { + # check input + x <- assert_epiparameter(x) + # capture dynamic dots + dots <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + + if (!is_parameterised(x)) { + if (length(dots) > 0) { + # unparameterised with parameters supplied through `...` + return(convert_params_to_summary_stats(x$prob_distribution, ...)) + } + # unparameterised with no parameters supplied through `...` + stop( + "<epiparameter> supplied has no parameters and none are suppled ", + "through `...`", + call. = FALSE + ) + } + + parameters <- as.list(get_parameters(x)) + + # warn for modification + if (any(names(dots) %in% names(parameters))) { + warning( + "One or more parameters in <epiparameter> are being overwritten by ", + "those supplied through `...`", + call. = FALSE + ) + } + parameters <- utils::modifyList(parameters, dots) + + # get and check distribution name + distribution <- match.arg( + family(x), + choices = c("lnorm", "gamma", "weibull", "nbinom", "geom") + ) + + # dispatch to function based on distribution specified + func <- switch(distribution, + lnorm = .convert_params_lnorm, + gamma = .convert_params_gamma, + weibull = .convert_params_weibull, + nbinom = .convert_params_nbinom, + geom = .convert_params_geom + ) + + # call selected function + out <- do.call(func, parameters) + + # return output + out +} + +#' Adds standard deviation to the list if not present or errors +#' +#' @param x A list of summary statistics +#' +#' @return A list of summary statistics +#' @keywords internal +#' @noRd +.get_sd <- function(x) { + if ("sd" %in% names(x)) { + return(x) + } + if ("var" %in% names(x)) { + x$sd <- sqrt(x$var) + } else if (all(c("mean", "cv") %in% names(x))) { + x$sd <- x$cv * x$mean + } + # return list of summary statistics + x +} + +#' Checks list of summary statistics is valid for conversion +#' +#' @inheritParams get_sd +#' +#' @return Invisibly returns a list of summary statistics +#' @keywords internal +#' @noRd +.chk_ss <- function(x) { + checkmate::assert_list( + x = x, + types = "numeric", + any.missing = FALSE, + all.missing = FALSE, + min.len = 2, + names = "unique" + ) + checkmate::assert_subset( + x = names(x), + choices = c( + "mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis", + "dispersion" + ) + ) + # invisibly return list of summary statistics + invisible(x) +} + +#' Converts the parameters of the lognormal distribution to summary statistics +#' +#' @description Converts the meanlog and sdlog parameters of the lognormal +#' distribution to a number of summary statistics which can be calculated +#' analytically given the lognormal parameters. +#' +#' @inheritParams convert_params_to_summary_stats +#' +#' @return A list of eight elements including: mean, median, mode, +#' variance (`var`), standard deviation (`sd`), coefficient of variation (`cv`), +#' skewness, and excess kurtosis (`ex_kurtosis`). +#' @keywords internal +.convert_params_lnorm <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input params + if (all(c("meanlog", "sdlog") %in% names(x))) { + meanlog <- x[["meanlog"]] + sdlog <- x[["sdlog"]] + } else { + stop("lnorm parameters must be named 'meanlog' and 'sdlog'", call. = FALSE) + } + + # check input + checkmate::assert_number(meanlog) + checkmate::assert_number(sdlog, lower = 0) + + # calculate metrics + mean <- exp(meanlog + sdlog^2 / 2) + median <- exp(meanlog) + mode <- exp(meanlog - sdlog^2) + var <- (exp(sdlog^2) - 1) * exp(2 * meanlog + sdlog^2) + sd <- sqrt(var) + cv <- sd / mean + skewness <- (exp(sdlog^2) + 2) * sqrt(exp(sdlog^2) - 1) + ex_kurtosis <- exp(4 * sdlog^2) + 2 * + exp(3 * sdlog^2) + 3 * exp(2 * sdlog^2) - 6 + + # return list of metrics + list( + mean = mean, + median = median, + mode = mode, + var = var, + sd = sd, + cv = cv, + skewness = skewness, + ex_kurtosis = ex_kurtosis + ) +} + +#' Convert summary statistics to parameters of the lognormal distribution +#' +#' @description Convert the summary statistics input into the meanlog and sdlog +#' parameters of the lognormal distribution. +#' +#' @inheritParams convert_summary_stats_to_params +#' +#' @return A list of two elements: meanlog and sdlog +#' @keywords internal +.convert_summary_stats_lnorm <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input + .chk_ss(x) + + # convert var or cv into sd if available + x <- .get_sd(x) + + if (checkmate::test_number(x$mean) && checkmate::test_number(x$sd)) { + # mean and sd to params + checkmate::assert_number(x$mean, lower = 0) + checkmate::assert_number(x$sd, lower = 0) + sdlog <- sqrt(log(x$sd^2 / x$mean^2 + 1)) + meanlog <- log(x$mean^2 / sqrt(x$sd^2 + x$mean^2)) + return(list(meanlog = meanlog, sdlog = sdlog)) + } + + if (checkmate::test_number(x$median) && + checkmate::test_number(x$dispersion)) { + # median and dispersion to params + checkmate::assert_number(x$median, lower = 0) + checkmate::assert_number(x$dispersion, lower = 0) + meanlog <- log(x$median) + sdlog <- log(x$dispersion) + return(list(meanlog = meanlog, sdlog = sdlog)) + } + + if (!(checkmate::test_number(x$median) && checkmate::test_number(x$sd))) { + stop("Cannot calculate lognormal parameters from given input") + } + + # median and sd to params + sdlog <- sqrt(log(1 + (x$sd / x$median)^2)) + meanlog <- log(x$median) - sdlog^2 / 2 + + # return list of params + list( + meanlog = meanlog, + sdlog = sdlog + ) +} + +#' Convert parameters of the gamma distribution to summary statistics +#' +#' @description Convert the shape and scale parameters of the gamma +#' distribution to a number of summary statistics which can be calculated +#' analytically given the gamma parameters. One exception is the median which +#' is calculated using [qgamma()] as no analytical form is available. +#' +#' @inheritParams convert_params_to_summary_stats +#' +#' @return A list of eight elements including: mean, median, mode, +#' variance (`var`), standard deviation (`sd`), coefficient of variation (`cv`), +#' skewness, and excess kurtosis (`ex_kurtosis`). +#' @keywords internal +.convert_params_gamma <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input params + if (all(c("shape", "scale") %in% names(x))) { + shape <- x[["shape"]] + scale <- x[["scale"]] + } else { + stop("gamma parameters must be named 'shape' and 'scale'", call. = FALSE) + } + + # check input + checkmate::assert_number(shape, lower = 0) + checkmate::assert_number(scale, lower = 0) + + # calculate metrics + mean <- shape * scale + median <- stats::qgamma(0.5, shape, scale) + mode <- max((shape - 1) * scale, 0) + var <- shape * scale^2 + sd <- sqrt(var) + cv <- sd / mean + skewness <- 2 / sqrt(shape) + ex_kurtosis <- 6 / shape + + # return list of metrics + list( + mean = mean, + median = median, + mode = mode, + var = var, + sd = sd, + cv = cv, + skewness = skewness, + ex_kurtosis = ex_kurtosis + ) +} + +#' Convert summary statistics to parameters of the gamma distribution +#' +#' @description Convert the summary statistics input into the shape and scale +#' parameters of the gamma distribution. +#' +#' @inheritParams convert_summary_stats_to_params +#' +#' @return A list of two elements, the shape and scale +#' @keywords internal +.convert_summary_stats_gamma <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input + .chk_ss(x) + + # convert var or cv into sd if available + x <- .get_sd(x) + + if (checkmate::test_number(x$mean) && checkmate::test_number(x$sd)) { + # mean and sd to params + checkmate::assert_number(x$mean, lower = 0) + checkmate::assert_number(x$sd, lower = 0) + shape <- (x$mean)^2 / x$sd^2 + scale <- x$sd^2 / abs(x$mean) + checkmate::assert_number(shape, lower = 0) + checkmate::assert_number(scale, lower = 0) + return(list(shape = shape, scale = scale)) + } + + # if either parameter hasn't been calculated, error + stop("Cannot calculate gamma parameters from given input") +} + +#' Convert parameters of the Weibull distribution to summary statistics +#' +#' @description Convert the shape and scale parameters of the Weibull +#' distribution to a number of summary statistics which can be calculated +#' analytically given the Weibull parameters. Note the conversion uses the +#' [gamma()] function. +#' +#' @inheritParams convert_params_to_summary_stats +#' +#' @return A list of eight elements including: mean, median, mode, +#' variance (`var`), standard deviation (`sd`), coefficient of variation (`cv`), +#' skewness, and excess kurtosis (`ex_kurtosis`). +#' @keywords internal +.convert_params_weibull <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input params + if (all(c("shape", "scale") %in% names(x))) { + shape <- x[["shape"]] + scale <- x[["scale"]] + } else { + stop("weibull parameters must be named 'shape' and 'scale'", call. = FALSE) + } + + # check input + checkmate::assert_number(shape, lower = 0) + checkmate::assert_number(scale, lower = 0) + + # calculate metrics + mean <- scale * gamma(1 + 1 / shape) + median <- scale * (log(2))^(1 / shape) + mode <- ifelse(shape > 1, scale * ((shape - 1) / shape)^(1 / shape), 0) + var <- scale^2 * (gamma(1 + 2 / shape) - (gamma(1 + 1 / shape))^2) + sd <- sqrt(var) + cv <- sd / mean + skewness <- (gamma(1 + 3 / shape) * scale^3 - 3 * + mean * sd^2 - mean^3) / (sd^3) + ex_kurtosis <- ((gamma(1 + 4 / shape) * scale^4 - 4 * skewness * mean * + sd^3 - 6 * mean^2 * sd^2 - mean^4) / (sd^4)) - 3 + + + # return list of metrics + list( + mean = mean, + median = median, + mode = mode, + var = var, + sd = sd, + cv = cv, + skewness = skewness, + ex_kurtosis = ex_kurtosis + ) +} + +#' Convert summary statistics to parameters of the Weibull distribution +#' +#' @description Convert summary statistics input into the shape and scale +#' parameters of the Weibull distribution. +#' +#' @inheritParams convert_summary_stats_to_params +#' +#' @return A list of two elements, the shape and scale. +#' @keywords internal +.convert_summary_stats_weibull <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input + .chk_ss(x) + + # convert var or cv into sd if available + x <- .get_sd(x) + + if (checkmate::test_number(x$mean) && checkmate::test_number(x$sd)) { + # mean and sd to params + checkmate::assert_number(x$mean, lower = 0) + checkmate::assert_number(x$sd, lower = 0) + # give warning message about numerical inaccuracies + message("Numerical approximation used, results may be unreliable.") + f <- function(k, mean, var) { + (var / mean^2) - ((gamma(1 + 2 / k)) / (gamma(1 + 1 / k))^2) + 1 + } + root <- stats::uniroot( + f = f, + interval = c(0.1, 1000), + mean = x$mean, + var = x$sd^2 + ) + shape <- root$root + scale <- x$mean / gamma(1 + 1 / shape) + return(list(shape = shape, scale = scale)) + } + + # if either parameter hasn't been calculated, error + stop("Cannot calculate Weibull parameters from given input") +} + +#' Convert parameters of the negative binomial distribution to summary +#' statistics +#' +#' @description Convert the probability (`prob`) and dispersion parameters of +#' the negative binomial distribution to a number of summary statistics which +#' can be calculated analytically given the negative binomial parameters. +#' One exception is the median which is calculated using [qnbinom()] as no +#' analytical form is available. +#' +#' The parameters are `prob` and `dispersion` (which is also commonly +#' represented as *r*). +#' +#' @inheritParams convert_params_to_summary_stats +#' +#' @return A list of eight elements including: mean, median, mode, +#' variance (`var`), standard deviation (`sd`), coefficient of variation (`cv`), +#' skewness, and ex_kurtosis. +#' @keywords internal +.convert_params_nbinom <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input params + if (all(c("prob", "dispersion") %in% names(x))) { + prob <- x[["prob"]] + dispersion <- x[["dispersion"]] + } else { + stop( + "nbinom parameters must be named 'prob' and 'dispersion'", + call. = FALSE + ) + } + + # check input + checkmate::assert_number(prob, lower = 0, upper = 1) + checkmate::assert_number(dispersion, lower = 0) + + # calculate metrics + mean <- dispersion * (1 - prob) / prob + median <- stats::qnbinom(p = 0.5, prob = prob, size = dispersion) + mode <- max((dispersion - 1) * (1 - prob) / prob, 0) + var <- dispersion * (1 - prob) / prob^2 + sd <- sqrt(var) + cv <- sd / mean + skewness <- (2 - prob) / sqrt((1 - prob) * dispersion) + ex_kurtosis <- 6 / dispersion + prob^2 / (1 - prob) * dispersion + + # return list of metrics + list( + mean = mean, + median = median, + mode = mode, + var = var, + sd = sd, + cv = cv, + skewness = skewness, + ex_kurtosis = ex_kurtosis + ) +} + +#' Convert summary statistics to parameters of the negative binomial +#' distribution +#' +#' @description Convert summary statistics of the negative binomial +#' distribution the parameters (`prob`) and (`dispersion`) of the negative +#' binomial distribution. +#' +#' @inheritParams convert_summary_stats_to_params +#' +#' @return A list of two elements, the probability and dispersion parameters. +#' @keywords internal +.convert_summary_stats_nbinom <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input + .chk_ss(x) + + # convert var or cv into sd if available + x <- .get_sd(x) + + if (checkmate::test_number(x$mean) && checkmate::test_number(x$dispersion)) { + prob <- 1 / (1 + x$mean / x$dispersion) + dispersion <- x$dispersion + } else if (checkmate::test_number(x$mean) && checkmate::test_number(x$sd)) { + prob <- x$mean / x$sd^2 + dispersion <- x$mean^2 / (x$sd^2 - x$mean) + } else { + # if either parameter hasn't been calculated error + stop( + "Cannot calculate negative binomial distribution ", + "parameters from given input" + ) + } + + # ensure variance-to-mean ratio > 1 + if (prob > 1 || dispersion < 0) { + stop( + "Negative binomial has a variance-to-mean ratio of greater ", + "than one, check input" + ) + } + + return( + list( + prob = prob, + dispersion = dispersion + ) + ) +} + +#' Convert parameter of the geometric distribution to summary statistics +#' +#' @description Convert the probability (`prob`) of the geometric distribution +#' to a number of summary statistics which can be calculated analytically given +#' the geometric parameter. One exception is the median which is calculated +#' using [stats::qgeom()] as the analytical form is not always unique. +#' +#' @details This conversion function assumes that distribution represents the +#' number of failures before the first success (supported for zero). This is +#' the same form as used by base R and [distributional::dist_geometric()]. +#' +#' @inheritParams convert_params_to_summary_stats +#' +#' @return A list of eight elements including: mean, median, mode, +#' variance (`var`), standard deviation (`sd`), coefficient of variation (`cv`), +#' skewness, and excess kurtosis (`ex_kurtosis`). +#' @keywords internal +.convert_params_geom <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input params + if (all("prob" %in% names(x))) { + prob <- x[["prob"]] + } else { + stop("geom parameter must be named 'prob'", call. = FALSE) + } + + # check input + checkmate::assert_number(prob, lower = 0, upper = 1) + + # calculate metrics + mean <- (1 - prob) / prob + median <- stats::qgeom(p = 0.5, prob = prob) + mode <- 0 + var <- (1 - prob) / prob^2 + sd <- sqrt(var) + cv <- sd / mean + skewness <- (2 - prob) / sqrt(1 - prob) + ex_kurtosis <- 6 + prob^2 / (1 - prob) + + # return list of metrics + list( + mean = mean, + median = median, + mode = mode, + var = var, + sd = sd, + cv = cv, + skewness = skewness, + ex_kurtosis = ex_kurtosis + ) +} + +#' Convert summary statistics to parameters of the geometric distribution +#' +#' @description Convert summary statistics of the geometric +#' distribution the parameter (`prob`) of the geometric distribution. +#' +#' @details This conversion function assumes that distribution represents the +#' number of failures before the first success (supported for zero). This is +#' the same form as used by base R and [distributional::dist_geometric()]. +#' +#' @inheritParams convert_summary_stats_to_params +#' +#' @return A list of one element, the probability parameter. +#' @keywords internal +.convert_summary_stats_geom <- function(...) { + # capture dynamic dots + x <- rlang::dots_list(..., .ignore_empty = "none", .homonyms = "error") + + # check input + checkmate::assert_list( + x = x, + types = "numeric", + any.missing = FALSE, + all.missing = FALSE, + min.len = 1, + names = "unique" + ) + checkmate::assert_subset( + x = names(x), + choices = c( + "mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis" + ) + ) + + # convert var or cv into sd if available + x <- .get_sd(x) + + # calculate mean + if (checkmate::test_number(x$mean)) { + checkmate::assert_number(x$mean, lower = 0, finite = TRUE) + prob <- 1 / (1 + x$mean) + return(list(prob = prob)) + } + + # if either parameter hasn't been calculated error + stop("Cannot calculate geometric distribution parameter from given input") +} diff --git a/R/create_prob_distribution.R b/R/create_prob_distribution.R new file mode 100644 index 000000000..563e80652 --- /dev/null +++ b/R/create_prob_distribution.R @@ -0,0 +1,199 @@ +#' Create a distribution object +#' +#' @description Creates an S3 class holding the distribution and parameters +#' from the probability distribution name, its parameters and distribution +#' truncation and discretisation. +#' +#' The class holding the distribution depends on whether it is a discretised +#' distribution. For continuous and discrete distributions S3 classes from the +#' \pkg{distributional} package are used, for discretised continuous +#' distributions the an S3 class from the \pkg{distcrete} package is used. +#' +#' For details on the properties of the distribution classes +#' from each respective package see their documentation (either +#' `?distributional` or `?distcrete`) +#' +#' @details Truncation is enabled only for continuous distributions as there +#' is no truncation implemented in \pkg{distcrete}. +#' +#' By default the discretisation of continuous distributions uses a +#' discretisation interval (`interval`) of 1. If the unit of the distribution +#' is days, then this will be discretised by day. The endpoint weighting (`w`) +#' for the discretisation is 1. `w` can be `[0,1]`. For more information please +#' see [distcrete::distcrete()]. +#' +#' @param prob_distribution A `character` string specifying the probability +#' distribution. This should match the \R naming convention of probability +#' distributions (e.g. lognormal is `lnorm`, negative binomial is `nbinom`, and +#' geometric is `geom`). +#' @param prob_distribution_params A named vector of probability distribution +#' parameters. +#' @param discretise A boolean `logical` whether the distribution is +#' discretised. Default is `FALSE` which assumes a continuous probability +#' distribution. +#' @param truncation A `numeric` specifying the truncation point if the inferred +#' distribution was truncated, `NA` if not or unknown. +#' @param ... [dots] Extra arguments to be passed to +#' \pkg{distributional} or \pkg{distcrete} functions that construct the S3 +#' distribution objects. To see which arguments can be adjusted for discretised +#' distributions see [distcrete::distcrete()], for other distributions see +#' the `?distributional` documentation and find the specific distribution +#' constructor function, e.g. for the Gamma distribution see +#' [distributional::dist_gamma()]. +#' +#' @return An S3 class containing the probability distribution or a `character` +#' string if the parameters of the probability distribution are unknown. +#' @export +#' +#' @examples +#' # example with continuous distribution without truncation +#' create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1), +#' discretise = FALSE, +#' truncation = NA +#' ) +#' +#' # example with continuous distribution with truncation +#' create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1), +#' discretise = FALSE, +#' truncation = 10 +#' ) +#' +#' # example with discrete distribution +#' create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1), +#' discretise = TRUE, +#' truncation = NA +#' ) +#' +#' # example passing extra arguments to distcrete +#' create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1), +#' discretise = TRUE, +#' truncation = NA, +#' w = 0.5 +#' ) +create_prob_distribution <- function(prob_distribution, + prob_distribution_params, + discretise = FALSE, + truncation = NA, + ...) { + checkmate::assert_character( + prob_distribution, + min.chars = 1, + min.len = 1, + max.len = 2 + ) + + # when only the type of probability distribution is known return string + if (missing(prob_distribution_params) || anyNA(prob_distribution_params)) { + return(prob_distribution) + } + + # NA parameters will be caught by if above so only need to check numeric + stopifnot( + "`prob_distribution_params` must be a named vector of numerics or NA" = + checkmate::test_numeric(prob_distribution_params, names = "unique") + ) + checkmate::assert_logical(discretise, len = 1) + checkmate::assert_number(truncation, na.ok = TRUE) + + # set prob_distribution to lowercase for downstream case sensitive matching + prob_distribution <- .clean_string(prob_distribution) + + stopifnot( + "Incorrect parameters provided for probability distribution." = + is_epiparameter_params(prob_distribution, prob_distribution_params) + ) + + # standardise common distribution parameters + prob_distribution_params <- .clean_params( + prob_distribution = prob_distribution, + prob_distribution_params = prob_distribution_params + ) + + dots <- list(...) + if (discretise) { + prob_distribution <- match.arg( + prob_distribution, + choices = c("gamma", "lnorm", "weibull", "norm") + ) + # create default list of args to construct <distcrete> + distcrete_args <- c( + name = prob_distribution, + interval = 1, + as.list(prob_distribution_params), + w = 1 + ) + # modify <distcrete> args if provided in dots + distcrete_args <- utils::modifyList(distcrete_args, dots) + # create discretised probability distribution object + prob_distribution <- do.call( + distcrete::distcrete, + distcrete_args + ) + } else { + # currently dots not used to construct <distribution> + chkDots(...) + # create non-discretised probability distribution object + prob_distribution <- switch(prob_distribution, + gamma = distributional::dist_gamma( + shape = prob_distribution_params[["shape"]], + rate = 1 / prob_distribution_params[["scale"]] + ), + lnorm = distributional::dist_lognormal( + mu = prob_distribution_params[["meanlog"]], + sigma = prob_distribution_params[["sdlog"]] + ), + weibull = distributional::dist_weibull( + shape = prob_distribution_params[["shape"]], + scale = prob_distribution_params[["scale"]] + ), + nbinom = distributional::dist_negative_binomial( + size = prob_distribution_params[["dispersion"]], + prob = convert_summary_stats_to_params( + "nbinom", + mean = prob_distribution_params[["mean"]], + dispersion = prob_distribution_params[["dispersion"]] + )$prob + ), + geom = distributional::dist_geometric( + prob = unname(prob_distribution_params) + ), + pois = distributional::dist_poisson( + lambda = unname(prob_distribution_params) + ), + norm = distributional::dist_normal( + mu = prob_distribution_params[["mean"]], + sigma = prob_distribution_params[["sd"]] + ), + exp = distributional::dist_exponential( + rate = prob_distribution_params[["rate"]] + ), + stop("Did not recognise distribution name", call. = FALSE) + ) + } + + # apply truncation to distribution if specified + if (!is.na(truncation)) { + if (discretise) { + stop( + "Truncation is not yet implemented for discrete distributions.", + call. = FALSE + ) + } else { + prob_distribution <- distributional::dist_truncated( + prob_distribution, + upper = truncation + ) + } + } + + # return prob_distribution object + prob_distribution +} diff --git a/R/data.R b/R/data.R new file mode 100644 index 000000000..120524b41 --- /dev/null +++ b/R/data.R @@ -0,0 +1,14 @@ +#' A vector of `character` strings with the core column names of the +#' epidemiological parameter data exported by the \pkg{epireview} R package. +#' +#' A subset of data from the World Health Organization Global Tuberculosis +#' Report ... +#' +#' @format ## `epireview_core_cols` +#' A `character` vector with 56 elements +#' +#' The data is taken as the intersection of the column names of each of the +#' disease parameter tables in the \pkg{epireview} R package. +#' +#' @source <https://github.com/mrc-ide/epireview> +"epireview_core_cols" diff --git a/R/dev-utils.R b/R/dev-utils.R new file mode 100644 index 000000000..2582d72d3 --- /dev/null +++ b/R/dev-utils.R @@ -0,0 +1,18 @@ +# This unexported function adds a custom item to `usethis::use_release_issue()` +release_bullets <- function() { # nocov start + + c( + "Run `goodpractice::gp()`", + "Review [WORDLIST](https://docs.cran.dev/spelling#wordlist)", + "Check if `# nolint` comments are still needed with recent lintr releases", + "All contributors to this release are acknowledged in some way", + "Run data-raw/parameters.R script to update sysdata", # nolint nonportable_path_linter + "Run vignettes/precompile.R to regenerate `extract-bias.Rmd` vignette" # nolint nonportable_path_linter + ) + +} # nocov end + +# Copied from potools +tr_ <- function(...) { + enc2utf8(gettext(paste0(...), domain = "R-{mypackage}")) +} diff --git a/R/epiparameter-package.R b/R/epiparameter-package.R new file mode 100644 index 000000000..015754d10 --- /dev/null +++ b/R/epiparameter-package.R @@ -0,0 +1,9 @@ +# https://usethis.r-lib.org/reference/use_package_doc.html + +#' @keywords internal +"_PACKAGE" + +## usethis namespace: start +#' @importFrom lifecycle deprecated +## usethis namespace: end +NULL diff --git a/R/epiparameter-utils.R b/R/epiparameter-utils.R new file mode 100644 index 000000000..371ad1155 --- /dev/null +++ b/R/epiparameter-utils.R @@ -0,0 +1,801 @@ +#' Specify distribution parameter uncertainty +#' +#' @description A helper function when creating uncertainty for the parameters +#' of the distribution for the `<epiparameter>` object. +#' +#' @param ci_limits A numeric vector of length two with the lower and upper +#' bound of the confidence interval or credible interval. +#' @param ci A numeric specifying the interval for the ci, e.g. 95 is +#' 95% ci. +#' @param ci_type A character string, either `"confidence interval"` or +#' `"credible interval"`. +#' +#' @return List of three elements: +#' +#' 1. `$ci_limits` is the upper and lower bounds +#' of the CI (either confidence interval or credible interval) (i.e. a two +#' element numeric vector). +#' 2. `$ci` the interval (e.g. 95 is 95% CI) given by a +#' single numeric. +#' 3. `$ci_type` a character string specifying the type of +#' uncertainty (can be either `"confidence interval"` or `"credible interval"`). +#' @export +#' +#' @examples +#' # example with uncertainty for a single parameter +#' create_uncertainty( +#' ci_limits = c(1, 3), +#' ci = 95, +#' ci_type = "confidence interval" +#' ) +#' +#' # example for multiple parameters +#' # lengh of list should match number of parameters +#' list( +#' shape = create_uncertainty( +#' ci_limits = c(1, 3), +#' ci = 95, +#' ci_type = "confidence interval" +#' ), +#' scale = create_uncertainty( +#' ci_limits = c(2, 4), +#' ci = 95, +#' ci_type = "confidence interval" +#' ) +#' ) +#' +#' # example with unknown uncertainty +#' # the function can be called without arguments +#' create_uncertainty() +#' # or give NA as the first argument +#' create_uncertainty(NA) +create_uncertainty <- function(ci_limits = NA_real_, ci, ci_type) { + # when no uncertainty is given + if (anyNA(ci_limits)) { + return(list( + ci_limits = NA_real_, + ci = c(NA_real_, NA_real_), + ci_type = NA_character_ + )) + } + + # check input + checkmate::assert_numeric(ci_limits, any.missing = FALSE, len = 2) + checkmate::assert_number(ci, lower = 0, upper = 100) + checkmate::assert_character(ci_type) + stopifnot( + "ci_type must be either 'confidence interval or credible interval" = + all(ci_type %in% c("confidence interval", "credible interval")) + ) + + # return list of parameter uncertainty + list( + ci_limits = ci_limits, + ci = ci, + ci_type = ci_type + ) +} + + +#' Specify metadata associated with data set +#' +#' @description A helper function when creating an `<epiparameter>` object to +#' create a metadata list with sensible defaults, type checking and arguments +#' to help remember metadata list structure (element names). +#' +#' @details In vector-borne diseases the transmissibility of a disease is +#' dependent on both the time taken for a host (i.e. human) to become +#' infectious, but also on the time it takes the vector to become infectious. +#' Therefore, the extrinsic delay, in which the vector has been infected by is +#' not yet infectious can have a role in the spread of a disease. +#' +#' @param units A `character` for the units of the epidemiological parameter. +#' @param sample_size The sample of the data used to fit the delay distribution. +#' This is usually the number of people with data on a primary and possibly +#' secondary event of interest. In cases where the sample size is not stated +#' NA can be used. +#' @param region The geographical location the data was collected. This can +#' either be given at sub-national, national, continental. Multiple nested +#' regions can be given and are comma separated. When the region is not +#' specified NA can be given. +#' @param transmission_mode A character string specifying how the pathogen is +#' transmitted. This information is used to determine whether the +#' epidemiological parameters are from a vector-borne disease (i.e. is +#' transmitted between humans through an intermediate vector), this is specified +#' by `transmission_mode = "vector_borne"`. +#' @param vector The name of the vector transmitting the vector-borne disease. +#' This can be a common name, or a latin binomial name of a specific vector +#' species. Both the common name and taxonomic name can be given with one given +#' in parentheses. When a disease is not vector-borne NA should be given. +#' @param extrinsic A boolean value defining whether the data entry is an +#' extrinsic delay distribution, such as the extrinsic incubation period. +#' This field is required because intrinsic and extrinsic delay distributions +#' are stored as separate entries in the database and can be linked. +#' When the disease is not vector-borne FALSE should be given. See Details for +#' explanation of extrinsic distribution. +#' @param inference_method The type of inference used to fit the delay +#' distribution to the data. Abbreviations of model fitting techniques can be +#' specified as long as they are non-ambiguous. This field is only used to +#' determine whether the uncertainty intervals possibly specified in the other +#' fields are: confidence intervals (in the case of maximum likelihood), or +#' credible intervals (in the case of bayesian inference). Uncertainty bounds +#' for another types of inference methods, or if the inference method is +#' unstated are assumed to be confidence intervals. When the inference method +#' is unknown or a disease does not have a probability distribution NA can be +#' given. +#' +#' @return A named list containing information on the sample size of the study, +#' geography, whether the disease is vector-borne and if so whether it is the +#' intrinsic or extrinsic distribution as well as method of distribution +#' parameter estimation. +#' @export +#' +#' @examples +#' # it will automatically populate the fields with defaults if left empty +#' create_metadata() +#' +#' # supplying each field +#' create_metadata( +#' units = "days", +#' sample_size = 10, +#' region = "UK", +#' transmission_mode = "vector_borne", +#' vector = "mosquito", +#' extrinsic = FALSE, +#' inference_method = "MLE" +#' ) +create_metadata <- function(units = NA_character_, + sample_size = NA_integer_, + region = NA_character_, + transmission_mode = NA_character_, + vector = NA_character_, + extrinsic = FALSE, + inference_method = NA_character_) { + # check input + checkmate::assert_character(units) + checkmate::assert_number( + sample_size, + na.ok = TRUE, + lower = 0, + finite = TRUE, + null.ok = TRUE + ) + checkmate::assert_character(region) + checkmate::assert_character(transmission_mode, len = 1) + checkmate::assert_character(vector) + checkmate::assert_logical(extrinsic, len = 1) + checkmate::assert_character(inference_method) + + if (transmission_mode != "vector_borne" && !is.na(vector)) { + stop( + "A vector is given for a non-vector-borne disease please check input", + call. = FALSE + ) + } + + # return list of metadata + list( + units = units, + sample_size = sample_size, + region = region, + transmission_mode = transmission_mode, + vector = vector, + extrinsic = extrinsic, + inference_method = inference_method + ) +} + +#' Specify the geography of the data entry +#' +#' @description The geography of the data set can be a single geographical +#' region at either continent, country, region or city level. By specifying +#' the level of the geography the other fields may be deduced. +#' +#' @param continent A `character` string specifying the continent. +#' @param country A `character` string specifying the country. +#' @param region A `character` string specifying the region. +#' @param city A `character` string specifying the city. +#' +#' @return A named list. +#' @export +#' +#' @examples +#' create_region(country = "UK") +create_region <- function(continent = NA_character_, + country = NA_character_, + region = NA_character_, + city = NA_character_) { + checkmate::assert_string(continent, na.ok = TRUE) + checkmate::assert_string(country, na.ok = TRUE) + checkmate::assert_string(region, na.ok = TRUE) + checkmate::assert_string(city, na.ok = TRUE) + + # return list of regions + list( + continent = continent, + country = country, + region = region, + city = city + ) +} + +# nolint start: line_length_linter +#' Specify reported summary statistics +#' +#' @description A helper function when creating an `<epiparameter>` object to +#' create a summary statistics list with sensible defaults, type checking +#' and arguments to help remember which summary statistics can be accepted in +#' the list. +#' +#' @param mean A `numeric` of the mean (expectation) of the probability +#' distribution. +#' @param mean_ci_limits A `numeric` vector of length two of the confidence +#' interval around the mean. +#' @param mean_ci A `numeric` specifying the confidence interval width, +#' e.g. `95` would be the 95% CI +#' @param sd A `numeric` of the standard deviation of the probability +#' distribution. +#' @param sd_ci_limits A `numeric` vector of length 2 of the confidence interval +#' around the standard deviation. +#' @param sd_ci A `numeric` specifying the confidence interval width, +#' e.g. `95` would be 95% confidence interval. +#' @param median A `numeric` of the median of the probability distribution. +#' @param median_ci_limits A `numeric` vector of length two of the confidence +#' interval around the median. +#' @param median_ci A `numeric` specifying the confidence interval width +#' of the median. +#' @param dispersion A `numeric` of the dispersion of the probability +#' distribution. **Important** this is the dispersion for probability +#' distributions that are not usually parameterised by a dispersion parameter, +#' for example a lognormal distribution. If a probability distribution is +#' usually parameterised with a dispersion parameter, e.g. negative binomial +#' distribution, then this should be considered a parameter and not a summary +#' statistic and should go in the `prob_distribution` argument when +#' constructing an `<epiparameter>` object with [epiparameter()] +#' (see [create_prob_distribution()]). +#' @param dispersion_ci_limits A `numeric` vector of length 2 of the confidence +#' interval around the dispersion. +#' @param dispersion_ci A `numeric` specifying the confidence interval width, +#' e.g. `95` would be 95% confidence interval. +#' @param lower_range The lower range of the data, used to infer the parameters +#' of the distribution when not provided. +#' @param upper_range The upper range of the data, used to infer the parameters +#' of the distribution when not provided. +#' @param quantiles A `numeric` vector of the quantiles for the distribution. +#' If quantiles are not provided a default empty vector with the 2.5th, 5th, +#' 25th, 75th, 95th, 97.5th quantiles are supplied. +#' +#' @return A list of summary statistics. The output list has element names +#' equal to the function arguments: +#' \preformatted{ +#' `r paste("$", names(formals(create_summary_stats)), sep = "", collapse = "\n")` +#' } +#' @export +#' +#' @examples +#' # mean and standard deviation +#' create_summary_stats(mean = 5, sd = 2) +#' +#' # mean and standard deviation with uncertainty +#' create_summary_stats( +#' mean = 4, +#' mean_ci_limits = c(2.1, 5.7), +#' mean_ci = 95, +#' sd = 0.7, +#' sd_ci_limits = c(0.3, 1.1), +#' sd_ci = 95 +#' ) +#' +#' # median and range +#' create_summary_stats( +#' median = 5, +#' lower_range = 1, +#' upper_range = 13 +#' ) +# nolint end: line_length_linter +create_summary_stats <- function(mean = NA_real_, + mean_ci_limits = c(NA_real_, NA_real_), + mean_ci = NA_real_, + sd = NA_real_, + sd_ci_limits = c(NA_real_, NA_real_), + sd_ci = NA_real_, + median = NA_real_, + median_ci_limits = c( + NA_real_, + NA_real_ + ), + median_ci = NA_real_, + dispersion = NA_real_, + dispersion_ci_limits = c(NA_real_, NA_real_), + dispersion_ci = NA_real_, + lower_range = NA_real_, + upper_range = NA_real_, + quantiles = NA_real_) { + # check input + checkmate::assert_number(mean, na.ok = TRUE) + checkmate::assert_numeric(mean_ci_limits, len = 2, any.missing = TRUE) + checkmate::assert_number(mean_ci, na.ok = TRUE) + checkmate::assert_number(sd, na.ok = TRUE) + checkmate::assert_numeric(sd_ci_limits, len = 2, any.missing = TRUE) + checkmate::assert_number(sd_ci, na.ok = TRUE) + checkmate::assert_number(median, na.ok = TRUE) + checkmate::assert_numeric(median_ci_limits, len = 2, any.missing = TRUE) + checkmate::assert_number(median_ci, na.ok = TRUE) + checkmate::assert_number(dispersion, na.ok = TRUE) + checkmate::assert_numeric(dispersion_ci_limits, len = 2, any.missing = TRUE) + checkmate::assert_number(dispersion_ci, na.ok = TRUE) + checkmate::assert_number(lower_range, na.ok = TRUE) + checkmate::assert_number(upper_range, na.ok = TRUE) + checkmate::assert_numeric(quantiles) + if (!all(is.na(quantiles))) { + checkmate::assert_named(quantiles) + } + + # return list of summary stats + list( + mean = mean, + mean_ci_limits = mean_ci_limits, + mean_ci = mean_ci, + sd = sd, + sd_ci_limits = sd_ci_limits, + sd_ci = sd_ci, + median = median, + median_ci_limits = median_ci_limits, + median_ci = median_ci, + dispersion = dispersion, + dispersion_ci_limits = dispersion_ci_limits, + dispersion_ci = dispersion_ci, + quantiles = quantiles, + range = c(lower_range, upper_range) + ) +} + +#' Create a citation for an `<epiparameter>` object +#' +#' @description A helper function when creating an `<epiparameter>` object to +#' create a citation list with sensible defaults, type checking and arguments +#' to help remember which citation information is accepted in the list. +#' +#' @details This function acts as a wrapper around [bibentry()] to create +#' citations for sources reporting epidemiological parameters. +#' +#' @param author Either a `<person>`, a `character` string, or a vector or list +#' of `characters` in the case of multiple authors. Specify the full name +#' (`"<given name>" "<family name>"`). When using `characters` make sure the +#' name can be converted to a `<person>` (see [as.person()]). Use white space +#' separation between names. Multiple names can be stored within a single +#' `<person>` (see [person()]). +#' @param year A `numeric` of the year of publication. +#' @param title A `character` string with the title of the article that +#' published the epidemiological parameters. +#' @param journal A `character` string with the name of the journal that +#' published the article that published the epidemiological parameters. +#' This can also be a pre-print server, e.g., medRxiv. +#' @param pmid A `character` string with the PubMed unique identifier number +#' (PMID) assigned to papers to give them a unique identifier within PubMed. +#' @param doi A `character` string of the Digital Object Identifier (DOI) +#' assigned to papers which are unique to each paper. +#' +#' @return A `<bibentry>` object of the citation +#' @export +#' +#' @examples +#' create_citation( +#' author = person(given = "John", family = "Smith"), +#' year = 2002, +#' title = "COVID-19 incubation period", +#' journal = "Epi Journal", +#' doi = "10.19832/j.1366-9516.2012.09147.x" +#' ) +create_citation <- function(author = utils::person(), + year = NA_integer_, + title = NA_character_, + journal = NA_character_, + doi = NA_character_, + pmid = NA_integer_) { + # if not <person> try and convert author to <person> + if (!inherits(author, "person")) + tryCatch(expr = { + author <- lapply(author, utils::as.person) + author <- Reduce(f = c, x = author) + }, + error = function(cnd) { + stop("Authors incorrectly formatted", call. = FALSE) + } + ) + + # check input + checkmate::assert_class(author, classes = "person") + checkmate::assert_number(year, na.ok = TRUE) + checkmate::assert_character(title) + checkmate::assert_character(journal) + checkmate::assert_character(doi) + checkmate::assert_number(pmid, na.ok = TRUE) + + if (length(author) == 0 || is.na(year) || is.na(journal) || is.na(title)) { + message( + "Citation cannot be created as author, year, journal or title is missing" + ) + return(utils::bibentry(bibtype = "Misc", title = "No citation")) + } + + citation <- utils::bibentry( + bibtype = "article", + author = author, + year = year, + title = title, + journal = journal, + doi = doi + ) + citation$pmid <- pmid + + message( + "Using ", format(citation), " \n", + "To retrieve the citation use the 'get_citation' function" + ) + + citation +} + +#' Specify methodological aspects of distribution fitting +#' +#' @description A helper function when creating an `<epiparameter>` object to +#' create a method assessment list with sensible defaults, type checking and +#' arguments to help remember which method assessments can be accepted in +#' the list. +#' +#' @details Currently, the method assessment focuses on common methodological +#' aspects of delay distributions (e.g. incubation period, serial interval, +#' etc.), and does not currently take into account methodological aspects which +#' may be important when fitting offspring distributions to data on disease +#' (super)spreading. +#' +#' @param censored A boolean `logical` whether the study used single or double +#' interval censoring in the methods to infer the delay distribution +#' @param right_truncated A boolean `logical` whether the study used right- +#' truncation in the methods to infer the delay distribution +#' @param phase_bias_adjusted A boolean `logical` whether the study adjusted for +#' phase bias in the methods to infer the delay distribution +#' +#' @return A named list with three elements +#' @export +#' +#' @examples +#' create_method_assess( +#' censored = FALSE, +#' right_truncated = FALSE, +#' phase_bias_adjusted = FALSE +#' ) +create_method_assess <- function(censored = NA, + right_truncated = NA, + phase_bias_adjusted = NA) { + # check input + checkmate::assert_logical(censored, len = 1) + checkmate::assert_logical(right_truncated, len = 1) + checkmate::assert_logical(phase_bias_adjusted, len = 1) + + # return method assessment list + list( + censored = censored, + right_truncated = right_truncated, + phase_bias_adjusted = phase_bias_adjusted + ) +} + +#' Check whether the vector of parameters for the probability distribution +#' are in the set of possible parameters used in the epiparameter package +#' +#' @details +#' This check for valid parameters is independent of whether the distribution +#' is truncated or discretised. +#' +#' @inheritParams create_prob_distribution +#' +#' @return A boolean `logical`. +#' @export +#' +#' @examples +#' is_epiparameter_params( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 2, scale = 1) +#' ) +is_epiparameter_params <- function(prob_distribution, + prob_distribution_params) { + if (is.na(prob_distribution) || anyNA(prob_distribution_params)) { + return(FALSE) + } + + # mixture distributions can multiple of the same parameters + if (prob_distribution != "mixture") { + checkmate::assert_numeric( + prob_distribution_params, + min.len = 1, + names = "unique" + ) + } + + # remove truncation parameters if truncated + if ("upper" %in% names(prob_distribution_params)) { + prob_distribution_params <- prob_distribution_params[ + names(prob_distribution_params) != c("lower", "upper") + ] + } + + # create dictionary of valid parameter combinations + possible_params <- list( + gamma = list(c("shape", "scale"), c("shape", "rate")), + weibull = list(c("shape", "scale")), + lnorm = list(c("meanlog", "sdlog"), c("mu", "sigma")), + nbinom = list(c("mean", "dispersion"), c("mean", "k"), c("n", "p")), + geom = list("mean", "p", "prob"), + pois = list("mean", "l", "lambda"), + norm = list(c("mean", "sd"), c("mu", "sigma")), + exp = list("rate", "lambda", "mean") + ) + if (prob_distribution != "mixture") { + possible_params <- possible_params[[prob_distribution]] + } else { + possible_params <- list(names(prob_distribution_params)) + } + + # check whether any combinations are valid + matches <- vapply( + possible_params, + function(x, y) all(names(y) %in% x) && identical(length(y), length(x)), + y = prob_distribution_params, + FUN.VALUE = logical(1) + ) + + # return whether check for valid params result + any(matches) +} + +#' Standardise distribution parameters +#' +#' @description `.clean_params()` dispatches to a distribution +#' specific parameter cleaning function depending on `prob_dist`. For example +#' `prob_dist = "gamma"` will call `.clean_params_gamma()`. +#' +#' @details +#' Calling [is_epiparameter_params()] at the start of +#' `.clean_params()` ensures that if the parameterisation is +#' incorrect that it will error early and dispatch to the distribution +#' specific cleaning functions (e.g. `.clean_params_gamma()`). +#' This means that the distribution specific parameter cleaning functions do +#' not need to check and error for incorrect parameterisation. +#' +#' @inheritParams create_prob_distribution +#' +#' @name .clean_params +#' +#' @return Named `numeric` vector of parameters. +#' @keywords internal +.clean_params <- function(prob_distribution, prob_distribution_params) { + valid_params <- is_epiparameter_params( + prob_distribution = prob_distribution, + prob_distribution_params = prob_distribution_params + ) + if (!valid_params) { + stop( + "Invalid parameterisation for ", prob_distribution, " distribution", + call. = FALSE + ) + } + is_trunc <- "upper" %in% names(prob_distribution_params) + # remove truncation parameters if truncated + if (is_trunc) { + trunc_params <- prob_distribution_params[ + names(prob_distribution_params) == c("lower", "upper") + ] + prob_distribution_params <- prob_distribution_params[ + names(prob_distribution_params) != c("lower", "upper") + ] + } + # weibull only has one parameterisation so does not need cleaning + # mixture can have many parameterisations so is not cleaned + clean_func <- switch( + prob_distribution, + gamma = .clean_params_gamma, + lnorm = .clean_params_lnorm, + weibull = function(x) x, + nbinom = .clean_params_nbinom, + geom = .clean_params_geom, + pois = .clean_params_pois, + norm = .clean_params_norm, + exp = .clean_params_exp, + mixture = function(x) x, + stop("Probability distribution not recognised", call. = FALSE) + ) + clean_params <- do.call(clean_func, list(prob_distribution_params)) + # reappend truncation parameter if truncated + if (is_trunc) { + clean_params <- append(clean_params, trunc_params) + } + + # return parameters + clean_params +} + +#' @name .clean_params +.clean_params_gamma <- function(prob_dist_params) { + # no cleaning needed for shape and scale parameterisation + # if shape and rate are provided convert to shape and scale + if (identical(names(prob_dist_params), c("shape", "rate"))) { + prob_dist_params[["rate"]] <- 1 / prob_dist_params[["rate"]] + names(prob_dist_params) <- gsub( + pattern = "rate", + replacement = "scale", + x = names(prob_dist_params), + fixed = TRUE + ) + } + # return prob_dist_params + prob_dist_params +} + +#' @name .clean_params +.clean_params_lnorm <- function(prob_dist_params) { + # no cleaning needed for meanlog and sdlog parameterisation + # if mu and sigma are provided convert to meanlog and sdlog + if (identical(names(prob_dist_params), c("mu", "sigma"))) { + # find index so parameters can be in any order + mu_index <- which(names(prob_dist_params) == "mu") + sigma_index <- which(names(prob_dist_params) == "sigma") + names(prob_dist_params)[c(mu_index, sigma_index)] <- c("meanlog", "sdlog") + } + # return prob_dist_params + prob_dist_params +} + +#' @name .clean_params +.clean_params_nbinom <- function(prob_dist_params) { + # no cleaning needed for mean and dispersion parameterisation + if (identical(names(prob_dist_params), c("n", "p"))) { + # convert prob to mean + prob_dist_params[["p"]] <- convert_params_to_summary_stats( + "nbinom", + prob = prob_dist_params[["p"]], + dispersion = prob_dist_params[["n"]] + )$mean + + # find index so parameters can be in any order + n_index <- which(names(prob_dist_params) == "n") + p_index <- which(names(prob_dist_params) == "p") + names(prob_dist_params)[c(n_index, p_index)] <- c("dispersion", "mean") + + # rearrange vector + prob_dist_params <- prob_dist_params[c("mean", "dispersion")] + } + # return prob_dist_params + prob_dist_params +} + +#' @name .clean_params +.clean_params_geom <- function(prob_dist_params) { + # no cleaning needed for prob parameterisation + # if mean is provided convert to prob + if (identical(names(prob_dist_params), "mean")) { + prob_dist_params[["mean"]] <- 1 / prob_dist_params[["mean"]] + names(prob_dist_params) <- gsub( + pattern = "mean", + replacement = "prob", + x = names(prob_dist_params), + fixed = TRUE + ) + } else if (identical(names(prob_dist_params), "p")) { + names(prob_dist_params) <- gsub( + pattern = "^p$", + replacement = "prob", + x = names(prob_dist_params) + ) + } + # return prob_dist_params + prob_dist_params +} + +#' @name .clean_params +.clean_params_pois <- function(prob_dist_params) { + if (names(prob_dist_params) %in% c("mean", "l", "lambda")) { + names(prob_dist_params) <- "mean" + } + # return prob_dist_params + prob_dist_params +} + +#' @name .clean_params +.clean_params_norm <- function(prob_dist_params) { + # no cleaning needed for mean and sd parameterisation + if (identical(names(prob_dist_params), c("mu", "sigma"))) { + + # find index so parameters can be in any order + mean_index <- which(names(prob_dist_params) == "mu") + sd_index <- which(names(prob_dist_params) == "sigma") + names(prob_dist_params)[c(mean_index, sd_index)] <- c("mean", "sd") + + # rearrange vector + prob_dist_params <- prob_dist_params[c("mean", "sd")] + } + # return prob_dist_params + prob_dist_params +} + +#' @name .clean_params +.clean_params_exp <- function(prob_dist_params) { + # no cleaning needed for rate parameterisation + if (identical(names(prob_dist_params), "lambda")) { + names(prob_dist_params) <- "rate" + } else if (identical(names(prob_dist_params), "mean")) { + names(prob_dist_params) <- "rate" + prob_dist_params[["rate"]] <- 1 / prob_dist_params[["rate"]] + } + # return prob_dist_params + prob_dist_params +} + +#' Standardise the variables input by users +#' +#' @description +#' Checks a user has supplied a `character` string and converts +#' to \pkg{epiparameter} standards: lower-case and whitespace instead of +#' dashes or underscores. +#' +#' Examples of strings needing to be cleaned are: disease and pathogen names, +#' and epidemiological distributions. +#' +#' @param x A `character` string. +#' +#' @return A `character` vector of equal length to the input. +#' @keywords internal +.clean_string <- function(x) { + checkmate::assert_character(x) + gsub(pattern = "_|-", replacement = " ", x = trimws(tolower(x))) +} + +#' Standardise distribution parameter uncertainty +#' +#' @param x An `<epiparameter>` object. +#' @inheritParams epiparameter +#' @param uncertainty_missing A boolean `logical` as to whether `uncertainty` +#' is missing (see [missing()]) from the parent function. +#' +#' @return An uncertainty list for an `<epiparameter>` object. +#' @keywords internal +.clean_uncertainty <- function(x, prob_distribution, uncertainty_missing) { + param_names <- names(get_parameters(x)) + param_names <- param_names %||% NA_character_ + if (uncertainty_missing || + !identical(prob_distribution, x$prob_distribution)) { + # create uncertainty for each parameter if not provided or auto calculated + x$uncertainty <- lapply( + param_names, + function(xx) list(uncertainty = create_uncertainty()) + ) + if (!anyNA(param_names)) names(x$uncertainty) <- param_names + } else { + ci_limits_ <- lapply(x$uncertainty, `[[`, 1) + # if uncertainty is unspecified then it only needs renaming + if (anyNA(ci_limits_, recursive = TRUE)) { + if (!anyNA(param_names)) names(x$uncertainty) <- param_names + } else { + # standardise parameter uncertainty in to match parameters + dist <- family(x) + params_ <- vector(mode = "list", length = length(x$uncertainty)) + names(params_) <- param_names + for (i in seq_along(ci_limits_)) { + params <- vapply(ci_limits_, `[[`, FUN.VALUE = numeric(1), i) + temp <- as.list(.clean_params( + prob_distribution = dist, + prob_distribution_params = params + )) + params_ <- Map(c, params_, temp) + } + ci_limits_ <- lapply(params_, function(x) sort(unname(x))) + for (i in seq_along(x$uncertainty)) { + x$uncertainty[[i]]$ci_limits <- ci_limits_[[i]] + } + names(x$uncertainty) <- param_names + } + } + # return <epiparameter> uncertainty + x$uncertainty +} diff --git a/R/epiparameter.R b/R/epiparameter.R new file mode 100644 index 000000000..e40b8e6c7 --- /dev/null +++ b/R/epiparameter.R @@ -0,0 +1,996 @@ +#' Constructor for `<epiparameter>` class +#' +#' @description Create an `<epiparameter>` object. The +#' constructor will search whether parameters of the probability distribution +#' are supplied and if not look to see whether they can be inferred/extracted/ +#' converted from summary statistics provided. It will also convert the +#' probability distribution (`prob_dist`) and its parameters +#' (`prob_dist_params`) into an S3 class, either a `distribution` object from +#' `{distributional}` when `discretise = FALSE`, or a `distcrete` object from +#' `{distcrete}` when `discretise = TRUE`. +#' +#' @inheritParams epiparameter +#' +#' @inherit epiparameter return +#' @keywords internal +new_epiparameter <- function(disease = character(), + pathogen = character(), + epi_name = character(), + prob_distribution = list(), + uncertainty = list(), + summary_stats = list(), + citation = character(), + metadata = list(), + method_assess = list(), + notes = character(), + auto_calc_params = logical(), + ...) { + if (auto_calc_params && is.character(prob_distribution)) { + # calculate parameters if not provided + prob_distribution_params <- .calc_dist_params( + prob_distribution = prob_distribution, + summary_stats = summary_stats, + sample_size = metadata$sample_size + ) + if (!anyNA(prob_distribution_params)) { + prob_distribution <- create_prob_distribution( + prob_distribution = prob_distribution, + prob_distribution_params = prob_distribution_params, + ... + ) + message( + "Parameterising the probability distribution with the summary ", + "statistics.\n Probability distribution is assumed not to be ", + "discretised or truncated." + ) + } + if (!inherits(prob_distribution, c("distribution", "distcrete"))) { + message("Unparameterised <epiparameter> object") + } + } + + if (epi_name == "offspring_distribution") { + method_assess <- paste( + "There is currently no method assessment for offspring distributions", + "stored in epiparameter" + ) + } + + if (is.null(notes)) { + notes <- "No additional notes" + } + + # create and return epiparameter class + structure( + list( + disease = disease, + pathogen = pathogen, + epi_name = epi_name, + prob_distribution = prob_distribution, + uncertainty = uncertainty, + summary_stats = summary_stats, + citation = citation, + metadata = metadata, + method_assess = method_assess, + notes = notes + ), + class = "epiparameter", + .epiparameter_namespace = .epiparameter_namespace + ) +} + +# Load {epiparameter} namespace when using <epiparameter> +# (incl. serialised objects) +.epiparameter_namespace <- function() NULL + +#' Create an `<epiparameter>` object +#' +#' @description The `<epiparameter>` class is used to store epidemiological +#' parameters for a single disease. These epidemiological parameters cover a +#' variety of aspects including delay distributions (e.g. incubation periods +#' and serial intervals, among others) and offspring distributions. +#' +#' The `<epiparameter>` object is the functional unit provided by +#' `{epiparameter}` to plug into epidemiological pipelines. Obtaining an +#' `<epiparameter>` object can be achieved in two main ways: +#' 1. The epidemiological distribution is stored in +#' the `{epiparameter}` library and can be accessed by [epiparameter_db()]. +#' 2. The alternative method is when you have information +#' (e.g. disease and distribution parameter estimates) and would like to input +#' this into an `<epiparameter>` object in order to work in existing analysis +#' pipelines. This is where the `epiparameter()` function can be used to fill +#' out each field for which information is known. +#' +#' @details Accepted `<epiparameter>` distribution parameterisations are: +#' - Gamma must be either 'shape' and 'scale' or 'shape' and 'rate' +#' - Weibull must be 'shape' and 'scale' +#' - Lognormal must be 'meanlog' and 'sdlog' or 'mu' and 'sigma' +#' - Negative Binomial must be either 'mean' and 'dispersion' or 'n' and 'p' +#' - Geometric must be either 'mean' or 'prob' +#' - Poisson must be 'mean' +#' +#' @param disease A `character` string with name of the infectious disease. +#' @param pathogen A `character` string with the name of the causative agent of +#' disease, or `NA` if not known. +#' @param epi_name A `character` string with the name of the +#' epidemiological parameter type. +#' @param prob_distribution An S3 class containing the probability +#' distribution or a character string if the parameters of the probability +#' distribution are unknown but the name of the distribution is known, or `NA` +#' if the distribution name and parameters are unknown. Use +#' [create_prob_distribution()] to create `prob_distribution`. +#' @param uncertainty A list of named vectors with the uncertainty around +#' the probability distribution parameters. If uncertainty around the parameter +#' estimates is unknown use [create_uncertainty()] (which is the +#' argument default) to create a list with the correct names with missing +#' values. +#' @param summary_stats A list of summary statistics, use +#' [create_summary_stats()] to create list. This list can include +#' summary statistics about the inferred distribution such as it's mean and +#' standard deviation, quantiles of the distribution, or information about the +#' data used to fit the distribution such as lower and upper range. The summary +#' statistics can also include uncertainty around metrics such as confidence +#' interval around mean and standard deviation. +#' @param auto_calc_params A boolean `logical` determining whether to try and +#' calculate the probability distribution parameters from summary statistics if +#' distribution parameters are not provided. Default is `TRUE`. In the case when +#' sufficient summary statistics are provided and the parameter(s) of the +#' distribution are not, the [.calc_dist_params()] function is called to +#' calculate the parameters and add them to the `epiparameter` object created. +#' @param citation A `<bibentry>` with the citation of the source of the +#' data or the paper that inferred the distribution parameters, use +#' [create_citation()] to create citation. +#' @param metadata A list of metadata, this can include: units, sample size, +#' the transmission mode of the disease (e.g. is it vector-borne or directly +#' transmitted), etc. It is assumed that the disease is not +#' vector-borne and that the distribution is intrinsic (e.g. not an extrinsic +#' delay distribution such as extrinsic incubation period) unless +#' `transmission_mode = "vector_borne"` is contained in the metadata. Use +#' [create_metadata()] to create metadata. +#' @param method_assess A list of methodological aspects used when fitting +#' the distribution, use [create_method_assess()] to create method +#' assessment. +#' @param notes A `character` string with any additional information about the +#' data, inference method or disease. +#' @param ... [dots] Extra arguments to be passed to internal functions. +#' +#' This is most commonly used to pass arguments to [distcrete::distcrete()] +#' that construct the discretised distribution S3 object. To see which +#' arguments can be adjusted for discretised distributions see +#' [distcrete::distcrete()]. +#' +#' @return An `<epiparameter>` object. +#' @export +#' +#' @examples +#' # minimal input required for `epiparameter` +#' ebola_incubation <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' +#' # minimal input required for discrete `epiparameter` +#' ebola_incubation <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1), +#' discretise = TRUE +#' ) +#' ) +#' +#' # example with more fields filled in +#' ebola_incubation <- epiparameter( +#' disease = "ebola", +#' pathogen = "ebola_virus", +#' epi_name = "incubation", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1), +#' discretise = FALSE, +#' truncation = NA +#' ), +#' uncertainty = list( +#' shape = create_uncertainty(), +#' scale = create_uncertainty() +#' ), +#' summary_stats = create_summary_stats(mean = 2, sd = 1), +#' citation = create_citation( +#' author = person(given = "John", family = "Smith"), +#' year = 2002, +#' title = "COVID-19 incubation period", +#' journal = "Epi Journal", +#' doi = "10.19832/j.1366-9516.2012.09147.x" +#' ), +#' metadata = create_metadata( +#' units = "days", +#' sample_size = 10, +#' region = "UK", +#' transmission_mode = "natural_human_to_human", +#' inference_method = "MLE" +#' ), +#' method_assess = create_method_assess( +#' censored = TRUE +#' ), +#' notes = "No notes" +#' ) +epiparameter <- function(disease, + pathogen = NA_character_, + epi_name, + prob_distribution = create_prob_distribution( + prob_distribution = NA_character_ + ), + uncertainty = create_uncertainty(), + summary_stats = create_summary_stats(), + citation = create_citation(), + metadata = create_metadata(), + method_assess = create_method_assess(), + notes = NULL, + auto_calc_params = TRUE, + ...) { + # check input + checkmate::assert_string(disease) + checkmate::assert_character(pathogen) + checkmate::assert_string(epi_name) + stopifnot( + "Probability distribution must be a distribution object or a character" = + !inherits(prob_distribution, c("distribution", "distcrete")) || + !is.character(prob_distribution) + ) + checkmate::assert_list(uncertainty, names = "unique") + checkmate::assert_list( + summary_stats, + types = c("numeric", "logical"), + names = "unique", + null.ok = TRUE + ) + checkmate::assert_class(citation, classes = "bibentry") + checkmate::assert_list(metadata) + checkmate::assert_list(method_assess) + checkmate::assert_character(notes, null.ok = TRUE) + + # call epiparameter constructor + epiparameter <- new_epiparameter( + disease = disease, + pathogen = pathogen, + epi_name = epi_name, + prob_distribution = prob_distribution, + uncertainty = uncertainty, + summary_stats = summary_stats, + auto_calc_params = auto_calc_params, + citation = citation, + metadata = metadata, + method_assess = method_assess, + notes = notes, + ... + ) + + # uncertainty is checked after new_epiparameter to use <epiparameter> methods + epiparameter$uncertainty <- .clean_uncertainty( + epiparameter, + prob_distribution = prob_distribution, + uncertainty_missing = missing(uncertainty) + ) + + param_names <- names(get_parameters(epiparameter)) %||% NA_character_ + + stopifnot( + "uncertainty must be provided for each parameter" = + length(param_names) == length(epiparameter$uncertainty), + "parameters and uncertainty must be named and match" = + identical(param_names, names(epiparameter$uncertainty)) || + is.na(param_names) + ) + + # call epiparameter validator + assert_epiparameter(epiparameter) + + # return epiparameter object + epiparameter +} + +#' Assert an object is a valid `<epiparameter>` object +#' +#' @param x An \R object. +#' +#' @return Invisibly returns an `<epiparameter>`. Called for side-effects +#' (errors when invalid `<epiparameter>` object is provided). +#' +#' @export +assert_epiparameter <- function(x) { + if (!is_epiparameter(x)) { + stop("Object should be of class epiparameter", call. = FALSE) + } + + list_names <- c( + "disease", "pathogen", "epi_name", "prob_distribution", "uncertainty", + "summary_stats", "citation", "metadata", "method_assess", "notes" + ) + missing_list_names <- list_names[!list_names %in% attributes(x)$names] + if (length(missing_list_names) != 0) { + stop( + "Object is missing ", toString(missing_list_names), call. = FALSE + ) + } + + # check for class invariants + stopifnot( + "epiparameter must contain a disease (single character string)" = + checkmate::test_string(x$disease), + "epiparameter must contain an epidemiological distribution" = + checkmate::test_string(x$epi_name), + "epiparameter must contain a <distribution> or <distcrete> or NA" = + checkmate::test_multi_class( + x$prob_distribution, classes = c("distribution", "distcrete") + ) || checkmate::test_string(x$prob_distribution, na.ok = TRUE), + "epidisit must contain uncertainty, summary stats and metadata" = + all( + is.list(x$uncertainty), is.list(x$summary_stats), is.list(x$metadata) + ), + "epiparameter must contain a citation" = + inherits(x$citation, "bibentry"), + "epiparameter notes must be a character string" = + checkmate::test_string(x$notes) + ) + + invisible(x) +} + +#' Test whether an object is a valid `<epiparameter>` object +#' +#' @param x An \R object. +#' +#' @return A boolean `logical` whether the object is a valid `<epiparameter>` +#' object. +#' @export +test_epiparameter <- function(x) { # nolint cyclocomp_linter + if (!is_epiparameter(x)) return(FALSE) + + list_names <- c( + "disease", "pathogen", "epi_name", "prob_distribution", "uncertainty", + "summary_stats", "citation", "metadata", "method_assess", "notes" + ) + missing_list_names <- list_names[!list_names %in% attributes(x)$names] + if (length(missing_list_names) != 0) return(FALSE) + + valid_elements <- checkmate::test_string(x$disease) && + checkmate::test_string(x$epi_name) && + (checkmate::test_multi_class( + x$prob_distribution, classes = c("distribution", "distcrete") + ) || checkmate::test_string(x$prob_distribution, na.ok = TRUE)) && + all( + is.list(x$uncertainty), is.list(x$summary_stats), is.list(x$metadata) + ) && + inherits(x$citation, "bibentry") && + checkmate::test_string(x$notes) + + if (!valid_elements) return(FALSE) + return(TRUE) +} + +#' Print method for `<epiparameter>` class +#' +#' @param x An `<epiparameter>` object. +#' @param ... [dots] Extra arguments to be passed to the method. +#' +#' @return Invisibly returns an `<epiparameter>`. Called for side-effects. +#' @export +#' +#' @examples +#' epiparameter <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' epiparameter +print.epiparameter <- function(x, ...) { + format(x, ...) +} + +#' Format method for `<epiparameter>` class +#' +#' @inheritParams print.epiparameter +#' +#' @return Invisibly returns an `<epiparameter>`. Called for printing +#' side-effects. +#' @export +#' +#' @examples +#' epiparameter <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' format(epiparameter) +format.epiparameter <- function(x, ...) { + writeLines( + c( + sprintf(tr_("Disease: %s"), x$disease), + sprintf(tr_("Pathogen: %s"), x$pathogen), + sprintf(tr_("Epi Parameter: %s"), .clean_string(x$epi_name)), + # aggregated <epiparameter> with repeated cits only are to be printed once + sprintf(tr_("Study: %s"), format(unique(x$citation))) + ) + ) + + if (is.object(x$prob_distribution) || is.character(x$prob_distribution)) { + dist_string <- ifelse( + test = inherits(x$prob_distribution, "distcrete"), + yes = tr_("Distribution: discrete %s"), + no = tr_("Distribution: %s") + ) + fam <- family(x) + # isTRUE to control for family returning NA for unparameterised + if (isTRUE(fam == "mixture")) { + fam <- paste(fam, toString(.get_mixture_family(x)), sep = ": ") + } + writeLines(sprintf(dist_string, fam)) + } else { + writeLines(tr_("Parameters: <no parameters>")) + } + + if (is.object(x$prob_distribution)) { + params <- get_parameters(x) + + # decide on parameter format from magnitude of number + format_params <- ifelse( + test = any(params > 9.999e-3 & params < 1e4), + yes = "f", + no = "g" + ) + + writeLines( + c( + sprintf(tr_("Parameters:")), + sprintf( + " %s: %s", + names(params), + formatC(params, digits = 3, format = format_params) + ) + ) + ) + } + + invisible(x) +} + +#' Check object is an `<epiparameter>` +#' +#' @param x An \R object. +#' +#' @return A boolean logical, `TRUE` if the object is an `<epiparameter>` +#' and `FALSE` if not. +#' @export +#' +#' @examples +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "serial_interval", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' +#' is_epiparameter(ep) +#' +#' false_ep <- list( +#' disease = "ebola", +#' epi_name = "serial_interval", +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' +#' is_epiparameter(false_ep) +is_epiparameter <- function(x) { + inherits(x, "epiparameter") +} + +#' PDF, CDF, PMF, quantiles and random number generation for `<epiparameter>` +#' objects +#' +#' @description The `<epiparameter>` object holds a probability distribution +#' which can either be a continuous or discrete distribution. These are the +#' density, cumulative distribution, quantile and random number generation +#' functions. These operate on any distribution that can be included in an +#' `<epiparameter>` object. +#' +#' @param x An `<epiparameter>` object. +#' @param at The quantiles to evaluate at. +#' @param q The quantiles to evaluate at. +#' @param p The probabilities to evaluate at. +#' @param times The number of random samples. +#' @inheritParams print.epiparameter +#' @inheritParams distributional::cdf +#' +#' @return `numeric` vector. +#' +#' @name epiparameter_distribution_functions +#' @keywords epiparameter_distribution_functions +#' +#' @examples +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' +#' # example of each distribution method for an `epiparameter` object +#' stats::density(ep, at = 1) +#' distributional::cdf(ep, q = 1) +#' stats::quantile(ep, p = 0.2) +#' distributional::generate(ep, times = 10) +NULL + +#' @rdname epiparameter_distribution_functions +#' @importFrom stats density +#' @export +density.epiparameter <- function(x, at, ...) { + if (isFALSE(is_parameterised(x))) { + stop("<epiparameter> is unparameterised", call. = FALSE) + } + unlist <- length(x$prob_distribution) == 1 + if (inherits(x$prob_distribution, "distcrete")) { + out <- x$prob_distribution$d(at) + } else { + out <- stats::density(x$prob_distribution, at = at) + } + out <- if (unlist) unlist(out, recursive = FALSE) else out + out +} + +#' @importFrom distributional cdf +#' @export +distributional::cdf + +#' @rdname epiparameter_distribution_functions +#' @importFrom distributional cdf +#' @export +cdf.epiparameter <- function(x, q, ..., log = FALSE) { + if (isFALSE(is_parameterised(x))) { + stop("<epiparameter> is unparameterised", call. = FALSE) + } + unlist <- length(x$prob_distribution) == 1 + if (inherits(x$prob_distribution, "distcrete")) { + out <- x$prob_distribution$p(q) + if (log) out <- log(out) + } else { + out <- distributional::cdf(x$prob_distribution, q = q, ..., log = log) + } + out <- if (unlist) unlist(out, recursive = FALSE) else out + out +} + +#' @rdname epiparameter_distribution_functions +#' @importFrom stats quantile +#' @export +quantile.epiparameter <- function(x, p, ...) { + if (isFALSE(is_parameterised(x))) { + stop("<epiparameter> is unparameterised", call. = FALSE) + } + unlist <- length(x$prob_distribution) == 1 + if (inherits(x$prob_distribution, "distcrete")) { + out <- x$prob_distribution$q(p) + } else { + out <- stats::quantile(x$prob_distribution, p = p) + } + out <- if (unlist) unlist(out, recursive = FALSE) else out + out +} + +#' @importFrom distributional generate +#' @export +distributional::generate + +#' @rdname epiparameter_distribution_functions +#' @importFrom distributional generate +#' @export +generate.epiparameter <- function(x, times, ...) { + if (isFALSE(is_parameterised(x))) { + stop("<epiparameter> is unparameterised", call. = FALSE) + } + # check times is a single number for consistent behaviour + checkmate::assert_number(times) + if (inherits(x$prob_distribution, "distcrete")) { + unlist <- length(x$prob_distribution) == 1 + out <- x$prob_distribution$r(n = times) + out <- if (unlist) unlist(out, recursive = FALSE) else out + } else { + recursive <- length(x$prob_distribution) == 1 + out <- distributional::generate(x$prob_distribution, times = times) + out <- unlist(out, recursive = recursive) + } + out +} + +#' Discretises a continuous distribution in an `<epiparameter>` object +#' +#' @details Converts the S3 distribution object in an `<epiparameter>` from +#' continuous (using an object from the `{distributional}` package) to a +#' discretised distribution (using an object from the `{distcrete}` package). +#' +#' @inheritParams print.epiparameter +#' @param ... [dots] Extra arguments to be passed to the method. +#' +#' @inherit epiparameter return +#' @export +#' +#' @examples +#' ebola_incubation <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' discretise(ebola_incubation) +discretise <- function(x, ...) { + UseMethod("discretise") +} + +#' @rdname discretise +#' @export +discretize <- discretise + +#' @rdname discretise +#' @export +discretise.epiparameter <- function(x, ...) { + # check if distribution is already discretised if so return early + if (inherits(x$prob_distribution, "distcrete")) { + message("Distribution in `epiparameter` is already discretised") + return(x) + } else { + # extract prob dist and prob dist parameters from epiparameter + prob_dist <- family(x) + if (prob_dist == "mixture") { + warning( + "<epiparameter> object with mixture distributions cannot be ", + "discretised.\n Returning undiscretised <epiparameter>.", + call. = FALSE + ) + return(x) + } + prob_dist_params <- get_parameters(x) + + # if distribution is truncated take only parameters + if (is_truncated(x)) { + warning( + "Discretising a truncated continuous distribution, ", + "returning non-truncated discretised distribution", + call. = FALSE + ) + + idx <- grep( + pattern = "lower|upper", + x = names(prob_dist_params), + ignore.case = TRUE + ) + prob_dist_params <- prob_dist_params[-idx] + + # trunc dist family is truncated so get prob dist by unclassing dist and + # extracting name + list_dist <- unclass(x$prob_distribution) + prob_dist <- gsub( + pattern = "dist_", + replacement = "", + x = class(list_dist[[1]][[1]])[1], + fixed = TRUE + ) + } + + # standardise distribution parameter names + prob_dist_params <- .clean_params( + prob_distribution = prob_dist, + prob_distribution_params = prob_dist_params + ) + + # create a new discretised probability distribution + x$prob_distribution <- create_prob_distribution( + prob_distribution = prob_dist, + prob_distribution_params = prob_dist_params, + discretise = TRUE, + truncation = NA + ) + } + + # return epiparameter + x +} + +#' @rdname discretise +#' @export +discretise.default <- function(x, ...) { + stop("No discretise method defined for class ", class(x)) +} + +#' Family method for the `<epiparameter>` class +#' +#' @description The [family()] function is used to extract the distribution +#' names from objects from `{distributional}` and `{distcrete}`. This method +#' provides the same interface for `<epiparameter>` objects to give consistent +#' output irrespective of the internal distribution class. +#' +#' @param object An `<epiparameter>` object. +#' @inheritParams stats::family +#' +#' @return A character string with the name of the distribution, or `NA` when +#' the `<epiparameter>` object is unparameterised. +#' @importFrom stats family +#' @export +#' +#' @examples +#' # example with continuous distribution +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 1, scale = 1) +#' ) +#' ) +#' family(ep) +#' +#' # example with discretised distribution +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "lnorm", +#' prob_distribution_params = c(meanlog = 1, sdlog = 1), +#' discretise = TRUE +#' ) +#' ) +#' family(ep) +family.epiparameter <- function(object, ...) { + if (inherits(object$prob_distribution, "distcrete")) { + prob_dist <- object$prob_distribution$name + } else if (inherits(object$prob_distribution, "distribution")) { + if (is_truncated(object)) { + prob_dist <- gsub( + pattern = "dist_", + replacement = "", + x = class(unclass(unclass(object$prob_distribution)[[1]])[[1]])[1], + fixed = TRUE + ) + } else { + prob_dist <- stats::family(object$prob_distribution) + } + } else if (is.character(object$prob_distribution)) { + prob_dist <- object$prob_distribution + } else { + return(NA) + } + + prob_dist <- switch(prob_dist, + lognormal = "lnorm", + negbin = "nbinom", + geometric = "geom", + poisson = "pois", + normal = "norm", + exponential = "exp", + prob_dist + ) + + # return prob dist + prob_dist +} + +#' Check if distribution in `<epiparameter>` is truncated +#' +#' @details The `<epiparameter>` class can hold probability distribution objects +#' from the `{distributional}` package or the `{distcrete}` package, +#' however, only distribution objects from `{distributional}` can be truncated. +#' If a `<epiparameter>` object has a `<distcrete>` object `is_truncated` will +#' return `FALSE` by default. +#' +#' @inheritParams print.epiparameter +#' +#' @return A boolean `logical`. +#' @export +#' +#' @examples +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "lnorm", +#' prob_distribution_params = c(meanlog = 1, sdlog = 1) +#' ) +#' ) +#' is_truncated(ep) +#' +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "lnorm", +#' prob_distribution_params = c(meanlog = 1, sdlog = 1), +#' truncation = 10 +#' ) +#' ) +#' is_truncated(ep) +is_truncated <- function(x) { + stopifnot( + "is_truncated only works for `<epiparameter> objects`" = + is_epiparameter(x) + ) + + # distcrete distributions cannot be truncated + if (inherits(x$prob_distribution, "distcrete")) { + return(FALSE) + } + + # unparameterised objects cannot be truncated + # dont use is_parameterised due to infinite recursion + if (is.na(x$prob_distribution) || is.character(x$prob_distribution)) { + return(FALSE) + } + + # use stats::family instead of epiparameter::family to check truncated + if (identical(stats::family(x$prob_distribution), "truncated")) { + return(TRUE) + } else { + return(FALSE) + } +} + +#' Check if distribution in `<epiparameter>` is continuous +#' +#' @details The `<epiparameter>` class can hold `<distribution>` and +#' `<distcrete>` probability distribution objects from the \pkg{distributional} +#' package and the \pkg{distcrete} package, respectively. `<distribution>` +#' objects can be continuous or discrete distributions (e.g. gamma or negative +#' binomial), and all `<distcrete>` objects are discrete. +#' +#' @inheritParams print.epiparameter +#' +#' @return A boolean `logical`. +#' @export +#' +#' @examples +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "lnorm", +#' prob_distribution_params = c(meanlog = 1, sdlog = 1) +#' ) +#' ) +#' is_continuous(ep) +#' is_continuous(discretise(ep)) +#' +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "offspring distribution", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "nbinom", +#' prob_distribution_params = c(mean = 2, dispersion = 0.5) +#' ) +#' ) +#' is_continuous(ep) +is_continuous <- function(x) { + stopifnot( + "is_truncated only works for `<epiparameter> objects`" = + is_epiparameter(x) + ) + # get individual distributions out of mixture to check if continuous + if (family(x) == "mixture") { + fam <- .get_mixture_family(x) + } else { + fam <- family(x) + } + + all(fam %in% c("gamma", "lnorm", "weibull", "normal")) && + !inherits(x$prob_distribution, "distcrete") +} + +#' Mean method for `<epiparameter>` class +#' +#' @inheritParams print.epiparameter +#' @param ... [dots] Not used, extra arguments supplied will cause a warning. +#' +#' @return A `numeric` mean of a distribution or `NA`. +#' @export +#' +#' @examples +#' ep <- epiparameter_db( +#' disease = "COVID-19", +#' epi_name = "incubation period", +#' single_epiparameter = TRUE +#' ) +#' mean(ep) +mean.epiparameter <- function(x, ...) { + chkDots(...) + # extract mean if given + if (utils::hasName(x$summary_stats, "mean")) { + mean <- x$summary_stats$mean + } else { + return(NA_real_) + } + + # if mean is not given try and convert from parameters + if (is.na(mean) && is_parameterised(x)) { + dist <- family(x) + params <- get_parameters(x) + args <- c(dist, as.list(params)) + summary_stats <- do.call(convert_params_to_summary_stats, args = args) + mean <- summary_stats$mean + } + + # return mean or NA + mean +} + +#' [c()] method for `<epiparameter>` class +#' +#' @param ... [dots] Objects to be concatenated. +#' +#' @return An `<epiparameter>` or list of `<epiparameter>` objects. +#' @export +#' +#' @examples +#' db <- epiparameter_db() +#' +#' # combine two <epiparameter> objects into a list +#' c(db[[1]], db[[2]]) +#' +#' # combine a list of <epiparameter> objects and a single <epiparameter> object +#' c(db, db[[1]]) +c.epiparameter <- function(...) { + x <- list(...) + if (!all(vapply(x, FUN = inherits, FUN.VALUE = logical(1), + what = c("epiparameter", "multi_epiparameter")))) { + stop( + "Can only combine <epiparameter> or <multi_epiparameter> objects", + call. = FALSE + ) + } + + # if <multi_epiparameter> are in `...` build the new unnested list of + # <epiparameter> objects iteratively in order to preserve input order + if (any(vapply(x, FUN = inherits, FUN.VALUE = logical(1), + what = "multi_epiparameter"))) { + # list is not pre-allocated as it's easier to append arbitrary length + # <multi_epiparameter> objects + ep_list <- list() + for (i in seq_along(x)) { + if (is_epiparameter(x[[i]])) { + ep_list <- c(ep_list, list(x[[i]])) + } else { + # unclass to prevent recursive dispatch + ep_list <- c(ep_list, unclass(x[[i]])) + } + } + } else { + ep_list <- x + } + + # for when `...` is a single <epiparameter> + if (length(ep_list) == 1) { + ep_list <- ep_list[[1]] + } else { + # will always be triggered if called from c.multi_epiparameter + class(ep_list) <- "multi_epiparameter" + } + ep_list +} + +#' @export +c.multi_epiparameter <- function(...) { + c.epiparameter(...) +} diff --git a/R/epiparameter_db.R b/R/epiparameter_db.R new file mode 100644 index 000000000..7810abaf7 --- /dev/null +++ b/R/epiparameter_db.R @@ -0,0 +1,765 @@ +#' Create `<epiparameter>` object(s) directly from the epiparameter library +#' (database) +#' +#' @description Extract `<epiparameter>` object(s) directly from +#' the library of epidemiological parameters. The epiparameter +#' library of epidemiological parameters is compiled from primary literature +#' sources. The list output from [epiparameter_db()] can be subset by the data +#' it contains, for example by: disease, pathogen, epidemiological distribution, +#' sample size, region, etc. +#' +#' If a distribution from a specific study is required, the `author` argument +#' can be specified. +#' +#' Multiple entries (`<epiparameter>` objects) can be returned, use the +#' arguments to subset entries and use `single_epiparameter = TRUE` to force a +#' single `<epiparameter>` to be returned. +#' +#' @details `disease`, `epi_name` and `author` are given as individual arguments +#' as these are the most common variables to subset the parameter library by. +#' The `subset` argument facilitates all other subsetting of rows to select the +#' `<epiparameter>` object(s) desired. To subset based on multiple variables +#' separate each expression with `&`. +#' +#' List of epidemiological parameters: +#' +#' * "all" (default, returns all entries in library) +#' * "incubation period" +#' * "onset to hospitalisation" +#' * "onset to death" +#' * "serial interval" +#' * "generation time" +#' * "offspring distribution" +#' * "hospitalisation to death" +#' * "hospitalisation to discharge" +#' * "notification to death" +#' * "notification to discharge" +#' * "onset to discharge" +#' * "onset to ventilation" +#' +#' @param disease A `character` string specifying the disease. +#' @param pathogen A `character` string specifying the pathogen. +#' @param epi_name A `character` string specifying the epidemiological +#' parameter. See details for full list of epidemiological distributions. +#' @param author A `character` string specifying the author of the study +#' reporting the distribution. Only the first author will be matched. It is +#' recommended to use the family name as first names may or may not be +#' initialised. +#' @param subset Either `NULL` or a valid R expressions that evaluates to +#' logicals to subset the list of `<epiparameter>`, or a function that can be +#' applied over a list of `<epiparameter>` objects. +#' +#' Subsetting (using `subset`) can be combined with the subsetting done with +#' the `disease` and `epi_name` arguments (and `author` if specified). If left +#' as `NULL` (default) no subsetting is carried out. +#' +#' The `subset` argument is similar to subsetting a `<data.frame>`, but the +#' difference is that fixed comparisons and not vectorised comparisons are +#' needed. For example `sample_size > 10` is a valid subset expression, but +#' `sample_size == max(sample_size)`, which would be a valid subset expression +#' for a `<data.frame>` does not work. The vectorised expression will often +#' not error, but will likely return unexpected results. For the +#' `sample_size == max(sample_size)` example it will always return `TRUE` +#' (except for `NA`s) as it is a single numeric so will be equal to it's +#' max value. +#' +#' The expression should be specified without using the data object name +#' (e.g. `df$var`) and instead just `var` should be supplied. In +#' other words, this argument uses non-standard evaluation, just as the +#' `subset` argument in [subset()], and is similar to `<data-masking>` used +#' by the `dplyr` package. +#' +#' @param single_epiparameter A boolean `logical` determining whether a single +#' `<epiparameter>` or multiple entries from the library can be returned if +#' matched by the other arguments (`disease`, `epi_name`, `author`). This +#' argument is used to prevent multiple sets of parameters being returned +#' when only one is wanted. +#' +#' **Note**: If multiple entries match the arguments supplied and +#' `single_epiparameter = TRUE` then the `<epiparameter>` that is parameterised +#' (and accounts for truncation if available) and has the largest sample size +#' will be returned (see [is_parameterised()]). If multiple entries are equal +#' after this sorting the first entry will be returned. +#' +#' @return An `<epiparameter>` object or list of `<epiparameter>` objects. +#' @export +#' +#' @examples +#' epiparameter_db(disease = "influenza", epi_name = "serial_interval") +#' +#' # example using custom subsetting +#' eparam <- epiparameter_db( +#' disease = "SARS", +#' epi_name = "offspring_distribution", +#' subset = sample_size > 40 +#' ) +#' +#' # example using functional subsetting +#' eparam <- epiparameter_db( +#' disease = "COVID-19", +#' epi_name = "incubation_period", +#' subset = is_parameterised +#' ) +#' +#' # example forcing a single <epiparameter> to be returned +#' eparam <- epiparameter_db( +#' disease = "SARS", +#' epi_name = "offspring_distribution", +#' single_epiparameter = TRUE +#' ) +epiparameter_db <- function(disease = "all", + pathogen = "all", + epi_name = "all", + author = NULL, + subset = NULL, + single_epiparameter = FALSE) { + # check input + checkmate::assert_string(disease) + checkmate::assert_string(pathogen) + checkmate::assert_string(epi_name) + checkmate::assert_logical(single_epiparameter, len = 1) + + # capture expression from subset and check type + expr <- substitute(subset) + if (is.character(expr)) { + stop( + "Subsetting is done with expressions that return logical values.\n", + "Remove quotation marks.", + call. = FALSE + ) + } + + # <multi_epiparameter> is sysdata + attrib <- attributes(multi_epiparameter) + + multi_epiparameter <- .filter_epiparameter_db( + multi_epiparameter = multi_epiparameter, + disease = disease, + pathogen = pathogen, + epi_name = epi_name + ) + + # extract study by author if given + if (!is.null(author)) { + first_author <- lapply(multi_epiparameter, function(x) { + x$citation$author[1] + }) + author_set <- grepl(pattern = author, x = first_author, ignore.case = TRUE) + + if (!any(author_set)) { + disease_str <- ifelse( + test = disease == "all", yes = "", no = paste(" for", disease) + ) + stop( + "Parameters by ", author, " are not available", disease_str, + call. = FALSE + ) + } + + # subset by authors + multi_epiparameter <- multi_epiparameter[author_set] + } + + # subset by subset conditions + if (is.call(expr)) { + nse_subject <- as.character(expr)[2] + cond_list <- lapply( + multi_epiparameter, + .is_cond_epiparameter, + expr, + nse_subject + ) + set <- vapply(cond_list, function(x) any(unlist(x)), FUN.VALUE = logical(1)) + set[is.na(set)] <- FALSE + multi_epiparameter <- multi_epiparameter[set] + } else if (is.function(subset)) { + set <- vapply(multi_epiparameter, subset, FUN.VALUE = logical(1)) + multi_epiparameter <- multi_epiparameter[set] + } + + attributes(multi_epiparameter) <- attrib + + if (length(multi_epiparameter) == 0) { + stop( + "No entries in the database meet the search criteria.", + call. = FALSE + ) + } + + lapply(multi_epiparameter, assert_epiparameter) + is_param <- vapply( + multi_epiparameter, + is_parameterised, + FUN.VALUE = logical(1) + ) + + if (single_epiparameter) { + # select parameterised entries + if (sum(is_param) >= 1) { + multi_epiparameter <- multi_epiparameter[is_param] + } + # select entries that accounted for truncation + idx <- vapply( + multi_epiparameter, + function(x) x$method_assess$right_truncated, + FUN.VALUE = logical(1) + ) + if (sum(idx) >= 1) { + multi_epiparameter <- multi_epiparameter[idx] + } + # select largest sample size + idx <- which.max( + vapply( + multi_epiparameter, + function(x) x$metadata$sample_size, + FUN.VALUE = numeric(1) + ) + ) + single_epiparameter <- multi_epiparameter[[idx]] + + message( + "Using ", format(get_citation(single_epiparameter)), ". \n", + "To retrieve the citation use the 'get_citation' function" + ) + + return(single_epiparameter) + } + + message( + "Returning ", length(multi_epiparameter), " results that match the ", + "criteria (", sum(is_param), " are parameterised). \n", + "Use subset to filter by entry variables or ", + "single_epiparameter to return a single entry. \n", + "To retrieve the citation for each use the ", + "'get_citation' function" + ) + + if (length(multi_epiparameter) == 1) { + multi_epiparameter <- multi_epiparameter[[1]] + } + + # return epiparameter + multi_epiparameter +} + +#' @inherit epiparameter_db title +#' +#' @description +#' `r lifecycle::badge('deprecated')` +#' +#' `epidist_db()` has been renamed [epiparameter_db()]. Please use +#' `epiparameter_db()` instead as the `epidist_db()` alias will be removed from +#' the package in the future. +#' +#' @inheritParams epiparameter_db +#' +#' @inherit epiparameter_db return +#' @export +#' @keywords internal +epidist_db <- function(disease = "all", + pathogen = "all", + epi_name = "all", + author = NULL, + subset = NULL, + single_epiparameter = FALSE) { + lifecycle::deprecate_warn( + when = "0.3.0", + what = "epidist_db()", + with = "epiparameter_db()" + ) + + # DUE TO NON-STANDARD EVALUATION epidist_db() CANNOT CALL epiparameter_db() + # SO THE FUNCTION CODE NEEDS TO BE COPIED + + # check input + checkmate::assert_string(disease) + checkmate::assert_string(pathogen) + checkmate::assert_string(epi_name) + checkmate::assert_logical(single_epiparameter, len = 1) + + # capture expression from subset and check type + expr <- substitute(subset) + if (is.character(expr)) { + stop( + "Subsetting is done with expressions that return logical values.\n", + "Remove quotation marks.", + call. = FALSE + ) + } + + # <multi_epiparameter> is sysdata + attrib <- attributes(multi_epiparameter) + + multi_epiparameter <- .filter_epiparameter_db( + multi_epiparameter = multi_epiparameter, + disease = disease, + pathogen = pathogen, + epi_name = epi_name + ) + + # extract study by author if given + if (!is.null(author)) { + first_author <- lapply(multi_epiparameter, function(x) { + x$citation$author[1] + }) + author_set <- grepl(pattern = author, x = first_author, ignore.case = TRUE) + + if (!any(author_set)) { + disease_str <- ifelse( + test = disease == "all", yes = "", no = paste(" for", disease) + ) + stop( + "Parameters by ", author, " are not available", disease_str, + call. = FALSE + ) + } + + # subset by authors + multi_epiparameter <- multi_epiparameter[author_set] + } + + # subset by subset conditions + if (is.call(expr)) { + nse_subject <- as.character(expr)[2] + cond_list <- lapply( + multi_epiparameter, + .is_cond_epiparameter, + expr, + nse_subject + ) + set <- vapply(cond_list, function(x) any(unlist(x)), FUN.VALUE = logical(1)) + set[is.na(set)] <- FALSE + multi_epiparameter <- multi_epiparameter[set] + } else if (is.function(subset)) { + set <- vapply(multi_epiparameter, subset, FUN.VALUE = logical(1)) + multi_epiparameter <- multi_epiparameter[set] + } + + attributes(multi_epiparameter) <- attrib + + if (length(multi_epiparameter) == 0) { + stop( + "No entries in the database meet the search criteria.", + call. = FALSE + ) + } + + lapply(multi_epiparameter, assert_epiparameter) + is_param <- vapply( + multi_epiparameter, + is_parameterised, + FUN.VALUE = logical(1) + ) + + if (single_epiparameter) { + # select parameterised entries + if (sum(is_param) >= 1) { + multi_epiparameter <- multi_epiparameter[is_param] + } + # select entries that accounted for truncation + idx <- vapply( + multi_epiparameter, + function(x) x$method_assess$right_truncated, + FUN.VALUE = logical(1) + ) + if (sum(idx) >= 1) { + multi_epiparameter <- multi_epiparameter[idx] + } + # select largest sample size + idx <- which.max( + vapply( + multi_epiparameter, + function(x) x$metadata$sample_size, + FUN.VALUE = numeric(1) + ) + ) + single_epiparameter <- multi_epiparameter[[idx]] + + message( + "Using ", format(get_citation(single_epiparameter)), ". \n", + "To retrieve the citation use the 'get_citation' function" + ) + + return(single_epiparameter) + } + + message( + "Returning ", length(multi_epiparameter), " results that match the ", + "criteria (", sum(is_param), " are parameterised). \n", + "Use subset to filter by entry variables or ", + "single_epiparameter to return a single entry. \n", + "To retrieve the citation for each use the ", + "'get_citation' function" + ) + + if (length(multi_epiparameter) == 1) { + multi_epiparameter <- multi_epiparameter[[1]] + } + + # return epiparameter + multi_epiparameter +} + +#' Reads in parameter library and formats data to <epiparameter> +#' +#' @inheritParams epiparameter_db +#' +#' @return `<multi_epiparameter>` object (i.e. a list of `<epiparameter>` with +#' nicer printing) +#' @keywords internal +#' @noRd +.read_epiparameter_db <- function() { + + if (!.is_pkg_installed("jsonlite")) { + stop( + "Cannot use this internal function without {jsonlite} installed", + call. = FALSE + ) + } + + params_json <- jsonlite::read_json( + path = system.file( + "extdata", + "parameters.json", + package = "epiparameter", + mustWork = TRUE + ) + ) + + # suppress individual <epiparameter> constructor messages + multi_epiparameter <- suppressMessages( + lapply(params_json, .format_epiparameter) + ) + + # create and return <multi_epiparameter> class + structure( + multi_epiparameter, + class = "multi_epiparameter" + ) +} + +#' Filter a list of `<epiparameter>` objects by disease and epi distribution +#' +#' @param multi_epiparameter A list of `<epiparameter>` objects. +#' @inheritParams epiparameter_db +#' +#' @return A list of `<epiparameter>` objects. +#' @keywords internal +#' @noRd +.filter_epiparameter_db <- function(multi_epiparameter, + disease, + pathogen, + epi_name) { + # copy of user input + disease_ <- disease + pathogen_ <- pathogen + epi_name_ <- epi_name + + # clean input strings + disease <- .clean_string(disease) + pathogen <- .clean_string(pathogen) + epi_name <- .clean_string(epi_name) + + # get valid options from db + disease_db <- vapply( + multi_epiparameter, function(x) x$disease, + FUN.VALUE = character(1) + ) + pathogen_db <- vapply( + multi_epiparameter, function(x) x$pathogen, + FUN.VALUE = character(1) + ) + epi_name_db <- vapply( + multi_epiparameter, function(x) x$epi_name, + FUN.VALUE = character(1) + ) + disease_db <- c("all", .clean_string(unique(disease_db))) + pathogen_db <- c("all", .clean_string(unique(pathogen_db))) + epi_name_db <- c("all", .clean_string(unique(epi_name_db))) + + # partial matching and custom error msg + tryCatch( + { + disease <- match.arg( + arg = disease, + choices = disease_db, + several.ok = FALSE + ) + pathogen <- match.arg( + arg = pathogen, + choices = pathogen_db, + several.ok = FALSE + ) + epi_name <- match.arg( + arg = epi_name, + choices = epi_name_db, + several.ok = FALSE + ) + }, + error = function(cnd) { + disease_str <- ifelse( + test = disease == "all", yes = "", no = paste(" for", disease_) + ) + pathogen_str <- ifelse( + test = pathogen == "all", yes = "", no = paste(" for", pathogen_) + ) + epi_name_str <- ifelse(test = epi_name == "all", yes = "", no = epi_name_) + stop( + epi_name_str, " distribution not available", disease_str, pathogen_str, + call. = FALSE + ) + } + ) + + # filter based on disease + if (disease != "all") { + multi_epiparameter <- Filter( + f = function(x) .clean_string(x$disease) == disease, + x = multi_epiparameter + ) + } + + # filter based on pathogen + if (pathogen != "all") { + multi_epiparameter <- Filter( + f = function(x) .clean_string(x$pathogen) == pathogen, + x = multi_epiparameter + ) + } + + # filter by epi dist + if (epi_name != "all") { + multi_epiparameter <- Filter( + f = function(x) .clean_string(x$epi_name) == epi_name, + x = multi_epiparameter + ) + } + + # return multi_epiparameter + multi_epiparameter +} + +#' Format data from JSON database into `<epiparameter>` objects +#' +#' @param x A single entry (element/object) from the database. +#' +#' @return An `<epiparameter>` object. +#' @keywords internal +#' @noRd +.format_epiparameter <- function(x) { + # convert nulls to NA + null2na <- function(l) { + if (is.list(l)) l <- lapply(l, null2na) else if (is.null(l)) l <- NA + l + } + x <- lapply(x, null2na) + + # format parameters and parameter uncertainty + params_uncertainty <- .format_params(x) + params <- params_uncertainty$params + uncertainty <- params_uncertainty$uncertainty + + # TODO: remove this and move precision from parameter to summary statistic + if ("precision" %in% names(params)) { + if (length(params) == 1) { + params <- NA_real_ + uncertainty <- list(uncertainty = create_uncertainty()) + } else { + params <- params[-which(names(params) == "precision")] + uncertainty <- uncertainty[-which(names(uncertainty) == "precision")] + } + } + + # format summary statistics + ss <- lapply(x$summary_statistics, unlist) + names(ss$quantile_values) <- ss$quantile_names + ss$quantile_names <- NULL + names(ss)[names(ss) == "quantile_values"] <- "quantiles" + + # format citation + cit <- x$citation + cit$author <- lapply( + cit$author, + function(aut) utils::person(given = aut$given, family = aut$family) + ) + cit$author <- Reduce(f = c, x = cit$author) + cit$pmid <- ifelse(is.null(cit$pmid), yes = NA_real_, no = cit$pmid) + cit <- suppressMessages( + create_citation( + author = cit$author, + year = cit$year, + title = cit$title, + journal = cit$journal, + doi = cit$doi, + pmid = cit$pmid + ) + ) + + # format metadata + meta <- create_metadata() + meta[names(x$metadata)] <- x$metadata + + # format method assessment + method <- create_method_assess() + truncation <- ifelse( + is.null(x$method_assessment$truncation), + yes = NA_real_, + no = x$method_assessment$truncation + ) + discretised <- x$method_assessment$discretised + x$method_assessment[c("truncation", "discretised")] <- NULL + method[names(x$method_assessment)] <- x$method_assessment + + # return <epiparameter> + epiparameter( + disease = x$disease, + pathogen = x$pathogen, + epi_name = x$epi_name, + prob_distribution = create_prob_distribution( + prob_distribution = x$probability_distribution$prob_distribution, + prob_distribution_params = params, + discretise = discretised, + truncation = truncation + ), + uncertainty = uncertainty, + summary_stats = ss, + auto_calc_params = TRUE, + citation = cit, + metadata = meta, + method_assess = method, + notes = x$notes + ) +} + +#' Format parameters and their uncertainty +#' +#' @param x A single entry (element/object) from the database. +#' +#' @return A list with parameters (`$params`) and uncertainty (`$uncertainty`). +#' @keywords internal +#' @noRd +.format_params <- function(x) { + params <- lapply(x$probability_distribution$parameters, unlist) + + # return unparameterised + if (length(params) == 0) { + return( + list( + params = NA_real_, + uncertainty = list(uncertainty = create_uncertainty()) + ) + ) + } + + # return params without uncertainty + if (!any(grepl(pattern = "ci", x = names(params), fixed = TRUE))) { + uncertainty <- lapply( + vector(mode = "list", length = length(params)), + function(x) x <- create_uncertainty() + ) + names(uncertainty) <- names(params) + return( + list( + params = unlist(params), + uncertainty = uncertainty + ) + ) + } + + # add ci to params without for consistent data struct + params_ <- vector(mode = "list") + for (i in seq_along(params)) { + nm <- names(params)[i] + nms <- names(params)[grepl(pattern = nm, x = names(params))] + if (any(grepl(pattern = "_ci", x = nms, fixed = TRUE))) { + params_ <- append(params_, params[i]) + } else { + params_ci <- list(params[[i]], c(NA_real_, NA_real_), NA_real_) + names(params_ci) <- c(nm, paste0(nm, "_ci_limits"), paste0(nm, "_ci")) + params_ <- append(params_, params_ci) + } + } + params <- params_ + + # params and uncertainty + ci_limits <- params[!is.na(names(params)) & + endsWith(names(params), suffix = "ci_limits")] + ci <- params[!is.na(names(params)) & endsWith(names(params), suffix = "ci")] + ci_type <- switch(x$metadata$inference_method, + mle = "confidence_interval", + bayesian = "credible_interval", + NA_character_ + ) + + # separate parameters and uncertainty + ci_idx <- grepl(pattern = "_ci", x = names(params), fixed = TRUE) + uncertainty <- params[ci_idx] + params <- params[!ci_idx] + + # default uncertainty for each parameters + uncertainty <- lapply( + vector(mode = "list", length = length(params)), + function(x) x <- create_uncertainty() + ) + + for (i in seq_along(ci_limits)) { + uncertainty[[i]] <- list( + ci_limits = ci_limits[[i]], + ci = ci[[i]], + ci_type = ci_type + ) + } + + params <- unlist(params) + names(uncertainty) <- names(params) + + # return params and uncertainty + list( + params = params, + uncertainty = uncertainty + ) +} + +#' Check `<epiparameter>` based on condition +#' +#' @return list of logical booleans. +#' @keywords internal +#' @noRd +.is_cond_epiparameter <- function(lst, condition, nse_subject) { + # check input + stopifnot(is_epiparameter(lst)) + if (nse_subject == "prob_dist") { + # special case to subset by dist as name is extracted first + if (is.object(lst$prob_distribution) || + is.character(lst$prob_distribution)) { + prob_dist <- family(lst) # nolint prob_dist used in eval + eval(expr = condition) + } else { + FALSE + } + } else { + # apply condition to <epiparameter> name matching elements + lapply(lst, function(x) { + if (nse_subject %in% names(x)) { + # <epiparameter> is only nested once so no need for recursive search + eval(expr = condition, envir = x) + } else { + FALSE + } + }) + } +} + +#' Check whether a package is installed +#' +#' @details This functions allows mock testing for when a package is not +#' installed on a users system (i.e. not a dependency of {epiparameter}). +#' +#' @inheritParams base::requireNamespace +#' +#' @return Invisibly returns a boolean `logical`. +#' @noRd +#' @keywords internal +.is_pkg_installed <- function(package) { + requireNamespace(package, quietly = TRUE) +} diff --git a/R/extract_param.R b/R/extract_param.R new file mode 100644 index 000000000..995e311e6 --- /dev/null +++ b/R/extract_param.R @@ -0,0 +1,396 @@ +#' Calculate the parameters of a parametric probability distribution from +#' reported values of percentiles, or median and range +#' +#' Summary data of distributions, as provided by reports and meta-analyses, can +#' be used to extract the parameters of a chosen distribution. Currently +#' available distributions are: lognormal, gamma, Weibull and normal. +#' Extracting from a lognormal returns the meanlog and sdlog parameters, +#' extracting from the gamma and Weibull returns the shape and scale parameters, +#' and extracting from the normal returns the mean and sd parameters. +#' +#' @details For `gamma`, `lnorm` and `weibull`, `extract_param()` works only +#' for strictly positive values at the percentiles of a distribution or the +#' median and range of data (numerics supplied to the `values` argument). +#' This means that negative values at the lower percentile or lower range +#' will not work with this function although they may present themselves in +#' epidemiological data (e.g. negative serial interval). For the `norm` +#' distribution negative values are allowed. +#' +#' @param type A `character` defining whether summary statistics based +#' around `percentiles` (default) or `range`. +#' @param values A `vector`. If `type = percentiles`: `c(percentile_1, +#' percentile_2)`; and if `type = range`: `c(median, min, max)`. +#' @param distribution A `character` specifying distribution to use. +#' Default is `lnorm`; also takes `gamma`, `weibull` and `norm`. +#' @param percentiles A `vector` with two elements specifying the +#' percentiles defined in `values` if using `type = "percentiles"`. +#' Percentiles should be specified between 0 and 1. For example 2.5th and 97.5th +#' percentile is given as `c(0.025, 0.975)`. +#' @param samples A `numeric` specifying the sample size if using +#' `type = "range"`. +#' @param control A named list containing options for the optimisation. List +#' element `$max_iter` is a `numeric` specifying the maximum number of times +#' the parameter extraction will run optimisation before returning result early. +#' This prevents overly long optimisation loops if optimisation is unstable and +#' does not converge over multiple iterations. Default is 1000 iterations. List +#' element `$tolerance` is passed to [.check_optim_conv()] for tolerance on +#' parameter convergence over iterations of optimisation. Elements of in the +#' control list are not passed to [optim()]. +#' +#' @return A named `numeric` vector with the parameter values of the +#' distribution. If the `distribution = lnorm` then the parameters returned are +#' the meanlog and sdlog; if the `distribution = gamma` or `distribution = +#' weibull` then the parameters returned are the shape and scale; if +#' `distribution = norm` then the parameters returned are mean and sd. +#' @keywords extract +#' @author Adam Kucharski, Joshua W. Lambert +#' @export +#' @examples +#' # set seed to control for stochasticity +#' set.seed(1) +#' +#' # extract parameters of a lognormal distribution from the 75 percentiles +#' extract_param( +#' type = "percentiles", +#' values = c(6, 13), +#' distribution = "lnorm", +#' percentiles = c(0.125, 0.875) +#' ) +#' +#' # extract parameters of a gamma distribution from median and range +#' extract_param( +#' type = "range", +#' values = c(10, 3, 18), +#' distribution = "gamma", +#' samples = 20 +#' ) +extract_param <- function(type = c("percentiles", "range"), + values, + distribution = c("lnorm", "gamma", "weibull", "norm"), + percentiles, + samples, + control = list( + max_iter = 1000, + tolerance = 1e-5 + )) { + # check string arguments + type <- match.arg(arg = type, several.ok = FALSE) + distribution <- match.arg(arg = distribution, several.ok = FALSE) + + # check numeric arguments + if (distribution == "norm") { + checkmate::assert_numeric(values) + } else { + checkmate::assert_numeric(values, lower = 1e-10) + } + + if (type == "percentiles") { + stopifnot( + "percentiles need to be given for type = 'percentiles'" = + !missing(percentiles), + "values vector should be c(lower, upper) check values" = + values[1] < values[2] + ) + checkmate::assert_numeric(values, len = 2) + checkmate::assert_numeric(percentiles, lower = 0, upper = 1, len = 2) + } + if (identical(type, "range")) { + stopifnot( + "samples need to be given for type = 'range'" = + !missing(samples), + "values vector should be c(median, min, max) check values" = + values[2] < values[1] && values[1] < values[3] + ) + checkmate::assert_number(samples, lower = 2) + } + + # prepare default control list + ctrl <- list( + max_iter = 1000, + tolerance = 1e-5 + ) + # pass user solver options to default control list + ctrl[names(control)] <- control + + stopifnot( + "control list requires max_iter and tolerance elements" = + identical(names(ctrl), c("max_iter", "tolerance")) + ) + + # Validate inputs + if (type == "percentiles") { + stopifnot( + "'values' and 'percentiles' need to be a vector of length 2" = + length(values) == 2 || length(percentiles) == 2 + ) + } + if (type == "range") { + stopifnot( + "'values need to be a vector of length 3" = + length(values) == 3 + ) + } + + # initialise for the loop + optim_conv <- FALSE + optim_params_list <- list() + i <- 0 + + # check numerical stability of results with different starting parameters + while (!optim_conv && i < ctrl$max_iter) { + # Extract distribution parameters by optimising for specific distribution + optim_params <- .extract_param( + values = values, + distribution = distribution, + percentiles = percentiles, + samples = samples + ) + + # add last optimisation to list + optim_params_list[[i + 1]] <- optim_params + i <- i + 1 + + optim_conv <- .check_optim_conv( + optim_params_list = optim_params_list, + optim_params = optim_params, + tolerance = ctrl$tolerance + ) + } + + # if convergence after maximum iterations is not reached + if (i >= ctrl$max_iter) { + warning( + "Maximum optimisation iterations reached, returning result early. \n", + "Result may not be reliable.", + call. = FALSE + ) + + # choose best parameter estimates from lowest optimisation value + best_iter <- which.min(unlist(lapply(optim_params_list, "[[", "value"))) + } else { + # if optimsation converged use last iteration + best_iter <- length(optim_params_list) + } + + # warn about local optima + message( + "Stochastic numerical optimisation used. \n", + "Rerun function multiple times to check global optimum is found" + ) + + # return parameters that repeatedly converge + optim_params_list[[best_iter]]$par +} + +#' Optimises the parameters for a specified probability distribution given the +#' percentiles of a distribution and the values at those percentiles, or the +#' median and range of a sample and the number of samples. +#' +#' @inheritParams extract_param +#' +#' @return A list with output from [stats::optim()]. +#' @keywords internal +.extract_param <- function(values, + distribution, + percentiles, + samples) { + # Set initial values for optimisation + if (distribution == "norm") { + param <- c(stats::median(values), (stats::sd(values) / 3)) + } else { + param <- stats::runif(n = 2, min = 0, max = 5) + } + + if (!missing(percentiles)) { + names(values) <- c("lower", "upper") + values_in <- c(values, q1 = percentiles[1], q2 = percentiles[2]) + fit_func <- .fit_percentiles + } else if (!missing(samples)) { + names(values) <- c("median", "lower", "upper") + values_in <- c(values, n = samples) + fit_func <- .fit_range + } else { + stop("percentiles or samples arguments must be specified", call. = FALSE) + } + + if (distribution == "lnorm") { + names(param) <- c("meanlog", "sdlog") + lower <- c(-1e5, 1e-10) + } + if (distribution == "gamma") { + names(param) <- c("shape", "scale") + lower <- c(1e-10, 1e-10) + } + if (distribution == "weibull") { + names(param) <- c("shape", "scale") + lower <- c(1e-10, 1e-10) + } + if (distribution == "norm") { + names(param) <- c("mean", "sd") + lower <- c(-1e5, 1e-10) + } + + optim_params <- stats::optim( + param, + fit_func, + method = "L-BFGS-B", + val = values_in, + dist = distribution, + lower = lower + ) + + optim_params +} + +#' Check whether the optimisation of distribution parameters has converged to +#' stable value for the parameters and function output for multiple iterations +#' +#' @description This function is to try and prevent optimisation to a local +#' optimum and thus checks whether multiple optimisation routines are +#' consistently finding parameter values to within a set tolerance. +#' +#' @param optim_params_list A list, where each element is the output of +#' [stats::optim()]. See `?optim` for more details. +#' @param optim_params A list given by the output of [stats::optim()]. +#' @param tolerance A `numeric` specifying within which disparity convergence +#' of parameter estimates and function minimisation is accepted. +#' +#' @return Boolean +#' @keywords internal +.check_optim_conv <- function(optim_params_list, + optim_params, + tolerance) { + optim_conv <- FALSE + # no pairwise comparison on first iterations + if (length(optim_params_list) > 1) { + # extract parameters from list + params <- lapply(optim_params_list, "[[", "par") + + # calculate pairwise comparison across all iterations + param_a_dist <- stats::dist(unlist(lapply(params, "[[", 1))) + param_b_dist <- stats::dist(unlist(lapply(params, "[[", 2))) + + # any convergence within tolerance for parameters + res_diff <- any(param_a_dist < tolerance) && + any(param_b_dist < tolerance) + + # any convergence within tolerance for function value + res_diff <- res_diff && + (abs(optim_params_list[[length(optim_params_list)]]$value - + min(unlist(lapply(optim_params_list, "[[", "value")))) < tolerance) + optim_conv <- res_diff && optim_params$convergence == 0 + } + optim_conv +} + +#' Function for extracting distribution parameters +#' +#' Set of functions that can be used to estimate the parameters of a +#' distribution (lognormal, gamma, Weibull, normal) via optimisation from +#' either the percentiles or the median and ranges. +#' +#' @param param Named `numeric` vector of the distribution parameters to be +#' optimised. +#' @param val `Numeric` vector, in the case of using percentiles it contains +#' the values at the percentiles and the percentiles, in the case of median and +#' range it contains the median, lower range, upper range and the number of +#' sample points to evaluate the function at. +#' @param dist A `character` string with the name of the distribution for +#' fitting. Naming follows the base R distribution names (e.g. `lnorm` for +#' lognormal). +#' +#' @keywords internal +#' @author Adam Kucharski, Joshua W. Lambert +#' @name extraction_functions +.fit_range <- function(param, + val, + dist = c("lnorm", "gamma", "weibull", "norm")) { + # check input + dist <- match.arg(dist) + + cumulative <- switch(dist, + lnorm = stats::plnorm, + gamma = stats::pgamma, + weibull = stats::pweibull, + norm = stats::pnorm + ) + density <- switch(dist, + lnorm = stats::dlnorm, + gamma = stats::dgamma, + weibull = stats::dweibull, + norm = stats::dnorm + ) + + param_names <- switch(dist, + lnorm = c("meanlog", "sdlog"), + gamma = c("shape", "scale"), + weibull = c("shape", "scale"), + norm = c("mean", "sd") + ) + + args <- list( + val[["median"]], + param[[param_names[1]]], + param[[param_names[[2]]]] + ) + names(args)[2:3] <- param_names + names(args)[1] <- "" + + # Median square residual + median_sr <- (do.call(cumulative, args = args) - 0.5)^2 + + args[[1]] <- val[["lower"]] + # Probability of obtaining min, max and range: + min_p <- do.call(density, args = args) + + args[[1]] <- val[["upper"]] + max_p <- do.call(density, args = args) + + args[[1]] <- val[["upper"]] + range_p_upper <- do.call(cumulative, args = args) + args[[1]] <- val[["lower"]] + range_p_lower <- do.call(cumulative, args = args) + range_p <- (range_p_lower - range_p_upper)^(val[["n"]] - 2) + + # Range likelihood + range_sr <- -(min_p * max_p * range_p) + + # Total value to be minimised + range_sr + median_sr +} + +#' @rdname extraction_functions +.fit_percentiles <- function(param, + val, + dist = c("lnorm", "gamma", "weibull", "norm")) { + # check input + dist <- match.arg(dist) + + cumulative <- switch(dist, + lnorm = stats::plnorm, + gamma = stats::pgamma, + weibull = stats::pweibull, + norm = stats::pnorm + ) + param_names <- switch(dist, + lnorm = c("meanlog", "sdlog"), + gamma = c("shape", "scale"), + weibull = c("shape", "scale"), + norm = c("mean", "sd") + ) + + args <- list( + val[["lower"]], + param[[param_names[1]]], + param[[param_names[[2]]]] + ) + names(args)[2:3] <- param_names + names(args)[1] <- "" + + lower <- (do.call(cumulative, args = args) - val[["q1"]])^2 + + args[[1]] <- val[["upper"]] + upper <- (do.call(cumulative, args = args) - val[["q2"]])^2 + + lower + upper +} diff --git a/R/get_percentiles.R b/R/get_percentiles.R new file mode 100644 index 000000000..74b78cc5a --- /dev/null +++ b/R/get_percentiles.R @@ -0,0 +1,98 @@ +#' Convert a vector of named percentiles into correct format and selects two +#' values for parameter extraction +#' +#' @description Parameters of a probability distribution can be extracted using +#' the values given at percentiles of the distribution and the percentiles using +#' [extract_param()]. [.get_percentiles()] takes a named vector of percentiles +#' (names) and values at those percentiles (elements in the vector) and selects +#' two values as lower and upper percentiles to be used in extraction. If a +#' lower and upper percentile are not available `NA` is returned. +#' +#' It also formats the vector names so that they can be correctly converted to +#' numeric using `as.numeric()`. +#' +#' @details The name format is a character of the value of the percentile. +#' Numbers with decimal places should have the decimal point in the name. For +#' example the 5th and 95th percentile can be given as +#' +#' ```r +#' .get_percentiles(c("5" = 1, "95" = 10)) +#' ``` +#' +#' or the 2.5th and 97.5th percentile can be given as +#' +#' ```r +#' .get_percentiles(c("2.5" = 1, "97.5" = 10)) +#' ``` +#' +#' @param percentiles A named vector of values at percentiles with the names the +#' percentiles. See Details for the accepted vector name format. +#' +#' @return A named `numeric` vector of percentiles. +#' @keywords internal +.get_percentiles <- function(percentiles) { + # check input + checkmate::assert_numeric(percentiles, names = "unique") + checkmate::assert_numeric( + as.numeric(names(percentiles)), + lower = 0, + upper = 100 + ) + + # extract a lower and an upper percentile + percentiles <- .get_sym_percentiles(percentiles) + + # return percentiles + percentiles +} + +#' Get the lower and upper percentiles with a preference for symmetrical +#' percentiles +#' +#' @param percentiles A named vector of percentiles. The names are in the +#' correct format to be converted to their numeric value using `as.numeric()`. +#' +#' @return A named `numeric` vector of two elements with the lower +#' (first element) and upper (second element) percentiles. +#' @keywords internal +.get_sym_percentiles <- function(percentiles) { + # make a copy of percentiles + percentiles_ <- percentiles + + # remove NA values + percentiles <- percentiles[!is.na(percentiles)] + + # get percentiles names for percentiles with and without NAs + intervals <- as.numeric(names(percentiles)) + + # split lower and upper percentiles + lower_intervals <- intervals[intervals <= 50] + upper_intervals <- intervals[intervals > 50] + + # if upper or lower percentiles are not available return percentiles + if (identical(length(lower_intervals), 0L) || + identical(length(upper_intervals), 0L)) { + return(NA) + } + + # calc differences of lower and upper percentiles from bounds + lw_interval_diff <- abs(0 - lower_intervals) + up_interval_diff <- abs(100 - upper_intervals) + + # calc distance between lower and upper percentiles + outer_diff <- abs(outer(lw_interval_diff, up_interval_diff, FUN = "-")) + + # get indices of symmetrical or most symmetrical lower and upper percentiles + idx <- as.vector(arrayInd(which.min(outer_diff), .dim = dim(outer_diff))) + + # extract lower and upper percentiles from non-NA percentiles + lower_percentile <- lower_intervals[idx[1]] + upper_percentile <- upper_intervals[idx[2]] + + # extract lower and upper percentiles from all percentiles + lower_percentile_idx <- which(names(percentiles_) %in% lower_percentile) + upper_percentile_idx <- which(names(percentiles_) %in% upper_percentile) + + # return vector of percentiles + percentiles_[c(lower_percentile_idx, upper_percentile_idx)] +} diff --git a/R/options.R b/R/options.R new file mode 100644 index 000000000..214d8af36 --- /dev/null +++ b/R/options.R @@ -0,0 +1,18 @@ +#' Package options +#' +#' Options to modify the printing of \pkg{epiparameter} objects. +#' Currently options are only used to modify the printing of the +#' `<multi_epiparameter>` class. +#' +#' Options are set with [options()] and retrieved with [getOption()]. +#' +#' If options are changed the \pkg{epiparameter} package will need to be +#' reloaded for new options to be taken into account. Options can be set in +#' the `.Rprofile` to persist across R sessions. +epiparameter_options <- list( + # Maximum number of <epiparameter> objects to print for <multi_epiparameter> + print_max = getOption("epiparameter.print_max", default = 5L), + # Number of <epiparameter> objects to print if <multi_epiparameter> has more + # than `print_max` + print_min = getOption("epiparameter.print_min", default = 3L) +) diff --git a/R/parameter_tbl.R b/R/parameter_tbl.R new file mode 100644 index 000000000..5cb901661 --- /dev/null +++ b/R/parameter_tbl.R @@ -0,0 +1,123 @@ +#' Table of epidemiological distributions +#' +#' @description This function subsets the epidemiological parameter library to +#' return only the chosen epidemiological distribution. The results are +#' returned as a data frame containing the disease, epidemiological +#' distribution, probability distribution, author of the study, and the year +#' of publication. +#' +#' @inheritParams epiparameter +#' @param multi_epiparameter Either an `<epiparameter>` object or a list of +#' `<epiparameter>` objects. +#' +#' @author Joshua W. Lambert, Adam Kucharski +#' @export +#' @examples +#' epiparameter_list <- epiparameter_db(disease = "COVID-19") +#' parameter_tbl(multi_epiparameter = epiparameter_list) +#' +#' # example filtering an existing list to incubation periods +#' epiparameter_list <- epiparameter_db(disease = "COVID-19") +#' parameter_tbl( +#' multi_epiparameter = epiparameter_list, +#' epi_name = "incubation period" +#' ) +parameter_tbl <- function(multi_epiparameter, + disease = "all", + pathogen = "all", + epi_name = "all") { + # wrap <epiparameter> in list for apply functions + if (is_epiparameter(multi_epiparameter)) { + multi_epiparameter <- list(multi_epiparameter) + } + + # check data + stopifnot( + "List of <epiparameter> objects should be supplied to multi_epiparameter" = + all( + vapply(multi_epiparameter, is_epiparameter, FUN.VALUE = logical(1)) + ) && length(multi_epiparameter) != 0 + ) + + multi_epiparameter <- .filter_epiparameter_db( + multi_epiparameter = multi_epiparameter, + disease = disease, + pathogen = pathogen, + epi_name = epi_name + ) + + disease <- vapply( + multi_epiparameter, "[[", "disease", FUN.VALUE = character(1) + ) + pathogen <- vapply( + multi_epiparameter, "[[", "pathogen", FUN.VALUE = character(1) + ) + epi_name <- vapply( + multi_epiparameter, "[[", "epi_name", + FUN.VALUE = character(1) + ) + prob_dist <- vapply( + multi_epiparameter, function(x) { + switch(class(x$prob_distribution)[1], + distcrete = family(x), + distribution = family(x), + character = x$prob_distribution, + logical = NA_character_ + ) + }, + FUN.VALUE = character(1) + ) + + short_author <- vapply(multi_epiparameter, function(x) { + x <- x$citation$author + first_author <- x[1]$family + # organisation first author + if (is.null(first_author)) { + return(x[1]$given) + } + # multiple or single authors + if (length(x) > 1) { + return(paste(first_author, "et al.")) + } + first_author + }, FUN.VALUE = character(1)) + + year <- vapply( + multi_epiparameter, function(x) as.numeric(x$citation$year), + FUN.VALUE = numeric(1) + ) + sample_size <- vapply( + multi_epiparameter, + function(x) x$metadata$sample_size, + FUN.VALUE = numeric(1) + ) + + # make data frame + df <- data.frame( + disease = disease, + pathogen = pathogen, + epi_name = epi_name, + prob_distribution = prob_dist, + author = short_author, + year = year, + sample_size + ) + class(df) <- c("parameter_tbl", class(df)) + + # return data + df +} + +#' @export +print.parameter_tbl <- function(x, ...) { + # p_tbl subclass needed see https://github.com/tidyverse/ggplot2/issues/4786 + class(x) <- c("p_tbl", "tbl", "data.frame") + print(x, ...) +} + +#' @importFrom pillar tbl_sum +#' @export +tbl_sum.p_tbl <- function(x, ...) { + default_header <- NextMethod() + c("Parameter table" = "", default_header) +} diff --git a/R/plot.R b/R/plot.R new file mode 100644 index 000000000..e337eb872 --- /dev/null +++ b/R/plot.R @@ -0,0 +1,132 @@ +#' Plot method for `<epiparameter>` class +#' +#' @description Plot an `<epiparameter>` object by displaying the either the +#' probability mass function (PMF), (in the case of discrete distributions) +#' or probability density function (PDF) (in the case of continuous +#' distributions), or the cumulative distribution function (CDF). +#' +#' @details +#' By default if the `xlim` argument is not specified the distribution is +#' plotted between day 0 and the 99th quantile of the distribution. +#' Alternatively, a `numeric` vector of length 2 with the +#' first and last day to plot on the x-axis can be supplied to `xlim` +#' (through [...]). +#' +#' +#' @param x An `<epiparameter>` object. +#' @param cumulative A boolean `logical`, default is `FALSE`. +#' `cumulative = TRUE` plots the cumulative distribution function (CDF). +#' @inheritParams base::print +#' +#' @author Joshua W. Lambert +#' @export +#' +#' @examples +#' # plot continuous epiparameter +#' ep <- epiparameter( +#' disease = "ebola", +#' epi_name = "incubation_period", +#' prob_distribution = create_prob_distribution( +#' prob_distribution = "gamma", +#' prob_distribution_params = c(shape = 2, scale = 1) +#' ) +#' ) +#' plot(ep) +#' +#' # plot different day range (x-axis) +#' plot(ep, xlim = c(0, 10)) +#' +#' # plot CDF +#' plot(ep, cumulative = TRUE) +#' +#' # plot discrete epiparameter +#' ep <- discretise(ep) +#' plot(ep) +plot.epiparameter <- function(x, + cumulative = FALSE, + ...) { + # check input + assert_epiparameter(x) + checkmate::assert_logical(cumulative, any.missing = FALSE, len = 1) + + # capture dots + dots <- list(...) + + oldpar <- graphics::par(no.readonly = TRUE) + on.exit(graphics::par(oldpar)) + + if (is_continuous(x)) { + main <- "Probability Density Function" + } else { + main <- "Probability Mass Function" + } + + if (is.null(dots$xlim)) { + xlim <- seq(0, quantile(x, p = 0.99), length.out = 1000) + } else { + checkmate::assert_numeric(dots$xlim, len = 2) + xlim <- seq(dots$xlim[1], dots$xlim[2], length.out = 1000) + } + + xlab <- tools::toTitleCase(x$epi_name) + units <- x$metadata$units + no_units <- grepl(pattern = "(no)*(units)", x = units, ignore.case = TRUE) || + anyNA(units) + if (!no_units) { + xlab <- paste0(xlab, " ", "(", tools::toTitleCase(units), ")") + } + + if (is_continuous(x)) { + if (cumulative) { + # plot CDF + plot( + x = xlim, + y = cdf(x, q = xlim), + ylab = "", + xlab = xlab, + type = "l", + lwd = 2, + pch = 16, + ylim = c(0, 1), + main = "Cumulative Distribution Function", + ... + ) + } else { + # plot either PDF or PMF + plot( + x = xlim, + y = density(x, at = xlim), + ylab = "", + xlab = xlab, + type = "l", + lwd = 2, + pch = 16, + main = main, + ... + ) + } + } else { + if (cumulative) { + graphics::barplot( + height = cdf(x, q = unique(round(xlim))), + space = 0, + names.arg = unique(round(xlim)), + xlab = xlab, + ylab = "", + ylim = c(0, 1), + main = "Cumulative Distribution Function", + ... + ) + } else { + graphics::barplot( + density(x, at = unique(round(xlim))), + space = 0, + names.arg = unique(round(xlim)), + xlab = xlab, + ylab = "", + main = main, + ... + ) + } + } +} diff --git a/R/print.R b/R/print.R new file mode 100644 index 000000000..eb0b6ff2b --- /dev/null +++ b/R/print.R @@ -0,0 +1,93 @@ +#' Print method for `<multi_epiparameter>` class +#' +#' @param x A `<multi_epiparameter>` object. +#' @param n A `numeric` specifying how many `<epiparameter>` objects to print. +#' This argument is passed to [head()] for `list` printing. Default is `NULL` +#' and the number of elements to print is controlled by package [options()]. +#' @inheritParams print.epiparameter +#' +#' @return Invisibly returns a `<multi_epiparameter>`. Called for side-effects. +#' @export +#' @examples +#' # entire database +#' db <- epiparameter_db() +#' db +#' +#' # a single disease +#' db <- epiparameter_db(disease = "Ebola") +#' db +#' +#' # a single epi parameter +#' db <- epiparameter_db(epi_name = "offspring distribution") +#' db +print.multi_epiparameter <- function(x, ..., n = NULL) { + chkDots(...) + + # determine how many <epiparameter> to print + if (is.null(n)) { + n <- getOption("epiparameter")$print_max + if (length(x) > n) { + n <- getOption("epiparameter")$print_min + } else { + n <- length(x) + } + } + + n_entries <- length(x) + extra_n <- n_entries - n + + diseases <- vapply(x, `[[`, FUN.VALUE = character(1), "disease") + alpha_unique_diseases <- sort(unique(diseases)) + epi_names <- vapply( + x, `[[`, FUN.VALUE = character(1), "epi_name" + ) + alpha_unique_epi_names <- sort(unique(epi_names)) + + # header + writeLines( + pillar::style_subtle( + cli::pluralize( + "# ", tr_("List of {n_entries} <epiparameter> object{?s}\n") + ) + ) + ) + writeLines( + pillar::style_subtle( + c( + tr_("Number of diseases: ", length(alpha_unique_diseases)), + paste(cli::symbol$pointer, alpha_unique_diseases, collapse = " "), + tr_("Number of epi parameters: ", length(alpha_unique_epi_names)), + paste(cli::symbol$pointer, alpha_unique_epi_names, collapse = " ") + ) + ) + ) + + # body + print(utils::head(x, n = n)) + + # footer + footer <- "" + if (extra_n >= 1) { + footer <- c( + sprintf(tr_("%s more elements"), extra_n), + tr_("Use `print(n = ...)` to see more elements.\n") + ) + footer <- paste("#", cli::symbol$info, footer, collapse = "\n") + } + + writeLines( + pillar::style_subtle( + paste0( + footer, + "# ", cli::symbol$info, + " Use `parameter_tbl()` to see a summary table of the parameters.\n", + "# ", cli::symbol$info, " Explore database online at: ", + cli::style_hyperlink( + text = "https://epiverse-trace.github.io/epiparameter/articles/database.html", # nolint line_length_linter + url = "https://epiverse-trace.github.io/epiparameter/articles/database.html" # nolint line_length_linter + ) + ) + ) + ) + invisible(x) +} diff --git a/R/sysdata.rda b/R/sysdata.rda new file mode 100644 index 000000000..7ea9dd0c3 Binary files /dev/null and b/R/sysdata.rda differ diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 000000000..87536c3ed --- /dev/null +++ b/R/utils.R @@ -0,0 +1,78 @@ +#' Calculate the quantiles of a probability distribution based on the vector +#' of probabilities and time data (e.g. time since infection) +#' +#' @description This function can be used in cases where the data on a fitted +#' distribution is not openly available and the summary statistics of the +#' distribution are not reported so the data are scraped from the plot and +#' the quantiles are needed in order use the [extract_param()] function. +#' +#' @param prob A `numeric` vector of probabilities. +#' @param days A `numeric` vector of days. +#' @param quantile A single `numeric` or vector of `numerics` specifying which +#' quantiles to extract from the distribution. +#' +#' @return A named vector of quantiles. +#' @export +#' +#' @examples +#' prob <- dgamma(seq(0, 10, length.out = 21), shape = 2, scale = 2) +#' days <- seq(0, 10, 0.5) +#' quantiles <- c(0.025, 0.975) +#' calc_disc_dist_quantile(prob = prob, days = days, quantile = quantiles) +calc_disc_dist_quantile <- function(prob, days, quantile) { + # check inputs + checkmate::assert_numeric(prob) + checkmate::assert_numeric(days) + checkmate::assert_numeric(quantile, lower = 0, upper = 1) + + csum_prob <- cumsum(prob) + sum_prob <- sum(prob) + q_value <- quantile * sum_prob + q_index <- vector(mode = "numeric", length = length(quantile)) + for (i in seq_along(quantile)) { + q_index[i] <- which.min(abs(q_value[i] - csum_prob)) + } + quantiles <- days[q_index] + names(quantiles) <- as.character(quantile) + quantiles +} + +#' Format short citation from `<bibentry>` object +#' +#' @description +#' Output is equivalent to the `\citet{}` function in the \pkg{natbib} LaTeX +#' package. +#' +#' @param x A `<bibentry>` object, see [bibentry()]. +#' +#' @return A `character` string with the short citation. +#' @keywords internal +.citet <- function(x) { + stopifnot(inherits(x, "bibentry")) + cite <- vapply( + x, + function(y) { + num_author <- length(y$author) + # check if first author is an organisation + is_org_author <- is.null(y$author[1]$family) + # this covers single author entries + if (is_org_author) { + # organisation name stored in $given + cit <- y$author[1]$given + } else { + cit <- y$author[1]$family + } + # append second author or et al for multi-author entries + if (num_author == 2) { + cit <- paste(cit, "&", y$author[2]$family) + } else if (num_author > 2) { + cit <- paste(cit, "et al.") + } + cit <- paste0(cit, " (", y$year, ")") + }, + FUN.VALUE = character(1) + ) + cite +} + +`%||%` <- function(x, y) if (is.null(x)) y else x diff --git a/R/zzz.R b/R/zzz.R new file mode 100644 index 000000000..4596c0f14 --- /dev/null +++ b/R/zzz.R @@ -0,0 +1,3 @@ +.onLoad <- function(libname, pkgname) { + options(epiparameter = epiparameter_options) # nolint undersirable_function_linter +} diff --git a/README.Rmd b/README.Rmd new file mode 100644 index 000000000..a462e2380 --- /dev/null +++ b/README.Rmd @@ -0,0 +1,139 @@ +--- +output: github_document +--- + +<!-- README.md is generated from README.Rmd. Please edit that file --> + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.path = "man/figures/README-", + out.width = "75%", + fig.align = "center" +) +``` + +# epiparameter <img src="man/figures/logo.png" align="right" width="120" /> + +<!-- badges: start --> +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![R-CMD-check](https://github.com/epiverse-trace/epiparameter/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/epiverse-trace/epiparameter/actions/workflows/R-CMD-check.yaml) +[![Codecov test coverage](https://codecov.io/gh/epiverse-trace/epiparameter/branch/main/graph/badge.svg)](https://app.codecov.io/gh/epiverse-trace/epiparameter?branch=main) +[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11110881.svg)](https://doi.org/10.5281/zenodo.11110881) +<!-- badges: end --> + +`{epiparameter}` is an `R` package that contains a library of epidemiological parameters for infectious diseases as well as classes and helper functions to work with the data. It also includes functions to extract and convert parameters from reported summary statistics. + +`{epiparameter}` is developed at the [Centre for the Mathematical Modelling of Infectious Diseases](https://www.lshtm.ac.uk/research/centres/centre-mathematical-modelling-infectious-diseases) at the [London School of Hygiene and Tropical Medicine](https://www.lshtm.ac.uk/) as part of [Epiverse-TRACE](https://data.org/initiatives/epiverse/). + + +## Installation + +The easiest way to install the development version of `{epiparameter}` is to use the `{pak}` package: + +``` r +# check whether {pak} is installed +if(!require("pak")) install.packages("pak") +pak::pak("epiverse-trace/epiparameter") +``` + +Alternatively, install pre-compiled binaries from [the Epiverse TRACE R-universe](https://epiverse-trace.r-universe.dev/epiparameter) + +```r +install.packages("epiparameter", repos = c("https://epiverse-trace.r-universe.dev", "https://cloud.r-project.org")) +``` + +## Quick start + +```{r load-epiparameter} +library(epiparameter) +``` + +To load the library of epidemiological parameters into `R`: + +```{r load-data} +epiparameters <- epiparameter_db() +epiparameters +``` + +This results in a list of database entries. Each entry of the library is an `<epiparameter>` object. + +Alternatively, the library of epiparameters can be viewed as a vignette locally (`vignette("database", package = "epiparameter")`) or on the [{epiparameter} website](https://epiverse-trace.github.io/epiparameter/articles/database.html). + +The results can be filtered by disease and epidemiological distribution. Here we set `single_epiparameter = TRUE` as we only want a single database entry returned, and by default (`single_epiparameter = FALSE`) it will return all database entries that match the disease (`disease`) and epidemiological parameter (`epi_name`). + +```{r load-single-epiparameter} +influenza_incubation <- epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + single_epiparameter = TRUE +) +influenza_incubation +``` + +To quickly view the list of epidemiological distributions returned by `epiparameter_db()` in a table, the `parameter_tbl()` gives a summary of the data, and offers the ability to subset you data by `disease`, `pathogen` and epidemiological parameter (`epi_name`). + +```{r parameter-tbl} +parameter_tbl(epiparameters) +parameter_tbl( + epiparameters, + epi_name = "onset to hospitalisation" +) +``` + +The `<epiparameter>` object can be plotted. + +```{r plot-epiparameter} +plot(influenza_incubation) +``` + +The CDF can also be plotted by setting `cumulative = TRUE`. + +```{r, plot-epiparameter-cdf} +plot(influenza_incubation, cumulative = TRUE) +``` + +### Parameter conversion and extraction + +The parameters of a distribution can be converted to and from mean and standard deviation. In `{epiparameter}` we implement this for a variety of distributions: + +- gamma +- lognormal +- Weibull +- negative binomial +- geometric + +The parameters of a probability distribution can also be extracted from other summary statistics, for example, percentiles of the distribution, or the median and range of the data. This can be done for: + +- gamma +- lognormal +- Weibull +- normal + +## Contributing to library of epidemiological parameters + +If you would like to contribute to the different epidemiological parameters stored in the `{epiparameter}` package, you can add data to a public [google sheet](https://docs.google.com/spreadsheets/d/1eCL3n_woseg5Npu7XD7TcuNoLUIhMBu8ZoLCkVdATUE/edit?usp=sharing). This spreadsheet contains two example entries as a guide to what fields can accept. We are monitoring this sheet for new entries that will subsequently be included in the package. + +Alternatively, parameters can be added to the [JSON file holding the data](https://github.com/epiverse-trace/epiparameter/blob/main/inst/extdata/parameters.json) base directly via a Pull Request. + +You can find explanation of accepted entries for each column in the [data dictionary](https://github.com/epiverse-trace/epiparameter/blob/main/inst/extdata/data_dictionary.json). + +## Help + +To report a bug please open an [issue](https://github.com/epiverse-trace/epiparameter/issues/new/choose) + +## Contribute + +Contributions to `{epiparameter}` are welcomed. [package contributing guide](https://github.com/epiverse-trace/.github/blob/main/CONTRIBUTING.md). + +## Code of Conduct + +Please note that the `{epiparameter}` project is released with a [Contributor Code of Conduct](https://github.com/epiverse-trace/.github/blob/main/CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. + +## Citing this package + +```{r message=FALSE, warning=FALSE} +citation("epiparameter") +``` diff --git a/README.md b/README.md index 4bfaf8c2b..a10b1d9d8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,286 @@ -# epiparameter -Library of epidemiological parameters for infectious diseases + +<!-- README.md is generated from README.Rmd. Please edit that file --> + +# epiparameter <img src="man/figures/logo.png" align="right" width="120" /> + +<!-- badges: start --> + +[![License: +MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![R-CMD-check](https://github.com/epiverse-trace/epiparameter/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/epiverse-trace/epiparameter/actions/workflows/R-CMD-check.yaml) +[![Codecov test +coverage](https://codecov.io/gh/epiverse-trace/epiparameter/branch/main/graph/badge.svg)](https://app.codecov.io/gh/epiverse-trace/epiparameter?branch=main) +[![Lifecycle: +experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.11110881.svg)](https://doi.org/10.5281/zenodo.11110881) +<!-- badges: end --> + +`{epiparameter}` is an `R` package that contains a library of +epidemiological parameters for infectious diseases as well as classes +and helper functions to work with the data. It also includes functions +to extract and convert parameters from reported summary statistics. + +`{epiparameter}` is developed at the [Centre for the Mathematical +Modelling of Infectious +Diseases](https://www.lshtm.ac.uk/research/centres/centre-mathematical-modelling-infectious-diseases) +at the [London School of Hygiene and Tropical +Medicine](https://www.lshtm.ac.uk/) as part of +[Epiverse-TRACE](https://data.org/initiatives/epiverse/). + +## Installation + +The easiest way to install the development version of `{epiparameter}` +is to use the `{pak}` package: + +``` r +# check whether {pak} is installed +if(!require("pak")) install.packages("pak") +pak::pak("epiverse-trace/epiparameter") +``` + +Alternatively, install pre-compiled binaries from [the Epiverse TRACE +R-universe](https://epiverse-trace.r-universe.dev/epiparameter) + +``` r +install.packages("epiparameter", repos = c("https://epiverse-trace.r-universe.dev", "https://cloud.r-project.org")) +``` + +## Quick start + +``` r +library(epiparameter) +``` + +To load the library of epidemiological parameters into `R`: + +``` r +epiparameters <- epiparameter_db() +#> Returning 125 results that match the criteria (100 are parameterised). +#> Use subset to filter by entry variables or single_epiparameter to return a single entry. +#> To retrieve the citation for each use the 'get_citation' function +epiparameters +#> # List of 125 <epiparameter> objects +#> Number of diseases: 23 +#> ❯ Adenovirus ❯ Chikungunya ❯ COVID-19 ❯ Dengue ❯ Ebola Virus Disease ❯ Hantavirus Pulmonary Syndrome ❯ Human Coronavirus ❯ Influenza ❯ Japanese Encephalitis ❯ Marburg Virus Disease ❯ Measles ❯ MERS ❯ Mpox ❯ Parainfluenza ❯ Pneumonic Plague ❯ Rhinovirus ❯ Rift Valley Fever ❯ RSV ❯ SARS ❯ Smallpox ❯ West Nile Fever ❯ Yellow Fever ❯ Zika Virus Disease +#> Number of epi parameters: 13 +#> ❯ case fatality risk ❯ generation time ❯ hospitalisation to death ❯ hospitalisation to discharge ❯ incubation period ❯ notification to death ❯ notification to discharge ❯ offspring distribution ❯ onset to death ❯ onset to discharge ❯ onset to hospitalisation ❯ onset to ventilation ❯ serial interval +#> [[1]] +#> Disease: Adenovirus +#> Pathogen: Adenovirus +#> Epi Parameter: incubation period +#> Study: Lessler J, Reich N, Brookmeyer R, Perl T, Nelson K, Cummings D (2009). +#> "Incubation periods of acute respiratory viral infections: a systematic +#> review." _The Lancet Infectious Diseases_. +#> doi:10.1016/S1473-3099(09)70069-6 +#> <https://doi.org/10.1016/S1473-3099%2809%2970069-6>. +#> Distribution: lnorm +#> Parameters: +#> meanlog: 1.723 +#> sdlog: 0.231 +#> +#> [[2]] +#> Disease: Human Coronavirus +#> Pathogen: Human_Cov +#> Epi Parameter: incubation period +#> Study: Lessler J, Reich N, Brookmeyer R, Perl T, Nelson K, Cummings D (2009). +#> "Incubation periods of acute respiratory viral infections: a systematic +#> review." _The Lancet Infectious Diseases_. +#> doi:10.1016/S1473-3099(09)70069-7 +#> <https://doi.org/10.1016/S1473-3099%2809%2970069-7>. +#> Distribution: lnorm +#> Parameters: +#> meanlog: 1.163 +#> sdlog: 0.140 +#> +#> [[3]] +#> Disease: SARS +#> Pathogen: SARS-Cov-1 +#> Epi Parameter: incubation period +#> Study: Lessler J, Reich N, Brookmeyer R, Perl T, Nelson K, Cummings D (2009). +#> "Incubation periods of acute respiratory viral infections: a systematic +#> review." _The Lancet Infectious Diseases_. +#> doi:10.1016/S1473-3099(09)70069-8 +#> <https://doi.org/10.1016/S1473-3099%2809%2970069-8>. +#> Distribution: lnorm +#> Parameters: +#> meanlog: 1.386 +#> sdlog: 0.593 +#> +#> # ℹ 122 more elements +#> # ℹ Use `print(n = ...)` to see more elements. +#> # ℹ Use `parameter_tbl()` to see a summary table of the parameters. +#> # ℹ Explore database online at: https://epiverse-trace.github.io/epiparameter/articles/database.html +``` + +This results in a list of database entries. Each entry of the library is +an `<epiparameter>` object. + +Alternatively, the library of epiparameters can be viewed as a vignette +locally (`vignette("database", package = "epiparameter")`) or on the +[{epiparameter} +website](https://epiverse-trace.github.io/epiparameter/articles/database.html). + +The results can be filtered by disease and epidemiological distribution. +Here we set `single_epiparameter = TRUE` as we only want a single +database entry returned, and by default (`single_epiparameter = FALSE`) +it will return all database entries that match the disease (`disease`) +and epidemiological parameter (`epi_name`). + +``` r +influenza_incubation <- epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + single_epiparameter = TRUE +) +#> Using Virlogeux V, Li M, Tsang T, Feng L, Fang V, Jiang H, Wu P, Zheng J, Lau +#> E, Cao Y, Qin Y, Liao Q, Yu H, Cowling B (2015). "Estimating the +#> Distribution of the Incubation Periods of Human Avian Influenza A(H7N9) +#> Virus Infections." _American Journal of Epidemiology_. +#> doi:10.1093/aje/kwv115 <https://doi.org/10.1093/aje/kwv115>.. +#> To retrieve the citation use the 'get_citation' function +influenza_incubation +#> Disease: Influenza +#> Pathogen: Influenza-A-H7N9 +#> Epi Parameter: incubation period +#> Study: Virlogeux V, Li M, Tsang T, Feng L, Fang V, Jiang H, Wu P, Zheng J, Lau +#> E, Cao Y, Qin Y, Liao Q, Yu H, Cowling B (2015). "Estimating the +#> Distribution of the Incubation Periods of Human Avian Influenza A(H7N9) +#> Virus Infections." _American Journal of Epidemiology_. +#> doi:10.1093/aje/kwv115 <https://doi.org/10.1093/aje/kwv115>. +#> Distribution: weibull +#> Parameters: +#> shape: 2.101 +#> scale: 3.839 +``` + +To quickly view the list of epidemiological distributions returned by +`epiparameter_db()` in a table, the `parameter_tbl()` gives a summary of +the data, and offers the ability to subset you data by `disease`, +`pathogen` and epidemiological parameter (`epi_name`). + +``` r +parameter_tbl(epiparameters) +#> # Parameter table: +#> # A data frame: 125 × 7 +#> disease pathogen epi_name prob_distribution author year sample_size +#> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> +#> 1 Adenovirus Adenovi… incubat… lnorm Lessl… 2009 14 +#> 2 Human Coronavir… Human_C… incubat… lnorm Lessl… 2009 13 +#> 3 SARS SARS-Co… incubat… lnorm Lessl… 2009 157 +#> 4 Influenza Influen… incubat… lnorm Lessl… 2009 151 +#> 5 Influenza Influen… incubat… lnorm Lessl… 2009 90 +#> 6 Influenza Influen… incubat… lnorm Lessl… 2009 78 +#> 7 Measles Measles… incubat… lnorm Lessl… 2009 55 +#> 8 Parainfluenza Parainf… incubat… lnorm Lessl… 2009 11 +#> 9 RSV RSV incubat… lnorm Lessl… 2009 24 +#> 10 Rhinovirus Rhinovi… incubat… lnorm Lessl… 2009 28 +#> # ℹ 115 more rows +parameter_tbl( + epiparameters, + epi_name = "onset to hospitalisation" +) +#> # Parameter table: +#> # A data frame: 5 × 7 +#> disease pathogen epi_name prob_distribution author year sample_size +#> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> +#> 1 MERS MERS-Cov onset to hospi… <NA> Assir… 2013 23 +#> 2 COVID-19 SARS-CoV-2 onset to hospi… gamma Linto… 2020 155 +#> 3 COVID-19 SARS-CoV-2 onset to hospi… gamma Linto… 2020 34 +#> 4 COVID-19 SARS-CoV-2 onset to hospi… lnorm Linto… 2020 155 +#> 5 COVID-19 SARS-CoV-2 onset to hospi… lnorm Linto… 2020 34 +``` + +The `<epiparameter>` object can be plotted. + +``` r +plot(influenza_incubation) +``` + +<img src="man/figures/README-plot-epiparameter-1.png" width="75%" style="display: block; margin: auto;" /> + +The CDF can also be plotted by setting `cumulative = TRUE`. + +``` r +plot(influenza_incubation, cumulative = TRUE) +``` + +<img src="man/figures/README-plot-epiparameter-cdf-1.png" width="75%" style="display: block; margin: auto;" /> + +### Parameter conversion and extraction + +The parameters of a distribution can be converted to and from mean and +standard deviation. In `{epiparameter}` we implement this for a variety +of distributions: + +- gamma +- lognormal +- Weibull +- negative binomial +- geometric + +The parameters of a probability distribution can also be extracted from +other summary statistics, for example, percentiles of the distribution, +or the median and range of the data. This can be done for: + +- gamma +- lognormal +- Weibull +- normal + +## Contributing to library of epidemiological parameters + +If you would like to contribute to the different epidemiological +parameters stored in the `{epiparameter}` package, you can add data to a +public [google +sheet](https://docs.google.com/spreadsheets/d/1eCL3n_woseg5Npu7XD7TcuNoLUIhMBu8ZoLCkVdATUE/edit?usp=sharing). +This spreadsheet contains two example entries as a guide to what fields +can accept. We are monitoring this sheet for new entries that will +subsequently be included in the package. + +Alternatively, parameters can be added to the [JSON file holding the +data](https://github.com/epiverse-trace/epiparameter/blob/main/inst/extdata/parameters.json) +base directly via a Pull Request. + +You can find explanation of accepted entries for each column in the +[data +dictionary](https://github.com/epiverse-trace/epiparameter/blob/main/inst/extdata/data_dictionary.json). + +## Help + +To report a bug please open an +[issue](https://github.com/epiverse-trace/epiparameter/issues/new/choose) + +## Contribute + +Contributions to `{epiparameter}` are welcomed. [package contributing +guide](https://github.com/epiverse-trace/.github/blob/main/CONTRIBUTING.md). + +## Code of Conduct + +Please note that the `{epiparameter}` project is released with a +[Contributor Code of +Conduct](https://github.com/epiverse-trace/.github/blob/main/CODE_OF_CONDUCT.md). +By contributing to this project, you agree to abide by its terms. + +## Citing this package + +``` r +citation("epiparameter") +#> To cite package 'epiparameter' in publications use: +#> +#> Lambert J, Kucharski A, Tamayo C (2024). _epiparameter: Library of +#> Epidemiological Parameters with Helper Functions and Classes_. +#> doi:10.5281/zenodo.11110881 +#> <https://doi.org/10.5281/zenodo.11110881>, +#> <https://epiverse-trace.github.io/epiparameter>. +#> +#> A BibTeX entry for LaTeX users is +#> +#> @Manual{, +#> title = {epiparameter: Library of Epidemiological Parameters with Helper Functions and Classes}, +#> author = {Joshua W. Lambert and Adam Kucharski and Carmen Tamayo}, +#> year = {2024}, +#> doi = {10.5281/zenodo.11110881}, +#> url = {https://epiverse-trace.github.io/epiparameter}, +#> } +``` diff --git a/_pkgdown.yml b/_pkgdown.yml new file mode 100644 index 000000000..bd8b56ecf --- /dev/null +++ b/_pkgdown.yml @@ -0,0 +1,111 @@ +url: https://epiverse-trace.github.io/epiparameter +template: + package: epiversetheme + bslib: + font_weight_base : 300 + +development: + mode: unreleased + +reference: + - title: epiparameter classes + + - subtitle: epiparameter object + desc: Class constructor, validator, and methods + contents: + - epiparameter + - discretise + - ends_with("\\.epiparameter") + - -has_keyword("epiparameter_distribution_functions") + - -starts_with("convert_") + - assert_epiparameter + - test_epiparameter + - ends_with("\\.multi_epiparameter") + + - title: Accessors + desc: Get data from epi classes + contents: + - get_citation + - get_parameters + + - title: epiparameter helper functions + desc: Functions to help construct `<epiparameter>` objects + contents: + - starts_with("create_") + + - title: epiparameter from {epiparameter} library + desc: Retrieve `<epiparameter>` object directly from database + contents: + - epiparameter_db + + - title: Coercion + desc: Convert data from and to `<epiparameter>` + contents: + - as_epiparameter + - as_epiparameter.data.frame + + - title: Explore epiparameters + desc: Table of epi parameters + contents: + - parameter_tbl + + - title: Distribution functions + desc: Functions for operating on `<epiparameter>` distributions + contents: + - cdf.epiparameter + + - title: Parameter extraction + desc: Extract distribution parameters from summary statistics + contents: + - extract_param + + - title: Parameter conversion + desc: Convert distribution parameter to summary statistics and vice versa + contents: + - starts_with("convert_") + + - title: Epi object checking + desc: Check an object is of a certain type or feature + contents: + - starts_with("is_") + + - title: Utility function + contents: + - calc_disc_dist_quantile + + - title: Package data + desc: Data stored in the package + contents: + - epireview_core_cols + + - title: Options + contents: + - epiparameter_options + +articles: +- title: Get started + navbar: Intro + contents: + - epiparameter + - extract_convert + +- title: Parameter library + navbar: Epiparameter Data + contents: + - data_protocol + - database + +- title: Data from other packages + navbar: Handling data from other packages + contents: + - articles/data_from_epireview + +- title: Auxiliary + navbar: Auxiliary + contents: + - extract-bias + +- title: Developer Documentation + navbar: Developer Documentation + contents: + - design_principles diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..04c558599 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,14 @@ +comment: false + +coverage: + status: + project: + default: + target: auto + threshold: 1% + informational: true + patch: + default: + target: auto + threshold: 1% + informational: true diff --git a/data-raw/epireview_core_cols.R b/data-raw/epireview_core_cols.R new file mode 100644 index 000000000..0008d9fe4 --- /dev/null +++ b/data-raw/epireview_core_cols.R @@ -0,0 +1,25 @@ +## code to prepare core columns from the {epireview} epidemiological +## parameters goes here + +# {epireview} is not a package dependency so wrapped in requireNamespace() +if (requireNamespace("epireview", quietly = TRUE)) { + epireview_marburg <- epireview::load_epidata("marburg") + epireview_ebola <- epireview::load_epidata("ebola") + epireview_lassa <- epireview::load_epidata("lassa") + + intersect_marburg_ebola <- intersect( + colnames(epireview_marburg$params), + colnames(epireview_ebola$params) + ) + epireview_core_cols <- intersect( + intersect_marburg_ebola, + colnames(epireview_lassa$params) + ) + usethis::use_data( + epireview_core_cols, + overwrite = TRUE, + version = 3 + ) +} + + diff --git a/data-raw/parameters.R b/data-raw/parameters.R new file mode 100644 index 000000000..4bb26c216 --- /dev/null +++ b/data-raw/parameters.R @@ -0,0 +1,9 @@ +## code to prepare `parameters` dataset goes here + +multi_epiparameter <- epiparameter:::.read_epiparameter_db() +usethis::use_data( + multi_epiparameter, + internal = TRUE, + overwrite = TRUE, + version = 3 +) diff --git a/data/epireview_core_cols.rda b/data/epireview_core_cols.rda new file mode 100644 index 000000000..f08fb3dac Binary files /dev/null and b/data/epireview_core_cols.rda differ diff --git a/epiparameter.Rproj b/epiparameter.Rproj new file mode 100644 index 000000000..49f2092f8 --- /dev/null +++ b/epiparameter.Rproj @@ -0,0 +1,19 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +StripTrailingWhitespace: Yes + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source diff --git a/inst/CITATION b/inst/CITATION new file mode 100644 index 000000000..80ee71903 --- /dev/null +++ b/inst/CITATION @@ -0,0 +1,24 @@ +# Code copied from citation() +author <- meta$`Authors@R` +if (length(author)) { + aar <- .read_authors_at_R_field(author) + author <- Filter(function(e) { + !(is.null(e$given) && is.null(e$family)) && !is.na(match("aut", + e$role)) + }, aar) +} + +if (is.null(meta$Date)) { + date <- format(Sys.Date(), "%Y") +} else { + date <- format(as.Date(meta$Date), "%Y") +} + +bibentry( + bibtype = "Manual", + title = paste0(meta$Package, ": ", gsub("[[:space:]]+", " ", meta$Title)), + author = author, + year = date, + doi = "10.5281/zenodo.11110881", + url = "https://epiverse-trace.github.io/epiparameter" +) diff --git a/inst/WORDLIST b/inst/WORDLIST new file mode 100644 index 000000000..d58628ed6 --- /dev/null +++ b/inst/WORDLIST @@ -0,0 +1,56 @@ +arxiv +bayesian +bioRxiv +ci +CMD +Codecov +contactmatrix +CoV +discretisation +discretised +Discretises +distcrete +dplyr +ebola +epidist +EpiParameter +epiparameters +epireview +episoap +Epiverse +estimat +etc +EVD +facetted +Guzzetta +jsonlite +Lassa +Lifecycle +Marburg +md +meanlog +medRxiv +MERS +monkeypox +mpox +ORCID +parameterisations +parameterised +PERG +pkgdown +PMF +poisson +Poisson +PRISMA +prob +PubMed +SARS +Scopus +sd +sdlog +sensu +stochasticity +th +un +unparameterised +zenodo \ No newline at end of file diff --git a/inst/extdata/data_dictionary.json b/inst/extdata/data_dictionary.json new file mode 100644 index 000000000..f0a30772c --- /dev/null +++ b/inst/extdata/data_dictionary.json @@ -0,0 +1,457 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "epiparameter data", + "description": "The database of epidemiological distributions for a variety of infectious diseases and pathogens. Last modified 11/05/2023.", + "type": "array", + "items": { + "type": "object", + "properties": { + "disease": { + "description": "The infectious disease specified in the study.", + "examples": ["ebola", "measles"], + "type": "string" + }, + "pathogen": { + "description": "Causative agent of disease specified in study. NA if not specified in study.", + "examples": ["SARS-CoV-2", "monkeypox virus"], + "type": ["string", "null"] + }, + "epi_name": { + "description": "The name of the epidemiological parameter type. Names should be whitespace separated within each string.", + "examples": ["incubation period", "serial interval", "offspring distribution"], + "type": "string", + "enum": ["incubation period", "onset to hospitalisation", "onset to death", "serial interval", "generation time", "offspring distribution", "hospitalisation to death", "hospitalisation to discharge", "notification to death", "notification to discharge", "onset to discharge", "onset to ventilation", "case fatality risk"] + }, + "probability_distribution": { + "description": "An object containing the name of the probability distribution and its porameters if available.", + "type": "object", + "properties": { + "prob_distribution": { + "description": "The name of the probability distribution, following R language distribution naming. A probability distribution can be null in cases when summary statistics are reported by a distribution is not given.", + "examples": ["lnorm", "gamma"], + "type": ["string", "null"], + "enum": ["lnorm", "gamma", "weibull", "nbinom", "geom", "pois", "norm", null] + }, + "parameters": { + "type": "object", + "propertyNames": { + "enum": ["shape", "shape_ci_limits", "shape_ci", "scale", "scale_ci_limits", "scale_ci", "meanlog", "meanlog_ci_limits", "meanlog_ci", "sdlog", "sdlog_ci_limits", "sdlog_ci", "dispersion", "dispersion_ci_limits", "dispersion_ci", "precision", "precision_ci_limits", "precision_ci", "mean", "mean_ci_limits", "mean_ci", "sd", "sd_ci_limits", "sd_ci"] + }, + "properties": { + "shape": { + "description": "The shape parameter of either the gamma or Weibull distribution.", + "examples": [2.0, 4.5], + "type": "number" + }, + "shape_ci_limits": { + "description": "The confidence interval of the distribution's shape parameter, specified by two numbers in an array.", + "examples": [[0.3, 3.2],[0.5, 0.7]], + "type": "array", + "items": { + "type": "number" + } + }, + "shape_ci": { + "description": "The interval of the uncertainty around the shape parameter of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": "number" + }, + "scale": { + "description": "The scale parameter of either the gamma or Weibull distribution.", + "examples": [0.9, 1.1], + "type": "number" + }, + "scale_ci_limits": { + "description": "The confidence interval of the distribution's scale parameter, specified by two numbers in an array.", + "examples": [[0.2, 0.5], [1.1, 1.7]], + "type": "array", + "items": { + "type": "number" + } + }, + "scale_ci": { + "description": "The interval of the uncertainty around the scale parameter of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": "number" + }, + "meanlog": { + "description": "The meanlog parameter of the lognormal distribution.", + "examples": [4.3, 7], + "type": "number" + }, + "meanlog_ci_limits": { + "description": "The confidence interval of the distribution's meanlog parameter, specified by two numbers in an array.", + "examples": [[0.4, 0.9], [1.5, 3.2]], + "type": "array", + "items": { + "type": "number" + } + }, + "meanlog_ci": { + "description": "The interval of the uncertainty around the meanlog parameter of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": "number" + }, + "sdlog": { + "description": "The sdlog parameter of the lognormal distribution.", + "examples": [1.2, 1.4], + "type": "number" + }, + "sdlog_ci_limits": { + "description": "The confidence interval of the distribution's sdlog parameter, specified by two numbers in an array.", + "examples": [[0.3, 0.8], [1.4, 1.45]], + "type": "array", + "items": { + "type": "number" + } + }, + "sdlog_ci": { + "description": "The interval of the uncertainty around the sdlog parameter of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": ["number", "null"] + }, + "dispersion": { + "description": "The dispersion parameter of the distribution. This is often used for negative binomial distributions and is often represented as k. This is distinct from the dispersion for a lognormal distribution, which is considered a summary statistic.", + "examples": [1.2, 1.4], + "type": "number" + }, + "dispersion_ci_limits": { + "description": "The confidence interval of the distribution's dispersion, specified by two numbers in an array.", + "examples": [[0.3, 0.8], [1.4, 1.45]], + "type": ["array", "null"], + "items": { + "type": "number" + } + }, + "dispersion_ci": { + "description": "The interval of the uncertainty around the dispersion of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": "number" + }, + "precision": { + "description": "The precision parameter of a distribution. It is common to parameterise a distribution using the precision parameter in Bayesian inference.", + "examples": [1.2, 1.4], + "type": ["number", "null"] + }, + "precision_ci_limits": { + "description": "The confidence interval of the distribution's precision parameter, specified by two numbers in an array.", + "examples": [[0.3, 0.8], [1.4, 1.45]], + "type": ["array", "null"], + "items": { + "type": "number" + } + }, + "precision_ci": { + "description": "The interval of the uncertainty around the precision parameter, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": ["number", "null"] + }, + "mean": { + "description": "The mean of the distribution. Only applies to normal and negative binomial distributions (checked by schema below), for other probability distributions the mean should be included in the summary statistics.", + "examples": [1.0, 2.5], + "type": ["number", "null"] + }, + "mean_ci_limits": { + "description": "The confidence interval of the distribution's mean, specified by two numbers in an array.", + "examples": [[0.3, 0.8], [1.4, 1.45]], + "type": ["array", "null"], + "items": { + "type": "number" + } + }, + "mean_ci": { + "description": "The interval of the uncertainty around the mean, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": ["number", "null"] + }, + "sd": { + "description": "The standard deviation of the distribution. Only applies to normal distributions (checked by schema below), for other probability distributions the standard deviation should be included in the summary statistics.", + "examples": [1.0, 2.5], + "type": ["number", "null"] + }, + "sd_ci_limits": { + "description": "The confidence interval of the distribution's standard deviation, specified by two numbers in an array.", + "examples": [[0.3, 0.8], [1.4, 1.45]], + "type": ["array", "null"], + "items": { + "type": "number" + } + }, + "sd_ci": { + "description": "The interval of the uncertainty around the standard deviation, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": ["number", "null"] + } + } + } + }, + "required": ["prob_distribution"], + "if": { + "properties": { + "prob_distribution": { "const": "norm" } + } + }, + "then": { + "properties": { + "parameters": { + "type": "object", + "anyOf": [ + { "required": ["mean"] }, + { "required": ["sd"] } + ] + } + } + }, + "else": { + "if": { + "properties": { + "prob_distribution": { "const": "nbinom" } + } + }, + "then": { + "properties": { + "parameters": { + "type": "object", + "anyOf": [ + { "required": ["mean"] }, + { "required": ["dispersion"] } + ] + } + } + }, + "else": { + "properties": { + "parameters": { + "type": "object", + "not": { + "anyOf": [ + { "required": ["mean"] }, + { "required": ["sd"] }, + { "required": ["dispersion"] } + ] + } + } + } + } + } + }, + "summary_statistics": { + "type": "object", + "propertyNames": { + "enum": ["mean", "mean_ci_limits", "mean_ci", "sd", "sd_ci_limits", "sd_ci", "median", "median_ci_limits", "median_ci", "dispersion", "dispersion_ci_limits", "dispersion_ci", "quantile_values", "quantile_names", "lower_range", "upper_range"] + }, + "properties": { + "mean": { + "description": "The mean value (expectation) of the distribution. If the mean is not reported put NA.", + "examples": [5, 3.2], + "type": "number" + }, + "mean_ci_limits": { + "description": "The confidence interval of the distribution mean specified by two numbers in an array.", + "examples": [[3.1, 5.5], [2, 4.2]], + "type": "array", + "items": { + "type": "number" + } + }, + "mean_ci": { + "description": "The interval of the uncertainty around the mean of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": ["number", "null"] + }, + "sd": { + "description": "The standard deviation of the distribution.", + "examples": [2.3, 0.5], + "type": "number" + }, + "sd_ci_limits": { + "description": "The confidence interval of the distribution standard deviation specified by two numbers in an array.", + "examples": [[0.2, 0.9], [0.8, 1.2]], + "type": "array", + "items": { + "type": "number" + } + }, + "sd_ci": { + "description": "The interval of the uncertainty around the standard deviation of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": "number" + }, + "median": { + "description": "The 50th quantile (or median) of the distribution.", + "examples": [1.7, 2.5], + "type": ["number", "null"] + }, + "median_ci_limits": { + "description": "The confidence interval of the distribution median specified by two numbers in an array.", + "examples": [[2.1, 2.2], [4.5, 5.1]], + "type": "array", + "items": { + "type": "number" + } + }, + "median_ci": { + "description": "The interval of the uncertainty around the median of the distribution, for example 95% confidence interval would be 95.", + "examples": [95, 90, 80], + "type": ["number", "null"] + }, + "quantile_values": { + "description": "The values at the quantiles of the distribution.", + "examples": [[2.1, 5.5], [4.3, 9.2]], + "type": "array", + "items": { + "type": "number" + } + }, + "quantile_names": { + "description": "The names of the quantiles of the distribution, for example 50 is the median and 95 is the 95th quantile of the distribution. These names need to correspond to the quantile values. The first element in quantile_values is named by the first element in quantile_names, etc.", + "examples": [["2.5", "97.5"], ["25", "75"]], + "type": "array", + "items": { + "type": "string" + } + }, + "lower_range": { + "description": "The lower bound of the range of the data which is used to infer the parameters of the distribution when they are not specified.", + "examples": [0.2, 0.4], + "type": "number" + }, + "upper_range": { + "description": "The upper bound of the range of the data which is used to infer the parameters of the distribution when they are not specified.", + "examples": [4.5, 6.7], + "type": "number" + } + } + }, + "citation": { + "type": "object", + "properties": { + "author": { + "type": "array", + "items": { + "type": "object", + "properties": { + "given": { + "description": "A character string with the given name(s) of the author. Middle name, initialised or not, should be included in the given name, not the family name. This is combined with the family name field to create the full name. Give all authors of the publication as separate authors. Following R's person class, give teams, institutes and companies in the given name and not in the family name.", + "examples": ["John", "Amy", "WHO Team"], + "type": "string" + }, + "family": { + "description": "A character string with the family name(s) of the author. Middle name, initialised or not, should be included in the given name, not the family name. This is combined with the given name field to create the full name. When organisations or teams are supplied as a given name, the family name is null.", + "examples": ["Smith", "Jones"], + "type": ["string", "null"] + } + }, + "required": ["given", "family"] + } + }, + "title": { + "description": "The title of the article that published the epidemiological parameters.", + "examples": ["Incubation period of COVID-19", "Serial interval of Ebola"], + "type": "string" + }, + "journal": { + "description": "The name of the journal that published the article that published the epidemiological parameters. This can also be a pre-print server, e.g., medRxiv.", + "examples": ["The Lancet", "PLoS One", "medRxiv"], + "type": "string" + }, + "year": { + "description": "The year the paper or report was published.", + "examples": ["2019", "2020"], + "type": "number", + "exclusiveMinimum": 0 + }, + "pmid": { + "description": "A PubMed unique identifier number assigned to papers to give them a unique identifier within PubMed.", + "examples": [18183754, 23749571], + "type": ["number", "null"] + }, + "doi": { + "description": "A Digital Object Identifier (DOI) assigned to papers which are unique to each paper.", + "examples": ["doi:10.1080/02626667.2018.1560449", "https://doi.org/10.1111/hex.12487", "https://dx.doi.org/10.1080/02626667.2018.1560449", "https://doi.org/10.1016/j.jpsychires.2017.11.014"], + "type": "string" + } + }, + "required": ["author", "title", "journal", "year", "doi"] + }, + "metadata": { + "type": "object", + "properties": { + "units": { + "description": "The units of the epidemiological parameter.", + "examples": ["days", "No units", "percentage"], + "type": ["string"] + }, + "sample_size": { + "description": "The sample of the data used to fit the delay distribution. This is usually the number of people with data on a primary and possibly secondary event of interest. In cases where the sample size is not stated NA can be used.", + "examples": [25, 150], + "type": ["number", "null"] + }, + "region": { + "description": "The geographical location the data was collected. This can either be given at sub-national, national, continental. Multiple nested regions can be given and are comma separated. When the region is not specified NA can be given.", + "examples": ["England", "Wuhan, China"], + "type": ["string", "null"] + }, + "transmission_mode": { + "description": "A character string defining the mode of transmission of the infectious agent, specific to the data used in the study. The defines whether a pathogen is vector-borne (i.e. is transmitted between humans through a intermediate vector), is transmitted from human-to-human ( natural_human_to_human) or other. If multiple modes of transmission are recorded then mixed can be given. In cases where no mode of transmission if known or given in the study unknown can be stated.", + "examples": ["vector_borne", "natural_human_to_human", "unknown"], + "type": "string" + }, + "vector": { + "description": "The name of the vector transmitting the vector-borne disease. This can be a common name, or a latin binomial name of a specific vector species (see examples). Both the common name and taxonomic name can be given with one given in parentheses. When a disease is not vector-borne NA should be given.", + "examples": ["mosquito", "Aedes aegypti", "mosquito (Aedes aegypti)", "Aedes aegypti (mosquito)"], + "type": "string" + }, + "extrinsic": { + "description": "A boolean value defining whether the data entry is an extrinsic delay distribution, such as the extrinsic incubation period. This field is required because intrinsic and extrinsic delay distributions are stored as separate entries in the database and can be linked. When the disease is not vector-borne FALSE should be given.", + "examples": [true, false], + "type": "boolean" + }, + "inference_method": { + "description": "The type of inference used to fit the delay distribution to the data. Abbreviations of model fitting techniques can be specified as long as they are non-ambiguous. This field is only used to determine whether the uncertainty intervals possibly specified in the other fields are: confidence intervals (in the case of maximum likelihood), or credible intervals (in the case of bayesian inference). Uncertainty bounds for another types of inference methods, or if the inference method is unstated are assumed to be confidence intervals. When the inference method is unknown or a disease does not have a probability distribution NA can be given.", + "examples": ["bayesian", "maximum likelihood", "mle"], + "type": ["string", "null"], + "enum": ["mle", "bayesian", null] + } + } + }, + "method_assessment": { + "type": "object", + "properties": { + "truncation": { + "description": "The truncation point for the distribution when right-truncation is used to account for the bias in survival data when fitting the distribution.", + "examples": [10, 15.5], + "type": ["number", "null"] + }, + "discretised": { + "description": "A boolean indicating whether the distribution fit to the data was discretised. If discretisation is not mentioned in the paper it is assumed the distribution fit to the data was continuous.", + "examples": [true, false], + "type": "boolean" + }, + "censored": { + "description": "A boolean indicating whether the distribution fit to the data correctly handled censored data. This is where the timing of events is either not known with precision or is known by recorded to a coarse level.", + "examples": [true, false], + "type": ["boolean", "null"] + }, + "right_truncated": { + "description": "A boolean indicating whether the distribution fit to the data correctly handled right-truncation to account for the fact that people in the cohort that experienced a primary event did not experience a secondary event and so shorter delay times are over-represented in the data.", + "examples": [true, false], + "type": ["boolean", "null"] + }, + "phase_bias_adjusted": { + "description": "A boolean indicating whether the distribution fit took into account whether the outbreak was in a stage of growth or decline which can bias the results.", + "examples": [true, false], + "type": ["boolean", "null"] + } + } + }, + "notes": { + "description": "A notes field to add extra information that can be used to inform the user of the data but could not be recorded in one of the previous fields. When no notes are given use NA.", + "examples": ["No additional notes", "Pooled data from many papers was used to fit distribution"], + "type": ["string", "null"] + } + }, + "required": ["disease", "epi_name", "summary_statistics", "citation", "metadata", "method_assessment", "notes"], + "additionalProperties": false + } +} diff --git a/inst/extdata/parameters.json b/inst/extdata/parameters.json new file mode 100644 index 000000000..4f7dd2dae --- /dev/null +++ b/inst/extdata/parameters.json @@ -0,0 +1,11553 @@ +[ + { + "disease": "Adenovirus", + "pathogen": "Adenovirus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [4.8, 6.5], + "quantile_names": ["25", "75"], + "median": 5.6, + "median_ci_limits": [4.8, 6.3], + "median_ci": 95, + "dispersion": 1.26, + "dispersion_ci_limits": [1.13, 1.38], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-6" + }, + "metadata": { + "units": "days", + "sample_size": 14, + "region": "USA", + "transmission_mode": "experimental", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Analysis on data from Commission on Acute Respiratory Disease. Experimental transmission of minor respiratory illness to human volunteers by filter-passing agents. I. Demonstration of two types of illness characterized by long and short incubation periods and diff erent clinical features. J Clin Invest 1947; 26: 957–82." + }, + { + "disease": "Human Coronavirus", + "pathogen": "Human_Cov", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.9, 3.5], + "quantile_names": ["25", "75"], + "median": 3.2, + "median_ci_limits": [2.8, 3.7], + "median_ci": 95, + "dispersion": 1.15, + "dispersion_ci_limits": [1.07, 1.34], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-7" + }, + "metadata": { + "units": "days", + "sample_size": 13, + "region": "UK", + "transmission_mode": "experimental", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Analysis on data from Bradburne AF, Bynoe ML, Tyrrell DA. Eff ects of a “new” human respiratory virus in volunteers. Br Med J 1967; 3: 767–69." + }, + { + "disease": "SARS", + "pathogen": "SARS-Cov-1", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [1.5, 2.7, 5.9, 10.6], + "quantile_names": ["5", "25", "75", "95"], + "median": 4, + "median_ci_limits": [3.6, 4.4], + "median_ci": 95, + "dispersion": 1.81, + "dispersion_ci_limits": [1.67, 1.95], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-8" + }, + "metadata": { + "units": "days", + "sample_size": 157, + "region": "Mixed", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2009 for references of datasets" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [0.7, 1.1, 1.9, 2.8], + "quantile_names": ["5", "25", "75", "95"], + "median": 1.4, + "median_ci_limits": [1.3, 1.5], + "median_ci": 95, + "dispersion": 1.51, + "dispersion_ci_limits": [1.43, 1.6], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-9" + }, + "metadata": { + "units": "days", + "sample_size": 151, + "region": "Mixed", + "transmission_mode": "mixed", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2009 for references of datasets" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [1.4, 1.7, 2.2, 2.7], + "quantile_names": ["5", "25", "75", "95"], + "median": 1.9, + "median_ci_limits": [1.8, 2], + "median_ci": 95, + "dispersion": 1.23, + "dispersion_ci_limits": [1.17, 1.29], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-10" + }, + "metadata": { + "units": "days", + "sample_size": 90, + "region": "Mixed", + "transmission_mode": "mixed", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "These estimates for the incubation period of influenza A from Lessler et al. 2009 are different from the estimates from the complete data, as they remove Henle et al. 1945 J Immunol, as it is an outlier in the dataset (n=61). Values found at the bottom Table 3." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-B", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [0.3, 0.4, 0.7, 1.1], + "quantile_names": ["5", "25", "75", "95"], + "median": 0.6, + "median_ci_limits": [0.5, 0.6], + "median_ci": 95, + "dispersion": 1.51, + "dispersion_ci_limits": [1.37, 1.64], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-11" + }, + "metadata": { + "units": "days", + "sample_size": 78, + "region": "USA", + "transmission_mode": "experimental", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2009 for references of datasets" +}, +{ + "disease": "Measles", + "pathogen": "Measles Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [8.9, 10.9, 14.4, 17.7], + "quantile_names": ["5", "25", "75", "95"], + "median": 12.5, + "median_ci_limits": [11.8, 13.3], + "median_ci": 95, + "dispersion": 1.23, + "dispersion_ci_limits": [1.18, 1.28], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-12" + }, + "metadata": { + "units": "days", + "sample_size": 55, + "region": "Mixed", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2009 for references of datasets" +}, +{ + "disease": "Parainfluenza", + "pathogen": "Parainfluenza Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.1, 3.2], + "quantile_names": ["25", "75"], + "median": 2.6, + "median_ci_limits": [2.1, 3.1], + "median_ci": 95, + "dispersion": 1.35, + "dispersion_ci_limits": [1.16, 1.55], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-13" + }, + "metadata": { + "units": "days", + "sample_size": 11, + "region": "Mixed", + "transmission_mode": "experimental", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2009 for references of datasets" +}, +{ + "disease": "RSV", + "pathogen": "RSV", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [3.1, 3.8, 5.1, 6.3], + "quantile_names": ["5", "25", "75", "95"], + "median": 4.4, + "median_ci_limits": [3.9, 4.9], + "median_ci": 95, + "dispersion": 1.24, + "dispersion_ci_limits": [1.13, 1.35], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-14" + }, + "metadata": { + "units": "days", + "sample_size": 24, + "region": "Mixed", + "transmission_mode": "mixed", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2009 for references of datasets" +}, +{ + "disease": "Rhinovirus", + "pathogen": "Rhinovirus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [0.8, 1.3, 2.7, 4.5], + "quantile_names": ["5", "25", "75", "95"], + "median": 1.9, + "median_ci_limits": [1.4, 2.4], + "median_ci": 95, + "dispersion": 1.68, + "dispersion_ci_limits": [1.36, 2.01], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Ron", + "family": "Brookmeyer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Kenrad E.", + "family": "Nelson" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of acute respiratory viral infections: a systematic review", + "journal": "The Lancet Infectious Diseases", + "year": 2009, + "pmid": 19393959, + "doi": "10.1016/S1473-3099(09)70069-15" + }, + "metadata": { + "units": "days", + "sample_size": 28, + "region": "USA", + "transmission_mode": "experimental", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2009 for references of datasets" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [0.73, 2.94], + "quantile_names": ["5", "95"], + "median": 1.46, + "median_ci_limits": [1.35, 1.57], + "median_ci": 95, + "dispersion": 1.53, + "dispersion_ci_limits": [1.44, 1.61], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + }, + { + "given": "Ron", + "family": "Brookmeyer" + } + ], + "title": "Estimating incubation period distributions with coarse data", + "journal": "Statistics in Medicine", + "year": 2009, + "pmid": 19598148, + "doi": "10.1002/sim.3659" + }, + "metadata": { + "units": "days", + "sample_size": 151, + "region": "Mixed", + "transmission_mode": "unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Data from Lessler et al 2009 using double interval-censored analysis. Not open source" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [0.73, 2.83], + "quantile_names": ["5", "95"], + "median": 1.43, + "median_ci_limits": [1.33, 1.54], + "median_ci": 95, + "dispersion": 1.51, + "dispersion_ci_limits": [1.43, 1.6], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + }, + { + "given": "Ron", + "family": "Brookmeyer" + } + ], + "title": "Estimating incubation period distributions with coarse data", + "journal": "Statistics in Medicine", + "year": 2009, + "pmid": 19598148, + "doi": "10.1002/sim.3659" + }, + "metadata": { + "units": "days", + "sample_size": 151, + "region": "Mixed", + "transmission_mode": "unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Data from Lessler et al 2009 using single interval-censored analysis. Not open source" +}, +{ + "disease": "RSV", + "pathogen": "RSV", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [3.05, 6.39], + "quantile_names": ["5", "95"], + "median": 4.41, + "median_ci_limits": [3.9, 4.92], + "median_ci": 95, + "dispersion": 1.25, + "dispersion_ci_limits": [1.14, 1.36], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + }, + { + "given": "Ron", + "family": "Brookmeyer" + } + ], + "title": "Estimating incubation period distributions with coarse data", + "journal": "Statistics in Medicine", + "year": 2009, + "pmid": 19598148, + "doi": "10.1002/sim.3659" + }, + "metadata": { + "units": "days", + "sample_size": 24, + "region": "Mixed", + "transmission_mode": "unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Data from Lessler et al 2009 using double interval-censored analysis. Not open source" +}, +{ + "disease": "RSV", + "pathogen": "RSV", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [3.11, 6.26], + "quantile_names": ["5", "95"], + "median": 4.41, + "median_ci_limits": [3.89, 4.94], + "median_ci": 95, + "dispersion": 1.24, + "dispersion_ci_limits": [1.12, 1.35], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + }, + { + "given": "Ron", + "family": "Brookmeyer" + } + ], + "title": "Estimating incubation period distributions with coarse data", + "journal": "Statistics in Medicine", + "year": 2009, + "pmid": 19598148, + "doi": "10.1002/sim.3659" + }, + "metadata": { + "units": "days", + "sample_size": 24, + "region": "Mixed", + "transmission_mode": "unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Data from Lessler et al 2009 using single interval-censored analysis. Not open source" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H1N1", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { + "shape": 3.27, + "scale": 0.51 + } + }, + "summary_statistics": { + "quantile_values": [3.43], + "quantile_names": ["95"], + "median": 1.51, + "median_ci_limits": [1.47, 1.55], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Hiroshi", + "family": "Nishiura" + }, + { + "given": "Hisashi", + "family": "Inaba" + } + ], + "title": "Estimation of the incubation period of influenza A (H1N1-2009) among imported cases: addressing censoring using outbreak data at the origin of importation", + "journal": "Journal of Theoretical Biology", + "year": 2011, + "pmid": 21168422, + "doi": "10.1016/j.jtbi.2010.12.017" + }, + "metadata": { + "units": "days", + "sample_size": 72, + "region": "Japan", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": true + }, + "notes": "Gamma and weibull distributions had equally good fit to the data. This entry is the gamma distribution. Gamma, exponential. Not open source." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H1N1", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { + "shape": 1.74, + "scale": 1.83 + } + }, + "summary_statistics": { + "quantile_values": [3.18], + "quantile_names": ["95"], + "median": 1.43, + "median_ci_limits": [1.21, 1.65], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Hiroshi", + "family": "Nishiura" + }, + { + "given": "Hisashi", + "family": "Inaba" + } + ], + "title": "Estimation of the incubation period of influenza A (H1N1-2009) among imported cases: addressing censoring using outbreak data at the origin of importation", + "journal": "Journal of Theoretical Biology", + "year": 2011, + "pmid": 21168422, + "doi": "10.1016/j.jtbi.2010.12.017" + }, + "metadata": { + "units": "days", + "sample_size": 72, + "region": "Japan", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": true + }, + "notes": "Gamma and weibull distributions had equally good fit to the data. This entry is the weibull distribution. Weibull, exponential" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H7N9", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { } + }, + "summary_statistics": { + "mean": 3.4, + "mean_ci_limits": [3, 3.7], + "mean_ci": 95, + "sd": 1.7, + "quantile_values": [6.5], + "quantile_names": ["95"] + }, + "citation": { + "author": [ + { + "given": "Victor", + "family": "Virlogeux" + }, + { + "given": "Ming", + "family": "Li" + }, + { + "given": "Tim K.", + "family": "Tsang" + }, + { + "given": "Luzhao", + "family": "Feng" + }, + { + "given": "Vicky J.", + "family": "Fang" + }, + { + "given": "Hui", + "family": "Jiang" + }, + { + "given": "Peng", + "family": "Wu" + }, + { + "given": "Jiandong", + "family": "Zheng" + }, + { + "given": "Eric H. Y.", + "family": "Lau" + }, + { + "given": "Yu", + "family": "Cao" + }, + { + "given": "Ying", + "family": "Qin" + }, + { + "given": "Qiaohong", + "family": "Liao" + }, + { + "given": "Hongjie", + "family": "Yu" + }, + { + "given": "Benjamin J.", + "family": "Cowling" + } + ], + "title": "Estimating the Distribution of the Incubation Periods of Human Avian Influenza A(H7N9) Virus Infections", + "journal": "American Journal of Epidemiology", + "year": 2015, + "pmid": 26409239, + "doi": "10.1093/aje/kwv115" + }, + "metadata": { + "units": "days", + "sample_size": 229, + "region": "China", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This study used an original data set and a modified data set. This weibull distribution was fitted to the modified data set and it is recommended to use this one." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H7N9", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 4.5, + "mean_ci_limits": [2.8, 16.2], + "mean_ci": 95, + "sd": 3.3, + "quantile_values": [11], + "quantile_names": ["95"] + }, + "citation": { + "author": [ + { + "given": "Victor", + "family": "Virlogeux" + }, + { + "given": "Ming", + "family": "Li" + }, + { + "given": "Tim K.", + "family": "Tsang" + }, + { + "given": "Luzhao", + "family": "Feng" + }, + { + "given": "Vicky J.", + "family": "Fang" + }, + { + "given": "Hui", + "family": "Jiang" + }, + { + "given": "Peng", + "family": "Wu" + }, + { + "given": "Jiandong", + "family": "Zheng" + }, + { + "given": "Eric H. Y.", + "family": "Lau" + }, + { + "given": "Yu", + "family": "Cao" + }, + { + "given": "Ying", + "family": "Qin" + }, + { + "given": "Qiaohong", + "family": "Liao" + }, + { + "given": "Hongjie", + "family": "Yu" + }, + { + "given": "Benjamin J.", + "family": "Cowling" + } + ], + "title": "Estimating the Distribution of the Incubation Periods of Human Avian Influenza A(H7N9) Virus Infections", + "journal": "American Journal of Epidemiology", + "year": 2015, + "pmid": 26409239, + "doi": "10.1093/aje/kwv115" + }, + "metadata": { + "units": "days", + "sample_size": 229, + "region": "China", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This study used an original data set and a modified data set. This gamma distribution was fitted to the original data set and it is recommended to use the weibull distribution that was fitted to the modified data set." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H7N9", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { } + }, + "summary_statistics": { + "mean": 3.5, + "mean_ci_limits": [3.2, 3.8], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Victor", + "family": "Virlogeux" + }, + { + "given": "Juan", + "family": "Yang" + }, + { + "given": "Vicky J.", + "family": "Fang" + }, + { + "given": "Luzhao", + "family": "Feng" + }, + { + "given": "Tim K.", + "family": "Tsang" + }, + { + "given": "Hui", + "family": "Jiang" + }, + { + "given": "Peng", + "family": "Wu" + }, + { + "given": "Jiandong", + "family": "Zheng" + }, + { + "given": "Eric H. Y.", + "family": "Lau" + }, + { + "given": "Ying", + "family": "Qin" + }, + { + "given": "Zhibin", + "family": "Peng" + }, + { + "given": "J. S. Malik", + "family": "Peiris" + }, + { + "given": "Hongjie", + "family": "Yu" + }, + { + "given": "Benjamin J.", + "family": "Cowling" + } + ], + "title": "Association between the Severity of Influenza A(H7N9) Virus Infections and Length of the Incubation Period", + "journal": "PLoS One", + "year": 2016, + "pmid": 26885816, + "doi": "10.1371/journal.pone.0148506" + }, + "metadata": { + "units": "days", + "sample_size": 395, + "region": "China", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This study fit the weibull distribution to estimate the parameters for the complete data set, those who had a fatal outcome and those with a non-fatal outcome. This is the distribution fit to the complete unpartitioned data." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H7N9", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { + "shape": 2.3, + "shape_ci_limits": [1.8, 2.89], + "shape_ci": 95, + "scale": 4.21, + "scale_ci_limits": [3.62, 4.85], + "scale_ci": 95 + } + }, + "summary_statistics": { + "mean": 3.7, + "mean_ci_limits": [3.4, 4.1], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Victor", + "family": "Virlogeux" + }, + { + "given": "Juan", + "family": "Yang" + }, + { + "given": "Vicky J.", + "family": "Fang" + }, + { + "given": "Luzhao", + "family": "Feng" + }, + { + "given": "Tim K.", + "family": "Tsang" + }, + { + "given": "Hui", + "family": "Jiang" + }, + { + "given": "Peng", + "family": "Wu" + }, + { + "given": "Jiandong", + "family": "Zheng" + }, + { + "given": "Eric H. Y.", + "family": "Lau" + }, + { + "given": "Ying", + "family": "Qin" + }, + { + "given": "Zhibin", + "family": "Peng" + }, + { + "given": "J. S. Malik", + "family": "Peiris" + }, + { + "given": "Hongjie", + "family": "Yu" + }, + { + "given": "Benjamin J.", + "family": "Cowling" + } + ], + "title": "Association between the Severity of Influenza A(H7N9) Virus Infections and Length of the Incubation Period", + "journal": "PLoS One", + "year": 2016, + "pmid": 26885816, + "doi": "10.1371/journal.pone.0148506" + }, + "metadata": { + "units": "days", + "sample_size": 173, + "region": "China", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This study fit the weibull distribution to estimate the parameters for the complete data set, those who had a fatal outcome and those with a non-fatal outcome. This is the distribution fit to the fatal outcome data." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H7N9", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { + "shape": 2.03, + "shape_ci_limits": [1.62, 2.52], + "shape_ci": 95, + "scale": 3.74, + "scale_ci_limits": [3.2, 4.36], + "scale_ci": 95 + } + }, + "summary_statistics": { + "mean": 3.3, + "mean_ci_limits": [2.9, 3.6], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Victor", + "family": "Virlogeux" + }, + { + "given": "Juan", + "family": "Yang" + }, + { + "given":"Vicky J.", + "family": "Fang" + }, + { + "given": "Luzhao", + "family": "Feng" + }, + { + "given": "Tim K.", + "family": "Tsang" + }, + { + "given": "Hui", + "family": "Jiang" + }, + { + "given": "Peng", + "family": "Wu" + }, + { + "given": "Jiandong", + "family": "Zheng" + }, + { + "given": "Eric H. Y.", + "family": "Lau" + }, + { + "given": "Ying", + "family": "Qin" + }, + { + "given": "Zhibin", + "family": "Peng" + }, + { + "given": "J. S. Malik", + "family": "Peiris" + }, + { + "given": "Hongjie", + "family": "Yu" + }, + { + "given": "Benjamin J.", + "family": "Cowling" + } + ], + "title": "Association between the Severity of Influenza A(H7N9) Virus Infections and Length of the Incubation Period", + "journal": "PLoS One", + "year": 2016, + "pmid": 26885816, + "doi": "10.1371/journal.pone.0148506" + }, + "metadata": { + "units": "days", + "sample_size": 222, + "region": "China", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This study fit the weibull distribution to estimate the parameters for the complete data set, those who had a fatal outcome and those with a non-fatal outcome. This is the distribution fit to the non-fatal outcome data." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H1N1", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 4.3, + "mean_ci_limits": [2.6, 6.6], + "mean_ci": 95, + "median": 4 + }, + "citation": { + "author": [ + { + "given": "Ashleigh R.", + "family": "Tuite" + }, + { + "given": "Amy L.", + "family": "Greer" + }, + { + "given": "Michael", + "family": "Whelan" + }, + { + "given": "Anne-Luise", + "family": "Winter" + }, + { + "given": "Brenda", + "family": "Lee" + }, + { + "given": "Ping", + "family": "Yan" + }, + { + "given": "Jianhong", + "family": "Wu" + }, + { + "given": "Seyed", + "family": "Moghadas" + }, + { + "given": "David", + "family": "Buckeridge" + }, + { + "given": "Babak", + "family": "Pourbohloul" + }, + { + "given": "David N.", + "family": "Fisman" + } + ], + "title": "Estimated epidemiologic parameters and morbidity associated with pandemic H1N1 influenza", + "journal": "Canadian Medical Association Journal", + "year": 2010, + "pmid": 19959592, + "doi": "10.1503/cmaj.091807" + }, + "metadata": { + "units": "days", + "sample_size": 316, + "region": "Canada", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The mid-point of the exposure time was used to approximate an exact exposure time instead of interval-censoring. This can lead to a possible bias (overestimation) in incubation times. It was ambiguously reported whether the mean is the mean of the distribution or the meanlog parameter of the lognormal distribution." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H1N1Pdm", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 2.05, + "sd": 0.49 + }, + "citation": { + "author": [ + { + "given": "Azra", + "family": "Ghani" + }, + { + "given": "Marc", + "family": "Baguelin" + }, + { + "given": "Jamie", + "family": "Griffin" + }, + { + "given": "Stefan", + "family": "Flasche" + }, + { + "given": "Albert Jan", + "family": "van Hoek" + }, + { + "given": "Simon", + "family": "Cauchemez" + }, + { + "given": "Christl", + "family": "Donnelly" + }, + { + "given": "Chris", + "family": "Robertson" + }, + { + "given": "Michael", + "family": "White" + }, + { + "given": "James", + "family": "Truscott" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Peter", + "family": "White" + }, + { + "given": "Steve", + "family": "Leach" + }, + { + "given": "Ian", + "family": "Hall" + }, + { + "given": "Helen", + "family": "Jenkins" + }, + { + "given": "Neil", + "family": "Ferguson" + }, + { + "given": "Ben", + "family": "Cooper" + } + ], + "title": "The Early Transmission Dynamics of H1N1pdm Influenza in the United Kingdom", + "journal": "PLoS Currents", + "year": 2009, + "pmid": 20029668, + "doi": "10.1371/currents.RRN1130" + }, + "metadata": { + "units": "days", + "sample_size": 16, + "region": "UK", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H1N1Pdm", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 2.51, + "sd": 1.55 + }, + "citation": { + "author": [ + { + "given": "Azra", + "family": "Ghani" + }, + { + "given": "Marc", + "family": "Baguelin" + }, + { + "given": "Jamie", + "family": "Griffin" + }, + { + "given": "Stefan", + "family": "Flasche" + }, + { + "given": "Albert Jan", + "family": "van Hoek" + }, + { + "given": "Simon", + "family": "Cauchemez" + }, + { + "given": "Christl", + "family": "Donnelly" + }, + { + "given": "Chris", + "family": "Robertson" + }, + { + "given": "Michael", + "family": "White" + }, + { + "given": "James", + "family": "Truscott" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Peter", + "family": "White" + }, + { + "given": "Steve", + "family": "Leach" + }, + { + "given": "Ian", + "family": "Hall" + }, + { + "given": "Helen", + "family": "Jenkins" + }, + { + "given": "Neil", + "family": "Ferguson" + }, + { + "given": "Ben", + "family": "Cooper" + } + ], + "title": "The Early Transmission Dynamics of H1N1pdm Influenza in the United Kingdom", + "journal": "PLoS Currents", + "year": 2009, + "pmid": 20029668, + "doi": "10.1371/currents.RRN1130" + }, + "metadata": { + "units": "days", + "sample_size": 58, + "region": "UK", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H1N1", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [0.9, 2.2], + "quantile_names": ["5", "95"], + "median": 1.4, + "median_ci_limits": [1, 1.8], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Derek A.T.", + "family": "Cummings" + }, + { + "given": "New York City Department of Health and Mental Hygiene Swine Influenza Investigation Team", + "family": null + } + ], + "title": "Outbreak of 2009 Pandemic Influenza A (H1N1) at a New York City School", + "journal": "The New England Journal of Medicine", + "year": 2009, + "pmid": 20042754, + "doi": "10.1056/NEJMoa0906089" + }, + "metadata": { + "units": "days", + "sample_size": 124, + "region": "New York, USA", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes." +}, +{ + "disease": "Influenza", + "pathogen": "Influenza-A-H1N1", + "epi_name": "generation time", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { + "shape": 2.36, + "scale": 3.18 + } + }, + "summary_statistics": { + "quantile_values": [0.9, 5.1], + "quantile_names": ["5", "95"], + "median": 2.7, + "median_ci_limits": [2, 3.5], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Derek A.T.", + "family": "Cummings" + }, + { + "given": "New York City Department of Health and Mental Hygiene Swine Influenza Investigation Team", + "family": null + } + ], + "title": "Outbreak of 2009 Pandemic Influenza A (H1N1) at a New York City School", + "journal": "The New England Journal of Medicine", + "year": 2009, + "pmid": 20042754, + "doi": "10.1056/NEJMoa0906089" + }, + "metadata": { + "units": "days", + "sample_size": 16, + "region": "New York, USA", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The parameters of the weibull are stated without reporting the uncertainty around them. The parameter estimates and sample size is reported in the supplementary appendix." +}, +{ + "disease": "Marburg Virus Disease", + "pathogen": "Marburg Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "lower_range": 2, + "upper_range": 26 + }, + "citation": { + "author": [ + { + "given": "Boris I.", + "family": "Pavlin" + } + ], + "title": "Calculation of incubation period and serial interval from multiple outbreaks of Marburg virus disease", + "journal": "BMC Research Notes", + "year": 2014, + "pmid": 25495697, + "doi": "10.1186/1756-0500-7-906" + }, + "metadata": { + "units": "days", + "sample_size": 76, + "region": "Mixed", + "transmission_mode": "mixed", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This paper did not fit a distribution to the incubation period data and only reported a lower and upper range of the data. This is present in the database as there are no other studies that report the incubation period for Marburg virus. There is another incubation period reported from the same paper for a subset of the data which report the median and interquartile range but again do not fit a distribution to the data." +}, +{ + "disease": "Marburg Virus Disease", + "pathogen": "Marburg Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "median": 7, + "lower_range": 2, + "upper_range": 13 + }, + "citation": { + "author": [ + { + "given": "Boris I.", + "family": "Pavlin" + } + ], + "title": "Calculation of incubation period and serial interval from multiple outbreaks of Marburg virus disease", + "journal": "BMC Research Notes", + "year": 2014, + "pmid": 25495697, + "doi": "10.1186/1756-0500-7-906" + }, + "metadata": { + "units": "days", + "sample_size": 18, + "region": "Mixed", + "transmission_mode": "mixed", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This paper did not fit a distribution to the incubation period data and only reported a median and range for a subset of the data. This is present in the database as there are no other studies that report the incubation period for Marburg virus. This paper also reports the maximum and minimum for the complete data set." +}, +{ + "disease": "Marburg Virus Disease", + "pathogen": "Marburg Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [8, 15], + "quantile_names": ["25", "75"], + "median": 11 + }, + "citation": { + "author": [ + { + "given": "Boris I.", + "family": "Pavlin" + } + ], + "title": "Calculation of incubation period and serial interval from multiple outbreaks of Marburg virus disease", + "journal": "BMC Research Notes", + "year": 2014, + "pmid": 25495697, + "doi": "10.1186/1756-0500-7-906" + }, + "metadata": { + "units": "days", + "sample_size": 38, + "region": "Mixed", + "transmission_mode": "mixed", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This paper did not fit a distribution to the serial interval data and only reported a median and interquartile range. This is present in the database as there are no other studies that report the serial interval for Marburg virus." +}, +{ + "disease": "Marburg Virus Disease", + "pathogen": "Marburg Virus", + "epi_name": "onset to death", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "median": 8, + "lower_range": 2, + "upper_range": 16 + }, + "citation": { + "author": [ + { + "given": "Robert", + "family": "Colebunders" + }, + { + "given": "Antoine", + "family": "Tshomba" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Daniel G.", + "family": "Bausch" + }, + { + "given": "Pat", + "family": "Campbell" + }, + { + "given": "Modeste", + "family": "Libande" + }, + { + "given": "Patricia", + "family": "Pirard" + }, + { + "given": "Florimond", + "family": "Tshioko" + }, + { + "given": "Simon", + "family": "Mardel" + }, + { + "given": "Sabue", + "family": "Mulangu" + }, + { + "given": "Hilde", + "family": "Sleurs" + }, + { + "given": "Pierre E.", + "family": "Rollin" + }, + { + "given": "Jean-Jacques", + "family": "Muyembe-Tamfum" + }, + { + "given": "Benjamin", + "family": "Jeffs" + }, + { + "given": "Matthias", + "family": "Borchert" + }, + { + "given": "International Scientific and Technical Committee 'DRC Watsa/Durba 1999 Marburg Outbreak Investigation Group'", + "family": null + } + ], + "title": "Marburg hemorrhagic fever in Durba and Watsa, Democratic Republic of the Congo: clinical documentation, features of illness, and treatment", + "journal": "The Journal of Infectious Diseases", + "year": 2007, + "pmid": 17940943, + "doi": "10.1086/520543" + }, + "metadata": { + "units": "days", + "sample_size": 77, + "region": "DR Congo", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This paper reports the median and range of the symptom onset to death delay but did not fit a parametric distribution to the data. This is included in the database as it is the only reported symptom onset to death reported in the literature" +}, +{ + "disease": "Marburg Virus Disease", + "pathogen": "Marburg Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 9, + "mean_ci_limits": [8.2, 10], + "mean_ci": 95, + "sd": 5.4, + "sd_ci_limits": [3.9, 8.6], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Marco", + "family": "Ajelli" + }, + { + "given": "Stefano", + "family": "Merler" + } + ], + "title": "Transmission Potential and Design of Adequate Control Measures for Marburg Hemorrhagic Fever", + "journal": "PLoS One", + "year": 2012, + "pmid": 23251407, + "doi": "10.1371/journal.pone.0050948" + }, + "metadata": { + "units": "days", + "sample_size": 374, + "region": "Angola", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The generation time is estimated from non-human viral load data. This paper reports the generation time but assumes the generation time and serial interval are the same it is classified as serial interval here based on Van Kerkove et al. 2015 <10.1038/sdata.2015.19>. The sample size is take from Van Kerkove et al. 2015." +}, +{ + "disease": "SARS", + "pathogen": "SARS-Cov-1", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 1.63, + "mean_ci_limits": [0.54, 2.65], + "mean_ci": 90, + "dispersion": 0.16, + "dispersion_ci_limits": [0.11, 0.64], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 57, + "region": "Singapore", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Parameter estimates are retrieved from the supplementary tables." +}, +{ + "disease": "SARS", + "pathogen": "SARS-Cov-1", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 0.94, + "mean_ci_limits": [0.27, 1.51], + "mean_ci": 90, + "dispersion": 0.17, + "dispersion_ci_limits": [0.1, 0.64], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 33, + "region": "Beijing", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Smallpox", + "pathogen": "Smallpox-Variola-Major", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 3.19, + "mean_ci_limits": [1.66, 4.62], + "mean_ci": 90, + "dispersion": 0.37, + "dispersion_ci_limits": [0.26, 0.69], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 32, + "region": "Europe", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Smallpox", + "pathogen": "Smallpox-Variola-Major", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 0.8, + "mean_ci_limits": [0.32, 1.2], + "mean_ci": 90, + "dispersion": 0.32, + "dispersion_ci_limits": [0.16, 1.76], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 25, + "region": "Benin", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Smallpox", + "pathogen": "Smallpox-Variola-Minor", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 1.6, + "mean_ci_limits": [0.88, 2.16], + "mean_ci": 90, + "dispersion": 0.65, + "dispersion_ci_limits": [0.34, 2.32], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 25, + "region": "England", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Smallpox", + "pathogen": "Smallpox-Variola-Minor", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 1.49, + "dispersion": 0.72, + "dispersion_ci_limits": [0.44, 2.05], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 47, + "region": "Pakistan", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Estimate of R0 taken from original study and CI of dispersion calculated mean of Z and proportion of zeros known " +}, +{ + "disease": "Mpox", + "pathogen": "Monkeypox Virus", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 0.32, + "mean_ci_limits": [0.22, 0.40], + "mean_ci": 90, + "dispersion": 0.58, + "dispersion_ci_limits": [0.32, 3.57], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 147, + "region": "Zaire", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "In the model comparison the geometric model was the better fit to the monkeypox data, however, only the parameters of the negative binomial were reported as so are stored in the database." +}, +{ + "disease": "Pneumonic Plague", + "pathogen": "Yersinia Pestis", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 1.32, + "mean_ci_limits": [1.01, 1.61], + "mean_ci": 90, + "dispersion": 1.37, + "dispersion_ci_limits": [0.88, 3.53], + "dispersion_ci": 90 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 74, + "region": "Mixed", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "In the model comparison the geometric model was the better fit to the Pneumonic Plague data, however, only the parameters of the negative binomial were reported as so are stored in the database." +}, +{ + "disease": "Hantavirus Pulmonary Syndrome", + "pathogen": "Hantavirus (Andes Virus)", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 0.7, + "mean_ci_limits": [0.20, 1.05], + "mean_ci": 90, + "dispersion": 1.66 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 20, + "region": "Argentina", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "In the model comparison the geometric model was the better fit to the Hantavirus data, however, only the parameters of the negative binomial were reported as so are stored in the database. The uncertainty for the dispersion parameter is currently not stored in the database as the upper bound for the confidence interval is infinite, and currently infinite values are not supported." +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "offspring distribution", + "probability_distribution": { + "prob_distribution": "nbinom", + "parameters": { + "mean": 1.5, + "mean_ci_limits": [0.85, 2.08], + "mean_ci": 90, + "dispersion": 5.10 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "J. O.", + "family": "Lloyd-Smith" + }, + { + "given": "S. J.", + "family": "Schreiber" + }, + { + "given": "P. E.", + "family": "Kopp" + }, + { + "given": "W. M.", + "family": "Getz" + } + ], + "title": "Superspreading and the effect of individual variation on disease emergence", + "journal": "Nature", + "year": 2005, + "pmid": 16292310, + "doi": "10.1038/nature04153" + }, + "metadata": { + "units": "No units", + "sample_size": 13, + "region": "Uganda", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "In the model comparison the poisson model was the better fit to the Ebola data, however, only the parameters of the negative binomial were reported as so are stored in the database. The uncertainty for the dispersion parameter is currently not stored in the database as the upper bound for the confidence interval is infinite, and currently infinite values are not supported." +}, +{ + "disease": "Dengue", + "pathogen": "Dengue Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 15, + "mean_ci_limits": [10, 20], + "mean_ci": 95, + "quantile_values": [5, 33], + "quantile_names": ["2.5", "97.5"] + }, + "citation": { + "author": [ + { + "given": "Miranda", + "family": "Chan" + }, + { + "given": "Michael A.", + "family": "Johansson" + } + ], + "title": "The Incubation Periods of Dengue Viruses", + "journal": "PLoS One", + "year": 2012, + "pmid": 23226436, + "doi": "10.1371/journal.pone.0050972" + }, + "metadata": { + "units": "days", + "sample_size": 146, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "Aedes aegypti and Aedes albopictus", + "extrinsic": true, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Extrinsic incubation period for data at 25 degrees celcius" +}, +{ + "disease": "Dengue", + "pathogen": "Dengue Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { + "precision": 4.9, + "precision_ci_limits": [2.8, 7.5], + "precision_ci": 95 + } + }, + "summary_statistics": { + "mean": 6.5, + "mean_ci_limits": [4.8, 8.8], + "mean_ci": 95, + "quantile_values": [2.4, 15], + "quantile_names": ["2.5" ,"97.5"] + }, + "citation": { + "author": [ + { + "given": "Miranda", + "family": "Chan" + }, + { + "given": "Michael A.", + "family": "Johansson" + } + ], + "title": "The Incubation Periods of Dengue Viruses", + "journal": "PLoS One", + "year": 2012, + "pmid": 23226436, + "doi": "10.1371/journal.pone.0050972" + }, + "metadata": { + "units": "days", + "sample_size": 146, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "Aedes aegypti and Aedes albopictus", + "extrinsic": true, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Extrinsic incubation period for data at 30 degrees celcius" +}, +{ + "disease": "Dengue", + "pathogen": "Dengue Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { + "meanlog": 1.75, + "sdlog": 0.27, + "precision": 13.7, + "precision_ci_limits": [10.9, 16.9], + "precision_ci": 95 + } + }, + "summary_statistics": { + "mean": 5.97, + "mean_ci_limits": [5.5, 6.4], + "mean_ci": 95, + "sd": 1.64, + "quantile_values": [3.4, 10], + "quantile_names": ["2.5", "97.5"] + }, + "citation": { + "author": [ + { + "given": "Miranda", + "family": "Chan" + }, + { + "given": "Michael A.", + "family": "Johansson" + } + ], + "title": "The Incubation Periods of Dengue Viruses", + "journal": "PLoS One", + "year": 2012, + "pmid": 23226436, + "doi": "10.1371/journal.pone.0050972" + }, + "metadata": { + "units": "days", + "sample_size": 153, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "Aedes aegypti and Aedes albopictus", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Standard deviation, meanlog and sdlog is taken from Siraj et al. 2017 <10.1371/journal.pntd.0005797>" +}, +{ + "disease": "Zika Virus Disease", + "pathogen": "Zika Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [3.2, 4.6, 7.6, 11.2], + "quantile_names": ["5" ,"25", "75", "95"], + "median": 5.9, + "median_ci_limits": [4.4, 7.6], + "median_ci": 95, + "dispersion": 1.5, + "dispersion_ci_limits": [1.2, 1.9], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Cassandra T.", + "family": "Ott" + }, + { + "given": "Andrea C.", + "family": "Carcelen" + }, + { + "given": "Jacob M.", + "family": "Konikoff" + }, + { + "given": "Joe", + "family": "Williamson" + }, + { + "given": "Qifang", + "family": "Bi" + }, + { + "given": "Lauren M.", + "family": "Kucirka" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Lelia H.", + "family": "Chaisson" + } + ], + "title": "Times to key events in Zika virus infection and implications for blood donation: a systematic review", + "journal": "Bulletin of the World Health Organization", + "year": 2016, + "pmid": 27821887, + "doi": "10.2471/BLT.16.174540" + }, + "metadata": { + "units": "days", + "sample_size": 25, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "Aedes aegypti and Aedes albopictus", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Lessler et al. 2016 for references of datasets" +}, +{ + "disease": "Chikungunya", + "pathogen": "Chikungunya Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.9, 3], + "quantile_names": ["25", "75"], + "median": 3, + "median_ci_limits": [0.5, 3.1], + "median_ci": 95, + "dispersion": 1.04, + "dispersion_ci_limits": [1.04, 1.08], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 21, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "Aedes albopictus", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets" +}, +{ + "disease": "Dengue", + "pathogen": "Dengue Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [4.5, 7.1], + "quantile_names": ["25", "75"], + "median": 5.6, + "median_ci_limits": [5.3, 6], + "median_ci": 95, + "dispersion": 1.41, + "dispersion_ci_limits": [1.34, 1.5], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 169, + "region": "Mixed", + "transmission_mode": "multiple", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets" +}, +{ + "disease": "Dengue", + "pathogen": "Dengue Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [4.3, 6.6], + "quantile_names": ["25", "75"], + "median": 5.3, + "median_ci_limits": [5, 5.7], + "median_ci": 95, + "dispersion": 1.37, + "dispersion_ci_limits": [1.27, 1.52], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 124, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "Aedes aegypti and Aedes albopictus", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets. This is a subset of data containing only mosquito-transmitted infections" +}, +{ + "disease": "Japanese Encephalitis", + "pathogen": "Japanese Encephalitis Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [8.1, 8.6], + "quantile_names": ["25", "75"], + "median": 8.4, + "median_ci_limits": [5.1, 9.4], + "median_ci": 95, + "dispersion": 1.04, + "dispersion_ci_limits": [1.04, 1.05], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 6, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "mosquito", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets" +}, +{ + "disease": "Rift Valley Fever", + "pathogen": "Rift Valley Fever Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [3.1, 5.3], + "quantile_names": ["25", "75"], + "median": 4, + "median_ci_limits": [3.4, 4.9], + "median_ci": 95, + "dispersion": 1.5, + "dispersion_ci_limits": [1.22, 1.82], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 23, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "mosquito", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets. Of the 18 samples at least 17 of them are not trasmitted by mosquitoes" +}, +{ + "disease": "West Nile Fever", + "pathogen": "West Nile Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [1, 1.7, 3.8, 7], + "quantile_names": ["5", "25", "75", "95"], + "median": 2.6, + "median_ci_limits": [1.6, 3.5], + "median_ci": 95, + "dispersion": 1.82, + "dispersion_ci_limits": [1.27, 2.67], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 18, + "region": "Mixed", + "transmission_mode": "multiple", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets" +}, +{ + "disease": "West Nile Fever", + "pathogen": "West Nile Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.8, 3], + "quantile_names": ["25", "75"], + "median": 2.9, + "median_ci_limits": [0.5, 3.1], + "median_ci": 95, + "dispersion": 1.04, + "dispersion_ci_limits": [1.04, 1.29], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 8, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "mosquito", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets. This is a subset of data containing only mosquito-transmitted infections" +}, +{ + "disease": "West Nile Fever", + "pathogen": "West Nile Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [8.7, 13.3], + "quantile_names": ["25", "75"], + "median": 10.8, + "median_ci_limits": [8.4, 14.2], + "median_ci": 95, + "dispersion": 1.35, + "dispersion_ci_limits": [1.12, 1.47], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 6, + "region": "Mixed", + "transmission_mode": "organ_transplant", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets. This is a subset of data containing only tramsission by transplant or transfusion. " +}, +{ + "disease": "Yellow Fever", + "pathogen": "Yellow Fever Viruses", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [1.9, 3.2, 6.3, 10.3], + "quantile_names": ["5", "25", "75", "95"], + "median": 4.4, + "median_ci_limits": [4, 5], + "median_ci": 95, + "dispersion": 1.66, + "dispersion_ci_limits": [1.48, 1.82], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 91, + "region": "Mixed", + "transmission_mode": "multiple", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets" +}, +{ + "disease": "Yellow Fever", + "pathogen": "Yellow Fever Viruses", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [1.9, 3.1, 6.2, 10.3], + "quantile_names": ["5", "25", "75", "95"], + "median": 4.4, + "median_ci_limits": [3.9, 5], + "median_ci": 95, + "dispersion": 1.67, + "dispersion_ci_limits": [1.47, 1.84], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kara E.", + "family": "Rudolph" + }, + { + "given": "Justin", + "family": "Lessler" + }, + { + "given": "Rachael M.", + "family": "Moloney" + }, + { + "given": "Brittany", + "family": "Kmush" + }, + { + "given": "Derek A. T.", + "family": "Cummings" + } + ], + "title": "Incubation periods of mosquito-borne viral infections: a systematic review", + "journal": "The American Journal of Tropical Medicine and Hygiene", + "year": 2014, + "pmid": 24639305, + "doi": "10.4269/ajtmh.13-0403" + }, + "metadata": { + "units": "days", + "sample_size": 80, + "region": "Mixed", + "transmission_mode": "vector_borne", + "vector": "mosquito", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Pooled analysis on several data sets, see Rudolph et al 2014 for references of datasets. This is a subset of data containing only mosquito-transmitted infections" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 9, + "mean_ci_limits": [6.6, 10.9], + "mean_ci": 95, + "quantile_values": [3.6, 4.2, 17.3, 19.9], + "quantile_names": ["2.5", "5", "95", "97.5"], + "median": 8.5, + "median_ci_limits": [6.6, 10.9], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Fuminari", + "family": "Miura" + }, + { + "given": "Catharina E.", + "family": "van Ewijk" + }, + { + "given": "Jantien A.", + "family": "Backer" + }, + { + "given": "Maria", + "family": "Xiridou" + }, + { + "given": "Eelco", + "family": "Franz" + }, + { + "given": "Eline", + "family": "Op de Coul" + }, + { + "given": "Diederik", + "family": "Brandwagt" + }, + { + "given": "Brigitte", + "family": "van Cleef" + }, + { + "given": "Gini", + "family": "van Rijckevorsel" + }, + { + "given": "Corien", + "family": "Swaan" + }, + { + "given": "Susan", + "family": "van den Hof" + }, + { + "given": "Jacco", + "family": "Wallinga" + } + ], + "title": "Estimated incubation period for monkeypox cases confirmed in the Netherlands, May 2022", + "journal": "Eurosurveillance", + "year": 2022, + "pmid": 35713026, + "doi": "10.2807/1560-7917.ES.2022.27.24.2200448" + }, + "metadata": { + "units": "days", + "sample_size": 18, + "region": "Netherlands", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 7.6, + "mean_ci_limits": [6.2, 9.7], + "mean_ci": 95, + "sd": 1.8, + "sd_ci_limits": [1.6, 2.2], + "sd_ci": 95, + "quantile_values": [17.1], + "quantile_names": ["95"], + "median": 6.4, + "median_ci_limits": [5.1, 7.9], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kelly", + "family": "Charniga" + }, + { + "given": "Nina B.", + "family": "Masters" + }, + { + "given": "Rachel B.", + "family": "Slayton" + }, + { + "given": "Lucas", + "family": "Gosdin" + }, + { + "given": "Faisal S.", + "family": "Minhaj" + }, + { + "given": "David", + "family": "Philpott" + }, + { + "given": "Dallas", + "family": "Smith" + }, + { + "given": "Shannon", + "family": "Gearhart" + }, + { + "given": "Francisco", + "family": "Alvarado-Ramy" + }, + { + "given": "Clive", + "family": "Brown" + }, + { + "given": "Michelle A.", + "family": "Waltenburg" + }, + { + "given": "Christine M.", + "family": "Hughes" + }, + { + "given": "Yoshinori", + "family": "Nakazawa" + } + ], + "title": "Estimating the incubation period of monkeypox virus during the 2022 multi-national outbreak", + "journal": "medRxiv", + "year": 2022, + "pmid": null, + "doi": "10.1101/2022.06.22.22276713" + }, + "metadata": { + "units": "days", + "sample_size": 22, + "region": "USA", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Uses the methods described by Lessler (10.2471/BLT.16.174540) and Reich (10.1002/sim.3659). Estimated from time from exposure to first symptom onset" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { + "shape": 2.42, + "shape_ci_limits": [1.26, 3.62], + "shape_ci": 95, + "scale": 3.75 , + "scale_ci_limits": [2.17, 7.13], + "scale_ci": 95 + } + }, + "summary_statistics": { + "mean": 9.1, + "mean_ci_limits": [6.5, 10.9], + "mean_ci": 95, + "quantile_values": [2, 20], + "quantile_names": ["5", "95"] + }, + "citation": { + "author": [ + { + "given": "Giorgio", + "family": "Guzzetta" + }, + { + "given": "Alessia", + "family": "Mammone" + }, + { + "given": "Federica", + "family": "Ferraro" + }, + { + "given": "Anna", + "family": "Caraglia" + }, + { + "given": "Alessia", + "family": "Rapiti" + }, + { + "given": "Valentina", + "family": "Marziano" + }, + { + "given": "Piero", + "family": "Poletti" + }, + { + "given": "Danilo", + "family": "Cereda" + }, + { + "given": "Francesco", + "family": "Vairo" + }, + { + "given": "Giovanna", + "family": "Mattei" + }, + { + "given": "Francesco", + "family": "Maraglino" + }, + { + "given": "Giovanni", + "family": "Rezza" + }, + { + "given": "Stefano", + "family": "Merler" + } + ], + "title": "Early Estimates of Monkeypox Incubation Period, Generation Time, and Reproduction Number, Italy, May-June 2022", + "journal": "Emerging Infectious Diseases", + "year": 2022, + "pmid": 35994726, + "doi": "10.3201/eid2810.221126" + }, + "metadata": { + "units": "days", + "sample_size": 30, + "region": "Italy", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { + "meanlog": 1.8, + "meanlog_ci_limits": [1.6, 2.1], + "meanlog_ci": 95, + "sdlog": 0.6, + "sdlog_ci_limits": [0.4, 0.8], + "sdlog_ci": 95 + } + }, + "summary_statistics": { + "mean": 7.5, + "mean_ci_limits": [6, 9.8], + "mean_ci": 95, + "sd": 4.9, + "sd_ci_limits": [3.2, 8.8], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Zachary J.", + "family": "Madewell" + }, + { + "given": "Kelly", + "family": "Charniga" + }, + { + "given": "Nina B.", + "family": "Masters" + }, + { + "given": "Jason", + "family": "Asher" + }, + { + "given": "Lily", + "family": "Fahrenwald" + }, + { + "given": "William", + "family": "Still" + }, + { + "given": "Judy", + "family": "Chen" + }, + { + "given": "Naama", + "family": "Kipperman" + }, + { + "given": "David", + "family": "Bui" + }, + { + "given": "Meghan", + "family": "Shea" + }, + { + "given": "Lori", + "family": "Saathoff-Huber" + }, + { + "given": "Shannon", + "family": "Johnson" + }, + { + "given": "Khalil", + "family": "Harbi" + }, + { + "given": "Abby L.", + "family": "Berns" + }, + { + "given": "Taidy", + "family": "Perez" + }, + { + "given": "Emily", + "family": "Gateley" + }, + { + "given": "Ian H.", + "family": "Spicknall" + }, + { + "given": "Yoshinori", + "family": "Nakazawa" + }, + { + "given": "Thomas L.", + "family": "Gift" + }, + { + "given": "2022 Monkeypox Outbreak Response Team", + "family": null + } + ], + "title": "Serial interval and incubation period estimates of monkeypox virus infection in 12 U.S. jurisdictions, May – August 2022", + "journal": "medRxiv", + "year": 2022, + "pmid": null, + "doi": "10.1101/2022.10.26.22281516" + }, + "metadata": { + "units": "days", + "sample_size": 35, + "region": "USA", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Meanlog, sdlog, and fitted distribution from supplementary material. Uses cases from Charniga 2022 + extra cases. Incubation period as exposure to rash onset." +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { + "meanlog": 1.5, + "meanlog_ci_limits": [1.2, 1.8], + "meanlog_ci": 95, + "sdlog": 0.7, + "sdlog_ci_limits": [0.5, 1], + "sdlog_ci": 95 + } + }, + "summary_statistics": { + "mean": 5.6, + "mean_ci_limits": [4.3, 7.8], + "mean_ci": 95, + "sd": 4.4, + "sd_ci_limits": [2.8, 8.7], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Zachary J.", + "family": "Madewell" + }, + { + "given": "Kelly", + "family": "Charniga" + }, + { + "given": "Nina B.", + "family": "Masters" + }, + { + "given": "Jason", + "family": "Asher" + }, + { + "given": "Lily", + "family": "Fahrenwald" + }, + { + "given": "William", + "family": "Still" + }, + { + "given": "Judy", + "family": "Chen" + }, + { + "given": "Naama", + "family": "Kipperman" + }, + { + "given": "David", + "family": "Bui" + }, + { + "given": "Meghan", + "family": "Shea" + }, + { + "given": "Lori", + "family": "Saathoff-Huber" + }, + { + "given": "Shannon", + "family": "Johnson" + }, + { + "given": "Khalil", + "family": "Harbi" + }, + { + "given": "Abby L.", + "family": "Berns" + }, + { + "given": "Taidy", + "family": "Perez" + }, + { + "given": "Emily", + "family": "Gateley" + }, + { + "given": "Ian H.", + "family": "Spicknall" + }, + { + "given": "Yoshinori", + "family": "Nakazawa" + }, + { + "given": "Thomas L.", + "family": "Gift" + }, + { + "given": "2022 Monkeypox Outbreak Response Team", + "family": null + } + ], + "title": "Serial interval and incubation period estimates of monkeypox virus infection in 12 U.S. jurisdictions, May – August 2023", + "journal": "medRxiv", + "year": 2022, + "pmid": null, + "doi": "10.1101/2022.10.26.22281516" + }, + "metadata": { + "units": "days", + "sample_size": 36, + "region": "USA", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Meanlog, sdlog, and fitted distribution from supplementary material. Uses cases from Charniga 2022 + extra cases. Incubation period as exposure to symptom onset." +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { + "shape": 2.9, + "shape_ci_limits": [2, 4.1], + "shape_ci": 95, + "scale": 2.9, + "scale_ci_limits": [2, 4.4], + "scale_ci": 95 + } + }, + "summary_statistics": { + "mean": 8.5, + "mean_ci_limits": [7.3, 9.9], + "mean_ci": 95, + "sd": 5, + "sd_ci_limits": [4, 6.4], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Zachary J.", + "family": "Madewell" + }, + { + "given": "Kelly", + "family": "Charniga" + }, + { + "given": "Nina B.", + "family": "Masters" + }, + { + "given": "Jason", + "family": "Asher" + }, + { + "given": "Lily", + "family": "Fahrenwald" + }, + { + "given": "William", + "family": "Still" + }, + { + "given": "Judy", + "family": "Chen" + }, + { + "given": "Naama", + "family": "Kipperman" + }, + { + "given": "David", + "family": "Bui" + }, + { + "given": "Meghan", + "family": "Shea" + }, + { + "given": "Lori", + "family": "Saathoff-Huber" + }, + { + "given": "Shannon", + "family": "Johnson" + }, + { + "given": "Khalil", + "family": "Harbi" + }, + { + "given": "Abby L.", + "family": "Berns" + }, + { + "given": "Taidy", + "family": "Perez" + }, + { + "given": "Emily", + "family": "Gateley" + }, + { + "given": "Ian H.", + "family": "Spicknall" + }, + { + "given": "Yoshinori", + "family": "Nakazawa" + }, + { + "given": "Thomas L.", + "family": "Gift" + }, + { + "given": "2022 Monkeypox Outbreak Response Team", + "family": null + } + ], + "title": "Serial interval and incubation period estimates of monkeypox virus infection in 12 U.S. jurisdictions, May – August 2024", + "journal": "medRxiv", + "year": 2022, + "pmid": null, + "doi": "10.1101/2022.10.26.22281516" + }, + "metadata": { + "units": "days", + "sample_size": 57, + "region": "USA", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Shape and scale from supp. material. Serial interval as exposure to symptom onset" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { + "shape": 2.8, + "shape_ci_limits": [1.8, 4.2], + "shape_ci": 95, + "scale": 2.5, + "scale_ci_limits": [2.5, 4], + "scale_ci": 95 + } + }, + "summary_statistics": { + "mean": 7, + "mean_ci_limits": [5.8, 8.4], + "mean_ci": 95, + "sd": 4.2, + "sd_ci_limits": [3.2, 5.6], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Zachary J.", + "family": "Madewell" + }, + { + "given": "Kelly", + "family": "Charniga" + }, + { + "given": "Nina B.", + "family": "Masters" + }, + { + "given": "Jason", + "family": "Asher" + }, + { + "given": "Lily", + "family": "Fahrenwald" + }, + { + "given": "William", + "family": "Still" + }, + { + "given": "Judy", + "family": "Chen" + }, + { + "given": "Naama", + "family": "Kipperman" + }, + { + "given": "David", + "family": "Bui" + }, + { + "given": "Meghan", + "family": "Shea" + }, + { + "given": "Lori", + "family": "Saathoff-Huber" + }, + { + "given": "Shannon", + "family": "Johnson" + }, + { + "given": "Khalil", + "family": "Harbi" + }, + { + "given": "Abby L.", + "family": "Berns" + }, + { + "given": "Taidy", + "family": "Perez" + }, + { + "given": "Emily", + "family": "Gateley" + }, + { + "given": "Ian H.", + "family": "Spicknall" + }, + { + "given": "Yoshinori", + "family": "Nakazawa" + }, + { + "given": "Thomas L.", + "family": "Gift" + }, + { + "given": "2022 Monkeypox Outbreak Response Team", + "family": null + } + ], + "title": "Serial interval and incubation period estimates of monkeypox virus infection in 12 U.S. jurisdictions, May – August 2025", + "journal": "medRxiv", + "year": 2022, + "pmid": null, + "doi": "10.1101/2022.10.26.22281516" + }, + "metadata": { + "units": "days", + "sample_size": 40, + "region": "USA", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Shape and scale from supp. material. Serial interval as exposure to rash onset" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus-Zaire Subtype", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 12.7, + "sd": 4.31 + }, + "citation": { + "author": [ + { + "given": "Martin", + "family": "Eichner" + }, + { + "given": "Scott F.", + "family": "Dowell" + }, + { + "given": "Nina", + "family": "Firese" + } + ], + "title": "Incubation period of ebola hemorrhagic virus subtype zaire", + "journal": "Osong Public Health and Research Perspectives", + "year": 2011, + "pmid": 24159443, + "doi": "10.1016/j.phrp.2011.04.001" + }, + "metadata": { + "units": "days", + "sample_size": 196, + "region": "Kikwit, Democratic Republic of Congo", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The paper reports lower and upper supported ranges for the mean and standard deviation but it is not clear if these are confidence intervals or not so are not included in the database" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus-Zaire Subtype", + "epi_name": "onset to death", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { + "shape": 2.4, + "shape_ci_limits": [1.1, 4.5], + "shape_ci": 95, + "scale": 3.3333, + "scale_ci_limits": [2, 10], + "scale_ci": 95 + } + }, + "summary_statistics": { + "mean": 9.3, + "mean_ci_limits": [6.6, 13.6], + "mean_ci": 95, + "sd": 6, + "sd_ci_limits": [4, 11], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "The Ebola Outbreak Epidemiology Team", + "family": null + }, + { + "given": "Ahmadou", + "family": "Barry" + }, + { + "given": "Steve", + "family": "Ahuka-Mundeke" + }, + { + "given": "Yahaya", + "family": "Ali Ahmed" + }, + { + "given": "Yokouide", + "family": "Allarangar" + }, + { + "given": "Julienne", + "family": "Anoko" + }, + { + "given": "Brett Nicholas", + "family": "Archer" + }, + { + "given": "Aaron Aruna", + "family": "Abedi" + }, + { + "given": "Jayshree", + "family": "Bagaria" + }, + { + "given": "Marie Roseline Darnycka", + "family": "Belizaire" + }, + { + "given": "Sangeeta", + "family": "Bhatia" + }, + { + "given": "Théophile", + "family": "Bokenge" + }, + { + "given": "Emanuele", + "family": "Bruni" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Ernest", + "family": "Dabire" + }, + { + "given": "Amadou Mouctar", + "family": "Diallo" + }, + { + "given": "Boubacar", + "family": "Diallo" + }, + { + "given": "Christl Ann", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Tshewang Choden", + "family": "Dorji" + }, + { + "given": "Aura Rocio Escobar Corado", + "family": "Waeber" + }, + { + "given": "Ibrahima Socé", + "family": "Fall" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Richard Gareth", + "family": "FitzJohn" + }, + { + "given": "Gervais Leon Folefack", + "family": "Tengomo" + }, + { + "given": "Pierre Bernard Henri", + "family": "Formenty" + }, + { + "given": "Alpha", + "family": "Forna" + }, + { + "given": "Anne", + "family": "Fortin" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Katy A. M.", + "family": "Gaythorpe" + }, + { + "given": "Celine", + "family": "Gurry" + }, + { + "given": "Esther", + "family": "Hamblion" + }, + { + "given": "Mamoudou Harouna", + "family": "Djingarey" + }, + { + "given": "Christopher", + "family": "Haskew" + }, + { + "given": "Stéphane Alexandre Louis", + "family": "Hugonnet" + }, + { + "given": "Natsuko", + "family": "Imai" + }, + { + "given": "Benido", + "family": "Impouma" + }, + { + "given": "Guylain", + "family": "Kabongo" + }, + { + "given": "Oly Ilunga", + "family": "Kalenga" + }, + { + "given": "Emerencienne", + "family": "Kibangou" + }, + { + "given": "Theresa Min-Hyung", + "family": "Lee" + }, + { + "given": "Charles Okot", + "family": "Lukoya" + }, + { + "given": "Ousmane", + "family": "Ly" + }, + { + "given": "Sheila", + "family": "Makiala-Mandanda" + }, + { + "given": "Augustin", + "family": "Mamba" + }, + { + "given": "Placide", + "family": "Mbala-Kingebeni" + }, + { + "given": "Franck Fortune Roland", + "family": "Mboussou" + }, + { + "given": "Tamayi", + "family": "Mlanda" + }, + { + "given": "Vital Mondonge", + "family": "Makuma" + }, + { + "given": "Oliver", + "family": "Morgan" + }, + { + "given": "Anastasie Mujinga", + "family": "Mulumba" + }, + { + "given": "Patrick Mukadi", + "family": "Kakoni" + }, + { + "given": "Daniel", + "family": "Mukadi-Bamuleka" + }, + { + "given": "Jean-Jaques", + "family": "Muyembe" + }, + { + "given": "Ndjoloko Tambwe", + "family": "Bathé" + }, + { + "given": "Patricia", + "family": "Ndumbi Ngamala" + }, + { + "given": "Roland", + "family": "Ngom" + }, + { + "given": "Guillaume", + "family": "Ngoy" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Justus", + "family": "Nsio" + }, + { + "given": "Kevin Babila", + "family": "Ousman" + }, + { + "given": "Emilie", + "family": "Peron" + }, + { + "given": "Jonathan Aaron", + "family": "Polonsky" + }, + { + "given": "Michael J.", + "family": "Ryan" + }, + { + "given": "Alhassane", + "family": "Touré" + }, + { + "given": "Rodney", + "family": "Towner" + }, + { + "given": "Gaston", + "family": "Tshapenda" + }, + { + "given": "Reinhilde", + "family": "Van De Weerdt" + }, + { + "given": "Maria", + "family": "Van Kerkhove" + }, + { + "given": "Annika", + "family": "Wendland" + }, + { + "given": "N'Da Konan Michel", + "family": "Yao" + }, + { + "given": "Zabulon", + "family": "Yoti" + }, + { + "given": "Etienne", + "family": "Yuma" + }, + { + "given": "Guy", + "family": "Kalambayi Kabamba" + }, + { + "given": "Jean de Dieu Lukwesa", + "family": "Mwati" + }, + { + "given": "Gisele", + "family": "Mbuy" + }, + { + "given": "Leopold", + "family": "Lubula" + }, + { + "given": "Anny", + "family": "Mutombo" + }, + { + "given": "Oscar", + "family": "Mavila" + }, + { + "given": "Yyonne", + "family": "Lay" + }, + { + "given": "Emma", + "family": "Kitenge" + } + ], + "title": "Outbreak of Ebola virus disease in the Democratic Republic of the Congo, April–May, 2018: an epidemiological study", + "journal": "The Lancet", + "year": 2018, + "pmid": 30047375, + "doi": "10.1016/S0140-6736(18)31387-4" + }, + "metadata": { + "units": "days", + "sample_size": 14, + "region": "DR Congo", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Data extracted from Appendix. The mean, sd, shape and scale are taken from the paper, the conversion between the two does not match exactly. The data used to estimate the onset-to-death distribution is not from the DRC outbreak but from the west african outbreak." +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 10.3, + "mean_ci_limits": [9.9, 10.7], + "mean_ci": 95, + "sd": 8.2, + "sd_ci_limits": [7.8, 8.6], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 1798, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Data extracted from Appendix. This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 12.6, + "mean_ci_limits": [9.1, 17.1], + "mean_ci": 95, + "sd": 13.1, + "sd_ci_limits": [9.6, 19.6], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 49, + "region": "Guinea", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the Guinea ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 10, + "mean_ci_limits": [9.6, 10.5], + "mean_ci": 95, + "sd": 7.6, + "sd_ci_limits": [7.1, 8.1], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 957, + "region": "Liberia", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the Liberia ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 10.4, + "mean_ci_limits": [9.8, 11], + "mean_ci": 95, + "sd": 8.6, + "sd_ci_limits": [8, 9.3], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 792, + "region": "Sierra Leone", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the Seirra Leone ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 14.2, + "mean_ci_limits": [13.1, 15.3], + "mean_ci": 95, + "sd": 9.6, + "sd_ci_limits": [8.6, 10.7], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 305, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 15.5, + "mean_ci_limits": [13.4, 18.1], + "mean_ci": 95, + "sd": 7, + "sd_ci_limits": [5.5, 9.4], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 37, + "region": "Guinea", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the Guinea ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 15.1, + "mean_ci_limits": [13.5, 16.9], + "mean_ci": 95, + "sd": 10.5, + "sd_ci_limits": [9.1, 12.5], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 147, + "region": "Liberia", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the Liberia ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 12.4, + "mean_ci_limits": [10.8, 14.2], + "mean_ci": 95, + "sd": 9, + "sd_ci_limits": [7.5, 10.9], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 112, + "region": "Sierra Leone", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the Sierra Leone ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "hospitalisation to death", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 4.3, + "mean_ci_limits": [4.1, 4.5], + "mean_ci": 95, + "sd": 4, + "sd_ci_limits": [3.8, 4.3], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 1167, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "hospitalisation to discharge", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 11.2, + "mean_ci_limits": [10.8, 11.7], + "mean_ci": 95, + "sd": 7.2, + "sd_ci_limits": [6.8, 7.6], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 1004, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "notification to death", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 3.5, + "mean_ci_limits": [3.3, 3.7], + "mean_ci": 95, + "sd": 5, + "sd_ci_limits": [4.7, 5.4], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 2536, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "notification to discharge", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 10.9, + "mean_ci_limits": [10.5, 11.4], + "mean_ci": 95, + "sd": 8.2, + "sd_ci_limits": [7.8, 8.7], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 1324, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "onset to death", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 8.2, + "mean_ci_limits": [7.9, 8.4], + "mean_ci": 95, + "sd": 6.4, + "sd_ci_limits": [6.1, 6.6], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 2741, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "Ebola Virus Disease", + "pathogen": "Ebola Virus", + "epi_name": "onset to discharge", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 15.1, + "mean_ci_limits": [14.6, 15.6], + "mean_ci": 95, + "sd": 8.9, + "sd_ci_limits": [8.5, 9.3], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "WHO Ebola Response Team", + "family": null + }, + { + "given": "Junerlyn", + "family": "Agua-Agum" + }, + { + "given": "Archchun", + "family": "Ariyarajah" + }, + { + "given": "Bruce", + "family": "Aylward" + }, + { + "given": "Isobel M.", + "family": "Blake" + }, + { + "given": "Richard", + "family": "Brennan" + }, + { + "given": "Anne", + "family": "Cori" + }, + { + "given": "Christl A.", + "family": "Donnelly" + }, + { + "given": "Ilaria", + "family": "Dorigatti" + }, + { + "given": "Christopher", + "family": "Dye" + }, + { + "given": "Tim", + "family": "Eckmanns" + }, + { + "given": "Neil M.", + "family": "Ferguson" + }, + { + "given": "Pierre", + "family": "Formenty" + }, + { + "given": "Christophe", + "family": "Fraser" + }, + { + "given": "Erika", + "family": "Garcia" + }, + { + "given": "Tini", + "family": "Garske" + }, + { + "given": "Wes", + "family": "Hinsley" + }, + { + "given": "David", + "family": "Holmes" + }, + { + "given": "Stéphane", + "family": "Hugonnet" + }, + { + "given": "Swathi", + "family": "Iyengar" + }, + { + "given": "Thibaut", + "family": "Jombart" + }, + { + "given": "Ravi", + "family": "Krishnan" + }, + { + "given": "Sascha", + "family": "Meijers" + }, + { + "given": "Harriet L.", + "family": "Mills" + }, + { + "given": "Yasmine", + "family": "Mohamed" + }, + { + "given": "Gemma", + "family": "Nedjati-Gilani" + }, + { + "given": "Emily", + "family": "Newton" + }, + { + "given": "Pierre", + "family": "Nouvellet" + }, + { + "given": "Louise", + "family": "Pelletier" + }, + { + "given": "Devin", + "family": "Perkins" + }, + { + "given": "Steven", + "family": "Riley" + }, + { + "given": "Maria", + "family": "Sagrado" + }, + { + "given": "Johannes", + "family": "Schnitzler" + }, + { + "given": "Dirk", + "family": "Schumacher" + }, + { + "given": "Anita", + "family": "Shah" + }, + { + "given": "Maria D.", + "family": "Van Kerkhove" + }, + { + "given": "Olivia", + "family": "Varsaneux" + }, + { + "given": "Niluka Wijekoon", + "family": "Kannangarage" + } + ], + "title": "West African Ebola Epidemic after One Year — Slowing but Not Yet under Control", + "journal": "The New England Journal of Medicine", + "year": 2015, + "pmid": 25539446, + "doi": "10.1056/NEJMc1414992" + }, + "metadata": { + "units": "days", + "sample_size": 1335, + "region": "West Africa", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This data comes from the entire period of the west africa ebola outbreak up to the point the paper was published (Dec 2013 - 25 Nov 2014). The methods fitting are reported in another paper: DOI: 10.1056/NEJMoa1411100" +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.2, 12.4], + "quantile_names": ["5", "95"], + "median": 5.2, + "median_ci_limits": [1.9, 14.7], + "median_ci": null + }, + "citation": { + "author": [ + { + "given": "Abdullah", + "family": "Assiri" + }, + { + "given": "Allison", + "family": "McGeer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Connie S.", + "family": "Price" + }, + { + "given": "Abdullah A.", + "family": "Al Rabeeah" + }, + { + "given": "Derek A.T.", + "family": "Cummings" + }, + { + "given": "Zaki N.", + "family": "Alabdullatif" + }, + { + "given": "Maher", + "family": "Assad" + }, + { + "given": "Abdulmohsen", + "family": "Almulhim" + }, + { + "given": "Hatem", + "family": "Makhdoom" + }, + { + "given": "Hossam", + "family": "Madani" + }, + { + "given": "Rafat", + "family": "Alhakeem" + }, + { + "given": "Jaffar A.", + "family": "Al-Tawfiq" + }, + { + "given": "Matthew", + "family": "Cotten" + }, + { + "given": "Simon J.", + "family": "Watson" + }, + { + "given": "Paul", + "family": "Kellam" + }, + { + "given": "Alimuddin I.", + "family": "Zumla" + }, + { + "given": "Ziad A.", + "family": "Memish" + }, + { + "given": "KSA MERSCOV Investigation Team", + "family": null + } + ], + "title": "Hospital Outbreak of Middle East Respiratory Syndrome Coronavirus", + "journal": "The New England Journal of Medicine", + "year": 2013, + "pmid": 23782161, + "doi": "10.1056/NEJMoa1306742" + }, + "metadata": { + "units": "days", + "sample_size": 23, + "region": "Saudi Arabia", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The sample size is not explicitly stated. The number of confirmed cases is 23 and there are 2 suspected cases, therefore it is not clear whether the 2 suspected cases were included in the estimation, the sample size is assumed to be 23." +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [3, 19.4], + "quantile_names": ["5", "95"], + "median": 7.6, + "median_ci_limits": [2.5, 23.1], + "median_ci": null + }, + "citation": { + "author": [ + { + "given": "Abdullah", + "family": "Assiri" + }, + { + "given": "Allison", + "family": "McGeer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Connie S.", + "family": "Price" + }, + { + "given": "Abdullah A.", + "family": "Al Rabeeah" + }, + { + "given": "Derek A.T.", + "family": "Cummings" + }, + { + "given": "Zaki N.", + "family": "Alabdullatif" + }, + { + "given": "Maher", + "family": "Assad" + }, + { + "given": "Abdulmohsen", + "family": "Almulhim" + }, + { + "given": "Hatem", + "family": "Makhdoom" + }, + { + "given": "Hossam", + "family": "Madani" + }, + { + "given": "Rafat", + "family": "Alhakeem" + }, + { + "given": "Jaffar A.", + "family": "Al-Tawfiq" + }, + { + "given": "Matthew", + "family": "Cotten" + }, + { + "given": "Simon J.", + "family": "Watson" + }, + { + "given": "Paul", + "family": "Kellam" + }, + { + "given": "Alimuddin I.", + "family": "Zumla" + }, + { + "given": "Ziad A.", + "family": "Memish" + }, + { + "given": "KSA MERSCOV Investigation Team", + "family": null + } + ], + "title": "Hospital Outbreak of Middle East Respiratory Syndrome Coronavirus", + "journal": "The New England Journal of Medicine", + "year": 2013, + "pmid": 23782161, + "doi": "10.1056/NEJMoa1306742" + }, + "metadata": { + "units": "days", + "sample_size": 23, + "region": "Saudi Arabia", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The sample size is not explicitly stated. The number of confirmed cases is 23 and there are 2 suspected cases, therefore it is not clear whether the 2 suspected cases were included in the estimation, the sample size is assumed to be 23." +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "onset to hospitalisation", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "median": 5, + "lower_range": 1, + "upper_range": 10 + }, + "citation": { + "author": [ + { + "given": "Abdullah", + "family": "Assiri" + }, + { + "given": "Allison", + "family": "McGeer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Connie S.", + "family": "Price" + }, + { + "given": "Abdullah A.", + "family": "Al Rabeeah" + }, + { + "given": "Derek A.T.", + "family": "Cummings" + }, + { + "given": "Zaki N.", + "family": "Alabdullatif" + }, + { + "given": "Maher", + "family": "Assad" + }, + { + "given": "Abdulmohsen", + "family": "Almulhim" + }, + { + "given": "Hatem", + "family": "Makhdoom" + }, + { + "given": "Hossam", + "family": "Madani" + }, + { + "given": "Rafat", + "family": "Alhakeem" + }, + { + "given": "Jaffar A.", + "family": "Al-Tawfiq" + }, + { + "given": "Matthew", + "family": "Cotten" + }, + { + "given": "Simon J.", + "family": "Watson" + }, + { + "given": "Paul", + "family": "Kellam" + }, + { + "given": "Alimuddin I.", + "family": "Zumla" + }, + { + "given": "Ziad A.", + "family": "Memish" + }, + { + "given": "KSA MERSCOV Investigation Team", + "family": null + } + ], + "title": "Hospital Outbreak of Middle East Respiratory Syndrome Coronavirus", + "journal": "The New England Journal of Medicine", + "year": 2013, + "pmid": 23782161, + "doi": "10.1056/NEJMoa1306742" + }, + "metadata": { + "units": "days", + "sample_size": 23, + "region": "Saudi Arabia", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "A distribution was not fitted to the data, instead the median and range observed are reported. The sample size is not explicitly stated. The number of confirmed cases is 23 and there are 2 suspected cases, therefore it is not clear whether the 2 suspected cases were included in the estimation, the sample size is assumed to be 23." +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "onset to death", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "median": 11, + "lower_range": 5, + "upper_range": 27 + }, + "citation": { + "author": [ + { + "given": "Abdullah", + "family": "Assiri" + }, + { + "given": "Allison", + "family": "McGeer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Connie S.", + "family": "Price" + }, + { + "given": "Abdullah A.", + "family": "Al Rabeeah" + }, + { + "given": "Derek A.T.", + "family": "Cummings" + }, + { + "given": "Zaki N.", + "family": "Alabdullatif" + }, + { + "given": "Maher", + "family": "Assad" + }, + { + "given": "Abdulmohsen", + "family": "Almulhim" + }, + { + "given": "Hatem", + "family": "Makhdoom" + }, + { + "given": "Hossam", + "family": "Madani" + }, + { + "given": "Rafat", + "family": "Alhakeem" + }, + { + "given": "Jaffar A.", + "family": "Al-Tawfiq" + }, + { + "given": "Matthew", + "family": "Cotten" + }, + { + "given": "Simon J.", + "family": "Watson" + }, + { + "given": "Paul", + "family": "Kellam" + }, + { + "given": "Alimuddin I.", + "family": "Zumla" + }, + { + "given": "Ziad A.", + "family": "Memish" + }, + { + "given": "KSA MERSCOV Investigation Team", + "family": null + } + ], + "title": "Hospital Outbreak of Middle East Respiratory Syndrome Coronavirus", + "journal": "The New England Journal of Medicine", + "year": 2013, + "pmid": 23782161, + "doi": "10.1056/NEJMoa1306742" + }, + "metadata": { + "units": "days", + "sample_size": 23, + "region": "Saudi Arabia", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "A distribution was not fitted to the data, instead the median and range observed are reported. The sample size is not explicitly stated. The number of confirmed cases is 23 and there are 2 suspected cases, therefore it is not clear whether the 2 suspected cases were included in the estimation, the sample size is assumed to be 23." +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "onset to ventilation", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "median": 7, + "lower_range": 3, + "upper_range": 11 + }, + "citation": { + "author": [ + { + "given": "Abdullah", + "family": "Assiri" + }, + { + "given": "Allison", + "family": "McGeer" + }, + { + "given": "Trish M.", + "family": "Perl" + }, + { + "given": "Connie S.", + "family": "Price" + }, + { + "given": "Abdullah A.", + "family": "Al Rabeeah" + }, + { + "given": "Derek A.T.", + "family": "Cummings" + }, + { + "given": "Zaki N.", + "family": "Alabdullatif" + }, + { + "given": "Maher", + "family": "Assad" + }, + { + "given": "Abdulmohsen", + "family": "Almulhim" + }, + { + "given": "Hatem", + "family": "Makhdoom" + }, + { + "given": "Hossam", + "family": "Madani" + }, + { + "given": "Rafat", + "family": "Alhakeem" + }, + { + "given": "Jaffar A.", + "family": "Al-Tawfiq" + }, + { + "given": "Matthew", + "family": "Cotten" + }, + { + "given": "Simon J.", + "family": "Watson" + }, + { + "given": "Paul", + "family": "Kellam" + }, + { + "given": "Alimuddin I.", + "family": "Zumla" + }, + { + "given": "Ziad A.", + "family": "Memish" + }, + { + "given": "KSA MERSCOV Investigation Team", + "family": null + } + ], + "title": "Hospital Outbreak of Middle East Respiratory Syndrome Coronavirus", + "journal": "The New England Journal of Medicine", + "year": 2013, + "pmid": 23782161, + "doi": "10.1056/NEJMoa1306742" + }, + "metadata": { + "units": "days", + "sample_size": 23, + "region": "Saudi Arabia", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "A distribution was not fitted to the data, instead the median and range observed are reported. The sample size is not explicitly stated. The number of confirmed cases is 23 and there are 2 suspected cases, therefore it is not clear whether the 2 suspected cases were included in the estimation, the sample size is assumed to be 23." +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "onset to death", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 14.6, + "mean_ci_limits": [11.5, 19.5], + "mean_ci": 95, + "sd": 10.4, + "sd_ci_limits": [7.6, 16.2], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Kenji", + "family": "Mizumoto" + }, + { + "given": "Akira", + "family": "Endo" + }, + { + "given": "Gerardo", + "family": "Chowell" + }, + { + "given": "Yuichiro", + "family": "Miyamatsu" + }, + { + "given": "Masaya", + "family": "Saitoh" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Real-time characterization of risks of death associated with the Middle East respiratory syndrome (MERS) in the Republic of Korea, 2015", + "journal": "BMC Medicine", + "year": 2015, + "pmid": 26420593, + "doi": "10.1186/s12916-015-0468-3" + }, + "metadata": { + "units": "days", + "sample_size": 185, + "region": "South Korea", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The distribution parameters were jointly inferred with the risk factors of mortality." +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 6.7, + "mean_ci_limits": [6.1, 7.3], + "mean_ci": 95, + "median": 6.3, + "median_ci_limits": [5.7, 6.8], + "median_ci": 95, + "quantile_values": [12.1], + "quantile_names": ["95"] + }, + "citation": { + "author": [ + { + "given": "B. J.", + "family": "Cowling" + }, + { + "given": "M.", + "family": "Park" + }, + { + "given": "V. J.", + "family": "Fang" + }, + { + "given": "P.", + "family": "Wu" + }, + { + "given": "G. M.", + "family": "Leung" + }, + { + "given": "J. T.", + "family": "Wu" + } + ], + "title": "Preliminary epidemiological assessment of MERS-CoV outbreak in South Korea, May to June 2015", + "journal": "Eurosurveillance", + "year": 2015, + "pmid": 26132767, + "doi": "10.2807/1560-7917.es2015.20.25.21163" + }, + "metadata": { + "units": "days", + "sample_size": 166, + "region": "South Korea", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "MERS", + "pathogen": "MERS-Cov", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 12.6, + "mean_ci_limits": [12.1, 13.1], + "mean_ci": 95, + "sd": 2.8, + "sd_ci_limits": [2.4, 3.1], + "sd_ci": 95 + }, + "citation": { + "author": [ + { + "given": "B. J.", + "family": "Cowling" + }, + { + "given": "M.", + "family": "Park" + }, + { + "given": "V. J.", + "family": "Fang" + }, + { + "given": "P.", + "family": "Wu" + }, + { + "given": "G. M.", + "family": "Leung" + }, + { + "given": "J. T.", + "family": "Wu" + } + ], + "title": "Preliminary epidemiological assessment of MERS-CoV outbreak in South Korea, May to June 2016", + "journal": "Eurosurveillance", + "year": 2015, + "pmid": 26132767, + "doi": "10.2807/1560-7917.es2015.20.25.21163" + }, + "metadata": { + "units": "days", + "sample_size": 99, + "region": "South Korea", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 5.84, + "mean_ci_limits": [5.07, 6.55], + "mean_ci": 95, + "sd": 2.98, + "sd_ci_limits": [2.31, 3.72], + "sd_ci": 95, + "quantile_values": [2.69, 12.89], + "quantile_names": ["2.5", "97.5"], + "median": 5.01, + "median_ci_limits": [4, 6], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Ke", + "family": "Men" + }, + { + "given": "Xia", + "family": "Wang" + }, + { + "given": "Li", + "family": "Yihao" + }, + { + "given": "Guangwei", + "family": "Zhang" + }, + { + "given": "Jingjing", + "family": "Hu" + }, + { + "given": "Yanyan", + "family": "Gao" + }, + { + "given": "Henry", + "family": "Han" + } + ], + "title": "Estimate the incubation period of coronavirus 2019 (COVID-19)", + "journal": "medRxiv", + "year": 2020, + "pmid": null, + "doi": "10.1101/2020.02.24.20027474" + }, + "metadata": { + "units": "days", + "sample_size": 59, + "region": "China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The estimate of the incubation period is from a non-parametric bootstrap approach that does not fit a parametric distribution." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 5.74, + "mean_ci_limits": [5.18, 6.3], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Balram", + "family": "Rai" + }, + { + "given": "Anandi", + "family": "Shukla" + }, + { + "given": "Laxmi Kant", + "family": "Dwivedi" + } + ], + "title": "Incubation period for COVID-19: a systematic review and meta-analysis", + "journal": "Zeitschrift fur Gesundheitswissenschaften", + "year": 2022, + "pmid": 33643779, + "doi": "10.1007/s10389-021-01478-1" + }, + "metadata": { + "units": "days", + "sample_size": 6241, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This estimated mean incubation period is from a meta-analysis of 15 other incubation period estimates. Only the mean is reported and a distribution cannot be specified as the meta-mean is estimated from a random-effects model." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 6.5, + "mean_ci_limits": [5.9, 7.1], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Muluneh", + "family": "Alene" + }, + { + "given": "Leltework", + "family": "Yismaw" + }, + { + "given": "Moges Agazhe", + "family": "Assemie" + }, + { + "given": "Daniel Bekele", + "family": "Ketema" + }, + { + "given": "Wodaje", + "family": "Gietaneh" + }, + { + "given": "Tilahun Yemanu", + "family": "Birhan" + } + ], + "title": "Serial interval and incubation period of COVID-19: a systematic review and meta-analysis", + "journal": "BMC Infectious Diseases", + "year": 2021, + "pmid": 33706702, + "doi": "10.1186/s12879-021-05950-x" + }, + "metadata": { + "units": "days", + "sample_size": 1453, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This estimated mean incubation period is from a meta-analysis of 14 other incubation period estimates. Only the mean is reported and a distribution cannot be specified as the meta-mean is estimated from a random-effects model." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 5.2, + "mean_ci_limits": [4.9, 5.5], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Muluneh", + "family": "Alene" + }, + { + "given": "Leltework", + "family": "Yismaw" + }, + { + "given": "Moges Agazhe", + "family": "Assemie" + }, + { + "given": "Daniel Bekele", + "family": "Ketema" + }, + { + "given": "Wodaje", + "family": "Gietaneh" + }, + { + "given": "Tilahun Yemanu", + "family": "Birhan" + } + ], + "title": "Serial interval and incubation period of COVID-19: a systematic review and meta-analysis", + "journal": "BMC Infectious Diseases", + "year": 2021, + "pmid": 33706702, + "doi": "10.1186/s12879-021-05950-x" + }, + "metadata": { + "units": "days", + "sample_size": 3924, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This estimated mean serial interval is from a meta-analysis of 23 other serial interval estimates. Only the mean is reported and a distribution cannot be specified as the meta-mean is estimated from a random-effects model." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 4.7, + "mean_ci_limits": [3.7, 6.0], + "mean_ci": 95, + "sd": 2.9, + "sd_ci_limits": [1.9, 4.9], + "sd_ci": 95, + "median": 4.0, + "median_ci_limits": [3.1, 4.9], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Hiroshi", + "family": "Nishiura" + }, + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + } + ], + "title": "Serial interval of novel coronavirus (COVID-19) infections", + "journal": "International Journal of Infectious Diseases", + "year": 2020, + "pmid": 32145466, + "doi": "10.1016/j.ijid.2020.02.060" + }, + "metadata": { + "units": "days", + "sample_size": 28, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": true, + "phase_bias_adjusted": false + }, + "notes": "These estimates are from fitting to the entire dataset of contact pairs, including pairs that are uncertain." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { } + }, + "summary_statistics": { + "mean": 4.8, + "mean_ci_limits": [3.8, 6.1], + "mean_ci": 95, + "sd": 2.3, + "sd_ci_limits": [1.6, 3.5], + "sd_ci": 95, + "median": 4.6, + "median_ci_limits": [3.5, 5.9], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Hiroshi", + "family": "Nishiura" + }, + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + } + ], + "title": "Serial interval of novel coronavirus (COVID-19) infections", + "journal": "International Journal of Infectious Diseases", + "year": 2020, + "pmid": 32145466, + "doi": "10.1016/j.ijid.2020.02.060" + }, + "metadata": { + "units": "days", + "sample_size": 18, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": true, + "phase_bias_adjusted": false + }, + "notes": "These estimates are from fitting to a subset of the dataset of contact pairs, only including pairs that are the most certain." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [1, 1.1, 13.7, 15, 17.8], + "quantile_names": ["2.5", "5", "95", "97.5", "99"], + "median": 5.4, + "median_ci_limits": [4.8, 6.0], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Lin", + "family": "Yang" + }, + { + "given": "Jingyi", + "family": "Dai" + }, + { + "given": "Jun", + "family": "Zhao" + }, + { + "given": "Yunfu", + "family": "Wang" + }, + { + "given": "Pingji", + "family": "Deng" + }, + { + "given": "Jing", + "family": "Wang" + } + ], + "title": "Estimation of incubation period and serial interval of COVID-19: analysis of 178 cases and 131 transmission chains in Hubei province, China", + "journal": "Epidemiology and Infection", + "year": 2020, + "pmid": 32594928, + "doi": "10.1017/S0950268820001338" + }, + "metadata": { + "units": "days", + "sample_size": 178, + "region": "Hubei province, China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "norm", + "parameters": { + "mean": 4.6, + "mean_ci_limits": [3.7, 5.5], + "mean_ci": 95, + "sd": 4.4, + "sd_ci_limits": [3.8, 5.0], + "sd_ci": 95 + } + }, + "summary_statistics": { + "quantile_values": [11.8, 14.8], + "quantile_names": ["95", "99"], + "median": 4.6 + }, + "citation": { + "author": [ + { + "given": "Lin", + "family": "Yang" + }, + { + "given": "Jingyi", + "family": "Dai" + }, + { + "given": "Jun", + "family": "Zhao" + }, + { + "given": "Yunfu", + "family": "Wang" + }, + { + "given": "Pingji", + "family": "Deng" + }, + { + "given": "Jing", + "family": "Wang" + } + ], + "title": "Estimation of incubation period and serial interval of COVID-19: analysis of 178 cases and 131 transmission chains in Hubei province, China", + "journal": "Epidemiology and Infection", + "year": 2020, + "pmid": 32594928, + "doi": "10.1017/S0950268820001338" + }, + "metadata": { + "units": "days", + "sample_size": 131, + "region": "Hubei province, China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 6.38, + "mean_ci_limits": [5.79, 6.97], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Christelle", + "family": "Elias" + }, + { + "given": "Abel", + "family": "Sekri" + }, + { + "given": "Pierre", + "family": "Leblanc" + }, + { + "given": "Michel", + "family": "Cucherat" + }, + { + "given": "Philippe", + "family": "Vanhems" + } + ], + "title": "The incubation period of COVID-19: A meta-analysis", + "journal": "International Journal of Infectious Diseases", + "year": 2021, + "pmid": 33548553, + "doi": "10.1016/j.ijid.2021.01.069" + }, + "metadata": { + "units": "days", + "sample_size": 28675, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This estimated mean incubation period is from a meta-analysis of 99 other incubation period estimates. Only the mean is reported and a distribution cannot be specified as the meta-mean is estimated from a random-effects model." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { } + }, + "summary_statistics": { + "mean": 6.4, + "mean_ci_limits": [4.89, 8.5], + "mean_ci": 95, + "sd": 3.05, + "sd_ci_limits": [3.05, 5.3], + "sd_ci": 95, + "quantile_values": [1.35, 1.9, 11.9, 13.04], + "quantile_names": ["2.5", "5", "95", "97.5"], + "median": 6.1 + }, + "citation": { + "author": [ + { + "given": "Long V.", + "family": "Bui" + }, + { + "given": "Ha T.", + "family": "Nguyen" + }, + { + "given": "Hagai", + "family": "Levine" + }, + { + "given": "Ha N.", + "family": "Nguyen" + }, + { + "given": "Thu-Anh", + "family": "Nguyen" + }, + { + "given": "Thuy P.", + "family": "Nguyen" + }, + { + "given": "Truong T.", + "family": "Nguyen" + }, + { + "given": "Toan T. T.", + "family": "Do" + }, + { + "given": "Ngoc T.", + "family": "Pham" + }, + { + "given": "My Hanh", + "family": "Bui" + } + ], + "title": "Estimation of the incubation period of COVID-19 in Vietnam", + "journal": "PLoS One", + "year": 2020, + "pmid": 33362233, + "doi": "10.1371/journal.pone.0243889" + }, + "metadata": { + "units": "days", + "sample_size": 19, + "region": "Vietnam", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes" +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { + "meanlog": 1.66, + "meanlog_ci_limits": [1.55, 1.76], + "meanlog_ci": 95, + "sdlog": 0.48, + "sdlog_ci_limits": [0.42, 0.54], + "sdlog_ci": 95 + } + }, + "summary_statistics": { }, + "citation": { + "author": [ + { + "given": "Conor", + "family": "McAloon" + }, + { + "given": "Áine", + "family": "Collins" + }, + { + "given": "Kevin", + "family": "Hunt" + }, + { + "given": "Ann", + "family": "Barber" + }, + { + "given": "Andrew W.", + "family": "Byrne" + }, + { + "given": "Francis", + "family": "Butler" + }, + { + "given": "Miriam", + "family": "Casey" + }, + { + "given": "John", + "family": "Griffin" + }, + { + "given": "Elizabeth", + "family": "Lane" + }, + { + "given": "David", + "family": "McEvoy" + }, + { + "given": "Patrick", + "family": "Wall" + }, + { + "given": "Martin", + "family": "Green" + }, + { + "given": "Luke", + "family": "O'Grady" + }, + { + "given": "Simon J.", + "family": "More" + } + ], + "title": "Incubation period of COVID-19: a rapid systematic review and meta-analysis of observational research", + "journal": "BMJ Open", + "year": 2020, + "pmid": 32801208, + "doi": "10.1136/bmjopen-2020-039652" + }, + "metadata": { + "units": "days", + "sample_size": 1357, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The incubation period parameters are estimated from a meta-analysis of other studies that estimated the incubation period using a lognormal distribution. This is the full set of data (N=9)." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { + "meanlog": 1.63, + "meanlog_ci_limits": [1.51, 1.75], + "meanlog_ci": 95, + "sdlog": 0.5, + "sdlog_ci_limits": [0.46, 0.55], + "sdlog_ci": 95 + } + }, + "summary_statistics": { + "mean": 5.8, + "mean_ci_limits": [5, 6.7], + "mean_ci": 95, + "median": 5.1, + "median_ci_limits": [4.5, 5.8], + "median_ci": 95, + "quantile_values": [11.7], + "quantile_names": ["95"] + }, + "citation": { + "author": [ + { + "given": "Conor", + "family": "McAloon" + }, + { + "given": "Áine", + "family": "Collins" + }, + { + "given": "Kevin", + "family": "Hunt" + }, + { + "given": "Ann", + "family": "Barber" + }, + { + "given": "Andrew W.", + "family": "Byrne" + }, + { + "given": "Francis", + "family": "Butler" + }, + { + "given": "Miriam", + "family": "Casey" + }, + { + "given": "John", + "family": "Griffin" + }, + { + "given": "Elizabeth", + "family": "Lane" + }, + { + "given": "David", + "family": "McEvoy" + }, + { + "given": "Patrick", + "family": "Wall" + }, + { + "given": "Martin", + "family": "Green" + }, + { + "given": "Luke", + "family": "O'Grady" + }, + { + "given": "Simon J.", + "family": "More" + } + ], + "title": "Incubation period of COVID-19: a rapid systematic review and meta-analysis of observational research", + "journal": "BMJ Open", + "year": 2020, + "pmid": 32801208, + "doi": "10.1136/bmjopen-2020-039652" + }, + "metadata": { + "units": "days", + "sample_size": 1269, + "region": "Mixed", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "The incubation period parameters are estimated from a meta-analysis of other studies that estimated the incubation period using a lognormal distribution. This is the data set with Backer removed as they did not have a defined exposure window (N=8)." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 5, + "mean_ci_limits": [4.2, 6], + "mean_ci": 95, + "sd": 3, + "sd_ci_limits": [2.1, 4.5], + "sd_ci": 95, + "quantile_values": [1.7, 10.6], + "quantile_names": ["5", "95"], + "median": 4.3, + "median_ci_limits": [3.5, 5.1], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 52, + "region": "China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This dataset excludes Wuhan residents (to have a more precise exposure interval). This method does not apply right-truncation, but does compare the gamma, weibull and lognormal distributions." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 5.6, + "mean_ci_limits": [5, 6.3], + "mean_ci": 95, + "sd": 2.8, + "sd_ci_limits": [2.2, 3.6], + "sd_ci": 95, + "quantile_values": [2.3, 10.8], + "quantile_names": ["5", "95"], + "median": 5, + "median_ci_limits": [4.4, 5.6], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 158, + "region": "China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This dataset includes Wuhan residents (which have a less precise exposure interval). This method does not apply right-truncation, but does compare the gamma, weibull and lognormal distributions." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "onset to hospitalisation", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 3.3, + "mean_ci_limits": [2.7, 4], + "mean_ci": 95, + "sd": 4.2, + "sd_ci_limits": [3.3, 5.4], + "sd_ci": 95, + "quantile_values": [0, 11.6], + "quantile_names": ["5", "95"], + "median": 1.7, + "median_ci_limits": [1.2, 2.2], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 155, + "region": "China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This method does not apply right-truncation, but does compare the gamma, weibull and lognormal distributions." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "onset to hospitalisation", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 6.5, + "mean_ci_limits": [5.2, 8], + "mean_ci": 95, + "sd": 4.3, + "sd_ci_limits": [2.9, 5.6], + "sd_ci": 95, + "quantile_values": [1.9, 13.9], + "quantile_names": ["5", "95"], + "median": 5.1, + "median_ci_limits": [4.1, 6.3], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 34, + "region": "China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This method does not apply right-truncation, but does compare the gamma, weibull and lognormal distributions." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "onset to death", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 14.5, + "mean_ci_limits": [12.5, 17], + "mean_ci": 95, + "sd": 6.7, + "sd_ci_limits": [4.9, 9.4], + "sd_ci": 95, + "quantile_values": [6.5, 26.8], + "quantile_names": ["5", "95"], + "median": 13.2, + "median_ci_limits": [11.3, 15.3], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 34, + "region": "China", + "transmission_mode": "natural_natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This method does not apply right-truncation, but does compare the gamma, weibull and lognormal distributions." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "hospitalisation to death", + "probability_distribution": { + "prob_distribution": "weibull", + "parameters": { } + }, + "summary_statistics": { + "mean": 8.9, + "mean_ci_limits": [7.3, 10.4], + "mean_ci": 95, + "sd": 5.7, + "sd_ci_limits": [4.3, 7.8], + "sd_ci": 95, + "quantile_values": [1.7, 18.8], + "quantile_names": ["5", "95"], + "median": 8, + "median_ci_limits": [6.2, 9.8], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 39, + "region": "China", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "This method does not apply right-truncation, but does compare the gamma, weibull and lognormal distributions." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 5.6, + "mean_ci_limits": [4.4, 4.8], + "mean_ci": 95, + "sd": 3.9, + "sd_ci_limits": [2.4, 6.9], + "sd_ci": 95, + "quantile_values": [1.7, 12.3], + "quantile_names": ["5", "95"], + "median": 4.6, + "median_ci_limits": [3.7, 5.7], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 52, + "region": "China", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": true, + "phase_bias_adjusted": true + }, + "notes": "This is excluding Wuhan residents from the dataset as this provides a more precise exposure interval. This method applies right-truncation but only fits a lognormal distribution." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "onset to hospitalisation", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 9.7, + "mean_ci_limits": [5.4, 17], + "mean_ci": 95, + "sd": 35.2, + "sd_ci_limits": [12.9, 84.5], + "sd_ci": 95, + "quantile_values": [0.2, 35.1], + "quantile_names": ["5", "95"], + "median": 2.6, + "median_ci_limits": [1.9, 3.8], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 155, + "region": "China", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": true, + "phase_bias_adjusted": true + }, + "notes": "This dataset includes only surviving patients. This method applies right-truncation but only fits a lognormal distribution." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "onset to hospitalisation", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 6.6, + "mean_ci_limits": [5.2, 8.8], + "mean_ci": 95, + "sd": 4.9, + "sd_ci_limits": [3, 8.6], + "sd_ci": 95, + "quantile_values": [1.9, 15], + "quantile_names": ["5", "95"], + "median": 5.3, + "median_ci_limits": [4.2, 6.8], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 34, + "region": "China", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": true, + "phase_bias_adjusted": true + }, + "notes": "This dataset includes only deceased patients. This method applies right-truncation but only fits a lognormal distribution." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "onset to death", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 20.2, + "mean_ci_limits": [15.1, 29.5], + "mean_ci": 95, + "sd": 11.6, + "sd_ci_limits": [6.6, 21.8], + "sd_ci": 95, + "quantile_values": [7.4, 39.9], + "quantile_names": ["5", "95"], + "median": 17.1, + "median_ci_limits": [13.5, 24.1], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 34, + "region": "China", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": true, + "phase_bias_adjusted": true + }, + "notes": "This method applies right-truncation but only fits a lognormal distribution." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "hospitalisation to death", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 13, + "mean_ci_limits": [8.7, 20.9], + "mean_ci": 95, + "sd": 12.7, + "sd_ci_limits": [6.4, 26], + "sd_ci": 95, + "quantile_values": [2.5, 33.1], + "quantile_names": ["5", "95"], + "median": 9.1, + "median_ci_limits": [6.7, 13.7], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Natalie M.", + "family": "Linton" + }, + { + "given": "Tetsuro", + "family": "Kobayashi" + }, + { + "given": "Yichi", + "family": "Yang" + }, + { + "given": "Katsuma", + "family": "Hayashi" + }, + { + "given": "Andrei R.", + "family": "Akhmetzhanov" + }, + { + "given": "Sung-mok", + "family": "Jung" + }, + { + "given": "Baoyin", + "family": "Yuan" + }, + { + "given": "Ryo", + "family": "Kinoshita" + }, + { + "given": "Hiroshi", + "family": "Nishiura" + } + ], + "title": "Incubation Period and Other Epidemiological Characteristics of 2019 Novel Coronavirus Infections with Right Truncation: A Statistical Analysis of Publicly Available Case Data", + "journal": "Journal of Clinical Medicine", + "year": 2020, + "pmid": 32079150, + "doi": "10.3390/jcm9020538" + }, + "metadata": { + "units": "days", + "sample_size": 39, + "region": "China", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": true, + "phase_bias_adjusted": true + }, + "notes": "This method applies right-truncation but only fits a lognormal distribution." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "mean": 5.5, + "quantile_values": [2.2, 11.5], + "quantile_names": ["2.5", "97.5"], + "median": 5.1, + "median_ci_limits": [4.5, 5.8], + "median_ci": 95, + "dispersion": 1.52, + "dispersion_ci_limits": [1.32, 1.72], + "dispersion_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Stephen A.", + "family": "Lauer" + }, + { + "given": "Kyra H.", + "family": "Grantz" + }, + { + "given": "Qifang", + "family": "Bi" + }, + { + "given": "Forrest K.", + "family": "Jones" + }, + { + "given": "Qulu", + "family": "Zheng" + }, + { + "given": "Hannah R.", + "family": "Meredith" + }, + { + "given": "Andrew S.", + "family": "Azman" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + } + ], + "title": "The Incubation Period of Coronavirus Disease 2019 (COVID-19) From Publicly Reported Confirmed Cases: Estimation and Application", + "journal": "Annals of Internal Medicine", + "year": 2020, + "pmid": 32150748, + "doi": "10.7326/M20-0504" + }, + "metadata": { + "units": "days", + "sample_size": 181, + "region": "Mixed", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": true + }, + "notes": "This is the complete data set." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.6, 12.5], + "quantile_names": ["2.5", "97.5"], + "median": 5.7, + "median_ci_limits": [4.9, 6.8], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Stephen A.", + "family": "Lauer" + }, + { + "given": "Kyra H.", + "family": "Grantz" + }, + { + "given": "Qifang", + "family": "Bi" + }, + { + "given": "Forrest K.", + "family": "Jones" + }, + { + "given": "Qulu", + "family": "Zheng" + }, + { + "given": "Hannah R.", + "family": "Meredith" + }, + { + "given": "Andrew S.", + "family": "Azman" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + } + ], + "title": "The Incubation Period of Coronavirus Disease 2019 (COVID-19) From Publicly Reported Confirmed Cases: Estimation and Application", + "journal": "Annals of Internal Medicine", + "year": 2020, + "pmid": 32150748, + "doi": "10.7326/M20-0504" + }, + "metadata": { + "units": "days", + "sample_size": 99, + "region": "Mixed", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": true + }, + "notes": "This is a subset of the data, including only those cases with a known onset of fever to be sure that the onset of symptoms is not from another pathogen." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.1, 14.7], + "quantile_names": ["2.5", "97.5"], + "median": 5.5, + "median_ci_limits": [4.4, 7], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Stephen A.", + "family": "Lauer" + }, + { + "given": "Kyra H.", + "family": "Grantz" + }, + { + "given": "Qifang", + "family": "Bi" + }, + { + "given": "Forrest K.", + "family": "Jones" + }, + { + "given": "Qulu", + "family": "Zheng" + }, + { + "given": "Hannah R.", + "family": "Meredith" + }, + { + "given": "Andrew S.", + "family": "Azman" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + } + ], + "title": "The Incubation Period of Coronavirus Disease 2019 (COVID-19) From Publicly Reported Confirmed Cases: Estimation and Application", + "journal": "Annals of Internal Medicine", + "year": 2020, + "pmid": 32150748, + "doi": "10.7326/M20-0504" + }, + "metadata": { + "units": "days", + "sample_size": 108, + "region": "Mixed", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": true + }, + "notes": "This is a subset of the data, including only cases that are detected outside of mainland China." +}, +{ + "disease": "COVID-19", + "pathogen": "SARS-CoV-2", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": "lnorm", + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [2.5, 9.2], + "quantile_names": ["2.5", "97.5"], + "median": 4.8, + "median_ci_limits": [4.2, 5.6], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Stephen A.", + "family": "Lauer" + }, + { + "given": "Kyra H.", + "family": "Grantz" + }, + { + "given": "Qifang", + "family": "Bi" + }, + { + "given": "Forrest K.", + "family": "Jones" + }, + { + "given": "Qulu", + "family": "Zheng" + }, + { + "given": "Hannah R.", + "family": "Meredith" + }, + { + "given": "Andrew S.", + "family": "Azman" + }, + { + "given": "Nicholas G.", + "family": "Reich" + }, + { + "given": "Justin", + "family": "Lessler" + } + ], + "title": "The Incubation Period of Coronavirus Disease 2019 (COVID-19) From Publicly Reported Confirmed Cases: Estimation and Application", + "journal": "Annals of Internal Medicine", + "year": 2020, + "pmid": 32150748, + "doi": "10.7326/M20-0504" + }, + "metadata": { + "units": "days", + "sample_size": 73, + "region": "China", + "transmission_mode": "natural_human_to_human", + "extrinsic": false, + "inference_method": "mle" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": true + }, + "notes": "This is a subset of the data, including only cases that are detected inside mainland China." +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 5.6, + "mean_ci_limits": [1.7, 10.4], + "mean_ci": 95, + "sd": 1.5, + "sd_ci_limits": [0.4, 2.4], + "sd_ci": 95, + "quantile_values": [8.3], + "quantile_names": ["95"], + "median": 5.5, + "median_ci_limits": [1.4, 10.4], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Zihao", + "family": "Guo" + }, + { + "given": "Shi", + "family": "Zhao" + }, + { + "given": "Shengzhi", + "family": "Sun" + }, + { + "given": "Daihai", + "family": "He" + }, + { + "given": "Ka Chun", + "family": "Chong" + }, + { + "given": "Eng Kiong", + "family": "Yeoh" + } + ], + "title": "Estimation of the serial interval of monkeypox during the early outbreak in 2022", + "journal": "Journal of Medical Virology", + "year": 2022, + "pmid": 36271480, + "doi": "10.1002/jmv.28248" + }, + "metadata": { + "units": "days", + "sample_size": 42, + "region": "Mixed", + "transmission_mode": "mixed", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": true, + "phase_bias_adjusted": true + }, + "notes": "Data from Kraemer et al 10.1016/S1473-3099(22)00359-0" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus Clade I", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [9.28, 10.05], + "quantile_names": ["25", "75"], + "median": 9.67 + }, + "citation": { + "author": [ + { + "given": "Shuqi", + "family": "Wang" + }, + { + "given": "Fengdi", + "family": "Zhang" + }, + { + "given": "Zhilu", + "family": "Yuan" + }, + { + "given": "Mingda", + "family": "Xu" + }, + { + "given": "Zhen", + "family": "Wang" + }, + { + "given": "Chao", + "family": "Gao" + }, + { + "given": "Renzhong", + "family": "Guo" + }, + { + "given": "Zhanwei", + "family": "Du" + } + ], + "title": "Serial intervals and incubation periods of the monkeypox virus clades", + "journal": "Journal of Travel Medicine", + "year": 2022, + "pmid": 36130210, + "doi": "10.1093/jtm/taac105" + }, + "metadata": { + "units": "days", + "sample_size": 16, + "region": "Congo", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Systematic review" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "serial interval", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [8.9, 10.67], + "quantile_names": ["25", "75"], + "median": 9.78 + }, + "citation": { + "author": [ + { + "given": "Shuqi", + "family": "Wang" + }, + { + "given": "Fengdi", + "family": "Zhang" + }, + { + "given": "Zhilu", + "family": "Yuan" + }, + { + "given": "Mingda", + "family": "Xu" + }, + { + "given": "Zhen", + "family": "Wang" + }, + { + "given": "Chao", + "family": "Gao" + }, + { + "given": "Renzhong", + "family": "Guo" + }, + { + "given": "Zhanwei", + "family": "Du" + } + ], + "title": "Serial intervals and incubation periods of the monkeypox virus clades", + "journal": "Journal of Travel Medicine", + "year": 2022, + "pmid": 36130210, + "doi": "10.1093/jtm/taac105" + }, + "metadata": { + "units": "days", + "sample_size": 34, + "region": "Mixed", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Systematic review" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus Clade I", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [8, 12.25], + "quantile_names": ["25", "75"], + "median": 9.5 + }, + "citation": { + "author": [ + { + "given": "Shuqi", + "family": "Wang" + }, + { + "given": "Fengdi", + "family": "Zhang" + }, + { + "given": "Zhilu", + "family": "Yuan" + }, + { + "given": "Mingda", + "family": "Xu" + }, + { + "given": "Zhen", + "family": "Wang" + }, + { + "given": "Chao", + "family": "Gao" + }, + { + "given": "Renzhong", + "family": "Guo" + }, + { + "given": "Zhanwei", + "family": "Du" + } + ], + "title": "Serial intervals and incubation periods of the monkeypox virus clades", + "journal": "Journal of Travel Medicine", + "year": 2022, + "pmid": 36130210, + "doi": "10.1093/jtm/taac105" + }, + "metadata": { + "units": "days", + "sample_size": 16, + "region": "Congo", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Systematic review" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus Clade IIa", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "quantile_values": [11.39, 23.91], + "quantile_names": ["25", "75"], + "median": 16.76 + }, + "citation": { + "author": [ + { + "given": "Shuqi", + "family": "Wang" + }, + { + "given": "Fengdi", + "family": "Zhang" + }, + { + "given": "Zhilu", + "family": "Yuan" + }, + { + "given": "Mingda", + "family": "Xu" + }, + { + "given": "Zhen", + "family": "Wang" + }, + { + "given": "Chao", + "family": "Gao" + }, + { + "given": "Renzhong", + "family": "Guo" + }, + { + "given": "Zhanwei", + "family": "Du" + } + ], + "title": "Serial intervals and incubation periods of the monkeypox virus clades", + "journal": "Journal of Travel Medicine", + "year": 2022, + "pmid": 36130210, + "doi": "10.1093/jtm/taac105" + }, + "metadata": { + "units": "days", + "sample_size": 27, + "region": "USA", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Systematic review" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus Clade IIb", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "median": 8.26, + "median_ci_limits": [7.55, 8.97], + "median_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Shuqi", + "family": "Wang" + }, + { + "given": "Fengdi", + "family": "Zhang" + }, + { + "given": "Zhilu", + "family": "Yuan" + }, + { + "given": "Mingda", + "family": "Xu" + }, + { + "given": "Zhen", + "family": "Wang" + }, + { + "given": "Chao", + "family": "Gao" + }, + { + "given": "Renzhong", + "family": "Guo" + }, + { + "given": "Zhanwei", + "family": "Du" + } + ], + "title": "Serial intervals and incubation periods of the monkeypox virus clades", + "journal": "Journal of Travel Medicine", + "year": 2022, + "pmid": 36130210, + "doi": "10.1093/jtm/taac105" + }, + "metadata": { + "units": "days", + "sample_size": 114, + "region": "mixed", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Systematic review" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 8.13, + "mean_ci_limits": [4.9, 19.5], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Fengying", + "family": "Wei" + }, + { + "given": "Zhihang", + "family": "Peng" + }, + { + "given": "Zhen", + "family": "Jin" + }, + { + "given": "Jinjie", + "family": "Wang" + }, + { + "given": "Ximing", + "family": "Xu" + }, + { + "given": "Xinyan", + "family": "Zhang" + }, + { + "given": "Jun", + "family": "Xu" + }, + { + "given": "Zixiong", + "family": "Ren" + }, + { + "given": "Yao", + "family": "Bai" + }, + { + "given": "Xiaoli", + "family": "Wang" + }, + { + "given": "Bulai", + "family": "Lu" + }, + { + "given": "Zhaojun", + "family": "Wang" + }, + { + "given": "Jianguo", + "family": "Xu" + }, + { + "given": "Senzhong", + "family": "Huang" + } + ], + "title": "Study and prediction of the 2022 global monkeypox epidemic", + "journal": "Journal of Biosafety and Biosecurity", + "year": 2022, + "pmid": 36573222, + "doi": "10.1016/j.jobb.2022.12.001" + }, + "metadata": { + "units": "days", + "sample_size": null, + "region": "USA", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "SEIR model from 10.1016/j.mbs.2008.06.005 where the IP is assumed to follow a gamma distribution" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 8.08, + "mean_ci_limits": [4.8, 21], + "mean_ci": 95 + }, + "citation": { + "author": [ + { + "given": "Fengying", + "family": "Wei" + }, + { + "given": "Zhihang", + "family": "Peng" + }, + { + "given": "Zhen", + "family": "Jin" + }, + { + "given": "Jinjie", + "family": "Wang" + }, + { + "given": "Ximing", + "family": "Xu" + }, + { + "given": "Xinyan", + "family": "Zhang" + }, + { + "given": "Jun", + "family": "Xu" + }, + { + "given": "Zixiong", + "family": "Ren" + }, + { + "given": "Yao", + "family": "Bai" + }, + { + "given": "Xiaoli", + "family": "Wang" + }, + { + "given": "Bulai", + "family": "Lu" + }, + { + "given": "Zhaojun", + "family": "Wang" + }, + { + "given": "Jianguo", + "family": "Xu" + }, + { + "given": "Senzhong", + "family": "Huang" + } + ], + "title": "Study and prediction of the 2022 global monkeypox epidemic", + "journal": "Journal of Biosafety and Biosecurity", + "year": 2022, + "pmid": 36573222, + "doi": "10.1016/j.jobb.2022.12.001" + }, + "metadata": { + "units": "days", + "sample_size": null, + "region": "Europe", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "SEIR model from 10.1016/j.mbs.2008.06.005 where the IP is assumed to follow a gamma distribution" +}, +{ + "disease": "Mpox", + "pathogen": "Mpox Virus", + "epi_name": "incubation period", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 8.23, + "mean_ci_limits": [4.9, 21.4], + "mean_ci": 95, + "quantile_values": [20], + "quantile_names": ["95"] + }, + "citation": { + "author": [ + { + "given": "Fengying", + "family": "Wei" + }, + { + "given": "Zhihang", + "family": "Peng" + }, + { + "given": "Zhen", + "family": "Jin" + }, + { + "given": "Jinjie", + "family": "Wang" + }, + { + "given": "Ximing", + "family": "Xu" + }, + { + "given": "Xinyan", + "family": "Zhang" + }, + { + "given": "Jun", + "family": "Xu" + }, + { + "given": "Zixiong", + "family": "Ren" + }, + { + "given": "Yao", + "family": "Bai" + }, + { + "given": "Xiaoli", + "family": "Wang" + }, + { + "given": "Bulai", + "family": "Lu" + }, + { + "given": "Zhaojun", + "family": "Wang" + }, + { + "given": "Jianguo", + "family": "Xu" + }, + { + "given": "Senzhong", + "family": "Huang" + } + ], + "title": "Study and prediction of the 2022 global monkeypox epidemic", + "journal": "Journal of Biosafety and Biosecurity", + "year": 2022, + "pmid": 36573222, + "doi": "10.1016/j.jobb.2022.12.001" + }, + "metadata": { + "units": "days", + "sample_size": null, + "region": "Global", + "transmission_mode": "natural_unknown", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "SEIR model from 10.1016/j.mbs.2008.06.005 where the IP is assumed to follow a gamma distribution" +}, +{ + "disease": "Chikungunya", + "pathogen": "Chikungunya Virus", + "epi_name": "generation time", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 14, + "sd": 6.2 + }, + "citation": { + "author": [ + { + "given": "Henrik", + "family": "Salje" + }, + { + "given": "Simon", + "family": "Cauchemez" + }, + { + "given": "Maria Theresa", + "family": "Alera" + }, + { + "given": "Isabel", + "family": "Rodriguez-Barraquer" + }, + { + "given": "Butsaya", + "family": "Thaisomboonsuk" + }, + { + "given": "Anon", + "family": "Srikiatkhachorn" + }, + { + "given": "Catherine B.", + "family": "Lago" + }, + { + "given": "Daisy", + "family": "Villa" + }, + { + "given": "Chonticha", + "family": "Klungthong" + }, + { + "given": "Ilya A.", + "family": "Tac-An" + }, + { + "given": "Stefan", + "family": "Fernandez" + }, + { + "given": "John Mark", + "family": "Velasco" + }, + { + "given": "Vito G.", + "family": "Roque Jr" + }, + { + "given": "Ananda", + "family": "Nisalak" + }, + { + "given": "Louis R.", + "family": "Macareo" + }, + { + "given": "Jens W.", + "family": "Levy" + }, + { + "given": "Derek", + "family": "Cummings" + }, + { + "given": "In-Kyu", + "family": "Yoon" + } + ], + "title": "Reconstruction of 60 Years of Chikungunya Epidemiology in the Philippines Demonstrates Episodic and Focal Transmission", + "journal": "The Journal of Infectious Diseases", + "year": 2015, + "pmid": 26410592, + "doi": "10.1093/infdis/jiv470" + }, + "metadata": { + "units": "days", + "sample_size": null, + "region": "Philippines", + "transmission_mode": "vector_borne", + "vector": "mosquito", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Database entry per communication K. Charniga, Z. Cucunubá & Laura Gomez Bermeo." +}, +{ + "disease": "Chikungunya", + "pathogen": "Chikungunya Virus", + "epi_name": "generation time", + "probability_distribution": { + "prob_distribution": "gamma", + "parameters": { } + }, + "summary_statistics": { + "mean": 12.4, + "mean_ci_limits": [11.7, 13.3], + "mean_ci": 95, + "quantile_values": [5.6, 22.1], + "quantile_names": ["2.5", "97.5"] + }, + "citation": { + "author": [ + { + "given": "Giorgio", + "family": "Guzzetta" + }, + { + "given": "Francesco", + "family": "Vairo" + }, + { + "given": "Alessia", + "family": "Mammone" + }, + { + "given": "Simone", + "family": "Lanini" + }, + { + "given": "Piero", + "family": "Poletti" + }, + { + "given": "Mattia", + "family": "Manica" + }, + { + "given": "Roberto", + "family": "Rosa" + }, + { + "given": "Beniamino", + "family": "Caputo" + }, + { + "given": "Angelo", + "family": "Solimini" + }, + { + "given": "Alessandra", + "family": "della Torre" + }, + { + "given": "Paola", + "family": "Scognamiglio" + }, + { + "given": "Alimuddin", + "family": "Zumla" + }, + { + "given": "Giuseppe", + "family": "Ippolito" + }, + { + "given": "Stefano", + "family": "Merler" + } + ], + "title": "Spatial modes for transmission of chikungunya virus during a large chikungunya outbreak in Italy: a modeling analysis", + "journal": "BMC Medicine", + "year": 2020, + "pmid": 32762750, + "doi": "10.1186/s12916-020-01674-y" + }, + "metadata": { + "units": "days", + "sample_size": 412, + "region": "Italy", + "transmission_mode": "vector_borne", + "vector": "Aedes albopictus", + "extrinsic": false, + "inference_method": "bayesian" + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": false, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "No additional notes." +}, +{ + "disease": "Chikungunya", + "pathogen": "Chikungunya Virus", + "epi_name": "case fatality risk", + "probability_distribution": { + "prob_distribution": null, + "parameters": { } + }, + "summary_statistics": { + "mean": 1.3 + }, + "citation": { + "author": [ + { + "given": "William M", + "family": "de Souza" + }, + { + "given": "Shirlene T. S.", + "family": "de Lima" + }, + { + "given": "Leda M Simões", + "family": "Mello" + }, + { + "given": "Darlan S.", + "family": "Candido" + }, + { + "given": "Lewis", + "family": "Buss" + }, + { + "given": "Charles", + "family": "Whittaker" + }, + { + "given": "Ingra M", + "family": "Claro" + }, + { + "given": "Nilani", + "family": "Chandradeva" + }, + { + "given": "Fabiana", + "family": "Granja" + }, + { + "given": "Ronaldo", + "family": "de Jesus" + }, + { + "given": "Poliana S.", + "family": "Lemos" + }, + { + "given": "Daniel A.", + "family": "Toledo-Teixeira" + }, + { + "given": "Priscilla P.", + "family": "Barbosa" + }, + { + "given": "Antonio Carlos L.", + "family": "Firmino" + }, + { + "given": "Mariene R.", + "family": "Amorim" + }, + { + "given": "Larissa M. F.", + "family": "Duarte" + }, + { + "given": "Ivan B.", + "family": "Pessoa Jr" + }, + { + "given": "Julia", + "family": "Forato" + }, + { + "given": "Irihane L.", + "family": "Vasconcelos" + }, + { + "given": "Ana Carolina B. M.", + "family": "Maximo" + }, + { + "given": "Emerson L. L.", + "family": "Araújo" + }, + { + "given": "Liana Perdigão", + "family": "Mello" + }, + { + "given": "Ester C.", + "family": "Sabino" + }, + { + "given": "José Luiz", + "family": "Proença-Módena" + }, + { + "given": "Nuno R.", + "family": "Faria" + }, + { + "given": "Scott C.", + "family": "Weaver" + } + ], + "title": "Spatiotemporal dynamics and recurrence of chikungunya virus in Brazil: an epidemiological study", + "journal": "The Lancet Microbe", + "year": 2023, + "pmid": 37031687, + "doi": "10.1016/S2666-5247(23)00033-2" + }, + "metadata": { + "units": "deaths per 1000 cases", + "sample_size": 253545, + "region": "Brazil", + "transmission_mode": "vector_borne", + "vector": "Aedes aegypti and Aedes albopictus", + "extrinsic": false, + "inference_method": null + }, + "method_assessment": { + "truncation": null, + "discretised": false, + "censored": true, + "right_truncated": false, + "phase_bias_adjusted": false + }, + "notes": "Case fatality risk is given in deaths per 1,000 cases. It was calculated as a cumulative case fatality ratio. CFR is a population-wide estimate. Odds of chikungunya-related death were not significantly different between males and females. Odds of chikungunya-related death were significantly higher for 55-74 years old, and >75 years old compared to <18." +} +] diff --git a/man/aggregate.multi_epiparameter.Rd b/man/aggregate.multi_epiparameter.Rd new file mode 100644 index 000000000..395b311a0 --- /dev/null +++ b/man/aggregate.multi_epiparameter.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/aggregate.R +\name{aggregate.multi_epiparameter} +\alias{aggregate.multi_epiparameter} +\title{Aggregate multiple \verb{<epiparameter>} objects into a single \verb{<epiparameter>} +object.} +\usage{ +\method{aggregate}{multi_epiparameter}(x, weighting = c("equal", "sample_size", "custom"), ..., weights) +} +\arguments{ +\item{x}{A \verb{<multi_epiparameter>} object.} + +\item{weighting}{A \code{character} string with the type of weighting to use to +create the mixture distribution. Options are: \code{"equal"} for equal weighting +across distributions, \code{"sample_size"} for using the sample size in each +\verb{<epiparameter>} object to weight the distribution (the sample sizes are +normalised), or \code{"custom"} allows a vector of weights to be passed to the +\code{weights} argument for a custom weighting.} + +\item{...}{\link{dots} Not used, will warn if extra arguments are passed to +function.} + +\item{weights}{A \code{numeric} vector of equal length the number of +\verb{<epiparameter>} objects passed to \code{x}. \code{weights} is only required if +\code{weighting = "custom"}.} +} +\value{ +An \verb{<epiparameter>} object +} +\description{ +Combine a list of \verb{<epiparameter>} objects into a single \verb{<epiparameter>} +with a mixture distribution [see \code{\link[distributional:dist_mixture]{distributional::dist_mixture()}}]. + +The aggregated \verb{<epiparameter>} returned from \code{aggregate()} can then be used +with the \code{density()}, \code{cdf()}, \code{quantile()} and \code{generate()} methods for the +combined distributions. +} +\details{ +The \code{aggregate()} method requires that all \verb{<epiparameter>} objects are +parameterised with \verb{<distribution>} objects (from the \pkg{distributional} +package). This means that unparameterised (see \code{\link[=is_parameterised]{is_parameterised()}}) or +discretised (see \code{\link[=discretise]{discretise()}}) distributions cannot be aggregated and the +function will error. +} +\examples{ +ebola_si <- epiparameter_db(epi_name = "serial interval", disease = "ebola") +aggregate(ebola_si) +} diff --git a/man/as.data.frame.epiparameter.Rd b/man/as.data.frame.epiparameter.Rd new file mode 100644 index 000000000..4ce021bfb --- /dev/null +++ b/man/as.data.frame.epiparameter.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{as.data.frame.epiparameter} +\alias{as.data.frame.epiparameter} +\title{\code{\link[=as.data.frame]{as.data.frame()}} method for \verb{<epiparameter>} class} +\usage{ +\method{as.data.frame}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \verb{<epiparameter>} object.} + +\item{...}{\link{dots} Not used, extra arguments supplied will cause a warning.} +} +\value{ +A \verb{<data.frame>} with a single row. +} +\description{ +\code{\link[=as.data.frame]{as.data.frame()}} method for \verb{<epiparameter>} class +} +\details{ +The \verb{<data.frame>} returned will contain some atomic columns (i.e. one +object per row), and other columns that are lists (i.e. multiple objects per +row). The list columns can contain lists or S3 objects (e.g. \verb{<bibentry>} +object in the \code{citation} column). +} diff --git a/man/as.data.frame.multi_epiparameter.Rd b/man/as.data.frame.multi_epiparameter.Rd new file mode 100644 index 000000000..b9e2ec3b6 --- /dev/null +++ b/man/as.data.frame.multi_epiparameter.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{as.data.frame.multi_epiparameter} +\alias{as.data.frame.multi_epiparameter} +\title{\code{\link[=as.data.frame]{as.data.frame()}} method for \verb{<multi_epiparameter>} class} +\usage{ +\method{as.data.frame}{multi_epiparameter}(x, ...) +} +\arguments{ +\item{x}{A \verb{<multi_epiparameter>} object.} + +\item{...}{\link{dots} Not used, extra arguments supplied will cause a warning.} +} +\value{ +A \verb{<data.frame>} with as many rows as length of input list. +} +\description{ +\code{\link[=as.data.frame]{as.data.frame()}} method for \verb{<multi_epiparameter>} class +} +\details{ +The \verb{<data.frame>} returned will contain some atomic columns (i.e. one +object per row), and other columns that are lists (i.e. multiple objects per +row). The list columns can contain lists or S3 objects (e.g. \verb{<bibentry>} +object in the \code{citation} column). +} diff --git a/man/as.function.epiparameter.Rd b/man/as.function.epiparameter.Rd new file mode 100644 index 000000000..430d07aef --- /dev/null +++ b/man/as.function.epiparameter.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{as.function.epiparameter} +\alias{as.function.epiparameter} +\title{\code{\link[=as.function]{as.function()}} method for \verb{<epiparameter>} class} +\usage{ +\method{as.function}{epiparameter}(x, func_type = c("density", "cdf", "generate", "quantile"), ...) +} +\arguments{ +\item{x}{An \verb{<epiparameter>} object.} + +\item{func_type}{A single \code{character} string specifying which distribution to +convert \verb{<epiparameter>} object into. Default is \code{"density"}. Other options +are \code{"cdf"}, \code{"generate"}, or \code{"quantile"}.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\value{ +A \link{function} object. +} +\description{ +Converts an \verb{<epiparameter>} object to a distribution function +(see \link{epiparameter_distribution_functions}), either probability density/mass +function, (\code{density}), cumulative distribution function (\code{cdf}), random +number generator (\code{generate}), or quantile (\code{quantile}). +} +\details{ +The function returned takes a single required argument \code{x}. +} diff --git a/man/as_epiparameter.Rd b/man/as_epiparameter.Rd new file mode 100644 index 000000000..0194f5b00 --- /dev/null +++ b/man/as_epiparameter.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{as_epiparameter} +\alias{as_epiparameter} +\title{Convert to an \verb{<epiparameter>} object} +\usage{ +as_epiparameter(x, ...) +} +\arguments{ +\item{x}{an object used to select a method.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\value{ +An \verb{<epiparameter>} object or list of \verb{<epiparameter>} objects. +} +\description{ +Convert from an \R object to an \verb{<epiparameter>} object. If conversion is not +possible the function will error. +} +\details{ +To create the full citation the information from the article table from the +\pkg{epireview} package of the corresponding entry will need to be passed +to function via the \code{...} argument. The argument should be called \code{article}, +as it will be matched by name by \code{$}. + +To specify a probability distribution pass a \code{character} string to the +function via the \code{...} argument. The argument should be called +\code{prob_distribution}. For example, to specify a gamma distribution: +\code{as_epiparameter(x, prob_distribution = "gamma")}. + +\emph{\strong{Warning}}: distributions specified via the \code{prob_dist} argument will +overwrite the probability distribution specified in the \code{x} argument. For +example, if the probability distribution is given in an \pkg{epireview} +entry and the \code{prob_dist} argument is specified then the function may error +or return an unparameterised \verb{<epiparameter>} if the parameterisation becomes +incompatible. + +Valid probability distributions are: \code{"gamma"}, \code{"lnorm"}, \code{"weibull"}, +\code{"nbinom"}, \code{"geom"}, \code{"pois"}, \code{"norm"}, \code{"exp"}. +} diff --git a/man/as_epiparameter.data.frame.Rd b/man/as_epiparameter.data.frame.Rd new file mode 100644 index 000000000..b268b7caa --- /dev/null +++ b/man/as_epiparameter.data.frame.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{as_epiparameter.data.frame} +\alias{as_epiparameter.data.frame} +\title{Convert \verb{<data.frame>} to an \verb{<epiparameter>} object} +\usage{ +\method{as_epiparameter}{data.frame}(x, ...) +} +\arguments{ +\item{x}{A \verb{<data.frame>}.} + +\item{...}{\link{dots} Not used, extra arguments supplied will cause a warning.} +} +\value{ +An \verb{<epiparameter>} object or list of \verb{<epiparameter>} objects. +} +\description{ +Convert the tabular information in \verb{<data.frame>} to an \verb{<epiparameter>}. +If the information in the \verb{<data.frame>} cannot be converted into an +\verb{<epiparameter>} the function will error. +} diff --git a/man/assert_epiparameter.Rd b/man/assert_epiparameter.Rd new file mode 100644 index 000000000..276e1b8e4 --- /dev/null +++ b/man/assert_epiparameter.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{assert_epiparameter} +\alias{assert_epiparameter} +\title{Assert an object is a valid \verb{<epiparameter>} object} +\usage{ +assert_epiparameter(x) +} +\arguments{ +\item{x}{An \R object.} +} +\value{ +Invisibly returns an \verb{<epiparameter>}. Called for side-effects +(errors when invalid \verb{<epiparameter>} object is provided). +} +\description{ +Assert an object is a valid \verb{<epiparameter>} object +} diff --git a/man/c.epiparameter.Rd b/man/c.epiparameter.Rd new file mode 100644 index 000000000..140844cc2 --- /dev/null +++ b/man/c.epiparameter.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{c.epiparameter} +\alias{c.epiparameter} +\title{\code{\link[=c]{c()}} method for \verb{<epiparameter>} class} +\usage{ +\method{c}{epiparameter}(...) +} +\arguments{ +\item{...}{\link{dots} Objects to be concatenated.} +} +\value{ +An \verb{<epiparameter>} or list of \verb{<epiparameter>} objects. +} +\description{ +\code{\link[=c]{c()}} method for \verb{<epiparameter>} class +} +\examples{ +db <- epiparameter_db() + +# combine two <epiparameter> objects into a list +c(db[[1]], db[[2]]) + +# combine a list of <epiparameter> objects and a single <epiparameter> object +c(db, db[[1]]) +} diff --git a/man/calc_disc_dist_quantile.Rd b/man/calc_disc_dist_quantile.Rd new file mode 100644 index 000000000..729e49b43 --- /dev/null +++ b/man/calc_disc_dist_quantile.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{calc_disc_dist_quantile} +\alias{calc_disc_dist_quantile} +\title{Calculate the quantiles of a probability distribution based on the vector +of probabilities and time data (e.g. time since infection)} +\usage{ +calc_disc_dist_quantile(prob, days, quantile) +} +\arguments{ +\item{prob}{A \code{numeric} vector of probabilities.} + +\item{days}{A \code{numeric} vector of days.} + +\item{quantile}{A single \code{numeric} or vector of \code{numerics} specifying which +quantiles to extract from the distribution.} +} +\value{ +A named vector of quantiles. +} +\description{ +This function can be used in cases where the data on a fitted +distribution is not openly available and the summary statistics of the +distribution are not reported so the data are scraped from the plot and +the quantiles are needed in order use the \code{\link[=extract_param]{extract_param()}} function. +} +\examples{ +prob <- dgamma(seq(0, 10, length.out = 21), shape = 2, scale = 2) +days <- seq(0, 10, 0.5) +quantiles <- c(0.025, 0.975) +calc_disc_dist_quantile(prob = prob, days = days, quantile = quantiles) +} diff --git a/man/convert_params_to_summary_stats.Rd b/man/convert_params_to_summary_stats.Rd new file mode 100644 index 000000000..a8a35ad8e --- /dev/null +++ b/man/convert_params_to_summary_stats.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{convert_params_to_summary_stats} +\alias{convert_params_to_summary_stats} +\alias{convert_params_to_summary_stats.character} +\alias{convert_params_to_summary_stats.epiparameter} +\title{Convert the parameter(s) of a distribution to summary statistics} +\usage{ +convert_params_to_summary_stats(x, ...) + +\method{convert_params_to_summary_stats}{character}( + x = c("lnorm", "gamma", "weibull", "nbinom", "geom"), + ... +) + +\method{convert_params_to_summary_stats}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \R object.} + +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named parameter(s) +used to convert to summary statistics. An example is the \code{meanlog} and +\code{sdlog} parameters of the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of eight elements including: mean, median, mode, +variance (\code{var}), standard deviation (\code{sd}), coefficient of variation (\code{cv}), +skewness, and excess kurtosis (\code{ex_kurtosis}). +} +\description{ +Convert the parameters for a range of distributions to a +number of summary statistics. All summary statistics are calculated +analytically given the parameters. +} +\details{ +The distribution names and parameter names follow the style of +distributions in \R, for example the lognormal distribution is \code{lnorm}, +and its parameters are \code{meanlog} and \code{sdlog}. +} +\examples{ +# example using characters +convert_params_to_summary_stats("lnorm", meanlog = 1, sdlog = 2) +convert_params_to_summary_stats("gamma", shape = 1, scale = 1) +convert_params_to_summary_stats("nbinom", prob = 0.5, dispersion = 2) + +# example using <epiparameter> +epiparameter <- epiparameter_db(single_epiparameter = TRUE) +convert_params_to_summary_stats(epiparameter) + +# example using <epiparameter> and specifying parameters +epiparameter <- epiparameter_db( + disease = "Influenza", + author = "Virlogeux", + subset = prob_dist == "weibull" +) +convert_params_to_summary_stats(epiparameter[[2]], shape = 1, scale = 1) +} +\seealso{ +\code{\link[=convert_summary_stats_to_params]{convert_summary_stats_to_params()}} +} diff --git a/man/convert_summary_stats_to_params.Rd b/man/convert_summary_stats_to_params.Rd new file mode 100644 index 000000000..ed82b9cb1 --- /dev/null +++ b/man/convert_summary_stats_to_params.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{convert_summary_stats_to_params} +\alias{convert_summary_stats_to_params} +\alias{convert_summary_stats_to_params.character} +\alias{convert_summary_stats_to_params.epiparameter} +\title{Convert the summary statistics of a distribution to parameters} +\usage{ +convert_summary_stats_to_params(x, ...) + +\method{convert_summary_stats_to_params}{character}( + x = c("lnorm", "gamma", "weibull", "nbinom", "geom"), + ... +) + +\method{convert_summary_stats_to_params}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \R object.} + +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named summary +statistics used to convert to parameter(s). An example is the \code{mean} +and \code{sd} summary statistics for the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of either one or two elements (depending on how many +parameters the distribution has). +} +\description{ +Convert the summary statistics for a range of distributions to +the distribution's parameters. Most summary statistics are calculated +analytically given the parameters. An exception is the Weibull distribution +which uses a root finding numerical method. +} +\details{ +Summary statistics should be named accordingly (case-sensitive): +\itemize{ +\item mean: \code{mean} +\item median: \code{median} +\item mode: \code{mode} +\item variance: \code{var} +\item standard deviation: \code{sd} +\item coefficient of variation: \code{cv} +\item skewness: \code{skewness} +\item excess kurtosis: \code{ex_kurtosis} +} + +\strong{Note}: Not all combinations of summary statistics can be converted into +distribution parameters. In this case the function will error stating that +the parameters cannot be calculated from the given input. + +The distribution names and parameter names follow the style of +distributions in \R, for example the lognormal distribution is \code{lnorm}, +and its parameters are \code{meanlog} and \code{sdlog}. +} +\examples{ +# examples using characters +convert_summary_stats_to_params("lnorm", mean = 1, sd = 1) +convert_summary_stats_to_params("weibull", mean = 2, var = 2) +convert_summary_stats_to_params("geom", mean = 2) + +# examples using <epiparameter> +epiparameter <- epiparameter_db(single_epiparameter = TRUE) +convert_summary_stats_to_params(epiparameter) + +# example using <epiparameter> and specifying summary stats +epiparameter$summary_stats <- list() +convert_summary_stats_to_params(epiparameter, mean = 10, sd = 2) +} +\seealso{ +\code{\link[=convert_params_to_summary_stats]{convert_params_to_summary_stats()}} +} diff --git a/man/create_citation.Rd b/man/create_citation.Rd new file mode 100644 index 000000000..b637d74f8 --- /dev/null +++ b/man/create_citation.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{create_citation} +\alias{create_citation} +\title{Create a citation for an \verb{<epiparameter>} object} +\usage{ +create_citation( + author = utils::person(), + year = NA_integer_, + title = NA_character_, + journal = NA_character_, + doi = NA_character_, + pmid = NA_integer_ +) +} +\arguments{ +\item{author}{Either a \verb{<person>}, a \code{character} string, or a vector or list +of \code{characters} in the case of multiple authors. Specify the full name +(\verb{"<given name>" "<family name>"}). When using \code{characters} make sure the +name can be converted to a \verb{<person>} (see \code{\link[=as.person]{as.person()}}). Use white space +separation between names. Multiple names can be stored within a single +\verb{<person>} (see \code{\link[=person]{person()}}).} + +\item{year}{A \code{numeric} of the year of publication.} + +\item{title}{A \code{character} string with the title of the article that +published the epidemiological parameters.} + +\item{journal}{A \code{character} string with the name of the journal that +published the article that published the epidemiological parameters. +This can also be a pre-print server, e.g., medRxiv.} + +\item{doi}{A \code{character} string of the Digital Object Identifier (DOI) +assigned to papers which are unique to each paper.} + +\item{pmid}{A \code{character} string with the PubMed unique identifier number +(PMID) assigned to papers to give them a unique identifier within PubMed.} +} +\value{ +A \verb{<bibentry>} object of the citation +} +\description{ +A helper function when creating an \verb{<epiparameter>} object to +create a citation list with sensible defaults, type checking and arguments +to help remember which citation information is accepted in the list. +} +\details{ +This function acts as a wrapper around \code{\link[=bibentry]{bibentry()}} to create +citations for sources reporting epidemiological parameters. +} +\examples{ +create_citation( + author = person(given = "John", family = "Smith"), + year = 2002, + title = "COVID-19 incubation period", + journal = "Epi Journal", + doi = "10.19832/j.1366-9516.2012.09147.x" +) +} diff --git a/man/create_metadata.Rd b/man/create_metadata.Rd new file mode 100644 index 000000000..ca0c3f00f --- /dev/null +++ b/man/create_metadata.Rd @@ -0,0 +1,91 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{create_metadata} +\alias{create_metadata} +\title{Specify metadata associated with data set} +\usage{ +create_metadata( + units = NA_character_, + sample_size = NA_integer_, + region = NA_character_, + transmission_mode = NA_character_, + vector = NA_character_, + extrinsic = FALSE, + inference_method = NA_character_ +) +} +\arguments{ +\item{units}{A \code{character} for the units of the epidemiological parameter.} + +\item{sample_size}{The sample of the data used to fit the delay distribution. +This is usually the number of people with data on a primary and possibly +secondary event of interest. In cases where the sample size is not stated +NA can be used.} + +\item{region}{The geographical location the data was collected. This can +either be given at sub-national, national, continental. Multiple nested +regions can be given and are comma separated. When the region is not +specified NA can be given.} + +\item{transmission_mode}{A character string specifying how the pathogen is +transmitted. This information is used to determine whether the +epidemiological parameters are from a vector-borne disease (i.e. is +transmitted between humans through an intermediate vector), this is specified +by \code{transmission_mode = "vector_borne"}.} + +\item{vector}{The name of the vector transmitting the vector-borne disease. +This can be a common name, or a latin binomial name of a specific vector +species. Both the common name and taxonomic name can be given with one given +in parentheses. When a disease is not vector-borne NA should be given.} + +\item{extrinsic}{A boolean value defining whether the data entry is an +extrinsic delay distribution, such as the extrinsic incubation period. +This field is required because intrinsic and extrinsic delay distributions +are stored as separate entries in the database and can be linked. +When the disease is not vector-borne FALSE should be given. See Details for +explanation of extrinsic distribution.} + +\item{inference_method}{The type of inference used to fit the delay +distribution to the data. Abbreviations of model fitting techniques can be +specified as long as they are non-ambiguous. This field is only used to +determine whether the uncertainty intervals possibly specified in the other +fields are: confidence intervals (in the case of maximum likelihood), or +credible intervals (in the case of bayesian inference). Uncertainty bounds +for another types of inference methods, or if the inference method is +unstated are assumed to be confidence intervals. When the inference method +is unknown or a disease does not have a probability distribution NA can be +given.} +} +\value{ +A named list containing information on the sample size of the study, +geography, whether the disease is vector-borne and if so whether it is the +intrinsic or extrinsic distribution as well as method of distribution +parameter estimation. +} +\description{ +A helper function when creating an \verb{<epiparameter>} object to +create a metadata list with sensible defaults, type checking and arguments +to help remember metadata list structure (element names). +} +\details{ +In vector-borne diseases the transmissibility of a disease is +dependent on both the time taken for a host (i.e. human) to become +infectious, but also on the time it takes the vector to become infectious. +Therefore, the extrinsic delay, in which the vector has been infected by is +not yet infectious can have a role in the spread of a disease. +} +\examples{ +# it will automatically populate the fields with defaults if left empty +create_metadata() + +# supplying each field +create_metadata( + units = "days", + sample_size = 10, + region = "UK", + transmission_mode = "vector_borne", + vector = "mosquito", + extrinsic = FALSE, + inference_method = "MLE" +) +} diff --git a/man/create_method_assess.Rd b/man/create_method_assess.Rd new file mode 100644 index 000000000..e75b82d24 --- /dev/null +++ b/man/create_method_assess.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{create_method_assess} +\alias{create_method_assess} +\title{Specify methodological aspects of distribution fitting} +\usage{ +create_method_assess( + censored = NA, + right_truncated = NA, + phase_bias_adjusted = NA +) +} +\arguments{ +\item{censored}{A boolean \code{logical} whether the study used single or double +interval censoring in the methods to infer the delay distribution} + +\item{right_truncated}{A boolean \code{logical} whether the study used right- +truncation in the methods to infer the delay distribution} + +\item{phase_bias_adjusted}{A boolean \code{logical} whether the study adjusted for +phase bias in the methods to infer the delay distribution} +} +\value{ +A named list with three elements +} +\description{ +A helper function when creating an \verb{<epiparameter>} object to +create a method assessment list with sensible defaults, type checking and +arguments to help remember which method assessments can be accepted in +the list. +} +\details{ +Currently, the method assessment focuses on common methodological +aspects of delay distributions (e.g. incubation period, serial interval, +etc.), and does not currently take into account methodological aspects which +may be important when fitting offspring distributions to data on disease +(super)spreading. +} +\examples{ +create_method_assess( + censored = FALSE, + right_truncated = FALSE, + phase_bias_adjusted = FALSE +) +} diff --git a/man/create_prob_distribution.Rd b/man/create_prob_distribution.Rd new file mode 100644 index 000000000..3c9adb308 --- /dev/null +++ b/man/create_prob_distribution.Rd @@ -0,0 +1,100 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/create_prob_distribution.R +\name{create_prob_distribution} +\alias{create_prob_distribution} +\title{Create a distribution object} +\usage{ +create_prob_distribution( + prob_distribution, + prob_distribution_params, + discretise = FALSE, + truncation = NA, + ... +) +} +\arguments{ +\item{prob_distribution}{A \code{character} string specifying the probability +distribution. This should match the \R naming convention of probability +distributions (e.g. lognormal is \code{lnorm}, negative binomial is \code{nbinom}, and +geometric is \code{geom}).} + +\item{prob_distribution_params}{A named vector of probability distribution +parameters.} + +\item{discretise}{A boolean \code{logical} whether the distribution is +discretised. Default is \code{FALSE} which assumes a continuous probability +distribution.} + +\item{truncation}{A \code{numeric} specifying the truncation point if the inferred +distribution was truncated, \code{NA} if not or unknown.} + +\item{...}{\link{dots} Extra arguments to be passed to +\pkg{distributional} or \pkg{distcrete} functions that construct the S3 +distribution objects. To see which arguments can be adjusted for discretised +distributions see \code{\link[distcrete:distcrete]{distcrete::distcrete()}}, for other distributions see +the \code{?distributional} documentation and find the specific distribution +constructor function, e.g. for the Gamma distribution see +\code{\link[distributional:dist_gamma]{distributional::dist_gamma()}}.} +} +\value{ +An S3 class containing the probability distribution or a \code{character} +string if the parameters of the probability distribution are unknown. +} +\description{ +Creates an S3 class holding the distribution and parameters +from the probability distribution name, its parameters and distribution +truncation and discretisation. + +The class holding the distribution depends on whether it is a discretised +distribution. For continuous and discrete distributions S3 classes from the +\pkg{distributional} package are used, for discretised continuous +distributions the an S3 class from the \pkg{distcrete} package is used. + +For details on the properties of the distribution classes +from each respective package see their documentation (either +\code{?distributional} or \code{?distcrete}) +} +\details{ +Truncation is enabled only for continuous distributions as there +is no truncation implemented in \pkg{distcrete}. + +By default the discretisation of continuous distributions uses a +discretisation interval (\code{interval}) of 1. If the unit of the distribution +is days, then this will be discretised by day. The endpoint weighting (\code{w}) +for the discretisation is 1. \code{w} can be \verb{[0,1]}. For more information please +see \code{\link[distcrete:distcrete]{distcrete::distcrete()}}. +} +\examples{ +# example with continuous distribution without truncation +create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA +) + +# example with continuous distribution with truncation +create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = 10 +) + +# example with discrete distribution +create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = NA +) + +# example passing extra arguments to distcrete +create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = NA, + w = 0.5 +) +} diff --git a/man/create_region.Rd b/man/create_region.Rd new file mode 100644 index 000000000..45f12dd65 --- /dev/null +++ b/man/create_region.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{create_region} +\alias{create_region} +\title{Specify the geography of the data entry} +\usage{ +create_region( + continent = NA_character_, + country = NA_character_, + region = NA_character_, + city = NA_character_ +) +} +\arguments{ +\item{continent}{A \code{character} string specifying the continent.} + +\item{country}{A \code{character} string specifying the country.} + +\item{region}{A \code{character} string specifying the region.} + +\item{city}{A \code{character} string specifying the city.} +} +\value{ +A named list. +} +\description{ +The geography of the data set can be a single geographical +region at either continent, country, region or city level. By specifying +the level of the geography the other fields may be deduced. +} +\examples{ +create_region(country = "UK") +} diff --git a/man/create_summary_stats.Rd b/man/create_summary_stats.Rd new file mode 100644 index 000000000..787d27c71 --- /dev/null +++ b/man/create_summary_stats.Rd @@ -0,0 +1,125 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{create_summary_stats} +\alias{create_summary_stats} +\title{Specify reported summary statistics} +\usage{ +create_summary_stats( + mean = NA_real_, + mean_ci_limits = c(NA_real_, NA_real_), + mean_ci = NA_real_, + sd = NA_real_, + sd_ci_limits = c(NA_real_, NA_real_), + sd_ci = NA_real_, + median = NA_real_, + median_ci_limits = c(NA_real_, NA_real_), + median_ci = NA_real_, + dispersion = NA_real_, + dispersion_ci_limits = c(NA_real_, NA_real_), + dispersion_ci = NA_real_, + lower_range = NA_real_, + upper_range = NA_real_, + quantiles = NA_real_ +) +} +\arguments{ +\item{mean}{A \code{numeric} of the mean (expectation) of the probability +distribution.} + +\item{mean_ci_limits}{A \code{numeric} vector of length two of the confidence +interval around the mean.} + +\item{mean_ci}{A \code{numeric} specifying the confidence interval width, +e.g. \code{95} would be the 95\% CI} + +\item{sd}{A \code{numeric} of the standard deviation of the probability +distribution.} + +\item{sd_ci_limits}{A \code{numeric} vector of length 2 of the confidence interval +around the standard deviation.} + +\item{sd_ci}{A \code{numeric} specifying the confidence interval width, +e.g. \code{95} would be 95\% confidence interval.} + +\item{median}{A \code{numeric} of the median of the probability distribution.} + +\item{median_ci_limits}{A \code{numeric} vector of length two of the confidence +interval around the median.} + +\item{median_ci}{A \code{numeric} specifying the confidence interval width +of the median.} + +\item{dispersion}{A \code{numeric} of the dispersion of the probability +distribution. \strong{Important} this is the dispersion for probability +distributions that are not usually parameterised by a dispersion parameter, +for example a lognormal distribution. If a probability distribution is +usually parameterised with a dispersion parameter, e.g. negative binomial +distribution, then this should be considered a parameter and not a summary +statistic and should go in the \code{prob_distribution} argument when +constructing an \verb{<epiparameter>} object with \code{\link[=epiparameter]{epiparameter()}} +(see \code{\link[=create_prob_distribution]{create_prob_distribution()}}).} + +\item{dispersion_ci_limits}{A \code{numeric} vector of length 2 of the confidence +interval around the dispersion.} + +\item{dispersion_ci}{A \code{numeric} specifying the confidence interval width, +e.g. \code{95} would be 95\% confidence interval.} + +\item{lower_range}{The lower range of the data, used to infer the parameters +of the distribution when not provided.} + +\item{upper_range}{The upper range of the data, used to infer the parameters +of the distribution when not provided.} + +\item{quantiles}{A \code{numeric} vector of the quantiles for the distribution. +If quantiles are not provided a default empty vector with the 2.5th, 5th, +25th, 75th, 95th, 97.5th quantiles are supplied.} +} +\value{ +A list of summary statistics. The output list has element names +equal to the function arguments: +\preformatted{ +$mean +$mean_ci_limits +$mean_ci +$sd +$sd_ci_limits +$sd_ci +$median +$median_ci_limits +$median_ci +$dispersion +$dispersion_ci_limits +$dispersion_ci +$lower_range +$upper_range +$quantiles +} +} +\description{ +A helper function when creating an \verb{<epiparameter>} object to +create a summary statistics list with sensible defaults, type checking +and arguments to help remember which summary statistics can be accepted in +the list. +} +\examples{ +# mean and standard deviation +create_summary_stats(mean = 5, sd = 2) + +# mean and standard deviation with uncertainty +create_summary_stats( + mean = 4, + mean_ci_limits = c(2.1, 5.7), + mean_ci = 95, + sd = 0.7, + sd_ci_limits = c(0.3, 1.1), + sd_ci = 95 +) + +# median and range +create_summary_stats( + median = 5, + lower_range = 1, + upper_range = 13 +) +} diff --git a/man/create_uncertainty.Rd b/man/create_uncertainty.Rd new file mode 100644 index 000000000..f7b1b3907 --- /dev/null +++ b/man/create_uncertainty.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{create_uncertainty} +\alias{create_uncertainty} +\title{Specify distribution parameter uncertainty} +\usage{ +create_uncertainty(ci_limits = NA_real_, ci, ci_type) +} +\arguments{ +\item{ci_limits}{A numeric vector of length two with the lower and upper +bound of the confidence interval or credible interval.} + +\item{ci}{A numeric specifying the interval for the ci, e.g. 95 is +95\% ci.} + +\item{ci_type}{A character string, either \code{"confidence interval"} or +\code{"credible interval"}.} +} +\value{ +List of three elements: +\enumerate{ +\item \verb{$ci_limits} is the upper and lower bounds +of the CI (either confidence interval or credible interval) (i.e. a two +element numeric vector). +\item \verb{$ci} the interval (e.g. 95 is 95\% CI) given by a +single numeric. +\item \verb{$ci_type} a character string specifying the type of +uncertainty (can be either \code{"confidence interval"} or \code{"credible interval"}). +} +} +\description{ +A helper function when creating uncertainty for the parameters +of the distribution for the \verb{<epiparameter>} object. +} +\examples{ +# example with uncertainty for a single parameter +create_uncertainty( + ci_limits = c(1, 3), + ci = 95, + ci_type = "confidence interval" +) + +# example for multiple parameters +# lengh of list should match number of parameters +list( + shape = create_uncertainty( + ci_limits = c(1, 3), + ci = 95, + ci_type = "confidence interval" + ), + scale = create_uncertainty( + ci_limits = c(2, 4), + ci = 95, + ci_type = "confidence interval" + ) +) + +# example with unknown uncertainty +# the function can be called without arguments +create_uncertainty() +# or give NA as the first argument +create_uncertainty(NA) +} diff --git a/man/discretise.Rd b/man/discretise.Rd new file mode 100644 index 000000000..c87141979 --- /dev/null +++ b/man/discretise.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{discretise} +\alias{discretise} +\alias{discretize} +\alias{discretise.epiparameter} +\alias{discretise.default} +\title{Discretises a continuous distribution in an \verb{<epiparameter>} object} +\usage{ +discretise(x, ...) + +discretize(x, ...) + +\method{discretise}{epiparameter}(x, ...) + +\method{discretise}{default}(x, ...) +} +\arguments{ +\item{x}{An \verb{<epiparameter>} object.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\value{ +An \verb{<epiparameter>} object. +} +\description{ +Discretises a continuous distribution in an \verb{<epiparameter>} object +} +\details{ +Converts the S3 distribution object in an \verb{<epiparameter>} from +continuous (using an object from the \code{{distributional}} package) to a +discretised distribution (using an object from the \code{{distcrete}} package). +} +\examples{ +ebola_incubation <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) +discretise(ebola_incubation) +} diff --git a/man/dot-calc_dist_params.Rd b/man/dot-calc_dist_params.Rd new file mode 100644 index 000000000..ea6f8f14f --- /dev/null +++ b/man/dot-calc_dist_params.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/calc_dist_params.R +\name{.calc_dist_params} +\alias{.calc_dist_params} +\title{Calculate the parameters of a probability distribution from a list of +summary statistics} +\usage{ +.calc_dist_params(prob_distribution, summary_stats, sample_size) +} +\arguments{ +\item{prob_distribution}{An S3 class containing the probability +distribution or a character string if the parameters of the probability +distribution are unknown but the name of the distribution is known, or \code{NA} +if the distribution name and parameters are unknown. Use +\code{\link[=create_prob_distribution]{create_prob_distribution()}} to create \code{prob_distribution}.} + +\item{summary_stats}{A list of summary statistics, use +\code{\link[=create_summary_stats]{create_summary_stats()}} to create list. This list can include +summary statistics about the inferred distribution such as it's mean and +standard deviation, quantiles of the distribution, or information about the +data used to fit the distribution such as lower and upper range. The summary +statistics can also include uncertainty around metrics such as confidence +interval around mean and standard deviation.} + +\item{sample_size}{The sample size of the data. Only needed when falling back +on using the median-range extraction calculation.} +} +\value{ +A named \code{numeric} vector with parameters. +} +\description{ +If parameters of a probability distribution are not +provided (e.g. when describing the distribution in the literature) and +instead summary statistics of a distribution are provided, the parameters +can usually be calculated from the summary statistics. + +This function can provide a convenient wrapper around +\code{\link[=convert_summary_stats_to_params]{convert_summary_stats_to_params()}} and \code{\link[=extract_param]{extract_param()}} +when it is not known which summary statistics can be used to +calculate the parameters of a distribution. +} +\details{ +The hierarchy of methods is: +\enumerate{ +\item Conversion is prioritised if the mean and standard deviation are +available as these are mostly analytical conversions (except for one of the +Weibull conversions). +\item Next method if possible is extraction from percentiles. This method +requires a lower percentile (between(0-50]) and an upper percentile +(between (50-100)). If multiple percentiles in each of these ranges is +provided the lowest value is used for the calculation. +\item The last method is the extraction using a median and range of the data. +} +} +\keyword{internal} diff --git a/man/dot-check_optim_conv.Rd b/man/dot-check_optim_conv.Rd new file mode 100644 index 000000000..185e1cc35 --- /dev/null +++ b/man/dot-check_optim_conv.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/extract_param.R +\name{.check_optim_conv} +\alias{.check_optim_conv} +\title{Check whether the optimisation of distribution parameters has converged to +stable value for the parameters and function output for multiple iterations} +\usage{ +.check_optim_conv(optim_params_list, optim_params, tolerance) +} +\arguments{ +\item{optim_params_list}{A list, where each element is the output of +\code{\link[stats:optim]{stats::optim()}}. See \code{?optim} for more details.} + +\item{optim_params}{A list given by the output of \code{\link[stats:optim]{stats::optim()}}.} + +\item{tolerance}{A \code{numeric} specifying within which disparity convergence +of parameter estimates and function minimisation is accepted.} +} +\value{ +Boolean +} +\description{ +This function is to try and prevent optimisation to a local +optimum and thus checks whether multiple optimisation routines are +consistently finding parameter values to within a set tolerance. +} +\keyword{internal} diff --git a/man/dot-citet.Rd b/man/dot-citet.Rd new file mode 100644 index 000000000..947f5f7d8 --- /dev/null +++ b/man/dot-citet.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{.citet} +\alias{.citet} +\title{Format short citation from \verb{<bibentry>} object} +\usage{ +.citet(x) +} +\arguments{ +\item{x}{A \verb{<bibentry>} object, see \code{\link[=bibentry]{bibentry()}}.} +} +\value{ +A \code{character} string with the short citation. +} +\description{ +Output is equivalent to the \verb{\\citet\{\}} function in the \pkg{natbib} LaTeX +package. +} +\keyword{internal} diff --git a/man/dot-clean_params.Rd b/man/dot-clean_params.Rd new file mode 100644 index 000000000..409aeb3d6 --- /dev/null +++ b/man/dot-clean_params.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{.clean_params} +\alias{.clean_params} +\alias{.clean_params_gamma} +\alias{.clean_params_lnorm} +\alias{.clean_params_nbinom} +\alias{.clean_params_geom} +\alias{.clean_params_pois} +\alias{.clean_params_norm} +\alias{.clean_params_exp} +\title{Standardise distribution parameters} +\usage{ +.clean_params(prob_distribution, prob_distribution_params) + +.clean_params_gamma(prob_dist_params) + +.clean_params_lnorm(prob_dist_params) + +.clean_params_nbinom(prob_dist_params) + +.clean_params_geom(prob_dist_params) + +.clean_params_pois(prob_dist_params) + +.clean_params_norm(prob_dist_params) + +.clean_params_exp(prob_dist_params) +} +\arguments{ +\item{prob_distribution}{A \code{character} string specifying the probability +distribution. This should match the \R naming convention of probability +distributions (e.g. lognormal is \code{lnorm}, negative binomial is \code{nbinom}, and +geometric is \code{geom}).} + +\item{prob_distribution_params}{A named vector of probability distribution +parameters.} +} +\value{ +Named \code{numeric} vector of parameters. +} +\description{ +\code{.clean_params()} dispatches to a distribution +specific parameter cleaning function depending on \code{prob_dist}. For example +\code{prob_dist = "gamma"} will call \code{.clean_params_gamma()}. +} +\details{ +Calling \code{\link[=is_epiparameter_params]{is_epiparameter_params()}} at the start of +\code{.clean_params()} ensures that if the parameterisation is +incorrect that it will error early and dispatch to the distribution +specific cleaning functions (e.g. \code{.clean_params_gamma()}). +This means that the distribution specific parameter cleaning functions do +not need to check and error for incorrect parameterisation. +} +\keyword{internal} diff --git a/man/dot-clean_string.Rd b/man/dot-clean_string.Rd new file mode 100644 index 000000000..d038e1f83 --- /dev/null +++ b/man/dot-clean_string.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{.clean_string} +\alias{.clean_string} +\title{Standardise the variables input by users} +\usage{ +.clean_string(x) +} +\arguments{ +\item{x}{A \code{character} string.} +} +\value{ +A \code{character} vector of equal length to the input. +} +\description{ +Checks a user has supplied a \code{character} string and converts +to \pkg{epiparameter} standards: lower-case and whitespace instead of +dashes or underscores. + +Examples of strings needing to be cleaned are: disease and pathogen names, +and epidemiological distributions. +} +\keyword{internal} diff --git a/man/dot-clean_uncertainty.Rd b/man/dot-clean_uncertainty.Rd new file mode 100644 index 000000000..d3a540656 --- /dev/null +++ b/man/dot-clean_uncertainty.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{.clean_uncertainty} +\alias{.clean_uncertainty} +\title{Standardise distribution parameter uncertainty} +\usage{ +.clean_uncertainty(x, prob_distribution, uncertainty_missing) +} +\arguments{ +\item{x}{An \verb{<epiparameter>} object.} + +\item{prob_distribution}{An S3 class containing the probability +distribution or a character string if the parameters of the probability +distribution are unknown but the name of the distribution is known, or \code{NA} +if the distribution name and parameters are unknown. Use +\code{\link[=create_prob_distribution]{create_prob_distribution()}} to create \code{prob_distribution}.} + +\item{uncertainty_missing}{A boolean \code{logical} as to whether \code{uncertainty} +is missing (see \code{\link[=missing]{missing()}}) from the parent function.} +} +\value{ +An uncertainty list for an \verb{<epiparameter>} object. +} +\description{ +Standardise distribution parameter uncertainty +} +\keyword{internal} diff --git a/man/dot-convert_params_gamma.Rd b/man/dot-convert_params_gamma.Rd new file mode 100644 index 000000000..b5549d86e --- /dev/null +++ b/man/dot-convert_params_gamma.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_params_gamma} +\alias{.convert_params_gamma} +\title{Convert parameters of the gamma distribution to summary statistics} +\usage{ +.convert_params_gamma(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named parameter(s) +used to convert to summary statistics. An example is the \code{meanlog} and +\code{sdlog} parameters of the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of eight elements including: mean, median, mode, +variance (\code{var}), standard deviation (\code{sd}), coefficient of variation (\code{cv}), +skewness, and excess kurtosis (\code{ex_kurtosis}). +} +\description{ +Convert the shape and scale parameters of the gamma +distribution to a number of summary statistics which can be calculated +analytically given the gamma parameters. One exception is the median which +is calculated using \code{\link[=qgamma]{qgamma()}} as no analytical form is available. +} +\keyword{internal} diff --git a/man/dot-convert_params_geom.Rd b/man/dot-convert_params_geom.Rd new file mode 100644 index 000000000..f1510a35b --- /dev/null +++ b/man/dot-convert_params_geom.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_params_geom} +\alias{.convert_params_geom} +\title{Convert parameter of the geometric distribution to summary statistics} +\usage{ +.convert_params_geom(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named parameter(s) +used to convert to summary statistics. An example is the \code{meanlog} and +\code{sdlog} parameters of the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of eight elements including: mean, median, mode, +variance (\code{var}), standard deviation (\code{sd}), coefficient of variation (\code{cv}), +skewness, and excess kurtosis (\code{ex_kurtosis}). +} +\description{ +Convert the probability (\code{prob}) of the geometric distribution +to a number of summary statistics which can be calculated analytically given +the geometric parameter. One exception is the median which is calculated +using \code{\link[stats:Geometric]{stats::qgeom()}} as the analytical form is not always unique. +} +\details{ +This conversion function assumes that distribution represents the +number of failures before the first success (supported for zero). This is +the same form as used by base R and \code{\link[distributional:dist_geometric]{distributional::dist_geometric()}}. +} +\keyword{internal} diff --git a/man/dot-convert_params_lnorm.Rd b/man/dot-convert_params_lnorm.Rd new file mode 100644 index 000000000..4c342bfff --- /dev/null +++ b/man/dot-convert_params_lnorm.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_params_lnorm} +\alias{.convert_params_lnorm} +\title{Converts the parameters of the lognormal distribution to summary statistics} +\usage{ +.convert_params_lnorm(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named parameter(s) +used to convert to summary statistics. An example is the \code{meanlog} and +\code{sdlog} parameters of the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of eight elements including: mean, median, mode, +variance (\code{var}), standard deviation (\code{sd}), coefficient of variation (\code{cv}), +skewness, and excess kurtosis (\code{ex_kurtosis}). +} +\description{ +Converts the meanlog and sdlog parameters of the lognormal +distribution to a number of summary statistics which can be calculated +analytically given the lognormal parameters. +} +\keyword{internal} diff --git a/man/dot-convert_params_nbinom.Rd b/man/dot-convert_params_nbinom.Rd new file mode 100644 index 000000000..a6b3e50ae --- /dev/null +++ b/man/dot-convert_params_nbinom.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_params_nbinom} +\alias{.convert_params_nbinom} +\title{Convert parameters of the negative binomial distribution to summary +statistics} +\usage{ +.convert_params_nbinom(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named parameter(s) +used to convert to summary statistics. An example is the \code{meanlog} and +\code{sdlog} parameters of the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of eight elements including: mean, median, mode, +variance (\code{var}), standard deviation (\code{sd}), coefficient of variation (\code{cv}), +skewness, and ex_kurtosis. +} +\description{ +Convert the probability (\code{prob}) and dispersion parameters of +the negative binomial distribution to a number of summary statistics which +can be calculated analytically given the negative binomial parameters. +One exception is the median which is calculated using \code{\link[=qnbinom]{qnbinom()}} as no +analytical form is available. + +The parameters are \code{prob} and \code{dispersion} (which is also commonly +represented as \emph{r}). +} +\keyword{internal} diff --git a/man/dot-convert_params_weibull.Rd b/man/dot-convert_params_weibull.Rd new file mode 100644 index 000000000..2ea700f3d --- /dev/null +++ b/man/dot-convert_params_weibull.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_params_weibull} +\alias{.convert_params_weibull} +\title{Convert parameters of the Weibull distribution to summary statistics} +\usage{ +.convert_params_weibull(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named parameter(s) +used to convert to summary statistics. An example is the \code{meanlog} and +\code{sdlog} parameters of the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of eight elements including: mean, median, mode, +variance (\code{var}), standard deviation (\code{sd}), coefficient of variation (\code{cv}), +skewness, and excess kurtosis (\code{ex_kurtosis}). +} +\description{ +Convert the shape and scale parameters of the Weibull +distribution to a number of summary statistics which can be calculated +analytically given the Weibull parameters. Note the conversion uses the +\code{\link[=gamma]{gamma()}} function. +} +\keyword{internal} diff --git a/man/dot-convert_summary_stats_gamma.Rd b/man/dot-convert_summary_stats_gamma.Rd new file mode 100644 index 000000000..38666448b --- /dev/null +++ b/man/dot-convert_summary_stats_gamma.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_summary_stats_gamma} +\alias{.convert_summary_stats_gamma} +\title{Convert summary statistics to parameters of the gamma distribution} +\usage{ +.convert_summary_stats_gamma(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named summary +statistics used to convert to parameter(s). An example is the \code{mean} +and \code{sd} summary statistics for the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of two elements, the shape and scale +} +\description{ +Convert the summary statistics input into the shape and scale +parameters of the gamma distribution. +} +\keyword{internal} diff --git a/man/dot-convert_summary_stats_geom.Rd b/man/dot-convert_summary_stats_geom.Rd new file mode 100644 index 000000000..d63a5c750 --- /dev/null +++ b/man/dot-convert_summary_stats_geom.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_summary_stats_geom} +\alias{.convert_summary_stats_geom} +\title{Convert summary statistics to parameters of the geometric distribution} +\usage{ +.convert_summary_stats_geom(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named summary +statistics used to convert to parameter(s). An example is the \code{mean} +and \code{sd} summary statistics for the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of one element, the probability parameter. +} +\description{ +Convert summary statistics of the geometric +distribution the parameter (\code{prob}) of the geometric distribution. +} +\details{ +This conversion function assumes that distribution represents the +number of failures before the first success (supported for zero). This is +the same form as used by base R and \code{\link[distributional:dist_geometric]{distributional::dist_geometric()}}. +} +\keyword{internal} diff --git a/man/dot-convert_summary_stats_lnorm.Rd b/man/dot-convert_summary_stats_lnorm.Rd new file mode 100644 index 000000000..6549f5fea --- /dev/null +++ b/man/dot-convert_summary_stats_lnorm.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_summary_stats_lnorm} +\alias{.convert_summary_stats_lnorm} +\title{Convert summary statistics to parameters of the lognormal distribution} +\usage{ +.convert_summary_stats_lnorm(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named summary +statistics used to convert to parameter(s). An example is the \code{mean} +and \code{sd} summary statistics for the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of two elements: meanlog and sdlog +} +\description{ +Convert the summary statistics input into the meanlog and sdlog +parameters of the lognormal distribution. +} +\keyword{internal} diff --git a/man/dot-convert_summary_stats_nbinom.Rd b/man/dot-convert_summary_stats_nbinom.Rd new file mode 100644 index 000000000..5cc0a8acd --- /dev/null +++ b/man/dot-convert_summary_stats_nbinom.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_summary_stats_nbinom} +\alias{.convert_summary_stats_nbinom} +\title{Convert summary statistics to parameters of the negative binomial +distribution} +\usage{ +.convert_summary_stats_nbinom(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named summary +statistics used to convert to parameter(s). An example is the \code{mean} +and \code{sd} summary statistics for the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of two elements, the probability and dispersion parameters. +} +\description{ +Convert summary statistics of the negative binomial +distribution the parameters (\code{prob}) and (\code{dispersion}) of the negative +binomial distribution. +} +\keyword{internal} diff --git a/man/dot-convert_summary_stats_weibull.Rd b/man/dot-convert_summary_stats_weibull.Rd new file mode 100644 index 000000000..4e3758983 --- /dev/null +++ b/man/dot-convert_summary_stats_weibull.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert_params.R +\name{.convert_summary_stats_weibull} +\alias{.convert_summary_stats_weibull} +\title{Convert summary statistics to parameters of the Weibull distribution} +\usage{ +.convert_summary_stats_weibull(...) +} +\arguments{ +\item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}> \code{Numeric} named summary +statistics used to convert to parameter(s). An example is the \code{mean} +and \code{sd} summary statistics for the lognormal (\code{lnorm}) distribution.} +} +\value{ +A list of two elements, the shape and scale. +} +\description{ +Convert summary statistics input into the shape and scale +parameters of the Weibull distribution. +} +\keyword{internal} diff --git a/man/dot-epiparameter_df_to_epiparameter.Rd b/man/dot-epiparameter_df_to_epiparameter.Rd new file mode 100644 index 000000000..7d979afa3 --- /dev/null +++ b/man/dot-epiparameter_df_to_epiparameter.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{.epiparameter_df_to_epiparameter} +\alias{.epiparameter_df_to_epiparameter} +\title{Convert \verb{<data.frame>} from \code{\link[=as.data.frame.epiparameter]{as.data.frame.epiparameter()}} to +\verb{<epiparameter>}} +\usage{ +.epiparameter_df_to_epiparameter(x, ...) +} +\arguments{ +\item{x}{A \verb{<data.frame>}.} + +\item{...}{\link{dots} Extra arguments to pass to \code{\link[=epiparameter]{epiparameter()}}.} +} +\value{ +An \verb{<epiparameter>} object. +} +\description{ +Convert \verb{<data.frame>} from \code{\link[=as.data.frame.epiparameter]{as.data.frame.epiparameter()}} to +\verb{<epiparameter>} +} +\keyword{internal} diff --git a/man/dot-extract_param.Rd b/man/dot-extract_param.Rd new file mode 100644 index 000000000..f7eea050d --- /dev/null +++ b/man/dot-extract_param.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/extract_param.R +\name{.extract_param} +\alias{.extract_param} +\title{Optimises the parameters for a specified probability distribution given the +percentiles of a distribution and the values at those percentiles, or the +median and range of a sample and the number of samples.} +\usage{ +.extract_param(values, distribution, percentiles, samples) +} +\arguments{ +\item{values}{A \code{vector}. If \code{type = percentiles}: \code{c(percentile_1, percentile_2)}; and if \code{type = range}: \code{c(median, min, max)}.} + +\item{distribution}{A \code{character} specifying distribution to use. +Default is \code{lnorm}; also takes \code{gamma}, \code{weibull} and \code{norm}.} + +\item{percentiles}{A \code{vector} with two elements specifying the +percentiles defined in \code{values} if using \code{type = "percentiles"}. +Percentiles should be specified between 0 and 1. For example 2.5th and 97.5th +percentile is given as \code{c(0.025, 0.975)}.} + +\item{samples}{A \code{numeric} specifying the sample size if using +\code{type = "range"}.} +} +\value{ +A list with output from \code{\link[stats:optim]{stats::optim()}}. +} +\description{ +Optimises the parameters for a specified probability distribution given the +percentiles of a distribution and the values at those percentiles, or the +median and range of a sample and the number of samples. +} +\keyword{internal} diff --git a/man/dot-get_percentiles.Rd b/man/dot-get_percentiles.Rd new file mode 100644 index 000000000..7a5d2f61a --- /dev/null +++ b/man/dot-get_percentiles.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_percentiles.R +\name{.get_percentiles} +\alias{.get_percentiles} +\title{Convert a vector of named percentiles into correct format and selects two +values for parameter extraction} +\usage{ +.get_percentiles(percentiles) +} +\arguments{ +\item{percentiles}{A named vector of values at percentiles with the names the +percentiles. See Details for the accepted vector name format.} +} +\value{ +A named \code{numeric} vector of percentiles. +} +\description{ +Parameters of a probability distribution can be extracted using +the values given at percentiles of the distribution and the percentiles using +\code{\link[=extract_param]{extract_param()}}. \code{\link[=.get_percentiles]{.get_percentiles()}} takes a named vector of percentiles +(names) and values at those percentiles (elements in the vector) and selects +two values as lower and upper percentiles to be used in extraction. If a +lower and upper percentile are not available \code{NA} is returned. + +It also formats the vector names so that they can be correctly converted to +numeric using \code{as.numeric()}. +} +\details{ +The name format is a character of the value of the percentile. +Numbers with decimal places should have the decimal point in the name. For +example the 5th and 95th percentile can be given as + +\if{html}{\out{<div class="sourceCode r">}}\preformatted{.get_percentiles(c("5" = 1, "95" = 10)) +}\if{html}{\out{</div>}} + +or the 2.5th and 97.5th percentile can be given as + +\if{html}{\out{<div class="sourceCode r">}}\preformatted{.get_percentiles(c("2.5" = 1, "97.5" = 10)) +}\if{html}{\out{</div>}} +} +\keyword{internal} diff --git a/man/dot-get_sym_percentiles.Rd b/man/dot-get_sym_percentiles.Rd new file mode 100644 index 000000000..5367cef91 --- /dev/null +++ b/man/dot-get_sym_percentiles.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_percentiles.R +\name{.get_sym_percentiles} +\alias{.get_sym_percentiles} +\title{Get the lower and upper percentiles with a preference for symmetrical +percentiles} +\usage{ +.get_sym_percentiles(percentiles) +} +\arguments{ +\item{percentiles}{A named vector of percentiles. The names are in the +correct format to be converted to their numeric value using \code{as.numeric()}.} +} +\value{ +A named \code{numeric} vector of two elements with the lower +(first element) and upper (second element) percentiles. +} +\description{ +Get the lower and upper percentiles with a preference for symmetrical +percentiles +} +\keyword{internal} diff --git a/man/dot-is_epireview.Rd b/man/dot-is_epireview.Rd new file mode 100644 index 000000000..fc0c27c22 --- /dev/null +++ b/man/dot-is_epireview.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{.is_epireview} +\alias{.is_epireview} +\title{Check if \verb{<data.frame>} input is from \pkg{epireview}} +\usage{ +.is_epireview(x) +} +\arguments{ +\item{x}{A \verb{<data.frame>}.} +} +\value{ +A single \code{logical} boolean. +} +\description{ +Check if \verb{<data.frame>} input is from \pkg{epireview} +} +\keyword{internal} diff --git a/man/epidist_db.Rd b/man/epidist_db.Rd new file mode 100644 index 000000000..0e350132f --- /dev/null +++ b/man/epidist_db.Rd @@ -0,0 +1,76 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter_db.R +\name{epidist_db} +\alias{epidist_db} +\title{Create \verb{<epiparameter>} object(s) directly from the epiparameter library +(database)} +\usage{ +epidist_db( + disease = "all", + pathogen = "all", + epi_name = "all", + author = NULL, + subset = NULL, + single_epiparameter = FALSE +) +} +\arguments{ +\item{disease}{A \code{character} string specifying the disease.} + +\item{pathogen}{A \code{character} string specifying the pathogen.} + +\item{epi_name}{A \code{character} string specifying the epidemiological +parameter. See details for full list of epidemiological distributions.} + +\item{author}{A \code{character} string specifying the author of the study +reporting the distribution. Only the first author will be matched. It is +recommended to use the family name as first names may or may not be +initialised.} + +\item{subset}{Either \code{NULL} or a valid R expressions that evaluates to +logicals to subset the list of \verb{<epiparameter>}, or a function that can be +applied over a list of \verb{<epiparameter>} objects. + +Subsetting (using \code{subset}) can be combined with the subsetting done with +the \code{disease} and \code{epi_name} arguments (and \code{author} if specified). If left +as \code{NULL} (default) no subsetting is carried out. + +The \code{subset} argument is similar to subsetting a \verb{<data.frame>}, but the +difference is that fixed comparisons and not vectorised comparisons are +needed. For example \code{sample_size > 10} is a valid subset expression, but +\code{sample_size == max(sample_size)}, which would be a valid subset expression +for a \verb{<data.frame>} does not work. The vectorised expression will often +not error, but will likely return unexpected results. For the +\code{sample_size == max(sample_size)} example it will always return \code{TRUE} +(except for \code{NA}s) as it is a single numeric so will be equal to it's +max value. + +The expression should be specified without using the data object name +(e.g. \code{df$var}) and instead just \code{var} should be supplied. In +other words, this argument uses non-standard evaluation, just as the +\code{subset} argument in \code{\link[=subset]{subset()}}, and is similar to \verb{<data-masking>} used +by the \code{dplyr} package.} + +\item{single_epiparameter}{A boolean \code{logical} determining whether a single +\verb{<epiparameter>} or multiple entries from the library can be returned if +matched by the other arguments (\code{disease}, \code{epi_name}, \code{author}). This +argument is used to prevent multiple sets of parameters being returned +when only one is wanted. + +\strong{Note}: If multiple entries match the arguments supplied and +\code{single_epiparameter = TRUE} then the \verb{<epiparameter>} that is parameterised +(and accounts for truncation if available) and has the largest sample size +will be returned (see \code{\link[=is_parameterised]{is_parameterised()}}). If multiple entries are equal +after this sorting the first entry will be returned.} +} +\value{ +An \verb{<epiparameter>} object or list of \verb{<epiparameter>} objects. +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} + +\code{epidist_db()} has been renamed \code{\link[=epiparameter_db]{epiparameter_db()}}. Please use +\code{epiparameter_db()} instead as the \code{epidist_db()} alias will be removed from +the package in the future. +} +\keyword{internal} diff --git a/man/epiparameter-package.Rd b/man/epiparameter-package.Rd new file mode 100644 index 000000000..27a4a6174 --- /dev/null +++ b/man/epiparameter-package.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-package.R +\docType{package} +\name{epiparameter-package} +\alias{epiparameter-package} +\title{epiparameter: Library of Epidemiological Parameters with Helper Functions and Classes} +\description{ +\if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} + +Library of epidemiological parameters for infectious diseases and a set of classes and helper functions. +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://github.com/epiverse-trace/epiparameter/} + \item \url{https://epiverse-trace.github.io/epiparameter/} + \item Report bugs at \url{https://github.com/epiverse-trace/epiparameter/issues} +} + +} +\author{ +\strong{Maintainer}: Joshua W. Lambert \email{joshua.lambert@lshtm.ac.uk} (\href{https://orcid.org/0000-0001-5218-3046}{ORCID}) [copyright holder] + +Authors: +\itemize{ + \item Adam Kucharski \email{adam.kucharski@lshtm.ac.uk} (\href{https://orcid.org/0000-0001-8814-9421}{ORCID}) [copyright holder] + \item Carmen Tamayo \email{carmen.tamayo-cuartero@lshtm.ac.uk} (\href{https://orcid.org/0000-0003-4184-2864}{ORCID}) +} + +Other contributors: +\itemize{ + \item Hugo Gruson \email{hugo.gruson@data.org} (\href{https://orcid.org/0000-0002-4094-1476}{ORCID}) [contributor, reviewer] + \item Sebastian Funk \email{sebastian.funk@lshtm.ac.uk} (\href{https://orcid.org/0000-0002-2842-3406}{ORCID}) [contributor] + \item Pratik Gupte \email{pratik.gupte@lshtm.ac.uk} (\href{https://orcid.org/0000-0001-5294-7819}{ORCID}) [reviewer] +} + +} +\keyword{internal} diff --git a/man/epiparameter.Rd b/man/epiparameter.Rd new file mode 100644 index 000000000..34aff5554 --- /dev/null +++ b/man/epiparameter.Rd @@ -0,0 +1,174 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{epiparameter} +\alias{epiparameter} +\title{Create an \verb{<epiparameter>} object} +\usage{ +epiparameter( + disease, + pathogen = NA_character_, + epi_name, + prob_distribution = create_prob_distribution(prob_distribution = NA_character_), + uncertainty = create_uncertainty(), + summary_stats = create_summary_stats(), + citation = create_citation(), + metadata = create_metadata(), + method_assess = create_method_assess(), + notes = NULL, + auto_calc_params = TRUE, + ... +) +} +\arguments{ +\item{disease}{A \code{character} string with name of the infectious disease.} + +\item{pathogen}{A \code{character} string with the name of the causative agent of +disease, or \code{NA} if not known.} + +\item{epi_name}{A \code{character} string with the name of the +epidemiological parameter type.} + +\item{prob_distribution}{An S3 class containing the probability +distribution or a character string if the parameters of the probability +distribution are unknown but the name of the distribution is known, or \code{NA} +if the distribution name and parameters are unknown. Use +\code{\link[=create_prob_distribution]{create_prob_distribution()}} to create \code{prob_distribution}.} + +\item{uncertainty}{A list of named vectors with the uncertainty around +the probability distribution parameters. If uncertainty around the parameter +estimates is unknown use \code{\link[=create_uncertainty]{create_uncertainty()}} (which is the +argument default) to create a list with the correct names with missing +values.} + +\item{summary_stats}{A list of summary statistics, use +\code{\link[=create_summary_stats]{create_summary_stats()}} to create list. This list can include +summary statistics about the inferred distribution such as it's mean and +standard deviation, quantiles of the distribution, or information about the +data used to fit the distribution such as lower and upper range. The summary +statistics can also include uncertainty around metrics such as confidence +interval around mean and standard deviation.} + +\item{citation}{A \verb{<bibentry>} with the citation of the source of the +data or the paper that inferred the distribution parameters, use +\code{\link[=create_citation]{create_citation()}} to create citation.} + +\item{metadata}{A list of metadata, this can include: units, sample size, +the transmission mode of the disease (e.g. is it vector-borne or directly +transmitted), etc. It is assumed that the disease is not +vector-borne and that the distribution is intrinsic (e.g. not an extrinsic +delay distribution such as extrinsic incubation period) unless +\code{transmission_mode = "vector_borne"} is contained in the metadata. Use +\code{\link[=create_metadata]{create_metadata()}} to create metadata.} + +\item{method_assess}{A list of methodological aspects used when fitting +the distribution, use \code{\link[=create_method_assess]{create_method_assess()}} to create method +assessment.} + +\item{notes}{A \code{character} string with any additional information about the +data, inference method or disease.} + +\item{auto_calc_params}{A boolean \code{logical} determining whether to try and +calculate the probability distribution parameters from summary statistics if +distribution parameters are not provided. Default is \code{TRUE}. In the case when +sufficient summary statistics are provided and the parameter(s) of the +distribution are not, the \code{\link[=.calc_dist_params]{.calc_dist_params()}} function is called to +calculate the parameters and add them to the \code{epiparameter} object created.} + +\item{...}{\link{dots} Extra arguments to be passed to internal functions. + +This is most commonly used to pass arguments to \code{\link[distcrete:distcrete]{distcrete::distcrete()}} +that construct the discretised distribution S3 object. To see which +arguments can be adjusted for discretised distributions see +\code{\link[distcrete:distcrete]{distcrete::distcrete()}}.} +} +\value{ +An \verb{<epiparameter>} object. +} +\description{ +The \verb{<epiparameter>} class is used to store epidemiological +parameters for a single disease. These epidemiological parameters cover a +variety of aspects including delay distributions (e.g. incubation periods +and serial intervals, among others) and offspring distributions. + +The \verb{<epiparameter>} object is the functional unit provided by +\code{{epiparameter}} to plug into epidemiological pipelines. Obtaining an +\verb{<epiparameter>} object can be achieved in two main ways: +\enumerate{ +\item The epidemiological distribution is stored in +the \code{{epiparameter}} library and can be accessed by \code{\link[=epiparameter_db]{epiparameter_db()}}. +\item The alternative method is when you have information +(e.g. disease and distribution parameter estimates) and would like to input +this into an \verb{<epiparameter>} object in order to work in existing analysis +pipelines. This is where the \code{epiparameter()} function can be used to fill +out each field for which information is known. +} +} +\details{ +Accepted \verb{<epiparameter>} distribution parameterisations are: +\itemize{ +\item Gamma must be either 'shape' and 'scale' or 'shape' and 'rate' +\item Weibull must be 'shape' and 'scale' +\item Lognormal must be 'meanlog' and 'sdlog' or 'mu' and 'sigma' +\item Negative Binomial must be either 'mean' and 'dispersion' or 'n' and 'p' +\item Geometric must be either 'mean' or 'prob' +\item Poisson must be 'mean' +} +} +\examples{ +# minimal input required for `epiparameter` +ebola_incubation <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) + +# minimal input required for discrete `epiparameter` +ebola_incubation <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) +) + +# example with more fields filled in +ebola_incubation <- epiparameter( + disease = "ebola", + pathogen = "ebola_virus", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ), + uncertainty = list( + shape = create_uncertainty(), + scale = create_uncertainty() + ), + summary_stats = create_summary_stats(mean = 2, sd = 1), + citation = create_citation( + author = person(given = "John", family = "Smith"), + year = 2002, + title = "COVID-19 incubation period", + journal = "Epi Journal", + doi = "10.19832/j.1366-9516.2012.09147.x" + ), + metadata = create_metadata( + units = "days", + sample_size = 10, + region = "UK", + transmission_mode = "natural_human_to_human", + inference_method = "MLE" + ), + method_assess = create_method_assess( + censored = TRUE + ), + notes = "No notes" +) +} diff --git a/man/epiparameter_db.Rd b/man/epiparameter_db.Rd new file mode 100644 index 000000000..331857cf2 --- /dev/null +++ b/man/epiparameter_db.Rd @@ -0,0 +1,131 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter_db.R +\name{epiparameter_db} +\alias{epiparameter_db} +\title{Create \verb{<epiparameter>} object(s) directly from the epiparameter library +(database)} +\usage{ +epiparameter_db( + disease = "all", + pathogen = "all", + epi_name = "all", + author = NULL, + subset = NULL, + single_epiparameter = FALSE +) +} +\arguments{ +\item{disease}{A \code{character} string specifying the disease.} + +\item{pathogen}{A \code{character} string specifying the pathogen.} + +\item{epi_name}{A \code{character} string specifying the epidemiological +parameter. See details for full list of epidemiological distributions.} + +\item{author}{A \code{character} string specifying the author of the study +reporting the distribution. Only the first author will be matched. It is +recommended to use the family name as first names may or may not be +initialised.} + +\item{subset}{Either \code{NULL} or a valid R expressions that evaluates to +logicals to subset the list of \verb{<epiparameter>}, or a function that can be +applied over a list of \verb{<epiparameter>} objects. + +Subsetting (using \code{subset}) can be combined with the subsetting done with +the \code{disease} and \code{epi_name} arguments (and \code{author} if specified). If left +as \code{NULL} (default) no subsetting is carried out. + +The \code{subset} argument is similar to subsetting a \verb{<data.frame>}, but the +difference is that fixed comparisons and not vectorised comparisons are +needed. For example \code{sample_size > 10} is a valid subset expression, but +\code{sample_size == max(sample_size)}, which would be a valid subset expression +for a \verb{<data.frame>} does not work. The vectorised expression will often +not error, but will likely return unexpected results. For the +\code{sample_size == max(sample_size)} example it will always return \code{TRUE} +(except for \code{NA}s) as it is a single numeric so will be equal to it's +max value. + +The expression should be specified without using the data object name +(e.g. \code{df$var}) and instead just \code{var} should be supplied. In +other words, this argument uses non-standard evaluation, just as the +\code{subset} argument in \code{\link[=subset]{subset()}}, and is similar to \verb{<data-masking>} used +by the \code{dplyr} package.} + +\item{single_epiparameter}{A boolean \code{logical} determining whether a single +\verb{<epiparameter>} or multiple entries from the library can be returned if +matched by the other arguments (\code{disease}, \code{epi_name}, \code{author}). This +argument is used to prevent multiple sets of parameters being returned +when only one is wanted. + +\strong{Note}: If multiple entries match the arguments supplied and +\code{single_epiparameter = TRUE} then the \verb{<epiparameter>} that is parameterised +(and accounts for truncation if available) and has the largest sample size +will be returned (see \code{\link[=is_parameterised]{is_parameterised()}}). If multiple entries are equal +after this sorting the first entry will be returned.} +} +\value{ +An \verb{<epiparameter>} object or list of \verb{<epiparameter>} objects. +} +\description{ +Extract \verb{<epiparameter>} object(s) directly from +the library of epidemiological parameters. The epiparameter +library of epidemiological parameters is compiled from primary literature +sources. The list output from \code{\link[=epiparameter_db]{epiparameter_db()}} can be subset by the data +it contains, for example by: disease, pathogen, epidemiological distribution, +sample size, region, etc. + +If a distribution from a specific study is required, the \code{author} argument +can be specified. + +Multiple entries (\verb{<epiparameter>} objects) can be returned, use the +arguments to subset entries and use \code{single_epiparameter = TRUE} to force a +single \verb{<epiparameter>} to be returned. +} +\details{ +\code{disease}, \code{epi_name} and \code{author} are given as individual arguments +as these are the most common variables to subset the parameter library by. +The \code{subset} argument facilitates all other subsetting of rows to select the +\verb{<epiparameter>} object(s) desired. To subset based on multiple variables +separate each expression with \code{&}. + +List of epidemiological parameters: +\itemize{ +\item "all" (default, returns all entries in library) +\item "incubation period" +\item "onset to hospitalisation" +\item "onset to death" +\item "serial interval" +\item "generation time" +\item "offspring distribution" +\item "hospitalisation to death" +\item "hospitalisation to discharge" +\item "notification to death" +\item "notification to discharge" +\item "onset to discharge" +\item "onset to ventilation" +} +} +\examples{ +epiparameter_db(disease = "influenza", epi_name = "serial_interval") + +# example using custom subsetting +eparam <- epiparameter_db( + disease = "SARS", + epi_name = "offspring_distribution", + subset = sample_size > 40 +) + +# example using functional subsetting +eparam <- epiparameter_db( + disease = "COVID-19", + epi_name = "incubation_period", + subset = is_parameterised +) + +# example forcing a single <epiparameter> to be returned +eparam <- epiparameter_db( + disease = "SARS", + epi_name = "offspring_distribution", + single_epiparameter = TRUE +) +} diff --git a/man/epiparameter_distribution_functions.Rd b/man/epiparameter_distribution_functions.Rd new file mode 100644 index 000000000..c8a2df989 --- /dev/null +++ b/man/epiparameter_distribution_functions.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{epiparameter_distribution_functions} +\alias{epiparameter_distribution_functions} +\alias{density.epiparameter} +\alias{cdf.epiparameter} +\alias{quantile.epiparameter} +\alias{generate.epiparameter} +\title{PDF, CDF, PMF, quantiles and random number generation for \verb{<epiparameter>} +objects} +\usage{ +\method{density}{epiparameter}(x, at, ...) + +\method{cdf}{epiparameter}(x, q, ..., log = FALSE) + +\method{quantile}{epiparameter}(x, p, ...) + +\method{generate}{epiparameter}(x, times, ...) +} +\arguments{ +\item{x}{An \verb{<epiparameter>} object.} + +\item{at}{The quantiles to evaluate at.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} + +\item{q}{The quantiles to evaluate at.} + +\item{log}{If \code{TRUE}, probabilities will be given as log probabilities.} + +\item{p}{The probabilities to evaluate at.} + +\item{times}{The number of random samples.} +} +\value{ +\code{numeric} vector. +} +\description{ +The \verb{<epiparameter>} object holds a probability distribution +which can either be a continuous or discrete distribution. These are the +density, cumulative distribution, quantile and random number generation +functions. These operate on any distribution that can be included in an +\verb{<epiparameter>} object. +} +\examples{ +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) + +# example of each distribution method for an `epiparameter` object +stats::density(ep, at = 1) +distributional::cdf(ep, q = 1) +stats::quantile(ep, p = 0.2) +distributional::generate(ep, times = 10) +} +\keyword{epiparameter_distribution_functions} diff --git a/man/epiparameter_options.Rd b/man/epiparameter_options.Rd new file mode 100644 index 000000000..c41efd21d --- /dev/null +++ b/man/epiparameter_options.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/options.R +\docType{data} +\name{epiparameter_options} +\alias{epiparameter_options} +\title{Package options} +\format{ +An object of class \code{list} of length 2. +} +\usage{ +epiparameter_options +} +\description{ +Options to modify the printing of \pkg{epiparameter} objects. +Currently options are only used to modify the printing of the +\verb{<multi_epiparameter>} class. +} +\details{ +Options are set with \code{\link[=options]{options()}} and retrieved with \code{\link[=getOption]{getOption()}}. + +If options are changed the \pkg{epiparameter} package will need to be +reloaded for new options to be taken into account. Options can be set in +the \code{.Rprofile} to persist across R sessions. +} +\keyword{datasets} diff --git a/man/epireview_core_cols.Rd b/man/epireview_core_cols.Rd new file mode 100644 index 000000000..170ffaf88 --- /dev/null +++ b/man/epireview_core_cols.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/data.R +\docType{data} +\name{epireview_core_cols} +\alias{epireview_core_cols} +\title{A vector of \code{character} strings with the core column names of the +epidemiological parameter data exported by the \pkg{epireview} R package.} +\format{ +\subsection{\code{epireview_core_cols}}{ + +A \code{character} vector with 56 elements + +The data is taken as the intersection of the column names of each of the +disease parameter tables in the \pkg{epireview} R package. +} +} +\source{ +\url{https://github.com/mrc-ide/epireview} +} +\usage{ +epireview_core_cols +} +\description{ +A subset of data from the World Health Organization Global Tuberculosis +Report ... +} +\keyword{datasets} diff --git a/man/extract_param.Rd b/man/extract_param.Rd new file mode 100644 index 000000000..6fdc765e3 --- /dev/null +++ b/man/extract_param.Rd @@ -0,0 +1,89 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/extract_param.R +\name{extract_param} +\alias{extract_param} +\title{Calculate the parameters of a parametric probability distribution from +reported values of percentiles, or median and range} +\usage{ +extract_param( + type = c("percentiles", "range"), + values, + distribution = c("lnorm", "gamma", "weibull", "norm"), + percentiles, + samples, + control = list(max_iter = 1000, tolerance = 1e-05) +) +} +\arguments{ +\item{type}{A \code{character} defining whether summary statistics based +around \code{percentiles} (default) or \code{range}.} + +\item{values}{A \code{vector}. If \code{type = percentiles}: \code{c(percentile_1, percentile_2)}; and if \code{type = range}: \code{c(median, min, max)}.} + +\item{distribution}{A \code{character} specifying distribution to use. +Default is \code{lnorm}; also takes \code{gamma}, \code{weibull} and \code{norm}.} + +\item{percentiles}{A \code{vector} with two elements specifying the +percentiles defined in \code{values} if using \code{type = "percentiles"}. +Percentiles should be specified between 0 and 1. For example 2.5th and 97.5th +percentile is given as \code{c(0.025, 0.975)}.} + +\item{samples}{A \code{numeric} specifying the sample size if using +\code{type = "range"}.} + +\item{control}{A named list containing options for the optimisation. List +element \verb{$max_iter} is a \code{numeric} specifying the maximum number of times +the parameter extraction will run optimisation before returning result early. +This prevents overly long optimisation loops if optimisation is unstable and +does not converge over multiple iterations. Default is 1000 iterations. List +element \verb{$tolerance} is passed to \code{\link[=.check_optim_conv]{.check_optim_conv()}} for tolerance on +parameter convergence over iterations of optimisation. Elements of in the +control list are not passed to \code{\link[=optim]{optim()}}.} +} +\value{ +A named \code{numeric} vector with the parameter values of the +distribution. If the \code{distribution = lnorm} then the parameters returned are +the meanlog and sdlog; if the \code{distribution = gamma} or \code{distribution = weibull} then the parameters returned are the shape and scale; if +\code{distribution = norm} then the parameters returned are mean and sd. +} +\description{ +Summary data of distributions, as provided by reports and meta-analyses, can +be used to extract the parameters of a chosen distribution. Currently +available distributions are: lognormal, gamma, Weibull and normal. +Extracting from a lognormal returns the meanlog and sdlog parameters, +extracting from the gamma and Weibull returns the shape and scale parameters, +and extracting from the normal returns the mean and sd parameters. +} +\details{ +For \code{gamma}, \code{lnorm} and \code{weibull}, \code{extract_param()} works only +for strictly positive values at the percentiles of a distribution or the +median and range of data (numerics supplied to the \code{values} argument). +This means that negative values at the lower percentile or lower range +will not work with this function although they may present themselves in +epidemiological data (e.g. negative serial interval). For the \code{norm} +distribution negative values are allowed. +} +\examples{ +# set seed to control for stochasticity +set.seed(1) + +# extract parameters of a lognormal distribution from the 75 percentiles +extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "lnorm", + percentiles = c(0.125, 0.875) +) + +# extract parameters of a gamma distribution from median and range +extract_param( + type = "range", + values = c(10, 3, 18), + distribution = "gamma", + samples = 20 +) +} +\author{ +Adam Kucharski, Joshua W. Lambert +} +\keyword{extract} diff --git a/man/extraction_functions.Rd b/man/extraction_functions.Rd new file mode 100644 index 000000000..0a21cac29 --- /dev/null +++ b/man/extraction_functions.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/extract_param.R +\name{extraction_functions} +\alias{extraction_functions} +\alias{.fit_range} +\alias{.fit_percentiles} +\title{Function for extracting distribution parameters} +\usage{ +.fit_range(param, val, dist = c("lnorm", "gamma", "weibull", "norm")) + +.fit_percentiles(param, val, dist = c("lnorm", "gamma", "weibull", "norm")) +} +\arguments{ +\item{param}{Named \code{numeric} vector of the distribution parameters to be +optimised.} + +\item{val}{\code{Numeric} vector, in the case of using percentiles it contains +the values at the percentiles and the percentiles, in the case of median and +range it contains the median, lower range, upper range and the number of +sample points to evaluate the function at.} + +\item{dist}{A \code{character} string with the name of the distribution for +fitting. Naming follows the base R distribution names (e.g. \code{lnorm} for +lognormal).} +} +\description{ +Set of functions that can be used to estimate the parameters of a +distribution (lognormal, gamma, Weibull, normal) via optimisation from +either the percentiles or the median and ranges. +} +\author{ +Adam Kucharski, Joshua W. Lambert +} +\keyword{internal} diff --git a/man/family.epiparameter.Rd b/man/family.epiparameter.Rd new file mode 100644 index 000000000..872b2e615 --- /dev/null +++ b/man/family.epiparameter.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{family.epiparameter} +\alias{family.epiparameter} +\title{Family method for the \verb{<epiparameter>} class} +\usage{ +\method{family}{epiparameter}(object, ...) +} +\arguments{ +\item{object}{An \verb{<epiparameter>} object.} + +\item{...}{further arguments passed to methods.} +} +\value{ +A character string with the name of the distribution, or \code{NA} when +the \verb{<epiparameter>} object is unparameterised. +} +\description{ +The \code{\link[=family]{family()}} function is used to extract the distribution +names from objects from \code{{distributional}} and \code{{distcrete}}. This method +provides the same interface for \verb{<epiparameter>} objects to give consistent +output irrespective of the internal distribution class. +} +\examples{ +# example with continuous distribution +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) +family(ep) + +# example with discretised distribution +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1), + discretise = TRUE + ) +) +family(ep) +} diff --git a/man/figures/README-plot-epidist-1.png b/man/figures/README-plot-epidist-1.png new file mode 100644 index 000000000..8ecf8afcf Binary files /dev/null and b/man/figures/README-plot-epidist-1.png differ diff --git a/man/figures/README-plot-epidist-cdf-1.png b/man/figures/README-plot-epidist-cdf-1.png new file mode 100644 index 000000000..0c0b224da Binary files /dev/null and b/man/figures/README-plot-epidist-cdf-1.png differ diff --git a/man/figures/README-plot-epiparameter-1.png b/man/figures/README-plot-epiparameter-1.png new file mode 100644 index 000000000..8ecf8afcf Binary files /dev/null and b/man/figures/README-plot-epiparameter-1.png differ diff --git a/man/figures/README-plot-epiparameter-cdf-1.png b/man/figures/README-plot-epiparameter-cdf-1.png new file mode 100644 index 000000000..0c0b224da Binary files /dev/null and b/man/figures/README-plot-epiparameter-cdf-1.png differ diff --git a/man/figures/lifecycle-archived.svg b/man/figures/lifecycle-archived.svg new file mode 100644 index 000000000..745ab0c78 --- /dev/null +++ b/man/figures/lifecycle-archived.svg @@ -0,0 +1,21 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="112" height="20" role="img" aria-label="lifecycle: archived"> + <title>lifecycle: archived + + + + + + + + + + + + + + + lifecycle + + archived + + diff --git a/man/figures/lifecycle-defunct.svg b/man/figures/lifecycle-defunct.svg new file mode 100644 index 000000000..d5c9559ed --- /dev/null +++ b/man/figures/lifecycle-defunct.svg @@ -0,0 +1,21 @@ + + lifecycle: defunct + + + + + + + + + + + + + + + lifecycle + + defunct + + diff --git a/man/figures/lifecycle-deprecated.svg b/man/figures/lifecycle-deprecated.svg new file mode 100644 index 000000000..b61c57c3f --- /dev/null +++ b/man/figures/lifecycle-deprecated.svg @@ -0,0 +1,21 @@ + + lifecycle: deprecated + + + + + + + + + + + + + + + lifecycle + + deprecated + + diff --git a/man/figures/lifecycle-experimental.svg b/man/figures/lifecycle-experimental.svg new file mode 100644 index 000000000..5d88fc2c6 --- /dev/null +++ b/man/figures/lifecycle-experimental.svg @@ -0,0 +1,21 @@ + + lifecycle: experimental + + + + + + + + + + + + + + + lifecycle + + experimental + + diff --git a/man/figures/lifecycle-maturing.svg b/man/figures/lifecycle-maturing.svg new file mode 100644 index 000000000..897370ecf --- /dev/null +++ b/man/figures/lifecycle-maturing.svg @@ -0,0 +1,21 @@ + + lifecycle: maturing + + + + + + + + + + + + + + + lifecycle + + maturing + + diff --git a/man/figures/lifecycle-questioning.svg b/man/figures/lifecycle-questioning.svg new file mode 100644 index 000000000..7c1721d05 --- /dev/null +++ b/man/figures/lifecycle-questioning.svg @@ -0,0 +1,21 @@ + + lifecycle: questioning + + + + + + + + + + + + + + + lifecycle + + questioning + + diff --git a/man/figures/lifecycle-soft-deprecated.svg b/man/figures/lifecycle-soft-deprecated.svg new file mode 100644 index 000000000..9c166ff30 --- /dev/null +++ b/man/figures/lifecycle-soft-deprecated.svg @@ -0,0 +1,21 @@ + + lifecycle: soft-deprecated + + + + + + + + + + + + + + + lifecycle + + soft-deprecated + + diff --git a/man/figures/lifecycle-stable.svg b/man/figures/lifecycle-stable.svg new file mode 100644 index 000000000..9bf21e76b --- /dev/null +++ b/man/figures/lifecycle-stable.svg @@ -0,0 +1,29 @@ + + lifecycle: stable + + + + + + + + + + + + + + + + lifecycle + + + + stable + + + diff --git a/man/figures/lifecycle-superseded.svg b/man/figures/lifecycle-superseded.svg new file mode 100644 index 000000000..db8d757f7 --- /dev/null +++ b/man/figures/lifecycle-superseded.svg @@ -0,0 +1,21 @@ + + lifecycle: superseded + + + + + + + + + + + + + + + lifecycle + + superseded + + diff --git a/man/figures/logo.png b/man/figures/logo.png new file mode 100644 index 000000000..004f98eca Binary files /dev/null and b/man/figures/logo.png differ diff --git a/man/format.epiparameter.Rd b/man/format.epiparameter.Rd new file mode 100644 index 000000000..8f7377baa --- /dev/null +++ b/man/format.epiparameter.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{format.epiparameter} +\alias{format.epiparameter} +\title{Format method for \verb{} class} +\usage{ +\method{format}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \verb{} object.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\value{ +Invisibly returns an \verb{}. Called for printing +side-effects. +} +\description{ +Format method for \verb{} class +} +\examples{ +epiparameter <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) +format(epiparameter) +} diff --git a/man/get_citation.Rd b/man/get_citation.Rd new file mode 100644 index 000000000..29ec07eb2 --- /dev/null +++ b/man/get_citation.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{get_citation} +\alias{get_citation} +\title{Get citation from an object} +\usage{ +get_citation(x, ...) +} +\arguments{ +\item{x}{an object used to select a method.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\description{ +Extract the citation stored in an \R object. +} diff --git a/man/get_citation.epiparameter.Rd b/man/get_citation.epiparameter.Rd new file mode 100644 index 000000000..22b01a255 --- /dev/null +++ b/man/get_citation.epiparameter.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{get_citation.epiparameter} +\alias{get_citation.epiparameter} +\title{Get citation from an \verb{} object} +\usage{ +\method{get_citation}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \verb{} object.} + +\item{...}{\link{dots} Not used, extra arguments supplied will cause a warning.} +} +\value{ +A \verb{} object. +} +\description{ +Extract the citation stored in an \verb{} object. +} +\examples{ +# example with +ep <- epiparameter_db(single_epiparameter = TRUE) +get_citation(ep) + +# example returning bibtex format +ep <- epiparameter_db(disease = "COVID-19", single_epiparameter = TRUE) +cit <- get_citation(ep) +format(cit, style = "bibtex") +} diff --git a/man/get_citation.multi_epiparameter.Rd b/man/get_citation.multi_epiparameter.Rd new file mode 100644 index 000000000..689e29e3c --- /dev/null +++ b/man/get_citation.multi_epiparameter.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{get_citation.multi_epiparameter} +\alias{get_citation.multi_epiparameter} +\title{Get citation from a list of \verb{} objects} +\usage{ +\method{get_citation}{multi_epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \verb{} object.} + +\item{...}{\link{dots} Not used, extra arguments supplied will cause a warning.} +} +\value{ +A \verb{} object containing multiple references. The length of +output \verb{} is equal to the length of the list of \verb{} +objects supplied. +} +\description{ +Extract the citation stored in a list of \verb{} objects. +} +\examples{ +# example with list of +db <- epiparameter_db() +get_citation(db) +} diff --git a/man/get_parameters.Rd b/man/get_parameters.Rd new file mode 100644 index 000000000..729b8032c --- /dev/null +++ b/man/get_parameters.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{get_parameters} +\alias{get_parameters} +\title{Get parameters from an object} +\usage{ +get_parameters(x, ...) +} +\arguments{ +\item{x}{an object used to select a method.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\description{ +Extract the parameters stored in an \R object. +} diff --git a/man/get_parameters.epiparameter.Rd b/man/get_parameters.epiparameter.Rd new file mode 100644 index 000000000..74cd68912 --- /dev/null +++ b/man/get_parameters.epiparameter.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{get_parameters.epiparameter} +\alias{get_parameters.epiparameter} +\title{Get parameters from an \verb{} object} +\usage{ +\method{get_parameters}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \verb{} object.} + +\item{...}{\link{dots} Not used, extra arguments supplied will cause a warning.} +} +\value{ +A named vector of parameters or \code{NA} when the \verb{} +object is unparameterised. +} +\description{ +Extract the parameters of the distribution stored in an \verb{} +object. +} +\details{ +The \verb{} object can be unparameterised in which it lacks +a probability distribution or parameters of a probability distribution, +in this case the \code{get_parameters.epiparameter()} method will return \code{NA}. +} +\examples{ +ep <- epiparameter_db( + disease = "COVID-19", + epi_name = "serial interval", + single_epiparameter = TRUE +) +get_parameters(ep) +} diff --git a/man/is_continuous.Rd b/man/is_continuous.Rd new file mode 100644 index 000000000..f7f0ec764 --- /dev/null +++ b/man/is_continuous.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{is_continuous} +\alias{is_continuous} +\title{Check if distribution in \verb{} is continuous} +\usage{ +is_continuous(x) +} +\arguments{ +\item{x}{An \verb{} object.} +} +\value{ +A boolean \code{logical}. +} +\description{ +Check if distribution in \verb{} is continuous +} +\details{ +The \verb{} class can hold \verb{} and +\verb{} probability distribution objects from the \pkg{distributional} +package and the \pkg{distcrete} package, respectively. \verb{} +objects can be continuous or discrete distributions (e.g. gamma or negative +binomial), and all \verb{} objects are discrete. +} +\examples{ +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ) +) +is_continuous(ep) +is_continuous(discretise(ep)) + +ep <- epiparameter( + disease = "ebola", + epi_name = "offspring distribution", + prob_distribution = create_prob_distribution( + prob_distribution = "nbinom", + prob_distribution_params = c(mean = 2, dispersion = 0.5) + ) +) +is_continuous(ep) +} diff --git a/man/is_epiparameter.Rd b/man/is_epiparameter.Rd new file mode 100644 index 000000000..a3b6ef61d --- /dev/null +++ b/man/is_epiparameter.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{is_epiparameter} +\alias{is_epiparameter} +\title{Check object is an \verb{}} +\usage{ +is_epiparameter(x) +} +\arguments{ +\item{x}{An \R object.} +} +\value{ +A boolean logical, \code{TRUE} if the object is an \verb{} +and \code{FALSE} if not. +} +\description{ +Check object is an \verb{} +} +\examples{ +ep <- epiparameter( + disease = "ebola", + epi_name = "serial_interval", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) + +is_epiparameter(ep) + +false_ep <- list( + disease = "ebola", + epi_name = "serial_interval", + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) +) + +is_epiparameter(false_ep) +} diff --git a/man/is_epiparameter_df.Rd b/man/is_epiparameter_df.Rd new file mode 100644 index 000000000..c64cdef38 --- /dev/null +++ b/man/is_epiparameter_df.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/coercion.R +\name{is_epiparameter_df} +\alias{is_epiparameter_df} +\title{Check if \verb{} input is from \code{\link[=as.data.frame.epiparameter]{as.data.frame.epiparameter()}}} +\usage{ +is_epiparameter_df(x) +} +\arguments{ +\item{x}{A \verb{}.} +} +\value{ +A single \code{logical} boolean. +} +\description{ +Check if \verb{} input is from \code{\link[=as.data.frame.epiparameter]{as.data.frame.epiparameter()}} +} +\keyword{internal} diff --git a/man/is_epiparameter_params.Rd b/man/is_epiparameter_params.Rd new file mode 100644 index 000000000..817607b10 --- /dev/null +++ b/man/is_epiparameter_params.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter-utils.R +\name{is_epiparameter_params} +\alias{is_epiparameter_params} +\title{Check whether the vector of parameters for the probability distribution +are in the set of possible parameters used in the epiparameter package} +\usage{ +is_epiparameter_params(prob_distribution, prob_distribution_params) +} +\arguments{ +\item{prob_distribution}{A \code{character} string specifying the probability +distribution. This should match the \R naming convention of probability +distributions (e.g. lognormal is \code{lnorm}, negative binomial is \code{nbinom}, and +geometric is \code{geom}).} + +\item{prob_distribution_params}{A named vector of probability distribution +parameters.} +} +\value{ +A boolean \code{logical}. +} +\description{ +Check whether the vector of parameters for the probability distribution +are in the set of possible parameters used in the epiparameter package +} +\details{ +This check for valid parameters is independent of whether the distribution +is truncated or discretised. +} +\examples{ +is_epiparameter_params( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 2, scale = 1) +) +} diff --git a/man/is_parameterised.Rd b/man/is_parameterised.Rd new file mode 100644 index 000000000..cc802e902 --- /dev/null +++ b/man/is_parameterised.Rd @@ -0,0 +1,51 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/checkers.R +\name{is_parameterised} +\alias{is_parameterised} +\alias{is_parameterized} +\title{Check if \verb{} or list of \verb{} objects contains a +distribution and distribution parameters} +\usage{ +is_parameterised(x, ...) + +is_parameterized(x, ...) +} +\arguments{ +\item{x}{An \verb{} or list of \verb{} objects.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\value{ +A single boolean \code{logical} for \verb{} or vector of +\code{logical}s equal in length to the list of \verb{} objects input. +If the \verb{} object is missing either a probability distribution +or parameters for the probability distribution returns \code{FALSE}, otherwise it +returns \code{TRUE}. +} +\description{ +Check if \verb{} or list of \verb{} objects contains a +distribution and distribution parameters +} +\examples{ +# parameterised +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) +is_parameterised(ep) + +# unparameterised +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation" +) +is_parameterised(ep) + +# list of +db <- epiparameter_db() +is_parameterised(db) +} diff --git a/man/is_truncated.Rd b/man/is_truncated.Rd new file mode 100644 index 000000000..b20dd08e6 --- /dev/null +++ b/man/is_truncated.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{is_truncated} +\alias{is_truncated} +\title{Check if distribution in \verb{} is truncated} +\usage{ +is_truncated(x) +} +\arguments{ +\item{x}{An \verb{} object.} +} +\value{ +A boolean \code{logical}. +} +\description{ +Check if distribution in \verb{} is truncated +} +\details{ +The \verb{} class can hold probability distribution objects +from the \code{{distributional}} package or the \code{{distcrete}} package, +however, only distribution objects from \code{{distributional}} can be truncated. +If a \verb{} object has a \verb{} object \code{is_truncated} will +return \code{FALSE} by default. +} +\examples{ +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ) +) +is_truncated(ep) + +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1), + truncation = 10 + ) +) +is_truncated(ep) +} diff --git a/man/mean.epiparameter.Rd b/man/mean.epiparameter.Rd new file mode 100644 index 000000000..98b6f8a66 --- /dev/null +++ b/man/mean.epiparameter.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{mean.epiparameter} +\alias{mean.epiparameter} +\title{Mean method for \verb{} class} +\usage{ +\method{mean}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \verb{} object.} + +\item{...}{\link{dots} Not used, extra arguments supplied will cause a warning.} +} +\value{ +A \code{numeric} mean of a distribution or \code{NA}. +} +\description{ +Mean method for \verb{} class +} +\examples{ +ep <- epiparameter_db( + disease = "COVID-19", + epi_name = "incubation period", + single_epiparameter = TRUE +) +mean(ep) +} diff --git a/man/new_epiparameter.Rd b/man/new_epiparameter.Rd new file mode 100644 index 000000000..57d166223 --- /dev/null +++ b/man/new_epiparameter.Rd @@ -0,0 +1,97 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{new_epiparameter} +\alias{new_epiparameter} +\title{Constructor for \verb{} class} +\usage{ +new_epiparameter( + disease = character(), + pathogen = character(), + epi_name = character(), + prob_distribution = list(), + uncertainty = list(), + summary_stats = list(), + citation = character(), + metadata = list(), + method_assess = list(), + notes = character(), + auto_calc_params = logical(), + ... +) +} +\arguments{ +\item{disease}{A \code{character} string with name of the infectious disease.} + +\item{pathogen}{A \code{character} string with the name of the causative agent of +disease, or \code{NA} if not known.} + +\item{epi_name}{A \code{character} string with the name of the +epidemiological parameter type.} + +\item{prob_distribution}{An S3 class containing the probability +distribution or a character string if the parameters of the probability +distribution are unknown but the name of the distribution is known, or \code{NA} +if the distribution name and parameters are unknown. Use +\code{\link[=create_prob_distribution]{create_prob_distribution()}} to create \code{prob_distribution}.} + +\item{uncertainty}{A list of named vectors with the uncertainty around +the probability distribution parameters. If uncertainty around the parameter +estimates is unknown use \code{\link[=create_uncertainty]{create_uncertainty()}} (which is the +argument default) to create a list with the correct names with missing +values.} + +\item{summary_stats}{A list of summary statistics, use +\code{\link[=create_summary_stats]{create_summary_stats()}} to create list. This list can include +summary statistics about the inferred distribution such as it's mean and +standard deviation, quantiles of the distribution, or information about the +data used to fit the distribution such as lower and upper range. The summary +statistics can also include uncertainty around metrics such as confidence +interval around mean and standard deviation.} + +\item{citation}{A \verb{} with the citation of the source of the +data or the paper that inferred the distribution parameters, use +\code{\link[=create_citation]{create_citation()}} to create citation.} + +\item{metadata}{A list of metadata, this can include: units, sample size, +the transmission mode of the disease (e.g. is it vector-borne or directly +transmitted), etc. It is assumed that the disease is not +vector-borne and that the distribution is intrinsic (e.g. not an extrinsic +delay distribution such as extrinsic incubation period) unless +\code{transmission_mode = "vector_borne"} is contained in the metadata. Use +\code{\link[=create_metadata]{create_metadata()}} to create metadata.} + +\item{method_assess}{A list of methodological aspects used when fitting +the distribution, use \code{\link[=create_method_assess]{create_method_assess()}} to create method +assessment.} + +\item{notes}{A \code{character} string with any additional information about the +data, inference method or disease.} + +\item{auto_calc_params}{A boolean \code{logical} determining whether to try and +calculate the probability distribution parameters from summary statistics if +distribution parameters are not provided. Default is \code{TRUE}. In the case when +sufficient summary statistics are provided and the parameter(s) of the +distribution are not, the \code{\link[=.calc_dist_params]{.calc_dist_params()}} function is called to +calculate the parameters and add them to the \code{epiparameter} object created.} + +\item{...}{\link{dots} Extra arguments to be passed to internal functions. + +This is most commonly used to pass arguments to \code{\link[distcrete:distcrete]{distcrete::distcrete()}} +that construct the discretised distribution S3 object. To see which +arguments can be adjusted for discretised distributions see +\code{\link[distcrete:distcrete]{distcrete::distcrete()}}.} +} +\value{ +An \verb{} object. +} +\description{ +Create an \verb{} object. The +constructor will search whether parameters of the probability distribution +are supplied and if not look to see whether they can be inferred/extracted/ +converted from summary statistics provided. It will also convert the +probability distribution (\code{prob_dist}) and its parameters +(\code{prob_dist_params}) into an S3 class, either a \code{distribution} object from +\code{{distributional}} when \code{discretise = FALSE}, or a \code{distcrete} object from +\code{{distcrete}} when \code{discretise = TRUE}. +} +\keyword{internal} diff --git a/man/parameter_tbl.Rd b/man/parameter_tbl.Rd new file mode 100644 index 000000000..bde1a4024 --- /dev/null +++ b/man/parameter_tbl.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/parameter_tbl.R +\name{parameter_tbl} +\alias{parameter_tbl} +\title{Table of epidemiological distributions} +\usage{ +parameter_tbl( + multi_epiparameter, + disease = "all", + pathogen = "all", + epi_name = "all" +) +} +\arguments{ +\item{multi_epiparameter}{Either an \verb{} object or a list of +\verb{} objects.} + +\item{disease}{A \code{character} string with name of the infectious disease.} + +\item{pathogen}{A \code{character} string with the name of the causative agent of +disease, or \code{NA} if not known.} + +\item{epi_name}{A \code{character} string with the name of the +epidemiological parameter type.} +} +\description{ +This function subsets the epidemiological parameter library to +return only the chosen epidemiological distribution. The results are +returned as a data frame containing the disease, epidemiological +distribution, probability distribution, author of the study, and the year +of publication. +} +\examples{ +epiparameter_list <- epiparameter_db(disease = "COVID-19") +parameter_tbl(multi_epiparameter = epiparameter_list) + +# example filtering an existing list to incubation periods +epiparameter_list <- epiparameter_db(disease = "COVID-19") +parameter_tbl( + multi_epiparameter = epiparameter_list, + epi_name = "incubation period" +) +} +\author{ +Joshua W. Lambert, Adam Kucharski +} diff --git a/man/plot.epiparameter.Rd b/man/plot.epiparameter.Rd new file mode 100644 index 000000000..6b07ce351 --- /dev/null +++ b/man/plot.epiparameter.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/plot.R +\name{plot.epiparameter} +\alias{plot.epiparameter} +\title{Plot method for \verb{} class} +\usage{ +\method{plot}{epiparameter}(x, cumulative = FALSE, ...) +} +\arguments{ +\item{x}{An \verb{} object.} + +\item{cumulative}{A boolean \code{logical}, default is \code{FALSE}. +\code{cumulative = TRUE} plots the cumulative distribution function (CDF).} + +\item{...}{further arguments passed to or from other methods.} +} +\description{ +Plot an \verb{} object by displaying the either the +probability mass function (PMF), (in the case of discrete distributions) +or probability density function (PDF) (in the case of continuous +distributions), or the cumulative distribution function (CDF). +} +\details{ +By default if the \code{xlim} argument is not specified the distribution is +plotted between day 0 and the 99th quantile of the distribution. +Alternatively, a \code{numeric} vector of length 2 with the +first and last day to plot on the x-axis can be supplied to \code{xlim} +(through \link{...}). +} +\examples{ +# plot continuous epiparameter +ep <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 2, scale = 1) + ) +) +plot(ep) + +# plot different day range (x-axis) +plot(ep, xlim = c(0, 10)) + +# plot CDF +plot(ep, cumulative = TRUE) + +# plot discrete epiparameter +ep <- discretise(ep) +plot(ep) +} +\author{ +Joshua W. Lambert +} diff --git a/man/print.epiparameter.Rd b/man/print.epiparameter.Rd new file mode 100644 index 000000000..e816f1bb6 --- /dev/null +++ b/man/print.epiparameter.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{print.epiparameter} +\alias{print.epiparameter} +\title{Print method for \verb{} class} +\usage{ +\method{print}{epiparameter}(x, ...) +} +\arguments{ +\item{x}{An \verb{} object.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} +} +\value{ +Invisibly returns an \verb{}. Called for side-effects. +} +\description{ +Print method for \verb{} class +} +\examples{ +epiparameter <- epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) +) +epiparameter +} diff --git a/man/print.multi_epiparameter.Rd b/man/print.multi_epiparameter.Rd new file mode 100644 index 000000000..06da7d81f --- /dev/null +++ b/man/print.multi_epiparameter.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/print.R +\name{print.multi_epiparameter} +\alias{print.multi_epiparameter} +\title{Print method for \verb{} class} +\usage{ +\method{print}{multi_epiparameter}(x, ..., n = NULL) +} +\arguments{ +\item{x}{A \verb{} object.} + +\item{...}{\link{dots} Extra arguments to be passed to the method.} + +\item{n}{A \code{numeric} specifying how many \verb{} objects to print. +This argument is passed to \code{\link[=head]{head()}} for \code{list} printing. Default is \code{NULL} +and the number of elements to print is controlled by package \code{\link[=options]{options()}}.} +} +\value{ +Invisibly returns a \verb{}. Called for side-effects. +} +\description{ +Print method for \verb{} class +} +\examples{ +# entire database +db <- epiparameter_db() +db + +# a single disease +db <- epiparameter_db(disease = "Ebola") +db + +# a single epi parameter +db <- epiparameter_db(epi_name = "offspring distribution") +db +} diff --git a/man/reexports.Rd b/man/reexports.Rd new file mode 100644 index 000000000..0d031136c --- /dev/null +++ b/man/reexports.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\docType{import} +\name{reexports} +\alias{reexports} +\alias{cdf} +\alias{generate} +\title{Objects exported from other packages} +\keyword{internal} +\description{ +These objects are imported from other packages. Follow the links +below to see their documentation. + +\describe{ + \item{distributional}{\code{\link[distributional]{cdf}}, \code{\link[distributional:reexports]{generate}}} +}} + diff --git a/man/test_epiparameter.Rd b/man/test_epiparameter.Rd new file mode 100644 index 000000000..205dcf014 --- /dev/null +++ b/man/test_epiparameter.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/epiparameter.R +\name{test_epiparameter} +\alias{test_epiparameter} +\title{Test whether an object is a valid \verb{} object} +\usage{ +test_epiparameter(x) +} +\arguments{ +\item{x}{An \R object.} +} +\value{ +A boolean \code{logical} whether the object is a valid \verb{} +object. +} +\description{ +Test whether an object is a valid \verb{} object +} diff --git a/pkgdown/favicon/apple-touch-icon-120x120.png b/pkgdown/favicon/apple-touch-icon-120x120.png new file mode 100644 index 000000000..45708fb09 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-120x120.png differ diff --git a/pkgdown/favicon/apple-touch-icon-152x152.png b/pkgdown/favicon/apple-touch-icon-152x152.png new file mode 100644 index 000000000..a66710e4f Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-152x152.png differ diff --git a/pkgdown/favicon/apple-touch-icon-180x180.png b/pkgdown/favicon/apple-touch-icon-180x180.png new file mode 100644 index 000000000..9a5668f81 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-180x180.png differ diff --git a/pkgdown/favicon/apple-touch-icon-60x60.png b/pkgdown/favicon/apple-touch-icon-60x60.png new file mode 100644 index 000000000..bf7ae6f5d Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-60x60.png differ diff --git a/pkgdown/favicon/apple-touch-icon-76x76.png b/pkgdown/favicon/apple-touch-icon-76x76.png new file mode 100644 index 000000000..7e5f002aa Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-76x76.png differ diff --git a/pkgdown/favicon/apple-touch-icon.png b/pkgdown/favicon/apple-touch-icon.png new file mode 100644 index 000000000..a5a9b4d85 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon.png differ diff --git a/pkgdown/favicon/favicon-16x16.png b/pkgdown/favicon/favicon-16x16.png new file mode 100644 index 000000000..8ec3344cd Binary files /dev/null and b/pkgdown/favicon/favicon-16x16.png differ diff --git a/pkgdown/favicon/favicon-32x32.png b/pkgdown/favicon/favicon-32x32.png new file mode 100644 index 000000000..f938ca2d0 Binary files /dev/null and b/pkgdown/favicon/favicon-32x32.png differ diff --git a/pkgdown/favicon/favicon.ico b/pkgdown/favicon/favicon.ico new file mode 100644 index 000000000..b38f61036 Binary files /dev/null and b/pkgdown/favicon/favicon.ico differ diff --git a/po/R-epiparameter.pot b/po/R-epiparameter.pot new file mode 100644 index 000000000..69b09bb6b --- /dev/null +++ b/po/R-epiparameter.pot @@ -0,0 +1,63 @@ +msgid "" +msgstr "" +"Project-Id-Version: epiparameter 0.2.0.9000\n" +"POT-Creation-Date: 2024-08-13 13:29+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: epiparameter.R:408 +msgid "Disease: %s" +msgstr "" + +#: epiparameter.R:409 +msgid "Pathogen: %s" +msgstr "" + +#: epiparameter.R:410 +msgid "Epi Distribution: %s" +msgstr "" + +#: epiparameter.R:411 +msgid "Study: %s" +msgstr "" + +#: epiparameter.R:418 +msgid "Distribution: discrete %s" +msgstr "" + +#: epiparameter.R:419 +msgid "Distribution: %s" +msgstr "" + +#: epiparameter.R:423 +msgid "Parameters: " +msgstr "" + +#: epiparameter.R:438 +msgid "Parameters:" +msgstr "" + +#: print.R:50 +msgid "List of {n_entries} object{?s}" +msgstr "" + +#: print.R:57 +msgid "Number of diseases:" +msgstr "" + +#: print.R:59 +msgid "Number of epi distributions:" +msgstr "" + +#: print.R:72 +msgid "%s more elements" +msgstr "" + +#: print.R:73 +msgid "Use `print(n = ...)` to see more elements." +msgstr "" diff --git a/tests/spelling.R b/tests/spelling.R new file mode 100644 index 000000000..647406c2d --- /dev/null +++ b/tests/spelling.R @@ -0,0 +1,7 @@ +if (requireNamespace("spelling", quietly = TRUE)) { + spelling::spell_check_test( + vignettes = TRUE, + error = TRUE, + skip_on_cran = TRUE + ) +} diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 000000000..66ec2bc7a --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,14 @@ +# This file is part of the standard setup for testthat. +# It is recommended that you do not modify it. +# +# Where should you do additional test configuration? +# Learn more about the roles of various files in: +# * https://r-pkgs.org/tests.html +# * https://testthat.r-lib.org/reference/test_package.html#special-files + +# nolint start +library(testthat) +library(epiparameter) +# nolint end + +test_check("epiparameter") diff --git a/tests/testthat/_snaps/convert_params.md b/tests/testthat/_snaps/convert_params.md new file mode 100644 index 000000000..4a9395fc4 --- /dev/null +++ b/tests/testthat/_snaps/convert_params.md @@ -0,0 +1,580 @@ +# convert_summary_stats_to_params.character works as expected + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["shape", "scale"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [4] + }, + { + "type": "double", + "attributes": {}, + "value": [0.25] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["shape", "scale"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [1.00001629] + }, + { + "type": "double", + "attributes": {}, + "value": [0.50000344] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["meanlog", "sdlog"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [-0.34657359] + }, + { + "type": "double", + "attributes": {}, + "value": [0.83255461] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["meanlog", "sdlog"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [1.60943791] + }, + { + "type": "double", + "attributes": {}, + "value": [0.69314718] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["prob", "dispersion"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [0.5] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["prob", "dispersion"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [0.44444444] + }, + { + "type": "double", + "attributes": {}, + "value": [0.8] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["prob"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [0.66666667] + } + ] + } + +# convert_summary_stats_to_params.epiparameter works as expected + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["meanlog", "sdlog"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [-0.34657359] + }, + { + "type": "double", + "attributes": {}, + "value": [0.83255461] + } + ] + } + +# convert_params_to_summary_stats.character works as expected + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [3.08021685] + }, + { + "type": "double", + "attributes": {}, + "value": [2.71828183] + }, + { + "type": "double", + "attributes": {}, + "value": [2.11700002] + }, + { + "type": "double", + "attributes": {}, + "value": [2.69475812] + }, + { + "type": "double", + "attributes": {}, + "value": [1.64157185] + }, + { + "type": "double", + "attributes": {}, + "value": [0.53294035] + }, + { + "type": "double", + "attributes": {}, + "value": [1.75018966] + }, + { + "type": "double", + "attributes": {}, + "value": [5.89844567] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [0] + }, + { + "type": "double", + "attributes": {}, + "value": [0] + }, + { + "type": "double", + "attributes": {}, + "value": [2] + }, + { + "type": "double", + "attributes": {}, + "value": [1.41421356] + }, + { + "type": "double", + "attributes": {}, + "value": [1.41421356] + }, + { + "type": "double", + "attributes": {}, + "value": [2.12132034] + }, + { + "type": "double", + "attributes": {}, + "value": [6.5] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [0.69314718] + }, + { + "type": "double", + "attributes": {}, + "value": [0] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [2] + }, + { + "type": "double", + "attributes": {}, + "value": [6] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [0.69314718] + }, + { + "type": "double", + "attributes": {}, + "value": [0] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [2] + }, + { + "type": "double", + "attributes": {}, + "value": [6] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [0] + }, + { + "type": "double", + "attributes": {}, + "value": [0] + }, + { + "type": "double", + "attributes": {}, + "value": [2] + }, + { + "type": "double", + "attributes": {}, + "value": [1.41421356] + }, + { + "type": "double", + "attributes": {}, + "value": [1.41421356] + }, + { + "type": "double", + "attributes": {}, + "value": [2.12132034] + }, + { + "type": "double", + "attributes": {}, + "value": [6.5] + } + ] + } + +# convert_params_to_summary_stats.epiparameter works as expected + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [4.48168907] + }, + { + "type": "double", + "attributes": {}, + "value": [2.71828183] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [34.51261311] + }, + { + "type": "double", + "attributes": {}, + "value": [5.87474366] + }, + { + "type": "double", + "attributes": {}, + "value": [1.31083249] + }, + { + "type": "double", + "attributes": {}, + "value": [6.18487714] + }, + { + "type": "double", + "attributes": {}, + "value": [110.93639218] + } + ] + } + +--- + + { + "type": "list", + "attributes": { + "names": { + "type": "character", + "attributes": {}, + "value": ["mean", "median", "mode", "var", "sd", "cv", "skewness", "ex_kurtosis"] + } + }, + "value": [ + { + "type": "double", + "attributes": {}, + "value": [4.48168907] + }, + { + "type": "double", + "attributes": {}, + "value": [2.71828183] + }, + { + "type": "double", + "attributes": {}, + "value": [1] + }, + { + "type": "double", + "attributes": {}, + "value": [34.51261311] + }, + { + "type": "double", + "attributes": {}, + "value": [5.87474366] + }, + { + "type": "double", + "attributes": {}, + "value": [1.31083249] + }, + { + "type": "double", + "attributes": {}, + "value": [6.18487714] + }, + { + "type": "double", + "attributes": {}, + "value": [110.93639218] + } + ] + } + diff --git a/tests/testthat/_snaps/epiparameter.md b/tests/testthat/_snaps/epiparameter.md new file mode 100644 index 000000000..d704a8ec9 --- /dev/null +++ b/tests/testthat/_snaps/epiparameter.md @@ -0,0 +1,35 @@ +# epiparameter.print works as expected + + Code + epiparameter(disease = "ebola", epi_name = "incubation", prob_distribution = create_prob_distribution( + prob_distribution = "gamma", prob_distribution_params = c(shape = 1, scale = 1))) + Message + Citation cannot be created as author, year, journal or title is missing + Output + Disease: ebola + Pathogen: NA + Epi Parameter: incubation + Study: (????). "No citation." + Distribution: gamma + Parameters: + shape: 1.000 + scale: 1.000 + +--- + + Code + epiparameter(disease = "ebola", epi_name = "incubation", prob_distribution = create_prob_distribution( + prob_distribution = "gamma", prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE)) + Message + Citation cannot be created as author, year, journal or title is missing + Output + Disease: ebola + Pathogen: NA + Epi Parameter: incubation + Study: (????). "No citation." + Distribution: discrete gamma + Parameters: + shape: 1.000 + scale: 1.000 + diff --git a/tests/testthat/_snaps/epiparameter/epiparameter-plot-non-default-range.svg b/tests/testthat/_snaps/epiparameter/epiparameter-plot-non-default-range.svg new file mode 100644 index 000000000..4f16c78aa --- /dev/null +++ b/tests/testthat/_snaps/epiparameter/epiparameter-plot-non-default-range.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +5 +10 +15 +20 + + + + + + + +0.0 +0.2 +0.4 +0.6 +0.8 +1.0 + +Probability Density Function +Incubation + + + + diff --git a/tests/testthat/_snaps/epiparameter/epiparameter-plot-units.svg b/tests/testthat/_snaps/epiparameter/epiparameter-plot-units.svg new file mode 100644 index 000000000..56acbbdae --- /dev/null +++ b/tests/testthat/_snaps/epiparameter/epiparameter-plot-units.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +1 +2 +3 +4 + + + + + + + +0.0 +0.2 +0.4 +0.6 +0.8 +1.0 + +Probability Density Function +Incubation (Days) + + + + diff --git a/tests/testthat/_snaps/epiparameter/epiparameter-plot.svg b/tests/testthat/_snaps/epiparameter/epiparameter-plot.svg new file mode 100644 index 000000000..bdbd1e2e6 --- /dev/null +++ b/tests/testthat/_snaps/epiparameter/epiparameter-plot.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +1 +2 +3 +4 + + + + + + + +0.0 +0.2 +0.4 +0.6 +0.8 +1.0 + +Probability Density Function +Incubation + + + + diff --git a/tests/testthat/_snaps/parameter_tbl.md b/tests/testthat/_snaps/parameter_tbl.md new file mode 100644 index 000000000..251b2a2f2 --- /dev/null +++ b/tests/testthat/_snaps/parameter_tbl.md @@ -0,0 +1,180 @@ +# parameter_tbl works as expected supplied with db + + Code + dist_tbl + Output + # Parameter table: + # A data frame: 125 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 Adenovirus Adenovi~ incubat~ lnorm Lessl~ 2009 14 + 2 Human Coronavir~ Human_C~ incubat~ lnorm Lessl~ 2009 13 + 3 SARS SARS-Co~ incubat~ lnorm Lessl~ 2009 157 + 4 Influenza Influen~ incubat~ lnorm Lessl~ 2009 151 + 5 Influenza Influen~ incubat~ lnorm Lessl~ 2009 90 + 6 Influenza Influen~ incubat~ lnorm Lessl~ 2009 78 + 7 Measles Measles~ incubat~ lnorm Lessl~ 2009 55 + 8 Parainfluenza Parainf~ incubat~ lnorm Lessl~ 2009 11 + 9 RSV RSV incubat~ lnorm Lessl~ 2009 24 + 10 Rhinovirus Rhinovi~ incubat~ lnorm Lessl~ 2009 28 + # i 115 more rows + +# parameter_tbl works for incubation period with db + + Code + incub_tbl + Output + # Parameter table: + # A data frame: 73 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 Adenovirus Adenovi~ incubat~ lnorm Lessl~ 2009 14 + 2 Human Coronavir~ Human_C~ incubat~ lnorm Lessl~ 2009 13 + 3 SARS SARS-Co~ incubat~ lnorm Lessl~ 2009 157 + 4 Influenza Influen~ incubat~ lnorm Lessl~ 2009 151 + 5 Influenza Influen~ incubat~ lnorm Lessl~ 2009 90 + 6 Influenza Influen~ incubat~ lnorm Lessl~ 2009 78 + 7 Measles Measles~ incubat~ lnorm Lessl~ 2009 55 + 8 Parainfluenza Parainf~ incubat~ lnorm Lessl~ 2009 11 + 9 RSV RSV incubat~ lnorm Lessl~ 2009 24 + 10 Rhinovirus Rhinovi~ incubat~ lnorm Lessl~ 2009 28 + # i 63 more rows + +# parameter_tbl works for different distribution with db + + Code + serial_tbl + Output + # Parameter table: + # A data frame: 18 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 Influenza Influen~ serial ~ gamma Ghani~ 2009 58 + 2 Marburg Virus D~ Marburg~ serial ~ Pavlin 2014 38 + 3 Marburg Virus D~ Marburg~ serial ~ gamma Ajell~ 2012 374 + 4 Mpox Mpox Vi~ serial ~ gamma Madew~ 2022 57 + 5 Mpox Mpox Vi~ serial ~ gamma Madew~ 2022 40 + 6 Ebola Virus Dis~ Ebola V~ serial ~ gamma WHO E~ 2015 305 + 7 Ebola Virus Dis~ Ebola V~ serial ~ gamma WHO E~ 2015 37 + 8 Ebola Virus Dis~ Ebola V~ serial ~ gamma WHO E~ 2015 147 + 9 Ebola Virus Dis~ Ebola V~ serial ~ gamma WHO E~ 2015 112 + 10 MERS MERS-Cov serial ~ lnorm Assir~ 2013 23 + 11 MERS MERS-Cov serial ~ gamma Cowli~ 2015 99 + 12 COVID-19 SARS-Co~ serial ~ Alene~ 2021 3924 + 13 COVID-19 SARS-Co~ serial ~ lnorm Nishi~ 2020 28 + 14 COVID-19 SARS-Co~ serial ~ weibull Nishi~ 2020 18 + 15 COVID-19 SARS-Co~ serial ~ norm Yang ~ 2020 131 + 16 Mpox Mpox Vi~ serial ~ gamma Guo e~ 2022 42 + 17 Mpox Mpox Vi~ serial ~ Wang ~ 2022 16 + 18 Mpox Mpox Vi~ serial ~ Wang ~ 2022 34 + +# parameter_tbl works for COVID-19 db + + Code + incub_tbl + Output + # Parameter table: + # A data frame: 27 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 COVID-19 SARS-CoV-2 incubation pe~ Men e~ 2020 59 + 2 COVID-19 SARS-CoV-2 incubation pe~ Rai e~ 2022 6241 + 3 COVID-19 SARS-CoV-2 incubation pe~ Alene~ 2021 1453 + 4 COVID-19 SARS-CoV-2 serial interv~ Alene~ 2021 3924 + 5 COVID-19 SARS-CoV-2 serial interv~ lnorm Nishi~ 2020 28 + 6 COVID-19 SARS-CoV-2 serial interv~ weibull Nishi~ 2020 18 + 7 COVID-19 SARS-CoV-2 incubation pe~ weibull Yang ~ 2020 178 + 8 COVID-19 SARS-CoV-2 serial interv~ norm Yang ~ 2020 131 + 9 COVID-19 SARS-CoV-2 incubation pe~ Elias~ 2021 28675 + 10 COVID-19 SARS-CoV-2 incubation pe~ weibull Bui e~ 2020 19 + # i 17 more rows + +# parameter_tbl works for SARS-CoV-2 db + + Code + incub_tbl + Output + # Parameter table: + # A data frame: 27 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 COVID-19 SARS-CoV-2 incubation pe~ Men e~ 2020 59 + 2 COVID-19 SARS-CoV-2 incubation pe~ Rai e~ 2022 6241 + 3 COVID-19 SARS-CoV-2 incubation pe~ Alene~ 2021 1453 + 4 COVID-19 SARS-CoV-2 serial interv~ Alene~ 2021 3924 + 5 COVID-19 SARS-CoV-2 serial interv~ lnorm Nishi~ 2020 28 + 6 COVID-19 SARS-CoV-2 serial interv~ weibull Nishi~ 2020 18 + 7 COVID-19 SARS-CoV-2 incubation pe~ weibull Yang ~ 2020 178 + 8 COVID-19 SARS-CoV-2 serial interv~ norm Yang ~ 2020 131 + 9 COVID-19 SARS-CoV-2 incubation pe~ Elias~ 2021 28675 + 10 COVID-19 SARS-CoV-2 incubation pe~ weibull Bui e~ 2020 19 + # i 17 more rows + +# parameter_tbl works for disease & epi_name subset with db + + Code + incub_tbl + Output + # Parameter table: + # A data frame: 15 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 COVID-19 SARS-CoV-2 incubation pe~ Men e~ 2020 59 + 2 COVID-19 SARS-CoV-2 incubation pe~ Rai e~ 2022 6241 + 3 COVID-19 SARS-CoV-2 incubation pe~ Alene~ 2021 1453 + 4 COVID-19 SARS-CoV-2 incubation pe~ weibull Yang ~ 2020 178 + 5 COVID-19 SARS-CoV-2 incubation pe~ Elias~ 2021 28675 + 6 COVID-19 SARS-CoV-2 incubation pe~ weibull Bui e~ 2020 19 + 7 COVID-19 SARS-CoV-2 incubation pe~ lnorm McAlo~ 2020 1357 + 8 COVID-19 SARS-CoV-2 incubation pe~ lnorm McAlo~ 2020 1269 + 9 COVID-19 SARS-CoV-2 incubation pe~ lnorm Linto~ 2020 52 + 10 COVID-19 SARS-CoV-2 incubation pe~ lnorm Linto~ 2020 158 + 11 COVID-19 SARS-CoV-2 incubation pe~ lnorm Linto~ 2020 52 + 12 COVID-19 SARS-CoV-2 incubation pe~ lnorm Lauer~ 2020 181 + 13 COVID-19 SARS-CoV-2 incubation pe~ lnorm Lauer~ 2020 99 + 14 COVID-19 SARS-CoV-2 incubation pe~ lnorm Lauer~ 2020 108 + 15 COVID-19 SARS-CoV-2 incubation pe~ lnorm Lauer~ 2020 73 + +# parameter_tbl works when supplied a subset db + + Code + covid_tbl + Output + # Parameter table: + # A data frame: 27 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 COVID-19 SARS-CoV-2 incubation pe~ Men e~ 2020 59 + 2 COVID-19 SARS-CoV-2 incubation pe~ Rai e~ 2022 6241 + 3 COVID-19 SARS-CoV-2 incubation pe~ Alene~ 2021 1453 + 4 COVID-19 SARS-CoV-2 serial interv~ Alene~ 2021 3924 + 5 COVID-19 SARS-CoV-2 serial interv~ lnorm Nishi~ 2020 28 + 6 COVID-19 SARS-CoV-2 serial interv~ weibull Nishi~ 2020 18 + 7 COVID-19 SARS-CoV-2 incubation pe~ weibull Yang ~ 2020 178 + 8 COVID-19 SARS-CoV-2 serial interv~ norm Yang ~ 2020 131 + 9 COVID-19 SARS-CoV-2 incubation pe~ Elias~ 2021 28675 + 10 COVID-19 SARS-CoV-2 incubation pe~ weibull Bui e~ 2020 19 + # i 17 more rows + +# parameter_tbl works as expected supplied with + + Code + dist_tbl + Output + # Parameter table: + # A data frame: 1 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 COVID-19 SARS-CoV-2 onset to hospi~ lnorm Linto~ 2020 155 + +# parameter_tbl works as expected with discretised + + Code + dist_tbl + Output + # Parameter table: + # A data frame: 1 x 7 + disease pathogen epi_name prob_distribution author year sample_size + + 1 Ebola serial interval gamma Smith 2022 NA + diff --git a/tests/testthat/_snaps/print.md b/tests/testthat/_snaps/print.md new file mode 100644 index 000000000..61c3488c4 --- /dev/null +++ b/tests/testthat/_snaps/print.md @@ -0,0 +1,102 @@ +# epiparameter_db print method works as expected for > 5 + + Code + epiparameter_db() + Message + Returning 125 results that match the criteria (100 are parameterised). + Use subset to filter by entry variables or single_epiparameter to return a single entry. + To retrieve the citation for each use the 'get_citation' function + Output + # List of 125 objects + Number of diseases: 23 + > Adenovirus > COVID-19 > Chikungunya > Dengue > Ebola Virus Disease > Hantavirus Pulmonary Syndrome > Human Coronavirus > Influenza > Japanese Encephalitis > MERS > Marburg Virus Disease > Measles > Mpox > Parainfluenza > Pneumonic Plague > RSV > Rhinovirus > Rift Valley Fever > SARS > Smallpox > West Nile Fever > Yellow Fever > Zika Virus Disease + Number of epi parameters: 13 + > case fatality risk > generation time > hospitalisation to death > hospitalisation to discharge > incubation period > notification to death > notification to discharge > offspring distribution > onset to death > onset to discharge > onset to hospitalisation > onset to ventilation > serial interval + [[1]] + Disease: Adenovirus + Pathogen: Adenovirus + Epi Parameter: incubation period + Study: Lessler J, Reich N, Brookmeyer R, Perl T, Nelson K, Cummings D (2009). + "Incubation periods of acute respiratory viral infections: a systematic + review." _The Lancet Infectious Diseases_. + doi:10.1016/S1473-3099(09)70069-6 + . + Distribution: lnorm + Parameters: + meanlog: 1.723 + sdlog: 0.231 + + [[2]] + Disease: Human Coronavirus + Pathogen: Human_Cov + Epi Parameter: incubation period + Study: Lessler J, Reich N, Brookmeyer R, Perl T, Nelson K, Cummings D (2009). + "Incubation periods of acute respiratory viral infections: a systematic + review." _The Lancet Infectious Diseases_. + doi:10.1016/S1473-3099(09)70069-7 + . + Distribution: lnorm + Parameters: + meanlog: 1.163 + sdlog: 0.140 + + [[3]] + Disease: SARS + Pathogen: SARS-Cov-1 + Epi Parameter: incubation period + Study: Lessler J, Reich N, Brookmeyer R, Perl T, Nelson K, Cummings D (2009). + "Incubation periods of acute respiratory viral infections: a systematic + review." _The Lancet Infectious Diseases_. + doi:10.1016/S1473-3099(09)70069-8 + . + Distribution: lnorm + Parameters: + meanlog: 1.386 + sdlog: 0.593 + + # i 122 more elements + # i Use `print(n = ...)` to see more elements. + # i Use `parameter_tbl()` to see a summary table of the parameters. + # i Explore database online at: https://epiverse-trace.github.io/epiparameter/articles/database.html + +# epiparameter_db print method works as expected for <= 5 + + Code + epiparameter_db(disease = "SARS", epi_name = "offspring distribution") + Message + Returning 2 results that match the criteria (2 are parameterised). + Use subset to filter by entry variables or single_epiparameter to return a single entry. + To retrieve the citation for each use the 'get_citation' function + Output + # List of 2 objects + Number of diseases: 1 + > SARS + Number of epi parameters: 1 + > offspring distribution + [[1]] + Disease: SARS + Pathogen: SARS-Cov-1 + Epi Parameter: offspring distribution + Study: Lloyd-Smith J, Schreiber S, Kopp P, Getz W (2005). "Superspreading and + the effect of individual variation on disease emergence." _Nature_. + doi:10.1038/nature04153 . + Distribution: nbinom + Parameters: + mean: 1.630 + dispersion: 0.160 + + [[2]] + Disease: SARS + Pathogen: SARS-Cov-1 + Epi Parameter: offspring distribution + Study: Lloyd-Smith J, Schreiber S, Kopp P, Getz W (2005). "Superspreading and + the effect of individual variation on disease emergence." _Nature_. + doi:10.1038/nature04153 . + Distribution: nbinom + Parameters: + mean: 0.940 + dispersion: 0.170 + + # i Use `parameter_tbl()` to see a summary table of the parameters. + # i Explore database online at: https://epiverse-trace.github.io/epiparameter/articles/database.html + diff --git a/tests/testthat/helper-state.R b/tests/testthat/helper-state.R new file mode 100644 index 000000000..4910faa6e --- /dev/null +++ b/tests/testthat/helper-state.R @@ -0,0 +1,26 @@ +# This helper ensures the package does not modify the session global state. As +# per CRAN policy, packages should not interfere with the user's session state. +# If global settings need to be modified, they should be restored to their +# original values on exit. This can be achieved with the `on.exit()` base +# function, or more conveniently with the `withr` package. +# We add a test on R >= 4.0.0 because some functions such as +# `globalCallingHandlers()` did not exist before. +if (getRversion() >= "4.0.0") { + testthat::set_state_inspector(function() { + list( + attached = search(), + connections = getAllConnections(), + cwd = getwd(), + envvars = Sys.getenv(), + handlers = globalCallingHandlers(), + libpaths = .libPaths(), + locale = Sys.getlocale(), + options = options(), + par = par(), + packages = .packages(all.available = TRUE), + sink = sink.number(), + timezone = Sys.timezone(), + NULL + ) + }) +} diff --git a/tests/testthat/setup-options.R b/tests/testthat/setup-options.R new file mode 100644 index 000000000..4ca3f1c05 --- /dev/null +++ b/tests/testthat/setup-options.R @@ -0,0 +1,7 @@ +# We want to flag partial matching as part of our testing & continuous +# integration process because it makes code more brittle. +options( + warnPartialMatchAttr = TRUE, + warnPartialMatchDollar = TRUE, + warnPartialMatchArgs = TRUE +) diff --git a/tests/testthat/test-accessors.R b/tests/testthat/test-accessors.R new file mode 100644 index 000000000..f92b0c114 --- /dev/null +++ b/tests/testthat/test-accessors.R @@ -0,0 +1,154 @@ +test_that("get_parameters works as expected for epiparameter from db", { + # suppress message about return + ep <- suppressMessages(epiparameter_db(disease = "SARS", single_epiparameter = TRUE)) + params <- get_parameters(ep) + expect_vector(params, ptype = numeric(1), size = 2) + expect_named(params, c("meanlog", "sdlog")) +}) + +test_that("get_parameters works as expected for unparameterised epiparameter", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation period", + prob_distribution = create_prob_distribution(prob_distribution = "gamma") + ) + ) + expect_true(is.na(get_parameters(ep))) +}) + +test_that("get_parameters works as expected for continuous epiparameter", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + params <- get_parameters(ep) + expect_vector(params, ptype = numeric(1), size = 2) + expect_named(params, c("shape", "scale")) +}) + +test_that("get_parameters works as expected for discretised epiparameter", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + params <- get_parameters(ep) + expect_vector(params, ptype = numeric(1), size = 2) + expect_named(params, c("shape", "scale")) +}) + +test_that("get_citation works as expected for epiparameter from db", { + # suppress message about return + db <- suppressMessages(epiparameter_db()) + citation <- get_citation(db) + expect_type(citation, "list") + expect_length(citation, length(db)) +}) + +test_that("get_citation works as expected for one entry from db", { + ep <- suppressMessages(epiparameter_db(single_epiparameter = TRUE)) + citation <- get_citation(ep) + expect_s3_class(citation, "bibentry") +}) + +test_that("get_citation works as expected for manual epiparameter", { + # suppress message about citation + ep <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ), + citation = create_citation( + author = person(given = "John F.", family = "Smith"), + year = 2000, + title = "Incubation period of COVID", + journal = "Journal of Epi", + doi = "10.19832/j.1366-9516.2012.09147.x" + ) + ) + ) + expect_s3_class(get_citation(ep), "bibentry") +}) + +test_that("get_citation works as expected for epiparameter missing citation", { + # suppress message about citation + ep <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + citation <- get_citation(ep) + expect_s3_class(citation, "bibentry") + expect_null(citation$year) + expect_identical(citation$title, "No citation") +}) + +test_that("get_citation works as expected for non-bibentry citation", { + # suppress message about citation + ep <- suppressMessages( + epiparameter_db(single_epiparameter = TRUE) + ) + ep$citation <- "WHO-Ebola-Response-Team (2015) NEJM" + expect_error(get_citation(ep), regexp = "Citation should be a ") +}) + +test_that("get_citation produces warnings with extra arguments", { + # suppress message about citation + ep <- suppressMessages( + epiparameter_db(single_epiparameter = TRUE) + ) + expect_warning( + get_citation(ep, extra_arg = "args"), + regexp = "(extra argument)*(will be disregarded)" + ) +}) + +test_that(".get_mixture_family works as expected", { + ebola_si <- suppressMessages( + epiparameter_db(disease = "Ebola", epi_name = "serial interval") + ) + ep <- aggregate(ebola_si) + expect_identical( + .get_mixture_family(ep), + rep("gamma", times = length(ebola_si)) + ) + incub <- suppressMessages( + epiparameter_db( + epi_name = "incubation period", + subset = is_parameterised + ) + ) + incub <- suppressMessages( + epiparameter_db( + disease = "Mpox", + epi_name = "incubation period", + subset = is_parameterised + ) + ) + ep <- aggregate(incub) + expect_identical( + .get_mixture_family(ep), + c(rep("lnorm", 2), "gamma", rep("lnorm", 2)) + ) +}) diff --git a/tests/testthat/test-aggregate.R b/tests/testthat/test-aggregate.R new file mode 100644 index 000000000..750bb944a --- /dev/null +++ b/tests/testthat/test-aggregate.R @@ -0,0 +1,101 @@ +{ + suppressMessages( + ebola_si <- epiparameter_db(epi_name = "serial interval", disease = "ebola") + ) +} + +test_that("aggregate works as expected", { + ep <- aggregate(ebola_si) + expect_s3_class(ep, class = "epiparameter") + expect_identical(family(ep), "mixture") + expect_identical(length(ep$citation), length(ebola_si)) +}) + +test_that("aggregate works as expected with sample size weights", { + ep <- aggregate(ebola_si, weighting = "sample_size") + expect_s3_class(ep, class = "epiparameter") + expect_identical(family(ep), "mixture") + expect_identical(length(ep$citation), length(ebola_si)) +}) + +test_that("aggregate works as expected with custom weights", { + ep <- aggregate( + ebola_si, + weighting = "custom", + weights = c(0.1, 0.2, 0.3, 0.4) + ) + expect_s3_class(ep, class = "epiparameter") + expect_identical(family(ep), "mixture") + expect_identical(length(ep$citation), length(ebola_si)) +}) + +test_that("aggregate works as expected for different distributions", { + incub <- suppressMessages( + epiparameter_db( + disease = "Mpox", + epi_name = "incubation period", + subset = is_parameterised + ) + ) + ep <- aggregate(incub) + expect_s3_class(ep, class = "epiparameter") + expect_identical(family(ep), "mixture") + expect_identical(length(ep$citation), length(incub)) +}) + +test_that("aggregate warns when dropping NA sample size", { + ebola_si[[1]]$metadata$sample_size <- NA + ebola_si[[2]]$metadata$sample_size <- NA + expect_warning( + aggregate(ebola_si, weighting = "sample_size"), + regexp = "(Input distribution)*(WHO)*(has been dropped)*(sample size)") +}) + +test_that("aggregate fails as expected for multiple diseases", { + ebola_si[[1]]$disease <- "marburg" + expect_error( + aggregate(ebola_si), + regexp = "All s in x must contain the same disease" + ) +}) + +test_that("aggregate fails as expected for multiple pathogens", { + ebola_si[[1]]$pathogen <- "marburg virus" + expect_error( + aggregate(ebola_si), + regexp = "All s in x must contain the same pathogen" + ) +}) + +test_that("aggregate fails as expected for multiple epi_names", { + ebola_si[[1]]$epi_name <- "generation time" + expect_error( + aggregate(ebola_si), + regexp = "All s in x must contain the same type of epi_name" + ) +}) + +test_that("aggregate fails as expected with unparameterised ", { + incub <- suppressMessages( + epiparameter_db(disease = "MERS", epi_name = "incubation period") + ) + expect_error( + aggregate(incub), + regexp = "(aggregate() requires all objects)*(parameterised)" + ) +}) + +test_that("aggregate fails as expected for with discretised ", { + ebola_si[[1]] <- discretise(ebola_si[[1]]) + expect_error( + aggregate(ebola_si), + regexp = "(`aggregate()` only works with distributions)*(not discretised)" + ) +}) + +test_that("aggregate fails as expected with custom weighting without weights", { + expect_error( + aggregate(ebola_si, weighting = "custom"), + regexp = "(weights)*(required for each distribution)*(weighting = custom)" + ) +}) diff --git a/tests/testthat/test-calc_dist_params.R b/tests/testthat/test-calc_dist_params.R new file mode 100644 index 000000000..5b9187b69 --- /dev/null +++ b/tests/testthat/test-calc_dist_params.R @@ -0,0 +1,93 @@ +test_that(".calc_dist_params works as expected converting from mean and sd", { + params <- .calc_dist_params( + prob_distribution = "gamma", + summary_stats = create_summary_stats(mean = 5, sd = 2), + sample_size = NA + ) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("shape", "scale")) +}) + +test_that(".calc_dist_params works as expected converting for different dist", { + params <- .calc_dist_params( + prob_distribution = "lnorm", + summary_stats = create_summary_stats(mean = 5, sd = 2), + sample_size = NA + ) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("meanlog", "sdlog")) +}) + +test_that(".calc_dist_params works as expected extracting from percentiles", { + # messages for numerical optimisation suppressed + params <- suppressMessages(.calc_dist_params( + prob_distribution = "gamma", + summary_stats = create_summary_stats( + quantiles = c("25" = 10, "75" = 20) + ), + sample_size = NA + )) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("shape", "scale")) + + # messages for numerical optimisation suppressed + params <- suppressMessages(.calc_dist_params( + prob_distribution = "lnorm", + summary_stats = create_summary_stats( + quantiles = c("25" = 10, "75" = 20) + ), + sample_size = NA + )) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("meanlog", "sdlog")) +}) + +test_that(".calc_dist_params works as expected extracting from median & range", { + # messages for numerical optimisation suppressed + params <- suppressMessages(.calc_dist_params( + prob_distribution = "gamma", + summary_stats = create_summary_stats( + median = 10, + lower_range = 5, + upper_range = 15 + ), + sample_size = 25 + )) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("shape", "scale")) +}) + +test_that(".calc_dist_params fails as expected extracting without sample size", { + expect_message( + params <- .calc_dist_params( + prob_distribution = "gamma", + summary_stats = create_summary_stats( + median = 10, + lower_range = 5, + upper_range = 15 + ), + sample_size = NA + ), + regexp = "(No adequate summary statistics available)" + ) + + expect_true(is.na(params)) +}) + +test_that(".calc_dist_params messages as expected without summary stats", { + expect_message( + params <- .calc_dist_params( + prob_distribution = "gamma", + summary_stats = create_summary_stats(mean = 5, median = 5), + sample_size = NA + ), + regexp = "(No adequate summary statistics available)" + ) + + expect_true(is.na(params)) +}) diff --git a/tests/testthat/test-checkers.R b/tests/testthat/test-checkers.R new file mode 100644 index 000000000..0d3d6a229 --- /dev/null +++ b/tests/testthat/test-checkers.R @@ -0,0 +1,45 @@ +test_that("is_parameterised works as expected with epiparameter parameters", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + expect_true(is_parameterised(ep)) +}) + +test_that("is_parameterised works as expected without epiparameter parameters", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period" + )) + expect_false(is_parameterised(ep)) +}) + +test_that("is_parameterised works as expected for multi_epiparameter", { + ep <- suppressMessages(epiparameter_db()) + res <- is_parameterised(ep) + expect_vector(res, ptype = logical(1), size = length(ep)) +}) + +test_that("is_parameterised works as expected with multi_epiparameter parameters", { + ep <- suppressMessages( + epiparameter_db( + epi_name = "incubation period", + author = "McAloon", + single_epiparameter = TRUE + ) + ) + expect_true(is_parameterised(ep)) +}) + +test_that("is_parameterised works as expected without parameters", { + ep <- suppressMessages( + epiparameter_db(epi_name = "incubation period", author = "Alene") + ) + expect_false(is_parameterised(ep)) +}) diff --git a/tests/testthat/test-coercion.R b/tests/testthat/test-coercion.R new file mode 100644 index 000000000..598e1390d --- /dev/null +++ b/tests/testthat/test-coercion.R @@ -0,0 +1,187 @@ +if (requireNamespace("epireview", quietly = TRUE)) { + # suppress message about loading data + ebola_data <- suppressMessages( + epireview::load_epidata("ebola") + ) + lassa_data <- suppressMessages( + epireview::load_epidata("lassa") + ) +} + +test_that("as_epiparameter works for ebola infectious period (issue #327 & #306)", { + # {epireview} is not a dependency so only run if already on system + skip_if_not_installed("epireview") + ebola_params <- ebola_data$params + ebola_infectiousness <- ebola_params[ + ebola_params$parameter_type == "Human delay - infectious period", + ] + ebola_infectiousness <- ebola_infectiousness[ + !is.na(ebola_infectiousness$distribution_type), + ] + # suppress warning and message about citation + ebola_infectiousness_epiparameter <- suppressWarnings( + suppressMessages( + as_epiparameter(ebola_infectiousness) + ) + ) + expect_s3_class(ebola_infectiousness_epiparameter, class = "epiparameter") + # Lau 2017 has information to parameterise an exponential distribution + expect_s3_class( + ebola_infectiousness_epiparameter$prob_distribution, + class = "distribution" + ) + # populate mean summary statistics + expect_true(all(!is.na(ebola_infectiousness_epiparameter$summary_stats[1:3]))) +}) + +test_that("as_epiparameter works for lassa incubation period (issue #306)", { + # {epireview} is not a dependency so only run if already on system + skip_if_not_installed("epireview") + lassa_params <- lassa_data$params + lassa_incub <- lassa_params[ + # TODO: temp use id until epireview #122 is fixed + which(lassa_params$id == "62332f18a631d2cdaafc5c5a500caea5" & + lassa_params$parameter_type == "Human delay - incubation period"), + ] + # suppress warning and message about citation + lassa_incub_epiparameter <- suppressWarnings( + suppressMessages( + as_epiparameter(lassa_incub) + ) + ) + expect_s3_class(lassa_incub_epiparameter, class = "epiparameter") + # Akhmetzhanov 2019 has information to parameterise a gamma distribution + expect_s3_class( + lassa_incub_epiparameter$prob_distribution, + class = "distribution" + ) + # populate mean and sd summary statistics without uncertainty + expect_true(all(!is.na(lassa_incub_epiparameter$summary_stats[c("mean", "sd")]))) +}) + +test_that("as_epiparameter works for ebola serial interval (issue #303)", { + # {epireview} is not a dependency so only run if already on system + skip_if_not_installed("epireview") + ebola_params <- ebola_data$params + ebola_serial <- ebola_params[ + which(ebola_params$parameter_type == "Human delay - serial interval" & + ebola_params$distribution_type == "Gamma" & + ebola_params$article_label == "Chan 2020"), + ] + # suppress warning and message about citation + ebola_serial_epiparameter <- suppressWarnings( + suppressMessages( + as_epiparameter(ebola_serial) + ) + ) + expect_s3_class(ebola_serial_epiparameter, class = "epiparameter") + # Chan 2020 has information to parameterise a gamma distribution + expect_s3_class( + ebola_serial_epiparameter$prob_distribution, + class = "distribution" + ) + # populate mean and sd summary statistics without uncertainty + expect_true(all(!is.na(ebola_serial_epiparameter$summary_stats[c("mean", "sd")]))) +}) + +test_that("as_epiparameter works for ebola SI assumed prob_dist (issue #310)", { + # {epireview} is not a dependency so only run if already on system + skip_if_not_installed("epireview") + ebola_params <- ebola_data$params + ebola_serial <- ebola_params[ + which( + grepl(pattern = "Faye", x = ebola_params$article_label) & + grepl(pattern = "serial", ebola_params$parameter_type) + ), + ] + # suppress warning and message about citation + ebola_serial_epiparameter <- suppressWarnings( + suppressMessages( + as_epiparameter(ebola_serial, prob_distribution = "gamma") + ) + ) + expect_s3_class(ebola_serial_epiparameter, class = "epiparameter") + # Faye 2015 parameterise an assumed gamma distribution + expect_s3_class( + ebola_serial_epiparameter$prob_distribution, + class = "distribution" + ) + # populate mean and sd summary statistics without uncertainty + expect_true(all(!is.na(ebola_serial_epiparameter$summary_stats[c("mean", "sd")]))) +}) + +test_that("as_epiparameter works for lassa incubation overwritten prob_dist", { + # {epireview} is not a dependency so only run if already on system + skip_if_not_installed("epireview") + lassa_params <- lassa_data$params + lassa_incub <- lassa_params[ + # TODO: temp use id until epireview #122 is fixed + which(lassa_params$id == "62332f18a631d2cdaafc5c5a500caea5" & + lassa_params$parameter_type == "Human delay - incubation period"), + ] + # suppress warning and message about citation + lassa_incub_epiparameter <- suppressWarnings( + suppressMessages( + as_epiparameter(lassa_incub, prob_distribution = "lnorm") + ) + ) + expect_s3_class(lassa_incub_epiparameter, class = "epiparameter") + # Akhmetzhanov 2019 has information to parameterise a gamma distribution + expect_s3_class( + lassa_incub_epiparameter$prob_distribution, + class = "distribution" + ) + expect_identical(family(lassa_incub_epiparameter), "lnorm") + expect_true(is_parameterised(lassa_incub_epiparameter)) + # populate mean and sd summary statistics without uncertainty + expect_true(all(!is.na(lassa_incub_epiparameter$summary_stats[c("mean", "sd")]))) +}) + +test_that("as_epiparameter works for overwritten prob_dist with same parameters", { + # {epireview} is not a dependency so only run if already on system + skip_if_not_installed("epireview") + ebola_params <- ebola_data$params + ebola_si <- ebola_params[ + which( + ebola_params$distribution_par1_type == "Shape" & + ebola_params$article_label == "Fallah 2015 (1)" + ), + ] + # suppress warning and message about citation + ebola_si_gamma <- suppressWarnings( + suppressMessages( + as_epiparameter(ebola_si) + ) + ) + ebola_si_weibull <- suppressWarnings( + suppressMessages( + as_epiparameter(ebola_si, prob_distribution = "weibull") + ) + ) + expect_s3_class(ebola_si_gamma, class = "epiparameter") + expect_s3_class(ebola_si_weibull, class = "epiparameter") + expect_true(is_parameterised(ebola_si_gamma)) + expect_true(is_parameterised(ebola_si_weibull)) + expect_identical(family(ebola_si_gamma), "gamma") + expect_identical(family(ebola_si_weibull), "weibull") +}) + +test_that("as_epiparameter fails as expected with overwritten prob_dist", { + # {epireview} is not a dependency so only run if already on system + skip_if_not_installed("epireview") + ebola_params <- ebola_data$params + ebola_si <- ebola_params[ + which( + ebola_params$distribution_par1_type == "Shape" & + ebola_params$article_label == "Fallah 2015 (1)" + ), + ] + expect_error( + suppressWarnings( + suppressMessages( + as_epiparameter(ebola_si, prob_distribution = "lnorm") + ) + ), + regexp = "Incorrect parameters provided for probability distribution." + ) +}) diff --git a/tests/testthat/test-convert_params.R b/tests/testthat/test-convert_params.R new file mode 100644 index 000000000..fa2843e1d --- /dev/null +++ b/tests/testthat/test-convert_params.R @@ -0,0 +1,248 @@ +ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation period", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ), + summary_stats = create_summary_stats(mean = 1, sd = 1) + ) +) + +test_that("convert_summary_stats_to_params.character works as expected", { + expect_snapshot_value( + convert_summary_stats_to_params("gamma", mean = 1, sd = 0.5), + style = "json2" + ) + expect_snapshot_value( + suppressMessages( + convert_summary_stats_to_params("weibull", mean = 0.5, cv = 1) + ), + style = "json2" + ) + expect_snapshot_value( + convert_summary_stats_to_params("lnorm", median = 1, sd = 1), + style = "json2" + ) + expect_snapshot_value( + convert_summary_stats_to_params("lnorm", median = 5, dispersion = 2), + style = "json2" + ) + expect_snapshot_value( + convert_summary_stats_to_params("nbinom", mean = 1, dispersion = 1), + style = "json2" + ) + expect_snapshot_value( + convert_summary_stats_to_params("nbinom", mean = 1, sd = 1.5), + style = "json2" + ) + expect_snapshot_value( + convert_summary_stats_to_params("geom", mean = 0.5), + style = "json2" + ) +}) + +test_that("convert_summary_stats_to_params.character works with dyn-dots", { + expect_identical( + convert_summary_stats_to_params("gamma", mean = 1, sd = 0.5), + convert_summary_stats_to_params("gamma", !!!list(mean = 1, sd = 0.5)) + ) +}) + +test_that("convert_summary_stats_to_params.epiparameter works as expected", { + expect_snapshot_value( + convert_summary_stats_to_params(ep), + style = "json2" + ) +}) + +test_that("convert_summary_stats_to_params.epiparameter warns as expected", { + expect_warning( + convert_summary_stats_to_params(ep, mean = 1, sd = 1), + regexp = "One or more summary statistics in are being overwritten" + ) +}) + +test_that("convert_summary_stats_to_params.character fails as expected", { + expect_error( + convert_summary_stats_to_params("random", mean = 1, sd = 1), + regexp = "(arg)*(should be one of)*(lnorm)*(gamma)" + ) + expect_error( + convert_summary_stats_to_params("lnorm"), + regexp = "Summary statistics need to be named and supplied to the function" + ) + expect_error( + convert_summary_stats_to_params("gamma", mean = -1, sd = 1), + regexp = "(Assertion on)*(x$mean)*(failed: Element 1 is not >= 0.)" + ) + expect_error( + convert_summary_stats_to_params("lnorm", mode = 1, var = 1), + regexp = "Cannot calculate lognormal parameters from given input" + ) + expect_error( + convert_summary_stats_to_params("gamma", mode = 1, var = 1), + regexp = "Cannot calculate gamma parameters from given input" + ) + expect_error( + convert_summary_stats_to_params("weibull", mode = 1, var = 1), + regexp = "Cannot calculate Weibull parameters from given input" + ) + expect_error( + convert_summary_stats_to_params("nbinom", mode = 1, var = 1), + regexp = "(Cannot calculate negative binomial)*(parameters from)*(input)" + ) + expect_error( + convert_summary_stats_to_params("geom", mode = 1, var = 1), + regexp = "(Cannot calculate geometric)*(parameter from given input)" + ) + expect_error( + convert_summary_stats_to_params("nbinom", mean = 1, var = 0.5), + regexp = "(Negative binomial)*(variance-to-mean ratio)*(greater than one)" + ) +}) + +test_that("convert_summary_stats_to_params.epiparameter fails as expected", { + ep$summary_stats <- list() + expect_error( + convert_summary_stats_to_params(ep), + regexp = "Summary statistics need to be named and supplied to the function" + ) +}) + +test_that("convert_params_to_summary_stats.character works as expected", { + expect_snapshot_value( + convert_params_to_summary_stats("lnorm", meanlog = 1, sdlog = 0.5), + style = "json2" + ) + expect_snapshot_value( + convert_params_to_summary_stats("nbinom", prob = 0.5, dispersion = 1), + style = "json2" + ) + expect_snapshot_value( + convert_params_to_summary_stats("gamma", shape = 1, scale = 1), + style = "json2" + ) + expect_snapshot_value( + convert_params_to_summary_stats("weibull", shape = 1, scale = 1), + style = "json2" + ) + expect_snapshot_value( + convert_params_to_summary_stats("geom", prob = 0.5), + style = "json2" + ) +}) + +test_that("convert_params_to_summary_stats.character works with dyn-dots", { + expect_identical( + convert_params_to_summary_stats("lnorm", meanlog = 1, sdlog = 0.5), + convert_params_to_summary_stats("lnorm", !!!list(meanlog = 1, sdlog = 0.5)) + ) +}) + +test_that("convert_params_to_summary_stats.epiparameter works as expected", { + expect_snapshot_value( + convert_params_to_summary_stats(ep), + style = "json2" + ) + ep <- "lnorm" + expect_snapshot_value( + convert_params_to_summary_stats(ep, meanlog = 1, sdlog = 1), + style = "json2" + ) +}) + +test_that("convert_params_to_summary_stats.epiparameter warns as expected", { + expect_warning( + convert_params_to_summary_stats(ep, meanlog = 1, sdlog = 1), + regexp = "One or more parameters in are being overwritten" + ) +}) + +test_that("convert_params_to_summary_stats.character fails as expected", { + expect_error( + convert_params_to_summary_stats("random", shape = 1, scale = 1), + regexp = "(arg)*(should be one of)*(lnorm)*(gamma)" + ) + expect_error( + convert_params_to_summary_stats("lnorm"), + regexp = "(Parameter(s) need to be named and supplied)*(to the function)" + ) + expect_error( + convert_params_to_summary_stats("gamma", shape = -1, scale = 1), + regexp = "(Assertion on)*(shape)*(failed: Element 1 is not >= 0.)" + ) + expect_error( + convert_params_to_summary_stats("lnorm", shape = 1, scale = 1), + regexp = "(lnorm parameters must be named)*(meanlog)*(sdlog)" + ) + expect_error( + convert_params_to_summary_stats("gamma", meanlog = 1, scale = 1), + regexp = "(gamma parameters must be named)*(shape)*(scale)" + ) + expect_error( + convert_params_to_summary_stats("weibull", meanlog = 1, scale = 1), + regexp = "(weibull parameters must be named)*(shape)*(scale)" + ) + expect_error( + convert_params_to_summary_stats( + "nbinom", probability = 0.5, dispersion = 1 + ), + regexp = "(nbinom parameters must be named)*(prob)*(dispersion)" + ) + expect_error( + convert_params_to_summary_stats("geom", probability = 0.5), + regexp = "(geom parameter must be named)*(prob)" + ) +}) + +test_that("convert_params_to_summary_stats.epiparameter fails as expected", { + ep$prob_distribution <- "lnorm" + expect_error( + convert_params_to_summary_stats(ep), + regexp = " supplied has no parameters and none are suppled" + ) +}) + +test_that(".get_sd works as expected", { + x <- list(mean = 1, sd = 1) + x <- .get_sd(x) + expect_identical(x, list(mean = 1, sd = 1)) + x <- list(mean = 1, var = 1) + x <- .get_sd(x) + expect_identical(x, list(mean = 1, var = 1, sd = 1)) + x <- list(mean = 1, cv = 1) + x <- .get_sd(x) + expect_identical(x, list(mean = 1, cv = 1, sd = 1)) +}) + +test_that(".chk_ss is working as expected", { + x <- list(mean = 1, sd = 1) + expect_no_error(.chk_ss(x)) + x <- c(mean = 1, sd = 1) + expect_error( + .chk_ss(x), + regexp = "(Assertion)*(failed: Must be of type)*(list)*(double)" + ) + x <- list(mean = 1) + expect_error( + .chk_ss(x), + regexp = "(Assertion)*(failed: Must have length)*(2)*(1)" + ) + x <- list(mean = 1, 1) + expect_error( + .chk_ss(x), + regexp = "(Assertion)*(failed: Must have names)*(empty)" + ) + x <- list(mean = 1, sd = "1") + expect_error( + .chk_ss(x), + regexp = "(Assertion)*(failed: May only contain)*(numeric)*(character)" + ) + x <- list(mean = 1, ss = 1) + expect_error( + .chk_ss(x), + regexp = "(Assertion)*(failed: Must be a subset)*(has additional elements)" + ) +}) diff --git a/tests/testthat/test-create_prob_distribution.R b/tests/testthat/test-create_prob_distribution.R new file mode 100644 index 000000000..f7e4eb980 --- /dev/null +++ b/tests/testthat/test-create_prob_distribution.R @@ -0,0 +1,243 @@ +test_that("create_prob_distribution works for continuous gamma", { + res <- create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "gamma") + expect_identical( + distributional::parameters(res), + data.frame(shape = 1, rate = 1) + ) +}) + +test_that("create_prob_distribution works for continuous lognormal", { + res <- create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1), + discretise = FALSE, + truncation = NA + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "lognormal") + expect_identical( + distributional::parameters(res), + data.frame(mu = 1, sigma = 1) + ) +}) + +test_that("create_prob_distribution works for continuous Weibull", { + res <- create_prob_distribution( + prob_distribution = "weibull", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "weibull") + expect_identical( + distributional::parameters(res), + data.frame(shape = 1, scale = 1) + ) +}) + +test_that("create_prob_distribution works for negative binomial", { + res <- create_prob_distribution( + prob_distribution = "nbinom", + prob_distribution_params = c(mean = 1, dispersion = 1), + discretise = FALSE, + truncation = NA + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "negbin") + expect_identical( + distributional::parameters(res), + data.frame(n = 1, p = 0.5) + ) +}) + +test_that("create_prob_distribution works for geometric", { + res <- create_prob_distribution( + prob_distribution = "geom", + prob_distribution_params = c(mean = 1), + discretise = FALSE, + truncation = NA + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "geometric") + expect_identical( + distributional::parameters(res), + data.frame(p = 1) + ) +}) + +test_that("create_prob_distribution works for poisson", { + res <- create_prob_distribution( + prob_distribution = "pois", + prob_distribution_params = c(mean = 1), + discretise = FALSE, + truncation = NA + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "poisson") + expect_identical( + distributional::parameters(res), + data.frame(l = 1) + ) +}) + +test_that("create_prob_distribution works for exponential", { + res <- create_prob_distribution( + prob_distribution = "exp", + prob_distribution_params = c(rate = 2), + discretise = FALSE, + truncation = NA + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "exponential") + expect_identical( + distributional::parameters(res), + data.frame(rate = 2) + ) +}) + +test_that("create_prob_distribution works for discrete gamma", { + res <- create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = NA + ) + + expect_s3_class(res, "distcrete") + expect_identical(res$name, "gamma") + expect_identical( + res$parameters, + list(shape = 1, scale = 1) + ) +}) + +test_that("create_prob_distribution works for discrete lognormal", { + res <- create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1), + discretise = TRUE, + truncation = NA + ) + + expect_s3_class(res, "distcrete") + expect_identical(res$name, "lnorm") + expect_identical( + res$parameters, + list(meanlog = 1, sdlog = 1) + ) +}) + +test_that("create_prob_distribution works for discrete Weibull", { + res <- create_prob_distribution( + prob_distribution = "weibull", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = NA + ) + + expect_s3_class(res, "distcrete") + expect_identical(res$name, "weibull") + expect_identical( + res$parameters, + list(shape = 1, scale = 1) + ) +}) + +test_that("create_prob_distribution works for discrete normal", { + res <- create_prob_distribution( + prob_distribution = "norm", + prob_distribution_params = c(mean = 1, sd = 1), + discretise = TRUE, + truncation = NA + ) + + expect_s3_class(res, "distcrete") + expect_identical(res$name, "norm") + expect_identical( + res$parameters, + list(mean = 1, sd = 1) + ) +}) + +test_that("create_prob_distribution works for truncated continuous", { + res <- create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = 10 + ) + + expect_s3_class(res, "distribution") + expect_identical(family(res), "truncated") +}) + +test_that("create_prob_distribution works passing args via ...", { + dist1 <- create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = NA, + w = 1 + ) + dist2 <- create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = NA, + w = 0.5 + ) + expect_false(identical(dist1, dist2)) + expect_identical(dist1$w, 1) + expect_identical(dist2$w, 0.5) +}) + +test_that("create_prob_distribution fails for unrecognised discretised", { + expect_error( + create_prob_distribution( + prob_distribution = "distribution", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = NA + ), + regexp = "Incorrect parameters provided for probability distribution." + ) +}) + +test_that("create_prob_distribution fails for unrecognised non-discretised", { + expect_error( + create_prob_distribution( + prob_distribution = "distribution", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ), + regexp = "Incorrect parameters provided for probability distribution." + ) +}) + +test_that("create_prob_distribution errors for discrete truncation", { + expect_error( + create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE, + truncation = 10 + ), + regexp = "Truncation is not yet implemented for discrete distributions" + ) +}) diff --git a/tests/testthat/test-epiparameter-utils.R b/tests/testthat/test-epiparameter-utils.R new file mode 100644 index 000000000..1413ec2c7 --- /dev/null +++ b/tests/testthat/test-epiparameter-utils.R @@ -0,0 +1,325 @@ +test_that("create_metadata fails when vector is given for non-vb", { + expect_error( + create_metadata( + transmission_mode = "natural_human_to_human", + vector = "mosquito" + ), + regexp = "(A vector is given for a non-vector-borne disease)" + ) +}) + +test_that("create_citation works with different author inputs", { + cit <- suppressMessages(create_citation( + author = person(given = "John", family = "Smith"), + year = 2002, + title = "COVID-19 incubation period", + journal = "Epi Journal", + doi = "10.19832/j.1366-9516.2012.09147.x" # nolint file.path + )) + expect_s3_class(cit, class = "bibentry") + expect_s3_class(cit$author, class = "person") + expect_identical(cit$author$given, "John") + expect_identical(cit$author$family, "Smith") + + cit <- suppressMessages(create_citation( + author = person( + given = list("John", "Amy"), family = list("Smith", "Jones") + ), + year = 2002, + title = "COVID-19 incubation period", + journal = "Epi Journal", + doi = "10.19832/j.1366-9516.2012.09147.x" # nolint file.path + )) + expect_s3_class(cit, class = "bibentry") + expect_s3_class(cit$author, class = "person") + expect_identical(cit$author$given, list("John", "Amy")) + expect_identical(cit$author$family, list("Smith", "Jones")) + + cit <- suppressMessages(create_citation( + author = "John Smith", + year = 2002, + title = "COVID-19 incubation period", + journal = "Epi Journal", + doi = "10.19832/j.1366-9516.2012.09147.x" # nolint file.path + )) + expect_s3_class(cit, class = "bibentry") + expect_s3_class(cit$author, class = "person") + expect_identical(cit$author$given, "John") + expect_identical(cit$author$family, "Smith") + + cit <- suppressMessages(create_citation( + author = c("John Smith", "Amy Jones", "WHO Team"), + year = 2002, + title = "COVID-19 incubation period", + journal = "Epi Journal", + doi = "10.19832/j.1366-9516.2012.09147.x" # nolint file.path + )) + expect_s3_class(cit, class = "bibentry") + expect_s3_class(cit$author, class = "person") + expect_identical(cit$author$given, list("John", "Amy", "WHO")) + expect_identical(cit$author$family, list("Smith", "Jones", "Team")) + + cit <- suppressMessages(create_citation( + author = list("John Smith", "Amy Jones", "WHO Team"), + year = 2002, + title = "COVID-19 incubation period", + journal = "Epi Journal", + doi = "10.19832/j.1366-9516.2012.09147.x" # nolint file.path + )) + expect_s3_class(cit, class = "bibentry") + expect_s3_class(cit$author, class = "person") + expect_identical(cit$author$given, list("John", "Amy", "WHO")) + expect_identical(cit$author$family, list("Smith", "Jones", "Team")) +}) + +test_that("create_citation works with PMID", { + # suppress message about citation + citation <- suppressMessages( + create_citation( + author = person(given = "John", family = "Smith"), + year = 2002, + title = "Incubation period of COVID", + journal = "Journal of Epi", + doi = "10.1282718", + pmid = 84772544 + ) + ) + expect_s3_class(citation, "bibentry") + expect_s3_class(citation$author, "person") + expect_identical(citation$pmid, "84772544") +}) + +test_that(".clean_params works as expected for gamma", { + params <- .clean_params( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + expect_identical(params, c(shape = 1, scale = 1)) + + params <- .clean_params( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, rate = 0.5) + ) + expect_identical(params, c(shape = 1, scale = 2)) +}) + +test_that(".clean_params fails when gamma parameters are incorrect", { + expect_error( + .clean_params( + prob_distribution = "gamma", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ), + regexp = "Invalid parameterisation for gamma distribution" + ) +}) + +test_that(".clean_params works as expected for lnorm", { + params <- .clean_params( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ) + expect_identical(params, c(meanlog = 1, sdlog = 1)) + + params <- .clean_params( + prob_distribution = "lnorm", + prob_distribution_params = c(mu = 2, sigma = 2) + ) + expect_identical(params, c(meanlog = 2, sdlog = 2)) +}) + +test_that(".clean_params fails when lnorm parameters are incorrect", { + expect_error( + .clean_params( + prob_distribution = "lnorm", + prob_distribution_params = c(shape = 1, scale = 1) + ), + regexp = "Invalid parameterisation for lnorm distribution" + ) +}) + +test_that(".clean_params works as expected for weibull", { + params <- .clean_params( + prob_distribution = "weibull", + prob_distribution_params = c(shape = 1, scale = 1) + ) + expect_identical(params, c(shape = 1, scale = 1)) +}) + +test_that(".clean_params fails when weibull parameters are incorrect", { + expect_error( + .clean_params( + prob_distribution = "weibull", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ), + regexp = "Invalid parameterisation for weibull distribution" + ) +}) + +test_that(".clean_params works as expected for nbinom", { + params <- .clean_params( + prob_distribution = "nbinom", + prob_distribution_params = c(n = 2, p = 0.5) + ) + expect_identical(params, c(mean = 2, dispersion = 2)) + + params <- .clean_params( + prob_distribution = "nbinom", + prob_distribution_params = c(mean = 1, dispersion = 1) + ) + expect_identical(params, c(mean = 1, dispersion = 1)) +}) + +test_that(".clean_params fails when nbinom parameters are incorrect", { + expect_error( + .clean_params( + prob_distribution = "nbinom", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ), + regexp = "Invalid parameterisation for nbinom distribution" + ) +}) + +test_that(".clean_params works as expected for geom", { + params <- .clean_params( + prob_distribution = "geom", + prob_distribution_params = c(prob = 0.5) + ) + expect_identical(params, c(prob = 0.5)) + + params <- .clean_params( + prob_distribution = "geom", + prob_distribution_params = c(p = 0.5) + ) + expect_identical(params, c(prob = 0.5)) + + params <- .clean_params( + prob_distribution = "geom", + prob_distribution_params = c(mean = 2) + ) + expect_identical(params, c(prob = 0.5)) +}) + +test_that(".clean_params fails when geom parameters are incorrect", { + expect_error( + .clean_params( + prob_distribution = "geom", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ), + regexp = "Invalid parameterisation for geom distribution" + ) +}) + +test_that(".clean_params works as expected for pois", { + params <- .clean_params( + prob_distribution = "pois", + prob_distribution_params = c(mean = 0.5) + ) + expect_identical(params, c(mean = 0.5)) + + params <- .clean_params( + prob_distribution = "pois", + prob_distribution_params = c(l = 0.5) + ) + expect_identical(params, c(mean = 0.5)) + + params <- .clean_params( + prob_distribution = "pois", + prob_distribution_params = c(lambda = 0.5) + ) + expect_identical(params, c(mean = 0.5)) +}) + +test_that(".clean_params fails when pois parameters are incorrect", { + expect_error( + .clean_params( + prob_distribution = "pois", + prob_distribution_params = c(means = 1) + ), + regexp = "Invalid parameterisation for pois distribution" + ) +}) + +test_that(".clean_params works as expected for exp", { + params <- .clean_params( + prob_distribution = "exp", + prob_distribution_params = c(rate = 2) + ) + expect_identical(params, c(rate = 2)) + + params <- .clean_params( + prob_distribution = "exp", + prob_distribution_params = c(lambda = 2) + ) + expect_identical(params, c(rate = 2)) + + params <- .clean_params( + prob_distribution = "exp", + prob_distribution_params = c(mean = 0.5) + ) + expect_identical(params, c(rate = 2)) +}) + +test_that(".clean_params fails when exp parameters are incorrect", { + expect_error( + .clean_params( + prob_distribution = "exp", + prob_distribution_params = c(means = 1) + ), + regexp = "Invalid parameterisation for exp distribution" + ) +}) + +test_that(".clean_params fails as expected", { + expect_error( + .clean_params( + prob_distribution = "distribution", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ), + regexp = "Invalid parameterisation for distribution distribution" + ) +}) + +test_that("create_region works as expected", { + region <- create_region( + continent = "Europe", + country = "UK", + region = "Cambridgeshire", + city = "Cambridge" + ) + expect_identical( + region, + list( + continent = "Europe", + country = "UK", + region = "Cambridgeshire", + city = "Cambridge" + ) + ) + + region <- create_region( + continent = NA, + country = "UK", + region = NA, + city = "Cambridge" + ) + expect_identical( + region, + list( + continent = NA, + country = "UK", + region = NA, + city = "Cambridge" + ) + ) +}) + +test_that(".clean_string works as expected", { + expect_identical(.clean_string("COVID-19"), "covid 19") +}) + +test_that(".clean_string fails as expected", { + expect_error( + .clean_string(5), + regexp = "(Assertion on 'x' failed)*(Must be of type)" + ) +}) diff --git a/tests/testthat/test-epiparameter.R b/tests/testthat/test-epiparameter.R new file mode 100644 index 000000000..658ac2a9b --- /dev/null +++ b/tests/testthat/test-epiparameter.R @@ -0,0 +1,1437 @@ +test_that("epiparameter works with minimal viable input", { + # message about missing citation suppressed + ebola_dist <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + + expect_s3_class(ebola_dist, class = "epiparameter") + expect_length(ebola_dist, 10) +}) + +test_that("epiparameter works with all arguments set", { + # suppress message about citation + mers_dist <- suppressMessages( + epiparameter( + disease = "MERS", + pathogen = "MERS_CoV", + epi_name = "serial_interval", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 2, sdlog = 1) + ), + uncertainty = list( + meanlog = create_uncertainty( + ci_limits = c(1, 3), + ci = 95, + ci_type = "confidence interval" + ), + sdlog = create_uncertainty( + ci_limits = c(0.1, 1.9), + ci = 95, + ci_type = "confidence interval" + ) + ), + summary_stats = create_summary_stats( + mean = 1, + mean_ci_limits = c(0.8, 1.2), + mean_ci = 95, + sd = 0.5, + sd_ci_limits = c(0.4, 0.6), + sd_ci = 95, + median = 1, + median_ci_limits = c(0.9, 1.1), + median_ci = 95, + lower_range = 0.1, + upper_range = 1.9, + quantiles = c( + "2.5" = 0.2, "5" = 0.3, "25" = 0.5, "75" = 0.7, "87.5" = 1.1, + "95" = 1.2, "97.5" = 1.5 + ) + ), citation = create_citation( + author = person(given = "John", family = "Smith"), + year = 2002, + title = "A title", + journal = "A journal", + doi = "10.23271/176237.x", + pmid = 28372882 + ), + metadata = create_metadata( + units = "days", + sample_size = 100, + region = "UK", + transmission_mode = "vector_borne", + vector = NA, + extrinsic = FALSE, + inference_method = "MLE" + ), + method_assess = create_method_assess( + censored = TRUE, + right_truncated = FALSE, + phase_bias_adjusted = FALSE + ), + discretise = FALSE, + truncation = NA_real_, + notes = "No notes" + ) + ) + expect_s3_class(mers_dist, class = "epiparameter") + expect_length(mers_dist, 10) +}) + +test_that("epiparameter works with default helper functions", { + # message about missing citation suppressed + sars_dist <- suppressMessages(epiparameter( + disease = "SARS", + pathogen = "SARS_CoV", + epi_name = "onset_to_death", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 2, sdlog = 1), + discretise = FALSE, + truncation = NA + ), + uncertainty = list( + meanlog = create_uncertainty(), + sdlog = create_uncertainty() + ), + summary_stats = create_summary_stats(), + citation = create_citation(), + metadata = create_metadata(), + method_assess = create_method_assess(), + notes = "No notes" + )) + + expect_s3_class(sars_dist, class = "epiparameter") + expect_length(sars_dist, 10) +}) + +test_that("epiparameter fails as expected", { + expect_error( + epiparameter( + disease = 1, + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ), + regexp = paste0( + "Assertion on 'disease' failed: Must be of type ", + "'string', not 'double'." + ) + ) + + expect_error( + epiparameter( + disease = "ebola", + epi_name = 1, + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ), + regexp = paste0( + "Assertion on 'epi_name' failed: Must be of type ", + "'string', not 'double'." + ) + ) + + expect_error( + suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = 1 + ) + ), + regexp = paste0( + "epiparameter must contain a or or NA" + ) + ) + + expect_error( + # message about missing citation suppressed + suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = "gamma", + prob_distribution_params = c(shape = "NA", scale = 1) + ), + regexp = paste0( + "(Assertion on 'prob_distribution_params' failed)*(Must be of type)*", + "(numeric)*(NULL)*(character)." + ) + ) + ) +}) + +test_that("epiparameter.print works as expected", { + expect_snapshot(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) +}) + +test_that("epiparameter.print works as expected", { + expect_snapshot(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + )) +}) + +test_that("epiparameter.plot does not produce an error", { + ebola_dist <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + + + expect_silent(plot(ebola_dist)) + + f <- function() plot(ebola_dist) + vdiffr::expect_doppelganger( + title = "epiparameter.plot", + fig = f + ) +}) + +test_that("epiparameter.plot prints units in x-axis", { + ebola_dist <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ), + metadata = create_metadata(units = "days") + )) + + + expect_silent(plot(ebola_dist)) + + f <- function() plot(ebola_dist) + vdiffr::expect_doppelganger( + title = "epiparameter.plot units", + fig = f + ) +}) + +test_that("epiparameter.plot works with non-default x-axis", { + ebola_dist <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + + expect_silent( + plot( + ebola_dist, + xlim = c(0, 20) + ) + ) + + f <- function() { + plot( + ebola_dist, + xlim = c(0, 20) + ) + } + vdiffr::expect_doppelganger( + title = "epiparameter.plot non-default range", + fig = f + ) +}) + +test_that("new_epiparameter works with minimal viable input", { + epiparameter_obj <- suppressMessages( + new_epiparameter( + disease = "ebola", + pathogen = "ebola virus", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ), + uncertainty = list( + shape = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ), + scale = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ) + ), + citation = create_citation( + author = person(given = "John", family = "Smith"), + year = 2002, + title = "Ebola incubation", + journal = "Journal of Epi" + ), + notes = "No notes" + ) + ) + + expect_s3_class(epiparameter_obj, class = "epiparameter") + expect_length(epiparameter_obj, 10) + expect_s3_class(assert_epiparameter(epiparameter_obj), class = "epiparameter") +}) + +test_that("assert_epiparameter passes when expected", { + epiparameter_obj <- suppressMessages( + new_epiparameter( + disease = "ebola", + pathogen = "ebola_virus", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distributions_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ), + uncertainty = list( + shape = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ), + scale = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ) + ), + citation = create_citation( + author = person(given = "John", family = "Smith"), + year = 2000, + title = "Ebola incubation", + journal = "Journal of Epi", + doi = "10.1872372hc" + ), + notes = "No notes", + auto_calc_params = FALSE + ) + ) + + expect_silent(assert_epiparameter(epiparameter_obj)) +}) + +test_that("assert_epiparameter catches class faults when expected", { + epiparameter_obj <- new_epiparameter( + disease = "ebola", + pathogen = "ebola_virus", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_dist_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ), + uncertainty = list( + shape = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ), + scale = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ) + ), + citation = "Smith (2002) <10.128372837>", + auto_calc_params = FALSE + ) + + epiparameter_obj$disease <- NULL + + expect_error( + assert_epiparameter(epiparameter_obj), + regexp = "Object is missing disease" + ) + + epiparameter_obj <- new_epiparameter( + disease = "ebola", + pathogen = "ebola_virus", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_dist_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ), + uncertainty = list( + shape = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ), + scale = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ) + ), + citation = "Smith (2002) <10.128372837>", + auto_calc_params = FALSE + ) + + epiparameter_obj$disease <- factor("disease") + + expect_error( + assert_epiparameter(epiparameter_obj), + regexp = "(epiparameter must contain a disease)" + ) + + epiparameter_obj <- new_epiparameter( + disease = "ebola", + pathogen = "ebola_virus", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_dist_params = c(shape = 1, scale = 1), + discretise = FALSE, + truncation = NA + ), + uncertainty = list( + shape = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ), + scale = create_uncertainty( + ci_limits = c(0, 2), + ci = 95, + ci_type = "confidence interval" + ) + ), + citation = "Smith (2002) <10.128372837>", + auto_calc_params = FALSE + ) + + epiparameter_obj$epi_name <- c("incubation", "period") + + expect_error( + assert_epiparameter(epiparameter_obj), + regexp = "epiparameter must contain an epidemiological distribution" + ) +}) + +test_that("assert_epiparameter fails as expected with input class", { + expect_error( + assert_epiparameter(1), + regexp = "Object should be of class epiparameter" + ) +}) + +test_that("test_epiparameter returns TRUE as expected", { + suppressMessages( + ep <- epiparameter_db(single_epiparameter = TRUE) + ) + expect_true(test_epiparameter(ep)) +}) + +test_that("test_epiparameter returns FALSE as expected", { + expect_false(test_epiparameter(1)) + suppressMessages( + ep <- epiparameter_db(single_epiparameter = TRUE) + ) + ep1 <- ep + ep1$disease <- NULL + expect_false(test_epiparameter(ep1)) + ep2 <- ep + ep2$disease <- 1 + expect_false(test_epiparameter(ep2)) + ep3 <- ep + ep3$citation <- "reference" + expect_false(test_epiparameter(ep3)) +}) + +test_that("density works as expected on continuous epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + res <- stats::density(ebola_dist, at = 0.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- stats::density(ebola_dist, at = 0) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- stats::density(ebola_dist, at = 1.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- stats::density(ebola_dist, at = 10) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) +}) + +test_that("density works as expected on discrete epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + res <- stats::density(ebola_dist, at = 0.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- stats::density(ebola_dist, at = 0) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- stats::density(ebola_dist, at = 1.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- stats::density(ebola_dist, at = 10) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) +}) + +test_that("density works as expected on continuous epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + res <- stats::density(ebola_dist, at = seq(0.1, 0.9, by = 0.1)) + expect_length(res, 9) + expect_type(res, "double") + expect_true(all(res >= 0)) +}) + +test_that("density works as expected on discrete epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + res <- stats::density(ebola_dist, at = seq(0.1, 0.9, by = 0.1)) + expect_length(res, 9) + expect_type(res, "double") + expect_true(all(res >= 0)) +}) + +test_that("cdf works as expected on continuous epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + res <- distributional::cdf(ebola_dist, q = 0.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) + + res <- distributional::cdf(ebola_dist, q = 0) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) + + res <- distributional::cdf(ebola_dist, q = 1.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) + + res <- distributional::cdf(ebola_dist, q = 10) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) +}) + +test_that("cdf works as expected on discrete epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + res <- distributional::cdf(ebola_dist, q = 0.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) + + res <- distributional::cdf(ebola_dist, q = 0) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) + + res <- distributional::cdf(ebola_dist, q = 1.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) + + res <- distributional::cdf(ebola_dist, q = 10) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + expect_lte(res, 1) +}) + +test_that("cdf works as expected on continuous epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + res <- distributional::cdf(ebola_dist, q = seq(0.1, 0.9, by = 0.1)) + expect_length(res, 9) + expect_type(res, "double") + expect_true(all(res >= 0)) + expect_true(all(res <= 1)) +}) + +test_that("cdf works as expected on discrete epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + res <- distributional::cdf(ebola_dist, q = seq(0.1, 0.9, by = 0.1)) + expect_length(res, 9) + expect_type(res, "double") + expect_true(all(res >= 0)) + expect_true(all(res <= 1)) +}) + +test_that("quantile works as expected on continuous epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + res <- quantile(ebola_dist, p = 0.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- quantile(ebola_dist, p = 0) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- quantile(ebola_dist, p = 1) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) +}) + +test_that("quantile works as expected on discrete epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + res <- quantile(ebola_dist, p = 0.5) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- quantile(ebola_dist, p = 0) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- quantile(ebola_dist, p = 1) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) +}) + +test_that("quantile works as expected on continuous epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + res <- quantile(ebola_dist, p = seq(0.1, 0.9, by = 0.1)) + expect_length(res, 9) + expect_type(res, "double") + expect_true(all(res >= 0)) +}) + +test_that("quantile works as expected on discrete epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + res <- quantile(ebola_dist, p = seq(0.1, 0.9, by = 0.1)) + expect_length(res, 9) + expect_type(res, "double") + expect_true(all(res >= 0)) +}) + +test_that("generate works as expected on continuous epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + res <- distributional::generate(ebola_dist, times = 1) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- distributional::generate(ebola_dist, times = 10) + expect_length(res, 10) + expect_type(res, "double") + expect_true(all(res >= 0)) +}) + +test_that("generate works as expected on discrete epiparameter object", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + res <- distributional::generate(ebola_dist, times = 1) + expect_length(res, 1) + expect_type(res, "double") + expect_gte(res, 0) + + res <- distributional::generate(ebola_dist, times = 10) + expect_length(res, 10) + expect_type(res, "double") + expect_true(all(res >= 0)) +}) + +test_that("generate fails as expected on continuous epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + + expect_error(distributional::generate(ebola_dist, times = c(10, 15))) +}) + +test_that("generate fails as expected on discrete epiparameter object with vector + input", { + ebola_dist <- suppressMessages( + epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + ) + ) + + expect_error(distributional::generate(ebola_dist, times = c(10, 15))) +}) + +test_that("is_epiparameter returns TRUE when expected", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "serial_interval", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + + expect_true(is_epiparameter(ep)) +}) + +test_that("is_epiparameter returns FALSE when expected", { + false_ep <- list( + disease = "ebola", + epi_name = "serial_interval", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + + expect_false(is_epiparameter(false_ep)) +}) + +test_that("discretise works as expected on continuous gamma", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + ep <- discretise(ep) + + expect_s3_class(ep$prob_distribution, "distcrete") + expect_identical(ep$prob_distribution$parameters, list(shape = 1, scale = 1)) + expect_identical(ep$prob_distribution$name, "gamma") +}) + +test_that("discretise works as expected on continuous lognormal", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ) + )) + ep <- discretise(ep) + + expect_s3_class(ep$prob_distribution, "distcrete") + expect_identical(ep$prob_distribution$parameters, list(meanlog = 1, sdlog = 1)) + expect_identical(ep$prob_distribution$name, "lnorm") +}) + +test_that("discretise works as expected on discretised dist", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + )) + expect_message( + discretise(ep), + regexp = "Distribution in `epiparameter` is already discretised" + ) + + expect_s3_class(ep$prob_distribution, "distcrete") + expect_identical(ep$prob_distribution$parameters, list(shape = 1, scale = 1)) + expect_identical(ep$prob_distribution$name, "gamma") +}) + +test_that("discretise works as expected on truncated dist", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + truncation = 10 + ) + )) + + expect_warning( + discretise(ep), + regexp = paste( + "Discretising a truncated continuous distribution,", + "returning non-truncated discretised distribution" + ) + ) + + ep <- suppressWarnings(discretise(ep)) + + expect_s3_class(ep$prob_distribution, "distcrete") + expect_identical(ep$prob_distribution$parameters, list(shape = 1, scale = 1)) + expect_identical(ep$prob_distribution$name, "gamma") +}) + +test_that("discretise fails as expected on non-epiparameter object", { + expect_error( + discretise("epiparameter"), + regexp = "No discretise method defined for class character" + ) + + expect_error( + discretise(c(1, 2, 3)), + regexp = "No discretise method defined for class numeric" + ) +}) + +test_that("parameters works as expected on continuous gamma", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + params <- get_parameters(ep) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("shape", "scale")) +}) + +test_that("parameters works as expected on continuous lognormal", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ) + )) + params <- get_parameters(ep) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("meanlog", "sdlog")) +}) + +test_that("parameters works as expected on discretised dist", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + )) + params <- get_parameters(ep) + + expect_vector(params, ptype = numeric(), size = 2) + expect_named(params, expected = c("shape", "scale")) +}) + +test_that("parameters works as expected on truncated dist", { + # suppress message about citation + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + truncation = 10 + ) + )) + params <- get_parameters(ep) + + expect_vector(params, ptype = numeric(), size = 4) + expect_named(params, expected = c("shape", "scale", "lower", "upper")) +}) + +test_that("parameters fails as expected on non-epiparameter object", { + expect_error( + get_parameters("epiparameter"), + regexp = paste0( + "(no applicable method for)*(parameters)*", + "(applied to an object of class)*(character)" + ) + ) + + expect_error( + get_parameters(c(1, 2, 3)), + regexp = paste0( + "(no applicable method for)*(parameters)*", + "(applied to an object of class)*(numeric)" + ) + ) +}) + +test_that("family works as expected for distributional", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ) + )) + expect_identical(family(ep), "lnorm") +}) + +test_that("family works as expected for distcrete", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + )) + expect_identical(family(ep), "gamma") +}) + +test_that("family works as expected for distributional truncated", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "weibull", + prob_distribution_params = c(shape = 1, scale = 1), + truncation = 10 + ) + )) + expect_identical(family(ep), "weibull") +}) + +test_that("is_truncated works as expected for continuous distributions", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + expect_false(is_truncated(ep)) +}) + +test_that("is_truncated works as expected for discretised distributions", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + )) + expect_false(is_truncated(ep)) +}) + +test_that("is_truncated works as expected for truncated distributions", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + truncation = 10 + ) + )) + expect_true(is_truncated(ep)) +}) + +test_that("is_continuous works as expected for continuous distributions", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation period", + prob_distribution = create_prob_distribution( + prob_distribution = "lnorm", + prob_distribution_params = c(meanlog = 1, sdlog = 1) + ) + )) + expect_true(is_continuous(ep)) + + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + expect_true(is_continuous(ep)) +}) + +test_that("is_continuous works as expected for discrete distributions", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "offspring distribution", + prob_distribution = create_prob_distribution( + prob_distribution = "nbinom", + prob_distribution_params = c(mean = 2, dispersion = 0.5) + ) + )) + expect_false(is_continuous(ep)) + + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + discretise = TRUE + ) + )) + expect_false(is_continuous(ep)) +}) + +test_that("mean works as expected when mean is supplied", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation_period", + prob_distribution = "gamma", + summary_stats = create_summary_stats(mean = 5) + ) + ) + expect_identical(mean(ep), 5) +}) + +test_that("mean works as expected with params and no mean", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation_period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + ) + ) + expect_identical(mean(ep), 1) +}) + +test_that("mean works as expected with no params and no mean", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation_period", + prob_distribution = "gamma" + ) + ) + expect_true(is.na(mean(ep))) +}) + +test_that("mean works for corrupted epiparameter", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "incubation_period", + prob_distribution = "gamma" + ) + ) + ep$summary_stats <- list() + expect_true(is.na(mean(ep))) +}) + +test_that("as.function works as expected for density", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + ep_func <- as.function(ep, func_type = "density") + expect_type(ep_func, type = "closure") + expect_length(formals(ep_func), 1) +}) + +test_that("as.function works as expected for cdf", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + ep_func <- as.function(ep, func_type = "cdf") + expect_type(ep_func, type = "closure") + expect_length(formals(ep_func), 1) +}) + +test_that("as.function works as expected for generate", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + ep_func <- as.function(ep, func_type = "generate") + expect_type(ep_func, type = "closure") + expect_length(formals(ep_func), 1) +}) + +test_that("as.function works as expected for quantile", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + ep_func <- as.function(ep, func_type = "quantile") + expect_type(ep_func, type = "closure") + expect_length(formals(ep_func), 1) +}) + +test_that("as.function fails as expected", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + expect_error( + as.function(ep, func_type = "random"), + regexp = "(arg)*(should be one of)*(density)*(cdf)*(generate)*(quantile)" + ) + + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = "gamma" + )) + expect_error( + as.function(ep), + regexp = "Cannot convert unparameterised to distribution function" + ) +}) + +test_that("as.data.frame works for ", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter( + disease = "ebola", + epi_name = "incubation", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1) + ) + )) + df <- as.data.frame(ep) + expect_s3_class(df, class = "data.frame") + expect_identical(dim(df), c(1L, 10L)) + expect_identical( + colnames(df), + c("disease", "pathogen", "epi_name", "prob_distribution", + "uncertainty", "summary_stats", "citation", "metadata", "method_assess", + "notes") + ) +}) + +test_that("as.data.frame works for from db", { + # message about missing citation suppressed + ep <- suppressMessages(epiparameter_db(single_epiparameter = TRUE)) + df <- as.data.frame(ep) + expect_s3_class(df, class = "data.frame") + expect_identical(dim(df), c(1L, 10L)) + expect_identical( + colnames(df), + c("disease", "pathogen", "epi_name", "prob_distribution", + "uncertainty", "summary_stats", "citation", "metadata", "method_assess", + "notes") + ) +}) + +{ + suppressMessages( + db <- epiparameter_db() + ) + ep <- db[[1]] +} + +test_that("c.epiparameter works as expected with two s", { + res <- c(ep, ep) + expect_s3_class(res, class = "multi_epiparameter") + expect_length(res, 2) + expect_s3_class(res[[1]], class = "epiparameter") +}) + +test_that("c.epiparameter works as expected with one ", { + res <- c(ep) + expect_s3_class(res, class = "epiparameter") + expect_true(test_epiparameter(res)) +}) + +test_that("c.epiparameter works with & ", { + res <- c(ep, db) + expect_s3_class(res, class = "multi_epiparameter") + expect_length(res, length(db) + 1) + expect_s3_class(res[[1]], class = "epiparameter") +}) + +test_that("c.multi_epiparameter works with two s", { + res <- c(db, db) + expect_s3_class(res, class = "multi_epiparameter") + expect_length(res, 250) + expect_s3_class(res[[1]], class = "epiparameter") +}) + +test_that("c.multi_epiparameter works with one ", { + res <- c(db) + expect_s3_class(res, class = "multi_epiparameter") + expect_length(res, length(db)) +}) + +test_that("c.multi_epiparameter works & ", { + res <- c(db, ep) + expect_s3_class(res, class = "multi_epiparameter") + expect_length(res, length(db) + 1) + expect_s3_class(res[[1]], class = "epiparameter") +}) + +test_that("c.epiparameter preserves input order", { + res <- c(ep, db, ep) + expect_s3_class(res, class = "multi_epiparameter") + expect_length(res, length(db) + 2) + expect_true(identical(res[[1]], res[[2]])) + expect_true(identical(res[[1]], res[[length(res)]])) +}) + +test_that("c.epiparameter fails as expected", { + expect_error( + c(ep, 1), + regexp = "Can only combine or objects" + ) +}) diff --git a/tests/testthat/test-epiparameter_db.R b/tests/testthat/test-epiparameter_db.R new file mode 100644 index 000000000..acab0064d --- /dev/null +++ b/tests/testthat/test-epiparameter_db.R @@ -0,0 +1,254 @@ +test_that("epiparameter_db works as expected", { + # suppress message about citation + db <- suppressMessages( + epiparameter_db(disease = "influenza", epi_name = "serial interval") + ) + + expect_s3_class(db, class = "epiparameter") + expect_length(db, 10) +}) + +test_that("epiparameter_db works as expected with author specified", { + # suppress message about citation + ep <- suppressMessages( + epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + author = "Ghani" + ) + ) + + expect_s3_class(ep, class = "epiparameter") + expect_length(ep, 10) +}) + +test_that("epiparameter_db works as expected with subsetting", { + # suppress message about citation + ep <- suppressMessages( + epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + subset = sample_size > 100 + ) + ) + + expect_s3_class(ep, class = "multi_epiparameter") + expect_length(ep, 10) +}) + +test_that("epiparameter_db works as expected with functional subsetting", { + db <- suppressMessages( + epiparameter_db( + disease = "COVID-19", + epi_name = "incubation period", + subset = is_parameterised + ) + ) + + expect_type(db, "list") + expect_s3_class(db, "multi_epiparameter") + expect_length(db, 11) +}) + +test_that("epiparameter_db works as expected with single_epiparameter as TRUE", { + # suppress message about citation + ep <- suppressMessages( + epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + single_epiparameter = TRUE + ) + ) + + expect_s3_class(ep, class = "epiparameter") + expect_length(ep, 10) +}) + +test_that("epiparameter_db chooses truncated with single_epiparameter as TRUE", { + # suppress message about citation + ep <- suppressMessages( + epiparameter_db( + disease = "COVID-19", + epi_name = "onset to death", + single_epiparameter = TRUE + ) + ) + + expect_s3_class(ep, class = "epiparameter") + expect_true(ep$method_assess$right_truncated) +}) + +test_that("epiparameter_db works as expected with subsetting and single_epiparameter", { + ep <- suppressMessages( + epiparameter_db( + disease = "COVID-19", + epi_name = "incubation period", + subset = sample_size > 50, + single_epiparameter = TRUE + ) + ) + + expect_s3_class(ep, class = "epiparameter") + expect_length(ep, 10) +}) + +test_that("epiparameter_db works as expected with subsetting and author", { + db <- suppressMessages( + epiparameter_db( + disease = "COVID-19", + epi_name = "incubation period", + author = "McAloon", + subset = sample_size > 10 + ) + ) + + expect_s3_class(db, class = "multi_epiparameter") + expect_length(db, 2) +}) + +test_that("epiparameter_db works as expected with subsetting by prod_dist", { + ep <- suppressMessages( + epiparameter_db( + disease = "COVID-19", + epi_name = "serial interval", + author = "Nishiura", + subset = prob_dist == "weibull" + ) + ) + + expect_s3_class(ep, class = "epiparameter") + expect_length(ep, 10) +}) + +test_that("epiparameter_db works as expected with subsetting by pathogen", { + # suppress message about citation + db <- suppressMessages( + epiparameter_db( + pathogen = "SARS-CoV-2", + epi_name = "incubation period" + ) + ) + + expect_s3_class(db, class = "multi_epiparameter") + expect_length(db, 15) +}) + +test_that("epiparameter_db fails as expected when author not recognised", { + expect_error( + epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + author = "Lessler_et_al" + ), + regexp = "Parameters by Lessler_et_al are not available for influenza" + ) +}) + +test_that("epiparameter_db fails as expected when disease not recognised", { + expect_error( + epiparameter_db(disease = "COVI-19", epi_name = "incubation period"), + regexp = "incubation period distribution not available for COVI-19" + ) +}) + +test_that("epiparameter_db fails as expected when epi_name not recognised", { + expect_error( + epiparameter_db( + disease = "influenza", + epi_name = "delay dist" + ), + regexp = "delay dist distribution not available for influenza" + ) +}) + +test_that("epiparameter_db fails as expected with no entry in the database", { + expect_error( + epiparameter_db( + disease = "RSV", + epi_name = "serial interval" + ), + regexp = "No entries in the database meet the search criteria." + ) +}) + +test_that("epiparameter_db gives message as expected with multiple entries", { + expect_message( + epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + author = "Reich" + ), + regexp = "(Returning)*(results that match the criteria)" + ) +}) + +test_that("epiparameter_db fails as expected when subset given as string", { + expect_error( + epiparameter_db( + disease = "influenza", + epi_name = "incubation period", + subset = "author == 'Lessler_et_al'" + ), + regexp = "(Subsetting is done with expressions)" + ) +}) + +test_that("epiparameter_db fails as expected when subset returns no results", { + expect_error( + epiparameter_db( + disease = "covid-19", + epi_name = "incubation period", + subset = year == 2018 + ), + regexp = "No entries in the database meet the search criteria." + ) +}) + +test_that(".read_epiparameter_db works as expected", { + db <- .read_epiparameter_db() + expect_s3_class(db, class = "multi_epiparameter") + expect_type(db, type = "list") + expect_length(db, 125) + expect_true(all(vapply(db, is_epiparameter, FUN.VALUE = logical(1)))) +}) + +test_that("sysdata is the same as .read_epiparameter_db output", { + # skipped due to covr failing when checking body of object attributes + skip_on_covr() + # .read_epiparameter_db uses numerical optimisation which can converge to + # different parameter estimates + set.seed(1) + sysdat <- suppressMessages(epiparameter_db()) + db <- .read_epiparameter_db() + expect_equal(sysdat, db, tolerance = 2e-3) +}) + +test_that(".read_epiparameter_db fails correctly when jsonlite is not installed", { + with_mocked_bindings( + .is_pkg_installed = function(package) FALSE, + code = expect_error( + .read_epiparameter_db(), + regexp = + "Cannot use this internal function without \\{jsonlite\\} installed" # nolint file.path + ) + ) +}) + +test_that(".is_pkg_installed works as expected", { + expect_true(.is_pkg_installed(package = "distributional")) + expect_false(.is_pkg_installed(package = "jsonlit")) +}) + +test_that("as.data.frame works for ", { + # message about missing citation suppressed + db <- suppressMessages(epiparameter_db()) + df <- as.data.frame(db) + expect_s3_class(df, class = "data.frame") + expect_identical(dim(df), c(125L, 10L)) + expect_identical( + colnames(df), + c("disease", "pathogen", "epi_name", "prob_distribution", + "uncertainty", "summary_stats", "citation", "metadata", "method_assess", + "notes") + ) +}) diff --git a/tests/testthat/test-extract_param.R b/tests/testthat/test-extract_param.R new file mode 100644 index 000000000..67796537c --- /dev/null +++ b/tests/testthat/test-extract_param.R @@ -0,0 +1,467 @@ +test_that("extract_param works for lnorm from percentiles", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + lnorm_params <- suppressMessages(extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "lnorm", + percentiles = c(0.125, 0.875) + )) + expect_equal( + lnorm_params, + c(meanlog = 2.178355650131613, sdlog = 0.336068813742589), + tolerance = testthat_tolerance() + ) +}) + +test_that("extract_param works for lnorm from median and range", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + lnorm_params <- suppressMessages(extract_param( + type = "range", + values = c(8, 4, 13), + distribution = "lnorm", + samples = 20 + )) + expect_equal( + lnorm_params, + c(meanlog = 2.07944157390479, sdlog = 4.25373938812171), + tolerance = testthat_tolerance() + ) +}) + +test_that("extract_param works for gamma from percentiles", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + gamma_params <- suppressMessages(extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "gamma", + percentiles = c(0.125, 0.875) + )) + expect_equal( + gamma_params, + c(shape = 9.20039196528191, scale = 1.02058982449651), + tolerance = testthat_tolerance() + ) +}) + +test_that("extract_param works for gamma from median and range", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + gamma_params <- suppressMessages(extract_param( + type = "range", + values = c(8, 4, 13), + distribution = "gamma", + samples = 20 + )) + # tolerance on this test is smaller because of differences across OS + expect_equal( + gamma_params, + c(shape = 10.818161002571626, scale = 0.762652109735326), + tolerance = 1e-3 + ) +}) + +test_that("extract_param works for Weibull from percentiles", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + weibull_params <- suppressMessages(extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "weibull", + percentiles = c(0.125, 0.875) + )) + expect_equal( + weibull_params, + c(shape = 3.55090029647809, scale = 10.57799242826989), + tolerance = testthat_tolerance() + ) +}) + +test_that("extract_param works for Weibull from median and range", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + weibull_params <- suppressMessages(extract_param( + type = "range", + values = c(8, 4, 13), + distribution = "weibull", + samples = 20 + )) + expect_equal( + weibull_params, + c(shape = 3.55994647578890, scale = 8.87141329172117), + tolerance = testthat_tolerance() + ) +}) + +test_that("extract_param works for norm from percentiles", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + norm_params <- suppressMessages(extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "norm", + percentiles = c(0.125, 0.875) + )) + expect_equal( + norm_params, + c(mean = 9.5, sd = 3.04255375956), + tolerance = testthat_tolerance() + ) +}) + +test_that("extract_param works for norm from median and range", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + norm_params <- suppressMessages(extract_param( + type = "range", + values = c(8, 4, 13), + distribution = "norm", + samples = 20 + )) + expect_equal( + norm_params, + c(mean = 8.00251593243, sd = 2.40820948602), + tolerance = testthat_tolerance() + ) +}) + +test_that("extract_param warns when max_iter exceeded", { + # set seed for stochastic optimisation + set.seed(1) + # suppress messages for testing + expect_warning( + suppressMessages(extract_param( + type = "percentiles", + values = c(2, 10), + distribution = "lnorm", + percentiles = c(0.05, 0.95), + control = list(max_iter = 5) + )), + regexp = paste0( + "(Maximum optimisation iterations reached)*(returning result early)*", + "(Result may not be reliable)" + ) + ) + + # suppress messages for testing + expect_warning( + suppressMessages(extract_param( + type = "range", + values = c(5, 2, 10), + distribution = "lnorm", + samples = 10, + control = list(max_iter = 5) + )), + regexp = paste0( + "(Maximum optimisation iterations reached)*(returning result early)*", + "(Result may not be reliable)" + ) + ) +}) + +test_that("extract_param fails as expected", { + expect_error( + extract_param( + type = "type", + values = c(6, 13), + distribution = "lnorm", + percentiles = c(0.125, 0.875) + ), + regexp = paste0( + "'arg' should be one of ", dQuote("percentiles"), ", ", + dQuote("range") + ) + ) + + expect_error( + extract_param( + type = "percentiles", + values = "values", + distribution = "lnorm", + percentiles = c(0.125, 0.875) + ), + regexp = "(Assertion)*(failed: Must be of type)*(numeric)*(not)*(character)" + ) + + expect_error( + extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "distribution", + percentiles = c(0.125, 0.875) + ), + regexp = paste0( + "'arg' should be one of ", dQuote("lnorm"), ", ", + dQuote("gamma"), ", ", dQuote("weibull") + ) + ) + + expect_error( + extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "lnorm", + percentiles = c("0.125", 0.875) + ), + regexp = paste0( + "Assertion on 'percentiles' failed: Must be of type", + " 'numeric', not 'character'." + ) + ) + + expect_error( + extract_param( + type = "range", + values = c(8, 4, 13), + distribution = "lnorm", + samples = "20" + ), + regexp = paste0( + "Assertion on 'samples' failed: Must be of type ", + "'number', not 'character'." + ) + ) + + expect_error( + extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "lnorm", + percentiles = c(0.125, 0.875), + control = list(extra = 1) + ), + regexp = "control list requires max_iter and tolerance elements" + ) +}) + +test_that(".extract_param works for lnorm percentiles", { + # set seed for stochastic optimisation + set.seed(1) + lnorm_params <- .extract_param( + values = c(6, 13), + distribution = "lnorm", + percentiles = c(0.125, 0.875) + ) + + expect_equal( + lnorm_params, + list( + par = c(meanlog = 2.13097474713655e+00, sdlog = 1.00000008274037e-10), + value = 0.03125, + counts = c("function" = 7, "gradient" = 7), + convergence = 0, + message = "CONVERGENCE: NORM OF PROJECTED GRADIENT <= PGTOL" + ), + tolerance = testthat_tolerance() + ) +}) + +test_that(".extract_param works for gamma percentiles", { + # set seed for stochastic optimisation + set.seed(1) + gamma_params <- .extract_param( + values = c(6, 13), + distribution = "gamma", + percentiles = c(0.125, 0.875) + ) + + expect_equal( + gamma_params, + list( + par = c(shape = 9.20038735184127, scale = 1.02058983834422), + value = 2.45662828557338e-14, + counts = c("function" = 30, "gradient" = 30), + convergence = 0, + message = "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH" + ), + tolerance = testthat_tolerance() + ) +}) + +test_that(".extract_param works for Weibull percentiles", { + # set seed for stochastic optimisation + set.seed(1) + weibull_params <- .extract_param( + values = c(6, 13), + distribution = "weibull", + percentiles = c(0.125, 0.875) + ) + + expect_equal( + weibull_params, + list( + par = c(shape = 0.0000000001000, scale = 2.6184985826797), + value = 0.316161684132644, + counts = c("function" = 6, "gradient" = 6), + convergence = 0, + message = "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH" + ), + tolerance = testthat_tolerance() + ) +}) + +test_that(".extract_param works for lnorm range", { + # set seed for stochastic optimisation + set.seed(1) + lnorm_params <- .extract_param( + values = c(8, 4, 13), + distribution = "lnorm", + samples = 20 + ) + + expect_equal( + lnorm_params, + list( + par = c(meanlog = 2.07944153869882, sdlog = 1.95820599716772), + value = -3.81451307459282e-15, + counts = c("function" = 6, "gradient" = 6), + convergence = 0, + message = "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH" + ), + tolerance = testthat_tolerance() + ) +}) + +test_that(".extract_param works for gamma range", { + # set seed for stochastic optimisation + set.seed(1) + gamma_params <- .extract_param( + values = c(8, 4, 13), + distribution = "gamma", + samples = 20 + ) + + expect_equal( + gamma_params, + list( + par = c(shape = 2.72933343452509, scale = 3.32748567278955), + value = -8.1823252560062e-07, + counts = c("function" = 10, "gradient" = 10), + convergence = 0, + message = "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH" + ), + tolerance = testthat_tolerance() + ) +}) + +test_that(".extract_param works for Weibull range", { + # set seed for stochastic optimisation + set.seed(1) + weibull_params <- .extract_param( + values = c(8, 4, 13), + distribution = "weibull", + samples = 20 + ) + + expect_equal( + weibull_params, + list( + par = c(shape = 0.0000000001000, scale = 2.5047337931743), + value = 0.0174558420764588, + counts = c("function" = 8, "gradient" = 8), + convergence = 0, + message = "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH" + ), + tolerance = testthat_tolerance() + ) +}) + +test_that(".extract_param fails as expected", { + expect_error( + .extract_param( + values = c(8, 4, 13), + distribution = "weibull" + ), + regexp = "percentiles or samples arguments must be specified" + ) +}) + +test_that(".fit_range works for lnorm for valid input", { + lnorm_range <- .fit_range( + param = c(meanlog = 2.0, sdlog = 0.5), + val = c(median = 8, lower = 4, upper = 13, n = 20), + dist = "lnorm" + ) + reference <- 0.00396181460097 + expect_equal(lnorm_range, reference, tolerance = testthat_tolerance()) +}) + +test_that(".fit_range works for gamma for valid input", { + gamma_range <- .fit_range( + param = c(shape = 2.0, scale = 0.5), + val = c(median = 8, lower = 4, upper = 13, n = 20), + dist = "gamma" + ) + reference <- 0.249998086906 + expect_equal(gamma_range, reference, tolerance = testthat_tolerance()) +}) + +test_that(".fit_range works for weibull for valid input", { + weibull_range <- .fit_range( + param = c(shape = 2.0, scale = 0.5), + val = c(median = 8, lower = 4, upper = 13, n = 20), + dist = "weibull" + ) + reference <- 0.25 + expect_equal(weibull_range, reference, tolerance = testthat_tolerance()) +}) + +test_that(".fit_range works for norm for valid input", { + norm_range <- .fit_range( + param = c(mean = 2.0, sd = 0.5), + val = c(median = 8, lower = 4, upper = 13, n = 20), + dist = "norm" + ) + reference <- 0.25 + expect_equal(norm_range, reference, tolerance = testthat_tolerance()) +}) + +test_that(".fit_percentiles works for lnorm for valud input", { + lnorm <- .fit_percentiles( + param = c(meanlog = 2.0, sdlog = 0.5), + val = c(lower = 6.0, upper = 13.0, q1 = 0.125, q2 = 0.875), + dist = "lnorm" + ) + reference <- 0.0456127816304 + expect_equal(lnorm, reference, tolerance = testthat_tolerance()) +}) + +test_that(".fit_percentiles works for gamma for valid input", { + gamma <- .fit_percentiles( + param = c(shape = 2.0, scale = 0.5), + val = c(lower = 6.0, upper = 13.0, q1 = 0.125, q2 = 0.875), + dist = "gamma" + ) + reference <- 0.781110225514 + expect_equal(gamma, reference, tolerance = testthat_tolerance()) +}) + +test_that(".fit_percentiles works for weibull for valid input", { + weibull <- .fit_percentiles( + param = c(shape = 2.0, scale = 0.5), + val = c(lower = 6.0, upper = 13.0, q1 = 0.125, q2 = 0.875), + dist = "weibull" + ) + reference <- 0.78125 + expect_equal(weibull, reference, tolerance = testthat_tolerance()) +}) + +test_that(".fit_percentiles works for norm for valud input", { + norm <- .fit_percentiles( + param = c(mean = 2.0, sd = 0.5), + val = c(lower = 6.0, upper = 13.0, q1 = 0.125, q2 = 0.875), + dist = "norm" + ) + reference <- 0.78125 + expect_equal(norm, reference, tolerance = testthat_tolerance()) +}) diff --git a/tests/testthat/test-get_percentiles.R b/tests/testthat/test-get_percentiles.R new file mode 100644 index 000000000..1f02f78cd --- /dev/null +++ b/tests/testthat/test-get_percentiles.R @@ -0,0 +1,86 @@ +test_that(".get_percentiles works as expected", { + res <- .get_percentiles(c("5" = 1, "95" = 10)) + expect_identical(res, c("5" = 1, "95" = 10)) + + res <- .get_percentiles(c("2.5" = 1, "97.5" = 10)) + expect_identical(res, c("2.5" = 1, "97.5" = 10)) + + res <- .get_percentiles(c("5" = 1, "45" = 10)) + expect_identical(res, NA) + + res <- .get_percentiles(c("55" = 1, "90" = 10)) + expect_identical(res, NA) +}) + +test_that(".get_percentiles fails as expected", { + expect_error( + .get_percentiles("string"), + regexp = "(Assertion on 'percentiles' failed)*(type 'numeric')" + ) + + expect_error( + .get_percentiles(c(1, 10)), + regexp = "Assertion on 'percentiles' failed: Must have names." + ) +}) + +test_that(".get_sym_percentiles works as expected for symmetrical", { + # trivial case + percentiles <- c("5" = 5, "95" = 15) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("5" = 5, "95" = 15)) + + # case without NAs + percentiles <- c( + "2.5" = 1, "5" = 5, "95" = 15, "99" = 25 + ) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("5" = 5, "95" = 15)) + + # case with NAs + percentiles <- c( + "2.5" = 1, "5" = 5, "25" = NA, "75" = NA, "95" = 15, "99" = 25 + ) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("5" = 5, "95" = 15)) + + # case with multiple symmetrical percentiles + percentiles <- c( + "2.5" = 1, "5" = 5, "25" = 7, "75" = 10, "95" = 15, "99" = 25 + ) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("25" = 7, "75" = 10)) +}) + +test_that(".get_sym_percentiles works as expected for asymmetrical", { + # trivial case + percentiles <- c("2.5" = 5, "95" = 15) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("2.5" = 5, "95" = 15)) + + # case without NAs + percentiles <- c( + "2.5" = 1, "25" = 5, "95" = 15, "99" = 25 + ) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("2.5" = 1, "99" = 25)) + + # case with NAs + percentiles <- c( + "2.5" = 5, "25" = NA, "87.5" = NA, "95" = 15, "99" = 25 + ) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("2.5" = 5, "99" = 25)) + + # case with multiple equally asymmetrical percentiles + percentiles <- c( + "2.5" = 1, "5" = 5, "25" = 7, "75" = 10, "95" = 15, "97.5" = 25 + ) + sym_percentiles <- .get_sym_percentiles(percentiles = percentiles) + expect_identical(sym_percentiles, c("25" = 7, "75" = 10)) +}) + +test_that(".get_sym_percentiles works as expected for all NAs", { + percentiles <- c("2.5" = NA, "95" = NA) + expect_true(is.na(.get_sym_percentiles(percentiles = percentiles))) +}) diff --git a/tests/testthat/test-parameter_tbl.R b/tests/testthat/test-parameter_tbl.R new file mode 100644 index 000000000..8c24a336f --- /dev/null +++ b/tests/testthat/test-parameter_tbl.R @@ -0,0 +1,174 @@ +# Data to be reused by multiple testing blocks +db <- suppressMessages(epiparameter_db()) + +test_that("parameter_tbl works as expected supplied with db", { + dist_tbl <- parameter_tbl(multi_epiparameter = db) + expect_s3_class(dist_tbl, "data.frame") + expect_identical(dim(dist_tbl), c(125L, 7L)) + expect_named( + dist_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(dist_tbl) +}) + +test_that("parameter_tbl works for incubation period with db", { + incub_tbl <- parameter_tbl( + multi_epiparameter = db, + epi_name = "incubation period" + ) + expect_s3_class(incub_tbl, "data.frame") + expect_identical(dim(incub_tbl), c(73L, 7L)) + expect_named( + incub_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(incub_tbl) +}) + +test_that("parameter_tbl works for different distribution with db", { + serial_tbl <- parameter_tbl( + multi_epiparameter = db, + epi_name = "serial interval" + ) + expect_s3_class(serial_tbl, "data.frame") + expect_identical(dim(serial_tbl), c(18L, 7L)) + expect_named( + serial_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(serial_tbl) +}) + +test_that("parameter_tbl works for COVID-19 db", { + incub_tbl <- parameter_tbl( + multi_epiparameter = db, + disease = "COVID-19" + ) + expect_s3_class(incub_tbl, "data.frame") + expect_identical(dim(incub_tbl), c(27L, 7L)) + expect_named( + incub_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(incub_tbl) +}) + +test_that("parameter_tbl works for SARS-CoV-2 db", { + incub_tbl <- parameter_tbl( + multi_epiparameter = db, + pathogen = "SARS-CoV-2" + ) + expect_s3_class(incub_tbl, "data.frame") + expect_identical(dim(incub_tbl), c(27L, 7L)) + expect_named( + incub_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(incub_tbl) +}) + +test_that("parameter_tbl works for disease & epi_name subset with db", { + incub_tbl <- parameter_tbl( + multi_epiparameter = db, + disease = "COVID-19", + epi_name = "incubation period" + ) + expect_s3_class(incub_tbl, "data.frame") + expect_identical(dim(incub_tbl), c(15L, 7L)) + expect_named( + incub_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(incub_tbl) +}) + +test_that("parameter_tbl works when supplied a subset db", { + db <- suppressMessages(epiparameter_db(disease = "COVID-19")) + covid_tbl <- parameter_tbl(multi_epiparameter = db, disease = "COVID-19") + expect_s3_class(covid_tbl, "data.frame") + expect_identical(dim(covid_tbl), c(27L, 7L)) + expect_named( + covid_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(covid_tbl) +}) + +test_that("parameter_tbl works as expected supplied with ", { + db <- suppressMessages(epiparameter_db(single_epiparameter = TRUE)) + dist_tbl <- parameter_tbl(multi_epiparameter = db) + expect_s3_class(dist_tbl, "data.frame") + expect_identical(dim(dist_tbl), c(1L, 7L)) + expect_named( + dist_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(dist_tbl) +}) + +test_that("parameter_tbl works as expected with discretised ", { + ep <- suppressMessages( + epiparameter( + disease = "Ebola", + epi_name = "serial interval", + prob_distribution = "gamma", + prob_distribution_params = c(shape = 1, scale = 1), + citation = create_citation( + author = person(given = "John", family = "Smith"), + year = 2022, + title = "A title", + journal = "A journal", + doi = "10.32561.x" + ), + discretise = TRUE + ) + ) + dist_tbl <- parameter_tbl(multi_epiparameter = ep) + expect_s3_class(dist_tbl, "data.frame") + expect_identical(dim(dist_tbl), c(1L, 7L)) + expect_named( + dist_tbl, + c("disease", "pathogen", "epi_name", "prob_distribution", + "author", "year", "sample_size") + ) + expect_snapshot(dist_tbl) +}) + +test_that("parameter_tbl fails correctly when subsetting a subset db", { + ep <- suppressMessages(epiparameter_db(disease = "Ebola")) + expect_error( + parameter_tbl(multi_epiparameter = ep, disease = "COVID-19"), + regexp = "(distribution not available for COVID-19)" + ) +}) + +test_that("parameter_tbl fails correctly", { + # check for incorrect input + expect_error( + parameter_tbl( + multi_epiparameter = list(), + epi_name = "incubation_period" + ), + regexp = "List of objects should be supplied to multi_epiparameter" + ) + + expect_error( + parameter_tbl(multi_epiparameter = db, epi_name = "random"), + regexp = "random distribution not available" + ) + + # check for multiple match input + expect_error( + parameter_tbl(multi_epiparameter = db, epi_name = "onset"), + regexp = "onset distribution not available" + ) +}) diff --git a/tests/testthat/test-print.R b/tests/testthat/test-print.R new file mode 100644 index 000000000..113236ee3 --- /dev/null +++ b/tests/testthat/test-print.R @@ -0,0 +1,9 @@ +test_that("epiparameter_db print method works as expected for > 5 ", { + expect_snapshot(epiparameter_db()) +}) + +test_that("epiparameter_db print method works as expected for <= 5 ", { + expect_snapshot( + epiparameter_db(disease = "SARS", epi_name = "offspring distribution") + ) +}) \ No newline at end of file diff --git a/tests/testthat/test-utils.R b/tests/testthat/test-utils.R new file mode 100644 index 000000000..8a03c4518 --- /dev/null +++ b/tests/testthat/test-utils.R @@ -0,0 +1,105 @@ +test_that("calc_disc_dist_quantile works as expected", { + prob <- dgamma(seq(0, 10, length.out = 21), shape = 2, scale = 2) + days <- seq(0, 10, 0.5) + quantiles <- c(0.025, 0.975) + quants <- calc_disc_dist_quantile( + prob = prob, + days = days, + quantile = quantiles + ) + expect_vector(quants) + expect_named(quants, expected = as.character(quantiles)) + expect_equal( + quants, + c("0.025" = 0, "0.975" = 9), + tolerance = testthat_tolerance() + ) +}) + +test_that("calc_disc_dist_quantile fails as expected", { + prob <- dgamma(seq(0, 10, length.out = 21), shape = 2, scale = 2) + days <- seq(0, 10, 0.5) + quantiles <- c(0.025, 0.975) + expect_error( + calc_disc_dist_quantile( + prob = "prob", + days = days, + quantile = quantiles + ), + regexp = paste0( + "Assertion on 'prob' failed: Must be of type 'numeric',", + " not 'character'." + ) + ) + + expect_error( + calc_disc_dist_quantile( + prob = prob, + days = "days", + quantile = quantiles + ), + regexp = paste0( + "Assertion on 'days' failed: Must be of type 'numeric',", + " not 'character'." + ) + ) + + expect_error( + calc_disc_dist_quantile( + prob = prob, + days = days, + quantile = "quantiles" + ), + regexp = paste0( + "Assertion on 'quantile' failed: Must be of type 'numeric',", + " not 'character'." + ) + ) +}) + +test_that(".citet works as expected for multi-author", { + suppressMessages( + epiparameter <- epiparameter_db( + author = "Lessler", + disease = "RSV", + single_epiparameter = TRUE + ) + ) + expect_identical(.citet(epiparameter$citation), "Lessler et al. (2009)") +}) + +test_that(".citet works as expected for single author", { + suppressMessages( + epiparameter <- epiparameter_db( + author = "Pavlin", + disease = "Marburg", + single_epiparameter = TRUE + ) + ) + expect_identical(.citet(epiparameter$citation), "Pavlin (2014)") +}) + +test_that(".citet works as expected for two authors", { + suppressMessages( + epiparameter <- epiparameter_db( + author = "Nishiura", + disease = "Influenza", + single_epiparameter = TRUE + ) + ) + expect_identical(.citet(epiparameter$citation), "Nishiura & Inaba (2011)") +}) + +test_that(".citet works as expected for organisation author", { + suppressMessages( + epiparameter <- epiparameter_db( + author = "WHO", + disease = "Ebola", + single_epiparameter = TRUE + ) + ) + expect_identical( + .citet(epiparameter$citation), + "WHO Ebola Response Team et al. (2015)" + ) +}) diff --git a/tools/check.env b/tools/check.env new file mode 100644 index 000000000..da57060c3 --- /dev/null +++ b/tools/check.env @@ -0,0 +1,18 @@ +# Do not report if package size is larger than 5 megabytes +_R_CHECK_PKG_SIZES_=false + +# Do not check Rd cross references +_R_CHECK_RD_XREFS_=false + +# Do not report if package requires GNU make +# https://github.com/epiverse-trace/packagetemplate/issues/119 +# https://github.com/r-lib/rcmdcheck/pull/219 +_R_CHECK_CRAN_INCOMING_NOTE_GNU_MAKE_=true + +# Do not check non-ASCII strings in datasets +_R_CHECK_PACKAGE_DATASETS_SUPPRESS_NOTES_=true + +# Exists since R 4.3.0 but `false` by default. +# https://bugs.r-project.org/show_bug.cgi?id=18419 +# Warn when using : with an element of length more than one +_R_CHECK_LENGTH_COLON_=true \ No newline at end of file diff --git a/vignettes/.gitignore b/vignettes/.gitignore new file mode 100644 index 000000000..aff8f7db9 --- /dev/null +++ b/vignettes/.gitignore @@ -0,0 +1,3 @@ +*.html +*.R +!precompile.R diff --git a/vignettes/_extract-bias.Rmd.orig b/vignettes/_extract-bias.Rmd.orig new file mode 100644 index 000000000..963a72cf7 --- /dev/null +++ b/vignettes/_extract-bias.Rmd.orig @@ -0,0 +1,498 @@ +--- +title: "{epiparameter} Extraction Bias Analysis" +output: + bookdown::html_vignette2: + fig_caption: yes + code_folding: show +vignette: > + %\VignetteIndexEntry{{epiparameter} Extraction Bias Analysis} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.width = 8 +) +``` + +::: {.alert .alert-info} +If you are unfamiliar with the parameter extraction functionality in {epiparameter} +the [Conversion and Extraction vignette](extract_convert.html) is a great place to start. +::: + +The {epiparameter} R package contains a set of functions to extract parameters +of probability distributions given a set of summary statistics. These summary statistics can +be the values at given percentiles of a distribution, or the median and range of +a data set to which a distribution can be fit. Using these and specifying the distribution +(e.g. gamma, lognormal, etc.) the parameters of the distribution can be extracted by +optimisation using least-squares. + +The precision and bias of this approach needs to be explored across the parameter space +of the different distributions to understand potential erroneous inferences. This +vignette aims to explore this inference bias for three distributions currently +supported in {epiparameter} for parameter extraction: gamma, lognormal and Weibull. Extraction +of parameters from a normal distribution is also supported in {epiparameter} but we +do not test that in this vignette. + +::: {.alert .alert-warning} +This is not an in depth analysis of the estimation methods implemented in {epiparameter}, +but rather a supplementary article exploring the bias and precision of the functions. +It is specific to the case of {epiparameter} and should not be taken as a generalisable result. +::: + +```{r setup} +library(epiparameter) +library(ggplot2) +``` + +## Extraction Bias + +### Extraction by percentiles + +First we explore extraction from percentiles. + +If a study reports the percentiles of a distribution, they are usually symmetrical +(e.g. 5th and 95th, or 2.5th and 97.5th). However, in a few instances, only asymmetrical +percentiles are available. We test whether asymmetry to varying degrees influences the +bias of parameter extraction for all distributions. + +We set up the parameter space to explore: + +```{r, set-up-parameter-space-percentiles} +distributions <- c("gamma", "lnorm", "weibull") +dist_parameters <- seq(0.5, 2, 0.5) +lower_percentiles <- c(2.5, 5, 25, 40) +upper_percentiles <- c(60, 95, 97.5) + +parameters_perc <- expand.grid( + dist = distributions, + param_1 = dist_parameters, + param_2 = dist_parameters, + lower = lower_percentiles, + upper = upper_percentiles +) + +# calculate the degree of asymmetry for each percentile combination +lw_interval_diff <- abs(0 - parameters_perc$lower) +up_interval_diff <- abs(100 - parameters_perc$upper) +deg_asym <- abs(lw_interval_diff - up_interval_diff) + +# add degree of asymmetry to percentiles +parameters_perc <- cbind(parameters_perc, deg_asym) + +# divide percentiles by 100 to make them probabilities for quantile functions +parameters_perc$lower <- parameters_perc$lower / 100 +parameters_perc$upper <- parameters_perc$upper / 100 +``` + +Now we can run the extraction for each point in parameter space. We set a seed +to control for stochasticity when estimating the parameters, however changing or +removing the seed should not drastically change the results or interpretation. + +```{r, set-seed} +set.seed(1) +``` + +```{r, run-extraction-percentile} +estim_params <- vector("list", nrow(parameters_perc)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_perc))) { + dist <- as.character(parameters_perc[params_idx, "dist"]) + percen <- unname(unlist(parameters_perc[params_idx, c("lower", "upper")])) + + if (dist == "lnorm") { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + meanlog = parameters_perc[params_idx, "param_1"], + sdlog = parameters_perc[params_idx, "param_2"] + ) + ) + } else { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + shape = parameters_perc[params_idx, "param_1"], + scale = parameters_perc[params_idx, "param_2"] + ) + ) + } + + # message about stochastic optimisation suppressed + estim_params[[params_idx]] <- suppressMessages( + extract_param( + type = "percentiles", + values = true_values, + distribution = dist, + percentiles = percen + ) + ) +} + +# combine results +results <- cbind(parameters_perc, do.call(rbind, estim_params)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "lower", "upper", + "deg_asym", "estim_param_1", "estim_param_2" +) + +# calculate absolute difference between true parameter and estimated value +results <- cbind( + results, + diff_param_1 = abs(results$param_1 - results$estim_param_1), + diff_param_2 = abs(results$param_2 - results$estim_param_2) +) +``` + +The `extract_param()` function re-runs the optimisation +until convergence to a set tolerance is achieved (or a maximum number of +iterations is reached) to more reliably return the global +optimum. In theory, this should help to minimise bias and instability in the +parameter estimation. See the function documentation (`?extract_param()`) or +the [Conversion and Extraction vignette](extract_convert.html) for more details. + +The extraction bias can be explored: + +```{r, plot-results-percentiles, class.source = 'fold-hide', fig.cap="Parameter estimation bias facetted by distribution. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution."} +# plot differences by distribution +ggplot(data = results) + + geom_point(mapping = aes( + x = diff_param_1, + y = diff_param_2, + colour = deg_asym + )) + + scale_x_continuous(name = "Parameter 1 Difference (|true - estimated|)") + + scale_y_continuous(name = "Parameter 2 Difference (|true - estimated|)") + + labs(colour = "Percentile Asym.") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +### Extraction by median and range + +The same analysis as above can be repeated, this time using the other summary +statistic possibly reported in studies: median and range of data. +For this extraction the number of samples used to infer the distribution is required +as this can impact the possible range exhibited by the data. + +Set up the parameter space: + +```{r, set-up-parameter-space-med-range} +n_samples <- c(10, 50, 100) +parameters_range <- expand.grid( + dist = distributions, # same as above + param_1 = dist_parameters, # same as above + param_2 = dist_parameters, # same as above + n_samples = n_samples +) +``` + +```{r run-extraction-med-range} +estim_params <- vector("list", nrow(parameters_range)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_range))) { + dist <- as.character(parameters_range[params_idx, "dist"]) + n_samples <- parameters_range[params_idx, "n_samples"] + # while loop to ensure values are min < median < max + resample_values <- TRUE + while (resample_values) { + if (dist == "lnorm") { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } else { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } + true_values <- c(true_median, true_range) + if (true_values[2] < true_values[1] && true_values[1] < true_values[3]) { + resample_values <- FALSE + } + } + # message about stochastic optimisation suppressed + estim_params[[params_idx]] <- suppressMessages( + expr = extract_param( + type = "range", + values = true_values, + distribution = dist, + samples = n_samples + ) + ) +} + +# combine results +results <- cbind(parameters_range, do.call(rbind, estim_params)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "n_samples", "estim_param_1", "estim_param_2" +) + +# calculate absolute difference between true parameter and estimated value +results <- cbind( + results, + diff_param_1 = abs(results$param_1 - results$estim_param_1), + diff_param_2 = abs(results$param_2 - results$estim_param_2) +) +``` + +Plot results: + +```{r, plot-results-med-range, class.source = 'fold-hide', fig.cap="Parameter extraction bias. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution."} +# plot differences by distribution +ggplot(data = results) + + geom_point( + mapping = aes( + x = diff_param_1, + y = diff_param_2, + colour = n_samples + ) + ) + + scale_x_continuous(name = "Parameter 1 Difference (|true - estimated|)") + + scale_y_continuous(name = "Parameter 2 Difference (|true - estimated|)") + + labs(colour = "No. Samples") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +## Extraction precision + +### Extraction by percentiles + +The two analyses above used a single extraction (replicate), however, it may be that +the estimation of the parameters is unstable for a given set of percentiles or median +range. Therefore, we finish with a test of whether repeated extraction of parameters +from a single percentile has large variance which would indicate the parameter extraction +is unstable, imprecise, and potentially untrustworthy. + +We use the same parameter space for percentiles as defined above +(`parameters_perc`). Now we can run the extraction for a set of replicates to +compute the variance of parameter estimates over those replicates. + +```{r, run-extraction-precision-percentile} +estim_param_var <- vector("list", nrow(parameters_perc)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_perc))) { + dist <- as.character(parameters_perc[params_idx, "dist"]) + percen <- unname(unlist(parameters_perc[params_idx, c("lower", "upper")])) + + if (dist == "lnorm") { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + meanlog = parameters_perc[params_idx, "param_1"], + sdlog = parameters_perc[params_idx, "param_2"] + ) + ) + } else { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + shape = parameters_perc[params_idx, "param_1"], + scale = parameters_perc[params_idx, "param_2"] + ) + ) + } + + # message about stochastic optimisation suppressed + estim <- suppressMessages( + replicate( + n = 5, + expr = extract_param( + type = "percentiles", + values = true_values, + distribution = dist, + percentiles = percen + ) + ) + ) + estim_param_var[[params_idx]] <- apply(estim, MARGIN = 1, FUN = var) +} + +# combine results +results <- cbind(parameters_perc, do.call(rbind, estim_param_var)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "lower", "upper", + "deg_asym", "estim_param_1_var", "estim_param_2_var" +) +``` + +```{r, plot-results, class.source = 'fold-hide', fig.cap="Parameter extraction precision, facetted by distribution. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution."} +ggplot(data = results) + + geom_point(mapping = aes( + x = estim_param_1_var, + y = estim_param_2_var, + colour = deg_asym + )) + + scale_x_continuous(name = "Parameter 1 Variance") + + scale_y_continuous(name = "Parameter 2 Variance") + + labs(colour = "Percentile Asym.") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +### Extraction by median and range + +The same test of estimation precision can be performed for the extraction from median and range. + + +```{r, run-extraction-precision-range} +estim_param_var <- vector("list", nrow(parameters_range)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_range))) { + dist <- as.character(parameters_range[params_idx, "dist"]) + n_samples <- parameters_range[params_idx, "n_samples"] + + # while loop to ensure values are min < median < max + resample_values <- TRUE + while (resample_values) { + if (dist == "lnorm") { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } else { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } + true_values <- c(true_median, true_range) + if (true_values[2] < true_values[1] && true_values[1] < true_values[3]) { + resample_values <- FALSE + } + } + # message about stochastic optimisation suppressed + estim <- suppressMessages( + replicate( + n = 5, + expr = extract_param( + type = "range", + values = true_values, + distribution = dist, + samples = n_samples + ) + ) + ) + estim_param_var[[params_idx]] <- apply(estim, MARGIN = 1, FUN = var) +} + +# combine results +results <- cbind(parameters_range, do.call(rbind, estim_param_var)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "n_samples", "estim_param_1_var", + "estim_param_2_var" +) +``` + +```{r, plot-estim-var-range, class.source = 'fold-hide', fig.cap="Parameter extraction precision, facetted by distribution. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution."} +ggplot(data = results) + + geom_point(mapping = aes( + x = estim_param_1_var, + y = estim_param_2_var, + colour = n_samples + )) + + scale_x_continuous(name = "Parameter 1 Variance") + + scale_y_continuous(name = "Parameter 2 Variance") + + labs(colour = "No. Samples") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +::: {.alert .alert-primary} +From the plots in this vignette, the bias is low and precision is high +when extracting parameters from the gamma, lognormal and Weibull distributions +from both percentiles of the distribution and from median and range of a data +set. + +The asymmetry of percentiles and sample size of the data does not noticeably +influence the bias in parameter extraction. + +However, this does not ensure reliable extract for all use cases of the +`extract_param()` function and we recommend checking the output for spurious +results. +::: diff --git a/vignettes/articles/data_from_epireview.Rmd b/vignettes/articles/data_from_epireview.Rmd new file mode 100644 index 000000000..97b5e6479 --- /dev/null +++ b/vignettes/articles/data_from_epireview.Rmd @@ -0,0 +1,288 @@ +--- +title: "Using {epireview} with {epiparameter}" +bibliography: ../references.json +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(epiparameter) +library(epireview) +``` + +The article describes how to use the {epireview} R package with {epiparameter}. {epireview} provides epidemiological parameters for a range of pathogens extracted from the literature by the Pathogen Epidemiology Review Group (PERG) in systematic reviews. The {epiparameter} R package can use these epidemiological parameters and can convert them into `` objects. + +::: {.alert .alert-warning} +This feature of interoperability of {epireview} and {epiparameter} is still under development. Currently only delay distributions (termed _Human delay_ in the "parameter_type" column in {epireview}'s database) are compatible with this feature. Attempting to convert other epidemiological parameters from {epireview} to {epiparameter} `` objects will likely error with an uninformative error message. +::: + +## Converting from {epireview} entries into an `` object + +The {epireview} package nicely provides epidemiological parameter data from systematically reviewing the literature, and {epiparameter} provides custom data structures for working with epidemiological data in R. Therefore, reading in data from the {epireview} R package and converting it to an `` object will provide the greatest utility when applied in outbreak analytics. + +Here we start with a simple example of reading in the Marburg data from {epireview} and converting to an `` object using `as_epiparameter()` function from the {epiparameter} package. + +```{r, load-marburg} +marburg_data <- load_epidata("marburg") +``` + +This loads a list with four tables, specifically `tibbles`, that contain the bibliographic information (`$articles`), epidemiological parameters (`$params`), epidemiological models (`$models`), and outbreak information (`$outbreaks`). + +```{r, marburg-list-names} +names(marburg_data) +``` + +We will start by just using the epidemiological parameter table to convert information into an ``. + +```{r, marburg-params} +marburg_params <- marburg_data$params +``` + +Out of these parameters, subset the data to only keep those rows that contain incubation periods for Marburg. + +```{r, subset-marburg-params} +marburg_incubation_period <- marburg_params[ + marburg_params$parameter_type_short == "incubation_period", +] +marburg_incubation_period +``` + +We will select the first entry to use as the first example: + +```{r, select-marburg-entry} +marburg_incub <- marburg_incubation_period[1, ] +marburg_incub +``` + +Then we can simply pass our epidemiological parameter set to `as_epiparameter()` to do the conversion. + +```{r, convert-to-epiparameter-single-entry} +marburg_incub_epiparameter <- as_epiparameter(marburg_incub) +marburg_incub_epiparameter +``` + +The resulting `` does not contain a parameterised probability distribution, instead it contains a range for the incubation period (in `$summary_stats`), and the `$metadata` shows that this is a single case from South Africa. + +```{r, show-epiparameter-single-entry-data} +marburg_incub_epiparameter$summary_stats +marburg_incub_epiparameter$metadata +``` + +## Creating an `` with full citation + +The last example showed how to convert the epidemiological parameter information, however, you may have noticed that the citation that was created did not contain the information for a full citation. + +```{r, show-incomplete-citation} +marburg_incub_epiparameter$citation +``` + +In order to provide a complete citation to the `` object, which is highly recommended so that you know the provenance of the parameters and can correctly attribute the original authors, we will need to also provide the bibliographic information from {epireview} as well as the epidemiological parameters. + +The article data needs to be loaded from {epireview} using `epireview::load_epidata_raw()` rather than `epireview::load_data()` because `load_data()` subsets the bibliographic information to only provide: `"id"`, `"first_author_surname"`, `"year_publication"`, and `"article_label"` columns. + +```{r, load-epreview-articles} +marburg_articles <- load_epidata_raw( + pathogen = "marburg", + table = "article" +) +marburg_articles +``` + +We need to match the entry in the epidemiological parameter table with the citation information in the article table to ensure we are using the correct citation for the parameter set. Thankfully, this can easily be achieved as {epireview} provides unique IDs to each table to link entries. + +```{r, match-parameter-to-article} +article_row <- match(marburg_incub$id, marburg_articles$id) +article_row +``` + +```{r, subset-articles} +marburg_incub_article <- marburg_articles[article_row, ] +marburg_incub_article +``` + +Now we can repeat the example of converting to `` as shown above, but this time pass the bibliographic information as well as the epidemiological parameter information to create a full citation. The bibliographic information needs to be passed with the `article` argument. + +```{r, convert-to-epiparameter-full-citation} +marburg_incub_epiparameter <- as_epiparameter( + marburg_incub, + article = marburg_incub_article +) +marburg_incub_epiparameter +``` + +```{r, show-full-citation} +marburg_incub_epiparameter$citation +``` + +::: {.alert .alert-info} +The `as_epiparameter()` function is an S3 generic. If you are not familiar with S3 object-oriented programming in R, then this detail is not important, however, it does mean that the `article` argument is not explicitly in the function definition of `as_epiparameter()` (i.e. it will not show up on autocomplete when typing out the function and will not be shown if you read the function help page `?as_epiparameter()`). Instead, the argument is specified as part of the `...` argument. This is because the `article` argument is only required when converting data from {epireview} into ``, and other data that can be converted to `` objects do not require this argument. +::: + +## Multi-row {epireview} entries + +In general, all required values for a parameter are represented as a _single_ entry in epireview. In some of cases, e.g. for Marburg Virus Disease and Ebola Virus Disease (as the first pathogens the PERG team extracted), values captured for a parameter are on multiple rows. We are trying to avoid this as _linking_ these entries is very challenging, but there are still some cases in which there are linked parameters on different rows. We provide further information in the limitations section below. + +The way the {epireview} data is stored means that some epidemiological parameter entries require multiple rows. This can be, for example, because they contain two summary statistics (e.g. mean and standard deviation) that are kept on separate rows. In order to create `` objects that contains the full information for each entry multiple rows of the epidemiological parameters table from {epireview} can be given to `as_epiparameter()` to create a single `` object. + +We can search which entries in the data have multiple rows by checking if there are duplicated parameter types and IDs. Remember that it is only possible to convert delay distributions into epiparameter objects (i.e. known as _Human delay_ parameter types in {epireview}). + +```{r, check-multi-row-entries} +multi_row_entries <- duplicated(marburg_params$parameter_type) & + duplicated(marburg_params$id) +multi_row_ids <- marburg_params$id[multi_row_entries] +``` + +```{r, subset-multi-row-entries} +multi_row_marburg_params <- + marburg_params[marburg_params$id %in% multi_row_ids, ] +multi_row_marburg_params +``` + +In this case there are two studies for Marburg with more than one entry (row) in the {epireview} database. Out of these studies we select the mean and standard deviation. + +```{r, check-multi-row-param-value-type} +multi_row_marburg_params$parameter_value_type +``` + +In this case, we know that the mean and standard deviation from the chosen rows correspond to the same estimation process by having read the corresponding article. However, there is currently no identifiers on the {epireview} `params` database for Marburg, Ebola or Lassa to directly identify which of the two rows with mean values correspond to the standard deviation. The {epireview} team are currently working on rectifying this issue. + +***Therefore, we encourage readers to manually verify their data subsets, to ensure that the entries that have been selected are indeed multiple rows for the same reported epidemiological parameter.*** + +* For future {epireview} pathogens (excluding SARS) mean and standard deviation estimates that match will form one row in the `$params` database. Current software development at {epireview} is working on ensuring compatibility between these formats. + +```{r, subset-multi-row-marburg-entry} +marburg_gt <- multi_row_marburg_params[ + multi_row_marburg_params$parameter_data_id %in% + c("056a8d6b5f9aee3622d3bd8b715d4296", "ce3976e2e15df3f6fb92f6deb2db2a29"), +] +marburg_gt +``` + +We can now convert this to an ``. + +```{r, convert-multi-row-entry-to-epiparameter} +marburg_gt_epiparameter <- as_epiparameter(marburg_gt) +marburg_gt_epiparameter +marburg_gt_epiparameter$summary_stats +``` + +## Entries with probability distributions + +For this example we will load the Ebola epidemiological parameters from the {epireview} package (as there are no entries for Marburg that have parametric distributions). + +```{r, load-ebola} +ebola_data <- load_epidata("ebola") +``` + +We will again subset the data to just use the epidemiological parameter table, and select those rows containing a serial interval. + +```{r, ebola-params} +ebola_params <- ebola_data$params +``` + +```{r, subset-ebola-params} +ebola_si_rows <- ebola_params[ + ebola_params$parameter_type_short == "serial_interval", +] +ebola_si_rows +``` + +We will select an entry that has estimated and reported a Weibull distribution: + +```{r, select-ebola-entry} +ebola_si <- ebola_si_rows[ + ebola_si_rows$parameter_data_id == "0c3e02f80addfccc1017fa619fba76c5", +] +ebola_si +``` + +We can now convert this to an `` object. + +```{r, convert-to-prob-dist-epiparameter-single-entry} +ebola_si_epiparameter <- as_epiparameter(ebola_si) +ebola_si_epiparameter +``` + +With the probability distribution for the serial interval we can utilise some of the `` methods. Here we illustrate this by checking that the `` is parameterised, plotting the PDF and CDF, and generating 10 random numbers sampling from the distribution. + +```{r, is-epiparameter-parameterised} +is_parameterised(ebola_si_epiparameter) +``` + +```{r, plot-epiparameter} +plot(ebola_si_epiparameter) +``` + +```{r, generate-epiparameter} +generate(ebola_si_epiparameter, times = 10) +``` + +## Specifying the probability distribution if unknown + +There may be instances where a delay distribution is reported in the literature, but either a probability distribution is not fit to the data, or it is not reported which probability distribution the parameters correspond to. Therefore, there will not be a probability distribution specified in the {epireview} data. In these cases, and when a parametric probability distribution is required for a particular epidemiological task then assuming a probability distribution can be useful. + +::: {.alert .alert-danger} +**Please use this feature with caution**. Assuming an incorrect probability distribution and applying this in an epidemiological method can lead to erroneous results. Additionally, if a probability distribution is specified by the user it will overwrite any probability distribution specified in input data (e.g. {epireview} parameter data) which can lead to an error if the distribution name supplied and parameters input are incompatible See `?as_epiparameter` details for more information. +::: + +Just as the example above we will load the Ebola parameters using the `epireview::load_epidata()` function and subset to just the parameters (`$params`). + +```{r, load-and-subset-ebola} +ebola_data <- load_epidata("ebola") +ebola_params <- ebola_data$params +``` + +Here we will use the serial interval for Ebola reported by @fayeChainsTransmissionControl2015a. This is stored, over two rows of the {epireview} parameter table, as the mean and standard deviation, but there is no probability distribution specified. + +The code chunk below subsets the Ebola parameter table to just return the serial interval from @fayeChainsTransmissionControl2015a. + +```{r, subset-ebola-serial-interval} +ebola_si <- ebola_params[ + which( + grepl(pattern = "Faye", x = ebola_params$article_label, fixed = TRUE) & + grepl(pattern = "serial", ebola_params$parameter_type, fixed = TRUE) + ), +] +``` + +If we were to supply this data to `as_epiparameter()` we would get an unparameterised `` object because no probability distribution is stated. + +```{r, convert-to-epiparameter-unspecified-prob-dist} +ebola_si_epiparameter <- as_epiparameter(ebola_si) +ebola_si_epiparameter +is_parameterised(ebola_si_epiparameter) +``` + +Given that we can convert the mean and standard deviation into parameters of a probability distribution if we assume a distribution form, we can supply this data to `as_epiparameter()`. This uses the parameter conversion functions in {epiparameter} (see `vignette("extract_convert", package = "epiparameter")`). + +```{r, convert-to-epiparameter-assumed-prob-dist} +ebola_si_epiparameter <- as_epiparameter(ebola_si, prob_distribution = "gamma") +ebola_si_epiparameter +is_parameterised(ebola_si_epiparameter) +``` + +The Ebola serial interval `` can now be used for various probability distribution methods. + +```{r, ebola-epiparameter-dist-methods} +get_parameters(ebola_si_epiparameter) +density(ebola_si_epiparameter, at = 20) +plot(ebola_si_epiparameter) +cdf(ebola_si_epiparameter, q = 10) +plot(ebola_si_epiparameter, cumulative = TRUE) +quantile(ebola_si_epiparameter, p = 0.5) +generate(ebola_si_epiparameter, times = 10) +``` + +## Limitations + +* The _database schema_ of {epireview} has evolved over time as the Imperial PERG team has extracted more pathogens. +* A list of [parameter types](https://mrc-ide.github.io/epireview/articles/pathogen_database_field_options.html) is available in the {epireview} package +* It is important to differentiate between variability of the sample (e.g. sample standard deviation) and uncertainty of the estimate (e.g. 95% confidence interval or credible interval). From the database version of {epireview} of Zika, the PERG team will explicitly expose this to remove any ambiguity of the extracted data. Please note that in the Marburg, Lassa, and Ebola datasets, there may be some ambiguity between variability and uncertainty. +* This is functionality in {epiparameter} and {epireview} which will be developed and improved over the coming months. + +## References diff --git a/vignettes/data_protocol.Rmd b/vignettes/data_protocol.Rmd new file mode 100644 index 000000000..52115549a --- /dev/null +++ b/vignettes/data_protocol.Rmd @@ -0,0 +1,166 @@ +--- +title: "Data Collation and Synthesis Protocol" +output: + bookdown::html_vignette2: + code_folding: show +bibliography: references.json +link-citations: true +vignette: > + %\VignetteIndexEntry{Data Collation and Synthesis Protocol} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r, load-epiparameter, echo=FALSE} +library(epiparameter) +``` + +## About the package + +The [`{epiparameter}` R package](https://github.com/epiverse-trace/epiparameter) contains a library of epidemiological parameter data and functions that read and handle this data. The delay distributions describe the time between two events in epidemiology, for example incubation period, serial interval and onset-to-death; while the offspring distributions describe the number of secondary infections from a primary infection in disease transmission. The library is compiled by a process of collecting, reviewing and extracting data from peer-reviewed literature[^1], including research articles, systematic reviews and meta-analyses. + +The `{epiparameter}` package will act as a 'living systematic review' (*sensu* @elliottLivingSystematicReviews2014) which will be actively updated and maintained to provide a reliable source of data on epidemiological distributions. To prevent bias in the collection or assessment of the data, a well-defined methodology of searching and refining is required. This document aims to provide transparency on the methodology used by the `{epiparameter}` maintainers by outlining the steps taken at each stage of the data handling. It can also serve as a guide to contributors wanting to search and provide epidemiological parameters currently missing from the library. This protocol should also facilitate reproducibility in the searches, results and appraisal steps. + +There is a large body of work on the methods to best conduct literature searches and data collection as part of systematic reviews and meta-analyses[^2], which we use as the basis for our protocol. These sources are: + +- [Cochrane Handbook](https://training.cochrane.org/handbook/current/) [@higginsCochraneHandbookSystematic2022] +- [PRISMA](https://www.prisma-statement.org/) [@pagePRISMA2020Statement2021] + +## Objective of `{epiparameter}` + +As defined by the PRISMA guidelines, having a clearly stated objective helps to refine the goal of the project. `{epiparameter}`'s objective is to provide information for a collection of distributions for a range of infectious diseases that is as accurate, unbiased and as comprehensive as possible. Such distributions will enable outbreak analysts to easily access these distributions for routine analysis. For example, delay distributions are necessary for: calculating case fatality rates adjusting for delay to outcome, quantifying implications of different screening measures and quarantine periods, estimating reproduction numbers, and scenario modelling using transmission dynamic models. + +## Contributing to the package + +To contribute to the `{epiparameter}` library of epidemiological parameter information, added your data to [this google sheet](https://docs.google.com/spreadsheets/d/1zVpaaKkQ7aeMdRN2r0p-W4d2TtccL5HcIOp_w-lfkEQ/edit?usp=sharing). This will then be integrated into the `{epiparameter}` library by the package maintainers, and the information will then be accessible to all `{epiparameter}` package users. + +## Scope of package + +The `{epiparameter}` package spans a range of infectious diseases, including several distributions for each disease when available. The pathogens and diseases that are currently systematically searched for and included in the package library are: + +```{r show-diseases, echo=FALSE} +db <- epiparameter_db() +disease <- vapply(db, "[[", FUN.VALUE = character(1), "disease") +pathogen <- vapply(db, "[[", FUN.VALUE = character(1), "pathogen") +knitr::kable( + data.frame( + Disease = disease, + Pathogen = pathogen + ), + align = "cc" +) +``` + +The distributions currently included in the literature search for each pathogen/disease are: + +```{r, show-epiparameters, echo=FALSE} +db <- epiparameter_db() +epi_name <- epiparameter:::.clean_string(unique( # nolint undesirable_operator_linter + vapply(db, "[[", FUN.VALUE = character(1), "epi_name") +)) +knitr::kable( + data.frame(epi_name), + align = "cc", + col.names = "Epidemiological Parameter" +) +``` + +## Guide to identifying distributions in the literature + +1. **Key word searches**: when searching the literature, the use of specific search phrases to ensure the correct literature is procured is required. We use a search schema that includes searching for the pathogen or the disease, and the desired distribution. The search phrase can optionally include a specific variant/strain/subtype. The search is not constrained based on year of publication. Examples of searches: +- "SARS-CoV-2 incubation period" +- "ebola serial interval" +- "influenza H7N9 onset to admission" + +However, these simple search phrases can return a large number of irrelevant papers. Using a more specific search schema depending on the search engine used. For example, if using Google Scholar a schema like: + +- ("Middle East Respiratory Syndrome" OR MERS) AND "onset to death" AND (estimation OR inference OR calculation) +- (ebola OR EVD) AND "onset to death" AND (estimation OR inference OR calculation) + +Or if Web of Science is being used: + +- ("Middle East Respiratory Syndrome" OR MERS) AND "onset to death" AND estimat* +- (ebola OR EVD) AND "onset to death" AND estimat* + +This should refine the results to a more suitable set of literature. + + +1. **Literature search engines**: using a selection of search engines to prevent one source potentially omitting papers. Suggested search sites are: Google Scholar, Web of Science, PubMed, and Scopus. + +1. **Adding papers**: in addition to the database entries from papers that have been identified in a literature search, entries can be supplemented by recommendations (i.e. from the community) or through being cited by a paper in the literature search. Papers may be recommended by experts in research or public health communities. We plan to use two methods of community engagement. Firstly a [open-access Google sheet](https://docs.google.com/spreadsheets/d/1zVpaaKkQ7aeMdRN2r0p-W4d2TtccL5HcIOp_w-lfkEQ/edit?usp=sharing) allows people to add their distribution data which will then be reviewed by one of the `{epiparameter}` maintainers and incorporated if it meets quality checks. The second method - not yet implemented - involves community members uploading their data to [zenodo](https://zenodo.org/), which can then be read and loaded into R using `{epiparameter}` once checked. + +1. **Language restrictions**: papers in English or Spanish are currently supported in `{epiparameter}`. Papers written in another language but verified by an expert can also be included in the database. However, these are not evaluated with the review process described below and as a result are flagged to the user when loaded in `{epiparameter}`. + +## Guide to data refinement once sources identified + +1. **Removing duplicates**: the library of parameters does not contain duplicates of studies, but multiple entries per study can be included if a paper reports multiple results (e.g. from the full data set and then a subset of the data). Studies that use the same data, subsets or supersets of data used in other papers in the library are included. + +1. **Abstract and methods screening**: once a number of unique sources have been identified, each should be reviewed for its suitability by reviewing the abstract and searching for words or phrases in the paper that indicate it reports the parameters or summary statistics of a distribution, this can include searching the methods section for words on types of distributions (e.g. lognormal), fitting procedures (e.g. maximum likelihood or bayesian), or searching the results for parameter estimates. The `{epiparameter}` library includes entries where parameters or summary statistics are reported but a distribution is not specified, and entries where the distribution is specified but the parameters are not reported. + + A database of unsuitable papers will be kept to remind maintainers which papers have not been included and aids in the updating of the database (see below) by preventing redundant reviewing a previously rejected paper. + +1. **Stopping criteria**: for many searches, the number of results is far larger than could be reasonably evaluated outside a full systematic review. After refining which papers contain the required information (abstract and methods screening), around 10 papers per pathogen are screened for each search (per search round, see updating section below for details). If the number of papers that pass the abstract and methods screening is fewer than 10, all suitable papers are reviewed. + +1. **Full paper screening**: after the abstract and methods screening, those papers not excluded should be reviewed in full to verify they indeed contain the required information on distribution parameters and information on methodology used. It is acceptable to include a secondary source that contains information on the delay distribution when the primary source is unavailable or does not report the distribution. The inference of the delay distribution does not have to be a primary subject of the research article, for example if it was inferred to be used in estimation of $R_0$ it can still be included in the database. Additionally, distribution parameters based on illustrative values for use in simulations - rather than inferred from data - are considered unsuitable and should be excluded. + + Again, any papers excluded at this stage should be recorded in the database of unsuitable sources with reasoning to prevent having to reassess when updating the database. + +1. **Post hoc removal**: if any `{epiparameter}` parameters are later identified as being inappropriate then they can be removed from the database. In most cases this is unlikely as limitations can be appended onto data entries to make users aware of limitations (e.g. around assumptions used to infer the distribution), only in the most extreme cases will data be completely removed from the database. + +Note: systematic reviews focusing on effect sizes can be subject to publication bias (e.g. more positive or significant results in the literature). However, distribution inference does not focus on significance testing or effect sizes, so this bias is not considered in the collection process. + +## Guide to extracting parameters + +**Extracting parameters**: for any underlying distributions (e.g. gamma, lognormal), parameters (e.g. shape/scale, meanlog/sdlog), and summary statistics (e.g. mean, standard deviation, median, range or quantiles) given in the paper, values should be recorded verbatim from the paper into the database. When these are read into R using the `{epiparameter}` package, other aspects of the distribution are automatically calculated and available. For example if the mean and standard deviation of a gamma distribution is reported for a serial interval these values will be stored in the database. But once in R, the shape and scale parameters of the gamma distribution will be automatically reconstructed and the resulting distribution available for use. + +The `{epiparameter}` library exactly reflects the literature. By which we mean that information not present in the paper should not be imputed from prior knowledge (e.g. vector of a disease is known but not stated), or by performing calculating with reported values. This prevents the issue of not having clear provenance for the data in the library. + +The requirements of each entry in the database is defined by the data dictionary. Here we outline the minimal dataset that is required to be included in the `{epiparameter}` library is: + +- Name of disease +- Type of distribution +- Citation information (author(s) of the paper, the year of publication, publication title and journal, and DOI) +- Whether the distribution is extrinsic (e.g. extrinsic incubation period). If the disease is not vector-borne this should be NA. +- Whether the distribution fitted was discretised, this is a boolean (true or false). + +All other information for each database entry is non-essential. + +See the data dictionary included in `{epiparameter}` for all database fields with a description of each and the range of possible values each field can take. + +## Data quality assessment in `{epiparameter}` + +The inference of parameters for a delay distribution often requires methodological adjustments to correct for factors that would otherwise bias the estimates. These includes accounting for interval-censoring of the data when the timing of an event (e.g. exposure to a pathogen) is not know with certainty, but rather within a time window. Or adjusting for phase bias when the distribution is estimated during a growing or shrinking stage of an epidemic. The aim of `{epiparameter}` is not to make a judgement on which parameters are 'better' than others, but to notify and warn the user of the potential limitations of the data. The aspects assessed are: 1) whether the method includes single or double interval-censoring when the exposure or onset times are not known with certainty (i.e. on a single day); 2) does the method adjust for phase bias when the outbreak is in an ascending or descending phase. These are indicated by boolean values to indicate whether they are reported in the paper and users are recommended to refer back to the paper to determine whether estimates are biased. + +## Guide to the `{epiparameter}` review process + +For a set of parameters to be included in the database it must pass the abstract and methods screening and full screening and subsequently a review by one of the `{epiparameter}` maintainers. This process involves running diagnostic checks and cross-referencing the reported parameters with those in the paper to ensure they match exactly and that the results plot of the PDF/CDF/PMF matches anything plotted in the paper, if available. This prevents a possible misinterpretation (e.g. serial interval for incubation period). This check also includes making sure the unique identifiers for the paper match the author's name, publication year and other data recorded in the database. + +## Updating parameters in the database + +Because search and review stages are time consuming and cannot be continuously carried out, we aim to keep the `{epiparameter}` library up-to-date as a living data library by conducting regular searches (i.e. every 3-4 months) to fill in any missing papers or new publication since the last search. The epidemiological literature can expand rapidly, especially during a new outbreak. Therefore we can optionally include new studies that are of use to the epidemiological community in between regular updates. These small additions will still be subject to the data quality assessment and diagnostics to ensure accuracy, and will likely be picked up in the subsequent literature searches. It is likely that for existing pathogens that have not had a major increase in incidence since the last update few new papers will be reporting delay distributions. In these cases papers that were not previously reviewed due to limited reviewing time for each round of updates are now checked. + +We particularly value community contributions to the database, so everyone can benefit from analysis that has already been conducted, and duplicated of effort is reduced. + +## Database of excluded papers + +All papers that are returned in the search results but are not suitable, either at the stage of abstract screening, or after reviewing the entirety of the paper, are recorded in a database by the following information: + +- First author's last name +- Unique identifier, ideally the DOI +- Journal, pre-print server, or host website +- One or several reasons for why it was deemed unsuitable +- Date of recording + +## References + +[^1]: We also include distribution parameters that are published on pre-print servers such as arxiv, bioRxiv and medRxiv. But will update the citation reference once the paper is accepted and published by a journal. + +[^2]: `{epiparameter}` is itself not a meta-analytic tool, but the references stored within may be useful as part of a meta-analysis. + diff --git a/vignettes/database.Rmd b/vignettes/database.Rmd new file mode 100644 index 000000000..99da8252a --- /dev/null +++ b/vignettes/database.Rmd @@ -0,0 +1,41 @@ +--- +title: "Current database" +output: + bookdown::html_vignette2: + fig_caption: yes + code_folding: show +vignette: > + %\VignetteIndexEntry{Current database} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r echo = FALSE} +library("DT") +library("epiparameter") + +db <- epiparameter_db() +tbl <- lapply(db, function(x) { + data.frame( + disease = x$disease, + pathogen = x$pathogen, + epi_name = x$epi_name, + citation_info = paste0( + epiparameter:::.citet(x$citation), # nolint undesirable_operator_linter + ", DOI: ", + "", + x$citation$doi, "" + ) + ) +}) +tb <- do.call(rbind, tbl) +## sort by disease then pathogen +tb <- tb[order(tb$disease, tb$pathogen), ] +datatable( + tb, + rownames = FALSE, + colnames = c("Disease", "Pathogen", "Distribution", "Reference"), + escape = FALSE, + options = list(pageLength = 50) +) +``` diff --git a/vignettes/design_principles.Rmd b/vignettes/design_principles.Rmd new file mode 100644 index 000000000..651fc80c3 --- /dev/null +++ b/vignettes/design_principles.Rmd @@ -0,0 +1,173 @@ +--- +title: "Design Principles for {epiparameter}" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Design Principles for {epiparameter}} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +This vignette outlines the design decisions that have been taken during the development of the {epiparameter} R package, and provides some of the reasoning, and possible pros and cons of each decision. + +This document is primarily intended to be read by those interested in understanding the code within the package and for potential package contributors. + +## Scope + +The {epiparameter} R package is a library of epidemiological parameters, and provides a class (i.e. data structure) and helper functions for working with epidemiological parameters and distributions. The `` class is the main functional object for working with epidemiological parameters and can hold information on delay distributions (e.g. incubation period, serial interval, onset-to-death distribution) and offspring distributions. The class has a number of methods, including allowing the user to easily calculate the PDF, CDF, and quantile, generate random numbers, calculate the distribution mean, and plot the distribution. An `` object can be created with the constructor function `epiparameter()`, and if uncertain whether an object is an ``, it can be validated with `assert_epiparameter()`. + +The package also converts distribution parameters to summary statistics, and vice versa. This is achieved either by conversion or extraction and both of these methods and the functions used are explained in the [Parameter extraction and conversion in {epiparameter} vignette](extract_convert.html). + +## Output + +The output of the `epiparameter()` constructor function is an `` object. This is a list of nine elements, where each element is either a single type (e.g. `character`), a non-nested `list` or another class. Classes as `` elements are used when there is existing well developed infrastructure for handling certain data types. The `$prod_dist` element uses a distribution class -- if there is a parameterised distribution available -- using either the `` class from {distributional} or the `` class from {distcrete}. The `$citation` is handled using the `` class from the {utils} package (included as part of the base R recommended packages). + +Other functions return the simplest type possible, this may be an atomic vector (including single element vectors), or un-nested lists. + +## Package architecture + +Much of the {epiparameter} package is centred around the `` class. Here is a diagram showing the class with it's S3 methods (the diagram below is interactive so can adjusted if labels are overlapping). + +```{r, echo=FALSE, fig.width=8, fig.height=5} +# read NAMESPACE +namespace <- base::parseNamespaceFile("epiparameter", .libPaths()[1L]) # nolint: undesirable_function_linter +s3methods <- namespace$S3methods +epiparameter_class_methods <- + s3methods[which(s3methods[, 2] == "epiparameter"), 1] + +# create network with all methods around the central node +getters <- c("family()", "get_citation()", "get_parameters()") +modifiers <- c("discretise()", "as.function()") +distribution_functions <- c("cdf()", "density()", "generate()", "quantile()") +utilities <- c("print()", "plot()", "mean()", "c()", "format()") +checkers <- c("is_epiparameter()", "is_parameterised()", "is_truncated()") +conversions <- c( + "convert_params_to_summary_stats()", "convert_summary_stats_to_params()" +) +coercion <- "as.data.frame()" + +# add one to each for the intermediate group nodes +groups <- data.frame( + group = c( + rep("Getters", length(getters) + 1), + rep("Modifiers", length(modifiers) + 1), + rep("Distribution functions", length(distribution_functions) + 1), + rep("Utilities", length(utilities) + 1), + rep("Checkers", length(checkers) + 1), + rep("Conversions", length(conversions) + 1), + rep("Coercion", length(coercion) + 1) + ), + functions = c( + c("Getters", getters), + c("Modifiers", modifiers), + c("Distribution functions", distribution_functions), + c("Utilities", utilities), + c("Checkers", checkers), + c("Conversions", conversions), + c("Coercion", coercion) + ) +) + +nodes <- data.frame( + id = seq_len(nrow(groups) + 1), + group = c("", groups$group), + label = c("", groups$functions), + shape = "box", + stringsAsFactors = FALSE +) + +from <- seq_len(nrow(groups)) + +# plus one for the central node +to <- 2:(nrow(groups) + 2) + +for (grp in unique(groups$group)) { + # plus one for central node + from[which(groups$group == grp) + 1] <- min(which(groups$group == grp)) + 1 +} + +# set intermediate nodes to connect to central node +from[groups$group == groups$functions] <- 1 + +edges <- data.frame( + from = from, + to = to, + color = "black", + stringsAsFactors = FALSE +) + +colours <- RColorBrewer::brewer.pal( + n = length(unique(nodes$group)), + name = "Set3" +) + +# functions from parseNamespaceFile() need parentheses to match formatting +epiparameter_class_methods <- paste0(epiparameter_class_methods, "()") +if (!all(epiparameter_class_methods %in% groups$functions)) { + message( + "This diagram is out of date, as new methods have been added to the ", + "package which are not included." + ) +} + +library(visNetwork) +visNetwork(nodes, edges) |> + visNodes(font = list(size = 18)) |> + visGroups(groupname = "", color = colours[1]) |> + visGroups(groupname = "Getters", color = colours[2]) |> + visGroups(groupname = "Modifiers", color = colours[3]) |> + visGroups( + groupname = "Distribution functions", + color = colours[4] + ) |> + visGroups(groupname = "Utilities", color = colours[5]) |> + visGroups(groupname = "Checkers", color = colours[6]) |> + visGroups(groupname = "Conversions", color = colours[7]) |> + visGroups(groupname = "Coercion", color = colours[8]) +``` + +## Design decisions + +* The `` class is designed to be a core unit for working with epidemiological parameters. It is designed in parallel to other epidemiological data structures such as a the `` class from the [{contactmatrix} R package](https://socialcontactdata.github.io/contactmatrix/index.html). The design principles of the `` class are aligned with the [`` design principles](https://socialcontactdata.github.io/contactmatrix/articles/design-principles.html). These include: + - A `new_*()` constructor + - Two validation functions + - `assert_()` + - `test_()` + - An `is_()` checker to determine if an object is of a given class (without checking the validity of class) + - Coercion generic `as_()`. + +* The conversion functions (`convert_*`) are S3 generic functions with methods provided by {epiparameter} for `character` and `` input. This follows the design pattern of other packages, such as [{dplyr}](https://dplyr.tidyverse.org/), which export their key data transformation functions as S3 generics to allow other developers to extend the conversions to other data objects. + +* The conversion functions are designed to have a single function exported to the user for summary statistics to parameters, and another function exported for parameters to summary statistics. These functions use a `switch()` to dispatch to the internal conversion functions. This provides a minimal number of conversion functions in the package namespace compared to exporting a conversion function for every distribution. + +* If there are a large number of entries returned when reading epidemiological parameters from the library using the `epiparameter_db()` function, it can flood the console, due to the default `list` printing in R. This is the reasoning for the `` object which is a minimal class to enable cleaner and more descriptive printing for a large list of `` objects. The `print.multi_epiparameter()` prints a header with metadata on the number of `` objects and number of diseases and epidemiological distributions in the list. It also lists all the diseases and epidemiological parameters returned. The footer of the `print()` function states the number of `` objects not shown, guides to use `print(n = ...)` and `parameter_tbl()` and a link to the online database vignette (`database.Rmd`). Information in the header and footer considered metadata or advice is prefixed with `#`. + +* The package uses S3 classes and S3 dispatch for exported functions, and `switch()` and `do.call()` for dispatching to internal functions. This is because it is easier to develop and debug internal functions that do not use S3 dispatch and avoids having to ensure that S3 methods are registered. Examples of S3 dispatch for exported functions are `get_parameters()` and `convert_summary_stats_to_params()`. Examples of internal dispatch using `switch()` and `do.call()` are `clean_params()` and `convert_params_to_summary_stats.character()`. + +* The function naming convention is for internal functions to have a dot (.) prefix (e.g. `.convert_params_lnorm()`). The only function that breaks with this convention is `new_epiparameter()` as advanced users of the package may want to call in the internal low-level constructor, and adding a dot prefix to this function may make it harder for users to find. + +## Dependencies + +The aim is to restrict the number of dependencies to a minimal required set for ease of maintenance. The current hard dependencies are: + +* [{checkmate}](https://CRAN.R-project.org/package=checkmate) +* [{distributional}](https://CRAN.R-project.org/package=distributional) +* [{distcrete}](https://CRAN.R-project.org/package=distcrete) +* {stats} +* {utils} + +{stats} and {utils} are distributed with the R language so are viewed as a lightweight dependencies, that should already be installed on a user's machine if they have R. {checkmate} is an input checking package widely used across Epiverse-TRACE packages. {distributional} and {distcrete} are used to import S3 classes for handling and working with distributions. Both are required as only {distcrete} can handle discretised distributions. + +[{jsonlite}](https://CRAN.R-project.org/package=jsonlite) is a suggested dependency because it is used to read the parameter library which is stored as a JSON file. However, it is only read by an internal function and instead the data is available to the user via `sysdata.rda`, so {jsonlite} is not required as an imported dependency. + +Currently {epiparameter} deviates from the [Epiverse policy on the number of previous R versions it supports](https://epiverse-trace.github.io/blueprints/dependencies.html#base-r-support-schedule). The {epiparameter} package requires R version >= 4.1.0 which only includes the current version and the last three minor R versions rather than the policy of four minor versions, as of September 2024. The reasons for this change is to enable usage of the base R pipe (`|>`). + +## Contribute + +In addition to the [package contributing guide](https://github.com/epiverse-trace/.github/blob/main/CONTRIBUTING.md), please refer to the [{epiparameter} specific contributing guidelines for adding epidemiological parameter to the package library](https://epiverse-trace.github.io/epiparameter/articles/data_protocol.html#contributing-to-the-package). diff --git a/vignettes/epiparameter.Rmd b/vignettes/epiparameter.Rmd new file mode 100644 index 000000000..b6c765152 --- /dev/null +++ b/vignettes/epiparameter.Rmd @@ -0,0 +1,213 @@ +--- +title: "Getting Started with {epiparameter}" +output: + bookdown::html_vignette2: + code_folding: show +vignette: > + %\VignetteIndexEntry{Getting Started with {epiparameter}} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.width = 8, + fig.height = 5 +) +``` + +It is often the case that in an infectious disease outbreak epidemiological parameters are required in order to characterise and model the dynamics of disease transmission and evaluate control strategies. In those scenarios, epidemiological parameters are commonly retrieved from the literature, and there is currently no library of parameters in order to contrast and compare different reported parameters for a range of infectious diseases and pathogens, from different published studies over time, of which some may be meta-analyses. + +The {epiparameter} R package is a library of epidemiological parameters, with classes to handle this data and a set of functions to manipulate and use epidemiological parameters and distributions. The package also contains functionality for converting and extracting distribution parameters from summary statistics. + +::: {.alert .alert-primary} +### Use case + +An outbreak of a known or potentially novel pathogen is detected and key parameters such as delay distributions (e.g. incubation period or serial interval) are required to interpret early data. + +{epiparameter} can provide these distributions from a selection of published sources, such as past analysis of the same or similar pathogen, in order to provide relevant epidemiological parameters for new analysis. +::: + +This vignette will provide a introduction to the data stored within {epiparameter}, how to read it into R, manipulate +the data, and the functions (and methods) implemented in the package to facilitate easy application of parameters into epidemiological pipelines. + + +```{r setup} +library(epiparameter) +``` + +### Library of epidemiological parameters + +First, we will introduce the library, or database, of epidemiological parameters available from {epiparameter}. The library is stored internally and can be read into R using the `epiparameter_db()` function. By default all entries in the library are returned. + +```{r read-in-library} +db <- epiparameter_db() +db +``` + +The output is a list of `` objects, where each element in the list corresponds to an entry in the parameter database. +To see a full list of the diseases and distributions stored in the library use the +`parameter_tbl()` function. Here we show the first six rows of the output. + +```{r, parameter-tbl} +parameter_tbl(multi_epiparameter = db) +``` + +`parameter_tbl()` can also subset the database supplied to the function. + +```{r, parameter-tbl-subset} +parameter_tbl(multi_epiparameter = db, disease = "Ebola") +``` + +More details on the data collation and the library of parameters can be found in +the [Data Collation and Synthesis Protocol vignette](https://epiverse-trace.github.io/epiparameter/articles/data_protocol.html). + +### Single set of epidemiological parameters + +{epiparameter} introduces a new class for working with epidemiological parameters in R: ``, contains the name of the disease, the name of the epidemiological distribution, parameters (if available) and citation information of parameter source, as well as other information. This is the core data structure in the {epiparameter} package and holds a single set of epidemiological parameters. + +An `` object can be: + +1. Pulled from database (`epiparameter_db()`) + +```{r epiparameter-db} +# from database + +# fetch for COVID-19 incubation period from database +# return only a single +covid_incubation <- epiparameter_db( + disease = "COVID-19", + epi_name = "incubation period", + single_epiparameter = TRUE +) +covid_incubation +``` + +2. Created manually (using the class constructor function: `epiparameter()`) + +```{r epiparameter-constructor} +# using constructor function +covid_incubation <- epiparameter( + disease = "COVID-19", + pathogen = "SARS-CoV-2", + epi_name = "incubation period", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 2, scale = 1) + ), + summary_stats = create_summary_stats(mean = 2), + citation = create_citation( + author = person( + given = list("John", "Amy"), + family = list("Smith", "Jones") + ), + year = 2022, + title = "COVID Incubation Period", + journal = "Epi Journal", + doi = "10.27861182.x" + ) +) +covid_incubation +``` + +Not all arguments are specified in the example using the class constructor (`epiparameter()`) above, for example the `metadata` or parameter uncertainty (`uncertainty`) is not provided. See the help documentation for the `epiparameter()` function using `?epiparameter` to see each argument. Also see documentation for `` helper functions, e.g., `?create_citation()`. + +Manually creating `` objects can be especially useful if new parameter estimates become available but are not yet incorporated into the {epiparameter} library. + +As seen in the examples in this vignette, the `` class has a custom printing method which shows the disease, pathogen (if known), the epidemiological distribution, a citation of the study the parameters are from and the probability distribution and parameter of that distribution (if available). + +::: {.alert .alert-success} +### Benefit of `` + +By providing a consistent and robust object to store epidemiological parameters, `` objects can be applied in epidemiological pipelines, for example [{episoap}](https://github.com/epiverse-trace/episoap). The data contained within the object (e.g. parameter values, pathogen type, etc.) can be modified but the pipeline will continue to operate because the class is unchanged. +::: + +The probability distribution (`prob_distribution`) argument requires the distribution specified in the standard R naming. In some cases these are the same as the distribution's name, e.g., `gamma` and `weibull`. Examples of where the distribution name and R name differ are lognormal and `lnorm`, negative binomial and `nbinom`, geometric and `geom`, and poisson and `pois`. + +## Subsetting database + +The database can be subset directly by `epiparameter_db()`. Here the results can be subset by author. It is recommended to use the family name of the first author instead of the full name. Only the first author will be matched when the entry is from a source with multiple authors. + +```{r epiparameter-db-subset-author} +epiparameter_db( + disease = "COVID-19", + epi_name = "incubation period", + author = "Linton" +) +``` + +The results can be further subset using the `subset` argument, for example `subset = sample_size > 100` will return entries with a sample size greater than 100. See `?epiparameter_db()` for details on how to use this argument to subset which database entries get returned. + +If a single `` is required then the `single_epiparameter` argument can be set to `TRUE` and this will return a single set of epidemiological parameters (i.e. one delay distribution), if available. If multiple entries in the parameter library match the search criteria (e.g. disease type) then the entries that are parameterised (i.e. distribution parameters are known), account for right truncation when inferred, and were estimated from the largest sample size are preferentially selected (in that order). + +```{r epiparameter-db-single-epiparameter} +epiparameter_db(disease = "SARS", single_epiparameter = TRUE) +``` + +## Distribution functions + +`` objects store distributions, and mathematical functions of these distribution can easily be extracted directly from them. It is often useful to access the probability density function, cumulative distribution function, quantiles of the distribution, or generate random numbers from the distribution in the `` object. The distribution functions in {epiparameter} allow users to easily use these. + +```{r epiparameter-dist-methods} +ebola_incubation <- epiparameter_db( + disease = "Ebola", + epi_name = "incubation period", + single_epiparameter = TRUE +) + +density(ebola_incubation, at = 0.5) +cdf(ebola_incubation, q = 0.5) +quantile(ebola_incubation, p = 0.5) +generate(ebola_incubation, times = 10) +``` + +## Plotting epidemiological distributions + +`` objects can easily be plotted to see the PDF and CDF of distribution. + +```{r plot-epiparameter} +plot(ebola_incubation) +``` + +The default plotting range for time since infection is from zero to the 99th quantile of the distribution. This can be altered by specifying the `xlim` argument when plotting an `` object. + +```{r plot-epiparameter-dayrange} +plot(ebola_incubation, xlim = c(1, 25)) +``` + +This plotting function can be useful for visually comparing epidemiological distributions from different publications on the same disease. In addition, plotting the distribution after manually creating an `` help to check that the parameters are sensible and produce the expected distribution. + +### Accessors + +The `` class also has accessor functions that can help access elements from the object in a standardised format. + +```{r epiparameter-accessors} +get_parameters(ebola_incubation) +get_citation(ebola_incubation) +``` + +## Parameter conversion and extraction + +### Conversion + +Parameters are often reported in the literature as mean and standard deviation (or variance). These summary statistics can often be (analytically) converted to the parameters of the distribution using the conversion function in the package (`convert_summary_stats_to_params()`). We also provide conversion functions in the opposite direction, parameters to summary statistics (`convert_params_to_summary_stats()`). + +### Extraction + +The functions `extract_param()` handles all the extraction of parameter estimates from summary statistics. The two extractions currently supported in {epiparameter} are from percentiles and from median and range. + +## Adding library entries and contributing to {epiparameter} + +If a set of epidemiological parameter has been inferred and is known to the user but has not yet been incorporated into the {epiparameter} database, these parameters can be manually added to the library. + +```{r add-to-library} +# wrap in list to append to database +new_db <- append(db, covid_incubation) +tail(new_db, n = 3) +``` + +Note that this only adds the parameters to the library in the environment, and does not save to the database file in the package. Hence, if you restart your R session, you will lose the changes. + +The library of epidemiological parameters is a living database, so as new studies are published we hope to incorporate these. Searching for and recording parameters in the database is extremely time-consuming, so we welcome contributions of new parameters by either making a pull request to the package or adding information to the contributing spreadsheet. These will be incorporated into the database by the package maintainers and your contributions will be acknowledged. See the [Data Collation and Synthesis Protocol](https://epiverse-trace.github.io/epiparameter/articles/data_protocol.html) vignette on information about contributing to the library of epidemiological parameters. diff --git a/vignettes/extract-bias.Rmd b/vignettes/extract-bias.Rmd new file mode 100644 index 000000000..f9c3bc92b --- /dev/null +++ b/vignettes/extract-bias.Rmd @@ -0,0 +1,522 @@ +--- +title: "{epiparameter} Extraction Bias Analysis" +output: + bookdown::html_vignette2: + fig_caption: yes + code_folding: show +vignette: > + %\VignetteIndexEntry{{epiparameter} Extraction Bias Analysis} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + + + +::: {.alert .alert-info} +If you are unfamiliar with the parameter extraction functionality in {epiparameter} +the [Conversion and Extraction vignette](extract_convert.html) is a great place to start. +::: + +The {epiparameter} R package contains a set of functions to extract parameters +of probability distributions given a set of summary statistics. These summary statistics can +be the values at given percentiles of a distribution, or the median and range of +a data set to which a distribution can be fit. Using these and specifying the distribution +(e.g. gamma, lognormal, etc.) the parameters of the distribution can be extracted by +optimisation using least-squares. + +The precision and bias of this approach needs to be explored across the parameter space +of the different distributions to understand potential erroneous inferences. This +vignette aims to explore this inference bias for three distributions currently +supported in {epiparameter} for parameter extraction: gamma, lognormal and Weibull. Extraction +of parameters from a normal distribution is also supported in {epiparameter} but we +do not test that in this vignette. + +::: {.alert .alert-warning} +This is not an in depth analysis of the estimation methods implemented in {epiparameter}, +but rather a supplementary article exploring the bias and precision of the functions. +It is specific to the case of {epiparameter} and should not be taken as a generalisable result. +::: + + +``` r +library(epiparameter) +library(ggplot2) +``` + +## Extraction Bias + +### Extraction by percentiles + +First we explore extraction from percentiles. + +If a study reports the percentiles of a distribution, they are usually symmetrical +(e.g. 5th and 95th, or 2.5th and 97.5th). However, in a few instances, only asymmetrical +percentiles are available. We test whether asymmetry to varying degrees influences the +bias of parameter extraction for all distributions. + +We set up the parameter space to explore: + + +``` r +distributions <- c("gamma", "lnorm", "weibull") +dist_parameters <- seq(0.5, 2, 0.5) +lower_percentiles <- c(2.5, 5, 25, 40) +upper_percentiles <- c(60, 95, 97.5) + +parameters_perc <- expand.grid( + dist = distributions, + param_1 = dist_parameters, + param_2 = dist_parameters, + lower = lower_percentiles, + upper = upper_percentiles +) + +# calculate the degree of asymmetry for each percentile combination +lw_interval_diff <- abs(0 - parameters_perc$lower) +up_interval_diff <- abs(100 - parameters_perc$upper) +deg_asym <- abs(lw_interval_diff - up_interval_diff) + +# add degree of asymmetry to percentiles +parameters_perc <- cbind(parameters_perc, deg_asym) + +# divide percentiles by 100 to make them probabilities for quantile functions +parameters_perc$lower <- parameters_perc$lower / 100 +parameters_perc$upper <- parameters_perc$upper / 100 +``` + +Now we can run the extraction for each point in parameter space. We set a seed +to control for stochasticity when estimating the parameters, however changing or +removing the seed should not drastically change the results or interpretation. + + +``` r +set.seed(1) +``` + + +``` r +estim_params <- vector("list", nrow(parameters_perc)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_perc))) { + dist <- as.character(parameters_perc[params_idx, "dist"]) + percen <- unname(unlist(parameters_perc[params_idx, c("lower", "upper")])) + + if (dist == "lnorm") { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + meanlog = parameters_perc[params_idx, "param_1"], + sdlog = parameters_perc[params_idx, "param_2"] + ) + ) + } else { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + shape = parameters_perc[params_idx, "param_1"], + scale = parameters_perc[params_idx, "param_2"] + ) + ) + } + + # message about stochastic optimisation suppressed + estim_params[[params_idx]] <- suppressMessages( + extract_param( + type = "percentiles", + values = true_values, + distribution = dist, + percentiles = percen + ) + ) +} + +# combine results +results <- cbind(parameters_perc, do.call(rbind, estim_params)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "lower", "upper", + "deg_asym", "estim_param_1", "estim_param_2" +) + +# calculate absolute difference between true parameter and estimated value +results <- cbind( + results, + diff_param_1 = abs(results$param_1 - results$estim_param_1), + diff_param_2 = abs(results$param_2 - results$estim_param_2) +) +``` + +The `extract_param()` function re-runs the optimisation +until convergence to a set tolerance is achieved (or a maximum number of +iterations is reached) to more reliably return the global +optimum. In theory, this should help to minimise bias and instability in the +parameter estimation. See the function documentation (`?extract_param()`) or +the [Conversion and Extraction vignette](extract_convert.html) for more details. + +The extraction bias can be explored: + + +```{.r .fold-hide} +# plot differences by distribution +ggplot(data = results) + + geom_point(mapping = aes( + x = diff_param_1, + y = diff_param_2, + colour = deg_asym + )) + + scale_x_continuous(name = "Parameter 1 Difference (|true - estimated|)") + + scale_y_continuous(name = "Parameter 2 Difference (|true - estimated|)") + + labs(colour = "Percentile Asym.") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +![Parameter estimation bias facetted by distribution. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution.](figure/plot-results-percentiles-1.png) + +### Extraction by median and range + +The same analysis as above can be repeated, this time using the other summary +statistic possibly reported in studies: median and range of data. +For this extraction the number of samples used to infer the distribution is required +as this can impact the possible range exhibited by the data. + +Set up the parameter space: + + +``` r +n_samples <- c(10, 50, 100) +parameters_range <- expand.grid( + dist = distributions, # same as above + param_1 = dist_parameters, # same as above + param_2 = dist_parameters, # same as above + n_samples = n_samples +) +``` + + +``` r +estim_params <- vector("list", nrow(parameters_range)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_range))) { + dist <- as.character(parameters_range[params_idx, "dist"]) + n_samples <- parameters_range[params_idx, "n_samples"] + # while loop to ensure values are min < median < max + resample_values <- TRUE + while (resample_values) { + if (dist == "lnorm") { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } else { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } + true_values <- c(true_median, true_range) + if (true_values[2] < true_values[1] && true_values[1] < true_values[3]) { + resample_values <- FALSE + } + } + # message about stochastic optimisation suppressed + estim_params[[params_idx]] <- suppressMessages( + expr = extract_param( + type = "range", + values = true_values, + distribution = dist, + samples = n_samples + ) + ) +} +#> Warning: Maximum optimisation iterations reached, returning result early. +#> Result may not be reliable. +``` + +``` r + +# combine results +results <- cbind(parameters_range, do.call(rbind, estim_params)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "n_samples", "estim_param_1", "estim_param_2" +) + +# calculate absolute difference between true parameter and estimated value +results <- cbind( + results, + diff_param_1 = abs(results$param_1 - results$estim_param_1), + diff_param_2 = abs(results$param_2 - results$estim_param_2) +) +``` + +Plot results: + + +```{.r .fold-hide} +# plot differences by distribution +ggplot(data = results) + + geom_point( + mapping = aes( + x = diff_param_1, + y = diff_param_2, + colour = n_samples + ) + ) + + scale_x_continuous(name = "Parameter 1 Difference (|true - estimated|)") + + scale_y_continuous(name = "Parameter 2 Difference (|true - estimated|)") + + labs(colour = "No. Samples") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +![Parameter extraction bias. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution.](figure/plot-results-med-range-1.png) + +## Extraction precision + +### Extraction by percentiles + +The two analyses above used a single extraction (replicate), however, it may be that +the estimation of the parameters is unstable for a given set of percentiles or median +range. Therefore, we finish with a test of whether repeated extraction of parameters +from a single percentile has large variance which would indicate the parameter extraction +is unstable, imprecise, and potentially untrustworthy. + +We use the same parameter space for percentiles as defined above +(`parameters_perc`). Now we can run the extraction for a set of replicates to +compute the variance of parameter estimates over those replicates. + + +``` r +estim_param_var <- vector("list", nrow(parameters_perc)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_perc))) { + dist <- as.character(parameters_perc[params_idx, "dist"]) + percen <- unname(unlist(parameters_perc[params_idx, c("lower", "upper")])) + + if (dist == "lnorm") { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + meanlog = parameters_perc[params_idx, "param_1"], + sdlog = parameters_perc[params_idx, "param_2"] + ) + ) + } else { + true_values <- do.call( + paste0("q", dist), + list( + p = percen, + shape = parameters_perc[params_idx, "param_1"], + scale = parameters_perc[params_idx, "param_2"] + ) + ) + } + + # message about stochastic optimisation suppressed + estim <- suppressMessages( + replicate( + n = 5, + expr = extract_param( + type = "percentiles", + values = true_values, + distribution = dist, + percentiles = percen + ) + ) + ) + estim_param_var[[params_idx]] <- apply(estim, MARGIN = 1, FUN = var) +} + +# combine results +results <- cbind(parameters_perc, do.call(rbind, estim_param_var)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "lower", "upper", + "deg_asym", "estim_param_1_var", "estim_param_2_var" +) +``` + + +```{.r .fold-hide} +ggplot(data = results) + + geom_point(mapping = aes( + x = estim_param_1_var, + y = estim_param_2_var, + colour = deg_asym + )) + + scale_x_continuous(name = "Parameter 1 Variance") + + scale_y_continuous(name = "Parameter 2 Variance") + + labs(colour = "Percentile Asym.") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +![Parameter extraction precision, facetted by distribution. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution.](figure/plot-results-1.png) + +### Extraction by median and range + +The same test of estimation precision can be performed for the extraction from median and range. + + + +``` r +estim_param_var <- vector("list", nrow(parameters_range)) +# Loop through parameter space estimating parameters +for (params_idx in seq_len(nrow(parameters_range))) { + dist <- as.character(parameters_range[params_idx, "dist"]) + n_samples <- parameters_range[params_idx, "n_samples"] + + # while loop to ensure values are min < median < max + resample_values <- TRUE + while (resample_values) { + if (dist == "lnorm") { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + meanlog = parameters_range[params_idx, "param_1"], + sdlog = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } else { + true_median <- do.call( + paste0("q", dist), + list( + p = 0.5, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- do.call( + paste0("r", dist), + list( + n = n_samples, + shape = parameters_range[params_idx, "param_1"], + scale = parameters_range[params_idx, "param_2"] + ) + ) + true_range <- c(min(true_range), max(true_range)) + } + true_values <- c(true_median, true_range) + if (true_values[2] < true_values[1] && true_values[1] < true_values[3]) { + resample_values <- FALSE + } + } + # message about stochastic optimisation suppressed + estim <- suppressMessages( + replicate( + n = 5, + expr = extract_param( + type = "range", + values = true_values, + distribution = dist, + samples = n_samples + ) + ) + ) + estim_param_var[[params_idx]] <- apply(estim, MARGIN = 1, FUN = var) +} +#> Warning: Maximum optimisation iterations reached, returning result early. +#> Result may not be reliable. +``` + +``` r + +# combine results +results <- cbind(parameters_range, do.call(rbind, estim_param_var)) + +colnames(results) <- c( + "dist", "param_1", "param_2", "n_samples", "estim_param_1_var", + "estim_param_2_var" +) +``` + + +```{.r .fold-hide} +ggplot(data = results) + + geom_point(mapping = aes( + x = estim_param_1_var, + y = estim_param_2_var, + colour = n_samples + )) + + scale_x_continuous(name = "Parameter 1 Variance") + + scale_y_continuous(name = "Parameter 2 Variance") + + labs(colour = "No. Samples") + + theme_bw() + + scale_color_viridis_c() + + facet_wrap(facets = vars(dist), scales = "free") + + theme( + strip.background = element_blank(), + axis.text.x = element_text(angle = 30, vjust = 0.5) + ) +``` + +![Parameter extraction precision, facetted by distribution. Parameter 1 is either the shape parameter, for gamma and Weibull distributions, or meanlog for the lognormal distribution. Parameter 2 is either the scale parameter for gamma and Weibull distributions, or sdlog for the lognormal distribution.](figure/plot-estim-var-range-1.png) + +::: {.alert .alert-primary} +From the plots in this vignette, the bias is low and precision is high +when extracting parameters from the gamma, lognormal and Weibull distributions +from both percentiles of the distribution and from median and range of a data +set. + +The asymmetry of percentiles and sample size of the data does not noticeably +influence the bias in parameter extraction. + +However, this does not ensure reliable extract for all use cases of the +`extract_param()` function and we recommend checking the output for spurious +results. +::: diff --git a/vignettes/extract_convert.Rmd b/vignettes/extract_convert.Rmd new file mode 100644 index 000000000..7f2bbdc61 --- /dev/null +++ b/vignettes/extract_convert.Rmd @@ -0,0 +1,275 @@ +--- +title: "Parameter extraction and conversion in {epiparameter}" +output: + bookdown::html_vignette2: + code_folding: show +bibliography: references.json +link-citations: true +vignette: > + %\VignetteIndexEntry{Parameter extraction and conversion in {epiparameter}} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +The reporting of parameters of distributions in the epidemiological literature +is varied. In some instances the parameters themselves will be given, in others, +summary statistics of the distribution are provided, such as mean, standard +deviation, variance, among others. + +When working with epidemiological parameters it can be useful to have the values +of the parameters for common parameterisations of the distribution. For example, +shape and scale parameters for the gamma and Weibull distribution, and the meanlog +and sdlog parameters for the lognormal distribution. + +In {epiparameter} we provide a range of conversion and extraction functions in +order to obtain distribution parameters from summary statistics and vice versa. + +Here we differentiate between conversion and extraction as what can be analytically +converted, as conversions, and those that require optimisation as extraction. +This vignette aims to describe the functionality of these conversions and +extractions provided by the {epiparameter} package. + +::: {.alert .alert-info} +### Conversion versus extraction + +Use conversion when possible over extraction to avoid possible limitations associated with +numerical optimisation used in the extraction function `extract_param()`. +::: + +```{r setup} +library(epiparameter) +``` + +## Conversions + +There are two conversion functions in {epiparameter}: `convert_params_to_summary_stats()` and `convert_summary_stats_to_params()`. `convert_params_to_summary_stats()` converts one set of statistical distribution parameters to common summary statistics, and `convert_summary_stats_to_params()` converts summary statistics to a set of parameters. + +### Conversion functions + +The conversion functions can take two types of inputs as the first argument: a `character` string of the distribution or an `` object. + +The conversion functions have two arguments. The first (`x`) defines which distribution you want to use and the second (`...`) lets you put as many named parameters or summary statistics as required. The arguments passed into `...` are matched by name, and therefore need to match exactly to the names expected. See the function documentation (`?convert_params_to_summary_stats` and `?convert_summary_stats_to_params` for names). In the case that an `` object is supplied, if it has the parameters or summary statistics required for conversion then nothing needs to be given as extra arguments (i.e. `...`). + +All currently supported summary statistic conversions in {epiparameter} are given below for each distribution. + +#### Gamma distribution + +#### Using a `character` string to name distribution + +```{r} +convert_params_to_summary_stats("gamma", shape = 2.5, scale = 1.5) +``` + +```{r} +convert_summary_stats_to_params("gamma", mean = 2, sd = 2) +convert_summary_stats_to_params("gamma", mean = 2, var = 2) +convert_summary_stats_to_params("gamma", mean = 2, cv = 2) +``` + +#### Using an `` + +An example with parameters provided by `` + +```{r} +ep <- epiparameter( + disease = "", + pathogen = "", + epi_name = "", + prob_distribution = create_prob_distribution( + prob_distribution = "gamma", + prob_distribution_params = c(shape = 2.5, scale = 1.5) + ) +) +convert_params_to_summary_stats(ep) +``` + +An example with `` missing parameters and supplied through `...` + +```{r} +ep <- epiparameter( + disease = "", + pathogen = "", + epi_name = "", + prob_distribution = "gamma" +) +convert_params_to_summary_stats(ep, shape = 2.5, scale = 1.5) +``` + +An example with summary statistics provided by `` + +```{r} +ep <- epiparameter( + disease = "", + pathogen = "", + epi_name = "", + prob_distribution = "gamma", + summary_stats = create_summary_stats(mean = 3.75, sd = 2.37) +) +convert_summary_stats_to_params(ep) +``` + +An example with `` missing summary statistics and supplied through `...` + +```{r} +ep <- epiparameter( + disease = "", + pathogen = "", + epi_name = "", + prob_distribution = "gamma" +) +convert_summary_stats_to_params(ep, mean = 3.75, sd = 2.37) +``` + +The usage of `` is not repeated for every distribution conversion available in {epiparameter}. The conversions shown below for each distribution are also available when using an `` object, by either having the parameters or summary statistics stored in the `` or supplied via named arguments. + +#### Lognormal distribution + +```{r} +convert_params_to_summary_stats("lnorm", meanlog = 2.5, sdlog = 1.5) +``` + +```{r} +convert_summary_stats_to_params("lnorm", mean = 2, sd = 2) +convert_summary_stats_to_params("lnorm", mean = 2, var = 2) +convert_summary_stats_to_params("lnorm", mean = 2, cv = 2) +convert_summary_stats_to_params("lnorm", median = 2, sd = 2) +convert_summary_stats_to_params("lnorm", median = 2, var = 2) +``` + +#### Weibull distribution + +```{r} +convert_params_to_summary_stats("weibull", shape = 2.5, scale = 1.5) +``` + +```{r} +convert_summary_stats_to_params("weibull", mean = 2, sd = 2) +convert_summary_stats_to_params("weibull", mean = 2, var = 2) +convert_summary_stats_to_params("weibull", mean = 2, cv = 2) +``` + +#### Negative binomial distribution + +```{r} +convert_params_to_summary_stats("nbinom", prob = 0.5, dispersion = 0.5) +``` + +```{r} +convert_summary_stats_to_params("nbinom", mean = 1, sd = 1) +convert_summary_stats_to_params("nbinom", mean = 1, var = 1) +convert_summary_stats_to_params("nbinom", mean = 1, cv = 1) +``` + +#### Geometric distribution + +```{r} +convert_params_to_summary_stats("geom", prob = 0.5) +``` + +```{r} +convert_summary_stats_to_params("geom", mean = 1) +``` + +## Extraction + +There are two methods of extraction implemented in {epiparameter}. One is to estimate +the parameters given the values of two percentiles, and the other is to estimate the parameters given the +median and the range of the data. Both of these extractions are implemented in the `extract_param()` function. + +Here we demonstrate extraction using percentiles. The `type` should be `"percentiles"`, the `values` are the values reported at the percentiles, given as a vector. The percentiles, given between 0 and 1, are specified as a vector in `percentiles`. The example below uses values 1 and 10 at the 2.5th and 97.5th percentile, respectively. + +```{r} +extract_param( + type = "percentiles", + values = c(1, 10), + distribution = "gamma", + percentiles = c(0.025, 0.975) +) +``` + +In the above example we estimate parameters of the gamma distribution, but extraction is also implemented for the lognormal, normal and Weibull distributions, but specifying `"lnorm"`, `"norm"` or `"weibull"`. + +A message is shown when running `extract_param()` to make the user aware that the estimates are not completely reliable due to the use of numerical optimisation. Rerunning the function to and finding the same parameters are returned indicates that they have successfully converged. This issue is mostly overcome by the internal setup of the `extract_param()` function which searches for convergence to consistent parameter estimates before returning these to the user. + +The alternative extraction, by median and range, can be achieved by specifying `type = "range"` and using the `samples` argument instead of the `percentiles` argument. When using `type = "percentiles"` the `samples` argument is ignored and when using `type = "range"` the `percentiles` argument is ignored. + +```{r} +extract_param( + type = "range", + values = c(10, 5, 15), + distribution = "lnorm", + samples = 25 +) +``` + +In the above section it was mentioned that `extract_param()` has an internal mechanism to check that the parameters have consistently converged to the same estimates over several optimisation iterations. The tolerance of this convergence and number of times the optimisation can be repeated is specified in the `control` argument of `extract_param()`. This is set by default (`tolerance = 1e-5` and `max_iter = 1000`), and thus does not need to be specified by the user (as shown in the above examples). In the case that the maximum number of optimisation iterations is reached, the calculation terminates returning the most recent optimisation result to the user along with a warning message. + +```{r} +# set seed to ensure warning is produced +set.seed(1) + +# lower maximum iteration to show warning +extract_param( + type = "range", + values = c(10, 1, 25), + distribution = "lnorm", + samples = 100, + control = list(max_iter = 100) +) +``` + +The reasoning for the default maximum number of iterations is to limit the computation time and prevent the function cycling through optimisation routines without converging on a consistent answer. If the runtime is not important and parameter accuracy is paramount then the maximum number of iterations can be increased and tolerance decreased. These `control` settings work identically for extracting from percentiles or median and range. + +### Use cases + +Here we present examples of published epidemiological parameters and distributions where the functions outlined above can be applied to get the parameters of the distribution. + +The 75th percentiles reported for a lognormal distribution from @nolenExtendedHumantoHumanTransmission2016 for the incubation period for mpox (monkeypox). + +```{r, extract_param for monkeypox percentiles} +# Mpox lnorm from 75th percentiles in WHO data +extract_param( + type = "percentiles", + values = c(6, 13), + distribution = "lnorm", + percentiles = c(0.125, 0.875) +) +``` + +The median and range are provided by @thornhillMonkeypoxVirusInfection2022 for mpox, and we want to calculate the parameters of a lognormal distribution. + +```{r, extract_param for monkeypox median and range} +# Mpox lnorm from median and range in 2022: +extract_param( + type = "range", + values = c(7, 3, 20), + distribution = "lnorm", + samples = 23 +) +``` + +::: {.alert .alert-warning} +### Assuming distributions + +It can be the case that a study will report summary statistics for an unspecified distribution or just for the raw data. In these cases if a parameterised distribution is required for downstream analysis a functional, parametric, form may have to be assumed. + +If the distribution is a delay distribution (i.e. serial interval or incubation period) it can often be sensible to assume a right-skewed distribution such as: gamma, lognormal or Weibull distributions. These are also the most commonly fit distributions in epidemiological analysis of delay distributions. + +However, one should take care when assuming a distribution as this may drastically influence the interpretation and application of the epidemiological parameters. +::: + +@donnellyEpidemiologicalDeterminantsSpread2003 provides the mean and variance of the gamma distribution for the incubation period of SARS. This conversion can be achieved by using the general conversion function (`convert_summary_stats_to_params()`). + +```{r, convert parameters} +# SARS gamma mean and var to shape and scale +convert_summary_stats_to_params("gamma", mean = 6.37, var = 16.7) +``` + +## References diff --git a/vignettes/figure/plot-estim-var-range-1.png b/vignettes/figure/plot-estim-var-range-1.png new file mode 100644 index 000000000..91997e42d Binary files /dev/null and b/vignettes/figure/plot-estim-var-range-1.png differ diff --git a/vignettes/figure/plot-results-1.png b/vignettes/figure/plot-results-1.png new file mode 100644 index 000000000..125e024ff Binary files /dev/null and b/vignettes/figure/plot-results-1.png differ diff --git a/vignettes/figure/plot-results-med-range-1.png b/vignettes/figure/plot-results-med-range-1.png new file mode 100644 index 000000000..5fe4b66f3 Binary files /dev/null and b/vignettes/figure/plot-results-med-range-1.png differ diff --git a/vignettes/figure/plot-results-percentiles-1.png b/vignettes/figure/plot-results-percentiles-1.png new file mode 100644 index 000000000..b87a86588 Binary files /dev/null and b/vignettes/figure/plot-results-percentiles-1.png differ diff --git a/vignettes/precompile.R b/vignettes/precompile.R new file mode 100644 index 000000000..34ca70f72 --- /dev/null +++ b/vignettes/precompile.R @@ -0,0 +1,9 @@ +# Pre-compiled vignettes that take a long time to render +# Must manually move image files from epiparameter/ to epiparameter/vignettes/ +# after knit +knitr::knit( + # _ prefix stops pkgdown from re-rendering the original + # https://pkgdown.r-lib.org/reference/build_articles.html + input = file.path("vignettes", "_extract-bias.Rmd.orig"), + output = file.path("vignettes", "extract-bias.Rmd") +) diff --git a/vignettes/references.json b/vignettes/references.json new file mode 100644 index 000000000..9449f0849 --- /dev/null +++ b/vignettes/references.json @@ -0,0 +1,756 @@ +[ + { + "id": "nolenExtendedHumantoHumanTransmission2016", + "type": "article-journal", + "container-title": "Emerging Infectious Diseases", + "DOI": "10.3201/eid2206.150579", + "ISSN": "1080-6040, 1080-6059", + "issue": "6", + "journalAbbreviation": "Emerg. Infect. Dis.", + "page": "1014-1021", + "source": "DOI.org (Crossref)", + "title": "Extended Human-to-Human Transmission during a Monkeypox Outbreak in the Democratic Republic of the Congo", + "URL": "http://wwwnc.cdc.gov/eid/article/22/6/15-0579_article.htm", + "volume": "22", + "author": [ + { + "family": "Nolen", + "given": "Leisha Diane" + }, + { + "family": "Osadebe", + "given": "Lynda" + }, + { + "family": "Katomba", + "given": "Jacques" + }, + { + "family": "Likofata", + "given": "Jacques" + }, + { + "family": "Mukadi", + "given": "Daniel" + }, + { + "family": "Monroe", + "given": "Benjamin" + }, + { + "family": "Doty", + "given": "Jeffrey" + }, + { + "family": "Hughes", + "given": "Christine Marie" + }, + { + "family": "Kabamba", + "given": "Joelle" + }, + { + "family": "Malekani", + "given": "Jean" + }, + { + "family": "Bomponda", + "given": "Pierre Lokwa" + }, + { + "family": "Lokota", + "given": "Jules Inonga" + }, + { + "family": "Balilo", + "given": "Marcel Pie" + }, + { + "family": "Likafi", + "given": "Toutou" + }, + { + "family": "Lushima", + "given": "Robert Shongo" + }, + { + "family": "Ilunga", + "given": "Benoit Kebela" + }, + { + "family": "Nkawa", + "given": "Frida" + }, + { + "family": "Pukuta", + "given": "Elisabeth" + }, + { + "family": "Karhemere", + "given": "Stomy" + }, + { + "family": "Tamfum", + "given": "Jean-Jacques Muyembe" + }, + { + "family": "Nguete", + "given": "Beatrice" + }, + { + "family": "Wemakoy", + "given": "Emile Okitolonda" + }, + { + "family": "McCollum", + "given": "Andrea M." + }, + { + "family": "Reynolds", + "given": "Mary G." + } + ], + "accessed": { + "date-parts": [ + [ + "2022", + 10, + 13 + ] + ] + }, + "issued": { + "date-parts": [ + [ + "2016", + 6 + ] + ] + } + }, + { + "id": "thornhillMonkeypoxVirusInfection2022", + "type": "article-journal", + "container-title": "New England Journal of Medicine", + "DOI": "10.1056/NEJMoa2207323", + "ISSN": "0028-4793, 1533-4406", + "issue": "8", + "journalAbbreviation": "N Engl J Med", + "language": "en", + "page": "679-691", + "source": "DOI.org (Crossref)", + "title": "Monkeypox Virus Infection in Humans across 16 Countries — April–June 2022", + "URL": "http://www.nejm.org/doi/10.1056/NEJMoa2207323", + "volume": "387", + "author": [ + { + "family": "Thornhill", + "given": "John P." + }, + { + "family": "Barkati", + "given": "Sapha" + }, + { + "family": "Walmsley", + "given": "Sharon" + }, + { + "family": "Rockstroh", + "given": "Juergen" + }, + { + "family": "Antinori", + "given": "Andrea" + }, + { + "family": "Harrison", + "given": "Luke B." + }, + { + "family": "Palich", + "given": "Romain" + }, + { + "family": "Nori", + "given": "Achyuta" + }, + { + "family": "Reeves", + "given": "Iain" + }, + { + "family": "Habibi", + "given": "Maximillian S." + }, + { + "family": "Apea", + "given": "Vanessa" + }, + { + "family": "Boesecke", + "given": "Christoph" + }, + { + "family": "Vandekerckhove", + "given": "Linos" + }, + { + "family": "Yakubovsky", + "given": "Michal" + }, + { + "family": "Sendagorta", + "given": "Elena" + }, + { + "family": "Blanco", + "given": "Jose L." + }, + { + "family": "Florence", + "given": "Eric" + }, + { + "family": "Moschese", + "given": "Davide" + }, + { + "family": "Maltez", + "given": "Fernando M." + }, + { + "family": "Goorhuis", + "given": "Abraham" + }, + { + "family": "Pourcher", + "given": "Valerie" + }, + { + "family": "Migaud", + "given": "Pascal" + }, + { + "family": "Noe", + "given": "Sebastian" + }, + { + "family": "Pintado", + "given": "Claire" + }, + { + "family": "Maggi", + "given": "Fabrizio" + }, + { + "family": "Hansen", + "given": "Ann-Brit E." + }, + { + "family": "Hoffmann", + "given": "Christian" + }, + { + "family": "Lezama", + "given": "Jezer I." + }, + { + "family": "Mussini", + "given": "Cristina" + }, + { + "family": "Cattelan", + "given": "AnnaMaria" + }, + { + "family": "Makofane", + "given": "Keletso" + }, + { + "family": "Tan", + "given": "Darrell" + }, + { + "family": "Nozza", + "given": "Silvia" + }, + { + "family": "Nemeth", + "given": "Johannes" + }, + { + "family": "Klein", + "given": "Marina B." + }, + { + "family": "Orkin", + "given": "Chloe M." + } + ], + "accessed": { + "date-parts": [ + [ + "2022", + 10, + 13 + ] + ] + }, + "issued": { + "date-parts": [ + [ + "2022", + 8, + 25 + ] + ] + } + }, + { + "id": "donnellyEpidemiologicalDeterminantsSpread2003", + "type": "article-journal", + "container-title": "The Lancet", + "DOI": "10.1016/S0140-6736(03)13410-1", + "ISSN": "01406736", + "issue": "9371", + "journalAbbreviation": "The Lancet", + "language": "en", + "page": "1761-1766", + "source": "DOI.org (Crossref)", + "title": "Epidemiological determinants of spread of causal agent of severe acute respiratory syndrome in Hong Kong", + "URL": "https://linkinghub.elsevier.com/retrieve/pii/S0140673603134101", + "volume": "361", + "author": [ + { + "family": "Donnelly", + "given": "Christl A" + }, + { + "family": "Ghani", + "given": "Azra C" + }, + { + "family": "Leung", + "given": "Gabriel M" + }, + { + "family": "Hedley", + "given": "Anthony J" + }, + { + "family": "Fraser", + "given": "Christophe" + }, + { + "family": "Riley", + "given": "Steven" + }, + { + "family": "Abu-Raddad", + "given": "Laith J" + }, + { + "family": "Ho", + "given": "Lai-Ming" + }, + { + "family": "Thach", + "given": "Thuan-Quoc" + }, + { + "family": "Chau", + "given": "Patsy" + }, + { + "family": "Chan", + "given": "King-Pan" + }, + { + "family": "Lam", + "given": "Tai-Hing" + }, + { + "family": "Tse", + "given": "Lai-Yin" + }, + { + "family": "Tsang", + "given": "Thomas" + }, + { + "family": "Liu", + "given": "Shao-Haei" + }, + { + "family": "Kong", + "given": "James HB" + }, + { + "family": "Lau", + "given": "Edith MC" + }, + { + "family": "Ferguson", + "given": "Neil M" + }, + { + "family": "Anderson", + "given": "Roy M" + } + ], + "accessed": { + "date-parts": [ + [ + "2022", + 10, + 14 + ] + ] + }, + "issued": { + "date-parts": [ + [ + "2003", + 5 + ] + ] + } + }, + { + "id": "higginsCochraneHandbookSystematic2022", + "type": "book", + "call-number": "R723.7 .C63 2008", + "collection-title": "Cochrane book series", + "edition": "6.3", + "event-place": "Chichester, England ; Hoboken, NJ", + "ISBN": "978-0-470-69951-5", + "note": "OCLC: ocn154798512", + "number-of-pages": "649", + "publisher": "Wiley-Blackwell", + "publisher-place": "Chichester, England ; Hoboken, NJ", + "source": "Library of Congress ISBN", + "title": "Cochrane Handbook for Systematic Reviews of Interventions", + "URL": "www.training.cochrane.org/handbook", + "editor": [ + { + "family": "Higgins", + "given": "Julian P. T." + }, + { + "literal": "Thomas, J" + }, + { + "literal": "Chandler, J" + }, + { + "literal": "Cumpston, M" + }, + { + "literal": "Li, T" + }, + { + "literal": "Page, MJ" + }, + { + "literal": "Welch, VA" + } + ], + "issued": { + "date-parts": [ + [ + "2022" + ] + ] + } + }, + { + "id": "pagePRISMA2020Statement2021", + "type": "article-journal", + "container-title": "BMJ", + "DOI": "10.1136/bmj.n71", + "ISSN": "1756-1833", + "journalAbbreviation": "BMJ", + "language": "en", + "page": "n71", + "source": "DOI.org (Crossref)", + "title": "The PRISMA 2020 statement: an updated guideline for reporting systematic reviews", + "title-short": "The PRISMA 2020 statement", + "URL": "https://www.bmj.com/lookup/doi/10.1136/bmj.n71", + "author": [ + { + "family": "Page", + "given": "Matthew J" + }, + { + "family": "McKenzie", + "given": "Joanne E" + }, + { + "family": "Bossuyt", + "given": "Patrick M" + }, + { + "family": "Boutron", + "given": "Isabelle" + }, + { + "family": "Hoffmann", + "given": "Tammy C" + }, + { + "family": "Mulrow", + "given": "Cynthia D" + }, + { + "family": "Shamseer", + "given": "Larissa" + }, + { + "family": "Tetzlaff", + "given": "Jennifer M" + }, + { + "family": "Akl", + "given": "Elie A" + }, + { + "family": "Brennan", + "given": "Sue E" + }, + { + "family": "Chou", + "given": "Roger" + }, + { + "family": "Glanville", + "given": "Julie" + }, + { + "family": "Grimshaw", + "given": "Jeremy M" + }, + { + "family": "Hróbjartsson", + "given": "Asbjørn" + }, + { + "family": "Lalu", + "given": "Manoj M" + }, + { + "family": "Li", + "given": "Tianjing" + }, + { + "family": "Loder", + "given": "Elizabeth W" + }, + { + "family": "Mayo-Wilson", + "given": "Evan" + }, + { + "family": "McDonald", + "given": "Steve" + }, + { + "family": "McGuinness", + "given": "Luke A" + }, + { + "family": "Stewart", + "given": "Lesley A" + }, + { + "family": "Thomas", + "given": "James" + }, + { + "family": "Tricco", + "given": "Andrea C" + }, + { + "family": "Welch", + "given": "Vivian A" + }, + { + "family": "Whiting", + "given": "Penny" + }, + { + "family": "Moher", + "given": "David" + } + ], + "accessed": { + "date-parts": [ + [ + "2023", + 3, + 9 + ] + ] + }, + "issued": { + "date-parts": [ + [ + "2021", + 3, + 29 + ] + ] + } + }, + { + "id": "elliottLivingSystematicReviews2014", + "type": "article-journal", + "container-title": "PLoS Medicine", + "DOI": "10.1371/journal.pmed.1001603", + "ISSN": "1549-1676", + "issue": "2", + "journalAbbreviation": "PLoS Med", + "language": "en", + "page": "e1001603", + "source": "DOI.org (Crossref)", + "title": "Living Systematic Reviews: An Emerging Opportunity to Narrow the Evidence-Practice Gap", + "title-short": "Living Systematic Reviews", + "URL": "https://dx.plos.org/10.1371/journal.pmed.1001603", + "volume": "11", + "author": [ + { + "family": "Elliott", + "given": "Julian H." + }, + { + "family": "Turner", + "given": "Tari" + }, + { + "family": "Clavisi", + "given": "Ornella" + }, + { + "family": "Thomas", + "given": "James" + }, + { + "family": "Higgins", + "given": "Julian P. T." + }, + { + "family": "Mavergames", + "given": "Chris" + }, + { + "family": "Gruen", + "given": "Russell L." + } + ], + "accessed": { + "date-parts": [ + [ + "2023", + 3, + 9 + ] + ] + }, + "issued": { + "date-parts": [ + [ + "2014", + 2, + 18 + ] + ] + } + }, + { + "id": "fayeChainsTransmissionControl2015a", + "type": "article-journal", + "container-title": "The Lancet Infectious Diseases", + "DOI": "10.1016/S1473-3099(14)71075-8", + "ISSN": "14733099", + "issue": "3", + "journalAbbreviation": "The Lancet Infectious Diseases", + "language": "en", + "page": "320-326", + "source": "DOI.org (Crossref)", + "title": "Chains of transmission and control of Ebola virus disease in Conakry, Guinea, in 2014: an observational study", + "title-short": "Chains of transmission and control of Ebola virus disease in Conakry, Guinea, in 2014", + "URL": "https://linkinghub.elsevier.com/retrieve/pii/S1473309914710758", + "volume": "15", + "author": [ + { + "family": "Faye", + "given": "Ousmane" + }, + { + "family": "Boëlle", + "given": "Pierre-Yves" + }, + { + "family": "Heleze", + "given": "Emmanuel" + }, + { + "family": "Faye", + "given": "Oumar" + }, + { + "family": "Loucoubar", + "given": "Cheikh" + }, + { + "family": "Magassouba", + "given": "N'Faly" + }, + { + "family": "Soropogui", + "given": "Barré" + }, + { + "family": "Keita", + "given": "Sakoba" + }, + { + "family": "Gakou", + "given": "Tata" + }, + { + "family": "Bah", + "given": "El Hadji Ibrahima" + }, + { + "family": "Koivogui", + "given": "Lamine" + }, + { + "family": "Sall", + "given": "Amadou Alpha" + }, + { + "family": "Cauchemez", + "given": "Simon" + } + ], + "accessed": { + "date-parts": [ + [ + "2024", + 6, + 17 + ] + ] + }, + "issued": { + "date-parts": [ + [ + "2015", + 3 + ] + ] + } + } +] \ No newline at end of file