[Insight-developers] [ITK + Python] Wrapping classes proposal

Benoit Regrain benoit.regrain at creatis.insa-lyon.fr
Fri Jun 10 11:35:45 EDT 2005


Motivation:
-----------

I would like to use ITK from Python (hey, I'm a heavy VTKPython user and
I would like to have the same pleasure with ITKPyton :).
Whenever if possible I would like to keep the code written in ITKPython
as close as possible to the corresponding ITK code written in C++
(this was the case for VTK/Python versus VTK/C++, and it was really neat).

I understand the wrapping stage requires instantiating the template classes
and that it is impossible to wrap all possible instantiations of ITK
templates (for obvious combinatorial explosion reasons and also because
there can be user-defined template arguments).

Still it would be nice to be able to instantiate an ITK template
at the Python level (instead of doing the instantiation at the C++ level
and then wrapping the code). If this feature is not provided, ITKPython
scripts will not be able to define new types on the fly (think of an
instantiation produced by user through GUIs or simple prototyping).

Ideally, I would like to be able to write ITKPython code looking like
the following snippet:

     1 reader=itk.itkImageFileReader_New(ITK_US,2)
     2 reader.SetFileName("Data/homersbrain.bmp")
     3 img=reader.GetOutput()
     4 process=itk.itkThresholdImageFilter_New(img)
     5 process.SetInput(img)
     6 process.SetOutsideValue(50)
     7 process.ThresholdBelow(200)
     8 cast=itk.itkCastImageFilter_New(img,itk.itkImage(ITK_UC,2))
     9 cast.SetInput(process.GetOutput())
    10 img=cast.GetOutput()
    11 writer=itk.itkImageFileWriter_New(img)
    12 writer.SetInput(img)
    13 writer.SetFileName("test2.bmp")
    14 writer.Write()

In the above snippet, the important lines are line 8, i.e.
    cast=itk.itkCastImageFilter_New(img,itk.itkImage(ITK_UC,2))
where we can make reference to an instantiated ITKPython class named
   itk.itkImage(ITK_UC,2)
which needs to be implicitely instantiated somewhere !
But we also need the functionality of line 11 i.e. 
   writer=itk.itkImageFileWriter_New(img)
where we construct a new ITK object of required type (and the constructor
should return an exception if the required type isn't wrapped).


The specified parameters for the pseudo-template could be one of the 3 
following possibilities :
 - explicit type like ITK_UC or 2
      example (line 8) : itk.itkImage_New(ITK_UC,2)
 - an itk python class like the result of call to itk.itkImage(ITK_UC,2)
   that returns : itk.itkImageUC2
      example (line 8) : itk.itkCastImageFilter_New(img,itk.itkImage(ITK_UC,2))
 - an itk python instance like img
      example (line 11) : itk.itkImageFileWriter_New(img)


I was able to realise a small Python module that offers me the possibility
to instanciate my ITKPython classes on the fly and to get the above snippet
running.
The key for this litte module to work in the following:
   it uses Python internal mechanisms to recover all the required 
   template classes and then creates the required constructor methods.

For example for the above snippet, my python module
   1/ finds the python classes itkImageUC2, itkImageUS2, etc.
   2/ searches the common radix class name that is itkImage
   3/ creates 2 methods :
      + itkImage(*args) that returns the itkImageUC2, itkImageUS2, etc.
        class in function of args
      + itkImage_New(*args) that returns the itkImageUC2, itkImageUS2, etc.
        class instanciation in function of args

This works fairly well but alas I couldn't get it running for all cases !


The snag is that ITK wrapping doesn't seem to be consistent when
choosing the mangled names for Python of the underlying ITK classes
(the mangled name is choosed manually).
Or at least the rules are fairly obscur and don't seem to be systematic.
For example, in the above snippet the specified template arguments falls
within one of the following categories :
 - The itkImage as a PixelType specified as itkVector(type,dim) or
   itkConvariantVector(type,dim) :
   example : itkImage_New( itkVector(ITK_F, 2), 2)
 - For the creation of itkFunctionBase class instance with a class (or 
   instance) in python
   example : itkFunctionBase_New( itkImage(ITK_F, 2), ITK_D)

But this strategy relies on consistent mangled class names at the Python
level. More precisely :
 - if we require a 2D image with vector<float,2> scalar type as template 
   parameter, we would like to write :
       itk.itkImage( itk.itkVector( ITK_FLOAT, 2), 2)
   and the method will search the itk.itkImageVF22 class.

   ALAS ITK doesn't produce this mangled name ! Indeed, the valid ITKPython
   class names are either itk.itkImageV2F2 or itk.itkImageVF2 !
 - if we require a processing on 2D image with float scalar type as template 
   parameter, we would like to write :
       itk.itkThresholdFilter( itk.itkImage( ITK_FLOAT, 2) )
   and the method will search the itk.itkThresholdFilterIF2 class.

   ALAS ITK doesn't produce this mangled name ! Indeed, the valid ITKPython
   class names are either itk.itkThresholdFilterF2 !
 - if we require a function on 2D image with float scalar type as template 
   parameter, we would like to write :
       itk.itkFucntionBase( itk.itkImage( ITK_FLOAT, 2), ITK_D )
   and the method will search the itk.itkFunctionBaseIF2D class.

   ITK produces this mangled name !
   The ITK wrappers constructs the above mangled named (well actually, they
   are manually defined in the wrap_Xxx files)! But those mangled names
   don't seem to be globaly coherent. And we probably rely on the
   choices of the author of each wrap_Xxx file to attain global
   coherence (well maybe I am wrong on this one).

This raises the two following questions:


First question: why is the ITK name mangling apparently inconsitent ?
---------------------------------------------------------------------------

I went looking at the wrapping of ITK classes. I don't fully
understand the logic used to create the wrapping. The mangled class's
name doesn't seem to be coherent/consistent for all the wrapped classes.
In the Wrapping/itkCSwigImages.h file, we can find the following code :
       1  typedef itk::Image< itkvector::F2, 2 > VF2;
       2  typedef itk::Image< itkvector::F3, 3 > VF3;
       3  typedef itk::Image< itkvector::F2, 2 > VD2;
       4  typedef itk::Image< itkvector::F3, 3 > VD3;
       5  typedef itk::Image< itkvector::F2, 2 > V2F2;
       6  typedef itk::Image< itkvector::F2, 3 > V2F3;
       7  typedef itk::Image< covariantvector::F2, 2 > CVF2;
       8  typedef itk::Image< covariantvector::F3, 3 > CVF3;
       9  typedef itk::Image< covariantvector::D2, 2 > CVD2;
      10  typedef itk::Image< covariantvector::D3, 3 > CVD3;

  + The lines 1, 3 & 5 represent the same type of datas but the typedef
    names are different !?
  + The lines 3 & 4 indicate the definition for floating images but the
    typedef name indicates a double !? 
  + An image having float as scalar type and dimension 2 has the F2
    mangled type. But, an image having Vector<float,2> as scalar type and
    dimension 2 has either VF2 or V2F2 as mangled type !? 
    Wouldn't it be better to use VF22 to avoid confusion ? VF22 would
    more clearly indicate : Image< V< F,2 >, 2>
  + A process like ImageThresholdFilter that only has one input might be
    mangled as:
        ImageThreshold< Image<F,2> >    ==> ImageThresholdIF2
    The I letter indicates that we have an image (like in few wrapped classes or
    when having ImageVF2... the V letter indicating Vector)

Could any one clarify the ITK mangling strategy for me ?


Second question: CableSwig versus Swig ?
----------------------------------------

I would like to know what is today the advantage of CableSwig ? 
(as opposed to Swig)

I understand the historic choice, when Swig didn't handle template classes.
But Swig evolved and is now able to handle template classes (and
nested classes, though their appear to still be some kind of limitations on
heavily nester classes, as I understand it).
What is now the CableSwig additional value compared to Swig ? Does
CableSwig add any special wrapping features for ITK ? [e.g. by adding or
removing some specific methods or any other ITK specific reason]  ?


Other informations for ITK :
----------------------------------------

If the ITK-Kitware folks are interested to work on this subject, I would
be deligthed to try to provide some help and feedback... since I need
this feature bad [ I'm a VTKPython drug addict: please help to switch
...to ITKPython ;-] .


    Yours,
    Benoit Regrain

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.itk.org/mailman/private/insight-developers/attachments/20050610/8ebab9b0/attachment.html


More information about the Insight-developers mailing list