coordinate transformation

AFNI version info (afni -ver): Version AFNI_23.1.07

Dear AFNI experts,

I tried to load a .nii file and convert to a physical size of array in python.
From what I checked, the size of the .nii file is (61,73,61) in (i,j,k) coordinate system, and the physical size of array should be (181, 217, 181).
1 <= i <= 61
1 <= j <= 73
1 <= k <= 61

-90 <= x <= 90
-90 <= y <= 126
-72 <= z <= 108

I thought there would be some matrix that maps the EPI data to a (i,j,k) coordinate system (.nii format), and if I multiply its inverse matrix to the .nii file, I could return the .nii file to the original size.

As Dr. Taylor mentioned in the post "ijk to xyz (voxel to mm) coordinate transformations", I ran the commands below and two 4*4 matrices were produced.

cat_matvec -4x4 pb08.s1.r01.scale+tlrc.::IJK_TO_DICOM_REAL           (matrix A)
       -3             0             0            90
        0            -3             0           126
        0             0             3           -72
        0             0             0             1```
cat_matvec -4x4 pb08.s1.r01.scale+tlrc.::IJK_TO_DICOM_REAL -I       (matrix B)
-0.333333             0             0            30
        0     -0.333333             0            42
        0             0      0.333333            24
        0             0             0             1

So, I multiplied the matrix A to a vector (1, 1, 1, 1), but a vector (87, 123, -69, 1) was returned.
However, I am not sure about the result I got because I think that a vector (1,1,1) should be mapped to (-90, -90, -72).

I would appreciate it if you look into my question and answer it.

Jinsu Kim

Hi, Jinsu-

Just to note that AFNI indexing is zero-based, like Python and C (unlike being one-based, as in Matlab and R). So, when you get the matrix size of a dataset, say:

3dinfo -n4 DSET

and get say 61 73 61 1 output, that means indices go from 0<=i<=60, etc.

To get the XYZ ranges, you can use:

3dinfo -extent DSET

and might see, like: -78.750000 78.750000 -78.750000 108.750000 -63.750000 83.750000 or something. Those give you ranges of physical coordinates:

-extent: The spatial extent of the dataset along R, L, A, P, I and S

Note for mapping an XYZ location to an IJK index in a dataset, there is the program @xyz_to_ijk.

In terms fo multiplying the matrix times the location, note that (0, 0, 0, 1) would be the origin coordinate point in the dset, and if you multiply that by IJK_TO_DICOM_REAL matrix, you should get: 90 126 -72 1. If you input (1,1,1,1), that should move you one voxel in from that corner in each direction, so I think it should return 87 123 -69 1, as you see.


Thank you, Dr. Taylor.

One more question,

When looking at diagonal components in matrix A, A[0,0] and A[1,1] are -3 not 3.
Does it mean the brain shape faces opposite direction in the course of changing coordinate system?
I thought both brain shape of BRIK file and .nii file face same direction.

Hi, Jinsu-

(And I appreciate the title, but I am happy with "Paul" or "pt" here.)

The diagonal contains the voxel dimension here. (There is no obliquity, so the matrix is diagonal.) The final column values essentially encode the coordinate origin location.

The sign/directionality of the voxel doesn't relate to brain orientation. It relates to the data storage coordinate orientation: if your matrix origin is on the left side of the coordinates, you have to walk rightward; if the origin is on the right side of the coordinates, you have to walk leftward. The sign of the voxel tells you which way you are stepping. Note how within each row there, the diagonal element's sign is opposite to the value on the right of the matrix. So, if you are on the rightmost side as a starting coordinate, the steps are leftward, etc.