Closed romainVala closed 3 years ago
Hi, Romain. I agree this could be useful for some people. What is the sform_code
of your images? If it's != 0
, you can use the NiBabel reader to read your images and the sform
will be used as affine:
In [1]: import nibabel as nib
In [2]: nii = nib.load('t1.nii.gz')
In [3]: nii.get_qform()
Out[3]:
array([[ 0. , 0. , 1. , -82.6807251 ],
[ -1. , 0. , 0. , 132.33735657],
[ 0. , -1. , 0. , 102.21686554],
[ 0. , 0. , 0. , 1. ]])
In [4]: nii.get_sform()
Out[4]:
array([[ -0. , 0. , 1. , -82.6807251 ],
[ -1. , -0. , -0. , 132.33735657],
[ 0. , -1. , 0. , 102.21686554],
[ 0. , 0. , 0. , 1. ]])
In [5]: new_sform = nii.get_sform() * 2
In [6]: new_sform[3, 3] = 1
In [7]: nii.set_sform(new_sform)
In [8]: nib.save(nii, 't1_different_sform.nii.gz')
In [9]: import torchio as tio
In [10]: image = tio.ScalarImage('t1_different_sform.nii.gz', reader=tio.io._read_nibabel)
In [11]: image.affine
Out[11]:
array([[ -0. , 0. , 2. , -165.3614502 ],
[ -2. , -0. , -0. , 264.67471313],
[ 0. , -2. , 0. , 204.43373108],
[ 0. , 0. , 0. , 1. ]])
In [12]: nii.header['sform_code']
Out[12]: array(1, dtype=int16)
Would this work for you?
Hi fernando
Yes usually when both sform ans qform are set, then sform_code and qform_code are 1 (at least in my case)
Yes it does make the job, (I did not know you can ask to specifically use nibabel,)
But it works because nibable make opposit default choice than itk. (nibabel use the sform and itk the qform ! that is an example of soft inconsistency regarding the nifti affine ...)
It would be much more clear for the user, if the choice could be explicit, with something like
image tio.ScalarImage('T1.nii"; default_affine='sform')
If the reader is nibabel, it should be easy to add, I do not know itk, but I guess too
Yes it does make the job, (I did not know you can ask to specifically use nibabel,)
Good! I added the kwarg in #454, the docs are at https://torchio.readthedocs.io/data/image.html#torchio.Image. It's not used in the tutorials, though.
If the reader is nibabel, it should be easy to add, I do not know itk, but I guess too
I don't think so. ITK is less flexible, and their implementation of NIfTI might be incomplete (maybe I'm wrong). Here are some discussions that you might find interesting:
thanks for the links, I see other reason to complain about nifti
but we still have to live with it ...
About those 2 possible reader, this is something a bit confusing, ... Do you know if both are really equivalent for torchio uses ?
About those 2 possible reader, this is something a bit confusing, ... Do you know if both are really equivalent for torchio uses ?
Do you mean NiBabel vs SimpleITK? They are not totally equivalent because
qform
always (I think), NiBabel looks at the codes in the NIfTI headerok, thanks, I close the issue, since the use of nibabel reader makes the job (but in an implicit way) but It is worth to recall this affine difference between the 2 reader in the doc.
That's a good point. Thanks, Romain!
🚀 Feature
I appologies to still using SPM coregister function. They made the "bad" (but pratical in some case) choice to modify the nifti sform, leaving me with volume having to different affine in the nifti header (note that all other software, ants fsl niftireg, to write the affine transformation in a separate txt file, and so the leave the initial volume with 2 identical sform and qform
Pitch
for now It seems that torchio affine, comes from the nifti qform
Alternatives
Could we add an attribute to force the affine sform instead ?
Additional context The 2 affines in the nifti, are just the worst choice they have made for nifti, since there are no commun handeling of those 2 affine definition between software so this is the reason of silent bug, when playing with different software ...