Skip to content

Commit 7607388

Browse files
[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
1 parent 6871400 commit 7607388

8 files changed

Lines changed: 37 additions & 48 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ From this, it infers $\mathcal{R}(t)$, the time-varying reproduction number, whi
88
The core renewal equation is:
99

1010
$$
11-
I(t) = \mathcal{R}(t) \sum_{s} I(t-s) \, w(s)
11+
I(t) = \mathcal{R}(t) \sum_{s} I(t - s) \, w(s)
1212
$$
1313

1414
where $w(s)$ is the generation interval distribution: the probability that $s$ time units separate infection in an index case and a secondary case.
@@ -17,7 +17,7 @@ However inference is complicated by the fact that observational data require the
1717
The observation equation links infections to expected observations:
1818

1919
$$
20-
\mu(t) = \alpha \sum_{s} I(t-s) \, \pi(s)
20+
\mu(t) = \alpha \sum_{s} I(t - s) \, \pi(s)
2121
$$
2222

2323
where $\alpha$ is the ascertainment rate and $\pi(s)$ is the delay distribution from infection to observation.

docs/tutorials/ascertainment.qmd

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ For emergency department visits, it can be called the infection-to-ED-visit rate
4141
For a count observation process, the ascertainment rate scales delayed latent infections to obtain the expected number of observed events:
4242

4343
$$
44-
\mu_s(t)
45-
=
46-
\alpha_s \sum_{d=0}^{D_s} I(t-d)\,\pi_{s,d},
44+
\mu_s(t) = \alpha_s \sum_{d=0}^{D_s} I(t - d)\,\pi_{s,d},
4745
$$
4846

4947
where $s$ identifies the signal, $\alpha_s$ is its ascertainment rate, and $\pi_{s,d}$ is its delay distribution.
@@ -132,14 +130,8 @@ Use `RatioLinkedAscertainment` when the relative quantity, such as IHR / IEDR, i
132130

133131
$$
134132
\boldsymbol{\eta}
135-
\sim
136-
\operatorname{MultivariateNormal}
137-
\left(
138-
\operatorname{logit}(\boldsymbol{\alpha}_0),
139-
\boldsymbol{\Sigma}
140-
\right),
141-
\qquad
142-
\boldsymbol{\alpha} = \operatorname{logit}^{-1}(\boldsymbol{\eta}).
133+
\sim \operatorname{MultivariateNormal} \left( \operatorname{logit}(\boldsymbol{\alpha}_0), \boldsymbol{\Sigma} \right), \qquad \boldsymbol{\alpha}
134+
= \operatorname{logit}^{-1}(\boldsymbol{\eta}).
143135
$$
144136

145137
The baseline rates $\boldsymbol{\alpha}_0$ set the prior location.
@@ -170,13 +162,8 @@ During model execution, this component creates one vector sample site, `he_ascer
170162
`RatioLinkedAscertainment` samples a base rate and a ratio of the linked rate to the base rate:
171163

172164
$$
173-
\alpha_{\mathrm{linked}}
174-
=
175-
\alpha_{\mathrm{base}}\rho,
176-
\qquad
177-
\rho
178-
=
179-
\frac{\alpha_{\mathrm{linked}}}{\alpha_{\mathrm{base}}}.
165+
\alpha_{\mathrm{linked}} = \alpha_{\mathrm{base}}\rho, \qquad \rho
166+
= \frac{\alpha_{\mathrm{linked}}}{\alpha_{\mathrm{base}}}.
180167
$$
181168

182169
For a hospital and ED model, the IEDR can be the base rate and the ratio can represent IHR / IEDR.
@@ -203,7 +190,7 @@ The priors are assigned to the base rate and the ratio, and together they induce
203190

204191
The ratio may be any positive value.
205192
Unlike `JointAscertainment`, this component does not automatically constrain the derived linked rate to the unit interval.
206-
If both rates should be $<1$ (for instance because both are probabilities), make sure to choose priors that make $\alpha_{\mathrm{base}}\rho > 1$ negligibly likely.
193+
If both rates should be $< 1$ (for instance because both are probabilities), make sure to choose priors that make $\alpha_{\mathrm{base}}\rho > 1$ negligibly likely.
207194
The component does not clip an invalid linked rate, because clipping would change the specified statistical model.
208195

209196
## Building a model an ascertainment component

docs/tutorials/day_of_week_effects.qmd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Ignoring this weekly periodicity forces the noise model to absorb systematic var
5050
PyRenew models day-of-week effects as a **multiplicative adjustment** applied to predicted counts after the delay convolution and ascertainment scaling:
5151

5252
$$
53-
\lambda(t) = d_{w(t)} \cdot \alpha \sum_{s} I(t-s)\,\pi(s)
53+
\lambda(t) = d_{w(t)} \cdot \alpha \sum_{s} I(t - s)\,\pi(s)
5454
$$
5555

5656
where $d_{w(t)}$ is the day-of-week multiplier for the weekday of timepoint $t$, $\alpha$ is the ascertainment rate, and $\pi(s)$ is the delay PMF.
@@ -335,7 +335,7 @@ Day-of-week effects and right-truncation are independent adjustments that compos
335335
Day-of-week is applied first (adjusting the expected counts for reporting patterns), then right-truncation scales down recent counts for incomplete reporting:
336336

337337
$$
338-
\lambda(t) = F(k_t) \cdot d_{w(t)} \cdot \alpha \sum_s I(t-s)\,\pi(s)
338+
\lambda(t) = F(k_t) \cdot d_{w(t)} \cdot \alpha \sum_s I(t - s)\,\pi(s)
339339
$$
340340

341341
```{python}

docs/tutorials/latent_infections.qmd

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,17 @@ Let $\tau = 0, 1, \ldots, n_{\text{init}} - 1$ index positions in the initializa
156156
Then:
157157

158158
$$
159-
I_{\text{init}}(\tau) = I_0 \cdot e^{r \cdot \tau}, \quad \tau = 0, 1,
160-
\ldots, n_{\text{init}} - 1
159+
I_{\text{init}}(\tau) = I_0 \cdot e^{r \cdot \tau}, \quad \tau
160+
= 0, 1, \ldots, n_{\text{init}} - 1
161161
$$
162162

163-
where $r$ is the asymptotic growth rate implied by the reproduction number at the start of the observation period, $\mathcal{R}(t=0) = e^{\text{log\_rt\_time\_0}}$, and the generation interval.
164-
The function `r_approx_from_R` converts $\mathcal{R}(t=0)$ and the generation interval into $r$ using Newton's method.
163+
where $r$ is the asymptotic growth rate implied by the reproduction number at the start of the observation period, $\mathcal{R}(t = 0) = e^{\text{log\_rt\_time\_0}}$, and the generation interval.
164+
The function `r_approx_from_R` converts $\mathcal{R}(t = 0)$ and the generation interval into $r$ using Newton's method.
165165

166166
- **The level is set by `I0`**.</br> `I0` is the infection prevalence at the earliest point in the initialization period, $n_{\text{init}} - 1$ time points before $t = 0$.
167167
It sets the scale of the entire initialization vector: $I_{\text{init}}(0) = I_0$, with subsequent entries growing or declining exponentially toward $t = 0$.
168168

169-
- **The shape is set by `log_rt_time_0`**.<br> `log_rt_time_0` enters the model in two places: it is the starting point of the $\mathcal{R}(t)$ trajectory ($\mathcal{R}(t=0) = e^{\text{log\_rt\_time\_0}}$), and it determines the exponential growth rate $r$ used to construct the initialization vector.
169+
- **The shape is set by `log_rt_time_0`**.<br> `log_rt_time_0` enters the model in two places: it is the starting point of the $\mathcal{R}(t)$ trajectory ($\mathcal{R}(t = 0) = e^{\text{log\_rt\_time\_0}}$), and it determines the exponential growth rate $r$ used to construct the initialization vector.
170170
When `log_rt_time_0 = 0`, $r = 0$ and the initialization vector is flat at level `I0`.
171171
When `log_rt_time_0 > 0`, infections are growing exponentially at $t = 0$; when `log_rt_time_0 < 0`, they are declining.
172172

@@ -232,7 +232,7 @@ init_df = pd.DataFrame(init_data)
232232
)
233233
```
234234

235-
The initialization vector matters because the renewal equation is a convolution: infections on day 0 depend on infections from days $-1$ through $-(K-1)$, weighted by the generation interval.
235+
The initialization vector matters because the renewal equation is a convolution: infections on day 0 depend on infections from days $-1$ through $-(K - 1)$, weighted by the generation interval.
236236
A flat initialization (stable) means the renewal equation starts with uniform recent history.
237237
A growing initialization means the most recent days have disproportionately more infections, which amplifies the effect of the generation interval's short-lag weights.
238238

@@ -362,7 +362,7 @@ The variance of $x_t$ grows linearly with time: $\text{Var}(x_t) = \sigma^2 t$.
362362
The further into the future, the less constrained the process is.
363363

364364
**Hyperparameter:** `innovation_sd` ($\sigma$) is the standard deviation of each daily step on the log scale.
365-
With `innovation_sd = 0.05`, each day's $\log \mathcal{R}$ changes by roughly $\pm 0.05$, which corresponds to roughly $\pm 5\%$ multiplicative change in $\mathcal{R}$.
365+
With `innovation_sd = 0.05`, each day's $\log \mathcal{R}$ changes by roughly $\pm0.05$, which corresponds to roughly $\pm5\%$ multiplicative change in $\mathcal{R}$.
366366

367367
```{python}
368368
#| label: rw-sample
@@ -408,7 +408,7 @@ If $\mathcal{R}(t)$ drifts above 1, the $\phi$ coefficient pulls it back; if it
408408
- `innovation_sd` ($\sigma$): standard deviation of daily noise.
409409

