Repository: mne-tools/mne-python

Issue:
plot_joint passes wrong position information to plot_topomap
Dear community,

I've just updated to 0.17 and noticed that calling AverageTFR.plot_joint() results in a ValueError when calling plot_topomap: 

ValueError("Data and pos need to be of same length. Got data of ""length %s, pos of length %s" % (len(data), len(pos)))

I believe this happens for the following reason: plot_joint() loads the position information for sensors from the layout file using find_layout() by default, which only excludes info['bads']. AverageTFR usually only contains a subset of the remaining channels. It seems that only position information for channels in info['ch_names'] should be passed to plot_topomap().

Best,

David



Discussion:
@jona-sassenhagen 
Can you share a minimally reproducible example?
Yes, of course:

```import mne
from mne.datasets.brainstorm import bst_phantom_ctf
from mne.time_frequency import tfr_morlet
from mne.io import read_raw_ctf
import os.path as op
import sys
import numpy as np

sys.argv[0] = "--accept-brainstorm-license"
path = bst_phantom_ctf.data_path()
path = op.join(path, 'phantom_20uA_20150603_03.ds')
raw = read_raw_ctf(path,preload=True)
raw.pick_types(meg=True,ref_meg=True)
events = np.array([2000,3000,4000])
events = np.vstack((events, np.zeros_like(events), np.ones_like(events))).T
epochs = mne.Epochs(raw, events, tmin=-0.5, tmax=0.5)
freqs = [10]
n_cycles = [2]
power = tfr_morlet(epochs, freqs=freqs, n_cycles=n_cycles, return_itc=False)
timefreqs=[(0,10)]
power.plot_joint(timefreqs=None,title="Example TFR",show=True)

```

This results in:

"ValueError: Data and pos need to be of same length. Got data of length 273, pos of length 275"
Thanks, I will get on it - unless you want to contribute a fix yourself?
Sure, I'll submit a pull request tomorrow.
Great, thanks, be sure to @ me.

Resolving patch:
diff --git a/mne/time_frequency/tfr.py b/mne/time_frequency/tfr.py
--- a/mne/time_frequency/tfr.py
+++ b/mne/time_frequency/tfr.py
@@ -1524,7 +1524,14 @@ def plot_joint(self, timefreqs=None, picks=None, baseline=None,
 
             data = tfr.data
 
-            pos = find_layout(tfr.info).pos if layout is None else layout.pos
+            if layout is None:
+                loaded_layout = find_layout(tfr.info)
+
+            # only use position information for channels from layout
+            # whose names appear as a substring in tfr.ch_names
+            idx = [any(ch_name in ch_name_tfr for ch_name_tfr in tfr.ch_names)
+                   for ch_name in loaded_layout.names]
+            pos = loaded_layout.pos[np.array(idx)]
 
             # merging grads here before rescaling makes ERDs visible
             if ch_type == 'grad':


Test patch:
diff --git a/mne/time_frequency/tests/test_tfr.py b/mne/time_frequency/tests/test_tfr.py
--- a/mne/time_frequency/tests/test_tfr.py
+++ b/mne/time_frequency/tests/test_tfr.py
@@ -521,8 +521,12 @@ def test_plot_joint():
                    topomap_args=topomap_args)
     plt.close('all')
     assert_array_equal(tfr.data, tfr_orig.data)
-    assert (set(tfr.ch_names) == set(tfr_orig.ch_names))
-    assert (set(tfr.times) == set(tfr_orig.times))
+    assert set(tfr.ch_names) == set(tfr_orig.ch_names)
+    assert set(tfr.times) == set(tfr_orig.times)
+
+    # test tfr with picked channels
+    tfr.pick_channels(tfr.ch_names[:-1])
+    tfr.plot_joint(title='auto', colorbar=True, topomap_args=topomap_args)
 
 
 def test_add_channels():
@@ -633,8 +637,8 @@ def test_compute_tfr():
 
     # Inter-trial coherence tests
     out = _compute_tfr(data, freqs, sfreq, output='itc', n_cycles=2.)
-    assert (np.sum(out >= 1) == 0)
-    assert (np.sum(out <= 0) == 0)
+    assert np.sum(out >= 1) == 0
+    assert np.sum(out <= 0) == 0
 
     # Check decim shapes
     # 2: multiple of len(times) even