Converting "-rotate ..." to matrix

Hello AFNI gurus,

I’m trying to convert a rotation specified by “-rotate -38I 0R 0A” to a matrix that I can apply to another dataset. I tried the following:

cat_matvec -ONELINE ‘-rotate -38.00I 0.00R 0.00A’ -I > xform_test.aff12.1D
3dAllineate -1Dmatrix_apply xform_test.aff12.1D -master t2.nii.gz -prefix test.3dAllineate.nii.gz t2.nii.gz

however, when I compare this to the following:
3drotate -rotate -38I 0R 0A -prefix test.3drotate.nii.gz t2.nii.gz

The datasets are both rotated by the same angle, but there is a shift (in the R-L direction) between the test.3dAllineate.nii.gz and test.3drotate.nii.gz datasets. Any idea what’s going on? Are 3drotate and 3dAllineate using different centers of rotation?

-Rasmus

Take a look at the transformation matrix stored in the header of the AFNI dataset created by the 3drotate command.

It looks like the transformation matrix is the same (ROTATE_MATVEC_000000 vs. ALLINEATE_MATVEC_S2B_000000), but the dataset from 3drotate specifies a ROTATE_CENTER_OLD and ROTATE_CENTER_BASE.

What I’m really trying to do is process some infant MRI data which were acquired with the head in a quite oblique orientation relative to the slices. As a result, the automatic warping to the template did not work very well. My solution to get a good mapping was to manually “nudge” the structural dataset first using the Nudge dataset plugin. Now I want to apply that nudge to the EPI, and ideally concatenate it with all the other transforms to avoid doing multiple interpolations. I was able to get the “-rotate …” string from the nudged dataset by parsing the dataset’s history note. But then I ran into the problem I mentioned when I tried to convert this to a transformation matrix.

So the question now is how best to handle the different center of rotation.

I’ve pasted the relevant header strings below.

From 3drotate:

type = float-attribute
name = ROTATE_CENTER_OLD
count = 3
2.929703 -8.199997 7.613998

type = float-attribute
name = ROTATE_CENTER_BASE
count = 3
2.929703 -8.199997 7.613998

type = float-attribute
name = ROTATE_MATVEC_000000
count = 12
0.7880108 0.6156615 0 0 -0.6156615
0.7880108 0 0 0 0
1 0

From 3dAllineate:

type = float-attribute
name = ALLINEATE_MATVEC_B2S_000000
count = 12
0.788011 -0.615661 0 0 0.615661
0.788011 0 0 0 0
1 0

type = float-attribute
name = ALLINEATE_MATVEC_S2B_000000
count = 12
0.7880111 0.6156611 -0 0 -0.6156611
0.7880111 0 0 0 -0
1 0

-Rasmus

Ignore my previous comment, I figured it out.

My commands to achieve what I want are now as follows:

If my original dataset is named t2.nii and the nudged dataset it t2_nudge.nii, then I extract the transformation matrix of that nudge as follows:

set nudge_string = 3dinfo t2.nudge.nii | tail -2 | head -1 | awk -F: '{print $NF}'
3drotate $nudge_string -prefix tmp.rot.t2 t2.nii
cat_matvec -ONELINE tmp.rot.t2+orig::ROTATE_MATVEC_000000 -I > xform.nudge.aff12.1D

In that case:
3dAllineate -1Dmatrix_apply xform_nudge.1D -prefix t2_nudged_using_matrix.nii t2.nii
returns the same result as the nudge plugin. I can now concatenate that matrix with other transformation matrices. Woohoo!

-Rasmus

Great! That looks about right to me.