Repository: mne-tools/mne-python

Issue:
compute_source_psd_epochs need 'noisenorm' from inverse operator
import mne
import os.path as op
from mne.datasets import sample
from mne.minimum_norm import make_inverse_operator, apply_inverse,compute_source_psd_epochs

data_path = sample.data_path()
subjects_dir = data_path + '/subjects'

# Read data
data_path = op.join(mne.datasets.sample.data_path(), 'MEG', 'sample')
raw = mne.io.read_raw_fif(
    op.join(data_path, 'sample_audvis_raw.fif'), preload=True)
raw.load_data().filter(None, 9, fir_design='firwin')
raw.set_eeg_reference('average', projection=True)  # set EEG average reference
event_id = {'auditory/left': 1, 'auditory/right': 2, 'visual/left': 3,
            'visual/right': 4, 'smiley': 5, 'button': 32}
events = mne.read_events(op.join(data_path, 'sample_audvis_raw-eve.fif'))
epochs = mne.Epochs(raw, events, event_id=event_id, tmin=-0.2, tmax=.5)
fname_fwd = sample.data_path() + '/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif'
fname_cov = sample.data_path() + '/MEG/sample/sample_audvis-cov.fif'
fwd = mne.read_forward_solution(fname_fwd)
cov = mne.read_cov(fname_cov)

inv = make_inverse_operator(epochs.info, fwd, cov, loose=0., depth=0.8,
                            verbose=True)

epochs = epochs.load_data()
stc = compute_source_psd_epochs(epochs, inv, lambda2=1.0, method='dSPM', fmin=7.0, fmax=35.0, pick_ori='normal', label=None, nave=len(epochs), pca=True, inv_split=None, bandwidth=4.0, adaptive=False, low_bias=True, return_generator=False, n_jobs=1, prepared=True, method_params=None, verbose=None)


Discussion:
The issue was with preload = True in the keyword arguments.
To clarify for future folks, I think you mean `prepared=True` here.

I'm going to reopen so we remember to catch non-prepared `inv` use in these sorts of functions

Resolving patch:
diff --git a/mne/minimum_norm/inverse.py b/mne/minimum_norm/inverse.py
--- a/mne/minimum_norm/inverse.py
+++ b/mne/minimum_norm/inverse.py
@@ -478,6 +478,18 @@ def _check_ch_names(inv, info):
     _check_comps(inv['info'], info, 'inverse')
 
 
+def _check_or_prepare(inv, nave, lambda2, method, method_params, prepared):
+    """Check if inverse was prepared, or prepare it."""
+    if not prepared:
+        inv = prepare_inverse_operator(
+            inv, nave, lambda2, method, method_params)
+    elif 'colorer' not in inv:
+        raise ValueError('inverse operator has not been prepared, but got '
+                         'argument prepared=True. Either pass prepared=False '
+                         'or use prepare_inverse_operator.')
+    return inv
+
+
 @verbose
 def prepare_inverse_operator(orig, nave, lambda2, method='dSPM',
                              method_params=None, verbose=None):
@@ -922,11 +934,9 @@ def apply_inverse(evoked, inverse_operator, lambda2=1. / 9., method="dSPM",
 
     _check_ch_names(inverse_operator, evoked.info)
 
-    if not prepared:
-        inv = prepare_inverse_operator(inverse_operator, nave, lambda2, method,
-                                       method_params)
-    else:
-        inv = inverse_operator
+    inv = _check_or_prepare(inverse_operator, nave, lambda2, method,
+                            method_params, prepared)
+
     #
     #   Pick the correct channels from the data
     #
@@ -1052,11 +1062,9 @@ def apply_inverse_raw(raw, inverse_operator, lambda2, method="dSPM",
     #
     #   Set up the inverse according to the parameters
     #
-    if not prepared:
-        inv = prepare_inverse_operator(inverse_operator, nave, lambda2, method,
-                                       method_params)
-    else:
-        inv = inverse_operator
+    inv = _check_or_prepare(inverse_operator, nave, lambda2, method,
+                            method_params, prepared)
+
     #
     #   Pick the correct channels from the data
     #
@@ -1131,11 +1139,9 @@ def _apply_inverse_epochs_gen(epochs, inverse_operator, lambda2, method='dSPM',
     #
     #   Set up the inverse according to the parameters
     #
-    if not prepared:
-        inv = prepare_inverse_operator(inverse_operator, nave, lambda2, method,
-                                       method_params)
-    else:
-        inv = inverse_operator
+    inv = _check_or_prepare(inverse_operator, nave, lambda2, method,
+                            method_params, prepared)
+
     #
     #   Pick the correct channels from the data
     #
diff --git a/mne/minimum_norm/time_frequency.py b/mne/minimum_norm/time_frequency.py
--- a/mne/minimum_norm/time_frequency.py
+++ b/mne/minimum_norm/time_frequency.py
@@ -15,7 +15,7 @@
 from ..time_frequency.multitaper import (_psd_from_mt, _compute_mt_params,
                                          _psd_from_mt_adaptive, _mt_spectra)
 from ..baseline import rescale, _log_rescale
-from .inverse import (combine_xyz, prepare_inverse_operator, _assemble_kernel,
+from .inverse import (combine_xyz, _check_or_prepare, _assemble_kernel,
                       _pick_channels_inverse_operator, _check_method,
                       _check_ori, _subject_from_inverse)
 from ..parallel import parallel_func
@@ -28,11 +28,9 @@ def _prepare_source_params(inst, inverse_operator, label=None,
                            decim=1, pca=True, pick_ori="normal",
                            prepared=False, method_params=None, verbose=None):
     """Prepare inverse operator and params for spectral / TFR analysis."""
-    if not prepared:
-        inv = prepare_inverse_operator(inverse_operator, nave, lambda2, method,
-                                       method_params)
-    else:
-        inv = inverse_operator
+    inv = _check_or_prepare(inverse_operator, nave, lambda2, method,
+                            method_params, prepared)
+
     #
     #   Pick the correct channels from the data
     #


Test patch:
diff --git a/mne/minimum_norm/tests/test_inverse.py b/mne/minimum_norm/tests/test_inverse.py
--- a/mne/minimum_norm/tests/test_inverse.py
+++ b/mne/minimum_norm/tests/test_inverse.py
@@ -746,6 +746,8 @@ def test_apply_mne_inverse_raw():
     label_lh = read_label(fname_label % 'Aud-lh')
     _, times = raw[0, start:stop]
     inverse_operator = read_inverse_operator(fname_full)
+    with pytest.raises(ValueError, match='has not been prepared'):
+        apply_inverse_raw(raw, inverse_operator, lambda2, prepared=True)
     inverse_operator = prepare_inverse_operator(inverse_operator, nave=1,
                                                 lambda2=lambda2, method="dSPM")
     for pick_ori in [None, "normal", "vector"]: