bridge

Cross-paper bridge — analytic bounds between sample- and alarm-based metrics under a declared AlarmPolicy.

Useful when comparing a published paper that reported only sample-based AUC against a paper that reported only alarm-based sensitivity + FP/hr.

Symbols

  • \(s\) — per-window sample sensitivity, \(\Pr(\hat{y} = 1 \mid y = 1)\).

  • \(\alpha\) — per-window false-positive rate, \(1 - \text{specificity} = \Pr(\hat{y} = 1 \mid y = 0)\).

  • \(\pi\) — pre-ictal-window prevalence, \(\Pr(y = 1)\).

  • \(\Delta\)cadence_seconds (seconds between prediction windows).

  • \(\text{SOP}\) — Seizure Occurrence Period (seconds).

  • \(R\)refractory_seconds (minimum gap between alarms).

Windows per SOP (K)

The number of prediction windows inside one Seizure Occurrence Period — i.e. the number of independent chances to catch a given seizure, since a seizure is “caught” iff at least one of its SOP windows fires:

\[K = \left\lceil \frac{\text{SOP}}{\Delta} \right\rceil\]

By construction every seizure’s SOP contains exactly \(K\) windows, independent of the global prevalence \(\pi\). Prevalence governs how many windows are pre-ictal across the whole stream (and hence the FP/hr negative-window count), not how many windows sit inside a single SOP. We therefore use \(K_{\text{eff}} = K\) for the per-seizure detection bounds and do not shrink it by \(\pi\).

Alarm sensitivity (per-seizure detection probability)

Upper bound (independent errors — optimistic envelope):

\[\text{alarm\_sens}_{\text{upper}} = 1 - (1 - s)^{K}\]

Lower bound (fully-clustered errors — if the \(K\) windows inside one SOP are perfectly correlated, either all fire or none does, so the per-seizure detection probability collapses to the per-window sensitivity; pessimistic envelope):

\[\text{alarm\_sens}_{\text{lower}} = s\]

Because \(K = \lceil \text{SOP} / \Delta \rceil\), a longer SOP now correctly widens the detection band (more chances per seizure) — the earlier prevalence-adjustment made SOP = 15 s and SOP = 60 s degenerate at low \(\pi\), which was wrong.

FP/hr (alarms per hour)

Naive (no refractory, independent errors):

\[\text{FP/h}_{\text{naive}} = \alpha \cdot \frac{3600}{\Delta} \cdot (1 - \pi)\]

Refractory cap (no two alarms within \(R\) seconds, regardless of \(\alpha\)):

\[\text{FP/h}_{\text{cap}} = \frac{3600}{R}\]

Upper bound:

\[\text{FP/h}_{\text{upper}} = \min\!\big(\text{FP/h}_{\text{naive}},\ \text{FP/h}_{\text{cap}}\big)\]

Lower bound: 0.0 by convention. Under maximal positive correlation the alarm count collapses; a calibrated non-trivial lower bound requires an autocorrelation-proxy parameter that sample-only metrics do not identify.

References

  • Andrade et al. 2024 — sample- vs alarm-based perspectives.

  • Mormann et al. 2007 — definition of false-prediction rate.

  • docs/math/sample_to_alarm.md — paper-ready derivation including the inverse direction (alarm → sample) and a worked example.

class scitex_seizure_metrics.bridge.SampleToAlarmBounds(alarm_sensitivity_upper, alarm_sensitivity_lower, fp_per_hour_lower, fp_per_hour_upper, K_effective=1, notes=())[source]

Bases: object

Analytic bounds on alarm-based metrics derived from sample-based.

Attrs:

alarm_sensitivity_upper: 1 - (1 - s) ** K alarm_sensitivity_lower: s (worst-case clustering) fp_per_hour_lower: 0.0 by convention (correlation-dependent) fp_per_hour_upper: min(α * preds_per_hour * (1 - π), 3600 / R) K_effective: windows per SOP, K = ceil(SOP / cadence) — the

number of independent chances to detect each seizure

notes: free-form list of pertinent caveats

Parameters:
  • alarm_sensitivity_upper (float)

  • alarm_sensitivity_lower (float)

  • fp_per_hour_lower (float)

  • fp_per_hour_upper (float)

  • K_effective (int)

  • notes (tuple[str, ...])

K_effective: int = 1
alarm_sensitivity_lower: float
alarm_sensitivity_upper: float
fp_per_hour_lower: float
fp_per_hour_upper: float
notes: tuple[str, ...] = ()
scitex_seizure_metrics.bridge.alarm_to_sample(*, alarm_sensitivity, fp_per_hour, sop_seconds, cadence_seconds, refractory_seconds=0.0, prevalence=0.5)[source]

Reverse-bound: feasible sample-metric ranges from alarm metrics.

Returns dict with sample_sensitivity_lower / upper and sample_specificity_lower / upper.

Parameters:
Return type:

dict

scitex_seizure_metrics.bridge.sample_to_alarm(*, sample_sensitivity, sample_specificity, sop_seconds, cadence_seconds, refractory_seconds=0.0, prevalence=0.5)[source]

Bound alarm-based metrics from sample-based metrics + AlarmPolicy.

Parameters:
  • sample_sensitivity (float) – per-window sensitivity (true-positive rate).

  • sample_specificity (float) – per-window specificity (1 - FPR).

  • sop_seconds (float) – Seizure Occurrence Period.

  • cadence_seconds (float) – time step between predictions.

  • refractory_seconds (float) – minimum gap between alarms.

  • prevalence (float) – per-window prior probability of pre-ictal class. Affects ONLY FP/hr: the per-hour count of negative windows scales with 1-π. It does NOT shrink the per-seizure detection bounds — every seizure’s SOP holds K windows by construction, regardless of the global prevalence.

Returns:

SampleToAlarmBounds with four numbers and K_effective (= K).

Return type:

SampleToAlarmBounds