nipy / nitransforms

a standalone fork of nipy/nibabel#656
https://nitransforms.readthedocs.io
MIT License
28 stars 15 forks source link

FIX _is_oblique #194

Closed mvdoc closed 3 months ago

mvdoc commented 3 months ago

As described in https://github.com/nipy/nitransforms/issues/158#issuecomment-2021670484, currently _is_oblique fails to detect certain oblique dataset. The reason (and fix) is very simple. Checking the implementation in AFNI (https://github.com/afni/afni/blob/b6a9f7a21c1f3231ff09efbd861f8975ad48e525/src/thd_coords.c#L689), the minimum across the three dimensions is computed before the arccos. However, in the implementation in nitransforms the minimum was computed after the arccos, which is incorrect--the max should be computed instead.

Example with the current PR:

import numpy as np
from nitransforms.io.afni import _is_oblique, obliquity

affine = np.array([[ -0.5       ,   0.        ,   0.        ,  70.10167694],
           [  0.        ,  -0.2254388 ,  -0.44629291, -36.50873947],
           [  0.        ,   0.44629291,  -0.2254388 , -90.31697845],
           [  0.        ,   0.        ,   0.        ,   1.        ]])
print(_is_oblique(affine))
>>> True

Note that now the implementation in AFNI and nitransforms should match:

print(obliquity(affine).max()*180/np.pi)
26.800002993238653

and the output of 3dinfo:

3dinfo epi2d_run1_masked_volreg.nii.gz | grep Oblique
Data Axes Tilt:  Oblique (26.800 deg. from plumb)
oesteban commented 3 months ago

Ugh, thanks for catching this :)