ImpulseClip#
Description#
ImpulseClip removes impulse spikes (glitches) from a signal that may be strongly
non-stationary. A spike is a large, isolated jump: hard to separate from the signal's
own swing in the raw level, but obvious in the sample-to-sample change. So detection
runs on the first difference, whose scale is trend-free:
where MAD(d) is the rolling median absolute deviation of the differences. A flagged
sample is replaced by the trailing median of the values.
It is strictly causal with zero latency.
Two consequences of detecting without looking ahead: an impulse is a +/- doublet in
the difference (a jump onto the spike and a jump back), so both the spike and its
return sample are flagged, replacing two consecutive samples (the second nudged to the
median); and a genuine level shift keeps its body, but its onset sample is clipped.
Preserving these would require a one-sample lookahead, which is deliberately not done.
For stationary data or multi-sample outliers, prefer Hampel.
Parameters:
window_size: (int) Trailing-window length. Must be positive.n_sigma: (float) Detection threshold in robust standard deviations of the differences. Larger values flag fewer samples. Typical value4.0.output: (optional, int) What to return:0(orNone): the cleaned signal, outliers replaced by the median.1: an outlier flag,1.0where a sample is flagged, else0.0.2: the input with flagged samples replaced byNaN.
start_policy: Warmup handling beforewindow_sizesamples are available ("strict","expanding", or"zero").
NaN handling#
Policy: ignore. A NaN in any input at index t causes the function to skip
that step: output at t is NaN and internal state is unchanged. Subsequent finite
samples are processed as if step t had not occurred.
Examples#
Usage example#
import numpy as np
from screamer import ImpulseClip
rng = np.random.default_rng(7)
t = np.linspace(0, 6 * np.pi, 400)
x = np.sin(t) + 0.3 * rng.standard_normal(t.size) # oscillating + noise
x[[80, 210, 330]] += 4.0 # spikes
cleaned = ImpulseClip(window_size=31, n_sigma=4.0)(x) # spikes removed
Implementation Details#
O(W) per step. Two trailing windows are maintained: one of the values (for the
replacement median) and one of the first differences (for the robust scale). Each step
takes the median of the differences' absolute deviations with std::nth_element to set
the threshold, tests the current jump, and on a flag replaces the sample with the value
median (written back into the window to keep it clean). Strictly causal, zero latency.