EpiNow2 Stan Functions
infections.stan
Go to the documentation of this file.
1/**
2 * Infection Modeling Functions
3 *
4 * This group of functions handles the generation, calculation, and backcalculation
5 * of infection time series in the model. These functions implement the core
6 * epidemiological dynamics, including the renewal equation approach.
7 *
8 * @ingroup infections_estimation
9 */
10
11/**
12 * Calculate infectiousness for a single time point
13 *
14 * This function computes the weighted sum of past infections with the generation
15 * time distribution to determine the current infectiousness.
16 *
17 * @param infections Vector of infection counts
18 * @param gt_rev_pmf Vector of reversed generation time PMF
19 * @param seeding_time Number of time steps used for seeding
20 * @param index Current time index (relative to seeding_time)
21 * @return The infectiousness at the specified time point
22 *
23 * @ingroup infections_estimation
24 */
25real update_infectiousness(vector infections, vector gt_rev_pmf,
26 int seeding_time, int index){
27 int gt_length = num_elements(gt_rev_pmf);
28 // work out where to start the convolution of past infections with the
29 // generation time distribution: (current_time - maximal generation time) if
30 // that is >= 1, otherwise 1
31 int inf_start = max(1, (index + seeding_time - gt_length + 1));
32 // work out where to end the convolution: current_time
33 int inf_end = (index + seeding_time);
34 // number of indices of the generation time to sum over
35 // (inf_end - inf_start + 1)
36 int pmf_accessed = min(gt_length, index + seeding_time);
37 // calculate the elements of the convolution
38 real new_inf = dot_product(
39 infections[inf_start:inf_end], tail(gt_rev_pmf, pmf_accessed)
40 );
41 return(new_inf);
42}
43
44/**
45 * @ingroup infections_estimation
46 * @brief Generate infections using a renewal equation approach
47 *
48 * This function implements the renewal equation to generate a time series of
49 * infections based on reproduction numbers and the generation time distribution.
50 * It can also account for population depletion if a population size is specified.
51 *
52 * @param R Vector of reproduction numbers
53 * @param uot Unobserved time (seeding time)
54 * @param gt_rev_pmf Vector of reversed generation time PMF
55 * @param initial_infections Array of initial infection values
56 * @param pop Initial susceptible population (0 for unlimited)
57 * @param use_pop Population adjustment mode (0=none, 1=forecast only, 2=all)
58 * @param pop_floor Minimum susceptible population (floor to prevent instability)
59 * @param ht Horizon time
60 * @param obs_scale Whether to scale by fraction observed (1) or not (0)
61 * @param frac_obs Fraction of infections that are observed
62 * @param initial_as_scale Whether initial infections are a scaling factor (1) or not (0)
63 * @return A vector of infection counts
64 */
65vector generate_infections(vector R, int uot, vector gt_rev_pmf,
66 array[] real initial_infections, real pop,
67 int use_pop, real pop_floor, int ht, int obs_scale, real frac_obs,
68 int initial_as_scale) {
69 // time indices and storage
70 int ot = num_elements(R);
71 int nht = ot - ht;
72 int t = ot + uot;
73 real exp_adj_Rt;
74 vector[t] infections = rep_vector(0, t);
75 vector[ot] cum_infections;
76 vector[ot] infectiousness;
77 real growth = R_to_r(R[1], gt_rev_pmf, 1e-3);
78 // Initialise infections using daily growth
79 if (initial_as_scale) {
80 infections[1] = exp(initial_infections[1] - growth * uot);
81 if (obs_scale) {
82 infections[1] = infections[1] / frac_obs;
83 }
84 } else {
85 infections[1] = exp(initial_infections[1]);
86 }
87 if (uot > 1) {
88 real exp_growth = exp(growth);
89 for (s in 2:uot) {
90 infections[s] = infections[s - 1] * exp_growth;
91 }
92 }
93 // calculate cumulative infections
94 if (use_pop) {
95 cum_infections[1] = sum(infections[1:uot]);
96 }
97 // iteratively update infections
98 for (s in 1:ot) {
99 infectiousness[s] = update_infectiousness(infections, gt_rev_pmf, uot, s);
100 if ((use_pop == 1 && s > nht) || use_pop == 2) {
101 real susceptible = fmax(pop_floor, pop - cum_infections[s]);
102 exp_adj_Rt = exp(-R[s] * infectiousness[s] / susceptible);
103 infections[s + uot] = susceptible * fmax(0, 1 - exp_adj_Rt);
104 } else{
105 infections[s + uot] = R[s] * infectiousness[s];
106 }
107 if (use_pop && s < ot) {
108 cum_infections[s + 1] = cum_infections[s] + infections[s + uot];
109 }
110 }
111 return(infections);
112}
113
114/**
115 * Backcalculate infections from cases
116 *
117 * This function estimates infections by working backwards from observed cases,
118 * applying noise to account for uncertainty in the process.
119 *
120 * @param shifted_cases Vector of shifted case counts
121 * @param noise Vector of noise values
122 * @param fixed Whether to use fixed (1) or variable (0) noise
123 * @param prior Prior type to use (0: noise only, 1: cases * noise, 2: random walk)
124 * @return A vector of infection counts
125 *
126 * @ingroup infections_estimation
127 */
128vector deconvolve_infections(vector shifted_cases, vector noise, int fixed,
129 int prior) {
130 int t = num_elements(shifted_cases);
131 vector[t] infections = rep_vector(1e-5, t);
132 if (!fixed) {
133 vector[t] exp_noise = exp(noise);
134 if (prior == 1) {
135 infections = infections + shifted_cases .* exp_noise;
136 } else if (prior == 0) {
137 infections = infections + exp_noise;
138 } else if (prior == 2) {
139 infections[1] = infections[1] + shifted_cases[1] * exp_noise[1];
140 for (i in 2:t) {
141 infections[i] = infections[i - 1] * exp_noise[i];
142 }
143 }
144 } else {
145 infections = infections + shifted_cases;
146 }
147 return(infections);
148}
vector generate_infections(vector R, int uot, vector gt_rev_pmf, array[] real initial_infections, real pop, int use_pop, real pop_floor, int ht, int obs_scale, real frac_obs, int initial_as_scale)
Generate infections using a renewal equation approach.
real update_infectiousness(vector infections, vector gt_rev_pmf, int seeding_time, int index)
vector deconvolve_infections(vector shifted_cases, vector noise, int fixed, int prior)
real R_to_r(real R, vector gt_rev_pmf, real abs_tol)
Definition rt.stan:128