diff --git a/doc/changes/dev/13556.new.rst b/doc/changes/dev/13556.new.rst new file mode 100644 index 00000000000..e3a6f53cb1c --- /dev/null +++ b/doc/changes/dev/13556.new.rst @@ -0,0 +1 @@ +Add ``on_drop_all`` parameter to :meth:`mne.Epochs.drop` to control behavior when all epochs are dropped. \ No newline at end of file diff --git a/mne/epochs.py b/mne/epochs.py index 4bd94ffa2c5..b143086a9a2 100644 --- a/mne/epochs.py +++ b/mne/epochs.py @@ -1515,7 +1515,7 @@ def plot_image( ) @verbose - def drop(self, indices, reason="USER", verbose=None): + def drop(self, indices, reason="USER", verbose=None, on_drop_all="warn"): """Drop epochs based on indices or boolean mask. .. note:: The indices refer to the current set of undropped epochs @@ -1569,6 +1569,18 @@ def drop(self, indices, reason="USER", verbose=None): ", ".join(map(str, np.sort(try_idx))), ) + if len(self) == 0: + msg = "All epochs dropped" + if on_drop_all == "raise": + raise ValueError(msg) + elif on_drop_all == "warn": + warn(msg) + elif on_drop_all != "ignore": + raise ValueError( + 'on_drop_all must be "warn", "raise" or "ignore", ' + f"got {on_drop_all}" + ) + return self def _get_epoch_from_raw(self, idx, verbose=None): diff --git a/mne/tests/test_epochs.py b/mne/tests/test_epochs.py index 91c5f902ac8..5235b728d7e 100644 --- a/mne/tests/test_epochs.py +++ b/mne/tests/test_epochs.py @@ -5273,3 +5273,30 @@ 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_drop_all_epochs(): + """Test on_drop_all parameter in Epochs.drop.""" + # Create tiny dummy data (3 epochs) + data = np.random.RandomState(0).randn(1, 1, 10) + info = create_info(["ch1"], 1000.0, "eeg") + epochs = EpochsArray(data, info) + + # 1. Test 'warn' (default) + # We expect a warning when dropping all epochs + with pytest.warns(RuntimeWarning, match="All epochs dropped"): + epochs.copy().drop([0]) + + # 2. Test 'raise' + # We expect a ValueError when dropping all epochs + with pytest.raises(ValueError, match="All epochs dropped"): + epochs.copy().drop([0], on_drop_all="raise") + + # 3. Test 'ignore' + # Should run silently (no warning, no error) + epochs.copy().drop([0], on_drop_all="ignore") + + # 4. Test Typo + # We expect a ValueError because 'wrn' is not valid + with pytest.raises(ValueError, match="on_drop_all must be"): + epochs.copy().drop([0], on_drop_all="wrn")