Scaling problem using plot_topomaps for spatial patterns

Dear all,
I am having an issue plotting computed spatial patterns (see image attached), as the sensors are totally unscaled with the head model.
One (maybe useful?) information side note : it was working properly before the ā€œmne.channels.read_montageā€ was not depreciated.

  • MNE-Python version: MNE 0.23.0
  • operating system: MacOS

Code snippets :

# Define classifier
clf = make_pipeline(
    StandardScaler(),         
    LinearModel(LinearSVC())) # Linear SVM augmented with an automatic storing of spatial patterns

clf.fit(X=psd_data,
        y=epochs.metadata['move'])

patterns = get_coef(clf, 'patterns_', inverse_transform=True)

n_elect = int(patterns.shape[0] / len(bands))
spatial_pattern = patterns.reshape(n_elect, len(bands))

montage = mne.channels.make_standard_montage(raw.info['montage']) #montage previously defined ("EGI_256")
raw.set_montage(montage)
pos = mne.channels.layout.find_layout(raw.info).pos

fig, axes = plt.subplots(1, 4,figsize=(10,3))
fig.tight_layout()
for idx, (band, sp, ax) in enumerate(zip(bands, spatial_pattern.T, axes)):
    scale = np.percentile(np.abs(sp), 99)
    im, _ = mne.viz.plot_topomap(sp, pos,
                                 vmin=-scale, vmax=+scale,
                                 cmap='RdBu_r', axes=ax, show=False)
    plt.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
    ax.set_title('%i - %i Hz' % band)

Do you have any hints about how to solve this problem ?
Thank you so much for your help !

Hello @romybeaute and welcome to the forum!

Can you try the following instead?

raw.set_montage(montage='EGI_256')

Best,

Richard

Hi Richard, thank you very much for your reply. Unfortunately, it didnā€™t resolve the issue

Best,

Romy

Hello @romybeaute, could you share a tiny reproducible example so the developers can have a look?

Ok, thank you very much! Can I send it to you by email?

Sure, my address is richard.hoechenberger@gmail.com

Hello @romybeaute,

Iā€™ve had a brief look at the data and notebook you sent me. I plotted the sensors with the following code before and after running set_montage():

# %%
from pathlib import Path
import mne

base_dir = Path('~/Development/Support/mne-python/Romy').expanduser()
raw_path = base_dir / 'BRIVER_MCP.mff'
raw = mne.io.read_raw_egi(raw_path)

raw.plot_sensors()

raw.set_montage('EGI_256', on_missing='warn')
raw.plot_sensors()

In fact, there are already sensor locations in the data before calling set_montage() ā€“ so Iā€™m wondering whether you even need to call this method?

As for the notebook, itā€™s unfortunately overwhelming as it contains an entire analysis pipeline, and I donā€™t have enough time to look into the details. Also a few functions are missing, so I cannot simply run it. Youā€™d need to create something much less complex that contains just enough code to demonstrate your problem, otherwise it will be very difficult for others to reproduce and understand the issue youā€™re experiencing.

Best wishes,

Richard

Dear all,

If any of you is also having this kind of problem, I might have found how to deal with it.
The problem came from the layout that I was taking from the data file and that seemed to be inaccurate :

pos = mne.channels.layout.find_layout(raw.info).pos 

Instead, I used the three following lines (as a checkup, I also used a second method using the ā€œdigā€ info of the data and I get the save results.
So here is the updated plotting function :

use_ch = [ch for ch in raw.info['ch_names'] if ch.startswith('E') and ch not in ['ECG', 'EMG-Leg','E257']]
posarray = np.array([raw.info['chs'][i]['loc'][:2].tolist() for i,p in enumerate(raw.info['chs']) if raw.info['chs'][i]['ch_name'] in use_ch])
posarray_names = np.array([raw.info['chs'][i]['ch_name'] for i,p in enumerate(raw.info['chs']) if raw.info['chs'][i]['ch_name'] in use_ch])
fig = plt.figure()
fig.tight_layout()
for idx, (band, sp) in enumerate(zip(bands, spatial_pattern.T)):
    scale = np.percentile(np.abs(sp), 99)
    print(' Spatial patterns over %i - %i Hz' % band)
    im, _ = mne.viz.plot_topomap(sp,
                                 pos=posarray,
                                 ch_type='eeg',
                                 names = posarray_names,
                                 show_names=True,
                                 vmin=-scale, vmax=+scale,
                                 #extrapolate = 'head',
                                 cmap='RdBu_r', show=True)
    plt.colorbar(im,ax=ax,fraction=0.046, pad=0.04)
    ax.set_title('%i - %i Hz' % band)
    plt.close()

EGI256 version :

10/20 version :

Bad layout (in 10/20) :

Hope this is useful ! :slight_smile:

1 Like