epinowcast
Loading...
Searching...
No Matches
primarycensored_pmf.stan
Go to the documentation of this file.
1
33int enw_to_pcens_dist_id(int dist) {
34 if (dist == 1) return 2; // exponential -> primarycensored gamma (shape 1)
35 if (dist == 2) return 1; // lognormal -> primarycensored lognormal
36 if (dist == 3) return 2; // gamma -> primarycensored gamma
37 reject(
38 "The primarycensored discretisation does not support distribution id ",
39 dist, ". Supported distributions are exponential, lognormal and gamma."
40 );
41}
42
60array[] real enw_to_pcens_params(real mu, real sigma, int dist) {
61 array[2] real params;
62 if (dist == 1) {
63 // Exponential: epinowcast uses exp(-mu) as the rate. Routed through the
64 // gamma path as Gamma(shape = 1, rate = exp(-mu)), which is identical to
65 // Exponential(rate = exp(-mu)) but hits the analytical gamma-uniform
66 // solution.
67 params[1] = 1;
68 params[2] = exp(-mu);
69 } else if (dist == 2) {
70 // Lognormal: shared (meanlog, sdlog) parameterisation.
71 params[1] = mu;
72 params[2] = sigma;
73 } else if (dist == 3) {
74 // Gamma: epinowcast uses exp(mu) as the shape with sigma as the rate;
75 // primarycensored gamma takes (shape, rate).
76 params[1] = exp(mu);
77 params[2] = sigma;
78 } else {
79 reject("Unsupported distribution id for primarycensored params: ", dist);
80 }
81 return params;
82}
83
97vector log_hazard_to_logit_hazard(vector lhaz) {
98 int n = num_elements(lhaz);
99 // Logit transform all but last, then append Inf (last hazard h[n] = 1)
100 return append_row(
101 lhaz[1:(n-1)] - log1m_exp(lhaz[1:(n-1)]),
102 positive_infinity()
103 );
104}
105
124vector lprob_to_log_hazard(vector lprob, int u) {
125 vector[u] lhaz;
126 // h_0 = p_0 (survival before delay 0 is 1).
127 lhaz[1] = lprob[1];
128 // Running log survival: log S_d = log(1 - sum_{i <= d} p_i).
129 real log_surv = log1m_exp(lprob[1]);
130 for (d in 2:u) {
131 // h_{d-1} = p_{d-1} / S_{d-2}; here lprob[d] is p_{d-1} and log_surv is
132 // log S_{d-2} (survival up to but excluding the current delay).
133 lhaz[d] = lprob[d] - log_surv;
134 // Update survival to exclude the current delay before the next iteration.
135 if (d < u) {
136 log_surv = log_diff_exp(log_surv, lprob[d]);
137 }
138 }
139 // Pin the terminal hazard to exactly 1 (log(1) = 0) so that
140 // log_hazard_to_logit_hazard() yields +inf and all remaining mass is
141 // reported at the maximum delay, rather than relying on floating-point
142 // cancellation in the final iteration above.
143 lhaz[u] = 0;
144 return log_hazard_to_logit_hazard(lhaz);
145}
146
178vector discretised_pcens_logit_hazard(real mu, real sigma, int dmax, int dist,
179 int ref_as_p) {
180 int pcens_dist = enw_to_pcens_dist_id(dist);
181 // All supported distributions (exponential routed via gamma, lognormal,
182 // gamma) take two parameters under the primarycensored convention.
183 array[2] real params = enw_to_pcens_params(mu, sigma, dist);
184 array[0] real primary_params;
185 vector[dmax] lprob = primarycensored_sone_lpmf_vectorized(
186 dmax - 1, 0.0, dmax * 1.0, pcens_dist, params, 1.0, 1, primary_params
187 );
188 if (ref_as_p == 1) {
189 return lprob;
190 }
191 return lprob_to_log_hazard(lprob, dmax);
192}
vector primarycensored_sone_lpmf_vectorized(data int max_delay, data real L, data real D, data int dist_id, array[] real params, data real pwindow, data int primary_id, array[] real primary_params)
vector discretised_pcens_logit_hazard(real mu, real sigma, int dmax, int dist, int ref_as_p)
int enw_to_pcens_dist_id(int dist)
vector lprob_to_log_hazard(vector lprob, int u)
vector log_hazard_to_logit_hazard(vector lhaz)
array[] real enw_to_pcens_params(real mu, real sigma, int dist)