diff --git a/Wrapping/Common/mitk_swig_common.i b/Wrapping/Common/mitk_swig_common.i index 7896f9e8f6..53d701c85a 100644 --- a/Wrapping/Common/mitk_swig_common.i +++ b/Wrapping/Common/mitk_swig_common.i @@ -1,33 +1,35 @@ // Ignore common warnings: // 302 : Redefinition of Macro, usually not a problem // 362 : Operator= is ignored. Can't help it. // 503 : Can't wrap operator of type "*" unless renamed to a valid identifier, no problem as operator not needed. // 509 : Overloaded function ignored. Usually not a problem, as overloaded functions shouldn't give different results. // 511 : Can't use keyword arguments with overloaded functions #pragma SWIG nowarn=302,362,503,509,511 // Splitted the information about the addition files into sub-files: +%naturalvar; + +// Includes of STD-Files goes in here +%include // Include c++ code in this file. It is basically a c++-header wrapped in the commands so it is included in the std-file %include // SWIG-Macro definition goes in here, for example SWIG_ADD_MITK_CLASS %include -// Includes of STD-Files goes in here -%include // information about classes that are going to be wrapped are in here: %include // // How to wrap a new class: // ------------------------------------ // 1. Add the c++ include file to mitk_swig_cpp_include.i // If the class is in a new module, make sure that this module is added as dependency in cmake // 2. Add the class definition in mitk_swig_classes.i // If the definition of the class needs new macros, for example because it is not in the core // and has a new Export-Macro, be sure to define this macro first. // If the class inherit from mitk::BaseData use the SWIG_ADD_MITK_CLASS macro, as it defines // some redundante code. // std::vector mitk::GetImageSize(mitk::Image::Pointer image); \ No newline at end of file diff --git a/Wrapping/Common/mitk_swig_cpp_include.i b/Wrapping/Common/mitk_swig_cpp_include.i index 62b980cc64..e0151493c6 100644 --- a/Wrapping/Common/mitk_swig_cpp_include.i +++ b/Wrapping/Common/mitk_swig_cpp_include.i @@ -1,96 +1,107 @@ %{ #include #include #include #include #include #include #include // SWIG Doesn't wrap namespaces. This leads to some problems, if the namespaces are not used. using namespace mitk; using namespace itk; std::vector GetImageSize(mitk::Image::Pointer image) { std::vector< unsigned int > size; unsigned int dimension = image->GetDimension(); for (int i = 0; i < dimension; ++i) { size.push_back(image->GetDimension(i)); } return size; } std::vector GetImageSize(mitk::Image* image) { std::vector< unsigned int > size; unsigned int dimension = image->GetDimension(); for (int i = 0; i < dimension; ++i) { size.push_back(image->GetDimension(i)); } return size; } struct TypeDefinitions { - static const int ComponentTypeUInt8 = MapPixelType::value>::IOComponentType; - static const int ComponentTypeInt8 = MapPixelType::value>::IOComponentType; - static const int ComponentTypeUInt16 = MapPixelType::value>::IOComponentType; - static const int ComponentTypeInt16 = MapPixelType::value>::IOComponentType; - static const int ComponentTypeUInt32 = MapPixelType::value>::IOComponentType; - static const int ComponentTypeInt32 = MapPixelType::value>::IOComponentType; - static const int ComponentTypeFloat = MapPixelType::value>::IOComponentType; - static const int ComponentTypeDouble = MapPixelType::value>::IOComponentType; + static const int ComponentTypeUInt8 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeInt8 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeUInt16 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeInt16 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeUInt32 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeInt32 = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeFloat = mitk::MapPixelType::value>::IOComponentType; + static const int ComponentTypeDouble = mitk::MapPixelType::value>::IOComponentType; }; mitk::PixelType MakePixelTypeFromTypeID(int componentTypeID, int numberOfComponents) { switch (componentTypeID) { case TypeDefinitions::ComponentTypeUInt8 : return mitk::MakePixelType(numberOfComponents); case TypeDefinitions::ComponentTypeInt8 : return mitk::MakePixelType(numberOfComponents); case TypeDefinitions::ComponentTypeUInt16 : return mitk::MakePixelType(numberOfComponents); case TypeDefinitions::ComponentTypeInt16 : return mitk::MakePixelType(numberOfComponents); case TypeDefinitions::ComponentTypeUInt32 : return mitk::MakePixelType(numberOfComponents); case TypeDefinitions::ComponentTypeInt32 : return mitk::MakePixelType(numberOfComponents); case TypeDefinitions::ComponentTypeFloat : return mitk::MakePixelType(numberOfComponents); case TypeDefinitions::ComponentTypeDouble : return mitk::MakePixelType(numberOfComponents); default: return mitk::MakePixelType(numberOfComponents); } } mitk::Image::Pointer MakeImage(mitk::PixelType pixelType, std::vector shape) { mitk::Image::Pointer image = mitk::Image::New(); image->Initialize(pixelType, shape.size(), shape.data()); return image; } +template +typename T::Pointer ConvertTo(mitk::BaseData::Pointer base) +{ + typename T::Pointer erg = dynamic_cast(base.GetPointer()); + return erg; +} + %} std::vector GetImageSize(mitk::Image::Pointer image); std::vector GetImageSize(mitk::Image* image); mitk::PixelType MakePixelTypeFromTypeID(int componentTypeID, int numberOfComponents); mitk::Image::Pointer MakeImage(mitk::PixelType pixelType, std::vector shape); %constant int ComponentTypeUInt8 = TypeDefinitions::ComponentTypeUInt8; %constant int ComponentTypeInt8 = TypeDefinitions::ComponentTypeInt8; %constant int ComponentTypeUInt16 = TypeDefinitions::ComponentTypeUInt16; %constant int ComponentTypeInt16 = TypeDefinitions::ComponentTypeInt16; %constant int ComponentTypeUInt32 = TypeDefinitions::ComponentTypeUInt32; %constant int ComponentTypeInt32 = TypeDefinitions::ComponentTypeInt32; %constant int ComponentTypeFloat = TypeDefinitions::ComponentTypeFloat; -%constant int ComponentTypeDouble = TypeDefinitions::ComponentTypeDouble; \ No newline at end of file +%constant int ComponentTypeDouble = TypeDefinitions::ComponentTypeDouble; + +template +typename T::Pointer ConvertTo(mitk::BaseData::Pointer base); + diff --git a/Wrapping/Common/mitk_swig_macros.i b/Wrapping/Common/mitk_swig_macros.i index 98a7bb977a..29c0103d46 100644 --- a/Wrapping/Common/mitk_swig_macros.i +++ b/Wrapping/Common/mitk_swig_macros.i @@ -1,28 +1,78 @@ // // This file contains macros for swig. // // // SWIG_ADD_MITK_CLASS is a helper macro in order to do // all important stuff before an mitk::Class is included. // Requires the name of the class as it is in c++ as classname // and the include file, in which the class is defined. // It is assumed that the class is somehow inherited from // mitk::BaseData, and supports smartpointers. // %define SWIG_ADD_MITK_CLASS(classname, classinclude) // Declaring that this class is a smart-pointer class, in order to handle // online upcasting where necessary (for example python) %feature("smartptr", noblock=1) mitk:: ## classname { itk::SmartPointer } // Include the given header, where the class definition is found %include - + typedef mitk:: ## classname classname ## ; // Initianziation of std. vectors containing pointers to these classes. This allows to use // vectors of these types as target language arrays. - %template(Vector ## classname ## Pointer) std::vector< itk::SmartPointer >; + %template(Vector ## classname ## Pointer) std::vector< mitk:: ## classname ## ::Pointer >; + //%template(Vector ## classname ## Pointer) std::vector< mitk:: ## classname ## ::Pointer >; + //%template(Vector ## classname ## Pointer) std::vector< itk::SmartPointer >; %template(Vector ## classname) std::vector< mitk:: ## classname ## ::Self *>; // Defining the Smartpointer, allows easy access in target language %template(classname ## Pointer) itk::SmartPointer; + + // Define a conversion method to convert from and to types + %template(ConvertTo ## classname) ConvertTo; + + + // This extend is necessary to have the automatic cast methods available +%extend itk::SmartPointer { + %pythoncode %{ + def _GetListOfValidItems(self): + return [str(k) for k in self.GetClassHierarchy() if k in convertion_list.keys() ] + %} + %pythoncode %{ + def __getattr__(self, item): + if type(item)==str: + if (len(item) > 9) and ('ConvertTo' in item): + searchString=item[9:] + if searchString in self._GetListOfValidItems(): + def func_t(): + return convertion_list[searchString](self) + return func_t + %} + %pythoncode %{ + def __dir__(self): + return super().__dir__() + ['ConvertTo'+k for k in self._GetListOfValidItems()] + %} +} + +%extend classname { + %pythoncode %{ + def _GetListOfValidItems(self): + return [str(k) for k in self.GetClassHierarchy() if k in convertion_list.keys() ] + %} + %pythoncode %{ + def __getattr__(self, item): + if type(item)==str: + if (len(item) > 9) and ('ConvertTo' in item): + searchString=item[9:] + if searchString in self._GetListOfValidItems(): + def func_t(): + return convertion_list[searchString](self) + return func_t + %} + %pythoncode %{ + def __dir__(self): + return super().__dir__() + ['ConvertTo'+k for k in self._GetListOfValidItems()] + %} +} + %enddef \ No newline at end of file diff --git a/Wrapping/Python/MITK.i b/Wrapping/Python/MITK.i index e76d304b0b..1b29b9178d 100644 --- a/Wrapping/Python/MITK.i +++ b/Wrapping/Python/MITK.i @@ -1,165 +1,172 @@ %module PythonMITK %include %{ #include "mitkNumpyArrayConversion.cxx" %} // Numpy array conversion support %native(_GetMemoryViewFromImage) PyObject *mitk_GetMemoryViewFromImage( PyObject *self, PyObject *args ); %native(_SetImageFromArray) PyObject *mitk_SetImageFromArray( PyObject *(self), PyObject *args ); %pythoncode %{ HAVE_NUMPY = True try: import numpy except ImportError: HAVE_NUMPY = False def _get_numpy_dtype( mitkImage ): """Given a MITK image, returns the numpy.dtype which describes the data""" if not HAVE_NUMPY: raise ImportError('Numpy not available.') # this is a mapping from MITK's pixel id to numpy's dtype _mitk_np = {ComponentTypeUInt8:numpy.uint8, ComponentTypeUInt16:numpy.uint16, ComponentTypeUInt32:numpy.uint32, ComponentTypeInt8:numpy.int8, ComponentTypeInt16:numpy.int16, ComponentTypeInt32:numpy.int32, ComponentTypeFloat:numpy.float32, ComponentTypeDouble:numpy.float64, } return _mitk_np[ mitkImage.GetPixelType().GetComponentType() ] def _get_mitk_pixelid(numpy_array_type): """Returns a SimpleITK PixelID given a numpy array.""" if not HAVE_NUMPY: raise ImportError('Numpy not available.') # This is a Mapping from numpy array types to sitks pixel types. _np_mitk = {numpy.character:ComponentTypeUInt8, numpy.uint8:ComponentTypeUInt8, numpy.uint16:ComponentTypeUInt16, numpy.uint32:ComponentTypeUInt32, numpy.int8:ComponentTypeInt8, numpy.int16:ComponentTypeInt16, numpy.int32:ComponentTypeInt32, numpy.float32:ComponentTypeFloat, numpy.float64:ComponentTypeDouble, } try: return _np_mitk[numpy_array_type.dtype] except KeyError: for key in _np_mitk: if numpy.issubdtype(numpy_array_type.dtype, key): return _np_mitk[key] raise TypeError('dtype: {0} is not supported.'.format(numpy_array_type.dtype)) def _get_sitk_vector_pixelid(numpy_array_type): """Returns a SimpleITK vecotr PixelID given a numpy array.""" if not HAVE_NUMPY: raise ImportError('Numpy not available.') # This is a Mapping from numpy array types to sitks pixel types. _np_sitk = {numpy.character:sitkVectorUInt8, numpy.uint8:sitkVectorUInt8, numpy.uint16:sitkVectorUInt16, numpy.uint32:sitkVectorUInt32, numpy.uint64:sitkVectorUInt64, numpy.int8:sitkVectorInt8, numpy.int16:sitkVectorInt16, numpy.int32:sitkVectorInt32, numpy.int64:sitkVectorInt64, numpy.float32:sitkVectorFloat32, numpy.float64:sitkVectorFloat64, } try: return _np_sitk[numpy_array_type.dtype] except KeyError: for key in _np_sitk: if numpy.issubdtype(numpy_array_type.dtype, key): return _np_sitk[key] raise TypeError('dtype: {0} is not supported.'.format(numpy_array_type.dtype)) # SimplyITK <-> Numpy Array conversion support. #http://www.nickdarnell.com/swig-casting-revisited/ def GetArrayViewFromImage(image): """Get a NumPy ndarray view of a SimpleITK Image. Returns a Numpy ndarray object as a "view" of the SimpleITK's Image buffer. This reduces pixel buffer copies, but requires that the SimpleITK image object is kept around while the buffer is being used. """ if not HAVE_NUMPY: raise ImportError('NumPy not available.') dtype = _get_numpy_dtype( image ) shape = GetImageSize(image); if image.GetPixelType().GetNumberOfComponents() > 1: shape = ( image.GetPixelType().GetNumberOfComponents(), ) + shape imageMemoryView = _PythonMITK._GetMemoryViewFromImage(image) arrayView = numpy.asarray(imageMemoryView).view(dtype = dtype) arrayView.shape = shape[::-1] return arrayView def GetArrayFromImage(image): """Get a NumPy ndarray from a SimpleITK Image. This is a deep copy of the image buffer and is completely safe and without potential side effects. """ # TODO: If the image is already not unique then a second copy may be made before the numpy copy is done. arrayView = GetArrayViewFromImage(image) # perform deep copy of the image buffer return numpy.array(arrayView, copy=True) def GetImageFromArray( arr, isVector=False): """Get a SimpleITK Image from a numpy array. If isVector is True, then a 3D array will be treated as a 2D vector image, otherwise it will be treated as a 3D image""" if not HAVE_NUMPY: raise ImportError('Numpy not available.') z = numpy.asarray( arr ) assert z.ndim in ( 2, 3, 4 ), \ "Only arrays of 2, 3 or 4 dimensions are supported." id = _get_mitk_pixelid( z ) #img = Image_New() if ( z.ndim == 3 and isVector ) or (z.ndim == 4): pixelType=MakePixelTypeFromTypeID(id, z.shape[-1]) newShape=VectorUInt32(z.shape[-2::-1]) img = MakeImage(pixelType, newShape) #img.Initialize(pixelType, z.ndim - 1, z.shape[-2::-1]) elif z.ndim in ( 2, 3 ): pixelType=MakePixelTypeFromTypeID(id, 1) newShape=VectorUInt32(z.shape[::-1]) img = MakeImage(pixelType, newShape) #img.Initialize(pixelType, z.ndim, z.shape[::-1]) _PythonMITK._SetImageFromArray( z.tostring(), img ) return img -%} \ No newline at end of file +convertion_list = {'Image':ConvertToImage, + 'SlicedData':ConvertToSlicedData, + 'BaseData':ConvertToBaseData} + +%} + + +