410410
The two hyperparameters jointly determine the **stationary standard deviation** $\sigma_{\text{stat}} = \sigma / \sqrt{1 - \phi^2}$, which is the long-run spread of $\log \mathcal{R}(t)$.
411-
For example, `autoreg = 0.9` and `innovation_sd = 0.05` give $\sigma_{\text{stat}} \approx 0.115$, meaning 95% of long-run $\log \mathcal{R}$ values fall within $\pm 0.23$ of zero, or equivalently $\mathcal{R} \in [0.79, 1.26]$.
411+
For example, `autoreg = 0.9` and `innovation_sd = 0.05` give $\sigma_{\text{stat}} \approx 0.115$, meaning 95% of long-run $\log \mathcal{R}$ values fall within $\pm0.23$ of zero, or equivalently $\mathcal{R} \in [0.79, 1.26]$.
412412

413413
```{python}
414414
#| label: ar1-sample
@@ -441,7 +441,8 @@ DifferencedAR1 models *changes* in $\mathcal{R}(t)$ as an autoregressive process
441441
In terms of increments,
442442

443443
$$
444-
\Delta x_t = \texttt{autoreg} \cdot \Delta x_{t-1} + \varepsilon_t, \quad x_t = x_{t-1} + \Delta x_t,
444+
\Delta x_t = \texttt{autoreg} \cdot \Delta x_{t-1} + \varepsilon_t, \quad x_t
445+
= x_{t-1} + \Delta x_t,
445446
$$
446447

447448
so the autoregressive structure applies to the *rate of change* rather than the level.

docs/tutorials/latent_subpopulation_infections.qmd

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,9 @@ Two temporal processes define the evolution of $\log \mathcal{R}_k(t)$:
146146
Together, these define the full set of reproduction numbers:
147147

148148
$$
149-
\log \mathcal{R}_k(t)
150-
= \log \mathcal{R}_{\text{baseline}}(t) + \delta_k(t),
151-
\qquad
152-
\mathcal{R}_k(t) = \exp\big(\log \mathcal{R}_k(t)\big).
149+
\log \mathcal{R}_k(t) = \log \mathcal{R}_{\text{baseline}}(t)
150+
+ \delta_k(t), \qquad \mathcal{R}_k(t)
151+
= \exp\big(\log \mathcal{R}_k(t)\big).
153152
$$
154153

155154
### Population structure

docs/tutorials/observation_processes_counts.qmd

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ Observed data can be aggregated or available as subpopulation-level counts, whic
5959
The deterministic transformation is given by the observation equation:
6060

6161
$$
62-
\mu(t) = \alpha \sum_{d=0}^{D} I(t-d)\, \pi_d
62+
\mu(t) = \alpha \sum_{d=0}^{D} I(t - d)\, \pi_d
6363
$$
6464

6565
where:
6666

67-
- $I(t-d)$ is the number of incident (new) infections on day $t-d$
67+
- $I(t - d)$ is the number of incident (new) infections on day $t - d$
6868
- $\alpha$ is the **ascertainment rate**, the probability that an infection results in an observed event (e.g., hospitalization)
6969
- $\pi_d$ is the delay distribution from infection to observation, conditional on an infection leading to an observed event
7070

@@ -103,7 +103,7 @@ In this tutorial, we simulate the observation process by specifying infections d
103103

104104
For hospital admissions data, we construct a `PopulationCounts` observation process.
105105

106-
The delay is the key mechanism: infections from $d$ days ago ($I(t-d)$) contribute to today's predicted hospital admissions ($\mu(t)$), weighted by the probability $\pi_d$ that an infection leads to hospitalization after exactly $d$ days.
106+
The delay is the key mechanism: infections from $d$ days ago ($I(t - d)$) contribute to today's predicted hospital admissions ($\mu(t)$), weighted by the probability $\pi_d$ that an infection leads to hospitalization after exactly $d$ days.
107107
The convolution sums these contributions across all past days.
108108

109109
Observed hospital admissions are then generated by sampling from a negative binomial distribution:
@@ -223,8 +223,8 @@ hosp_process = PopulationCounts(
223223
The observation process convolves infections with a delay distribution, maintaining alignment between input and output: day $t$ in the output corresponds to day $t$ in the input.
224224

225225
Hospital admissions depend on infections from prior days.
226-
A delay PMF of length $L$ covers delays 0 to $L-1$, requiring $L-1$ days of prior infection history.
227-
The method `lookback_days()` returns $L-1$; the first valid observation day is at index `lookback_days()`.
226+
A delay PMF of length $L$ covers delays 0 to $L - 1$, requiring $L - 1$ days of prior infection history.
227+
The method `lookback_days()` returns $L - 1$; the first valid observation day is at index `lookback_days()`.
228228
Earlier days are marked invalid.
229229

230230
```{python}

