Applies a sequential probability ratio test (SPRT) or CUSUM procedure to lineage frequency data, determining when accumulated evidence is sufficient to declare a variant "emerging" rather than sampling noise. Controls the false alarm rate while minimising detection delay.
Usage
alert_threshold(
data,
method = c("sprt", "cusum"),
alpha = 0.05,
beta = 0.1,
delta_0 = 0,
delta_1 = 0.03,
threshold = 5
)Arguments
- data
An
lfq_dataobject.- method
Detection method:
"sprt"(default) for the sequential probability ratio test, or"cusum"for the cumulative sum control chart.- alpha
False alarm probability. Default 0.05.
- beta
Missed detection probability. Default 0.10.
- delta_0
Null hypothesis growth rate (no emergence). Default 0 (frequency is stable).
- delta_1
Alternative hypothesis growth rate (emergence). Default 0.03 (3 percent per-week increase on logit scale).
- threshold
CUSUM decision threshold. Default 5.0. Only used when
method = "cusum".
Value
A tibble with columns lineage, date,
statistic (log-likelihood ratio or CUSUM value),
alert (logical), direction (emerging/declining/
stable), and confidence (1 - alpha).
Details
SPRT (Wald, 1945) computes the log-likelihood ratio between the alternative (lineage is growing at rate \(\delta_1\)) and the null (frequency is stable). The test stops when the cumulative log-ratio crosses the upper boundary \(B = \log((1-\beta)/\alpha)\) (declare emerging) or the lower boundary \(A = \log(\beta/(1-\alpha))\) (declare stable).
CUSUM accumulates deviations from expected frequency under the null: \(S_t = \max(0, S_{t-1} + (x_t - k))\) where \(x_t\) is the observed frequency change and \(k\) is the allowance (half the shift to detect). An alert is raised when \(S_t > h\).
References
Wald A (1945). Sequential tests of statistical hypotheses. Annals of Mathematical Statistics, 16(2), 117–186.
See also
summarize_emerging for non-sequential
trend tests, detection_horizon for prospective
power analysis.
Examples
# \donttest{
sim <- simulate_dynamics(n_lineages = 3,
advantages = c("A" = 1.5, "B" = 0.8),
n_timepoints = 15, seed = 1)
alerts <- alert_threshold(sim)
alerts
#> # A tibble: 3 × 6
#> lineage date statistic alert direction confidence
#> <chr> <date> <dbl> <lgl> <chr> <dbl>
#> 1 A 2026-07-20 0.222 FALSE inconclusive 0.95
#> 2 B 2026-07-20 -0.193 FALSE inconclusive 0.95
#> 3 ref 2026-07-20 -0.193 FALSE inconclusive 0.95
# }