diff --git a/doc/changes/devel/13208.bugfix.rst.rst b/doc/changes/devel/13208.bugfix.rst.rst new file mode 100644 index 00000000000..dfb04cf39ae --- /dev/null +++ b/doc/changes/devel/13208.bugfix.rst.rst @@ -0,0 +1 @@ +Remove channels with potential electrode location from :func:`~mne.preprocessing.maxwell_filter_prepare_emptyroom`, by `Mathieu Scheltienne`_. diff --git a/mne/preprocessing/maxwell.py b/mne/preprocessing/maxwell.py index 47c5b52e0c6..5765775f36d 100644 --- a/mne/preprocessing/maxwell.py +++ b/mne/preprocessing/maxwell.py @@ -16,7 +16,7 @@ from .._fiff.compensator import make_compensator from .._fiff.constants import FIFF, FWD from .._fiff.meas_info import Info, _simplify_info -from .._fiff.pick import pick_info, pick_types +from .._fiff.pick import _picks_to_idx, pick_info, pick_types from .._fiff.proc_history import _read_ctc from .._fiff.proj import Projection from .._fiff.tag import _coil_trans_to_loc, _loc_to_coil_trans @@ -131,12 +131,17 @@ def maxwell_filter_prepare_emptyroom( * Set the following properties of the empty-room recording to match the experimental recording: - * Montage + * Montage (required for the fiducials defining the head coordinate frame) * ``raw.first_time`` and ``raw.first_samp`` * Adjust annotations according to the ``annotations`` parameter. * Adjust the measurement date according to the ``meas_date`` parameter. + .. note:: + + Note that in case of dual MEG/EEG acquisition, EEG channels should not be + included in the empty room recording. If provided, they will be ignored. + .. versionadded:: 1.1 """ # noqa: E501 _validate_type(item=raw_er, types=BaseRaw, item_name="raw_er") @@ -157,6 +162,29 @@ def maxwell_filter_prepare_emptyroom( ) raw_er_prepared = raw_er.copy() + # just in case of combine MEG/other modality, let's explicitly drop other channels + # that might have a digitization and emit a warning. + picks = [elt for elt in ("eeg", "ecog", "seeg", "dbs") if elt in raw_er_prepared] + if len(picks) != 0: + picks = _picks_to_idx(raw_er_prepared.info, picks=picks, exclude=()) + idx = np.setdiff1d(np.arange(raw_er_prepared.info["nchan"]), picks) + raw_er_prepared.pick(idx, exclude=()) + if len(raw_er.ch_names) != len(raw_er_prepared.ch_names): + warn( + "The empty-room recording contained EEG-like channels. These channels " + "were dropped from the empty-room recording, as they are not " + "compatible with Maxwell filtering. If you need to, add those channels " + "back after the execution of 'maxwell_filter_prepare_emptyroom' from your " + "original empty-room recording using 'raw.add_channels'." + ) + # apply the same channel selection to raw + picks = [elt for elt in ("eeg", "ecog", "seeg", "dbs") if elt in raw] + if len(picks) != 0: + picks = _picks_to_idx( + raw.info, picks=("eeg", "ecog", "seeg", "dbs"), exclude=() + ) + idx = np.setdiff1d(np.arange(raw_er_prepared.info["nchan"]), picks) + raw = raw.copy().pick(idx, exclude=()) del raw_er # just to be sure # handle bads; only keep MEG channels diff --git a/mne/preprocessing/tests/test_maxwell.py b/mne/preprocessing/tests/test_maxwell.py index 5b149421f98..18e074b8dfe 100644 --- a/mne/preprocessing/tests/test_maxwell.py +++ b/mne/preprocessing/tests/test_maxwell.py @@ -1896,7 +1896,7 @@ def test_prepare_emptyroom_bads(bads): assert raw_er_prepared.info["bads"] == ["MEG0113", "MEG2313"] assert raw_er_prepared.info["dev_head_t"] == raw.info["dev_head_t"] - montage_expected = raw.copy().pick(picks="meg").get_montage() + montage_expected = raw.pick(picks="meg").get_montage() assert raw_er_prepared.get_montage() == montage_expected # Ensure the originals were not modified @@ -1906,6 +1906,18 @@ def test_prepare_emptyroom_bads(bads): assert raw_er.get_montage() is None +@testing.requires_testing_data +def test_prepare_empty_room_with_eeg() -> None: + """Test preparation of MEG empty-room which was acquired with EEG enabled.""" + raw = read_raw_fif(raw_fname, allow_maxshield="yes", verbose=False) + raw_er = read_raw_fif(erm_fname, allow_maxshield="yes", verbose=False) + with pytest.warns(RuntimeWarning, match="empty-room recording contained EEG-like"): + raw_er_prepared = maxwell_filter_prepare_emptyroom(raw_er=raw_er, raw=raw) + assert raw_er_prepared.info["dev_head_t"] == raw.info["dev_head_t"] + montage_expected = raw.pick(picks="meg").get_montage() + assert raw_er_prepared.get_montage() == montage_expected + + @testing.requires_testing_data @pytest.mark.slowtest # lots of params @pytest.mark.parametrize("set_annot_when", ("before", "after"))