Skip to content

ENH: Multi-channel Wiener filter (MWF) native denoiser - #51

Draft
snesmaeili wants to merge 4 commits into
mainfrom
feature/native-mwf
Draft

ENH: Multi-channel Wiener filter (MWF) native denoiser#51
snesmaeili wants to merge 4 commits into
mainfrom
feature/native-mwf

Conversation

@snesmaeili

@snesmaeili snesmaeili commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Rebases PR #51 onto current main and hardens the new multi-channel Wiener filter around an explicit, evidence-aware contract.

  • Adds canonical MultichannelWienerFilter; MWF remains a documented short alias.
  • Implements the zero-delay generalized-eigendecomposition (GEVD) MWF equations from Somers, Francart & Bertrand (2018), including the reference poseig-style positive-rank default, full/integer rank controls, artifact weighting (mu), and relative covariance loading.
  • Requires an explicit 0/1/NaN artifact mask or an independent clean reference. The high-frequency detector is available only through an explicit mask_strategy=hf_power opt-in and is documented as an unvalidated mask-authoring heuristic, not part of core MWF.
  • Keeps fitting and evaluation separate: fit() freezes the learned spatial operator and transform() never re-estimates a mask or covariance on evaluation data.
  • Preserves MNE object subtype and metadata, aligns channels by name, keeps unselected channels unchanged, supports epoch-shaped masks, and checks sampling-rate compatibility for independent references.
  • Exposes sample counts, covariance ranks, GEVD values, selected components, regularization loading, and identity/no-op information as fit diagnostics.

Evidence boundary

This implementation follows the authors' public MATLAB equations and locks internal invariants such as full-rank covariance-ratio equivalence and common-unit rescaling. It does not yet claim external numerical parity with the MATLAB toolbox or validated performance for a particular acquisition regime. The authors' delay-embedded extension is also not included; this PR implements the zero-delay method only.

Primary references:

Tests and documentation

  • 30 focused MWF tests pass on Python 3.10, covering explicit asset contracts, GEVD/full-rank invariants, attenuation, rank deficiency, NaN policies, frozen-operator behavior, unit rescaling, and Raw/Epochs/Evoked metadata preservation.
  • Ruff check and format checks pass.
  • The complete pre-commit suite passes.
  • Strict Sphinx (-W --keep-going) passes with gallery execution disabled for the local documentation check.

The full cross-platform/package matrix remains delegated to this PR's GitHub Actions checks.

@snesmaeili
snesmaeili force-pushed the feature/native-mwf branch from f08c95c to ef3febd Compare July 2, 2026 10:40
Add mne_denoise.mwf with MWF (BaseEstimator/TransformerMixin) plus compute_mwf,
mwf_filter, and hf_power_mask. MWF is a generic reference-free spatial cleaner
and the RELAX-pipeline core (Somers, Francart & Bertrand 2018): it recovers the
clean signal via R_clean @ inv(R_artifact) @ X from artifact-free and
artifact-present segment covariances, with artifact segments marked by broadband
HF power (or a supplied mask). fit() learns the Wiener operator, transform()
applies it (leakage-safe); accepts MNE Raw/Epochs (sfreq from info) or NumPy
arrays. Documented as a general cleaner (can attenuate neural HF activity), not
an artifact-specific method.

Edge cases handled: cap the HF-mask smoothing window at the signal length (numpy
convolve mode=same otherwise yields a mask longer than short recordings/epochs);
guard single-channel input; coerce int 0/1 masks to bool. Includes unit tests
(tests/test_mwf.py) and docs (docs/mwf.md, api/index).
@codecov

codecov Bot commented Aug 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.77419% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.11%. Comparing base (e84d8d0) to head (c05db1a).

Files with missing lines Patch % Lines
mne_denoise/mwf/core.py 96.73% 5 Missing and 4 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #51      +/-   ##
==========================================
+ Coverage   96.08%   96.11%   +0.03%     
==========================================
  Files          65       67       +2     
  Lines        8170     8448     +278     
  Branches     1420     1473      +53     
==========================================
+ Hits         7850     8120     +270     
- Misses        152      157       +5     
- Partials      168      171       +3     
Flag Coverage Δ
unittests 96.11% <96.77%> (+0.03%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
mne_denoise/__init__.py 100.00% <100.00%> (ø)
mne_denoise/dss/denoisers/temporal.py 100.00% <ø> (ø)
mne_denoise/mwf/__init__.py 100.00% <100.00%> (ø)
mne_denoise/mwf/core.py 96.73% <96.73%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@snesmaeili
snesmaeili marked this pull request as draft August 1, 2026 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant