Convert ROI from MNI to native space

Hi everybody,
I am a new AFNI user (so sorry in advance for a basic question)

I am trying to convert an ROI from MNI space to the subject’s native space. I looked into the 3Dwarp help but I don’t see any flags/options for this type of conversion, and I don’t have any matrix to load.
Can you please help me figuring this out?

Thank a lot in advance.

Hi-

You would do this creating a transformation between the two datasets (MNI template and subject anatomical), and then applying that transformation to the ROI dset. Between two different subject brains (like the MNI template and a person), you would probably want to use nonlinear alignment, because the structural differences are so great. Programs in AFNI for this would be 3dQwarp or @SSwarper (the latter being a program that combines skullstripping (SS) and nonlinear warping). When applying the transformation to the ROI dset of interest, you also have to be careful to apply correct interpolation for the data of interest–in this case, integer values within the ROI dset–which we would typically call “NN” = nearest neighbor interpolation.

It might be worth checking out some of the AFNI Academy videos about these concepts and relevant programs here:
for alignment/warping/transforming:
https://www.youtube.com/watch?v=PaZinetFKGY&list=PL_CD549H9kgqJ1GDXAs1BWkgEimAHZeNX
for atlas/template descriptions and info:
https://www.youtube.com/watch?v=IAjGwwrqtbk&list=PL_CD549H9kgqsb1Core6DhdCIw9vhQhQP

It might be easier to discuss setting up this particular problem, then. Some further details, like, are you running FreeSurfer on your anatomical and some other things might be useful, too.

–pt

In case it helps you or anyone in the future, I just worked on this question myself and this seemed to have worked for me:

I ran @SSwarper to transfer my native space anat into MNI. This outputs a .1D file with the warping info. From there I just ran these two lines:

invert the warp so it is MNI>native:
cat_matvec -ONELINE anatQQ.s${sub}.aff12.1D -I>warp_Matrix.1D
apply the inverted warp to the MNI ROI:
3dAllineate -1Dmatrix_apply warp_Matrix.1D -prefix ATL_tocalc -cost lpa -source_automask -master anatSS.s${sub}.nii -source ATL+tlrc

Hi, heatherb-

Thanks, and that is a good suggestion for people using @SSwarper, which is generally our currently recommended way for people to align a subject anatomical to a template, such as the MNI. However, @SSwarper includes both linear affine and nonlinear warp components, and I only see linear affine pieces included in your inverse transformation. Also, the initial question was about warping and ROI, specifically, which has the particular constraint of wanting to use an “NN” interpolant when applying the transformation (to preserve integer values in the source dset); in your example, that interpolant is not listed, so I don’t think the integer-valued nature of the input atlas dset would be preserved.

