How VitalSignStore Uses Welford Running Statistics for Clinical Alerts in RuView
VitalSignStore maintains a ring buffer of raw vital-sign readings while VitalAnomalyDetector applies Welford's online algorithm to compute running mean and variance for real-time z-score-based clinical alerting in the RuView monitoring system.
The RuView project (ruvnet/RuView) implements contactless vital sign monitoring using WiFi CSI signals. At the core of its alerting pipeline, the system decouples data retention from statistical analysis: VitalSignStore handles raw history for visualization, while VitalAnomalyDetector leverages Welford running statistics to detect anomalies without retaining complete datasets.
Architecture of VitalSignStore and Clinical Alert Detection
VitalSignStore: The Raw Data Ring Buffer
Located in src/store.rs, VitalSignStore functions as a lightweight ring buffer that retains the most recent vital-sign readings (respiratory rate and heart rate). It provides simple aggregate functions—count, mean, min/max, and valid-fraction—but does not perform statistical smoothing or anomaly detection itself.
This design keeps the store agnostic to specific analytics methods, allowing it to serve UI visualization and retrospective analysis while remaining reusable for diverse downstream consumers.
VitalAnomalyDetector: Welford Statistics Engine
The VitalAnomalyDetector in src/anomaly.rs transforms the raw stream from VitalSignStore into clinical alerts. For each incoming VitalReading, the detector:
- Pushes the reading into
VitalSignStoreto maintain history for UI visualization - Updates two Welford running statistics accumulators—
rr_statsfor respiratory rate andhr_statsfor heart rate - Computes a z-score using the running mean and variance
- Triggers an
AnomalyAlertif the z-score exceeds configurable thresholds or if hard clinical bounds are crossed (e.g., respiratory rate < 4 BPM indicating apnea)
How Welford Running Statistics Work in RuView
The Welford algorithm provides numerically stable, low-memory statistics critical for continuous bedside monitoring. In src/anomaly.rs, the WelfordStats struct tracks three floating-point values per vital sign:
count: Number of observations processedmean: Running mean of valuesm2: Sum of squares of differences from the current mean (used to derive variance)
When a new reading arrives, the detector updates the statistics in O(1) time:
// Based on src/anomaly.rs WelfordStats implementation
impl WelfordStats {
pub fn update(&mut self, x: f64) {
self.count += 1;
let delta = x - self.mean;
self.mean += delta / self.count as f64;
let delta2 = x - self.mean;
self.m2 += delta * delta2;
}
pub fn variance(&self) -> f64 {
if self.count < 2 {
0.0
} else {
self.m2 / (self.count - 1) as f64
}
}
}
This approach avoids catastrophic cancellation errors that plague naive incremental averaging, particularly when processing thousands of samples at ~1 Hz sampling rates over long monitoring sessions.
Clinical Alert Detection Logic
The VitalAnomalyDetector combines Welford-derived statistics with clinical domain knowledge to generate actionable alerts. The detection pipeline evaluates two criteria:
Statistical Outliers: The system calculates z-scores using the running mean and standard deviation from the Welford accumulators. When |z-score| > threshold (typically 2.5), the detector flags the reading as statistically anomalous.
Hard Clinical Bounds: Regardless of variance, the system enforces absolute physiological limits. For example, respiratory rates below 4 BPM trigger immediate apnea alerts, while extreme bradycardia or tachycardia thresholds generate priority alerts.
When triggered, the detector emits AnomalyAlert structures containing the vital type, anomaly classification, severity clamped to [0, 1], and human-readable messages for clinician notification systems.
Implementation Example
The following example demonstrates integrating VitalSignStore with VitalAnomalyDetector using Welford running statistics:
use wifi_densepose_vitals::{
store::VitalSignStore,
anomaly::{VitalAnomalyDetector, AnomalyAlert},
types::{VitalReading, VitalEstimate, VitalStatus},
};
// Initialize 1-hour ring buffer (~3600 samples at 1 Hz)
let mut store = VitalSignStore::default_capacity();
// Detector with default Welford accumulators and z-score threshold of 2.5
let mut detector = VitalAnomalyDetector::default_config();
// Simulated CSI-derived vital sign reading
let reading = VitalReading {
respiratory_rate: VitalEstimate {
value_bpm: 12.0,
confidence: 0.9,
status: VitalStatus::Valid,
},
heart_rate: VitalEstimate {
value_bpm: 78.0,
confidence: 0.9,
status: VitalStatus::Valid,
},
subcarrier_count: 56,
signal_quality: 0.95,
timestamp_secs: 0.0,
};
// Store raw reading for UI visualization and retrospective analysis
store.push(reading.clone());
// Run anomaly detection using Welford statistics
let alerts: Vec<AnomalyAlert> = detector.check(&reading);
for alert in alerts {
println!(
"[ALERT] {} – {} (severity {:.2}) – {}",
alert.vital_type, alert.alert_type, alert.severity, alert.message
);
}
To reset the Welford accumulators after patient hand-offs or calibration changes:
detector.reset(); // Clears rr_stats and hr_stats Welford accumulators
store.clear(); // Optionally clear stored readings
Accessing the running means for custom downstream logic:
let current_rr_mean = detector.rr_mean(); // Welford-derived respiratory rate mean
let current_hr_mean = detector.hr_mean(); // Welford-derived heart rate mean
Summary
- VitalSignStore in
src/store.rsmaintains a ring buffer of raw vital-sign readings for visualization and retrospective analysis, but does not perform statistical processing. - VitalAnomalyDetector in
src/anomaly.rsimplements Welford running statistics viarr_statsandhr_statsaccumulators to compute online mean and variance in O(1) time per sample. - The Welford algorithm provides numerical stability and memory efficiency (three floats per vital sign), essential for continuous monitoring at ~1 Hz sampling rates.
- Clinical alerts trigger based on z-scores derived from Welford statistics and hard clinical bounds (e.g., apnea thresholds), producing
AnomalyAlertstructures for downstream notification systems.
Frequently Asked Questions
What is the difference between VitalSignStore and VitalAnomalyDetector in RuView?
VitalSignStore functions as a ring buffer that retains raw vital-sign readings for UI visualization and basic aggregation (count, min/max, valid-fraction). It operates independently of statistical methods. VitalAnomalyDetector consumes these readings to perform real-time statistical analysis using Welford running statistics, generating clinical alerts when anomalies are detected. This decoupling allows the store to support diverse analytics workflows while the detector focuses on memory-efficient statistical monitoring.
Why does RuView use Welford's algorithm instead of standard averaging?
Welford's online algorithm provides numerical stability that naive incremental averaging lacks, particularly when processing thousands of samples over long monitoring sessions. It avoids catastrophic cancellation errors by computing variance through differences from the running mean. Additionally, Welford requires only O(1) memory (three floats per vital sign: count, mean, and M2) and O(1) time per update, making it ideal for resource-constrained, high-frequency (~1 Hz) bedside monitoring in RuView.
How are clinical alert thresholds configured in the anomaly detector?
The VitalAnomalyDetector applies a two-tier threshold system. First, it calculates z-scores using the Welford-derived mean and standard deviation, comparing these against configurable statistical thresholds (e.g., z-score > 2.5). Second, it enforces hard clinical bounds independent of variance, such as triggering apnea alerts when respiratory rate falls below 4 BPM. Alerts carry severity scores clamped to [0, 1] and human-readable messages for clinician notification systems.
Can VitalSignStore retain data for retrospective analysis while the detector uses Welford statistics?
Yes, this is the intended architecture. VitalSignStore maintains a complete ring buffer of VitalReading structures for retrospective analysis, charting, and UI visualization. Simultaneously, VitalAnomalyDetector processes the same stream using Welford running statistics without storing the full history, enabling real-time alerting. The decoupled design allows the store to support diverse analytics workflows while the detector focuses on memory-efficient statistical monitoring.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →