3dNwarpApply error: Warp dataset 'nwarp native_al_mat.aff12.1D' name is too much like a matrix text file :-?

Hi all,

I want to warp ROIs from an atlas to a native image space, which only consists of several slices covering the upper part of the brainstem. To this end, I aligned the native image to a native structural image using align_epi_anat.py resulting in a native_al+orig and a native_al_mat.aff12.1D file .
Next, I aligned the atlas space MNI template image to the structural image using @SUMA_AlignToExperiment resulting in a MNI152_T1_1mm_brain_Alnd_Exp+orig and MNI152_T1_1mm_brain_Alnd_Exp.A2E.1D files.
Finally, to warp individual ROIs from the atlas template space to native space, I want to use 3dNwarpApply with the following call:
3dNwarpApply -nwarp native_al_mat.aff12.1D -source atlas_ROI.nii -master native_image.nii -prefix ROI_in_native_space

However, when I run this command, the error: 3dNwarpApply error “Warp dataset ‘native_al_mat.aff12.1D’ name is too much like a matrix text file :-?” is thrown.

I highly appreciate your help here!

Bests,
Philipp

Hi Philipp,

It might be whining that the warp seems to be simply affine, in which case it is not really the appropriate program to use. For an affine warp, 3dAllineate should work.

  • rick

Hi Rick,

thanks for your fast response!

I followed your advice and called 3dAllineate with the following command:

3dAllineate -prefix ROI_in_native_space -base native_image.nii -source atlas_ROI.nii -twopass -cost lpa -1Dmatrix_apply native_al_mat.aff12.1D -autoweight -cmass -twobest MAX

The good news is that the program worked. The bad news is that the ROI is far off from where it should be (see image attached).

Did I miss something here?

Bests,
Philipp

It might expect the inverse of the transformation. And there should not be any actual alignment happening (so you can remove -autoweight -cmass -twobest MAX).

You also might compare with what afni_proc.py does when applying an aea.py xform matrix, as in s15.proc.FT.uber. Note that it uses “cat_matvec AEAMAT -I” to extract the inverse of that matrix before passing it to 3dAllineate to apply.

  • rick

Hi, Philipp-

It sounds like you have 2 stages of alignment (conceptually: MNI → anat; anat → EPI). You will want to concatenate these alignments, so that you have one (MNI → EPI). Each of these alignments appears to be affine, so the concatenation can be done with cat_matvec (and any inversion, if necessary, can be done on one or more component matrices in this program), and then the result will also be affine, you you would use 3dAllineate to apply it.

Note that we talk about “aligning A to B”, so we conceptualize taking a point in A’s space and figuring out where to send it in B’s space. The way AFNI warps/alignments are actually calculated are sitting at a grid point in B and figuring out where to pull data from in A. This matters in terms of order of concatenating: think about starting in your “end” space (here, EPI) and ordering your warps by which successive pulling of data (so, would be the “anat->EPI” warp, then “MNI->anat” warp).

Second note: we often use affine registration between the EPI and anatomical data from the same subject. However, when aligning data between different subjects’ anatomicals (which includes a subject brain to a standard space template), then we would typically recommend using nonlinear alignment (e.g., 3dQwarp or @SSwarper—which combines skullstripping (ss) with nonlinear warping, or @animal_warper for non-human data). That is something for you to consider. The nonlinear warps and affine transforms can still be concatenated and applied, just using different programs (actually, the 3dNwarpApply that you were using).

For the present data, you could do the following:


cat_matvec \
     -ONELINE \
     mat_MNI_to_anat.aff12.1D mat_anat_to_EPI.aff12.1D > mat_MNI_to_EPI.aff12.1D

and, if above you actually had mat_anat_to_MNI.aff12.1D, say, you could use the following to invert that:


cat_matvec \
    -ONELINE \
    mat_anat_to_MNI.aff12.1D -I mat_anat_to_EPI.aff12.1D > mat_MNI_to_EPI.aff12.1D

… and I think the “-ONELINE” is useful for formatting the output dset to use later.

Then, use 3dAllineate:


3dAllineate \
   -1Dmatrix_apply mat_MNI_to_EPI.aff12.1D \
   -source DSET_ATLAS_in_MNI   \
   -prefix  DSET_ATLAS_in_EPI \
   -final NN \
   -master DSET_EPI

… where “-master DSET_EPI” sets the appropriate grid for the output dset, and “-final NN” tells the program to use nearest neighbor interpolation for the final output creation, so that integers stay integer.

Furthermore, if there is a labeltable associated with the dset, you can run the following to copy its header info along (while also telling AFNI to use an ROI-based colorbar when overlaying it in the GUI):


         3drefit -copytables DSET_ATLAS_in_MNI  DSET_ATLAS_in_EPI
         3drefit -cmap INT_CMAP DSET_ATLAS_in_EPI

Please let me know how that goes, esp. verifying in the GUI that I have put things in the correct order here…
–pt

Hi rick and ptaylor,

thank you very much for your valuable input! I can follow the idea of having eventually a “stack” of transformation matrices that can be used to warp an atlas ROI in MNI space via an anatomical image to EPI (native) space. Regarding the registration between an anatomical and a template brain I was satisfied with running @SUMA_AlignToExperiment and using the following call that transformed the MNI brain into anat space:

@SUMA_AlignToExperiment -exp_anat anat -surf_anat MNI -wd -align_centers

However, the transformation matrix it gives me, mat_MNI_to_anat…A2E.1D, can apparently not be read by cat_matvec.

As a side note, I have to invert the mat_EPI_to_anat.aff12.1D, as I registered the EPI to the anatomical image using the following call:

align_epi_anat.py -overwrite -dset1 native_epi -dset2 anat+orig. -dset1to2 -partial_axial -dset1_strip None -dset2_strip None -edge -cost lpa

I tried using your command to invert said matrix and concatenate them in a new file:

cat_matvec -ONELINE mat_MNI_to_anat.A2E.1D mat_epi_to_anat.aff12.1D -I mat_anat_to_epi.aff12.1D

it throws the following error:
** ERROR: mri_read_double_ascii: couldn’t open file mat_MNI_to_anat.A2E.1D
** ERROR: THD_read_dvecmat: can’t read matrix+vector from ‘mat_MNI_to_anat.A2E.1D’
** FATAL ERROR: Can’t read matrix from ‘mat_MNI_to_anat.A2E.1D’
** Program compile date = Nov 21 2021

The contents of the file look like this:
1.08317 -0.00756723 0.0145874 3.15473 0.0522929 1.04778 -0.459598 45.9083 -0.0103524 0.49026 1.08279 30.4149

Please advise.

Bests,
Philipp

Howdy-

I ran:


@SUMA_AlignToExperiment \
    -exp_anat FT_anat+orig. \
    -surf_anat ~/REF_TEMPLATES/MNI_avg152T1+tlrc. \
    -wd \
    -align_centers

… and got “MNI_avg152T1_Alnd_Exp.A2E.1D” (-> which is the mat_MNI_to_anat).

And I ran:


align_epi_anat.py \
    -dset1 short_epi+orig. \
    -dset2 FT_anat+orig. \
    -dset1to2 \
    -partial_axial \
    -dset1_strip None \
    -dset2_strip None \
    -edge \
    -cost lpa

… getting “short_epi_al_mat.aff12.1D” (-> mat_EPI_to_anat). Note that in this step, the whole EPI time series was selected—is that really what you want? Normally we use 3dvolreg for across-EPI motion correction, and just select a single volume from the EPI time series to align to the anatomical. (It will take a much longer time to have the whole EPI aligned in the way currently coded here; in your case, it sounds like you should already have a processed/motion-corrected EPI time series, anyways?)

I can then run:


cat_matvec \
    -ONELINE \
    MNI_avg152T1_Alnd_Exp.A2E.1D \
    short_epi_al_mat.aff12.1D -I \
    > mat_MNI_to_EPI.aff12.1D

… with no error. (Note the use of “>” to redirect the output—that was missing from your command, above, and would create a “missing” file error, but it would be a different filename than what you had input.)

Note that I don’t think I would use @SUMA_AlignToExperiment in this way, if I were wanting to bring a volumetric ROI dataset from one space to another. It should be OK, but I would probably use 3dAllineate if I only wanted affine, and (as noted above) a nonlinear program for closer alignment.

–pt

Hi,

thanks again for your patience and thorough support! In the end it turned out there was a typo in the cat_matvec command. It works now and the transformed atlas ROI looks beautiful in native space :slight_smile:

[i]"And I ran:

align_epi_anat.py
-dset1 short_epi+orig.
-dset2 FT_anat+orig.
-dset1to2
-partial_axial
-dset1_strip None
-dset2_strip None
-edge
-cost lpa

… getting “short_epi_al_mat.aff12.1D” (-> mat_EPI_to_anat). Note that in this step, the whole EPI time series was selected—is that really what you want? Normally we use 3dvolreg for across-EPI motion correction, and just select a single volume from the EPI time series to align to the anatomical. (It will take a much longer time to have the whole EPI aligned in the way currently coded here; in your case, it sounds like you should already have a processed/motion-corrected EPI time series, anyways?) "[/i]

Regarding your comment above, I do not really have an EPI time series. I “only” have one 0.4^3mm native image (covering a part of the brainstem) that looks very similar to an EPI image. I used align_epi_anat.py because it seems to be a very flexible tool that can be used for many non-T1 images.

“Note that I don’t think I would use @SUMA_AlignToExperiment in this way, if I were wanting to bring a volumetric ROI dataset from one space to another. It should be OK, but I would probably use 3dAllineate if I only wanted affine, and (as noted above) a nonlinear program for closer alignment.”

Do I understand it correctly that 3dAllineate is a more parsimonious approach compared to @SUMA_AlignToExperiment? Would it look like this:

3dAllineate -prefix anatT1_to_MNI_brain -base MNI -source anat -twopass -cost lpa -1Dmatrix_save anatT1_to_MNI.aff12.1D -autoweight -fineblur 3 -cmass -twobest MAX -source_automask

Finally, out of curiousity, in what situation would it have been appropriate to use 3dNwarpApply? It seems it was not necessary to use it at any step after all.

Thanks again and bests,
Philipp

Hi, Philipp-

Great, glad that was sorted for this case.

Re. the 3dAllineate command: I am just more familiar with 3dAllineate options, and there is probably more detailed control over alignment. You command looks reasonable/well-formed to me, though it is important to verify all alignment visually, to be sure. (Though, is @SUMA_Align* worked for you in this case, okeyoke.)

Re. using nonlinear vs affine: the general recommendation would be to use nonlinear whenever you are alignment brains from different subjects. Here are some notes/images about the difference of alignment (between a subject and a template):
https://youtu.be/PaZinetFKGY?list=PL_CD549H9kgqJ1GDXAs1BWkgEimAHZeNX&t=1768
… and here are more general alignment videos in the AFNI Bootcamp series:
https://www.youtube.com/watch?v=PaZinetFKGY&list=PL_CD549H9kgqJ1GDXAs1BWkgEimAHZeNX&index=1
Here, 3dNwarpApply would note be applicable, because you were only applying linear affine fits. If you had used 3dQwarp, @SSwarper, auto_warp.py, or @animal_warper, and therefore generated nonlinear _WARP dataset files, then 3dNwarpApply might come to bear.

–pt

Thank you for your answer and the background information.

I’ll watch these videos. After taking a closer look at the registration, the anat–>MNI transformation underperforms quite a bit using 3dAllineate. I may switch to 3dQwarp and 3dNwarpApply to see whether this improves things. I would open a new thread though as this topic has been dealt with successfully :slight_smile:

Bests,
Philipp

Hi, Philipp-

That kind of result for affine allignment isn’t so surprising–happy to talk more about nonlinear alignment if you have questions.

Integrating nonlinear alignment with @SSwarper and full FMRI processing with afni_proc.py is probably the most recommended way to go. If you want your final subject data in subject anatomical space for some reason (which is perfectly reasonable!), you can still use afni_proc.py and @SSwarper, just not using the results of the latter in the former directly.

Just let us know what location for “final” data makes most sense, and we can discuss options for processing.

-pt

Hi,

I would like to discuss options for nonlinear processing and opened another thread called “Nonlinear registration for hires slab” with more detailed information about my idea and data.

Bests,
Philipp