draw topomap with a custom ch_type

Is it possible to draw topomap with a custom data?

I am 306channel meg data, then each channel is [-1,1] r value, I want to draw the topomap of this r value, is there any recommended way?
I use this code:

evoke = mne.EvokedArray(data, info)
env_topo = evoke.plot_topomap(ch_type="mag")

But this has to specify a ch_type, and my data is not either eeg or meg, so the plot is a bit strange with the specified ch_type.

env_cor_topo

:question: If you have a question or issue with MNE-Python, please include the following info:

  • MNE version: 0.24.0
  • operating system: Ubuntu 20.04

Hi @elvisjade! Unfortunately, as far as I know, that is not currently a supported use case; in the documentation (mne.Evoked — MNE 1.0.0 documentation) it specifies that the only accepted channel types are in the list for ch_types.

I have had the need to grab the head outline and sensor positions and plot something in my work so I can point you to:

picks, pos, merge_channels, names, ch_type, sphere, clip_origin = \
    mne.viz.topomap._prepare_topomap_plot(evoked, ch_type)
outlines = mne.viz.topomap._make_head_outlines(
    sphere, pos, outlines='head', clip_origin=clip_origin)

This will give you pos and outlines from which you can plot the lines with ax.plot and show an image based on the values at each position with ax.imshow using the interpolation parameter (this is with maplotlib). It’s a bit of an advanced so might be quite tricky to implement though!

1 Like

you can just pass colorbar=False

if the unit is meaningless

Alex

1 Like

Thank you very much for your suggestion, I have tried it as you said.
But it seems that different ch_types do not present the data in the same way.

ch_type ‘mag’ | ‘grad’ | ‘planar1’ | ‘planar2’ | ‘eeg’ | None
The type of channel to be plotted. For ‘grad’, gradiometers are collected in pairs, and the valid values of each pair are plotted. If not, the channels are selected in the order given above.

Thank you very much for your suggestion.

I have extracted picks, pos, merge_channels, names, ch_type, sphere, clip_origin ,outlines and other parameters according to your code.

But it is true that these are only the relevant values, and I need to completely redraw the graph with matplotlib, which seems too difficult for me, I don’t have a good foundation in matplotlib.

You are trying to plot the vector of r (floats) with a shape of (306, ) on a topomap, correct? Did you try using mne.viz.plot_topomap? mne.viz.plot_topomap — MNE 1.0.0 documentation

If so, what was the problem encountered with this one?

1 Like

Thank you very much for your reply, I have tried this before.

But this seems to be similar to evoke.plot_topomap.

When I use mne.viz.plot_topomap directly myself, I have been unable to get the correct pos parameter.
I refer to this tutorial for the process of getting the pos parameter, but it keeps reporting errors in the middle.
I’m sorry I didn’t log the error in time, but I did try this function. (How to plot topomaps the way EEGLAB does — MNE 1.0.0 documentation sphere-py)

How about providing pos as:

import mne

info = create_info(306, 1, 'misc')
info.set_montage(whatever_your_montage_is)

Basically the info you provide in EvokedArray, but with all channels set to misc.

1 Like

Thank you very much for your advice, I just tried to do it.
This is my code:
This is my error:

data = mne.io.read_raw_fif("/sss.fif",preload=False)
data.drop_channels(
["EOG001","ECG003","IASX+","IASX-","IASY+","IASY-","IASZ+","IASZ-","IAS_DX","IAS_DY","IAS_X","IAS_Y","IAS_Z","MISC001","STI001","STI002","STI003","STI004","STI005","STI006","STI007","STI008","STI009","STI010","STI011","STI012","STI013","STI014","STI015","STI016","STI101","SYS201","EOG001","ECG003","IASX+","IASX-","IASY+","IASY-","IASZ+","IASZ-","IAS_DX","IAS_DY","IAS_X","IAS_Y","IAS_Z","MISC001","STI001","STI002","STI003","STI004","STI005","STI006","STI007","STI008","STI009","STI010","STI011","STI012","STI013","STI014","STI015","STI016","STI101","SYS201"]
info = data.info
df = pd.read_csv("/r.csv",)
finfo = mne.create_info(info.ch_names,1,'misc')
mne.viz.plot_topomap(df, finfo)

it will report bug:

File “/mne/lib/python3.9/site-packages/mne/io/pick.py”, line 538, in pick_info
raise ValueError(‘No channels match the selection.’)
No channels match the selection.

finfo = mne.create_info(info.ch_names,1,‘eeg’)
mne.viz.plot_topomap(df, finfo)

it will report bug:

File “/mne/lib/python3.9/site-packages/mne/channels/layout.py”, line 690, in _auto_topomap_coords
raise RuntimeError(‘No digitization points found.’)
RuntimeError: No digitization points found.

Yes, you forgot the set_montage() line. you can add: finfo.set_montage(info.get_montage()) before the topomap plot.

1 Like

I tried it as you suggested, but it gives the same error.

finfo = mne.create_info(info.ch_names, 1, “misc”)

finfo = finfo.set_montage(data.get_montage())

mne.viz.plot_topomap(df_r, finfo)

bug:

File “/mne24/lib/python3.9/site-packages/mne/io/pick.py”, line 538, in pick_info

raise ValueError(‘No channels match the selection.’)

ValueError: No channels match the selection.

And I tried this codes:

finfo = mne.create_info(info.ch_names, 1, “eeg”)

finfo = finfo.set_montage(data.get_montage())

mne.viz.plot_topomap(df_r, finfo)

It will report an error like this.

DigMontage is only a subset of info. There are 306 channel positions not present in the DigMontage. The required channels are:

[‘MEG0111’ all meg channel]

Consider using inst.set_channel_types if these are not EEG channels, or use the on_missing parameter if the channel positions are allowed to be unknown in your analyses.

It seems that this idea is also required to match the type of channel and the type of info, and cannot avoid the channel type.

Arf, I guess setting the montage match with the channel types and not the channel names only. My bad… How about:

import mne

data = mne.io.read_raw_fif("/sss.fif",preload=False)
data.drop_channels(
["EOG001","ECG003","IASX+","IASX-","IASY+","IASY-","IASZ+","IASZ-","IAS_DX","IAS_DY","IAS_X","IAS_Y","IAS_Z","MISC001","STI001","STI002","STI003","STI004","STI005","STI006","STI007","STI008","STI009","STI010","STI011","STI012","STI013","STI014","STI015","STI016","STI101","SYS201","EOG001","ECG003","IASX+","IASX-","IASY+","IASY-","IASZ+","IASZ-","IAS_DX","IAS_DY","IAS_X","IAS_Y","IAS_Z","MISC001","STI001","STI002","STI003","STI004","STI005","STI006","STI007","STI008","STI009","STI010","STI011","STI012","STI013","STI014","STI015","STI016","STI101","SYS201"]
# Set all channels to one type, 'misc' or 'eeg', or whatever
data.set_channel_types({ch_name: 'misc' for ch_name in data.ch_names}) 
df = pd.read_csv("/r.csv")
mne.viz.plot_topomap(df, data.info)
1 Like

Thank you very much for your patience in helping.

I tried following your latest reply.
data.set_channel_types({ch_name: ‘misc’ for ch_name in data.ch_names})
df = pd.read_csv("/r.csv")
mne.viz.plot_topomap(df, data.info)
but still gives an error
File “/mne24/lib/python3.9/site-packages/mne/io/pick.py”, line 538, in pick_info
raise ValueError(‘No channels match the selection.’)
ValueError: No channels match the selection.

I tried
evoke = mne.EvokedArray(df_r, info)
evoke.plot_topomap()
then it will give an error
File “/mne24/lib/python3.9/site-packages/mne/channels/channels.py”, line 102, in _get_ch_type
raise RuntimeError(‘No plottable channel types found’)

RuntimeError: No plottable channel types found

I also tried this idea

data.set_channel_types({ch_name: ‘eeg’ for ch_name in data.ch_names})
df = pd.read_csv("/r.csv")
mne.viz.plot_topomap(df, data.info)

Then an error will be reported:
File “/mne24/lib/python3.9/site-packages/mne/channels/layout.py”, line 724, in _auto_topomap_coords
raise ValueError(‘The following electrodes have overlapping positions,’

ValueError: The following electrodes have overlapping positions, which causes problems during visualization:
MEG0111…all channel

I think we are at a point where helping/debugging via discourse becomes difficult.
I suggest you join the next office hours on Discord where you can directly ask your question to MNE developers and share your screen. The office hours take place every 2 weeks on Fridays at 17h CET.

1 Like

Just to comment and maybe clarify, misc channel types are not supported for plotting in plot_topomap so you’ll have to hack it a bit and pass eeg like you did. It looks like you’re really close, the error is telling you what’s wrong, some of your sensors have the same position. It looks like they are gradiometers and magnetometers which makes sense. I would suggest separating the data out by gradiometers and then plotting those distances only, it would be the same for magnetometers.

1 Like

Thank you very much for your continued patience and help.
I’ll join mne’s Discord event later and screen share to discuss with the developers.
Many thanks.

I understand part of what you are saying.
Thank you very much for your suggestion!
But this is too difficult for me, and I may not be able to do this with my current programming skills.