docs/tutorials/observation_processes_measurements.qmd

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,12 @@ The concentration is determined by:
198198
The predicted concentration at time $t$ is given by
199199

200200
$$
201-
\mu(t) = \frac{G}{V} \sum_{d=0}^{D} I(t-d)\, \pi_d,
201+
\mu(t) = \frac{G}{V} \sum_{d=0}^{D} I(t - d)\, \pi_d,
202202
$$
203203

204204
where:
205205

206-
- $I(t-d)$ is the number of infections on day $t-d$
206+
- $I(t - d)$ is the number of infections on day $t - d$
207207
- $\pi_d$ is the shedding kinetics PMF, giving the fraction of total shedding occurring $d$ days after infection, analogous to the delay distribution in count observation models
208208
- $G$ is the number of genome copies shed per infection
209209
- $V$ is the wastewater volume per person per day
@@ -213,7 +213,8 @@ This has the same convolution structure as the observation equation for count da
213213
We model the observed **log-concentration** as
214214

215215
$$
216-
Y(t) \sim \text{Normal}\big(\log(\mu(t)) + \text{sensor\_mode}, \ \text{sensor\_sd}\big),
216+
Y(t)
217+
\sim \text{Normal}\big(\log(\mu(t)) + \text{sensor\_mode}, \ \text{sensor\_sd}\big),
217218
$$
218219

