Class RespiratoryRateEstimationActor
Actor for estimating respiratory rate (RR) from a continuous EtCO₂ waveform using a robust slope‑based breath detection algorithm. This component consumes streaming etCO2 waveform samples and publishes a continuously updated respiratory rate (in breaths/min) to a designated output channel.
Triggering
This actor is invoked for every new value on the configured ETCO2_WAVE input channel. Messages are handled in a non‑consuming manner, i.e., other actors may also subscribe to the same input.
Input
- ETCO2_WAVE — A numeric CO₂ concentration sample
(mmHg or %) associated with a timestamp. The snapshot should contain:
{ "value": <double>, "timestamp": "<ISO‑8601 string>" }The timestamp is read from<channel>-timestampif attached by the event bus; otherwiseInstant.now()is used.
Output
- Publishes RR (breaths/min) as a JSON object to the configured
rrOutChannel. A typical message is:
{ "rr": <double breaths/min>, "timestamp": "<ISO‑8601>" }
Algorithm Overview
The algorithm detects breaths by analyzing the time derivative (slope) of the EtCO₂ signal via linear regression over a sliding window. Each breath is detected when:
- The slope exceeds a positive threshold (arming phase, rising limb).
- The slope subsequently crosses below a negative threshold (falling limb), at which point an end‑tidal peak is estimated and recorded.
To improve robustness, the implementation supports:
- Exponential Moving Average (EMA) smoothing.
- Hampel filtering for outlier suppression.
- Sliding‑window least squares slope estimation.
- Hysteresis for reliable peak detection.
- Refractory interval enforcement to reject physiologically impossible breath intervals.
- Median inter‑breath interval over a history window for stable RR estimation.
Respiratory Rate Computation
Registered peak timestamps are maintained in a bounded history. Intervals between consecutive peaks (in milliseconds) are computed and the median value is used to derive the respiratory rate:
RR = 60000 / median(inter_breath_interval_ms)
Configuration Parameters
The constructor exposes all tunable parameters:
windowSize: Number of samples used for slope regression.riseSlopeMin: Slope threshold (mmHg/s) to arm breath detection.fallSlopeMin: Negative slope threshold to confirm peak detection.minBreathIntervalSec: Minimum physiologic allowable interval between breaths.historySeconds: Duration of stored peak timestamps used for median RR calculation.useEMA,emaAlpha: Optional exponential smoothing.useHampel,hampelWindow,hampelK: Optional Hampel outlier suppression.
Thread Safety
This actor is designed to run within the actor framework's single‑threaded dispatch model. Internal data structures (sliding windows, peak buffers) are not thread‑safe for concurrent external access.
Intended Use
Suitable for real‑time respiratory monitoring in decision-support systems where robustness against noise, CO₂ baseline drift, and cardiogenic oscillations is required.
See Also
- Slope‑based breath detection literature
- Hampel filter for robust outlier detection
- Actor/event‑driven CDSS architecture
-
Field Summary
Fields inherited from class com.framed.cdss.Actor
id, inputChannels, outputChannels -
Constructor Summary
ConstructorsConstructorDescriptionRespiratoryRateEstimationActor(EventBus eventBus, String id, String etco2Channel, org.json.JSONArray outputChannels, int windowSize, double riseSlopeMin, double fallSlopeMin, double minBreathIntervalSec, int historySeconds, boolean useEMA, double emaAlpha, boolean useHampel, int hampelWindow, double hampelK) Creates a respiratory rate estimator actor that detects breaths from an EtCO₂ waveform using a robust slope-based algorithm with optional smoothing and outlier suppression. -
Method Summary
Modifier and TypeMethodDescriptionvoidfireFunction(Map<String, Object> snapshot) Processes a single incoming ETCO2_WAVE sample, updates the smoothing/filters, maintains the sliding window, estimates the local slope (mmHg/s), and drives the hysteresis-based breath detection state machine.Methods inherited from class com.framed.cdss.Actor
getInputChannels, getOutputChannels, valueMatchesExpected
-
Constructor Details
-
RespiratoryRateEstimationActor
public RespiratoryRateEstimationActor(EventBus eventBus, String id, String etco2Channel, org.json.JSONArray outputChannels, int windowSize, double riseSlopeMin, double fallSlopeMin, double minBreathIntervalSec, int historySeconds, boolean useEMA, double emaAlpha, boolean useHampel, int hampelWindow, double hampelK) Creates a respiratory rate estimator actor that detects breaths from an EtCO₂ waveform using a robust slope-based algorithm with optional smoothing and outlier suppression.- Parameters:
eventBus- Event bus for subscribing and publishing messages.id- Unique actor identifier.etco2Channel- Input channel name carrying ETCO2_WAVE samples.outputChannels- List of channels this actor is permitted to publish to.windowSize- Sliding window size (in samples) for slope regression; must be>= 3.riseSlopeMin- Positive slope threshold (mmHg/s) to "arm" detection on the expiratory upstroke.fallSlopeMin- Magnitude of negative slope threshold (mmHg/s) required to confirm a breath (falling limb).minBreathIntervalSec- Minimum allowed inter-breath interval (seconds) used as a refractory period.historySeconds- Duration (seconds) to retain detected peak timestamps for RR calculation.useEMA- Whether to apply exponential moving average smoothing to the incoming signal.emaAlpha- EMA smoothing factor(0 < alpha <= 1); higher values weight recent samples more.useHampel- Whether to apply a Hampel filter for outlier suppression.hampelWindow- Window size (in samples) for the Hampel filter; odd value preferred.hampelK- Outlier threshold in MAD multiples (e.g., 3.0) for the Hampel filter.- Throws:
IllegalArgumentException- ifwindowSize < 3.
-
-
Method Details
-
fireFunction
Processes a single incoming ETCO2_WAVE sample, updates the smoothing/filters, maintains the sliding window, estimates the local slope (mmHg/s), and drives the hysteresis-based breath detection state machine. When a breath is confirmed, registers its timestamp and, if enough history is present, computes and publishes RR.Expected input: The snapshot should contain the ETCO2 value under
etco2Channel(Number or String convertible to double). A timestamp is read from<channel>-timestampif available; otherwiseInstant.now()is used as a fallback.Side effects: Updates internal buffers (EMA value, Hampel buffer, sliding window, peak history), and may publish RR to
outputChannels.- Specified by:
fireFunctionin classActor- Parameters:
snapshot- A map-like payload representing the latest event bus snapshot for the input channel. Must contain a numeric ETCO2 value at keyetco2Channel. Timestamp is optional.
-