Inconsistent qform /sform on nifti image


#1

Hi all,

I’ve recently upgraded MRtrix to the last available version (3.0_RC3-9-g8cef8321). In order to start testing the commands newest version, I ran some of them (for example mrinfo) on images that I’ve obtained with an older version of MRtrix (mrtrix_version: 0.3.15-482-g5159ea35) but, for some subjects, the following message appeared:
[WARNING] qform and sform are inconsistent in NIfTI image "dwi_raw.nii" - using qform

I read this topic and I checked what fslhd reports:

qform_name Scanner Anat
qform_code 1
qto_xyz:1 -0.932456 -0.038162 0.285776 121.982002
qto_xyz:2 0.038914 -0.936672 0.019370 156.352997
qto_xyz:3 0.088980 0.009728 2.986296 -38.749401
qto_xyz:4 0.000000 0.000000 0.000000 1.000000
qform_xorient Right-to-Left
qform_yorient Anterior-to-Posterior
qform_zorient Inferior-to-Superior
sform_name Scanner Anat
sform_code 1
sto_xyz:1 -0.932456 -0.038167 0.285776 121.982002
sto_xyz:2 0.038911 -0.936672 0.019369 156.352997
sto_xyz:3 0.088980 0.009728 2.986297 -38.749401
sto_xyz:4 0.000000 0.000000 0.000000 1.000000
sform_xorient Right-to-Left
sform_yorient Anterior-to-Posterior
sform_zorient Inferior-to-Superior

Should I see the inconsistency reflected there?

So taking in mind that doesn’t happen to all my subjects, how can this inconsistency affect an output file of any newest version command? how can I fix it?

Thanks.
Cheers
Stella


#2

You can get the full precision transformation that is used with mrinfo image.nii -transform. You can set the MRtrix config file option NIfTIUseSform: true to check whether there is a significant difference between sform and qform.

We made some changes to the part of the code that handles qforms (issue). These might trigger this warning.

For context, this warning is issued if the FOV corner differs between both transformations by more than 1e-3 voxels. Depending on the number of voxels, the precision you are seeing using fslhd might not be sufficient to see this difference.


#3

Hi Stella,

I have unfortunately also encountered this issue since the 3.0_RC3 tag; we had hoped we’d resolved the issue, but it seems that there are still edge cases.

For clarity, there are a few changes surrounding this terminal warning that are worth separating:

  • On NIfTI image load, if both qform and sform are flagged as present within the image, MRtrix3 will now uses the qform transform by default; in previous versions, it would automatically use the sform.

    • If only one or the other is defined, then the transform that is defined will always be used.

    • This behaviour can be reverted by setting NIfTIUseSform: true in the MRtrix3 config file. MRtrix3 will then always use the sform transform in cases where both are present.

  • If both transforms are present, then MRtrix3 will additionally compare the two transformations. If they are effectively identical, then the decision of which transform to use is effectively irrelevant. If however they differ, then MRtrix3 will present you with the warning you have observed, basically stating that there is some ambiguity about where the image should be positioned in space and telling you what decision it has made.

  • There has additionally been a small fix to how qform transforms are imported, due to numerical precision issues when converting between quaternion and matrix representations.

Given that this warning is still appearing, it’s possible that:

  • Our qform import code is not quite robust enough.

  • Our numerical tolerances between manipulation of the transformation data, and testing for equivalence between the transforms, are somehow unbalanced.

So what would help us here to find a solution that works as advertised for all use cases would be, whenever somebody encounters this warning (and believes that the warning is erroneous), if you could provide:

  • The output of fslhd

  • The output of mrinfo -transform

  • The output of mrinfo -transform, after having set NIfTIUseSform: true in the MRtrix3 configuration file.


#4

I note that the qform and sform transforms reported by fslhd match up to 4 digits. There’s still scope for the positions of the corner voxels to differ by >1e-3 voxels if the matrix is large enough – a mismatch of 1e-4 might lead to shift of 1e-2 for the position 100 voxels away. Maybe we really just need to relax the tolerance around these tests. There is a fundamental precision issue introduced by the quaternion representation, given that the components are stored as 32 bit floats, which led to the issues we’d discussed here. Given these problems, we shouldn’t be surprised to find small differences, that can sometimes get (relatively) large in edge cases, even though the transforms still fundamentally match.

It’s also worth pointing out that these tests are quite a bit more stringent than those performed by FSL commands. Also, they are warnings only, and don’t otherwise affect the operation of the commands. But I agree that we would rather not see warnings appearing for data that don’t actually have any issues as such…


