From e9c86eb70da83e4388cb5d2228661b7d1ef5ca8b Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Tue, 30 Jun 2026 03:48:59 +0000 Subject: [PATCH 1/3] Fix pick channels crash when _orig_units is None (#11314) Picking/reordering channels built {k: v for ... in self._orig_units.items()} unconditionally, raising AttributeError when _orig_units is None (as produced by some readers / RawArray flows). Guard for a falsy _orig_units. Adds a test. --- doc/changes/dev/11314.bugfix.rst | 1 + mne/channels/channels.py | 7 ++++--- mne/channels/tests/test_channels.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 doc/changes/dev/11314.bugfix.rst diff --git a/doc/changes/dev/11314.bugfix.rst b/doc/changes/dev/11314.bugfix.rst new file mode 100644 index 00000000000..8a30fec7520 --- /dev/null +++ b/doc/changes/dev/11314.bugfix.rst @@ -0,0 +1 @@ +Fix a crash (``AttributeError`` on ``NoneType``) when picking channels on a :class:`~mne.io.Raw` whose ``_orig_units`` is ``None``, by `Cedric Conday`_. diff --git a/mne/channels/channels.py b/mne/channels/channels.py index c1a3d462525..c18ac8d253c 100644 --- a/mne/channels/channels.py +++ b/mne/channels/channels.py @@ -646,9 +646,10 @@ def _pick_drop_channels(self, idx, *, verbose=None): if isinstance(self, BaseRaw): self.annotations._prune_ch_names(self.info, on_missing="ignore") - self._orig_units = { - k: v for k, v in self._orig_units.items() if k in self.ch_names - } + if self._orig_units: + self._orig_units = { + k: v for k, v in self._orig_units.items() if k in self.ch_names + } self._pick_projs() return self diff --git a/mne/channels/tests/test_channels.py b/mne/channels/tests/test_channels.py index 138d2b325c7..b35aa68495c 100644 --- a/mne/channels/tests/test_channels.py +++ b/mne/channels/tests/test_channels.py @@ -696,3 +696,17 @@ def test_combine_channels_metadata(): good = dict(foo=[0, 1, 3, 4], bar=[5, 2]) # good grad and mag combined_epochs = combine_channels(epochs, good) pd.testing.assert_frame_equal(epochs.metadata, combined_epochs.metadata) + + +def test_pick_channels_orig_units_none(): + """Picking channels must not crash when _orig_units is None (gh-11314).""" + import numpy as np + + import mne + + info = mne.create_info(["Fp1", "Fp2", "F3", "F4"], 100.0, "eeg") + raw = mne.io.RawArray(np.zeros((4, 100)), info) + raw._orig_units = None # the state reported by some readers / RawArray flows + raw.pick(["Fp1", "Fp2"]) # previously raised AttributeError on None.items() + assert raw.ch_names == ["Fp1", "Fp2"] + assert raw._orig_units is None From 3189b595c80a88dd8d58b0e70b6b6b5c907156fa Mon Sep 17 00:00:00 2001 From: Cedric Conday Date: Tue, 30 Jun 2026 03:49:52 +0000 Subject: [PATCH 2/3] rename changelog fragment to PR number --- doc/changes/dev/{11314.bugfix.rst => 14006.bugfix.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/changes/dev/{11314.bugfix.rst => 14006.bugfix.rst} (100%) diff --git a/doc/changes/dev/11314.bugfix.rst b/doc/changes/dev/14006.bugfix.rst similarity index 100% rename from doc/changes/dev/11314.bugfix.rst rename to doc/changes/dev/14006.bugfix.rst From 1e8c790e0be85ac450b6b5a75452924aaef71677 Mon Sep 17 00:00:00 2001 From: CedricConday Date: Wed, 1 Jul 2026 05:31:24 +0000 Subject: [PATCH 3/3] test: hoist numpy/mne imports to module level per review --- mne/channels/tests/test_channels.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mne/channels/tests/test_channels.py b/mne/channels/tests/test_channels.py index b35aa68495c..2c2bfc6db6f 100644 --- a/mne/channels/tests/test_channels.py +++ b/mne/channels/tests/test_channels.py @@ -14,6 +14,7 @@ from numpy.testing import assert_allclose, assert_array_equal, assert_equal from scipy.io import savemat +import mne from mne import ( Epochs, EpochsArray, @@ -700,10 +701,6 @@ def test_combine_channels_metadata(): def test_pick_channels_orig_units_none(): """Picking channels must not crash when _orig_units is None (gh-11314).""" - import numpy as np - - import mne - info = mne.create_info(["Fp1", "Fp2", "F3", "F4"], 100.0, "eeg") raw = mne.io.RawArray(np.zeros((4, 100)), info) raw._orig_units = None # the state reported by some readers / RawArray flows