Skip to content

ENH: allow specifying ransac at class inst of NoisyChannels #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 17, 2025
Merged
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
6 changes: 5 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ repos:
- id: check-docstring-first

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.0
rev: v0.12.3
hooks:
- id: ruff
name: ruff check --fix
files: ^(pyprep/|examples/|tests/)
args: ["--fix"]
- id: ruff-format
name: ruff format
files: ^(pyprep/|examples/|tests/)

- repo: https://github.com/pappasam/toml-sort
rev: v0.24.2
Expand Down
38 changes: 32 additions & 6 deletions pyprep/find_noisy_channels.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""finds bad channels."""
"""Find bad channels."""

# Authors: The PyPREP developers
# SPDX-License-Identifier: MIT
Expand Down Expand Up @@ -44,6 +44,11 @@ class NoisyChannels:
Whether or not PyPREP should strictly follow MATLAB PREP's internal
math, ignoring any improvements made in PyPREP over the original code
(see :ref:`matlab-diffs` for more details). Defaults to ``False``.
ransac : bool
Whether RANSAC should be used for bad channel detection, in addition
to other methods. RANSAC can detect bad channels that other
methods are unable to catch, but also slows down noisy channel
detection considerably. Defaults to ``True``.

References
----------
Expand All @@ -53,7 +58,15 @@ class NoisyChannels:

"""

def __init__(self, raw, do_detrend=True, random_state=None, matlab_strict=False):
def __init__(
self,
raw,
do_detrend=True,
random_state=None,
matlab_strict=False,
*,
ransac=True,
):
# Make sure that we got an MNE object
assert isinstance(raw, mne.io.BaseRaw)

Expand All @@ -68,6 +81,9 @@ def __init__(self, raw, do_detrend=True, random_state=None, matlab_strict=False)
)
self.matlab_strict = matlab_strict

assert isinstance(ransac, bool), f"ransac must be boolean, got: {ransac}"
self.ransac = ransac

# Extra data for debugging
self._extra_info = {
"bad_by_deviation": {},
Expand Down Expand Up @@ -187,18 +203,20 @@ def get_bads(self, verbose=False, as_dict=False):

return bads

def find_all_bads(self, ransac=True, channel_wise=False, max_chunk_size=None):
def find_all_bads(self, ransac=None, channel_wise=False, max_chunk_size=None):
"""Call all the functions to detect bad channels.

This function calls all the bad-channel detecting functions.

Parameters
----------
ransac : bool, optional
ransac : bool | None
Whether RANSAC should be used for bad channel detection, in addition
to the other methods. RANSAC can detect bad channels that other
methods are unable to catch, but also slows down noisy channel
detection considerably. Defaults to ``True``.
detection considerably. If ``None`` (default), then the value at
instantiation of the ``NoisyChannels`` class is taken (defaults
to ``True``), else the instantiation value is overwritten.
channel_wise : bool, optional
Whether RANSAC should predict signals for chunks of channels over the
entire signal length ("channel-wise RANSAC", see `max_chunk_size`
Expand All @@ -218,12 +236,20 @@ def find_all_bads(self, ransac=True, channel_wise=False, max_chunk_size=None):
effect. Defaults to ``None``.

"""
if ransac is not None and ransac != self.ransac:
assert isinstance(ransac, bool), f"ransac must be boolean, got: {ransac}"
logger.warning(
f"Overwriting `ransac` value. Was `{self.ransac}` at instantiation "
f"of NoisyChannels. Now setting to `{ransac}`."
)
self.ransac = ransac

# NOTE: Bad-by-NaN/flat is already run during init, no need to re-run here
self.find_bad_by_deviation()
self.find_bad_by_hfnoise()
self.find_bad_by_correlation()
self.find_bad_by_SNR()
if ransac:
if self.ransac:
self.find_bad_by_ransac(
channel_wise=channel_wise, max_chunk_size=max_chunk_size
)
Expand Down
Loading