EpiNow2 Stan Functions
rt.stan
Go to the documentation of this file.
1/**
2 * Reproduction Number (Rt) Functions
3 *
4 * This group of functions handles the calculation, updating, and conversion of
5 * reproduction numbers in the model. The reproduction number represents the average
6 * number of secondary infections caused by a single infected individual.
7 *
8 * @ingroup rt_estimation
9 */
10
11/**
12 * @ingroup rt_estimation
13 * @brief Update a vector of effective reproduction numbers (Rt) based on
14 * an intercept, breakpoints (i.e. a random walk), and a Gaussian
15 * process.
16 *
17 * @param t Length of the time series
18 * @param R0 Initial reproduction number
19 * @param noise Vector of Gaussian process noise values
20 * @param bps Array of breakpoint indices
21 * @param bp_effects Vector of breakpoint effects
22 * @param stationary Whether the Gaussian process is stationary (1) or non-stationary (0)
23 * @param n_centre Number of leading positions over which to centre the
24 * non-stationary GP trajectory and the breakpoint random walk. Set to the
25 * observation window length so the centring is invariant to the forecast
26 * horizon. Ignored for the GP branch when `stationary` is 1; the breakpoint
27 * path is centred whenever breakpoints are present.
28 * @return A vector of length t containing the updated Rt values
29 */
30vector update_Rt(int t, real R0, vector noise, array[] int bps,
31 vector bp_effects, int stationary, int n_centre) {
32 // define control parameters
33 int bp_n = num_elements(bp_effects);
34 int gp_n = num_elements(noise);
35 // initialise intercept
36 vector[t] logR = rep_vector(log(R0), t);
37 //initialise breakpoints + rw
38 if (bp_n) {
39 vector[bp_n + 1] bp0;
40 bp0[1] = 0;
41 bp0[2:(bp_n + 1)] = cumulative_sum(bp_effects);
42 vector[t] bp = bp0[bps];
43 // Centre over the observation window (same identifiability fix as the GP below).
44 bp -= mean(bp[1:n_centre]);
45 logR = logR + bp;
46 }
47 //initialise gaussian process
48 if (gp_n) {
49 vector[t] gp = rep_vector(0, t);
50 if (stationary) {
51 gp[1:gp_n] = noise;
52 // fix future gp based on last estimated
53 if (t > gp_n) {
54 gp[(gp_n + 1):t] = rep_vector(noise[gp_n], t - gp_n);
55 }
56 } else {
57 gp[2:(gp_n + 1)] = noise;
58 gp = cumulative_sum(gp);
59 // Centre over the observation window (same identifiability fix as the BP above).
60 gp -= mean(gp[1:n_centre]);
61 }
62 logR = logR + gp;
63 }
64
65 return exp(logR);
66}
67
68/**
69 * Calculate the log-probability of the reproduction number (Rt) priors
70 *
71 * This function adds the log density contributions from priors on initial infections
72 * and breakpoint effects to the target.
73 *
74 * @param initial_infections_scale Array of initial infection values
75 * @param bp_effects Vector of breakpoint effects
76 * @param bp_sd Array of breakpoint standard deviations
77 * @param bp_n Number of breakpoints
78 * @param cases Array of observed case counts
79 * @param initial_infections_guess Initial guess for infections based on cases
80 *
81 * @ingroup rt_estimation
82 */
83void rt_lp(array[] real initial_infections_scale, vector bp_effects,
84 array[] real bp_sd, int bp_n, array[] int cases,
85 real initial_infections_guess) {
86 //breakpoint effects on Rt
87 if (bp_n > 0) {
88 bp_sd[1] ~ normal(0, 0.1) T[0,];
89 bp_effects ~ normal(0, bp_sd[1]);
90 }
91 initial_infections_scale ~ normal(initial_infections_guess, 2);
92}
93
94/**
95 * Helper function for calculating r from R using Newton's method
96 *
97 * This function performs a single Newton step in the iterative calculation
98 * of the growth rate r from the reproduction number R.
99 *
100 * Code is based on Julia code from
101 * https://github.com/CDCgov/Rt-without-renewal/blob/d6344cc6e451e3e6c4188e4984247f890ae60795/EpiAware/test/predictive_checking/fast_approx_for_r.jl
102 * under Apache license 2.0.
103 *
104 * @param R Reproduction number
105 * @param r Current estimate of the growth rate
106 * @param pmf Generation time probability mass function (first index: 0)
107 * @return The Newton step for updating r
108 *
109 * @ingroup rt_estimation
110 */
111real R_to_r_newton_step(real R, real r, vector pmf) {
112 int len = num_elements(pmf);
113 vector[len] zero_series = linspaced_vector(len, 0, len - 1);
114 vector[len] exp_r = exp(-r * zero_series);
115 real ret = (R * dot_product(pmf, exp_r) - 1) /
116 (- R * dot_product(pmf .* zero_series, exp_r));
117 return(ret);
118}
119
120/**
121 * Estimate the growth rate r from reproduction number R
122 *
123 * This function uses the Newton method to solve for the growth rate r
124 * that corresponds to a given reproduction number R, using the generation
125 * time distribution.
126 *
127 * Code is based on Julia code from
128 * https://github.com/CDCgov/Rt-without-renewal/blob/d6344cc6e451e3e6c4188e4984247f890ae60795/EpiAware/test/predictive_checking/fast_approx_for_r.jl
129 * under Apache license 2.0.
130 *
131 * @param R Reproduction number
132 * @param gt_rev_pmf Reversed probability mass function of the generation time
133 * @param abs_tol Absolute tolerance for the Newton solver
134 * @return The estimated growth rate r
135 *
136 * @ingroup rt_estimation
137 */
138real R_to_r(real R, vector gt_rev_pmf, real abs_tol) {
139 int gt_len = num_elements(gt_rev_pmf);
140 vector[gt_len] gt_pmf = reverse(gt_rev_pmf);
141 real mean_gt = dot_product(gt_pmf, linspaced_vector(gt_len, 0, gt_len - 1));
142 real r = fmax((R - 1) / (R * mean_gt), -1);
143 real step = abs_tol + 1;
144 while (abs(step) > abs_tol) {
145 step = R_to_r_newton_step(R, r, gt_pmf);
146 r -= step;
147 }
148
149 return(r);
150}
real R_to_r_newton_step(real R, real r, vector pmf)
Definition rt.stan:111
real R_to_r(real R, vector gt_rev_pmf, real abs_tol)
Definition rt.stan:138
vector update_Rt(int t, real R0, vector noise, array[] int bps, vector bp_effects, int stationary, int n_centre)
Update a vector of effective reproduction numbers (Rt) based on an intercept, breakpoints (i....
Definition rt.stan:30
void rt_lp(array[] real initial_infections_scale, vector bp_effects, array[] real bp_sd, int bp_n, array[] int cases, real initial_infections_guess)
Definition rt.stan:83