Here is a script that I would use to map ROIs to subj anat space when using @SSwarper, with the above considerations applied. It would run in the Bootcamp Dataset directory: ~/AFNI_data6/FT_analysis/Qwarp/anat_warped/, assuming that you have also added the MNI_Glasser_HCP_v1.0_LPI_2009c.nii.gz in that directory
(which could be downloaded here: https://afni.nimh.nih.gov/pub/sscc/staff/ptaylor/MNI_Glasser_HCP_v1.0_LPI_2009c.nii.gz); or any atlas on the MNI*SSW.nii.gz grid will work there.


#!/bin/tcsh

# -------------------------- input info -----------------------------

# subject anatomy, native (subject) space
set dset_anat = anatUA.FT.nii

# MNI "Glasser" atlas (on grid of MNI*SSW*nii.gz), which might need to
# be downloaded, Dear Reader.  NB: any atlas on MNI*SSW*nii.gz grid
# will work here
set dset_atl = MNI_Glasser_HCP_v1.0_LPI_2009c.nii.gz

# SSW transform pieces: affine and NL parts
set ssw_aff   = anatQQ.FT.aff12.1D
set ssw_nl    = anatQQ.FT_WARP.nii

# ------------------------ outputs to be made ---------------------------
# prefix of output warp: could be made using a ${subj} variable
set ssw_full_inv = anatQQ.FT_full_INVWARP.nii.gz

# ... and to be created, in subj anat space
set dset_atl_subj = mni_glass_in_FT.nii.gz

# ----------------------------------------------------------------------

# create full inv warp: (aff + nl)^{-1}
3dNwarpCat                                  \
    -iwarp                                  \
    -warp1  "${ssw_nl}"                     \
    -warp2  "${ssw_aff}"                    \
    -prefix "${ssw_full_inv}"

# apply full inv warp, with NN interpolant to preserve ints
3dNwarpApply                                                  \
    -prefix  "${dset_atl_subj}"                               \
    -nwarp   "${ssw_full_inv}"                                \
    -ainterp  NN                                              \
    -source  "${dset_atl}"                                    \
    -master  "${dset_anat}"

# bonus nicety: attach any labletables/atlas points, as well as have
# it open a nice "ROI-like" colorbar in GUI when overlaid
3drefit -copytables "${dset_atl}"  "${dset_atl_subj}"
3drefit -cmap INT_CMAP             "${dset_atl_subj}"

All the inputs and outputs are listed at the top of the script. I called the script “do_inv_ssw_roi.tcsh”, and it can be run in the Bootcamp data directory like:


tcsh do_inv_ssw_roi.tcsh

It produced the ROIs as desired, see the attached image, which shows even the labels are attached again successfully.

Yet another consideration might be applying “modal smoothing” to the ROIs after warping like this: basically, because we are mapping one discrete grid to another, some odd edge things can happen, and modal smoothing might be nice to apply. But perhaps seeing how the first steps above seem would be a good place to start.

–pt

Hi, @ptaylor,

Seeing this thread, I noticed that in your script you would need to have the output from @SSwarp/3dQwarp before hand, correct?

i.e., 3dNwarpCat just creates the inverted warp from that you already have.

I haven't used 3dQwarp (other than "indirectly" in my preprocessing generated by afni_proc.py). I was wondering... Because in my case I'm using a skull-stripped image, I would have to run 3dQwarp. But I am not sure how to apply it. Say I have sub-01_ss_anat+orig, and an MNI_template...

Would this do...?

3dQwarp
-base MNI_template
-source sub-01_ss_anat+orig
-iwarp
-prefix qwarp

Or how would it work?

Thank you!

Howdy-

Perhaps could you please describe what you want to do? And what state is your data in?

For example, did you use nonlinear warping in afni_proc.py, but you didn't run @SSwarper itself ahead of time (instead, using what afni_proc.py would use for nonlinear warping internally, which would be auto_warp.py, which is a different wrapper for 3dQwarp)?

And if you have run afni_proc.py, it would help to see that command, too, just to be more certain.

--pt

Sorry, I'm commenting on this thread because it's just about what I want to do: convert ROIs that are in MNI space to each of my subjects' individual space.

In my preprocessing I didn't run any alignment to MNI template. Just volreg to align anat to epi:

afni_proc.py                                                                       \
    -subj_id sub-00                                                                \
    -copy_anat                                                                     \
    -anat_has_skull yes                                                            \
    -dsets                                                                         \
    sub-00/func/sub-00_task-LexDec_acq-epfid2d188_dir-COL_run-1_echo-1_bold.nii.gz \
    sub-00/func/sub-00_task-LexDec_acq-epfid2d188_dir-COL_run-2_echo-1_bold.nii.gz \
    sub-00/func/sub-00_task-LexDec_acq-epfid2d188_dir-COL_run-3_echo-1_bold.nii.gz \
    sub-00/func/sub-00_task-LexDec_acq-epfid2d188_dir-COL_run-4_echo-1_bold.nii.gz \
    sub-00/func/sub-00_task-LexDec_acq-epfid2d188_dir-COL_run-5_echo-1_bold.nii.gz \
    sub-00/func/sub-00_task-LexDec_acq-epfid2d188_dir-COL_run-6_echo-1_bold.nii.gz \
    -blocks tshift align volreg mask blur scale                                    \
    -tcat_remove_first_trs 6                                                       \
    -align_opts_aea -cost lpc+ZZ                                                   \
    -giant_move                                                                    \
    -volreg_align_to MIN_OUTLIER                                                   \
    -volreg_align_e2a                                                              \
    -volreg_compute_tsnr yes                                                       \
    -blur_size 4.0

So any 1D matrix I have is from the e2a transform.

That's why I guessed I need to run 3dQwarp.

Thank you for your help!

OK, indeed, you haven't used the "tlrc" block here, so there is no alignment to standard space here. The final space is the subject anatomical. And I guess you don't want to rerun this with an updated afni_proc.py command, to include the full nonlinear alignment there? It will lead to less extra blur added, because afni_proc.py's processing will concatenate all transforms before applying them---reducing the number of regridding operations during processing.

Sidenote: if you add the "regress" block to your list of -blocks ..---even if you don't care any regression modeling---you will get the lovely QC HTML:

It is certainly possible to run 3dQwarp here to estimate your warp to standard space.

  • I would probably add -allineate, for the initial alignment and possibly add -allopt '-cost lpa+ZZ', to specify a nice cost function for similar-contrast datasets.
  • -pblur is likely useful here:
     Use progressive blurring; that is, for larger patch sizes,
                 the amount of blurring is larger. The general idea is to
                 avoid trying to match finer details when the patch size
                 and incremental warps are coarse. When '-blur' is used
                 as well, it sets a minimum amount of blurring that will
                 be used. 
    

--pt

Exactly. The thing is I already ran the preprocessing on all subjects, and I want to run my analyses on the native space. If I can just do the normalization to get the matrix, I would prefer that over rerunning the whole preprocessing (I know, in the future I'll save time and just do it all in one :sweat_smile:).

Sidenote noted down, thanks! :slightly_smiling_face:

And thank you also for the extra tips for 3dQwarp. I tested it on one subject with the additional arguments you provided and it seems to work perfectly.

All the best,

Abraham

Hi, Abraham-

Cool, glad that is working for creating the warp to standard space. Note that the warp should be a full *_WARP* file---that is, that command creates a full volumetric dataset. The affine matrix that is there was created by the preliminary (internal) 3dAllineate call.

In terms of applying the warp, note that (from the 3dQwarp help):

   ** PLEASE NOTE that if you use the '-allineate' option in 3dQwarp, to   **
   ** do the 3dAllineate step inside 3dQwarp, then you do NOT catenate     **
   ** the affine and nonlinear warps as in the 3dNwarpApply example above, **
   ** since the output nonlinear warp will ALREADY have be catenated with  **
   ** the affine warp -- this output warp is the transformation directly   **
   ** between the '-source' and '-base' datasets (as is reasonable IZHO).  **

That is, you only need to apply the *_WARP* and *_INVWARP* dsets.

Also note that when you apply the warp to an ROI dataset, you will likely want to preserve integer values when you warp. To do so with 3dNwarpApply, you would use this option:

 -ainterp jjj = This option lets you specify a different interpolation mode
                for the data than might be used for the warp.
                ++ In particular, '-ainterp NN' would be most logical for
                   atlas datasets, where the data values being mapped are
                   integer labels.

--> i.e., -ainterp NN.

Note further: many AFNI-distributed atlases have string labels attached to ROIs. You can re-attach those to your warped ROI dataset. Consider the original ROI dset "DSET_ROI_ORIG" and the warped one "DSET_ROI_WRPD". Then:

# copy over labeltables and/or atlas_points
3drefit -copytables  DSET_ROI_ORIG  DSET_ROI_WRPD
# copy over part of header so ROI-based colormap will be used
# by default in AFNI GUI:
3drefit -cmap INT_CMAP DSET_ROI_WRPD

--pt

Paul's recommendations will work fine. Just for reference, there are several ways to go from template space to native space, depending on how the transformation was computed. Consider the options presented on slides 35-38 presented here:

https://afni.nimh.nih.gov/pub/dist/edu/latest/afni11_roi/afni11_roi.pdf

Aah so, I would just need to do the 3dNwarpApply?

For more context, I ran:

3dQwarp                                  \
-base MNI_template                       \
-source sub-01_ss_anat+orig              \
-iwarp                                   \
-allineate                               \
-pblur                                   \
-prefix qwp                              \

And got the yellow output:

imagen

Then, I would run:

3dNwarpApply                        \
-prefix rois_in_sub-01              \
-nwarp qwp_WARPINV+tlrc             \
-ainterp NN                         \
-source MNI_Glasser_HCP_v1.0.nii.gz \
-master sub-01_ss_anat+orig

Is that correct?

Thanks again!

Hi, Abraham-

That looks correct to me, yes.

I would just follow that up with:

3drefit -copytables  MNI_Glasser_HCP_v1.0.nii.gz  rois_in_sub-01+tlrc.HEAD
3drefit -cmap INT_CMAP rois_in_sub-01+tlrc.HEAD

You can verify in the GUI that all went well by clicking around, too.

--pt

Beautiful, it works perfectly :innocent:

Thank you so much!!

Ah, music to my eyes!

--pt