ANTsPy: to_nibabel() produces wrong transforms
While using transforms on the MNI152 template I noticed that the output of to_nibabel() was flipped along the vertical plane. While investigating the issue, I noticed, that this is caused by a wrong extraction of the q-form parameters (direction, origin) from ITK.
ants_mni = ants.image_read('./MNI152.nii.gz')
nii_mni = nib.load('./MNI152.nii.gz')
ants_mni = ants_mni.to_nibabel()
print(ants_mni.get_qform())
print(nii_mni.get_qform())
results in:
[[ 2. 0. 0. -90.]
[ 0. -2. 0. 126.]
[ 0. 0. 2. -72.]
[ 0. 0. 0. 1.]]
[[ -2. 0. 0. 90.]
[ 0. 2. 0. -126.]
[ 0. 0. 2. -72.]
[ 0. 0. 0. 1.]]
Using the ITK internal functions for exporting to nifti file format, everything works as expected:
ants_mni = ants.image_read('./MNI152.nii.gz')
ants.image_write(ants_mni, './ANTS_MNI152.nii.gz')
ants_nii = nib.load('./ANTS_MNI152.nii.gz')
nii_mni = nib.load('./MNI152.nii.gz')
print(ants_nii.get_qform())
print(nii_mni.get_qform())
[[ -2. 0. 0. 90.]
[ 0. 2. 0. -126.]
[ 0. 0. 2. -72.]
[ 0. 0. 0. 1.]]
[[ -2. 0. 0. 90.]
[ 0. 2. 0. -126.]
[ 0. 0. 2. -72.]
[ 0. 0. 0. 1.]]
Although this could be used a a quick work around, like in the from_nibabel() implementation, a Nifti/Nibabel class export, should no rely on using hard-drive exports, when all the necessary information could be retrieved while loading the file initially.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 26 (15 by maintainers)
ITK uses LPS coordinates and NIFTI RAS. This is handled in the I/O, when ITK converts qform into a direction cosine matrix or writes a cosine matrix back out as a qform.
https://github.com/InsightSoftwareConsortium/ITK/blob/master/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx
See methods
SetImageIOOrientationFromNIfTI
andSetNIfTIOrientationFromImageIO
.According to this page
https://nipy.org/nibabel/coordinate_systems.html
NiBabel always wants RAS coordinates so I think it should be safe to apply the same conversion steps in the
to_nibabel
andfrom_nibabel
functions.Some more on this:
https://itk.org/Doxygen/html/classitk_1_1ImageBase.html#a23ebc76de3b60bb1eeabf66cd4dabc48
This is the base ITK class that handles voxel to physical space conversion. It references this page
https://itk.org/Wiki/Proposals:Orientation#Some_notes_on_the_DICOM_convention_and_current_ITK_usage
consider https://github.com/ANTsX/ANTsPy/commit/1e73b82fd23a9c39d80918739991da41f290cd9d
thx - i am leaving this open until a test is added to help prevent this from coming up in the future.
This issue is not nibabel related, since the qform is saved within the nifti header and should be parsed the same way in all implementations. I checked the values within SPM and MRIcroN and they are the same as the nibabel output, so there has to be an issue by extracting the values via the ReadImageInformation().
As reading and writing through ITK methods results in correct qforms, my guess is that ITK stores the quatern_b, quatern_c and quatern_d values from the header as well to correct the directions.