Wave Detector#

Wave detection#

WaveDetector finds waves (a negative half-wave followed by a positive half-wave) inside a chosen frequency band and reports morphological features of those waves – amplitude, peak-to-peak, duration and slope.

It is a general half-wave detector: with fband=(0.5, 4) it detects delta waves, with (0.5, 0.9) slow oscillations, and any other band works too. The interface mirrors brainmaze_eeg.features.feature_extraction.SleepSpectralFeatureExtractor and brainmaze_eeg.features.time_domain_features.TimeDomainFeatureExtractor: calling the detector returns (values, names) so wave features can be concatenated with spectral / time-domain features for the same epochs.

Two ways to use it#

Windowed feature extraction (__call__):

from brainmaze_eeg.features.wave_detector import WaveDetector

det = WaveDetector(fs=200, fband=(0.5, 4.0), segm_size=30)
values, names = det(x)                 # x: 1-D or (n_signals, n_samples)

Raw detections, for plotting or custom analysis (detect):

det = WaveDetector(fs=200, fband=(0.5, 4.0))
waves = det.detect(x)                  # dict (1-D) or list of dicts (2-D)
plt.plot(x)
plt.plot(waves['min_pos'], waves['min_val'], 'v')
plt.plot(waves['max_pos'], waves['max_val'], '^')

Slope conventions#

slope='upslope'

Trough -> peak rate, (max_val - min_val) / (t_peak - t_trough). This is the historical behaviour of this class.

slope='downslope'

Zero-crossing -> negative-trough rate, |min_val| / (t_trough - t_zero_cross). This is the slow-wave downslope used by Carvalho et al. 2024, who measure it on a broadband trace (pass that trace via measure_on=) after detecting on the narrow band, and apply an amplitude threshold on the negative peak (amplitude_threshold).

References

Carvalho D.Z. et al. (2024), Non-rapid eye movement sleep slow-wave activity features are associated with amyloid accumulation in older adults with obstructive sleep apnoea, Brain Communications 6(5): fcae354. https://doi.org/10.1093/braincomms/fcae354

Lineage: this detector is the successor of the SlowWaveDetect routine used in the study above, generalised to an arbitrary band; the slope='downslope' + amplitude_threshold + measure_on options reproduce that original feature.

class brainmaze_eeg.features.wave_detector.WaveDetector(fs, fband=(0.5, 4.0), segm_size=None, overlap=0.0, slope='downslope', amplitude_threshold=None, datarate=False, n_processes=1, cutoff_low=None, cutoff_high=None)#

Band-limited wave detector and windowed feature extractor.

Parameters:
  • fs (float) – Sampling frequency (Hz).

  • fband ((float, float)) – Single (low, high) band in Hz. One detector detects in one band; run several detectors for several bands. Default (0.5, 4.0) (delta).

  • segm_size (float, optional) – Feature window length in seconds. None (default) treats the whole signal as one window.

  • overlap (float) – Feature window overlap in seconds. Default 0.0.

  • slope ({'downslope', 'upslope'}) – Which slope WAVE_SLOPE_MEAN reports (see module docstring). Default 'downslope'.

  • amplitude_threshold (float, optional) – Keep only waves whose negative trough is at least this deep (-min_val >= amplitude_threshold), measured on the amplitude signal. None (default) keeps all waves. Carvalho et al. use 5 (µV).

  • datarate (bool) – If True, prepend a DATA_RATE feature (fraction of non-NaN samples per window).

  • n_processes (int) – Parallelise detection across signals for 2-D / list input. Default 1.

property cutoff_high#
property cutoff_low#
detect(x, measure_on=None)#

Raw per-signal detections.

Parameters:
  • x (np.ndarray or list) – 1-D (n_samples,), 2-D (n_signals, n_samples), or list of 1-D arrays.

  • measure_on (np.ndarray or list, optional) – Amplitude signal(s), same shape as x.

Returns:

A single detection dict for 1-D input, otherwise one dict per signal. Signals are detected independently – positions index into that signal.

Return type:

dict or list of dict

brainmaze_eeg.features.wave_detector.detect_waves(x, fs, fband=(0.5, 4.0), measure_on=None)#

Detect waves in a single 1-D signal and return their positions and morphology.

Parameters:
  • x (np.ndarray) – 1-D signal.

  • fs (float) – Sampling frequency (Hz).

  • fband ((float, float)) – (low, high) band in Hz that defines the waves to detect.

  • measure_on (np.ndarray, optional) – Signal the amplitudes/slopes are read from (same length as x). Detection always runs on x; when measure_on is given, morphology is measured on it (e.g. detect on a narrow band, measure on a 0.5-35 Hz broadband trace). Defaults to the drift-removed x.

Returns:

Keys: min_pos, min_val, max_pos, max_val, zero_pos (arrays over waves) and the derived per-wave arrays pk2pk, delta_t, upslope, down_dur, downslope.

Return type:

dict