From 635ad29807680adb1b4d9c58c4f352213db2c18a Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Tue, 30 Jun 2026 03:41:09 +0000 Subject: [PATCH 01/13] Warn when Epochs events fall outside the raw data (#12989) Events whose epoch window lies (partly) outside the raw data are silently dropped, which is surprising e.g. when events come from a different sampling frequency or contain samples before first_samp. Warn at construction listing how many events are out of bounds. Adds a regression test. --- doc/changes/dev/12989.bugfix.rst | 1 + mne/epochs.py | 21 +++++++++++++++++++++ mne/tests/test_epochs.py | 12 ++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 doc/changes/dev/12989.bugfix.rst diff --git a/doc/changes/dev/12989.bugfix.rst b/doc/changes/dev/12989.bugfix.rst new file mode 100644 index 00000000000..674537a01a3 --- /dev/null +++ b/doc/changes/dev/12989.bugfix.rst @@ -0,0 +1 @@ +When creating :class:`mne.Epochs`, a warning is now emitted if any ``events`` fall outside the range of the raw data, since the corresponding epochs are otherwise silently dropped, by `Cedric Conday`_. diff --git a/mne/epochs.py b/mne/epochs.py index 442359f3d65..f90cb36b9b2 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -3651,6 +3651,27 @@ def __init__( annotations=annotations, ) + # Warn about events whose epoch falls (partly) outside the raw data: those + # epochs are silently dropped, which is surprising e.g. when ``events`` was + # created at a different sampling frequency or contains samples before + # ``first_samp``. See gh-12989. + if self._raw is not None and len(self.events) > 0: + sfreq = self._raw.info["sfreq"] + starts = ( + np.round(self.events[:, 0] + self._raw_times[0] * sfreq).astype(int) + - self._raw.first_samp + ) + stops = starts + len(self._raw_times) + n_oob = int(np.sum((starts < 0) | (stops > self._raw.n_times))) + if n_oob > 0: + warn( + f"{n_oob} event{_pl(n_oob)} {'is' if n_oob == 1 else 'are'} " + "outside the data range; the corresponding " + f"epoch{_pl(n_oob)} will be dropped. This can happen e.g. if " + "the events were created at a different sampling frequency, or " + "contain sample numbers before first_samp." + ) + @verbose def _get_epoch_from_raw(self, idx, verbose=None): """Load one epoch from disk. diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 2eb55d8ed62..2d7e9ec83f8 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -5278,3 +5278,15 @@ def test_empty_error(method, epochs_empty): pytest.importorskip("pandas") with pytest.raises(RuntimeError, match="is empty."): getattr(epochs_empty.copy(), method[0])(**method[1]) + + +def test_epochs_warn_out_of_bounds_events(): + """Warn when events fall outside the raw data range (gh-12989).""" + sfreq = 100.0 + info = create_info(3, sfreq, "eeg") + raw = RawArray(np.random.default_rng(0).standard_normal((3, 1000)), info) + # second event (sample 2000) is past the 1000-sample data, so its epoch is + # out of bounds and silently dropped; we should warn about it. + events = np.array([[100, 0, 1], [2000, 0, 1]]) + with pytest.warns(RuntimeWarning, match="outside the data range"): + mne.Epochs(raw, events, tmin=0, tmax=0.5, baseline=None) From 797e8ec7d46d78be226d2e0063aedf7099e17099 Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Tue, 30 Jun 2026 03:41:49 +0000 Subject: [PATCH 02/13] rename changelog fragment to PR number --- doc/changes/dev/{12989.bugfix.rst => 14004.bugfix.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/changes/dev/{12989.bugfix.rst => 14004.bugfix.rst} (100%) diff --git a/doc/changes/dev/12989.bugfix.rst b/doc/changes/dev/14004.bugfix.rst similarity index 100% rename from doc/changes/dev/12989.bugfix.rst rename to doc/changes/dev/14004.bugfix.rst From 8e5325805ce455e3293943a8bf2593ff980936dd Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Tue, 30 Jun 2026 09:57:59 +0000 Subject: [PATCH 03/13] Narrow out-of-bounds warning to event sample positions (#12989) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Warn only when an event's sample number falls outside the recorded data ([first_samp, first_samp + n_times)) — the issue's actual scenario (events at a different sampling frequency, or before first_samp). The earlier check on the epoch *window* also fired for in-range events whose window merely clips the edge (wide tmax / negative tmin on short data), which is normal and broke several existing tests. Full test_epochs.py is green under -W error. --- doc/changes/dev/14004.bugfix.rst | 2 +- mne/epochs.py | 31 +++++++++++++++---------------- mne/tests/test_epochs.py | 15 +++++++++------ 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/doc/changes/dev/14004.bugfix.rst b/doc/changes/dev/14004.bugfix.rst index 674537a01a3..602613a5352 100644 --- a/doc/changes/dev/14004.bugfix.rst +++ b/doc/changes/dev/14004.bugfix.rst @@ -1 +1 @@ -When creating :class:`mne.Epochs`, a warning is now emitted if any ``events`` fall outside the range of the raw data, since the corresponding epochs are otherwise silently dropped, by `Cedric Conday`_. +When creating :class:`mne.Epochs`, a warning is now emitted if any ``events`` have sample numbers outside the recorded data, since the corresponding epochs are otherwise silently dropped, by `Cedric Conday`_. diff --git a/mne/epochs.py b/mne/epochs.py index f90cb36b9b2..2637700eec5 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -3651,24 +3651,23 @@ def __init__( annotations=annotations, ) - # Warn about events whose epoch falls (partly) outside the raw data: those - # epochs are silently dropped, which is surprising e.g. when ``events`` was - # created at a different sampling frequency or contains samples before - # ``first_samp``. See gh-12989. + # Warn when an event's *sample number* falls outside the recorded data + # (before ``first_samp`` or at/after the last sample). Such an event yields + # no epoch and is silently dropped, which is surprising and usually means + # the events were created at a different sampling frequency or precede + # ``first_samp``. This checks the event positions, not the epoch window — + # an in-range event whose window merely clips the edge is normal and quiet. + # See gh-12989. if self._raw is not None and len(self.events) > 0: - sfreq = self._raw.info["sfreq"] - starts = ( - np.round(self.events[:, 0] + self._raw_times[0] * sfreq).astype(int) - - self._raw.first_samp - ) - stops = starts + len(self._raw_times) - n_oob = int(np.sum((starts < 0) | (stops > self._raw.n_times))) - if n_oob > 0: + lo = self._raw.first_samp + hi = lo + self._raw.n_times + n_oob = int(((self.events[:, 0] < lo) | (self.events[:, 0] >= hi)).sum()) + if n_oob: warn( - f"{n_oob} event{_pl(n_oob)} {'is' if n_oob == 1 else 'are'} " - "outside the data range; the corresponding " - f"epoch{_pl(n_oob)} will be dropped. This can happen e.g. if " - "the events were created at a different sampling frequency, or " + f"{n_oob} event{_pl(n_oob)} {'has' if n_oob == 1 else 'have'} a " + "sample number outside the recorded data; the corresponding " + f"epoch{_pl(n_oob)} will be dropped. This can happen if the " + "events were created at a different sampling frequency, or " "contain sample numbers before first_samp." ) diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 2d7e9ec83f8..5b6916e7a02 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -1,4 +1,5 @@ # Authors: The MNE-Python contributors. +import warnings # License: BSD-3-Clause # Copyright the MNE-Python contributors. @@ -5281,12 +5282,14 @@ def test_empty_error(method, epochs_empty): def test_epochs_warn_out_of_bounds_events(): - """Warn when events fall outside the raw data range (gh-12989).""" + """Warn when event sample numbers fall outside the recorded data (gh-12989).""" sfreq = 100.0 info = create_info(3, sfreq, "eeg") raw = RawArray(np.random.default_rng(0).standard_normal((3, 1000)), info) - # second event (sample 2000) is past the 1000-sample data, so its epoch is - # out of bounds and silently dropped; we should warn about it. - events = np.array([[100, 0, 1], [2000, 0, 1]]) - with pytest.warns(RuntimeWarning, match="outside the data range"): - mne.Epochs(raw, events, tmin=0, tmax=0.5, baseline=None) + # event sample 2000 is past the 1000-sample recording -> warn + with pytest.warns(RuntimeWarning, match="outside the recorded data"): + mne.Epochs(raw, np.array([[2000, 0, 1]]), tmin=-0.2, tmax=0.5, baseline=None) + # an in-range event whose epoch window merely clips the edge must NOT warn + with warnings.catch_warnings(): + warnings.simplefilter("error") + mne.Epochs(raw, np.array([[990, 0, 1]]), tmin=0, tmax=0.5, baseline=None) From 244ea62fe3bad69067f37f19672f25e17533e6e9 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:58:43 +0000 Subject: [PATCH 04/13] [autofix.ci] apply automated fixes --- mne/tests/test_epochs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 5b6916e7a02..7d4f7734827 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -1,5 +1,4 @@ # Authors: The MNE-Python contributors. -import warnings # License: BSD-3-Clause # Copyright the MNE-Python contributors. From 1d8d166f3cf1fa67e7c1d9b37c5ab973af64d113 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:58:55 +0000 Subject: [PATCH 05/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mne/tests/test_epochs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 7d4f7734827..087f50b33a2 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -1,8 +1,8 @@ # Authors: The MNE-Python contributors. # License: BSD-3-Clause # Copyright the MNE-Python contributors. - import pickle +import warnings from copy import deepcopy from datetime import timedelta from functools import partial From 5ab7993b75b50a832d1fde774a7b65e5a9b93c10 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 09:59:35 +0000 Subject: [PATCH 06/13] [autofix.ci] apply automated fixes --- mne/tests/test_epochs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 087f50b33a2..b6f0fc828c4 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -1,6 +1,7 @@ # Authors: The MNE-Python contributors. # License: BSD-3-Clause # Copyright the MNE-Python contributors. + import pickle import warnings from copy import deepcopy From 7c1faed08e17a47b6ffbb81e01185aa960b4cf48 Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Tue, 30 Jun 2026 14:16:27 +0000 Subject: [PATCH 07/13] Add on_outside option to control out-of-bounds events warning Mirrors the on_missing pattern used for out-of-range Raw annotations (_on_missing helper): 'raise' | 'warn' (default) | 'ignore'. Addresses maintainer review on gh-14004. --- doc/changes/dev/14004.bugfix.rst | 2 +- mne/epochs.py | 14 ++++++++++++-- mne/tests/test_epochs.py | 12 ++++++++++-- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/doc/changes/dev/14004.bugfix.rst b/doc/changes/dev/14004.bugfix.rst index 602613a5352..52434aaea21 100644 --- a/doc/changes/dev/14004.bugfix.rst +++ b/doc/changes/dev/14004.bugfix.rst @@ -1 +1 @@ -When creating :class:`mne.Epochs`, a warning is now emitted if any ``events`` have sample numbers outside the recorded data, since the corresponding epochs are otherwise silently dropped, by `Cedric Conday`_. +When creating :class:`mne.Epochs`, a warning is now emitted if any ``events`` have sample numbers outside the recorded data, since the corresponding epochs are otherwise silently dropped; this is configurable via the new ``on_outside`` parameter (``'raise'`` | ``'warn'`` | ``'ignore'``), by `Cedric Conday`_. diff --git a/mne/epochs.py b/mne/epochs.py index 2637700eec5..9e539c7c561 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -3487,6 +3487,13 @@ class Epochs(BaseEpochs): .. versionadded:: 0.16 %(event_repeated_epochs)s + on_outside : 'raise' | 'warn' | 'ignore' + What to do if an event's sample number falls outside the recorded data + range. Such events yield no epoch and are dropped. Can be ``'raise'`` + to raise an error, ``'warn'`` (default) to emit a warning, or + ``'ignore'`` to do nothing. + + .. versionadded:: 1.13 %(verbose)s Attributes @@ -3587,6 +3594,7 @@ def __init__( reject_by_annotation=True, metadata=None, event_repeated="error", + on_outside="warn", verbose=None, ): from .io import BaseRaw @@ -3663,12 +3671,14 @@ def __init__( hi = lo + self._raw.n_times n_oob = int(((self.events[:, 0] < lo) | (self.events[:, 0] >= hi)).sum()) if n_oob: - warn( + _on_missing( + on_outside, f"{n_oob} event{_pl(n_oob)} {'has' if n_oob == 1 else 'have'} a " "sample number outside the recorded data; the corresponding " f"epoch{_pl(n_oob)} will be dropped. This can happen if the " "events were created at a different sampling frequency, or " - "contain sample numbers before first_samp." + "contain sample numbers before first_samp.", + name="on_outside", ) @verbose diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index b6f0fc828c4..9412a2ae8ea 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -5286,9 +5286,17 @@ def test_epochs_warn_out_of_bounds_events(): sfreq = 100.0 info = create_info(3, sfreq, "eeg") raw = RawArray(np.random.default_rng(0).standard_normal((3, 1000)), info) - # event sample 2000 is past the 1000-sample recording -> warn + oob = np.array([[2000, 0, 1]]) + # event sample 2000 is past the 1000-sample recording -> warn (default) with pytest.warns(RuntimeWarning, match="outside the recorded data"): - mne.Epochs(raw, np.array([[2000, 0, 1]]), tmin=-0.2, tmax=0.5, baseline=None) + mne.Epochs(raw, oob, tmin=-0.2, tmax=0.5, baseline=None) + # on_outside="raise" turns it into an error + with pytest.raises(ValueError, match="outside the recorded data"): + mne.Epochs(raw, oob, tmin=-0.2, tmax=0.5, baseline=None, on_outside="raise") + # on_outside="ignore" stays silent + with warnings.catch_warnings(): + warnings.simplefilter("error") + mne.Epochs(raw, oob, tmin=-0.2, tmax=0.5, baseline=None, on_outside="ignore") # an in-range event whose epoch window merely clips the edge must NOT warn with warnings.catch_warnings(): warnings.simplefilter("error") From 254d87b0eb4a89229745881ab9c01e1a0209ca47 Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Wed, 1 Jul 2026 19:20:43 +0000 Subject: [PATCH 08/13] Address review: keyword-only on_outside, move logic to BaseEpochs, fix test - on_outside made keyword-only in both Epochs and EpochsArray - Warning logic moved from Epochs to BaseEpochs._oob_check for reuse - EpochsArray now accepts and forwards on_outside to BaseEpochs - Test uses pytest.raises instead of pytest.warns per mne warnings-as-errors policy --- mne/epochs.py | 45 ++++++++++++++++++++-------------------- mne/tests/test_epochs.py | 3 ++- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/mne/epochs.py b/mne/epochs.py index 9e539c7c561..c766476130c 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -462,6 +462,7 @@ def __init__( filename=None, metadata=None, event_repeated="error", + on_outside="warn", *, raw_sfreq=None, annotations=None, @@ -575,6 +576,7 @@ def __init__( self.detrend = detrend self._raw = raw + self._oob_check(on_outside) info._check_consistency() self.picks = _picks_to_idx( info, picks, none="all", exclude=(), allow_empty=False @@ -691,6 +693,23 @@ def __init__( self._check_consistency() self.set_annotations(annotations, on_missing="ignore") + def _oob_check(self, on_outside): + """Warn when event sample numbers fall outside recorded data (gh-12989).""" + if self._raw is not None and len(self.events) > 0: + lo = self._raw.first_samp + hi = lo + self._raw.n_times + n_oob = int(((self.events[:, 0] < lo) | (self.events[:, 0] >= hi)).sum()) + if n_oob: + _on_missing( + on_outside, + f"{n_oob} event{_pl(n_oob)} {'has' if n_oob == 1 else 'have'} a " + "sample number outside the recorded data; the corresponding " + f"epoch{_pl(n_oob)} will be dropped. This can happen if the " + "events were created at a different sampling frequency, or " + "contain sample numbers before first_samp.", + name="on_outside", + ) + def _check_consistency(self): """Check invariants of epochs object.""" if hasattr(self, "events"): @@ -3594,6 +3613,7 @@ def __init__( reject_by_annotation=True, metadata=None, event_repeated="error", + *, on_outside="warn", verbose=None, ): @@ -3654,33 +3674,12 @@ def __init__( on_missing=on_missing, preload_at_end=preload, event_repeated=event_repeated, + on_outside=on_outside, verbose=verbose, raw_sfreq=raw_sfreq, annotations=annotations, ) - # Warn when an event's *sample number* falls outside the recorded data - # (before ``first_samp`` or at/after the last sample). Such an event yields - # no epoch and is silently dropped, which is surprising and usually means - # the events were created at a different sampling frequency or precede - # ``first_samp``. This checks the event positions, not the epoch window — - # an in-range event whose window merely clips the edge is normal and quiet. - # See gh-12989. - if self._raw is not None and len(self.events) > 0: - lo = self._raw.first_samp - hi = lo + self._raw.n_times - n_oob = int(((self.events[:, 0] < lo) | (self.events[:, 0] >= hi)).sum()) - if n_oob: - _on_missing( - on_outside, - f"{n_oob} event{_pl(n_oob)} {'has' if n_oob == 1 else 'have'} a " - "sample number outside the recorded data; the corresponding " - f"epoch{_pl(n_oob)} will be dropped. This can happen if the " - "events were created at a different sampling frequency, or " - "contain sample numbers before first_samp.", - name="on_outside", - ) - @verbose def _get_epoch_from_raw(self, idx, verbose=None): """Load one epoch from disk. @@ -3807,6 +3806,7 @@ def __init__( metadata=None, selection=None, *, + on_outside="warn", drop_log=None, raw_sfreq=None, verbose=None, @@ -3843,6 +3843,7 @@ def __init__( selection=selection, proj=proj, on_missing=on_missing, + on_outside=on_outside, drop_log=drop_log, raw_sfreq=raw_sfreq, verbose=verbose, diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 9412a2ae8ea..31450aa595b 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -5288,7 +5288,8 @@ def test_epochs_warn_out_of_bounds_events(): raw = RawArray(np.random.default_rng(0).standard_normal((3, 1000)), info) oob = np.array([[2000, 0, 1]]) # event sample 2000 is past the 1000-sample recording -> warn (default) - with pytest.warns(RuntimeWarning, match="outside the recorded data"): + # Under mne's warnings-as-errors test policy the RuntimeWarning is raised. + with pytest.raises(RuntimeWarning, match="outside the recorded data"): mne.Epochs(raw, oob, tmin=-0.2, tmax=0.5, baseline=None) # on_outside="raise" turns it into an error with pytest.raises(ValueError, match="outside the recorded data"): From f283d01a83f3473df7404bd6a28f943d32c313d9 Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Wed, 1 Jul 2026 20:30:26 +0000 Subject: [PATCH 09/13] ci: fix EpochsFIF first_samp crash, test for old env without warnings-as-errors, add missing BaseEpochs on_outside doc --- mne/epochs.py | 13 ++++++++++++- mne/tests/test_epochs.py | 3 +-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/mne/epochs.py b/mne/epochs.py index c766476130c..03bf2592a10 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -418,6 +418,13 @@ class BaseEpochs( .. versionadded:: 0.16 %(event_repeated_epochs)s + on_outside : 'raise' | 'warn' | 'ignore' + What to do if an event's sample number falls outside the recorded data + range. Such events yield no epoch and are dropped. Can be ``'raise'`` + to raise an error, ``'warn'`` (default) to emit a warning, or + ``'ignore'`` to do nothing. + + .. versionadded:: 1.13 %(raw_sfreq)s annotations : instance of mne.Annotations | None Annotations to set. @@ -695,7 +702,11 @@ def __init__( def _oob_check(self, on_outside): """Warn when event sample numbers fall outside recorded data (gh-12989).""" - if self._raw is not None and len(self.events) > 0: + if ( + self._raw is not None + and len(self.events) > 0 + and hasattr(self._raw, "first_samp") + ): lo = self._raw.first_samp hi = lo + self._raw.n_times n_oob = int(((self.events[:, 0] < lo) | (self.events[:, 0] >= hi)).sum()) diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 31450aa595b..9412a2ae8ea 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -5288,8 +5288,7 @@ def test_epochs_warn_out_of_bounds_events(): raw = RawArray(np.random.default_rng(0).standard_normal((3, 1000)), info) oob = np.array([[2000, 0, 1]]) # event sample 2000 is past the 1000-sample recording -> warn (default) - # Under mne's warnings-as-errors test policy the RuntimeWarning is raised. - with pytest.raises(RuntimeWarning, match="outside the recorded data"): + with pytest.warns(RuntimeWarning, match="outside the recorded data"): mne.Epochs(raw, oob, tmin=-0.2, tmax=0.5, baseline=None) # on_outside="raise" turns it into an error with pytest.raises(ValueError, match="outside the recorded data"): From 1e7cea95acb3ead139324a883cd941b48fe6fdbf Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Wed, 1 Jul 2026 21:41:33 +0000 Subject: [PATCH 10/13] docs: document on_outside param on EpochsArray (fix numpydoc/build_docs) --- mne/epochs.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mne/epochs.py b/mne/epochs.py index 03bf2592a10..04231f73dae 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -3768,6 +3768,13 @@ class EpochsArray(BaseEpochs): .. versionadded:: 0.16 %(selection)s + on_outside : 'raise' | 'warn' | 'ignore' + What to do if an event's sample number falls outside the recorded data + range. Such events yield no epoch and are dropped. Can be ``'raise'`` + to raise an error, ``'warn'`` (default) to emit a warning, or + ``'ignore'`` to do nothing. + + .. versionadded:: 1.13 %(drop_log)s .. versionadded:: 1.3 From 11f6a3b518720955cdf8b95982e1ba20f54b623e Mon Sep 17 00:00:00 2001 From: CedricConday Date: Fri, 3 Jul 2026 10:53:28 +0000 Subject: [PATCH 11/13] test(ica): silence out-of-bounds event warning where tests feed full event file (gh-12989) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_warnings and test_n_components_none pass the complete event file against a shorter/cropped raw, so some events fall past the data and are dropped — expected here. Pass on_outside='ignore' at those call sites so the new default warning does not trip warnings-as-errors. No behavior change to the tests' actual assertions. --- mne/preprocessing/tests/test_ica.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mne/preprocessing/tests/test_ica.py b/mne/preprocessing/tests/test_ica.py index 7ca5bfc31e3..a94b39220fc 100644 --- a/mne/preprocessing/tests/test_ica.py +++ b/mne/preprocessing/tests/test_ica.py @@ -188,7 +188,7 @@ def test_warnings(): """Test that ICA warns on certain input data conditions.""" raw = read_raw_fif(raw_fname).crop(0, 5).load_data() events = read_events(event_name) - epochs = Epochs(raw, events=events, baseline=None, preload=True) + epochs = Epochs(raw, events=events, baseline=None, preload=True, on_outside="ignore") ica = ICA(n_components=2, max_iter=1, method="infomax", random_state=0) # not high-passed @@ -1348,6 +1348,7 @@ def test_eog_channel(method): baseline=None, preload=True, proj=False, + on_outside="ignore", ) n_components = 0.9 ica = ICA(n_components=n_components, method=method) From ebdc19768fd5f648eca99c74ba511ec6e6bb74fc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 3 Jul 2026 11:44:13 +0000 Subject: [PATCH 12/13] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mne/preprocessing/tests/test_ica.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mne/preprocessing/tests/test_ica.py b/mne/preprocessing/tests/test_ica.py index a94b39220fc..ec53f214a7d 100644 --- a/mne/preprocessing/tests/test_ica.py +++ b/mne/preprocessing/tests/test_ica.py @@ -188,7 +188,9 @@ def test_warnings(): """Test that ICA warns on certain input data conditions.""" raw = read_raw_fif(raw_fname).crop(0, 5).load_data() events = read_events(event_name) - epochs = Epochs(raw, events=events, baseline=None, preload=True, on_outside="ignore") + epochs = Epochs( + raw, events=events, baseline=None, preload=True, on_outside="ignore" + ) ica = ICA(n_components=2, max_iter=1, method="infomax", random_state=0) # not high-passed From b2333afce8c8f45433bc44d31c3b58d031047459 Mon Sep 17 00:00:00 2001 From: Cedric Conday <277679649+CedricConday@users.noreply.github.com> Date: Tue, 7 Jul 2026 23:11:17 +0000 Subject: [PATCH 13/13] test(ica): silence out-of-bounds warning in test_n_components_none (gh-12989) test_n_components_none crops raw to (1.5, stop) but reads the full event file, so some events fall past the cropped data and are dropped as expected. Pass on_outside='ignore' at that call site so the new default warning does not trip warnings-as-errors. A prior commit fixed the two sibling ICA tests but missed this one. Test-only; no behavior change. --- mne/preprocessing/tests/test_ica.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mne/preprocessing/tests/test_ica.py b/mne/preprocessing/tests/test_ica.py index ec53f214a7d..4a67beffeb5 100644 --- a/mne/preprocessing/tests/test_ica.py +++ b/mne/preprocessing/tests/test_ica.py @@ -1384,7 +1384,15 @@ def test_n_components_none(method, tmp_path): events = read_events(event_name) picks = pick_types(raw.info, eeg=True, meg=False)[::5] epochs = Epochs( - raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + preload=True, + on_outside="ignore", ) n_components = None