I’m using mne.preprocessing.maxwell_filter_prepare_emptyroom() to prepare my empty room recording for constructing noise covariance. I have previously successfully used the pipeline for MEG-only data, but running into error with new MEG+EEG data. I traced down the error and found it was when trying to set the montage for the ER:
The cause seems to be that the ER instance has an empty montage. My questions are:
-Why is it not possible to directly copy the montage from one instance to the other, whether it’s empty or not?
-Should I have set some parameter when recording ER (MEGIN Triux) to have a non-empty montage?
-Is there a fix to the problem, for example only use the MEG info and discard the EEG?
If I look at the sample dataset, th raw recordings is a MEG+EEG recording and the ER only contains MEG channels (sample.data_path() / "MEG" / "sample" / "ernoise_raw.fif").
I can (almost) reproduce with:
import numpy as np
from mne import pick_info
from mne._fiff.pick import _picks_to_idx
from mne.datasets import sample
from mne.io import RawArray, read_raw_fif
from mne.preprocessing import maxwell_filter_prepare_emptyroom
fname = sample.data_path() / "MEG" / "sample" / "sample_audvis_raw.fif"
raw = read_raw_fif(fname, preload=True)
fname_er = sample.data_path() / "MEG" / "sample" / "ernoise_raw.fif"
raw_er = read_raw_fif(fname_er, preload=True) # does not have EEG channels
raw_er_prepared = maxwell_filter_prepare_emptyroom(raw_er, raw=raw) # works
# try again but faking the presence of EEG channels
raw_er = read_raw_fif(fname_er, preload=True)
idx = _picks_to_idx(raw.info, picks="eeg", exclude=())
info_eeg = pick_info(raw.info, idx)
data = np.ones((len(info_eeg.ch_names), raw_er.times.size))
raw_eeg = RawArray(data, info_eeg, first_samp=raw_er.first_samp)
raw_er.add_channels([raw_eeg], force_update_info=True)
raw_er_prepared = maxwell_filter_prepare_emptyroom(raw_er, raw=raw)
Getting the similar error:
File ~\git\mscheltienne\mne-python\mne\channels\montage.py:1323, in _set_montage(***failed resolving arguments***)
1316 # determine if needed to add an extra EEG REF DigPoint
1317 if custom_eeg_ref_dig:
1318 # ref_name = 'EEG000' if match_case else 'eeg000'
1319 ref_dig_dict = {
1320 "kind": FIFF.FIFFV_POINT_EEG,
1321 "r": eeg_ref_pos,
1322 "ident": 0,
-> 1323 "coord_frame": info["dig"].pop()["coord_frame"],
1324 }
1325 ref_dig_point = _format_dig_points([ref_dig_dict])[0]
1326 # only append the reference dig point if it was already
1327 # in the old dig
IndexError: pop from empty list
So removing the eeg channels for this step would resolve the problem; but I wonder what is the correct approach here. On one hand EEG channels are probably excluded from maxwell_filter anyway; so you could (1) drop the EEG channels (2) prepare the ER (3) run maxwell filter (4) add the EEG channels back – on the otherhand, the docstirng of maxwell_filter_prepare_emptyroom explicitly mentions montage and the code explicitly gets the montage from raw and applies it to raw_er. I’m not clear as to why this is necessary, what information needs to be retrieved from the montage and set in the ER to run maxwell_filter. @larsoner Maybe you can clarify this part?
Thinking again about it; the montage is needed because of the LPA / RPA / NAS digitization, defining the head coordinate frame, which is stored as part of the montage. So I would recommend on your side to:
(1) drop the EEG channels
(2) prepare the ER
(3) run maxwell_filter_prepare_emptyroom
(4) add the EEG channels back, if you need them e.g. to mimic the rest of the preprocessing