#5

Hi, thanks for your responses.

Rob, please find bellow the outputs you asked:

  • fslhd reports:

      filename       dwi_raw.nii
    
      sizeof_hdr     348
      data_type      INT16
      dim0           4
      dim1           256
      dim2           256
      dim3           44
      dim4           36
      dim5           1
      dim6           1
      dim7           1
      vox_units      mm
      time_units     s
      datatype       4
      nbyper         2
      bitpix         16
      pixdim0        0.000000
      pixdim1        0.937500
      pixdim2        0.937500
      pixdim3        3.000024
      pixdim4        12.000000
      pixdim5        1.000000
      pixdim6        1.000000
      pixdim7        56266.000000
      vox_offset     352
      cal_max        0.0000
      cal_min        0.0000
      scl_slope      1.000000
      scl_inter      0.000000
      phase_dim      0
      freq_dim       0
      slice_dim      0
      slice_name     Unknown
      slice_code     0
      slice_start    0
      slice_end      0
      slice_duration 0.000000
      time_offset    0.000000
      intent         Unknown
      intent_code    0
      intent_name    
      intent_p1      0.000000
      intent_p2      0.000000
      intent_p3      0.000000
      qform_name     Scanner Anat
      qform_code     1
      qto_xyz:1      -0.932456  0.038163  0.285777  112.249336
      qto_xyz:2      0.038915  0.936672  0.019370  -82.498436
      qto_xyz:3      0.088979  -0.009727  2.986319  -36.268818
      qto_xyz:4      0.000000  0.000000  0.000000  1.000000
      qform_xorient  Right-to-Left
      qform_yorient  Posterior-to-Anterior
      qform_zorient  Inferior-to-Superior
      sform_name     Scanner Anat
      sform_code     1
      sto_xyz:1      -0.932456  0.038167  0.285778  112.249336
      sto_xyz:2      0.038911  0.936672  0.019370  -82.498436
      sto_xyz:3      0.088980  -0.009728  2.986319  -36.268818
      sto_xyz:4      0.000000  0.000000  0.000000  1.000000
      sform_xorient  Right-to-Left
      sform_yorient  Posterior-to-Anterior
      sform_zorient  Inferior-to-Superior
      file_type      NIFTI-1+
      file_code      1
      descrip        TE=91.09999847;sec=56266.0000
      aux_file       
    
  • mrinfo -transform:

      mrinfo: [WARNING] qform and sform are inconsistent in NIfTI image "dwi_raw.nii" - using qform
        0.9946199286938637  0.04070710161471539  0.09525822443832641    -125.526990460701
      -0.04150952215963574   0.9991172472381403 0.006456457338166832   -72.57506583283318
       -0.0949113113126778 -0.01037584451551273   0.9954316575413391   -13.57908254092429
                         0                    0                    0                    1
    
  • mrinfo -transform after NIfTIUseSform: true:

      mrinfo: [WARNING] qform and sform are inconsistent in NIfTI image "dwi_raw.nii" - using sform
        0.9946200688680013  0.04071180423100789  0.09525857399972487   -125.5270239710808
      -0.04150480429331461    0.999117088317871 0.006456449957573755   -72.57619369775057
       -0.0949117104212443 -0.01037630041440328   0.9954316982744912   -13.57898712903261
                         0                    0                    0                    1

#6

Yes, it looks like the y coefficient of the origin (i.e. 2nd row, last column) already differs by more than 1e-3 voxels. I think it’s a straight precision issue. Note that the origin reported by mrinfo differs from that in the NIfTI header due to MRtrix3’s internal transform reshuffle (probably best explained here), which explains why the origin reported by fslhd matches perfectly between qform and sform, but not for mrinfo. You should get the exact same results for both fslhd and mrinfo by adding the -norealign option to mrinfo – if that doesn’t match up exactly with what fslhd reports, please let us know, that shouldn’t happen.

I’ll take a look into how the qform is converted into the transformation matrix again, make sure there’s nothing we can do to improve things further. Otherwise, we might need to relax the precision of these tests. Realistically, we only need to make sure the corners correspond to the same voxels, and preferably better than that. Maybe 0.1 voxels would be sufficient for those checks…?


#7

