Creating a morph object for subjects with different number of vertices

  • MNE-Python version: 0.23.4
  • operating system: Windows 10

I have several subjects that have different numbers of vertices in their stc objects (volumetric). I can only create a morph object for one subject, and for others, I get a “dimension mismatch” error since they have more or fewer vertices.

I need to average all morph objects for my group analysis, and I do not know how to do it when my subjects’ vertices are different in number. I can neither create a morph object for them nor average their stc objects due to this issue.

(I also checked this discussion on Github, and unfortunately, it did not help me)

Thank you!

Best,
Aqil

Hello @aqil.izadysadr, it’s difficult to help without seeing your code or a minimal working example that reproduces your issue.

Typically what you’ll want to do is morph each participant’s brain to fsaverage. Once all brains have been morphed, you can simply average their activation, as they’ll have identical dimensions.

Best wishes,
Richard

Hello @richard,

Thank you for your response. Here is a snippet of my script:

import numpy as np
import matplotlib.pyplot as plt

import mne

from tkinter import Tk     
from tkinter import filedialog
from tkinter.filedialog import askopenfilename

def open_dir(f_type):    
    root = Tk()
    root.withdraw()
    root.overrideredirect(True)
    root.geometry('0x0+0+0')
    root.deiconify()
    root.lift()
    root.focus_force()
    f_dir = filedialog.askdirectory(title="Select the {} directory".format(f_type))
    root.destroy()
    return f_dir

import pickle

def get_file(text):
    root = Tk()
    root.withdraw()
    root.overrideredirect(True)
    root.geometry('0x0+0+0')
    root.deiconify()
    root.lift()
    root.focus_force()
    fname = askopenfilename(parent=root, title=text,
                                filetypes=((text,"*"),
                                           ("all files","*.*"))) 
    root.destroy()
    return fname

def open_pickle(pickle_dir):
    with open(pickle_dir, 'rb') as p:
        return pickle.load(p)

stc = get_file("stc object")
stc = open_pickle(stc)

subject_dir = (open_dir("single subject folder"))
subj_fsaverage_dir = (open_dir("fsaverage folder"))
anat = open_dir("anat folder")

morph = mne.compute_source_morph(stc, 
                                     subject_from=stc.subject,
                                     subject_to=subj_fsaverage_dir,
                                     subjects_dir=subject_dir)   

stc_fsaverage_1 = morph.apply(stc)

surfer_kwargs = dict(hemi='lh', subjects_dir=subject_dir, views='lateral')
brain_inf = stc_fsaverage_1.plot(**surfer_kwargs)
brain_inf.add_text(0.1, 0.9, 'Morphed to fsaverage (inflated)', 'title', font_size=16)

I can only morph a few participant’s brains to fsaverage, and other participants’ brain data containing more vertices cannot be morphed to fsaverage. I am wondering if there is a way to fix the number of vertices for all subjects to a certain number so that there will not be any discrepancy in the vertices number when it comes to morphing the brain data, but I am not sure if that is a viable solution.

Thanks!

Aqil

Do you construct a separate morph object for each subject? If so, what is the error that you get?

1 Like

Hello @mmagnuski,

Yes, I construct a separate morph object for each subject. However, there is only one ‘fsaverage’ for all subjects.

Here is the error that I get when constructing a separate morph object for other subjects:

Traceback (most recent call last):

  File "C:\Users\Aqil\AppData\Local\Temp/ipykernel_14280/3311823618.py", line 1, in <module>
    morph_2 = mne.compute_source_morph(stc_list[2],

  File "<decorator-gen-327>", line 22, in compute_source_morph

  File "C:\Users\Aqil\anaconda3\envs\mne\lib\site-packages\mne\morph.py", line 248, in compute_source_morph
    morph_mat = _compute_morph_matrix(

  File "C:\Users\Aqil\anaconda3\envs\mne\lib\site-packages\mne\morph.py", line 1112, in _compute_morph_matrix
    morpher.append(_hemi_morph(

  File "C:\Users\Aqil\anaconda3\envs\mne\lib\site-packages\mne\morph.py", line 1152, in _hemi_morph
    mm = maps[vertices_to] * mm

  File "C:\Users\Aqil\anaconda3\envs\mne\lib\site-packages\scipy\sparse\base.py", line 479, in __mul__
    raise ValueError('dimension mismatch')

ValueError: dimension mismatch

Thank you!

Can share the surf/*h.sphere*, surf/*h.white surfaces for your subject, plus the stc? Then locally we should be able to reproduce your error with something like:

>>> import mne
>>> import numpy as np
>>> src = mne.setup_source_space('test', 'oct-6', subjects_dir='.', add_dist='patch')
>>> morph = mne.compute_source_morph(src=src, subject_from='test')
>>> n_verts = sum(s['nuse'] for s in src)
>>> vertices = [s['vertno'] for s in src]
>>> stc = mne.SourceEstimate(np.eye(n_verts), vertices, 0, 1e-3, subject='test')
>>> morph = mne.compute_source_morph(src=src, subject_from='test', subjects_dir='.')
>>> morph.apply(stc)
<SourceEstimate | 20484 vertices, subject : fsaverage, tmin : 0.0 (ms), tmax : 8195.0 (ms), tstep : 1.0 (ms), data shape : (20484, 8196), ~1.25 GB>

and even the middle few lines with creating src shouldn’t even be necessary with you sharing a STC because we can just use that directly:

>>> import mne
>>> import pickle
>>> with open('stc_pickle') as fid:
...        stc = pickle.load(fid)
>>> morph = mne.compute_source_morph(src=stc, subject_from='test', subjects_dir='.')
>>> morph.apply(stc)

Dear @larsoner ,

Thank you! I shared the requested files here. Please, let me know if more information is required.

Thank you!

Best,
Aqil

I’ll need lh.sphere.reg and rh.sphere.reg as well

Of course @larsoner !

I just uploaded the subject’s surf folder here so that all the files are available for morphing.

Thank you!

With this code:

import pickle
import mne
with open('sample stc object.pkl', 'rb') as fid:
    stc = pickle.load(fid)
morph = mne.compute_source_morph(stc, subjects_dir='.', verbose=True)
stc_fs = morph.apply(stc)
stc_fs.plot(initial_time=0.3)

Everything works:

I noticed that your subject name is just "anat". This sounds like it might be a generic name. One thing to know is that each FreeSurfer subject reconstruction (and mapping to/from fsaverage) is effectively unique to the T1.mgz that was used to create it. I suspect what happened here is you had one reconstruction named anat, did morphing at some point, and then replaced that anat with another, different FreeSurfer reconstructed subject also named anat. This will break things.

So the big fix I think is to make sure your FreeSurfer subjects have unique names. The small fix is to delete the morph-maps/fsaverage-anat-morph.fif and morph-maps/anat-fsaverage-morph.fif in your SUBJECTS_DIR.

2 Likes

Thank you very much, @larsoner ! Yes, it did work for me as well!

As you aptly described, anat was used as the subject name, a generic one to be exact, and by removing the suggested files every time morphing was computed, the issue was indeed resolved! A big thank you!

Aqil

1 Like