mne_rt.tools.RiemannianPotatoDetector#

class mne_rt.tools.RiemannianPotatoDetector(threshold: float = 3.0, estimator: str = 'oas', metric: str = 'riemann', verbose: bool | str | None = None)[source]#

Bases: object

Online EEG/MEG artifact detector based on the Riemannian Potato.

The Riemannian Potato detects artifactual epochs by measuring how far each incoming covariance matrix is from the geometric mean of a clean calibration set — distance is computed in the Riemannian metric on the manifold of symmetric positive-definite (SPD) matrices. A window is declared artifactual when this distance (expressed as a z-score) exceeds threshold.

Unlike threshold-based or ICA-based methods, this approach requires no reference channel and is robust to gradual amplitude drift (because the geometric mean adapts to the signal statistics during calibration rather than using a fixed absolute threshold).

Parameters:
thresholdfloat, default 3.0

Z-score cutoff (Riemannian distance units). Windows with a distance z-score above this value are flagged as artifacts. Typical range: 2.5–4.0. Lower = more aggressive rejection.

estimatorstr, default “oas”

Covariance estimator passed to pyriemann.estimation.Covariances. "oas" (Oracle Approximating Shrinkage) is robust at low sample-to-channel ratios; "scm" gives the raw sample covariance.

metricstr, default “riemann”

Riemannian metric used for the potato. "riemann" (affine-invariant) is the canonical choice; "logeuclid" is faster but less robust.

verbosebool | str | None, default None

Verbosity level. See set_log_level().

Attributes:
is_fitted_bool

True after fit() has been called successfully.

n_channels_int

Number of channels seen during fit().

n_calibration_windows_int

Number of clean windows used to fit the potato.

Raises:
ImportError

If pyriemann is not installed.

RuntimeError

If detect() is called before fit().

Examples

Calibrate on 60 s of clean data, then detect online:

detector = RiemannianPotatoDetector(threshold=3.0)
detector.fit(clean_windows)            # shape (n_windows, n_ch, n_samples)

while streaming:
    window = stream.get_data(1.0)      # shape (n_ch, n_samples)
    is_clean, z_score = detector.detect(window)
    if is_clean:
        process_for_nf(window)

Added in version 1.0.0.

__init__(threshold: float = 3.0, estimator: str = 'oas', metric: str = 'riemann', verbose: bool | str | None = None) None[source]#

Methods

__init__([threshold, estimator, metric, verbose])

detect(window)

Test a single window for artifacts.

fit(windows)

Calibrate the potato on clean data windows.

fit(windows: ndarray) RiemannianPotatoDetector[source]#

Calibrate the potato on clean data windows.

Computes covariance matrices for each window and fits the geometric mean and variance used as the potato centre and spread.

Parameters:
windowsndarray, shape (n_windows, n_channels, n_samples)

Calibration data. Should contain clean (artifact-free) segments. At least 10 windows are recommended; 30–60 is typical for a 1-second window length at standard EEG sampling rates.

Returns:
selfRiemannianPotatoDetector
Raises:
ValueError

If windows.ndim != 3 or fewer than 2 windows are provided.

detect(window: ndarray) tuple[bool, float][source]#

Test a single window for artifacts.

Parameters:
windowndarray, shape (n_channels, n_samples)

One data window to evaluate.

Returns:
is_cleanbool

True when the window is inside the potato (clean); False when it is outside (potential artifact).

z_scorefloat

Riemannian distance z-score. Higher = more anomalous.

Raises:
RuntimeError

If called before fit().

ValueError

If the channel count does not match the calibration set.