Skip to main content

AnnotateArtifact

Namespace: RTPROCESSINGLIB  ·  Library: DSP Library

Module

This page documents a header-level module — a collection of free functions that share an algorithmic topic. There is no enclosing C++ class; the functions live directly in the library namespace.

Python equivalent

mne.preprocessing.annotate_muscle_zscore / annotate_amplitude in MNE-Python.

#include <dsp/annotate_artifact.h>

SPDX-License-Identifier: BSD-3-Clause Copyright (c) 2026 MNE-CPP Authors.

The detectors in this header scan continuous MEG / EEG data and emit FiffAnnotation intervals marking time segments that should be excluded from downstream averaging, ICA fitting or PSD estimation. annotateMusclZscore band-pass filters the signal in the 110–140 Hz range (typical EMG band), z-scores the Hilbert envelope of every channel, combines and smooths the scores and marks samples above a threshold as BAD_muscle. annotateAmplitude marks spans where consecutive samples jump by more than a "peak" threshold or change by less than a "flat" one, and returns channels for which that holds too often as bad.

Both routines reproduce their MNE-Python counterparts mne.preprocessing.annotate_muscle_zscore and mne.preprocessing.annotate_amplitude onset for onset.

src/examples/ex_dsp_artifacts/main.cpp
AnnotateAmplitudeParams amplitude;
amplitude.flat = 1e-12; // consecutive samples within 1 pV of each other
QStringList flatChannels;
const FiffAnnotations flatSpans = annotateAmplitude(loose, info, kSFreq, amplitude, &flatChannels);
src/examples/ex_dsp_artifacts/main.cpp
AnnotateMusclParams muscle; // mne defaults: z > 4 in the 110-140 Hz envelope, gaps < 0.1 s filled
const FiffAnnotations emgBad = annotateMusclZscore(emgData, info.pick_info(RowVectorXi::LinSpaced(kEeg, 0, kEeg - 1)), emgSFreq, muscle);

Functions​

annotateMusclZscore(data, info, sfreq, params, scores)​

[FiffAnnotations](/docs/api/fiff/fiff-annotations) annotateMusclZscore(const Eigen::MatrixXd & data, const [FiffInfo](/docs/api/fiff/fiff-info) & info, double sfreq, const [AnnotateMusclParams](/docs/api/dsp/annotate-muscl-params) & params, Eigen::RowVectorXd * scores);

Detect muscle artifacts via high-frequency z-score and annotate bad segments.

Algorithm of mne.preprocessing.annotate_muscle_zscore with ch_type None: Pick the magnetometers, else the gradiometers, else the EEG channels.

Band-pass them with mne's default FIR filter (FirFilter::filterData).

Take the Hilbert envelope (FFT length padded to the next 5-smooth size).

Z-score every channel over time, sum over channels and divide by sqrt(n_channels).

Low-pass the score at 4 Hz with the same FIR filter.

Mark samples above the threshold; good stretches shorter than dMinLengthGood become bad.

Parameters:

  • data : const Eigen::MatrixXd & Raw data matrix (n_channels × n_times).

  • info : const FiffInfo & Measurement info.

  • sfreq : double Sampling frequency in Hz.

  • params : const AnnotateMusclParams & Detection parameters.

  • scores : *Eigen::RowVectorXd ** If not null, receives the smoothed score per sample (mne's scores_muscle).

Returns:


annotateAmplitude(data, info, sfreq, params, bads)​

[FiffAnnotations](/docs/api/fiff/fiff-annotations) annotateAmplitude(const Eigen::MatrixXd & data, const [FiffInfo](/docs/api/fiff/fiff-info) & info, double sfreq, const [AnnotateAmplitudeParams](/docs/api/dsp/annotate-amplitude-params) & params, QStringList * bads);

Annotate spans where consecutive samples jump or stay flat, as mne.preprocessing.annotate_amplitude.

For every data channel that is not bad, the absolute differences between consecutive samples are compared with params.peak (at least) and params.flat (at most); runs shorter than params.dMinDuration are ignored. A channel whose runs cover at least params.dBadPercent of the recording is returned in bads; the runs of the other channels are merged into "BAD_flat" and "BAD_peak" annotations. Unlike mne, a channel that is bad for both reasons is listed once, and BAD_ACQ_SKIP spans are not skipped (the data matrix carries no annotations).

Parameters:

  • data : const Eigen::MatrixXd & Raw data matrix (n_channels × n_times).

  • info : const FiffInfo & Measurement info (channel types, names and bads).

  • sfreq : double Sampling frequency in Hz.

  • params : const AnnotateAmplitudeParams & Thresholds; at least one of peak and flat must be set.

  • bads : *QStringList ** If not null, receives the channels annotated for too long, in channel order.

Returns:


Example​

Authors of this file​