Project GLM t-map on SPM onto Freesurfer subject's cortex in native space

Hi everyone,
I would appreciate if someone could help with this:

Summary of what happened:

I analyzed my fMRI on SPM with a classical pipeline, including co-registration of the anatomical image to the functional images. The final output I am interested in is the t-map resulting from the GLM. I wish to plot these maps to the cortical surface which is generated by Freesurfer, as I need to compare this with another imaging modality (fNIRS). Thus, I need to get the t-map back to the native space (not the BOLD co-registered one). Is there a way to do it without calculating manually the transformation matrix and applying it to the t-map?

Command used (and if a helper script was used, a link to the helper script or the command generated):

SPM co-registration
fMRI model specification and estimation (GLM)
recon-all (Freesurfer)


Freesurfer 6.0.0

Environment (Docker, Singularity, custom installation):

Custom installation

Screenshots / relevant information:

The Freesurfer cortex was imported on Brainstorm for the fNIRS analysis. The final goal is to be able to plot the fMRI t-map onto the same cortex in the native space.

Thank you in advance!

Giulia Rocco

Hi @Giulia_Rocco,

Does SPM not output the T1-to-standard transformation matrix? You can just apply the inverse transform to your t-map.


Hi @Steven,
Thank you for your answer. I am running SPM on a custom script in batch mode, and for some reason the matrix is not displayed in the Graphics window. However, I believe this might be stored in the headers of the nifti file.
I checked the anatomical image file, importing it into Matlab with the command ‘nifti’ and there are two 4 x 4 arrays called ‘mat’ and ‘mat0’ with a respective label variable called ‘Aligned’ (for ‘mat’) and ‘Scanner’ (for ‘mat0’). So I think I found what I was looking for, thanks!

Giulia Rocco

Not sure if it helps but you can save the coregistraton matrix computed by SPM by using the batch and creating dependencies between modules.

  • BasicIO → Variable Input/Ouput → Save variables

Then use the dependency button to specify what output from what previous module in your batch you want to save.

The problem with this is that it forces to rerun things

So an alternative would to be to let Freesurfer take care of the registration back to native space.

I think there are pointers on how to do it in there but be VERY careful: the stuff described there is VERY VERY old and more recent versions of Freesurfer may have different or better ways of doing this.

Hi @Remi-Gau ,
Thank you a lot for your help.

  • I was reading the Freesurfer registration, but I am not sure it’s feasible in my case as the core part of my analysis is the cerebellum. I am using a surface called cortex_cereb which is reconstructed by Brainstorm creating an isosurface of the cerebellum from aseg.

  • It could be useful to save the variable. However, how would apply the inverse of the transformation matrix to the t-maps? I checked and the co-registration module always requires images as input (providing they are aligned), not a transformation matrix. I was trying to apply linear algebra in the header of the nifti file without reslicing the image, but the result is not well aligned. To be more explicit, as I was reading in an old thread if I want to map voxels from image 2 to image 1:

inv(M1) * inv(R) * M2

with M1 as matrix image 1 to world space, R as rotation and translation to align with image 2, and M2 as image 2 to world space.
For example, after co-registering anatomical image to BOLD, the matrix I will find in the nifti header is inv(M1) * inv(R) * M2? @Steven when you said to apply the inverse, did you mean the inverse of the whole expression?

Thanks everyone!

You can use the reorient images module: SPM → utils → reorient images

This should help you generate a script to do this.

  • load the M variable from the matrix saved during coregistration,
  • pass its inverse inv(M) in the reorientiation matrix of this module
  • pass your t map as image to reorient

Hopefully this should do the trick.

Hi @Remi-Gau,
Thank you for your suggestion. Unfortunately, it did not work. There is a problem with the transformation matrix saved from the co-registration. However, with the transformation matrix estimated with this code it seems to work:

anat = spm_vol(T1_filename);
nii = spm_vol(BOLD_filename);

x = spm_coreg(anat, nii); %Co-registration of the T1 to the functional image (estimate)
M = spm_matrix(x); %Calculate transformation matrix given parameters of rigid body transformation
spm_get_space(T1_filename, M * anat.mat);  % Apply the transformation matrix to the voxel-to-world mapping

spm_get_space(any_filename, inv(M) * nii.mat); %Apply the inverse of the transformation matrix to any BOLD-aligned image I want to register to the anatomical one

The value of the transformation matrix estimated this way is different from the one saved from the co-registration module. Also, the nifti headers files looked different from the ones obtained by loading the volumes with the nifty package (instead of spm_vol here). I am not sure why they differ, though.
I commented the code above in case it could be useful for someone else.
Thank you again for your help!

yeah I know it can be done just via batching but as usual as I was building a full example I must have missed something: glad you found a solution in any case. :rocket: