Make_inverse_resolution_matrix raises error when custom_ref_applied is missing

MNE-Python version: 0.22.1
operating system: macOS 10.15.7

Hi all,

I came across an unexpected error from make_inverse_resolution_matrix that stems from _check_referrence in apply_inverse:

The error is related to custom_ref_applied in the inverse info dictionary. It seems that if the inverse is newly generated, rather than saved and reloaded, this field is missing from the dict (see final image below). This causes the above call to info.get() to proceed to raise the error. On the other hand, if the same inverse is saved and read back in, the dictionary now contains custom_ref_applied, avoiding the error. I’ve copied code below that replicates the problem with the mne-sample dataset on my machine. See the difference between inv vs. inv_reloaded.

I guess first I’m wondering whether this might be a mistake in the way I’m generating the inverse operator… or if not, is this a problem in how the info dictionary is being prepared, or _check_reference is applied?

Here is the code for reproducing with mne-sample:

import mne
import glob
from mne.datasets import sample
from mne.minimum_norm import make_inverse_resolution_matrix

# raw path
data_path = sample.data_path()
fname_raw = data_path + '/MEG/sample/sample_audvis_filt-0-40_raw.fif'

# set some params
event_id, tmin, tmax = 1, -0.2, 0.5
snr = 3.0
lambda2 = 1.0 / snr ** 2
method = "dSPM" 

# read raw & epoch
raw = mne.io.read_raw_fif(fname_raw, verbose=False)

events = mne.find_events(raw)

event_id = dict(trigger = 1)
epochs = mne.Epochs(raw, events, event_id = event_id, proj = False, picks = ['meg'], reject=None, tmin=tmin,tmax=tmax, decim=5, baseline=(None,0), preload=False, reject_by_annotation=False, verbose=False) # decim to speed up but shouldn't

# estimate covariance
cov = mne.compute_covariance(epochs, tmin=-0.2, tmax=0, method='empirical',verbose=False) #empirical for speed

# bem sol
bem_path = data_path + '/subjects/sample/bem/sample-5120-5120-5120-bem-sol.fif'
bem = mne.read_bem_solution(bem_path, verbose=False)

# source space
src = mne.read_source_spaces(fname = data_path + '/subjects/sample/bem/sample-oct-6-src.fif')

# trans
trans_fname = data_path + '/MEG/sample/sample_audvis_raw-trans.fif'
trans = mne.read_trans(trans_fname, verbose=False)

# forward
fwd = mne.make_forward_solution(raw.info, trans=trans, src=src, bem=bem,
                                meg=True, eeg=False, mindist=5.0, n_jobs=1,
                                verbose=False, ignore_ref=True)

fwd_fixed = mne.convert_forward_solution(fwd, surf_ori=True, force_fixed=True,
         use_cps=True, verbose=False)

# make 2 inverses - one saved and reloaded
inv = mne.minimum_norm.make_inverse_operator(raw.info, fwd_fixed, cov, loose=0., depth=None, fixed=True)
mne.minimum_norm.write_inverse_operator(fname = data_path + 'mne-sample-inv.fif',inv=inv)
# this one reloaded
inv_reloaded = mne.minimum_norm.read_inverse_operator(data_path + 'mne-sample-inv.fif')


# this runs with the reloaded inv, no problem:
rm = make_inverse_resolution_matrix(forward= fwd_fixed, inverse_operator = inv_reloaded, method='dSPM', lambda2 = lambda2)

# this fails with inv (i.e., the non-saved one)
rm = make_inverse_resolution_matrix(forward= fwd_fixed, inverse_operator = inv, method='dSPM', lambda2 = lambda2)

Here is the error when the unloaded inverse is used:

Here is the difference between the info dictionaries in each inverse:

See here ^ how the reloaded dictionary contains custom_ref_applied while the original one does not. Strangely both raw.info or epochs.info do have custom_ref_applied = False. It only appears to be lost when generating the inverse, and then re-gained when loading a saved inverse operator.

Friendly ping @larsoner

this field is missing from the dict (see final image below). This causes the above call to info.get() to proceed to raise the error.

It shouldn’t fail even for an empty dict:

>>> dict().get('custom_ref_applied', False)
False

Looks like you are actually on 0.22.1, which does not have this fix:

You need to be on latest main to get the dict.get behavior in the commit you reference above.

Ahhh yes sorry, I see that now. The fix was right there :slight_smile: Thanks!