Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Output sform matrix does not match that of the target image. #1804

Open
ckovach opened this issue Nov 4, 2024 · 8 comments
Open

Output sform matrix does not match that of the target image. #1804

ckovach opened this issue Nov 4, 2024 · 8 comments

Comments

@ckovach
Copy link

ckovach commented Nov 4, 2024

Operating system and version

Cent OS 7

CPU architecture

x86_64 (PC, Intel Mac, other Intel/AMD)

ANTs code version

ANTs Version: 2.1.0.post783-g64645 Compiled: Apr 25 2017 23:53:19

ANTs installation type

Compiled from source

Summary of the problem

I recently noticed that the sform matrix in the output NIFTI from antsRegistrationSyN.sh sometimes does not match that of the target volume, which creates some confusing discrepancies in the alignment of the images. We found this after being confounded by images that align well in voxel space but not upon being viewed in fsleyes, freeview, leadDBS, etc. I eventually traced the problem to cases in which the q_offset values in the target NIFTI are discrepant with the translation component of the sform matrix. ANTs evidently substitutes the sform matrix from the target image with one derived from qform values. I'd urge you you to preserve all the transformations from the target image as they are, so that images align regardless of the space in which a given viewer renders them.

Commands to reproduce the problem.

antsRegistrationSyN.sh -d 3 -n ${nthreads} -t b -o ${prefix} -f ${T1ind} -m ${T1tmp} 2>&1 > ${logfile}

Output of the command with verbose output.

N/A

Data to reproduce the problem

N/A

@ntustison
Copy link
Member

Have seen this?

@ckovach
Copy link
Author

ckovach commented Nov 4, 2024

Sorry - After posting this, I did find the explanation of how qform and sform transformations are handled here: https://github.com/ANTsX/ANTs/wiki/How-does-ANTs-handle-qform-and-sform-in-NIFTI-1-images%3F

This should not be an issue if I update to ANTs >= 2.3.5, correct?

@cookpa
Copy link
Member

cookpa commented Nov 4, 2024

Hi,

This is handled upstream of ANTs in ITK.

There has been an ongoing debate about how best to handle NIFTI I/O. Because of ITK's limitations on the transforms it can use (rotation + offset + voxel scaling), there are a some compromises and tradeoffs that can affect some use cases.

I went through the current code and made a flow chart of the heuristic

InsightSoftwareConsortium/ITK#4839 (comment)

This shows what is done on read. For writing images, the internal transform (rotation + offset + voxel scaling), however defined, is written to both the qform and sform, and both are set to NIFTI_XFORM_SCANNER_ANAT.

If you can post the headers of your fixed and moving images, I can probably tell how modern ANTs would handle them.

@ckovach
Copy link
Author

ckovach commented Nov 4, 2024

And thanks for the speedy reply!

@ckovach
Copy link
Author

ckovach commented Nov 4, 2024

Here is the header for the target image:

endian little
sizeof_hdr 348
data_type 0 0 0 0 0 0 0 0 0 0
db_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
extents 16384
session_error 0
regular 114
hkey_un0 0
dim0 3
dim1 256
dim2 216
dim3 170
dim4 1
dim5 1
dim6 1
dim7 1
vox_units 0 0 0 0
cal_units 0 0 0 0 0 0 0 0
unused1 0
datatype 16
bitpix 32
dim_un0 0
qfac 1
pixdim1 1
pixdim2 1
pixdim3 1
pixdim4 0.00516
pixdim5 0
pixdim6 0
pixdim7 0
vox_offset 352
funused1 1
funused2 0
funused3 6.162976e-33
cal_max 0
cal_min 0
compressed 0
verified 0
glmax 0
glmin 0
descrip 50 50 48 51 46 54 45 100 105 114 116 121 32 50 48 50 50 45 48 57 45 48 56 84 49 53 58 51 56 58 53 54 43 48 49 58 48 48 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
aux_file 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
qform_code 1
sform_code 1
quatern_b 0
quatern_c 0
quatern_d 0
qoffset_x -130.4428
qoffset_y -116.42
qoffset_z -113.4488
srow_x 1 0 0 -130.4428
srow_y 0 1 0 -116.42
srow_z 0 0 1 -71.44881
intent_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
magic 110 43 49 0

@ckovach
Copy link
Author

ckovach commented Nov 4, 2024

And from the source:

endian little
sizeof_hdr 348
data_type 0 0 0 0 0 0 0 0 0 0
db_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
extents 0
session_error 0
regular 114
hkey_un0 0
dim0 3
dim1 260
dim2 311
dim3 260
dim4 1
dim5 1
dim6 1
dim7 1
vox_units 0 0 0 0
cal_units 0 0 0 0 0 0 0 0
unused1 0
datatype 64
bitpix 64
dim_un0 0
qfac -1
pixdim1 0.7
pixdim2 0.7
pixdim3 0.7
pixdim4 0
pixdim5 0
pixdim6 0
pixdim7 0
vox_offset 352
funused1 1
funused2 0
funused3 9.403955e-38
cal_max 0
cal_min 0
compressed 0
verified 0
glmax 0
glmin 0
descrip 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
aux_file 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
qform_code 2
sform_code 1
quatern_b -0
quatern_c 1
quatern_d 0
qoffset_x 90
qoffset_y -126
qoffset_z -72
srow_x -0.7 -0 0 90
srow_y -0 0.7 -0 -126
srow_z 0 0 0.7 -72
intent_name 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
magic 110 43 49 0

@cookpa
Copy link
Member

cookpa commented Nov 4, 2024

Thanks, this looks like what ANTs 2.1 would produce, qform_code was set to 2, sform_code set to 1. The qform is always rigid so it was used on read, and then the sform would be set to the same transform.

Later versions set qform_code=1 and sform_code=0, to make clear that qform was being used. However, this made precision errors worse, so the switch was made to set qform_code=1 and sform_code=1, and use the sform where possible.

Looking at these, I think if you use a recent ANTs, the output should match the target header.

@ckovach
Copy link
Author

ckovach commented Nov 4, 2024

Perfect- many thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants