Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add ConvertToITKTransform example #243

Merged

Conversation

tbirdso
Copy link
Collaborator

@tbirdso tbirdso commented Aug 28, 2023

Adds a Jupyter Notebook example demonstrating how to convert Elastix registration transform results into standard ITK transform format.

@tbirdso tbirdso requested review from thewtex and N-Dekker August 28, 2023 17:08
@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@review-notebook-app
Copy link

review-notebook-app bot commented Aug 28, 2023

View / edit / reply to this conversation on ReviewNB

dzenanz commented on 2023-08-28T17:13:48Z
----------------------------------------------------------------

Line #1.    itk_composite_transform = itk.CompositeTransform[itk.D, 2].New()

Why not use this, more convenient form:

py

comb_transform = registration_method.GetCombinationTransform()

itk_composite_transform = registration_method.ConvertToItkTransform(comb_transform)


thewtex commented on 2023-08-28T20:10:18Z
----------------------------------------------------------------

+1

@dzenanz
Copy link
Member

dzenanz commented Aug 28, 2023

comb_transform = registration_method.GetCombinationTransform()
itk_composite_transform = registration_method.ConvertToItkTransform(comb_transform)

ReviewNB messed up formatting.

@N-Dekker
Copy link
Collaborator

Thanks for this PR @tbirdso!

ConvertToItkTransform does indeed support converting a "single" transform (as returned by GetNthTransform) as well as a "combination transform" (returned by GetCombinationTransform()). It converts a combination transform to an ITK CompositeTransform (although it will only do so when the elastix combination transform did use composition, rather than addition, to combine the transforms).

@tbirdso
Copy link
Collaborator Author

tbirdso commented Aug 28, 2023

@dzenanz @N-Dekker Thanks for the notes! I will add a cell to demonstrate GetCombinationTransform.

In practice I am not getting an itk.CompositeTransform from GetCombinationTransform, but instead some apparent Advanced representation of the last transform layer. Is this expected?

For the given example:

> print(registration_method.GetCombinationTransform())
AdvancedBSplineTransform (000001B7546E2960)
  RTTI typeinfo:   class elastix::AdvancedBSplineTransform<class elastix::ElastixTemplate<class itk::Image<float,2>,class itk::Image<float,2> > >
  Reference Count: 14
  Modified Time: 121552
  Debug: Off
  Object Name: 
  Observers: 
    none

The transform cannot be cast to a itk.CompositeTransform:

> itk.CompositeTransform[itk.D,2].cast(registration_method.GetCombinationTransform())
RuntimeError                              Traceback (most recent call last)
Cell In[17], line 1
----> 1 itk.CompositeTransform[itk.D,2].cast(registration_method.GetCombinationTransform())

RuntimeError: bad cast

However, calling TransformPoint on our manually composed itk.CompositeTransform and the result of GetCombinationTransform return the same results. So, I believe that internally represent the same conceptual state.

> print(registration_method.GetCombinationTransform().TransformPoint([0,0]))
itkPointD2 ([-0.944895, 1.38383])
> print(itk_composite_transform.TransformPoint([0,0]))
itkPointD2 ([-0.944895, 1.38383])

For demonstration purposes, I believe it is easier to understand what is happening in the itk.CompositeTransform where each transform stage is clearly enumerated.

EDIT: As another (perhaps more important) distinction, I am not able to serialize the result of GetCombinationTransform, whereas I am able to write/read the manually composed itk.CompositeTransform with itk.transformwrite/itk.transformread.

> itk.transformwrite([registration_method.GetCombinationTransform()],'testout_advanced.h5',compression=False)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[16], line 1
----> 1 itk.transformwrite([registration_method.GetCombinationTransform()],'testout_advanced.h5',compression=False)

File C:\venvs\venv-itk\lib\site-packages\itk\support\extras.py:1447, in transformwrite(transforms, filename, compression)
   1445 for transform in transforms:
   1446     writer.AddTransform(transform)
-> 1447 writer.Update()

RuntimeError: C:\P\IPP\ITK-source\ITK\Modules\IO\TransformHDF5\src\itkHDF5TransformIO.cxx:462:
ITK ERROR: HDF5TransformIOTemplate(00000201B49C4B80): H5Fcreate failed
> itk.transformwrite([itk_composite_transform],'testout_composite_transform.h5',compression=False)
> itk.transformread('testout_composite_transform.h5')
[<itk.itkCompositeTransformPython.itkCompositeTransformD2; proxy of <Swig Object of type 'itkCompositeTransformD2 *' at 0x00000223FBBE81B0> >]

@dzenanz
Copy link
Member

dzenanz commented Aug 28, 2023

You need to convert the resulting thing into an ITK transform, like this:
itk_transform = registration_method.ConvertToItkTransform(registration_method.GetCombinationTransform())

@tbirdso
Copy link
Collaborator Author

tbirdso commented Aug 28, 2023

You need to convert the resulting thing into an ITK transform, like this:

Thanks @dzenanz , this is the step I was missing. I will revise the notebook to prefer this approach 👍

@dzenanz
Copy link
Member

dzenanz commented Aug 28, 2023

Since you already did the work, you could leave the current thing as an alternative approach.

Adds a Jupyter Notebook example demonstrating how to convert Elastix
registration transform results into standard ITK transform format.
@tbirdso tbirdso force-pushed the itk-composite-transform branch from b42f29a to fc53574 Compare August 28, 2023 19:02
@tbirdso
Copy link
Collaborator Author

tbirdso commented Aug 28, 2023

To avoid confusion between two approaches I've opted to remove the previous approach manually composing an itk.CompositeTransform from individual stages and instead use the expected type information for validation.

Update GitHub `actions/checkout` to v3 for linting
Copy link
Member

thewtex commented Aug 28, 2023

+1


View entire conversation on ReviewNB

Copy link
Member

@thewtex thewtex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love this!! 📖 ❤️

@tbirdso tbirdso merged commit 26cf3a1 into InsightSoftwareConsortium:main Aug 29, 2023
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.

4 participants