Best practice to get NIML/GIfTI or NIfTI from STC


I have predefined ROIs in .dset format (AFNI). I want to extract the activity of vertices within those ROIs from an STC file in MNE, but I am unsure about the best strategy. I found a discussion on adding GIfTI output for STC here or exporting surface sources as NIfTI volume here, but still, I am not sure what is the best strategy.
Is it possible to export the source estimated file as NIML.DSET or GIfTI? Or exporting surface sources as NIfTI?
Is it better to generate volume sources to export as NIfTI or surface sources?

  • MNE version: e.g. 0.24.1
  • operating system: Windows 10


It is possible to export as GIFTI, but we haven’t yet rolled the function into MNE proper. If you give us a few days we can make that repo public with some light documentation for the process.

In the meantime, it would be a good to update to the current version of MNE - 1.2.



Hoping I managed to avoid any typos in this. We’d love to bring this into MNE proper, but there’s some debate on whether this belongs in MNE or in NiBabel.

Lots of thanks to Josh Teves (@jbteves) for the legwork on the python part of this. He wrote this “hack” for converting STC files to GIFTI that are written to disk. You can get it via pip and info is here:

Taken from the help, you can run this directly from the command line:

stc2gii_hack \
    mymodel.fif \ \ \

This is where mymodel.fif is your surface source space. The are your STC time series. And the myhead is your prefix to save the new files as.

Check the surfaces with SUMA: suma -i myhead-lh.gii, open a surface controller and load the (in this case) left hemisphere time series (myhead-lh.time.gii). You’ll notice that these are fairly grainy looking since MNE decimates the surface for (in part) faster computation. You should be able to select a node and press g to open the graph view and see your time series.

The rest of this post owes great thanks to the AFNI team as we went back and forth a bunch of times to try and get this working. Special thanks to Daniel Glen, Rick Reynolds, and Paul Taylor. These steps are needed to map those surface time series to the SUMA volumes. To start this process, you need to align the output GIFTI file from the hack to the SUMA folder corresponding file. I have this scripted, but because I thought (hoped?) it would be easier to read, I’ve filled in the details with an example left hemisphere file and added “better-ish” comments.

  1. Get surface info coordinates out:

SurfaceMetrics -i myhead-lh.gii -coords

  1. Calculate center of surface:
centerX=`3dBrickStat -mean myhead-lh.gii.coord.1D.dset[1]`
centerY=`3dBrickStat -mean myhead-lh.gii.coord.1D.dset[2]`
centerZ=`3dBrickStat -mean myhead-lh.gii.coord.1D.dset[3]`

echo "Center for your dataset: ${centerX} ${centerY} ${centerZ}"
  1. Get center of your SUMA surface:
SurfaceMetrics -i SUMA/std.60.lh.white.gii -coords
stdCenterX=`3dBrickStat -mean std.60.lh.white.gii.coord.1D.dset[1]`
stdCenterY=`3dBrickStat -mean std.60.lh.white.gii.coord.1D.dset[2]`
stdCenterZ=`3dBrickStat -mean std.60.lh.white.gii.coord.1D.dset[3]`

echo "Center for your std.60: ${stdCenterX} ${stdCenterY} ${stdCenterZ}"
  1. Calculate the distance between your surface and SUMA surface:
scaleX=`ccalc ${stdCenterX} - ${centerX}`
scaleY=`ccalc ${stdCenterY} - ${centerY}`
scaleZ=`ccalc ${stdCenterZ} - ${centerZ}`

echo "Shifting..."
echo "${scaleX} ${scaleY} ${scaleZ}"

if [ -e center_al.1D ]; then
    rm center_al.1D
echo "1 0 0 ${scaleX}" >> center_al.1D
echo "0 1 0 ${scaleY}" >> center_al.1D
echo "0 0 1 ${scaleZ}" >> center_al.1D
  1. Create a new surface on the std.60 mesh with new center
    ConvertSurface -xmat_1D center_al.1D -i myhead-lh.gii -o myhead-lh_centered.gii

  2. Now that we have centered anatomical surfaces we want to bring the time series along with it:

SurfToSurf -i_gii SUMA/std.60.lh.white.gii \
-i_gii myhead-lh_centered.gii \
-dset myhead-lh.time.gii \
-prefix std.60.
  1. Finally you should be able to visualize the time series on the higher resolution (upsampled) surfaces using something like this:
    suma -spec SUMA/std.60.MySubject_lh.spec -sv SUMA/MySubject_SurfVol.nii

Followed by opening the Surface Controller and selecting std.60.myhead-lh.time.niml.dset

  1. Repeat this process for the right hemisphere and convert your ROI to a std.60 map and you should be able to do any of the 3dROIstats or 3dmaskave steps…

Thank you, Peter!