Cloning a composite transform yields incorrect result

A composite transform node, such as those created by an ANTs QuickSyN registration, is not cloned correctly by the subject hierarchy node. I am using Slicer 5.8.1 on Windows 11. I have been working on taking apart and reassembling composite transforms and initially thought that my code must have errors somewhere, but I have now reproduced the problems without using any of my code.

Steps to reproduce:

  1. Add the following composite transform to the scene: https://drive.google.com/file/d/1AH9RWsc5dIsRNxah0p4COLteh7VvCZs_/view?usp=drive_link
  2. Load the MRHead image volume from SampleData.
  3. Clone the transform (e.g. by right-clicking on it in the subject hierarchy and clicking “Clone”)
  4. Alternately soft-apply the original and the cloned transformation to MRHead. Note the visible shifts in the image distortion in the slice views

This particular transform was created using the QuickSyN preset in the “General Registration (ANTs)” module, but it shouldn’t matter how it was created: a cloned MRML node should behave just like the original. I wonder if the problem might arise from the fact that the component transforms of this composite transform are both defined in the inverse (“FromParent”) direction, and maybe something in the cloning isn’t respecting or appreciating that? It looks like the actual copying in CloneSubjectHierarchyItem is done with a call to CopyContent(), which in turn involves a call to DeepCopyTransform in vtkMRMLTransformNode.cxx. I would speculate that the problem is here, but I don’t follow the C++ well enough to pinpoint the issue.

I do regard this as a relatively serious bug. I have never had cause previously to doubt the reliability of cloning a node in Slicer.

It sounds like your guess is correct about where the bug is. It would help if you could write a small self contained script to reproduce this and file an issue on github. There’s probably just a small change needed in the mrml code.

1 Like

Issue reported here: Cloning a composite transform yields incorrect result · Issue #8766 · Slicer/Slicer

That’s probably the case. Looks like the order of linear and grid transforms are swapped in cloned and original one. Transforms are exactly the same, but the order is not preserved during the cloning for some reason.

Transform 1: Displacement field:
  Grid size: 256 256 160
  Grid origin: -73.532 179.936 144.715
  Grid spacing: 0.976562 0.976562 1
  Grid orientation:
    -0.018713  -0.00334281  0.999819
    -0.992177  -0.123387  -0.0189825
    0.123428  -0.992353  -0.00100772
Transform 2: Linear
    1.00532  -0.0569842  0.0847543  -2.886
    0.0525922  0.98656  -0.067834  -13.2129
    -0.0846486  0.0587005  0.992948  -39.5675
    0  0  0  1

cloned:

Transform 1: Linear
    1.00532  -0.0569842  0.0847543  -2.886
    0.0525922  0.98656  -0.067834  -13.2129
    -0.0846486  0.0587005  0.992948  -39.5675
    0  0  0  1
Transform 2: Displacement field:
  Grid size: 256 256 160
  Grid origin: -73.532 179.936 144.715
  Grid spacing: 0.976562 0.976562 1
  Grid orientation:
    -0.018713  -0.00334281  0.999819
    -0.992177  -0.123387  -0.0189825
    0.123428  -0.992353  -0.00100772
1 Like

This is now fixed here: BUG: Fixed cloning of composite transforms by lassoan · Pull Request #8768 · Slicer/Slicer
Thanks for the quick response and fix!

Thanks, that’s what it looked like, but I was hoping that someone would be able to look at the C++ code and fix it so it worked appropriately in all cases. In this case, it was reversed, but I wasn’t sure if there were other cases where reversing the order would not be the right thing to do. It seems like Andras took a look and was able to fix it, hopefully in a general way.