Here I show what is reported in each case with -norealign option:

  • mrinfo -transform -norealign (NIfTIUseSform: true):

      mrinfo: [WARNING] qform and sform are inconsistent in NIfTI image "dwi_raw.nii" - using sform
       -0.9946200688680013  0.04071180423100789  0.09525857399972487    112.2493362426758
       0.04150480429331461    0.999117088317871 0.006456449957573755   -82.49843597412109
        0.0949117104212443 -0.01037630041440328   0.9954316982744912   -36.26881790161133
                         0                    0                    0                    1
    
  • mrinfo -transform -norealign (NIfTIUseSform: false):

      mrinfo: [WARNING] qform and sform are inconsistent in NIfTI image "dwi_raw.nii" - using qform
       -0.9946199286938637  0.04070710161471539  0.09525822443832641    112.2493362426758
       0.04150952215963574   0.9991172472381403 0.006456457338166832   -82.49843597412109
        0.0949113113126778 -0.01037584451551273   0.9954316575413391   -36.26881790161133
                         0                    0                    0                    1
    

Thanks!


#8

Thanks for the additional info. We’ve been discussing this issue in the meantime on GitHub (see this issue), and I think we’ve more or less got to the bottom of it. We’re now trying to figure out what to do about it, but hopefully we’ll have an acceptable solution shortly.

To recap briefly: unfortunately, that warning is correct, the transform derived from the qform can be inaccurate, and lead to appreciable differences relative to the (more stable) sform. This is the case particularly for NIfTI-1 due to the use of single-precision (32 bit) floats to store the coefficients, leading to loss of precision (in NIfTI-2, these coefficients are stored using double precision). There’s nothing we can do about this, it’s an inherent limitation of the way that information is stored in NIfTI images, and FSL produces the exact same results (although they don’t flag this with a warning like we now do).


#9

Hello

This is a quite important change, that I only realize it now.
Why to make this change ? I advocate for taking the sform as default mainly because this is the way spm choose :

The choice of 2 orientations matrix on the nifti header, was really a bad choice, that has cause a number “silent” bugs.
The bigger mistake is to not have specified a clear use of those 2 matrix (which one should be taken first) . I did not read the all nifti specification but I can see from the different sorftware uses of those orientation file that there is no common use.

Nifti format has made the multi-software user life much better but this 2 matrix makes it buggy: arggg !!!

spm made the choice to directly modify the sform when you do a coregistration to an other volume. This is a quite unique choice (since fls mrtrix ants freesurfer) have all choosen to write the coregistration in a distinc file and to never touch the nifti orientation. Both solution have pro and cons.
I thing that spm use if coherent with the fact to desing 2 orientation matrix, in this way you can have a view of the current possition of the volume (and of its previous one). if you alway keep the sform qform identical, what is then the need to define 2 orientations in the header ?

I am fine with spm use (and I use spm for coregistration) but then we have to clearly decide which orientation to take into consideration. Why this point is not clearly define in the nifti specification ? why spm is making the assumption that the sform should be taken and why mrtrix change it recently to the qform ???

Sorry for this long mail. on this old topic,


#10

Just to gives an other argument, I thing that this is also the choice of FSL to take the sform first.
for instance if you use flirt to reslice an image : with a command like
flirt -in i1 -ref i2 -out i3 -usesqform -applyxfm
then it takes the sform (as spm)


#11

I share your frustration… The problem with the old Analyze format was that there was no way to store the transform. The problem with NIfTI is that there’s two ways to store the transform… :no_mouth:

We used to rely on the sform preferentially, pretty much for the reasons you outline (my thoughts on the matter at the time here). But that changed after reading the FSL FAQ – here’s the discussion that sparked this change. Since then, we’ve had plenty of discussions about this, including finding out that the way the qform is stored inherently leads to a loss of precision. For this reason, we’re also by default relying on the sform if the qform & sform match within precision (it’s the more reliable of the two).

I’m still undecided as to which is ‘right’. But given what you say:

I reckon that might settle the argument – we should take the sform preferentially. The most important thing about conventions is that we all follow the same ones…

In the meantime, you can always set the NIfTIUseSform config file entry to 1 to force MRtrix3 to use the sform preferentially.


#12

Hi I am glad you are stil undecided, so I have a chance to convince you.
Reading the nifti’s FAQ Q19 (by Jenkinson), led me to the opposite conclusion: we should use the sform since it represent the spatial orientation in a more “coherent manner” (coherent among the subjects)

It is not clear to me why the affine part of the transformation (which change the voxel size) may pose problem (can you argue why ?), but note that this sform is used (exactly as for mni registration) when you do a DWI to anat rigid registration.

In this case it makes sens that you want to take the sform since its represente the voxel space position (relative to the anat, ie after coregistration)
As pointed by Jenkinson this way of changing the sform after a coregistration is very convienient to correct for subject motion between scan without any reslicing of the data.

