Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into splash
Browse files Browse the repository at this point in the history
* upstream/main:
  [MRG] ENH: add skip_by_annotation to notch_filter (mne-tools#11388)
  • Loading branch information
larsoner committed Jan 4, 2023
2 parents 3c6eac1 + b298e6d commit 39499fb
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 19 deletions.
4 changes: 3 additions & 1 deletion doc/changes/latest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ Current (1.4.dev0)

Enhancements
~~~~~~~~~~~~
- None yet
- Added ability to read stimulus durations from SNIRF files when using :func:`mne.io.read_raw_snirf` (:gh:`11397` by `Robert Luke`_)
- Add :meth:`mne.Info.save` to save an :class:`mne.Info` object to a fif file (:gh:`11401` by `Alex Rockhill`_)
- Add support for ``skip_by_annotation`` in :func:`mne.io.Raw.notch_filter` (:gh:`11388` by `Mainak Jas`_)

Bugs
~~~~
Expand Down
10 changes: 1 addition & 9 deletions mne/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1935,15 +1935,7 @@ def filter(self, l_freq, h_freq, picks=None, filter_length='auto',
%(phase)s
%(fir_window)s
%(fir_design)s
skip_by_annotation : str | list of str
If a string (or list of str), any annotation segment that begins
with the given string will not be included in filtering, and
segments on either side of the given excluded annotated segment
will be filtered separately (i.e., as independent signals).
The default (``('edge', 'bad_acq_skip')`` will separately filter
any segments that were concatenated by :func:`mne.concatenate_raws`
or :meth:`mne.io.Raw.append`, or separated during acquisition.
To disable, provide an empty list. Only used if ``inst`` is raw.
%(skip_by_annotation)s
.. versionadded:: 0.16.
%(pad_fir)s
Expand Down
28 changes: 19 additions & 9 deletions mne/io/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
copy_function_doc_to_method_doc, _validate_type,
_check_preload, _get_argvalues, _check_option,
_build_data_frame, _convert_times, _scale_dataframe_data,
_check_time_format, _arange_div, TimeMixin, repr_html)
_check_time_format, _arange_div, TimeMixin, repr_html,
_pl)
from ..defaults import _handle_default
from ..viz import plot_raw, _RAW_CLIP_DEF
from ..event import find_events, concatenate_events
Expand Down Expand Up @@ -987,7 +988,9 @@ def notch_filter(self, freqs, picks=None, filter_length='auto',
notch_widths=None, trans_bandwidth=1.0, n_jobs=None,
method='fir', iir_params=None, mt_bandwidth=None,
p_value=0.05, phase='zero', fir_window='hamming',
fir_design='firwin', pad='reflect_limited', verbose=None):
fir_design='firwin', pad='reflect_limited',
skip_by_annotation=('edge', 'bad_acq_skip'),
verbose=None):
"""Notch filter a subset of channels.
Parameters
Expand Down Expand Up @@ -1024,6 +1027,7 @@ def notch_filter(self, freqs, picks=None, filter_length='auto',
The default is ``'reflect_limited'``.
.. versionadded:: 0.15
%(skip_by_annotation)s
%(verbose)s
Returns
Expand Down Expand Up @@ -1053,13 +1057,19 @@ def notch_filter(self, freqs, picks=None, filter_length='auto',
fs = float(self.info['sfreq'])
picks = _picks_to_idx(self.info, picks, exclude=(), none='data_or_ica')
_check_preload(self, 'raw.notch_filter')
self._data = notch_filter(
self._data, fs, freqs, filter_length=filter_length,
notch_widths=notch_widths, trans_bandwidth=trans_bandwidth,
method=method, iir_params=iir_params, mt_bandwidth=mt_bandwidth,
p_value=p_value, picks=picks, n_jobs=n_jobs, copy=False,
phase=phase, fir_window=fir_window, fir_design=fir_design,
pad=pad)
onsets, ends = _annotations_starts_stops(
self, skip_by_annotation, invert=True)
logger.info('Filtering raw data in %d contiguous segment%s'
% (len(onsets), _pl(onsets)))
for si, (start, stop) in enumerate(zip(onsets, ends)):
self._data = notch_filter(
self._data[:, start:stop], fs, freqs,
filter_length=filter_length, notch_widths=notch_widths,
trans_bandwidth=trans_bandwidth, method=method,
iir_params=iir_params, mt_bandwidth=mt_bandwidth,
p_value=p_value, picks=picks, n_jobs=n_jobs, copy=False,
phase=phase, fir_window=fir_window, fir_design=fir_design,
pad=pad)
return self

@verbose
Expand Down
10 changes: 10 additions & 0 deletions mne/tests/test_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,16 @@ def test_annotation_filtering(first_samp):
raws_concat_stop = raws_concat.copy().filter(skip_by_annotation='edge',
**kwargs_stop)
assert_allclose(raws_zero[0][0], raws_concat_stop[0][0], atol=1e-14)

# test notch_filtering
raw_notch = concatenate_raws([raws_concat.copy(), raws_concat.copy()])
raw_notch.annotations.append(7. + raw_notch._first_time, 1., 'foo_notch')
with catch_logging() as log:
raw_notch.notch_filter(60., fir_design='firwin',
skip_by_annotation='foo_notch', verbose='info')
log = log.getvalue()
assert '1 contiguous segment' in log

# one last test: let's cut out a section entirely:
# here the 1-3 second window should be skipped
raw = raws_concat.copy()
Expand Down
12 changes: 12 additions & 0 deletions mne/utils/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3224,6 +3224,18 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
Side length of each subplot in inches.
"""

docdict['skip_by_annotation'] = """
skip_by_annotation : str | list of str
If a string (or list of str), any annotation segment that begins
with the given string will not be included in filtering, and
segments on either side of the given excluded annotated segment
will be filtered separately (i.e., as independent signals).
The default (``('edge', 'bad_acq_skip')`` will separately filter
any segments that were concatenated by :func:`mne.concatenate_raws`
or :meth:`mne.io.Raw.append`, or separated during acquisition.
To disable, provide an empty list. Only used if ``inst`` is raw.
"""

docdict['skip_by_annotation_maxwell'] = """
skip_by_annotation : str | list of str
If a string (or list of str), any annotation segment that begins
Expand Down

0 comments on commit 39499fb

Please sign in to comment.