BUG: Fix tensor reorientation with displacement fields#1871
Conversation
FSL requires radiological orientation of bvecs / tensors, regardless of image orientation. This causes a problem for "NEUROLOGICAL" images (positive determinant of direction matrix), because the tensors are then not transformed to physical space by the direction matrix. On import, we fix this by applying a reflection in x, and we do the same on export back to FSL tensor format.
|
Added two commands to ImageMath: FSLTensorToITK <input 4D tensor> FSL requires radiological orientation of bvecs / tensors, regardless On import, we fix this by applying a reflection in x, and we do the same |
|
I think this PR may fix a longstanding issue #1137 - different behavior of ReorientTensorImage when given affine vs displacement fields. A few others have brought up similar issues, eg #1461. I think the divergence between affine / displacement fields were that the affine transform was being corrected for the direction matrix, but the displacement field transform was not. I was confused by the In this PR, I've tried to simplify things by rebasing the tensors to physical space (rather than modifying the transform), then applying the reorientation as before, then rebasing back to voxel space for output. In short: reorientation with a displacement field was incorrect if the fixed image (into which the tensors are resampled by antsApplyTransforms) has a non-identity transform. The resampling itself is not affected; so tensor FA, MD etc are correct. |
|
I think this is close to ready. There's still a systematic difference between mat and warp that is bigger than I'd like
this is "yawToYawRotated" in https://github.com/cookpa/antsDTOrientationTests. The offset might be because the warp field is sampled coarsely (3mm). I'll investigate further. Despite this, the major errors look to be resolved. I don't know how I didn't see these before. Lots of layers of confusion including the radiological / neurological display thing, and changing basis of the tensors (before #678), and limited scope of the bug. The three conditions for wrong results are:
Merely rebasing the tensors into another image space with antsApplyTransforms was fine after #678. |
|
I did some more digging, example scripts here https://github.com/cookpa/itkTensorReorientation The Jacobian estimation in the displacement field transform systematically underestimates rotation if the angle is large. When tested using rotations converted with TransformToDisplacementField, the estimated rotation is pretty good in the range 0-15 degrees, but by 30 degrees, it is consistently 5-6 degrees off. I'm going to update the code to use a composite transform - this way large rigid rotations can be more accurately preserved. |

There was a lot of unused code in the PPD filter, and it was not consistent about how it expected the input tensors to be based - it seems it corrected for the header orientation with affine transforms, but not with displacement fields. A comment suggested this was intentional, but it produces wrong results if the resampled tensor image does not have an identity header transform.
I've simplified the code in this PR.
Tensors should be stored in voxel orientation. In antsApplyTransforms, they are reoriented correctly into the voxel orientation of the reference space (#678). In the new PPD filter, the tensors are rebased into physical orientation, the rotation from the transform is applied, then they are rebased onto the voxel orientation.
My motivation for getting back into this issue is the forthcoming BIDS extension proposal for dMRI derivatives. I plan to eventually do all the reorientation in
antsApplyTransforms, but first I wanted to get the existing workflow correct.There remains the issue of how to import / export FSL tensors, these will require special handling, partly because of different NIFTI storage conventions, but also the tensor orientation in FSL has an x-axis flip compared to the ITK direction matrix, if the header transform has a positive determinant. This will require some special handling on input.