VersorTransformation does not work correctly with CompositeTransform after version 2.0.0

My code with VersorTransform & CompositeTransform doesn’t work anymore after I updated SimpleITK from 1.2.4 to anything above 2.0.0. Diving into the issue, I found that for some reason by adding VersorTransform into a CompositeTransform, the offset for VersorTransform gets reset to zero. [Credits to Josh M. who identified the bug]

I am using a temporary fix of replacing VersorTransform with VersorRigid3DTransform, which works perfectly fine with CompositeTransform. Nevertheless, it would be really helpful if this issue can be corrected in the newer version.

import SimpleITK as sitk

rotTrans = sitk.VersorTransform((0, 1, 0), -np.pi/2)
rotTrans.SetCenter((10, 10, 10))

compositeTrans = sitk.CompositeTransform([rotTrans])

print(rotTrans)
print(compositeTrans)

And the corresponding output:

itk::simple::VersorTransform
 VersorTransform (000002048ADD4060)
   RTTI typeinfo:   class itk::VersorTransform<double>
   Reference Count: 1
   Modified Time: 670
   Debug: Off
   Object Name:
   Observers:
     none
   Matrix:
     -2.22045e-16 0 -1
     0 1 0
     1 0 -2.22045e-16
   Offset: [20, 0, 4.44089e-16]
   Center: [10, 10, 10]
   Translation: [0, 0, 0]
   Inverse:
     -2.22045e-16 0 1
     0 1 0
     -1 0 -2.22045e-16
   Singular: 0
   Versor: [ -0, -0.707107, -0, 0.707107 ]

itk::simple::CompositeTransform
 CompositeTransform (00000204FFC1F140)
   RTTI typeinfo:   class itk::CompositeTransform<double,3>
   Reference Count: 1
   Modified Time: 680
   Debug: Off
   Object Name:
   Observers:
     none
   Transforms in queue, from begin to end:
   >>>>>>>>>
   VersorTransform (000002048ADD50E0)
     RTTI typeinfo:   class itk::VersorTransform<double>
     Reference Count: 1
     Modified Time: 676
     Debug: Off
     Object Name:
     Observers:
       none
     Matrix:
       -2.22045e-16 0 -1
       0 1 0
       1 0 -2.22045e-16
     Offset: [0, 0, 0]
     Center: [10, 10, 10]
     Translation: [0, 0, 0]
     Inverse:
       -2.22045e-16 0 1
       0 1 0
       -1 0 -2.22045e-16
     Singular: 0
     Versor: [ -0, -0.707107, -0, 0.707107 ]
   End of MultiTransform.
<<<<<<<<<<
   TransformsToOptimizeFlags, begin() to end():
      1
   TransformsToOptimize in queue, from begin to end:
   End of TransformsToOptimizeQueue.
<<<<<<<<<<
   End of CompositeTransform.
<<<<<<<<<<

Hello @rraayyii,

I was not able to reproduce with the latest pre-release version of SimpleITK, so apparently already addressed and will be included in SimpleITK 2.2.0 . To install the latest pre-release:

pip install --upgrade --pre SimpleITK --find-links https://github.com/SimpleITK/SimpleITK/releases/tag/latest

Hi zivy. Thanks for replying!

I reran my code and the issue persists with 2.2.0. Can you post your output from running this code snippet?

Hello @rraayyii,

2.2.0 is not out yet so not sure which RC you are referring to. I use the latest from github, 2.2.0rc3.post4. The output I get is:

itk::simple::VersorTransform
 VersorTransform (0x7fd821423dd0)
   RTTI typeinfo:   itk::VersorTransform<double>
   Reference Count: 1
   Modified Time: 1667
   Debug: Off
   Object Name: 
   Observers: 
     none
   Matrix: 
     2.22045e-16 0 -1 
     0 1 0 
     1 0 2.22045e-16 
   Offset: [20, 0, -2.22045e-15]
   Center: [10, 10, 10]
   Translation: [0, 0, 0]
   Inverse: 
     2.22045e-16 0 1 
     0 1 0 
     -1 0 2.22045e-16 
   Singular: 0
   Versor: [ -0, -0.707107, -0, 0.707107 ]

itk::simple::CompositeTransform
 CompositeTransform (0x7fd82141d7a0)
   RTTI typeinfo:   itk::CompositeTransform<double, 3u>
   Reference Count: 1
   Modified Time: 1677
   Debug: Off
   Object Name: 
   Observers: 
     none
   Transforms in queue, from begin to end:
   >>>>>>>>>
   VersorTransform (0x7fd8214177a0)
     RTTI typeinfo:   itk::VersorTransform<double>
     Reference Count: 1
     Modified Time: 1673
     Debug: Off
     Object Name: 
     Observers: 
       none
     Matrix: 
       2.22045e-16 0 -1 
       0 1 0 
       1 0 2.22045e-16 
     Offset: [20, 0, -2.22045e-15]
     Center: [10, 10, 10]
     Translation: [0, 0, 0]
     Inverse: 
       2.22045e-16 0 1 
       0 1 0 
       -1 0 2.22045e-16 
     Singular: 0
     Versor: [ -0, -0.707107, -0, 0.707107 ]
   End of MultiTransform.
<<<<<<<<<<
   TransformsToOptimizeFlags, begin() to end(): 
      1 
   TransformsToOptimize in queue, from begin to end:
   End of TransformsToOptimizeQueue.
<<<<<<<<<<
   End of CompositeTransform.
<<<<<<<<<<


The issue reported likely was addressed in this PR for ITK:

That output is exactly what I need! I ran the installation code pip install --upgrade --pre SimpleITK --find-links https://github.com/SimpleITK/SimpleITK/releases/tag/latest but it gave me the 2.1.1.2 version. How can I get the 2.2.0rc3.post4 version?

You probably require a python wheel which is not built for nightly/latest. Try RC3:

python -m pip install --pre SimpleITK --find-links https://github.com/SimpleITK/SimpleITK/releases/tag/v2.2rc3

It raises this error:

ERROR: File "setup.py" not found for legacy project SimpleITK from https://github.com/SimpleITK/SimpleITK/releases/download/v2.2rc3/SimpleITK-2.2rc3.zip.

What Python version, OS, and architecture are you on?

I am on Windows x86-64, python 3.6

Unfortunately, Python 3.6 entered end of life on Dec 23, 2021 and is not longer supported by the Python Software Foundation, and SimpleITK is not longer creating binary distributions for the unsupported versions of Python.

Can you upgrade to a maintained version of Python?

Worked like a charm in Python 3.8. Thank you so much!

2 Likes