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 \
me-lh.stc \
me-rh.stc \
myhead
This is where mymodel.fif
is your surface source space. The me-lh.stc/me-rh.stc 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.
- Get surface info coordinates out:
SurfaceMetrics -i myhead-lh.gii -coords
- 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}"
- 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}"
- 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
fi
echo "1 0 0 ${scaleX}" >> center_al.1D
echo "0 1 0 ${scaleY}" >> center_al.1D
echo "0 0 1 ${scaleZ}" >> center_al.1D
-
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
-
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.
- 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
- 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ā¦