Estimate and Forecast Real-Time Infection Dynamics
Overview
Estimates the time-varying reproduction number, rate of spread, and doubling time using a renewal equation approach combined with Bayesian inference via Stan. Supports Gaussian process and random walk priors for modelling changes in transmission over time. Accounts for delays between infection and observation (incubation period, reporting delays), right-truncation in recent data, day-of-week effects, and observation overdispersion. Can estimate relationships between primary and secondary outcomes (e.g., cases to hospitalisations or deaths) and forecast both. Runs across multiple regions in parallel. Based on Abbott et al. (2020) doi:10.12688/wellcomeopenres.16006.1 and Gostic et al. (2020) doi:10.1101/2020.06.18.20134858.
New features
- Added support for all
dist_specdelay families andobs_opts()observation model selection (Poisson or negative binomial) toestimate_truncation(). The existing observation model functions (report_lp,report_rng) are now reused internally. - Wired the
likelihoodandreturn_likelihoodsettings ofobs_opts()throughestimate_truncation()so that prior-only fits andloo-compatible log-likelihood output are available, matchingestimate_infections()andestimate_secondary(). - Added a
noiseargument toestimate_truncation()that takes adist_speccontrolling the additive noise term, replacing the previously hardcodedsigma ~ normal(0, 1) T[0,]. estimate_truncation()now warns viacheck_truncation_obs_opts()whenobs_opts()settings unused by the truncation model (weight,week_effect,week_length,scale) are set to non-default values.- Added
estimate_dist()for fitting delay distributions from interval-censored linelist data using Bayesian inference, with support for lognormal, gamma, normal, exponential, and Weibull distributions. - Added
Exp(),Weibull(), andNormal()distribution constructors. - Added
Dirichlet()and updatedNonParametric()to support estimating nonparametric delay distributions using a Dirichlet prior, as an alternative to fixedNonParametric()or parametric distributions. This uses a gamma normalisation trick for efficient sampling with ragged simplex support in Stan. - Added a shared internal helper
check_simulation_input()that bundles the repeated input data frame validation insimulate_infections()andsimulate_secondary(). - Added
as_forecast_sample()S3 methods forepinow,estimate_infections,forecast_secondary, andestimate_truncationobjects, allowing direct conversion toforecast_sampleobjects viascoringutils::as_forecast_sample()for evaluation.
Breaking changes
- Removed deprecated arguments that have been erroring since v1.7.0/v1.8.0:
Show all changes in 1.9.0Hide the rest of the changes in 1.9.0
gp_opts(ls_mean, ls_sd, ls_min, ls_max): uselsinsteadgp_opts(alpha_mean, alpha_sd): usealphainsteadobs_opts(phi): usedispersioninsteadobs_opts(na): usefill_missing()insteadestimate_infections(filter_leading_zeros, zero_threshold, horizon)estimate_secondary(filter_leading_zeros, zero_threshold)epinow(filter_leading_zeros, zero_threshold, horizon)regional_epinow(horizon)format_fit(burn_in, start_date)- Removed the internal function
default_fill_missing_obs(). - The
popargument inrt_opts()andsimulate_infections()now errors when passed a numeric value. UseFixed(pop)instead. - Deprecated accessors on model objects now error instead of warning:
estimate_infections():$samples,$summarisedestimate_secondary():$predictions,$posterior,$dataestimate_truncation():$dist,$obs,$data,$last_obs,$cmfepinow():$estimates,$estimated_reported_cases,$summary,$plots,$estimate_infectionssummary.epinow(output)andsummary.estimate_infections(type = 'samples')now error.- Removed internal function
extract_parameter_samples(). Useformat_simulation_output()instead.
Deprecations
estimate_delay()is soft-deprecated in favour ofestimate_dist().
Model changes
- Changed the non-stationary Gaussian process used to model Rt to sample in a mean-centred form internally, eliminating the
(R0, drift)ridge in the joint posterior that caused stuck chains and catastrophic R-hat values on some seeds. The user-facing interpretation is unchanged: thepriorargument inrt_opts()is still the prior on the initial Rt. Implemented by sampling the trajectory mean internally and applying the user prior to the derived initial Rt with the Jacobian-correct change of variables, so the joint prior matches the pre-change model. - Updated the breakpoint random walk to be centred over the observation window, removing the
(R0, drift)ridge in the joint posterior alongside the equivalent fix for the non-stationary Gaussian process. - Delay distribution discretisation now properly accounts for primary event censoring during model fitting, matching the correction already applied on the R side since v1.8.0. This improves accuracy for short delays where the observation window is large relative to the delay.
- Left truncation of delay distributions (e.g. excluding generation times of zero) is now handled analytically rather than by zeroing and renormalising, giving more accurate PMFs near the truncation point.
- Refactored the Gaussian process, convolution, and observation model Stan functions for efficiency and readability, including a shared
matern_indices()helper for the Matern spectral densities, outer-product basis function construction inPHI()andPHI_periodic(), and a sharedreporting_phi()helper for the negative binomial overdispersion.
Bug fixes
- Fixed a bug where the
target_dateargument toepinow()was silently ignored: the recomputed forecast horizon fromupdate_horizon()was never propagated into the call toestimate_infections(). - Fixed a bug in
forecast_infections()where the summary call to extract dates was using modified args instead of the original fit dimensions, causing a date-dimension mismatch when extending the R trajectory beyond the original observation period. - Centralised the gating of
dispersiononfamilyinobs_opts():dispersionis nowNULLwheneverfamily != "negbin", with a warning if the caller supplied one explicitly. As a result,reporting_overdispersionis no longer sampled from its prior inestimate_infections(),estimate_secondary(),simulate_infections()andestimate_truncation()when a Poisson observation model is used. - Fixed a bug where
estimate_dist()would fail with a "model fitting timed out or failed" error when observed delays had near-zero variance. Scale parameters are now initialised from the prior when variance cannot be estimated from the data, and a warning is issued. - Fixed a bug where
example_truncatedwas generated with the old discrete-CDF PMF whileestimate_truncation()now uses the primarycensored-based PMF, causing biased parameter recovery. The dataset has been regenerated for consistency. - Fixed a bug where
get_parameters()failed with$ operator not defined for this S4 classon a fit with an estimated nonparametric (Dirichlet) delay when using therstanbackend. Posterior draws are now extracted in a backend-agnostic way. - Fixed a bug where
forecast_infections()errored when called on anestimate_infectionsobject fitted with thecmdstanrbackend (it was callingrstan::extract()directly on theCmdStanMCMCfit; now uses the backend-agnostic internal helper). - A bug was fixed where the trailing entries of
imputed_reportsinestimate_infections()output were undefined due to a size mismatch in the Stan generated quantities block.
Documentation
- Added a vignette demonstrating delay distribution fitting workflows and posterior validation.
- Added a model definition vignette for
estimate_dist(). - Added a model overview vignette with an architecture diagram showing how the package's models connect.
- Added a model features vignette providing a quick reference to all modelling options with links to detailed documentation.
- The delay distribution fitting vignette has been renamed from
vignette("estimate-dist")tovignette("estimate_dist_workflow")for consistency with the other workflow vignettes; the model definition is atvignette("estimate_dist"). - Added a cross-reference from the
estimate_truncation()vignette toestimate_dist(), summarising when to use each. - Expanded the case studies vignette with additional literature references and public health surveillance examples.
- The lower-accuracy GP example in the
estimate_infections_optionsvignette now usesbasis_prop = 0.15instead of0.1, which fits cleanly under the new centred parameterisation.
Package changes
- The touchstone continuous benchmarks now also cover
estimate_truncation(),estimate_secondary()andestimate_dist()alongside the existingepinow()configurations, giving a single standardised view of wall-clock performance across the main user-facing fitting functions. - Updated the vendored primarycensored Stan code to version 1.5.0 (CRAN release 2026-06-04).
From NEWS.md in the release
Install
Health
- OK13 OK2026-08-22
- ERROR12 OK, 1 ERROR2026-08-20
- OK13 OK2026-08-05
- NOTE12 OK, 1 NOTE2026-08-01
- OK13 OK2026-07-29
Show 7 earlier changesHide 7 earlier changes
- ERROR12 OK, 1 ERROR2026-07-27
- OK12 OK2026-04-25
- NOTE11 OK, 3 NOTE2026-04-22
- ERROR10 OK, 3 NOTE, 1 ERROR2026-04-18
- NOTE11 OK, 3 NOTE2026-03-18
- WARNING11 OK, 2 NOTE, 1 WARNING2026-03-17
- NOTE11 OK, 3 NOTE2026-03-10
Documentation
- Help pages
- 200 (99 internal)includes a package overview page
- Examples that run
- 67%55 run in a plain check · 14 only when donttest examples are enabled (R CMD check --as-cran) · 13 never run
- Exported functions with examples
- 84%
- Documented parameters
- 95%
- Return-value docs
- 100%
- Help pages citing references
- 3%
- Getting started with EpiNow2
- Case studies and use in the literature HTML
- Examples: estimate_infections()
- Fitting delay distributions with estimate_dist()
- Forecasting multiple data streams
- Gaussian Process implementation details
- Model definition: estimate_dist()
- Model definition: estimate_infections()
- Model definition: estimate_secondary() HTML
- Model definition: estimate_truncation() HTML
Downloads
Repository
- PRs merged (all time)
- 73%
- Median days to close, 50 most recently updated closed issues
- 26
- Median days to close, 50 most recently updated closed PRs
- 2
Stars over time
Forks over time
Releases over time
Issues over time
PRs over time
Commits over time
20 development-tooling and community-health practices detected across 10 families in the upstream repository
Checks run against github.com/epiforecasts/epinow2 on 2026-10-22.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-10-05 · The repository has a site deploy workflow
pkgdown site last built 2026-06-17
Show all practicesHide 6 practices
This repository shows signs of AI coding tools.
- Claude Codefirst seen 2025-10-31Seen in the repository: CLAUDE.mdNamed in .Rbuildignore: .claude, CLAUDE.local.md, CLAUDE.mdNamed in .gitignore: .claudePull request it wrote: opened by a project memberCommits: 1 by its own account · at least 20 crediting it in the message
- Claude CodePull requests: 3 from outside contributors, first on 2025-05-28
Dependencies
Installing EpiNow2 adds 63 packages (28 with compiled code, 56 MB of source tarballs). Heaviest: BH 14 MB, ggplot2 6.0 MB, data.table 5.7 MB.
Code & Tests
Datasets
People & History
Show 3 more contributorsHide 3 contributors
Previously maintained by Sam Abbott (1.1.0 to 1.4.0).
Pick two releases to compare their code metrics.
- 1.9.0Latest
- RR 4.6.0 released · 2026-04-24
- 1.8.02026-02-05 · diff ↗ ·
removed 3 exports
apply_tolerance, dist_skel, fix_distadded 2 exports
get_predictions, get_samples - RR 4.5.0 released · 2025-04-11
- 1.7.12025-02-20 · diff ↗ ·
removed 11 exports
adjust_infection_to_report, gamma_dist_def, get_dist, get_generation_time, get_incubation_period, lognorm_dist_def, report_cases, rstan_opts, rstan_sampling_opts, rstan_vb_opts, sample_approx_dist - 1.7.02025-02-05 · diff ↗ ·
added 4 exports
add_breakpoints, fill_missing, filter_leading_zeros, forecast_opts - 1.6.12024-10-31 · diff ↗
- 1.6.02024-10-02 · diff ↗ ·
removed 1 export
dist_specadded 5 exports
bound_dist, epinow2_cmdstan_model, fix_parameters, gt_opts, is_constrained - 1.5.22024-05-17 · diff ↗
- 1.5.12024-05-14 · diff ↗
- 1.5.02024-05-10 · diff ↗ ·
removed 25 exports
add_day_of_week, construct_output, copy_results_to_latest, create_backcalc_data, create_clean_reported_cases, create_gp_data, create_initial_conditions, create_obs_model, create_rt_data, create_shifted_cases, create_stan_args, create_stan_data, estimates_by_report_date, get_raw_result, get_regions, get_regions_with_most_reports, save_estimate_infections, save_input, setup_dt, setup_target_folder, summarise_key_measures, summarise_results, tune_inv_gamma, update_horizon, update_listadded 21 exports
Fixed, Gamma, LogNormal, NonParametric, Normal, apply_tolerance, collapse, convolve_and_scale, discretise, discretize, extract_samples, fix_dist, forecast_infections, get_distribution, get_parameters, get_pmf, new_dist_spec, stan_laplace_opts, stan_pathfinder_opts, stan_sampling_opts, stan_vb_opts - RR 4.4.0 released · 2024-04-24
- 1.4.02023-09-26 · diff ↗
- unarchivedReturned to CRAN2023-04-27
- 1.3.52023-04-27 · diff ↗
- RR 4.3.0 released · 2023-04-21
Show 11 earlier eventsHide 11 earlier events
- archivedRemoved from CRAN2023-03-02issues were not corrected in time
- unarchivedReturned to CRAN2023-02-12
- 1.3.42023-02-12 · diff ↗ ·
removed 6 exports
country_map, forecast_infections, global_map, save_forecast_infections, simulate_cases, theme_mapadded 6 exports
add_day_of_week, dist_spec, generation_time_opts, set_dt_single_thread, simulate_secondary, update_secondary_args - archivedRemoved from CRAN2022-10-19issues were not corrected in time
- RR 4.2.0 released · 2022-04-22
- RR 4.1.0 released · 2021-05-18
- 1.3.22020-12-14 · diff ↗ ·
added 5 exports
estimate_secondary, extract_inits, extract_stan_param, forecast_secondary, secondary_opts - 1.3.12020-11-22 · diff ↗ ·
removed 1 export
match_output_argumentsadded 22 exports
backcalc_opts, convert_to_logmean, convert_to_logsd, create_backcalc_data, create_gp_data, create_obs_model, create_rt_data, delay_opts, estimate_delay, estimate_truncation, expose_stan_fns, gp_opts, obs_opts, opts_list, rstan_opts, rstan_sampling_opts, rstan_vb_opts, rt_opts, simulate_infections, stan_opts, trunc_opts, update_list - 1.2.12020-10-20 · diff ↗ ·
added 29 exports
calc_CrI, calc_CrIs, calc_summary_measures, calc_summary_stats, construct_output, copy_results_to_latest, create_clean_reported_cases, create_initial_conditions, create_shifted_cases, create_stan_args, create_stan_data, estimates_by_report_date, extract_CrIs, get_dist, get_generation_time, get_incubation_period, get_regions_with_most_reports, match_output_arguments, regional_runtimes, save_estimate_infections, save_forecast_infections, save_input, setup_default_logging, setup_dt, setup_future, setup_logging, setup_target_folder, tune_inv_gamma, update_horizon - 1.1.02020-09-01
- RR 4.0.0 released · 2020-04-24
Package metadata
- First published
- 2020-09-01
- Total releases
- 16 / 6 yrs
- License
- MIT + file LICENSE OSI
- Additional repositories
- production.r-multiverse.org
- Minimum R
- ≥ 3.5.0
- Bundled data
- 2.4 KB / 5 files
- Download size
- 6.6 MB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("EpiNow2")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
The repository also keeps a CITATION.cff.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-23, which the citation names so these numbers can be found later. More on citing and the projects behind them.