ANTs inverse transform is inaccurate

Hi everyone,

I am using niworkflows SpatialNorm module (version 1.5.4 with ANTs ; niworkflows.interfaces.norm module - niworkflows 1.5.4+17.g45ab13e1 documentation) to register T1w images to MNI space, which works perfectly fine:

Shape and affine of my T1w (we have a non-standard resolution after preprocessing)

(112, 112, 35)

array([[ 1.99832809e+00, 7.41248727e-02, 5.69230914e-02,
-1.17586777e+02],
[-7.08075762e-02, 1.99095488e+00, -2.90909529e-01,
-1.05518166e+02],
[-4.08772230e-02, 1.74940050e-01, 3.28665876e+00,
1.41945553e+00],
[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
1.00000000e+00]])

Shape and affine of MNI

(97, 115, 97)

array([[ 2. , 0. , 0. , -96.5],
[ 0. , 2. , 0. , -132.5],
[ 0. , 0. , 2. , -78.5],
[ 0. , 0. , 0. , 1. ]])

Resulting affine of normalized T1w

array([[ 2. , 0. , -0. , -96.5],
[ 0. , 2. , -0. , -132.5],
[ 0. , 0. , 2. , -78.5],
[ 0. , 0. , 0. , 1. ]])

However, when I use the inverse transform on the mni template, I get tiny inaccuracies in the resulting affine

(112, 112, 35)

array([[ 1.99832821e+00, 7.41248578e-02, 5.69230616e-02,
-1.17586777e+02],
[-7.08075911e-02, 1.99095488e+00, -2.90909529e-01,
-1.05518166e+02],
[-4.08772454e-02, 1.74940079e-01, 3.28665900e+00,
1.41945553e+00],
[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
1.00000000e+00]])

Comparing the native and MNI->native affine

array([[False, False, False, True],
[False, True, True, True],
[False, False, False, True],
[ True, True, True, True]])

The command I used for this example (via a jupyter notebook)

! antsApplyTransforms -d 3 -i {t1_native_path} -r {mni_path} -t {xfm_T1wToMni.path} -o {t1_mni_out}

I am out of ideas on why the forward transform works, but not the inverse, and why the inaccuracies are so tiny. I’d be grateful for any help and can of course supply more information.

Best,

André

Hi,

I’m not familiar with the SpatialNorm code, but I suspect this is a result of how the image voxel to physical transform is handled in ITK. Internally, ITK describes the voxel to physical coordinate mapping as translation (defined by the image origin), rotation (derived from sform or qform), and scaling (voxel spacing). On input of a NIFTI image, it tries to get these parameters from the sform or qform. On output it tries to produce the correct output qform and sform from the internal representation.

Some more details here

There have been some recent fixes to ITK that might improve precision in the latest ANTs release. More of the computation is now done with double precision. However, it’s still written to disk as single (32-bit) float, because that’s what the NIFTI header requires.

Hi cookpa,

thanks so much for your reply & digging up my post. It is at least reassuring to see that small inaccuracies are to be expected (although it is still not clear to me why this only happens for the inverse). Maybe the wiki will enlighten me.