How to convert between ITK transforms and Slicer transform nodes?

I am creating a scripted module for ANTs registration (wip). It is invoking a wrapped itk::ANTSRegistration. For Slicer node ↔ ITKImage conversion, I am using previously added utility functions. But I am not aware of a convenient way to convert between ITK transforms and Slicer transform nodes.

These static methods from vtkITKTransformConverter look interesting. I don’t know how to access them from Python, and whether that is even possible. I assume vtkTransforms would be usable for invoking GetTransformFromNode and SetAndObserveTransformToParent methods of vtkMRMLTransformNode.

My fallback is using existing utility functions, which will almost certainly necessitate more coding.

Are there any suggestions?

@lassoan @pieper @simonoxen

Any suggestions?

You can use transformNode = slicer.util.loadTransform(path) utility function. Internally, it uses transform storage MRML nodes, which use vtkITKTransformConverter functions. Similarly, for loading images, I would recommend to use volumeNode = slicer.util.loadVolume(path).

Important: There is a quite nice extension for ANTs registration in Slicer. It provides command-line interface and Python scripted module interface. It can execute registration in a background process (does not block the application), has comprehensive GUI for adjusting parameters, manages registration parameter sets, etc.

Having two extensions for the exact same purpose would confuse users, divide developers, and double maintenance and support costs. Therefore, in the long term, having two extensions for the same thing is actually worse than just having one. To avoid these issues, please do not create a new extension but consolidate your efforts with development and maintenance of the existing one. There are many ways to achieve this, you could add an option to choose between Elastix backends, improve the existing GUI, add a new frontend if the feature sets are impossible to merge, etc.

Thanks Andras. the purpose of this project is to make the whole ANTsX ecosystem available in the Slicer, not just the registration. This includes things like atlas building, jacobian analysis, etc…

Great, then there should be no overlap (you just save some time by not having to write an entirely new module for registration). Please add the new modules to the existing extension.

That will be something JC and Matt McCormick to decide. I believe plan is to actually leverage the antspy package as opposed to re-implement all the functionality.

It should not matter much for the extension if the ANTs binaries are from wheels or downloaded from PyPI or built locally - changes in the existing extension should be minimal.

By switching to getting ANTs from PyPI, we give up our freedom to choose how ANTs is built (you cannot easily have a debug build to do C++ troubleshooting, you cannot decide if you want VTK support, etc.) and binary compatibility is no longer guaranteed. However, using antspy would make it easier to use ANTs from Python and extension build system would be a bit simpler. Overall, switching to antspy may make sense.

Let’s hear from @jcfr, @thewtex, and @simonoxen and make a decision here.

Hi, great to hear that there’s interest in integrating more of ANTs into Slicer!

Back then I chose to go with a superbuild because I found it easier to integrate with Slicer build for all OSs; using CLIs in the background; and the capability to modify ANTs more freely.

Currently, the antspy configures ITK and ANTs projects and builds them. I found it easier to handle this directly building ANTs from superbuild.

I currently also patch ANTs to show progress of the registration from CLI module. I found this very handy for processes that take some considerable time for the user.

Adding more ANTs functionality to this current implementation should be quite easy: select which ANTs apps to build, and add them into a CLI. Then calling the CLIs from python is also easy.

However, if there’s interest in having the python wrappers directly from antspy, I could also consider migrating my antsRegistration module, which is mostly UI work allowing the user to test lots of parameters for the registration. With not so development, this would work as well with other ANTs backends.

I wonder, what are the motivations in using antspy?

Considering there probably is more development bandwidth and expertise from this new effort, I’m happy to retire my extension once this one takes over. We could probably still keep the current antsRegistration as some sort of advanced antsRegistration or so.


1 Like


Yes, we completely agree and have the same goals – we do not want to duplicate efforts and keep ants adoption easy for Slicer users.

We aim to merge the current draft Slicer extension development with @simonoxen 's excellent work. Simon made nice UI development and refinements, we certainly want to keep them when it makes sense. Also extend the functionality, as @muratmaga mentioned.

Under the hood, we are working to improve performance, portability, ease of use, maintainability, scalability, interoperability, and debuggability (both from C++ and Python). We are using much of the same code in antspy, contributing improvements to ants along the way, but these improvements mean it is neither exactly ants CLI or antspy. We are keeping the programmatic antspy interface when it makes sense. This interface is something that Nick and Brian worked hard to refine – they did an excellent job – and it is what antspy or antsr users are familiar with. We can modify or refine the graphical interface in Slicer when it makes sense.

1 Like