Skip to content

Conversation

cookpa
Copy link
Member

@cookpa cookpa commented Apr 30, 2025

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.

cookpa added 3 commits April 30, 2025 10:44
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.
@cookpa
Copy link
Member Author

cookpa commented May 2, 2025

Added two commands to ImageMath:

FSLTensorToITK <input 4D tensor>
ITKTensorToFSL <input 3D tensor>

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.

@cookpa
Copy link
Member Author

cookpa commented May 2, 2025

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 GetLocalDeformation function, which does apply the image direction - this function was called in the filter, but then the results were not used. So in the end, displacement field reorientation was being applied to tensors still in the voxel orientation.

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.

@cookpa
Copy link
Member Author

cookpa commented May 2, 2025

I think this is close to ready. There's still a systematic difference between mat and warp that is bigger than I'd like

image

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:

  1. There's a physical space rotation
  2. The transform is a displacement field
  3. The fixed image has a non-identity direction matrix.

Merely rebasing the tensors into another image space with antsApplyTransforms was fine after #678.

@cookpa
Copy link
Member Author

cookpa commented May 5, 2025

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.

@cookpa cookpa merged commit d0b7625 into master May 5, 2025
1 check passed
@cookpa cookpa deleted the fix_tensor_orient_disp branch May 5, 2025 14:09
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

Successfully merging this pull request may close these issues.

1 participant