the original position of the volume (as writen by the dicom) is anyway arbitrary, the important is to have the same arbitrary between the session. I do not know why but some scanner orientation are very different in some subject (making 2 subject as if they were 100 cm appart in z direction)
I never dig into it to understand why but this make me realized that it is more important to have a common referential between the subject (mni for instance) so that all subject are close.
I understand that corregistration to mni was one of the first preprocessing step in the HCP pipeline. this is more important than keeping the subject in the scanner space (since this scanner space is sometime not coherent)

All this was to point out the interest to change the sform in the nifti header (as spm does). But more important is to decide, which should be taken as default, and to be coherent with spm and fsl, let’s take the same choice : the sform !

Now the fact that the sform (after an affine coregestration to mni) can change the volume voxel size, is puzzeling, if this is not a good idea, then one should avoid the affine transformation to DWI data (but not take the qform) …


#13

We’re always open to suggestions! We may have strong opinions, but they’re not set in stone…

On this issue, I have to say I’ve been leaning towards the sform for some time. The qform is clearly lossy, both in terms of precision and its ability to represent non-rigid transformations. Your evidence that FSL does this is sufficient to warrant reverting back to that interpretation, as far as I’m concerned. But we’ll discuss this amongst ourselves to reach a democratic consensus before making any changes…

The issue around the non-rigid part of the transform is discussed here. The main issue is that the NIfTI qform can only store a rigid transform (not an issue if we default to sform), and that mrview struggles with non-rigid transforms (but that can be fixed) – so no big deal. We’re also aware of the advantages of allowing fully affine transforms.

It’s got nothing to do with the voxel size, though (not sure why that’s come up?)


#14

Do you have a bias view about FSL > SPM ? :wink:
I am a great fan of both (after mrtrix of course)…,

but anyway the issue here is due to a compatibility with SPM. It is the only software I know, that changes the sform only after the coregistration. (with the qform keeping the original space). (tel me if you know other ?)
(Sorry to repeat : ) FSL flirt function is interpreting the sform when using with the option -usesqform, … I just realise that it is a totaly bad name since they using the sform !!! (I will double check it withem …:disappointed_relieved:)

To demonstrate the problem, I select a small brain, this is very clear from those mrview screeshoot.

I show you on spm GM template, the result of the subject segemented GM (file rp1_affine) of the subject after affine coregistration to the template

reslice with flirt
flirt -in rp1_affine.nii.gz -ref TPM.nii -out rTPM_rp1 -usesqform -applyxfm

overlay rTPM_rp1 on the TPM is fine :slight_smile:


image

but now overlay the rp1_affine file

Ok I know understand what you mean by handeling the affine part …

Look now what happen if I use the qform ( NIfTIUseSform: 0)

this is the original subject space …

just to be 100% sure of my interpretation of flirt I test the same reslice but before
fslorient -copyqform2sform rp1.nii.gz
the overlay is then identical to the last one.

this make clear the point (if one would like to keep compatibility with SPM) that one should take the sform first . (and also to correct the mrview bug to correctly take the affine part of the transform, which will make the figure 2 identical to figure 1)


#15

???

Not particularly – but we do deal with FSL far more often than SPM. Primarily because it doesn’t rely on MATLAB – no license issue, and can be invoked directly and efficiently from the command line…

Yep, the way the display works assumes the transform is rigid, so things will go funny when presented with non-rigid transforms. Like I said, it’s fixable, but I’d need some time to look into it. Way too much marking to do at the moment unfortunately…

Yep, point taken. You had be convinced with your first post, no need to labour the point… :wink:


#16

Sorry to have insist, with this too long post.

Apologies also to have post a wrong information, figure 2 is wrong just because my nifti header was not consistent : the voxel dimension was “wrong”, it was corresponding to the stored qform but not to the sform.

spm, and fsl are reading the voxel dimension from the sform but mrtirx is reading it from the nifit fields pixdim (wich in my case was not coherent with the one deduce from the sform). (here again a problem induce by redundant information … )

This explain the mismatch observed in figure 2. If I correct the voxel dimensions I get the same as figure 1.

so I do not see any bug with affine transform in mrview …


#17

Good to know! But trust me, mrview does struggle with non-rigid transforms…


#18

but anyway the issue here is due to a compatibility with SPM. It is the only software I know, that changes the sform only after the coregistration. (with the qform keeping the original space). (tel me if you know other ?)

Yes, I just came across this myself…