219220
where:
@@ -437,8 +438,8 @@ print(f"Required lookback: {ww_process.lookback_days()} days")
437438
### Timeline alignment
438439

439440
The observation process maintains alignment: day $t$ in output corresponds to day $t$ in input.
440-
A temporal PMF of length $L$ covers lags 0 to $L-1$, requiring $L-1$ days of prior history.
441-
The method `lookback_days()` returns $L-1$; the first valid observation day is at index `lookback_days()`.
441+
A temporal PMF of length $L$ covers lags 0 to $L - 1$, requiring $L - 1$ days of prior history.
442+
The method `lookback_days()` returns $L - 1$; the first valid observation day is at index `lookback_days()`.
442443

443444
```{python}
444445
#| label: helper-function

docs/tutorials/right_truncation.qmd

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Ignoring this produces a spurious decline in recent counts.
4747
PyRenew's observation equation defines the expected observation count as:
4848

4949
$$
50-
\mu(t) = \alpha \sum_{s} I(t-s) \, \pi(s)
50+
\mu(t) = \alpha \sum_{s} I(t - s) \, \pi(s)
5151
$$
5252

5353
where $\alpha$ is the ascertainment rate and $\pi(s)$ is the infection-to-observation delay distribution.
@@ -65,7 +65,8 @@ Concretely, let $T$ denote the last observation day and let $\text{offset} = \te
6565
Then:
6666

6767
$$
68-
k_t = (T - t) + \text{offset} = (T - t) + (\text{data pull date} - T) = \text{data pull date} - t
68+
k_t = (T - t) + \text{offset} = (T - t) + (\text{data pull date} - T)
69+
= \text{data pull date} - t
6970
$$
7071

7172
Because $k_t$ depends only on the data pull date and the timepoint $t$, its behavior is straightforward: timepoints far in the past (small $t$) have large $k_t$, so $F(k_t) \approx 1$ and counts are fully reported.

0 commit comments

Comments
 (0)