Make a c++ library available as a python module

Hi everybody,

While struggling with some python wrapping stuff, I realized I might not have the right strategy to make some code easily available to the ITK community especially for quick prototyping in python.

I saw there is a template for new module on the ITK github. In my case, I have a framework with a core library written and C++ and 2 higher level c++ libraries to make the features available in the ITK and VTK frameworks. The ITK library depends on some stuff in the framework (core lib, test lib) and on external dependencies. It consists of ITK transforms and their associated classes for statistical shape modelling.

Given that, it is easy to integrate the features into c++ ITK code (nothing todo apart from some cmake stuff to import the framework). But what would be your recommendation to make it easily available for people prototyping with ITK in python?

Thanks for your help!

Best Regads

2 Likes

Hi @cg2, it seems to me that you could use the standard wrapping used in external modules. See examples in any external module with wrappings. Also this one using an internal library.

If your third-party dependencies are used internally and are not in the interface this should be easy, i.e if the input of your filters are ITK images, and not a mixture of VTK, or any other kind of third-party object, you should be all set using the wrapping infrastructure of ITK (if you install them correctly with CMake for the python library to link to them correctly).

Things get more complicated if these third-party objects are in the interface (they are input for your filters). If they already have python wrappings, you might want to use numpy (or a regular python data structure) as a bridge. Assuming the third-party library has ways to get numpy arrays from their objects (usually most do, including ITK and VTK).
Create a new function in c++ which parameter is a numpy/python object (in c++) instead of a third-party class, and then internally, construct the third-party object from the numpy data, and run your regular functions from there.

My recommendation would be to not mix frameworks and go with the first option. Create an external module in ITK, include your c++ core library, and just wrap the ITK filters using your core library internally in the module (this is really easy following existing examples!). At the end of the process, users would be able to use your module with just a pip install itk-yourmodule

If you want to make them available for VTK, create a module for VTK with a similar approach (I am not familiar with the VTK infrastructure for wrapping external modules though).

Hope it helps!

2 Likes

Thanks a lot! This is helpful indead. Thanks for pointing me out the possible issues with wrapping and
a nice starting point!

1 Like

Hi,

After analysis of my module, I think I will be in a bit of trouble with the current implementation. If you have time,

I would be glad to have your feedback.

The ITK pseudo module is part of statismo, that I am currently refactoring (switch to modern c++, style, formating etc.):

Here is an example:

https://github.com/kenavolic/statismo/blob/develop/modules/ITK/examples/itkShapeModelFitting.cxx

The contribution to ITK is in the form of mesh/image transform to match a statistical model to a target mesh/image. Thus, you have a bunch of new concepts (itk::representer, itk::statisticalmodel…) that inherits from itk::Object and (unfortunately due to my refactoring) an implementation wrapper that forwards call to the base object of the core library (statismo::representer etc), and the itk transforms that takes as input the model and a target mesh/image.

To be honest, I don’t know if the current implementation is compatible with an ITK wrapping.

Thanks again for your help!

1 Like

It looks to me, first you will have to create a function with what the main function is doing (except parsing the command line and reading/writing the meshes from files). And wrap that function.

MeshType statismoShapeModelFitting(const std::string &model_name, const MeshType &input_mesh)

The MeshType is already wrapped in ITK for common PixelTypes and dimensions.
The statismo::itk::representer and such, could be wrapped as well, but maybe your python users do not really need them, as they seem internal.

Instead of a free function, you could also create a derived class from itkMeshToMeshFilter which is already wrapped

1 Like

I was actually redirecting you to an example but the core stuff is in the include module.

I guess I could in a first time just drop the wrapping of model creation because it needs the wrapping of the all the core concepts and focus on the wrapping of the fitting. Your answer made me think that we could feed the transform with a string representing the model filename instead of a model pointer. But then I realized the fitting algorithm is going to give you parameters you cannot use (you need at least to be able to draw a sample of the model with the resulting params). Thus, I guess I’ll have to try a way to wrap the transforms, the itkStatisticalModel class and the itkXXXRepresenter classes…

Thanks for your help and your quick answers! It’s on my hand now!

1 Like