Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,20 @@ iCanClean
mne_denoise.icanclean.ICanClean
mne_denoise.icanclean.compute_icanclean

Multi-channel Wiener filter
---------------------------
.. autosummary::
:toctree: generated/
:nosignatures:

mne_denoise.mwf.MultichannelWienerFilter
mne_denoise.mwf.MWF
mne_denoise.mwf.compute_mwf
mne_denoise.mwf.hf_power_mask
mne_denoise.mwf.mwf_filter

``MWF`` is a short alias of ``MultichannelWienerFilter``.

Denoisers
---------
.. autosummary::
Expand Down
3 changes: 3 additions & 0 deletions docs/changes/devel/51.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added the zero-delay GEVD :class:`mne_denoise.mwf.MultichannelWienerFilter`
with explicit artifact-mask and clean-reference contracts, diagnostics, and MNE
metadata preservation. ``MWF`` remains available as a documented short alias.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ to extract reproducible or rhythmic components while preserving data rank.
getting-started
dss
asr
mwf
auto_examples/index

.. toctree::
Expand Down
108 changes: 108 additions & 0 deletions docs/mwf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Multi-channel Wiener filtering

`mne_denoise.mwf.MultichannelWienerFilter` implements the zero-delay GEVD
multi-channel Wiener filter described by Somers, Francart, and Bertrand (2018).
`MWF` is a short compatibility alias of the same class.

MWF is semi-supervised. It needs examples of both artifact-present and clean EEG
to estimate their covariance matrices. The core algorithm does not discover
artifacts automatically, and the origin of the mask is part of the scientific
operating point.

## Explicit-mask workflow

Mask values have precise meanings:

- `1`: artifact-present training sample;
- `0`: clean training sample;
- `NaN`: ignored, or reassigned through `treat_nan`.

```python
from mne_denoise.mwf import MultichannelWienerFilter

mwf = MultichannelWienerFilter(rank="positive")
mwf.fit(train_raw, artifact_mask=train_mask)
cleaned = mwf.transform(eval_raw)
```

`transform()` uses only the frozen spatial operator. It does not inspect the
evaluation recording or create a new mask.

For epoched input, a mask can have shape `(n_epochs, n_times)` or be a flat
epoch-major vector. MNE channel names are aligned at transform time, and channels
not selected for fitting are preserved unchanged.

## Independent clean reference

A separate clean recording can supply the clean covariance. If no mask is
provided, all samples in `X` train the artifact-present covariance:

```python
mwf.fit(artifact_training_raw, clean_reference=clean_reference_raw)
```

The training and reference data must have the same channels, channel scaling,
physical units, and—when both are MNE objects—the same sampling frequency.

## Optional high-frequency mask authoring

`hf_power_mask()` is a convenience heuristic, not part of the reference MWF
algorithm. It can be used explicitly:

```python
from mne_denoise.mwf import hf_power_mask

mask = hf_power_mask(train_data, sfreq=250.0, hf_hz=20.0, quantile=0.7)
mwf.fit(train_data, artifact_mask=mask)
```

Or requested as an explicit estimator strategy:

```python
mwf = MultichannelWienerFilter(
mask_strategy="hf_power",
sfreq=250.0,
hf_hz=20.0,
quantile=0.7,
)
mwf.fit(train_data)
```

This detector can label genuine high-frequency neural activity as artifact. Its
cutoff, quantile, and smoothing duration must therefore be validated for the
acquisition regime.

## GEVD rank and diagnostics

The default `rank="positive"` matches the reference MATLAB toolbox's `poseig`
setting: only positive artifact eigenvalues are retained. `rank="full"` applies
the full-rank covariance-ratio filter, and an integer retains that many leading
GEVD directions.

After fitting, the estimator exposes:

- `generalized_eigenvalues_` and `artifact_eigenvalues_`;
- `selected_components_`;
- `artifact_mask_` and `artifact_fraction_`;
- `fit_diagnostics_`, including sample counts, covariance ranks, and the actual
diagonal loading.

Relative diagonal loading makes the operator invariant to a shared global unit
rescaling. It cannot correct channel-specific unit mismatches.

## Evidence boundary

This implementation is derived from the authors' public MATLAB equations and
locks internal invariants such as full-rank covariance-ratio equivalence. It does
not yet claim external numerical parity with the MATLAB toolbox or validated
performance for a particular acquisition regime. The reference toolbox also
supports temporal delay embedding; this implementation currently covers the
zero-delay method only.

## References

1. Somers, B., Francart, T., & Bertrand, A. (2018). A generic EEG artifact
removal algorithm based on the multi-channel Wiener filter. *Journal of
Neural Engineering*, 15(3), 036007. https://doi.org/10.1088/1741-2552/aaac92
2. Authors' MATLAB implementation:
https://github.com/exporl/mwf-artifact-removal
7 changes: 6 additions & 1 deletion mne_denoise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@
spectrum_interpolation : Spectrum Interpolation
Removes power-line noise and its harmonics by interpolating spectral amplitudes
while preserving phase.

mwf : Multi-channel Wiener Filtering
Semi-supervised covariance-based artifact suppression using explicit artifact
and clean training segments.
"""

from . import asr, dss, icanclean, spectrum_interpolation, zapline
from . import asr, dss, icanclean, mwf, spectrum_interpolation, zapline

__version__ = "0.0.1"

Expand All @@ -41,5 +45,6 @@
"dss",
"icanclean",
"spectrum_interpolation",
"mwf",
"zapline",
]
2 changes: 1 addition & 1 deletion mne_denoise/dss/denoisers/temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class SmoothingBias(LinearDenoiser):
Uses a boxcar moving average filter to smooth the data. When used to split
the signal into a smooth branch and a residual (``data - smooth``), fitting
DSS on the residual and adding the smooth branch back follows ZapLine's
period-matched decomposition (de Cheveigné, 2020 [3]_): with
period-matched decomposition (de Cheveigné, 2020): with
``window = round(sfreq / f_line)`` the smoother has zeros at ``f_line`` and
its harmonics, so the residual concentrates the narrowband artifact.

Expand Down
23 changes: 23 additions & 0 deletions mne_denoise/mwf/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""Semi-supervised multi-channel Wiener filtering.

``MultichannelWienerFilter`` is the canonical estimator name. ``MWF`` is a
documented short alias. The implementation uses the zero-delay GEVD formulation
from Somers, Francart, and Bertrand (2018); explicit temporal delay embedding is
not yet implemented.
"""

from .core import (
MWF,
MultichannelWienerFilter,
compute_mwf,
hf_power_mask,
mwf_filter,
)

__all__ = [
"MWF",
"MultichannelWienerFilter",
"compute_mwf",
"hf_power_mask",
"mwf_filter",
]
Loading
Loading