From 4da9ce7c06771a4b5464258c92aaf7c263382c28 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 14:10:05 +0200 Subject: [PATCH 01/26] wrap and core ants image local working --- .vscode/settings.json | 88 ++++ CMakeLists.txt | 70 +++ ants/__init__.py | 2 +- ants/core/ants_image.py | 26 +- ants/lib/CMakeLists.txt | 200 --------- ants/lib/CONTRIB_antsImageAugment.cxx | 397 ------------------ ants/lib/LOCAL_antsImage.cxx | 316 -------------- ants/lib/LOCAL_antsImage.h | 380 ----------------- ants/lib/LOCAL_antsImageClone.cxx | 117 ------ ants/lib/LOCAL_mergeChannels.cxx | 219 ---------- ants/lib/LOCAL_mergeChannels.h | 25 -- ants/lib/LOCAL_readImage.cxx | 123 ------ ants/lib/WRAP_Atropos.cxx | 17 - ants/lib/WRAP_AverageAffineTransform.cxx | 17 - .../WRAP_AverageAffineTransformNoRigid.cxx | 16 - ants/lib/WRAP_ConvertScalarImageToRGB.cxx | 17 - .../WRAP_CreateJacobianDeterminantImage.cxx | 17 - ants/lib/WRAP_CreateTiledMosaic.cxx | 17 - ants/lib/WRAP_DenoiseImage.cxx | 17 - ants/lib/WRAP_KellyKapowski.cxx | 17 - ants/lib/WRAP_LabelClustersUniquely.cxx | 17 - ants/lib/WRAP_LabelGeometryMeasures.cxx | 17 - ants/lib/WRAP_LesionFilling.cxx | 17 - ants/lib/WRAP_N3BiasFieldCorrection.cxx | 17 - ants/lib/WRAP_N4BiasFieldCorrection.cxx | 17 - ants/lib/WRAP_NonLocalSuperResolution.cxx | 17 - ants/lib/WRAP_ResampleImage.cxx | 17 - ants/lib/WRAP_SuperResolution.cxx | 17 - ants/lib/WRAP_ThresholdImage.cxx | 17 - ants/lib/WRAP_TileImages.cxx | 17 - ants/lib/WRAP_TimeSCCAN.cxx | 17 - ants/lib/WRAP_antsAffineInitializer.cxx | 17 - ants/lib/WRAP_antsApplyTransforms.cxx | 17 - ants/lib/WRAP_antsJointFusion.cxx | 17 - ..._antsLandmarkBasedTransformInitializer.cxx | 17 - ants/lib/WRAP_antsMotionCorr.cxx | 17 - ants/lib/WRAP_antsMotionCorrStats.cxx | 17 - ants/lib/WRAP_antsRegistration.cxx | 17 - .../WRAP_antsSliceRegularizedRegistration.cxx | 17 - ants/lib/WRAP_antsSurf.cxx | 17 - ants/lib/WRAP_antsVol.cxx | 17 - ants/lib/WRAP_iMath.cxx | 17 - ants/lib/__init__.py | 89 ---- ants/utils/channels.py | 4 +- ants/utils/smooth_image.py | 2 +- pyproject.toml | 50 +++ ...onfigure_ANTsPy.bat => configure_ANTs.bat} | 0 ...{configure_ANTsPy.sh => configure_ANTs.sh} | 12 +- ...y_windows.sh => configure_ANTs_windows.sh} | 0 scripts/configure_ITK.sh | 7 +- setup.cfg | 2 - setup.py | 206 --------- {ants/lib => src}/ANTsVersionConfig.h | 0 {ants/lib => src}/LOCAL_SmoothImage.cxx | 27 +- {ants/lib => src}/LOCAL_addNoiseToImage.cxx | 49 +-- {ants/lib => src}/LOCAL_antiAlias.cxx | 0 src/LOCAL_antsImage.cxx | 389 +++++++++++++++++ src/LOCAL_antsImage.h | 226 ++++++++++ src/LOCAL_antsImageClone.cxx | 114 +++++ .../lib => src}/LOCAL_antsImageHeaderInfo.cxx | 36 +- .../LOCAL_antsImageMutualInformation.cxx | 0 .../LOCAL_antsImageToImageMetric.cxx | 0 .../LOCAL_antsImageToImageMetric.h | 0 {ants/lib => src}/LOCAL_antsImageUtils.cxx | 0 {ants/lib => src}/LOCAL_antsImageWin.cxx | 2 +- {ants/lib => src}/LOCAL_antsTransform.cxx | 0 {ants/lib => src}/LOCAL_antsTransform.h | 0 .../LOCAL_composeDisplacementFields.cxx | 0 {ants/lib => src}/LOCAL_cropImage.cxx | 0 .../LOCAL_fitBsplineDisplacementField.cxx | 0 ...splineDisplacementFieldToScatteredData.cxx | 0 .../LOCAL_fitBsplineObjectToScatteredData.cxx | 0 ...SplineDisplacementFieldToScatteredData.cxx | 0 {ants/lib => src}/LOCAL_fsl2antstransform.cxx | 0 .../LOCAL_getNeighborhoodMatrix.cxx | 0 {ants/lib => src}/LOCAL_hausdorffDistance.cxx | 0 .../LOCAL_histogramMatchImages.cxx | 0 .../LOCAL_integrateVelocityField.cxx | 0 .../LOCAL_invertDisplacementField.cxx | 0 .../LOCAL_labelOverlapMeasures.cxx | 0 {ants/lib => src}/LOCAL_labelStats.cxx | 0 src/LOCAL_mergeChannels.cxx | 142 +++++++ src/LOCAL_mergeChannels.h | 22 + {ants/lib => src}/LOCAL_padImage.cxx | 0 src/LOCAL_readImage.cxx | 99 +++++ {ants/lib => src}/LOCAL_readImage.h | 14 +- {ants/lib => src}/LOCAL_readTransform.cxx | 0 {ants/lib => src}/LOCAL_readTransform.h | 0 {ants/lib => src}/LOCAL_reflectionMatrix.cxx | 0 {ants/lib => src}/LOCAL_reorientImage.cxx | 0 {ants/lib => src}/LOCAL_reorientImage2.cxx | 0 {ants/lib => src}/LOCAL_rgbToVector.cxx | 0 {ants/lib => src}/LOCAL_sccaner.cxx | 0 .../LOCAL_simulateDisplacementField.cxx | 0 {ants/lib => src}/LOCAL_sliceImage.cxx | 0 .../LOCAL_weingartenImageCurvature.cxx | 0 {ants/lib => src}/ReadWriteData.h | 0 src/WRAP_Atropos.cxx | 20 + src/WRAP_AverageAffineTransform.cxx | 20 + src/WRAP_AverageAffineTransformNoRigid.cxx | 19 + src/WRAP_CreateJacobianDeterminantImage.cxx | 19 + src/WRAP_DenoiseImage.cxx | 19 + src/WRAP_KellyKapowski.cxx | 19 + src/WRAP_LabelClustersUniquely.cxx | 19 + src/WRAP_LabelGeometryMeasures.cxx | 19 + src/WRAP_N3BiasFieldCorrection.cxx | 19 + src/WRAP_N4BiasFieldCorrection.cxx | 19 + src/WRAP_ResampleImage.cxx | 19 + src/WRAP_ThresholdImage.cxx | 19 + src/WRAP_TileImages.cxx | 19 + src/WRAP_antsAffineInitializer.cxx | 20 + src/WRAP_antsApplyTransforms.cxx | 19 + .../WRAP_antsApplyTransformsToPoints.cxx | 16 +- src/WRAP_antsJointFusion.cxx | 19 + src/WRAP_antsRegistration.cxx | 20 + src/WRAP_iMath.cxx | 19 + {ants/lib => src}/itkPyBuffer.h | 0 {ants/lib => src}/itkPyBuffer.hxx | 0 {ants/lib => src}/itkPyVnl.h | 0 {ants/lib => src}/itkPyVnl.hxx | 0 src/main.cpp | 89 ++++ {ants/lib => src}/register_transforms.h | 0 122 files changed, 1733 insertions(+), 2682 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 CMakeLists.txt delete mode 100644 ants/lib/CMakeLists.txt delete mode 100644 ants/lib/CONTRIB_antsImageAugment.cxx delete mode 100644 ants/lib/LOCAL_antsImage.cxx delete mode 100644 ants/lib/LOCAL_antsImage.h delete mode 100644 ants/lib/LOCAL_antsImageClone.cxx delete mode 100644 ants/lib/LOCAL_mergeChannels.cxx delete mode 100644 ants/lib/LOCAL_mergeChannels.h delete mode 100644 ants/lib/LOCAL_readImage.cxx delete mode 100644 ants/lib/WRAP_Atropos.cxx delete mode 100644 ants/lib/WRAP_AverageAffineTransform.cxx delete mode 100644 ants/lib/WRAP_AverageAffineTransformNoRigid.cxx delete mode 100644 ants/lib/WRAP_ConvertScalarImageToRGB.cxx delete mode 100644 ants/lib/WRAP_CreateJacobianDeterminantImage.cxx delete mode 100644 ants/lib/WRAP_CreateTiledMosaic.cxx delete mode 100644 ants/lib/WRAP_DenoiseImage.cxx delete mode 100644 ants/lib/WRAP_KellyKapowski.cxx delete mode 100644 ants/lib/WRAP_LabelClustersUniquely.cxx delete mode 100644 ants/lib/WRAP_LabelGeometryMeasures.cxx delete mode 100644 ants/lib/WRAP_LesionFilling.cxx delete mode 100644 ants/lib/WRAP_N3BiasFieldCorrection.cxx delete mode 100644 ants/lib/WRAP_N4BiasFieldCorrection.cxx delete mode 100644 ants/lib/WRAP_NonLocalSuperResolution.cxx delete mode 100644 ants/lib/WRAP_ResampleImage.cxx delete mode 100644 ants/lib/WRAP_SuperResolution.cxx delete mode 100644 ants/lib/WRAP_ThresholdImage.cxx delete mode 100644 ants/lib/WRAP_TileImages.cxx delete mode 100644 ants/lib/WRAP_TimeSCCAN.cxx delete mode 100644 ants/lib/WRAP_antsAffineInitializer.cxx delete mode 100644 ants/lib/WRAP_antsApplyTransforms.cxx delete mode 100644 ants/lib/WRAP_antsJointFusion.cxx delete mode 100644 ants/lib/WRAP_antsLandmarkBasedTransformInitializer.cxx delete mode 100644 ants/lib/WRAP_antsMotionCorr.cxx delete mode 100644 ants/lib/WRAP_antsMotionCorrStats.cxx delete mode 100644 ants/lib/WRAP_antsRegistration.cxx delete mode 100644 ants/lib/WRAP_antsSliceRegularizedRegistration.cxx delete mode 100644 ants/lib/WRAP_antsSurf.cxx delete mode 100644 ants/lib/WRAP_antsVol.cxx delete mode 100644 ants/lib/WRAP_iMath.cxx delete mode 100644 ants/lib/__init__.py create mode 100644 pyproject.toml rename scripts/{configure_ANTsPy.bat => configure_ANTs.bat} (100%) rename scripts/{configure_ANTsPy.sh => configure_ANTs.sh} (82%) rename scripts/{configure_ANTsPy_windows.sh => configure_ANTs_windows.sh} (100%) delete mode 100644 setup.cfg delete mode 100644 setup.py rename {ants/lib => src}/ANTsVersionConfig.h (100%) rename {ants/lib => src}/LOCAL_SmoothImage.cxx (65%) rename {ants/lib => src}/LOCAL_addNoiseToImage.cxx (60%) rename {ants/lib => src}/LOCAL_antiAlias.cxx (100%) create mode 100644 src/LOCAL_antsImage.cxx create mode 100644 src/LOCAL_antsImage.h create mode 100644 src/LOCAL_antsImageClone.cxx rename {ants/lib => src}/LOCAL_antsImageHeaderInfo.cxx (80%) rename {ants/lib => src}/LOCAL_antsImageMutualInformation.cxx (100%) rename {ants/lib => src}/LOCAL_antsImageToImageMetric.cxx (100%) rename {ants/lib => src}/LOCAL_antsImageToImageMetric.h (100%) rename {ants/lib => src}/LOCAL_antsImageUtils.cxx (100%) rename {ants/lib => src}/LOCAL_antsImageWin.cxx (99%) rename {ants/lib => src}/LOCAL_antsTransform.cxx (100%) rename {ants/lib => src}/LOCAL_antsTransform.h (100%) rename {ants/lib => src}/LOCAL_composeDisplacementFields.cxx (100%) rename {ants/lib => src}/LOCAL_cropImage.cxx (100%) rename {ants/lib => src}/LOCAL_fitBsplineDisplacementField.cxx (100%) rename {ants/lib => src}/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx (100%) rename {ants/lib => src}/LOCAL_fitBsplineObjectToScatteredData.cxx (100%) rename {ants/lib => src}/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx (100%) rename {ants/lib => src}/LOCAL_fsl2antstransform.cxx (100%) rename {ants/lib => src}/LOCAL_getNeighborhoodMatrix.cxx (100%) rename {ants/lib => src}/LOCAL_hausdorffDistance.cxx (100%) rename {ants/lib => src}/LOCAL_histogramMatchImages.cxx (100%) rename {ants/lib => src}/LOCAL_integrateVelocityField.cxx (100%) rename {ants/lib => src}/LOCAL_invertDisplacementField.cxx (100%) rename {ants/lib => src}/LOCAL_labelOverlapMeasures.cxx (100%) rename {ants/lib => src}/LOCAL_labelStats.cxx (100%) create mode 100644 src/LOCAL_mergeChannels.cxx create mode 100644 src/LOCAL_mergeChannels.h rename {ants/lib => src}/LOCAL_padImage.cxx (100%) create mode 100644 src/LOCAL_readImage.cxx rename {ants/lib => src}/LOCAL_readImage.h (55%) rename {ants/lib => src}/LOCAL_readTransform.cxx (100%) rename {ants/lib => src}/LOCAL_readTransform.h (100%) rename {ants/lib => src}/LOCAL_reflectionMatrix.cxx (100%) rename {ants/lib => src}/LOCAL_reorientImage.cxx (100%) rename {ants/lib => src}/LOCAL_reorientImage2.cxx (100%) rename {ants/lib => src}/LOCAL_rgbToVector.cxx (100%) rename {ants/lib => src}/LOCAL_sccaner.cxx (100%) rename {ants/lib => src}/LOCAL_simulateDisplacementField.cxx (100%) rename {ants/lib => src}/LOCAL_sliceImage.cxx (100%) rename {ants/lib => src}/LOCAL_weingartenImageCurvature.cxx (100%) rename {ants/lib => src}/ReadWriteData.h (100%) create mode 100644 src/WRAP_Atropos.cxx create mode 100644 src/WRAP_AverageAffineTransform.cxx create mode 100644 src/WRAP_AverageAffineTransformNoRigid.cxx create mode 100644 src/WRAP_CreateJacobianDeterminantImage.cxx create mode 100644 src/WRAP_DenoiseImage.cxx create mode 100644 src/WRAP_KellyKapowski.cxx create mode 100644 src/WRAP_LabelClustersUniquely.cxx create mode 100644 src/WRAP_LabelGeometryMeasures.cxx create mode 100644 src/WRAP_N3BiasFieldCorrection.cxx create mode 100644 src/WRAP_N4BiasFieldCorrection.cxx create mode 100644 src/WRAP_ResampleImage.cxx create mode 100644 src/WRAP_ThresholdImage.cxx create mode 100644 src/WRAP_TileImages.cxx create mode 100644 src/WRAP_antsAffineInitializer.cxx create mode 100644 src/WRAP_antsApplyTransforms.cxx rename {ants/lib => src}/WRAP_antsApplyTransformsToPoints.cxx (50%) create mode 100644 src/WRAP_antsJointFusion.cxx create mode 100644 src/WRAP_antsRegistration.cxx create mode 100644 src/WRAP_iMath.cxx rename {ants/lib => src}/itkPyBuffer.h (100%) rename {ants/lib => src}/itkPyBuffer.hxx (100%) rename {ants/lib => src}/itkPyVnl.h (100%) rename {ants/lib => src}/itkPyVnl.hxx (100%) create mode 100644 src/main.cpp rename {ants/lib => src}/register_transforms.h (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..43896c1b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,88 @@ +{ + "files.associations": { + "iosfwd": "cpp", + "__bit_reference": "cpp", + "__bits": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__functional_base": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__nullptr": "cpp", + "__split_buffer": "cpp", + "__string": "cpp", + "__threading_support": "cpp", + "__tuple": "cpp", + "algorithm": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "exception": "cpp", + "fstream": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iostream": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "locale": "cpp", + "memory": "cpp", + "mutex": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "utility": "cpp", + "vector": "cpp", + "random": "cpp", + "__tree": "cpp", + "any": "cpp", + "cfenv": "cpp", + "condition_variable": "cpp", + "csetjmp": "cpp", + "csignal": "cpp", + "future": "cpp", + "list": "cpp", + "map": "cpp", + "numeric": "cpp", + "queue": "cpp", + "regex": "cpp", + "set": "cpp", + "unordered_set": "cpp", + "valarray": "cpp", + "variant": "cpp", + "*.in": "cpp" + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..b4e98081 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 3.16.3...3.26) + +project(ants LANGUAGES CXX) + +set(CMAKE_POSITION_INDEPENDENT_CODE ON) + +# Try to import all Python components potentially needed by nanobind +find_package(Python 3.8 + REQUIRED COMPONENTS Interpreter Development.Module + OPTIONAL_COMPONENTS Development.SABIModule) + +# Import nanobind through CMake's find_package mechanism +find_package(nanobind CONFIG REQUIRED) + +# TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) +# TODO: make this handle different OS either here or within the configure script +# TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) +# otherwise you have to comment it out during development +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) + +# ITK +set(ITK_DIR "./itkbuild") +find_package(ITK REQUIRED) +include(${ITK_USE_FILE}) + +# ANTS +add_library(antsUtilities STATIC src/antscore/antsUtilities.cxx src/antscore/antsCommandLineOption.cxx src/antscore/antsCommandLineParser.cxx src/antscore/ReadWriteData.cxx src/antscore/ANTsVersion.cxx) +add_library(registrationUtilities STATIC src/antscore/antsRegistrationTemplateHeader.cxx + src/antscore/antsRegistration2DDouble.cxx src/antscore/antsRegistration2DFloat.cxx + src/antscore/antsRegistration3DDouble.cxx src/antscore/antsRegistration3DFloat.cxx + src/antscore/antsRegistration4DDouble.cxx src/antscore/antsRegistration4DFloat.cxx) + + +add_library(imageMathUtilities STATIC src/antscore/ImageMathHelper2D.cxx src/antscore/ImageMathHelper3D.cxx src/antscore/ImageMathHelper4D.cxx) + +# this may not be needed +target_link_libraries(antsUtilities ${ITK_LIBRARIES}) +target_link_libraries(registrationUtilities ${ITK_LIBRARIES}) +target_link_libraries(imageMathUtilities ${ITK_LIBRARIES}) + +nanobind_add_module( + lib + STABLE_ABI + NB_STATIC + src/main.cpp + src/antscore/antsAffineInitializer.cxx + src/antscore/antsApplyTransforms.cxx + src/antscore/antsApplyTransformsToPoints.cxx + src/antscore/antsJointFusion.cxx + src/antscore/antsRegistration.cxx + src/antscore/Atropos.cxx + src/antscore/AverageAffineTransform.cxx + src/antscore/AverageAffineTransformNoRigid.cxx + src/antscore/CreateJacobianDeterminantImage.cxx + src/antscore/DenoiseImage.cxx + src/antscore/iMath.cxx + src/antscore/KellyKapowski.cxx + src/antscore/LabelClustersUniquely.cxx + src/antscore/LabelGeometryMeasures.cxx + src/antscore/N3BiasFieldCorrection.cxx + src/antscore/N4BiasFieldCorrection.cxx + src/antscore/ResampleImage.cxx + src/antscore/ThresholdImage.cxx + src/antscore/TileImages.cxx +) +target_link_libraries(lib PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities imageMathUtilities) + +# Install directive for scikit-build-core +install(TARGETS lib LIBRARY DESTINATION ants) \ No newline at end of file diff --git a/ants/__init__.py b/ants/__init__.py index 9ecccac6..9d523b06 100644 --- a/ants/__init__.py +++ b/ants/__init__.py @@ -1,5 +1,5 @@ -__version__ = '0.5.2' +__version__ = '0.6.0' from .core import * from .utils import * diff --git a/ants/core/ants_image.py b/ants/core/ants_image.py index 7284ea80..ae1411b9 100644 --- a/ants/core/ants_image.py +++ b/ants/core/ants_image.py @@ -80,7 +80,7 @@ def __init__(self, pixeltype='float', dimension=3, components=1, pointer=None, i self._libsuffix = '%s%s%i' % (self._shortpclass, utils.short_ptype(self.pixeltype), self.dimension) - self.shape = utils.get_lib_fn('getShape%s'%self._libsuffix)(self.pointer) + self.shape = tuple(utils.get_lib_fn('getShape')(self.pointer)) self.physical_shape = tuple([round(sh*sp,3) for sh,sp in zip(self.shape, self.spacing)]) self._array = None @@ -94,8 +94,8 @@ def spacing(self): ------- tuple """ - libfn = utils.get_lib_fn('getSpacing%s'%self._libsuffix) - return libfn(self.pointer) + libfn = utils.get_lib_fn('getSpacing') + return tuple(libfn(self.pointer)) def set_spacing(self, new_spacing): """ @@ -116,7 +116,7 @@ def set_spacing(self, new_spacing): if len(new_spacing) != self.dimension: raise ValueError('must give a spacing value for each dimension (%i)' % self.dimension) - libfn = utils.get_lib_fn('setSpacing%s'%self._libsuffix) + libfn = utils.get_lib_fn('setSpacing') libfn(self.pointer, new_spacing) @property @@ -128,8 +128,8 @@ def origin(self): ------- tuple """ - libfn = utils.get_lib_fn('getOrigin%s'%self._libsuffix) - return libfn(self.pointer) + libfn = utils.get_lib_fn('getOrigin') + return tuple(libfn(self.pointer)) def set_origin(self, new_origin): """ @@ -150,7 +150,7 @@ def set_origin(self, new_origin): if len(new_origin) != self.dimension: raise ValueError('must give a origin value for each dimension (%i)' % self.dimension) - libfn = utils.get_lib_fn('setOrigin%s'%self._libsuffix) + libfn = utils.get_lib_fn('setOrigin') libfn(self.pointer, new_origin) @property @@ -162,8 +162,8 @@ def direction(self): ------- tuple """ - libfn = utils.get_lib_fn('getDirection%s'%self._libsuffix) - return libfn(self.pointer) + libfn = utils.get_lib_fn('getDirection') + return np.array(libfn(self.pointer)).reshape(self.dimension,self.dimension) def set_direction(self, new_direction): """ @@ -187,7 +187,7 @@ def set_direction(self, new_direction): if len(new_direction) != self.dimension: raise ValueError('must give a origin value for each dimension (%i)' % self.dimension) - libfn = utils.get_lib_fn('setDirection%s'%self._libsuffix) + libfn = utils.get_lib_fn('setDirection') libfn(self.pointer, new_direction) @property @@ -221,7 +221,7 @@ def view(self, single_components=False): shape = img.shape[::-1] if img.has_components or (single_components == True): shape = list(shape) + [img.components] - libfn = utils.get_lib_fn('toNumpy%s'%img._libsuffix) + libfn = utils.get_lib_fn('toNumpy') memview = libfn(img.pointer) return np.asarray(memview).view(dtype = dtype).reshape(shape).view(np.ndarray).T @@ -281,7 +281,7 @@ def clone(self, pixeltype=None): p1_short = utils.short_ptype(self.pixeltype) p2_short = utils.short_ptype(pixeltype) ndim = self.dimension - fn_suffix = '%s%i%s%i' % (p1_short,ndim,p2_short,ndim) + fn_suffix = '%s%i' % (p2_short,ndim) libfn = utils.get_lib_fn('antsImageClone%s'%fn_suffix) pointer_cloned = libfn(self.pointer) return ANTsImage(pixeltype=pixeltype, @@ -348,7 +348,7 @@ def to_file(self, filename): filepath to which the image will be written """ filename = os.path.expanduser(filename) - libfn = utils.get_lib_fn('toFile%s'%self._libsuffix) + libfn = utils.get_lib_fn('toFile') libfn(self.pointer, filename) to_filename = to_file diff --git a/ants/lib/CMakeLists.txt b/ants/lib/CMakeLists.txt deleted file mode 100644 index 00763f38..00000000 --- a/ants/lib/CMakeLists.txt +++ /dev/null @@ -1,200 +0,0 @@ -cmake_minimum_required(VERSION 3.0) - -project(ants) - -#set(PYBIND11_CPP_STANDARD -std=c++14) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - - -## SETUP ITK ## -find_package(ITK REQUIRED) -include(${ITK_USE_FILE}) - - -## SETUP PYBIND11 ## -add_subdirectory(pybind11) - -## BUILD ANTS LIBRARIES ## -add_library(antsUtilities STATIC antscore/antsUtilities.cxx - antscore/antsCommandLineOption.cxx - antscore/antsCommandLineParser.cxx - antscore/ReadWriteData.cxx - antscore/ANTsVersion.cxx ) - -add_library(registrationUtilities STATIC antscore/antsRegistrationTemplateHeader.cxx - antscore/antsRegistration2DDouble.cxx antscore/antsRegistration2DFloat.cxx - antscore/antsRegistration3DDouble.cxx antscore/antsRegistration3DFloat.cxx - antscore/antsRegistration4DDouble.cxx antscore/antsRegistration4DFloat.cxx) - -add_library(imageMathUtilities STATIC antscore/ImageMathHelper2D.cxx - antscore/ImageMathHelper3D.cxx antscore/ImageMathHelper4D.cxx) -target_link_libraries(antsUtilities ${ITK_LIBRARIES}) -target_link_libraries(registrationUtilities ${ITK_LIBRARIES}) -target_link_libraries(imageMathUtilities ${ITK_LIBRARIES}) - -# ------------------------------------------------------------ -## BUILD ANTSPY LIBRARY ## - -# MODULES - -## LOCAL ## -pybind11_add_module(addNoiseToImage LOCAL_addNoiseToImage.cxx) -pybind11_add_module(antiAlias LOCAL_antiAlias.cxx) -pybind11_add_module(antsImage LOCAL_antsImage.cxx) -pybind11_add_module(antsImageClone LOCAL_antsImageClone.cxx) -pybind11_add_module(antsImageHeaderInfo LOCAL_antsImageHeaderInfo.cxx) -pybind11_add_module(antsImageMutualInformation LOCAL_antsImageMutualInformation.cxx) -pybind11_add_module(antsImageToImageMetric LOCAL_antsImageToImageMetric.cxx) -pybind11_add_module(antsImageUtils LOCAL_antsImageUtils.cxx) -pybind11_add_module(antsTransform LOCAL_antsTransform.cxx) -pybind11_add_module(composeDisplacementFields LOCAL_composeDisplacementFields.cxx) -pybind11_add_module(cropImage LOCAL_cropImage.cxx) -pybind11_add_module(fitBsplineObjectToScatteredData LOCAL_fitBsplineObjectToScatteredData.cxx) -pybind11_add_module(fitBsplineDisplacementField LOCAL_fitBsplineDisplacementField.cxx) -pybind11_add_module(fitBsplineDisplacementFieldToScatteredData LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx) -pybind11_add_module(fitThinPlateSplineDisplacementFieldToScatteredData LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx) -pybind11_add_module(fsl2antstransform LOCAL_fsl2antstransform.cxx) -pybind11_add_module(getNeighborhoodMatrix LOCAL_getNeighborhoodMatrix.cxx) -pybind11_add_module(hausdorffDistance LOCAL_hausdorffDistance.cxx) -pybind11_add_module(histogramMatchImage LOCAL_histogramMatchImages.cxx) -pybind11_add_module(integrateVelocityField LOCAL_integrateVelocityField.cxx) -pybind11_add_module(invertDisplacementField LOCAL_invertDisplacementField.cxx) -pybind11_add_module(labelOverlapMeasures LOCAL_labelOverlapMeasures.cxx) -pybind11_add_module(labelStats LOCAL_labelStats.cxx) -pybind11_add_module(mergeChannels LOCAL_mergeChannels.cxx) -pybind11_add_module(padImage LOCAL_padImage.cxx) -pybind11_add_module(readImage LOCAL_readImage.cxx) -pybind11_add_module(readTransform LOCAL_readTransform.cxx) -pybind11_add_module(reflectionMatrix LOCAL_reflectionMatrix.cxx) -pybind11_add_module(reorientImage LOCAL_reorientImage.cxx) -pybind11_add_module(reorientImage2 LOCAL_reorientImage2.cxx) -pybind11_add_module(rgbToVector LOCAL_rgbToVector.cxx) -pybind11_add_module(sccaner LOCAL_sccaner.cxx) -pybind11_add_module(simulateDisplacementField LOCAL_simulateDisplacementField.cxx) -pybind11_add_module(sliceImage LOCAL_sliceImage.cxx) -pybind11_add_module(SmoothImage LOCAL_SmoothImage.cxx) -pybind11_add_module(weingartenImageCurvature LOCAL_weingartenImageCurvature.cxx) - -## WRAP ## -pybind11_add_module(antsAffineInitializer antscore/antsAffineInitializer.cxx WRAP_antsAffineInitializer.cxx) -pybind11_add_module(antsApplyTransforms antscore/antsApplyTransforms.cxx WRAP_antsApplyTransforms.cxx) -pybind11_add_module(antsApplyTransformsToPoints antscore/antsApplyTransformsToPoints.cxx WRAP_antsApplyTransformsToPoints.cxx) -pybind11_add_module(antsJointFusion antscore/antsJointFusion.cxx WRAP_antsJointFusion.cxx) -pybind11_add_module(antsRegistration antscore/antsRegistration.cxx WRAP_antsRegistration.cxx) -pybind11_add_module(Atropos antscore/Atropos.cxx WRAP_Atropos.cxx) -pybind11_add_module(CreateJacobianDeterminantImage antscore/CreateJacobianDeterminantImage.cxx WRAP_CreateJacobianDeterminantImage.cxx) -pybind11_add_module(CreateTiledMosaic antscore/CreateTiledMosaic.cxx WRAP_CreateTiledMosaic.cxx) -pybind11_add_module(DenoiseImage antscore/DenoiseImage.cxx WRAP_DenoiseImage.cxx) -pybind11_add_module(iMath antscore/iMath.cxx WRAP_iMath.cxx) -pybind11_add_module(KellyKapowski antscore/KellyKapowski.cxx WRAP_KellyKapowski.cxx) -pybind11_add_module(LabelClustersUniquely antscore/LabelClustersUniquely.cxx WRAP_LabelClustersUniquely.cxx) -pybind11_add_module(LabelGeometryMeasures antscore/LabelGeometryMeasures.cxx WRAP_LabelGeometryMeasures.cxx) -pybind11_add_module(N3BiasFieldCorrection antscore/N3BiasFieldCorrection.cxx WRAP_N3BiasFieldCorrection.cxx) -pybind11_add_module(N4BiasFieldCorrection antscore/N4BiasFieldCorrection.cxx WRAP_N4BiasFieldCorrection.cxx) -pybind11_add_module(ResampleImage antscore/ResampleImage.cxx WRAP_ResampleImage.cxx) -pybind11_add_module(ThresholdImage antscore/ThresholdImage.cxx WRAP_ThresholdImage.cxx) -pybind11_add_module(TileImages antscore/TileImages.cxx WRAP_TileImages.cxx) - -pybind11_add_module(AverageAffineTransform antscore/AverageAffineTransform.cxx WRAP_AverageAffineTransform.cxx) -pybind11_add_module(AverageAffineTransformNoRigid antscore/AverageAffineTransformNoRigid.cxx WRAP_AverageAffineTransformNoRigid.cxx) - -## CONTRIB ## -pybind11_add_module(antsImageAugment CONTRIB_antsImageAugment.cxx) - - -## NOT-WRAPPED ## -#pybind11_add_module(antsLandmarkBasedTransformInitializer antscore/antsLandmarkBasedTransformInitializer.cxx WRAP_antsLandmarkBasedTransformInitializer.cxx) -#pybind11_add_module(antsMotionCorr antscore/antsMotionCorr.cxx WRAP_antsMotionCorr.cxx) -#pybind11_add_module(antsMotionCorrStats antscore/antsMotionCorrStats.cxx WRAP_antsMotionCorrStats.cxx) -#pybind11_add_module(antsSliceRegularizedRegistration antscore/antsSliceRegularizedRegistration.cxx WRAP_antsSliceRegularizedRegistration.cxx) -#pybind11_add_module(LesionFilling antscore/LesionFilling.cxx WRAP_LesionFilling.cxx) -#pybind11_add_module(NonLocalSuperResolution antscore/NonLocalSuperResolution.cxx WRAP_NonLocalSuperResolution.cxx) -#pybind11_add_module(SuperResolution antscore/SuperResolution.cxx WRAP_SuperResolution.cxx) -#pybind11_add_module(TimeSCCAN antscore/TimeSCCAN.cxx WRAP_TimeSCCAN.cxx) - -# ----------------------------------------------------------------- - -## LOCAL ## -target_link_libraries(addNoiseToImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antiAlias PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsImageClone PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsImageHeaderInfo PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsImageMutualInformation PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsImageToImageMetric PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsImageUtils PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsTransform PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(antsTransform PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(composeDisplacementFields PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(cropImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(fitBsplineObjectToScatteredData PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(fitBsplineDisplacementField PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(fitBsplineDisplacementFieldToScatteredData PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(fitThinPlateSplineDisplacementFieldToScatteredData PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(fsl2antstransform PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(getNeighborhoodMatrix PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(hausdorffDistance PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(histogramMatchImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(integrateVelocityField PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(invertDisplacementField PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(labelOverlapMeasures PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(labelStats PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(mergeChannels PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(padImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(readImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(readTransform PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(reflectionMatrix PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(reorientImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(reorientImage2 PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(rgbToVector PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(sccaner PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(simulateDisplacementField PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(sliceImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(SmoothImage PRIVATE ${ITK_LIBRARIES}) -target_link_libraries(weingartenImageCurvature PRIVATE ${ITK_LIBRARIES}) - -## WRAP ## -target_link_libraries(antsAffineInitializer PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -target_link_libraries(antsApplyTransforms PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -target_link_libraries(antsApplyTransformsToPoints PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -target_link_libraries(antsJointFusion PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -target_link_libraries(antsRegistration PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -target_link_libraries(Atropos PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(CreateJacobianDeterminantImage PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(CreateTiledMosaic PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(DenoiseImage PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(iMath PRIVATE ${ITK_LIBRARIES} antsUtilities imageMathUtilities) -target_link_libraries(KellyKapowski PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(LabelClustersUniquely PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(LabelGeometryMeasures PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(N3BiasFieldCorrection PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(N4BiasFieldCorrection PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(ResampleImage PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(ThresholdImage PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(TileImages PRIVATE ${ITK_LIBRARIES} antsUtilities) -target_link_libraries(AverageAffineTransform PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -target_link_libraries(AverageAffineTransformNoRigid PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) - -## CONTRIB ## -target_link_libraries(antsImageAugment PRIVATE ${ITK_LIBRARIES}) - - -## NOT-WRAPPED ## -#target_link_libraries(antsLandmarkBasedTransformInitializer PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -#target_link_libraries(antsMotionCorr PRIVATE ${ITK_LIBRARIES} antsUtilities) -#target_link_libraries(antsMotionCorrStats PRIVATE ${ITK_LIBRARIES} antsUtilities) -#target_link_libraries(antsSliceRegularizedRegistration PRIVATE ${ITK_LIBRARIES} antsUtilities registrationUtilities) -#target_link_libraries(LesionFilling PRIVATE ${ITK_LIBRARIES} antsUtilities) -#target_link_libraries(NonLocalSuperResolution PRIVATE ${ITK_LIBRARIES} antsUtilities) -#target_link_libraries(SuperResolution PRIVATE ${ITK_LIBRARIES} antsUtilities) -#target_link_libraries(TimeSCCAN PRIVATE ${ITK_LIBRARIES} antsUtilities) - -# ----------------------------------------------------------------- -## VIZ ## -#pybind11_add_module(antsSurf antscore/antsSurf.cxx WRAP_antsSurf.cxx) -#pybind11_add_module(antsVol antscore/antsVol.cxx WRAP_antsVol.cxx) -#pybind11_add_module(ConvertScalarImageToRGB antscore/ConvertScalarImageToRGB.cxx WRAP_ConvertScalarImageToRGB.cxx) -# -#target_link_libraries(antsSurf PRIVATE ${ITK_LIBRARIES} ${VTK_LIBRARIES} antsUtilities) -#target_link_libraries(antsVol PRIVATE ${ITK_LIBRARIES} ${VTK_LIBRARIES} antsUtilities) -# target_link_libraries(ConvertScalarImageToRGB PRIVATE ${ITK_LIBRARIES} antsUtilities) diff --git a/ants/lib/CONTRIB_antsImageAugment.cxx b/ants/lib/CONTRIB_antsImageAugment.cxx deleted file mode 100644 index 17eb8b0f..00000000 --- a/ants/lib/CONTRIB_antsImageAugment.cxx +++ /dev/null @@ -1,397 +0,0 @@ - -#include -#include - -#include "itkImage.h" -#include "itkCastImageFilter.h" -#include "itkRescaleIntensityImageFilter.h" -#include "itkNormalizeImageFilter.h" -#include "itkSigmoidImageFilter.h" -#include "itkFlipImageFilter.h" -#include "itkTranslationTransform.h" -#include "itkResampleImageFilter.h" -#include "itkLinearInterpolateImageFunction.h" -#include "itkNearestNeighborInterpolateImageFunction.h" -#include "itkInterpolateImageFunction.h" -#include "itkDiscreteGaussianImageFilter.h" -#include "itkGradientAnisotropicDiffusionImageFilter.h" -#include "itkAnisotropicDiffusionFunction.h" -#include "itkAnisotropicDiffusionImageFilter.h" -#include "itkAnisotropicDiffusionImageFilter.hxx" -#include "itkGradientAnisotropicDiffusionImageFilter.h" -#include "itkImage.h" -#include "itkImageFileWriter.h" -#include "itkRescaleIntensityImageFilter.h" -#include "itkRecursiveMultiResolutionPyramidImageFilter.h" -#include "itkScaleTransform.h" - -#include "LOCAL_antsImage.h" - -namespace py = pybind11; - -/* -Rotate a 2D image -See pg 174 of ITK User Guide Part 2 - -template -py::capsule rotateAntsImage2D( py::capsule & antsImage ) -{ - -} -*/ - - -template -std::vector< py::capsule > multiResolutionAntsImage( py::capsule & antsImage , unsigned int numberOfLevels ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - //unsigned int numberOfLevels = 4; - - typedef itk::RecursiveMultiResolutionPyramidImageFilter - RecursiveMultiResolutionPyramidImageFilterType; - - typename RecursiveMultiResolutionPyramidImageFilterType::Pointer recursiveMultiResolutionPyramidImageFilter = - RecursiveMultiResolutionPyramidImageFilterType::New(); - - recursiveMultiResolutionPyramidImageFilter->SetInput(itkImage); - recursiveMultiResolutionPyramidImageFilter->SetNumberOfLevels(numberOfLevels); - recursiveMultiResolutionPyramidImageFilter->Update(); - - std::vector< py::capsule > newImageList(numberOfLevels); - // This outputs the levels (0 is the lowest resolution) - for(unsigned int i = 0; i < numberOfLevels; ++i) - { - newImageList[i] = wrap< ImageType >( recursiveMultiResolutionPyramidImageFilter->GetOutput(i) ); - } - - return newImageList; -} - -/* -Apply gaussian filter to ANTsImage with given variance and width parameters -*/ -template -py::capsule blurAntsImage( py::capsule & antsImage, - float variance, int maxKernelWidth ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - - typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType > FilterType; - typename FilterType::Pointer filter = FilterType::New(); - filter->SetInput( itkImage ); - - filter->SetVariance( variance ); - filter->SetMaximumKernelWidth( maxKernelWidth ); - - filter->Update(); - return wrap< ImageType >( filter->GetOutput() ); -} - -/* -Apply gaussian filter to ANTsImage with given variance and width parameters -*/ -template -py::capsule locallyBlurAntsImage( py::capsule & antsImage, unsigned long nIterations, - double conductance ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - - typedef itk::GradientAnisotropicDiffusionImageFilter< ImageType, ImageType >FilterType; - typedef typename FilterType::TimeStepType TimeStepType; - - // Select time step size. - TimeStepType spacingsize = 0; - for( unsigned int d = 0; d < ImageType::ImageDimension; d++ ) - { - TimeStepType sp = itkImage->GetSpacing()[d]; - spacingsize += sp * sp; - } - spacingsize = sqrt( spacingsize ); - - // FIXME - cite reason for this step - double dimPlusOne = ImageType::ImageDimension + 1; - TimeStepType mytimestep = spacingsize / std::pow( 2.0 , dimPlusOne ); - TimeStepType reftimestep = 0.4 / std::pow( 2.0 , dimPlusOne ); - if ( mytimestep > reftimestep ) - { - mytimestep = reftimestep; - } - - typename FilterType::Pointer filter = FilterType::New(); - filter->SetInput( itkImage ); - filter->SetConductanceParameter( conductance ); // might need to change this - filter->SetNumberOfIterations( nIterations ); - filter->SetTimeStep( mytimestep ); - - filter->Update(); - //return filter->GetOutput(); - return wrap< ImageType >( filter->GetOutput() ); -} - - -/* -Cast an ANTsImage to another pixel type -*/ -template -py::capsule castAntsImage( py::capsule & antsImage ) -{ - typename InputImageType::Pointer itkImage = as< InputImageType >( antsImage ); - - typedef itk::CastImageFilter CastFilterType; - typename CastFilterType::Pointer castFilter = CastFilterType::New(); - castFilter->SetInput( itkImage ); - - castFilter->Update(); - return wrap< OutputImageType >( castFilter->GetOutput() ); -} - - -/* -Rescale the intensity of an ANTsImage linearly between a given minimum and maximum value -*/ -template -py::capsule rescaleAntsImage( py::capsule & antsImage, float outputMinimum, float outputMaximum ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - - typedef itk::RescaleIntensityImageFilter< ImageType, ImageType > RescaleFilterType; - typename RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); - rescaleFilter->SetInput( itkImage ); - rescaleFilter->SetOutputMinimum( outputMinimum ); - rescaleFilter->SetOutputMaximum( outputMaximum ); - - rescaleFilter->Update(); - return wrap< ImageType >( rescaleFilter->GetOutput() ); -} - -/* -Shift the intensity of an ANTsImage then scale it -*/ -template -py::capsule shiftScaleAntsImage( py::capsule & antsImage, float outputScale, float outputShift ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - - typedef itk::ShiftScaleImageFilter< ImageType, ImageType > ShiftScaleFilterType; - typename ShiftScaleFilterType::Pointer shiftFilter = ShiftScaleFilterType::New(); - shiftFilter->SetInput( itkImage ); - shiftFilter->SetScale( outputScale ); - shiftFilter->SetShift( outputShift ); - - shiftFilter->Update(); - return wrap< ImageType >( shiftFilter->GetOutput() ); -} - -/* -Normalize the intensity of an ANTsImage by setting its mean to zero and variance to one. -*/ -template -py::capsule normalizeAntsImage( py::capsule & antsImage ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - - typedef itk::NormalizeImageFilter< ImageType, ImageType > NormalizeFilterType; - typename NormalizeFilterType::Pointer normalizeFilter = NormalizeFilterType::New(); - normalizeFilter->SetInput( itkImage ); - - normalizeFilter->Update(); - return wrap< ImageType >( normalizeFilter->GetOutput() ); -} - -/* -Apply Sigmoid filter to ANTsImage with given alpha and gamma parameters -*/ -template -py::capsule sigmoidAntsImage( py::capsule & antsImage, - float outputMinimum, float outputMaximum, - float alpha, float beta ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - - typedef itk::SigmoidImageFilter< ImageType, ImageType > SigmoidFilterType; - typename SigmoidFilterType::Pointer sigmoidFilter = SigmoidFilterType::New(); - sigmoidFilter->SetInput( itkImage ); - sigmoidFilter->SetOutputMinimum( outputMinimum ); - sigmoidFilter->SetOutputMaximum( outputMaximum ); - sigmoidFilter->SetAlpha( alpha ); - sigmoidFilter->SetBeta( beta ); - - sigmoidFilter->Update(); - return wrap< ImageType >( sigmoidFilter->GetOutput() ); -} - - -/* -Filp an ANTsImage in a given direction -*/ -template -py::capsule flipAntsImage( py::capsule & antsImage, unsigned int axis1, unsigned int axis2 ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - - typedef itk::FlipImageFilter< ImageType > FlipFilterType; - typename FlipFilterType::Pointer flipFilter = FlipFilterType::New(); - flipFilter->SetInput( itkImage ); - - typedef typename FlipFilterType::FlipAxesArrayType FlipAxesArrayType; - FlipAxesArrayType flipArray; - flipArray[0] = axis1; - flipArray[1] = axis2; - flipFilter->SetFlipAxes( flipArray ); - - flipFilter->Update(); - return wrap< ImageType >( flipFilter->GetOutput() ); -} - -/* -Apply a translation to an ANTsImage. This function uses itk::TranslationTransform -which is faster than using itk::AffineTransform. - -General steps for applying an ITK transform to an ANTsImage: -- unwrap py::capsule(s) -- create new transform smartpointer -- set transform parameters, etc -- create resample filter -- create interpolation filter -- set resample filter parameters, etc -*/ -template -py::capsule translateAntsImage( py::capsule & inputAntsImage, py::capsule refAntsImage, std::vector translationList) -{ - // unwrap ANTsImage(s) - typename ImageType::Pointer inputImage = as< ImageType >( inputAntsImage ); - typename ImageType::Pointer refImage = as< ImageType >( refAntsImage ); - - // create new transform smartpointer - typedef itk::TranslationTransform TranslationTransformType; - typename TranslationTransformType::Pointer translationTransform = TranslationTransformType::New(); - - // set transform parameters, etc - typename TranslationTransformType::OutputVectorType translation; - for (unsigned int i = 0; i < translationList.size(); ++i ) - { - translation[i] = translationList[i]; - } - translationTransform->Translate(translation); - - // create resample filter - typedef itk::ResampleImageFilter ResampleFilterType; - typename ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New(); - - // create interpolation filter - typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); - - // set resample filter parameters, etc - resampleFilter->SetInput( inputImage ); - resampleFilter->SetSize( refImage->GetLargestPossibleRegion().GetSize() ); - resampleFilter->SetOutputSpacing( refImage->GetSpacing() ); - resampleFilter->SetOutputOrigin( refImage->GetOrigin() ); - resampleFilter->SetOutputDirection( refImage->GetDirection() ); - resampleFilter->SetInterpolator( interpolator ); - - resampleFilter->SetTransform( translationTransform ); - resampleFilter->Update(); - - return wrap< ImageType >( resampleFilter->GetOutput() ); -} - - -/* -Scale an ANTsImage -*/ -template -py::capsule scaleAntsImage( py::capsule & antsImage, py::capsule & antsRefImage, std::vector scaleList ) -{ - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); - typename ImageType::Pointer refImage = as< ImageType >( antsRefImage ); - - typedef itk::ScaleTransform TransformType; - typename TransformType::Pointer transform = TransformType::New(); - - itk::FixedArray scale; - for (unsigned int i = 0; i < Dimension; i++ ) - { - scale[i] = scaleList[i]; - } - transform->SetScale(scale); - - itk::Point center; - for (unsigned int i = 0; i < Dimension; i++ ) - { - center[i] = itkImage->GetOrigin()[i] + itkImage->GetSpacing()[i] * itkImage->GetLargestPossibleRegion().GetSize()[i]/2; - } - transform->SetCenter(center); - - // create resample filter - typedef itk::ResampleImageFilter ResampleFilterType; - typename ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New(); - - // create interpolation filter - typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); - - // set resample filter parameters, etc - resampleFilter->SetInput( itkImage ); - resampleFilter->SetSize( refImage->GetLargestPossibleRegion().GetSize() ); - resampleFilter->SetOutputSpacing( refImage->GetSpacing() ); - resampleFilter->SetOutputOrigin( refImage->GetOrigin() ); - resampleFilter->SetOutputDirection( refImage->GetDirection() ); - resampleFilter->SetInterpolator( interpolator ); - - resampleFilter->SetTransform( transform ); - resampleFilter->Update(); - - return wrap< ImageType >( resampleFilter->GetOutput() ); -} - - -PYBIND11_MODULE(antsImageAugment, m) -{ - m.def("multiResolutionAntsImageF2", &multiResolutionAntsImage>); - m.def("multiResolutionAntsImageF3", &multiResolutionAntsImage>); - - m.def("blurAntsImageF2", &blurAntsImage>); - m.def("blurAntsImageF3", &blurAntsImage>); - - m.def("locallyBlurAntsImageF2", &locallyBlurAntsImage>); - m.def("locallyBlurAntsImageF3", &locallyBlurAntsImage>); - - m.def("castAntsImageUC2F2", &castAntsImage,itk::Image>); - m.def("castAntsImageUI2F2", &castAntsImage,itk::Image>); - m.def("castAntsImageD2F2", &castAntsImage,itk::Image>); - - m.def("castAntsImageUC3F3", &castAntsImage,itk::Image>); - m.def("castAntsImageUI3F3", &castAntsImage,itk::Image>); - m.def("castAntsImageD3F3", &castAntsImage,itk::Image>); - - m.def("rescaleAntsImageF2", &rescaleAntsImage>); - m.def("rescaleAntsImageF3", &rescaleAntsImage>); - - m.def("shiftScaleAntsImageF2", &shiftScaleAntsImage>); - m.def("shiftScaleAntsImageF3", &shiftScaleAntsImage>); - - m.def("normalizeAntsImageF2", &normalizeAntsImage>); - m.def("normalizeAntsImageF3", &normalizeAntsImage>); - - m.def("sigmoidAntsImageF2", &sigmoidAntsImage>); - m.def("sigmoidAntsImageF3", &sigmoidAntsImage>); - - m.def("flipAntsImageF2", &flipAntsImage>); - m.def("flipAntsImageF3", &flipAntsImage>); - - m.def("translateAntsImageF2_linear", &translateAntsImage, itk::LinearInterpolateImageFunction, float>, float, 2>); - m.def("translateAntsImageF2_nearest", &translateAntsImage, itk::NearestNeighborInterpolateImageFunction, float>, float, 2>); - m.def("translateAntsImageF3_linear", &translateAntsImage, itk::LinearInterpolateImageFunction, float>, float, 3>); - m.def("translateAntsImageF3_nearest", &translateAntsImage, itk::NearestNeighborInterpolateImageFunction, float>, float, 3>); - - m.def("scaleAntsImageF2_linear", &scaleAntsImage, itk::LinearInterpolateImageFunction, float>, float, 2>); - m.def("scaleAntsImageF2_nearest", &scaleAntsImage, itk::NearestNeighborInterpolateImageFunction, float>, float, 2>); - m.def("scaleAntsImageF3_linear", &scaleAntsImage, itk::LinearInterpolateImageFunction, float>, float, 3>); - m.def("scaleAntsImageF3_nearest", &scaleAntsImage, itk::NearestNeighborInterpolateImageFunction, float>, float, 3>); - -} - - - - - - diff --git a/ants/lib/LOCAL_antsImage.cxx b/ants/lib/LOCAL_antsImage.cxx deleted file mode 100644 index a112f4cc..00000000 --- a/ants/lib/LOCAL_antsImage.cxx +++ /dev/null @@ -1,316 +0,0 @@ - -#include -#include -#include - -#include "itkImage.h" -#include "itkImageFileReader.h" -#include "itkPyBuffer.h" - -#include "itkMath.h" -#include "itkPyVnl.h" -#include "itkMatrix.h" -#include "vnl/vnl_matrix_fixed.hxx" -#include "vnl/vnl_transpose.h" -#include "vnl/algo/vnl_matrix_inverse.h" -#include "vnl/vnl_matrix.h" -#include "vnl/algo/vnl_determinant.h" -#include "LOCAL_antsImage.h" - - -namespace py = pybind11; - -template -py::array numpyHelper( typename ImageType::Pointer itkImage ) -{ - typedef itk::PyBuffer PyBufferType; - PyObject * itkArray = PyBufferType::_GetArrayViewFromImage( itkImage ); - py::array itkArrayObject = py::reinterpret_steal( itkArray ); - - return itkArrayObject; - -} - -template -py::array toNumpy( py::capsule myPointer ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - return numpyHelper( itkImage ); -} - -std::string ptrstr(py::capsule c) -{ - std::stringstream ss; - ss << (void const *)c; - std::string s = ss.str(); - return s; -} - - - - -PYBIND11_MODULE(antsImage, m) { - m.def("ptrstr", &ptrstr); - - m.def("getShapeUC2", &getShape>); - m.def("getShapeUC3", &getShape>); - m.def("getShapeUC4", &getShape>); - m.def("getShapeUI2", &getShape>); - m.def("getShapeUI3", &getShape>); - m.def("getShapeUI4", &getShape>); - m.def("getShapeF2", &getShape>); - m.def("getShapeF3", &getShape>); - m.def("getShapeF4", &getShape>); - m.def("getShapeD2", &getShape>); - m.def("getShapeD3", &getShape>); - m.def("getShapeD4", &getShape>); - m.def("getShapeVUC2", &getShape>); - m.def("getShapeVUC3", &getShape>); - m.def("getShapeVUC4", &getShape>); - m.def("getShapeVUI2", &getShape>); - m.def("getShapeVUI3", &getShape>); - m.def("getShapeVUI4", &getShape>); - m.def("getShapeVF2", &getShape>); - m.def("getShapeVF3", &getShape>); - m.def("getShapeVF4", &getShape>); - m.def("getShapeVD2", &getShape>); - m.def("getShapeVD3", &getShape>); - m.def("getShapeVD4", &getShape>); - m.def("getShapeRGBUC2", &getShape,2>>); - m.def("getShapeRGBUC3", &getShape,3>>); - m.def("getShapeRGBF2", &getShape,2>>); - m.def("getShapeRGBF3", &getShape,3>>); - - m.def("getOriginUC2", &getOrigin>); - m.def("getOriginUC3", &getOrigin>); - m.def("getOriginUC4", &getOrigin>); - m.def("getOriginUI2", &getOrigin>); - m.def("getOriginUI3", &getOrigin>); - m.def("getOriginUI4", &getOrigin>); - m.def("getOriginF2", &getOrigin>); - m.def("getOriginF3", &getOrigin>); - m.def("getOriginF4", &getOrigin>); - m.def("getOriginD2", &getOrigin>); - m.def("getOriginD3", &getOrigin>); - m.def("getOriginD4", &getOrigin>); - m.def("getOriginVUC2", &getOrigin>); - m.def("getOriginVUC3", &getOrigin>); - m.def("getOriginVUC4", &getOrigin>); - m.def("getOriginVUI2", &getOrigin>); - m.def("getOriginVUI3", &getOrigin>); - m.def("getOriginVUI4", &getOrigin>); - m.def("getOriginVF2", &getOrigin>); - m.def("getOriginVF3", &getOrigin>); - m.def("getOriginVF4", &getOrigin>); - m.def("getOriginVD2", &getOrigin>); - m.def("getOriginVD3", &getOrigin>); - m.def("getOriginVD4", &getOrigin>); - m.def("getOriginRGBUC2", &getOrigin,2>>); - m.def("getOriginRGBUC3", &getOrigin,3>>); - m.def("getOriginRGBF2", &getOrigin,2>>); - m.def("getOriginRGBF3", &getOrigin,3>>); - - m.def("setOriginUC2", &setOrigin>); - m.def("setOriginUC3", &setOrigin>); - m.def("setOriginUC4", &setOrigin>); - m.def("setOriginUI2", &setOrigin>); - m.def("setOriginUI3", &setOrigin>); - m.def("setOriginUI4", &setOrigin>); - m.def("setOriginF2", &setOrigin>); - m.def("setOriginF3", &setOrigin>); - m.def("setOriginF4", &setOrigin>); - m.def("setOriginD2", &setOrigin>); - m.def("setOriginD3", &setOrigin>); - m.def("setOriginD4", &setOrigin>); - m.def("setOriginVUC2", &setOrigin>); - m.def("setOriginVUC3", &setOrigin>); - m.def("setOriginVUC4", &setOrigin>); - m.def("setOriginVUI2", &setOrigin>); - m.def("setOriginVUI3", &setOrigin>); - m.def("setOriginVUI4", &setOrigin>); - m.def("setOriginVF2", &setOrigin>); - m.def("setOriginVF3", &setOrigin>); - m.def("setOriginVF4", &setOrigin>); - m.def("setOriginVD2", &setOrigin>); - m.def("setOriginVD3", &setOrigin>); - m.def("setOriginVD4", &setOrigin>); - m.def("setOriginRGBUC2", &setOrigin,2>>); - m.def("setOriginRGBUC3", &setOrigin,3>>); - m.def("setOriginRGBF2", &setOrigin,2>>); - m.def("setOriginRGBF3", &setOrigin,3>>); - - m.def("getSpacingUC2", &getSpacing>); - m.def("getSpacingUC3", &getSpacing>); - m.def("getSpacingUC4", &getSpacing>); - m.def("getSpacingUI2", &getSpacing>); - m.def("getSpacingUI3", &getSpacing>); - m.def("getSpacingUI4", &getSpacing>); - m.def("getSpacingF2", &getSpacing>); - m.def("getSpacingF3", &getSpacing>); - m.def("getSpacingF4", &getSpacing>); - m.def("getSpacingD2", &getSpacing>); - m.def("getSpacingD3", &getSpacing>); - m.def("getSpacingD4", &getSpacing>); - m.def("getSpacingVUC2", &getSpacing>); - m.def("getSpacingVUC3", &getSpacing>); - m.def("getSpacingVUC4", &getSpacing>); - m.def("getSpacingVUI2", &getSpacing>); - m.def("getSpacingVUI3", &getSpacing>); - m.def("getSpacingVUI4", &getSpacing>); - m.def("getSpacingVF2", &getSpacing>); - m.def("getSpacingVF3", &getSpacing>); - m.def("getSpacingVF4", &getSpacing>); - m.def("getSpacingVD2", &getSpacing>); - m.def("getSpacingVD3", &getSpacing>); - m.def("getSpacingVD4", &getSpacing>); - m.def("getSpacingRGBUC2", &getSpacing,2>>); - m.def("getSpacingRGBUC3", &getSpacing,3>>); - m.def("getSpacingRGBF2", &getSpacing,2>>); - m.def("getSpacingRGBF3", &getSpacing,3>>); - - m.def("setSpacingUC2", &setSpacing>); - m.def("setSpacingUC3", &setSpacing>); - m.def("setSpacingUC4", &setSpacing>); - m.def("setSpacingUI2", &setSpacing>); - m.def("setSpacingUI3", &setSpacing>); - m.def("setSpacingUI4", &setSpacing>); - m.def("setSpacingF2", &setSpacing>); - m.def("setSpacingF3", &setSpacing>); - m.def("setSpacingF4", &setSpacing>); - m.def("setSpacingD2", &setSpacing>); - m.def("setSpacingD3", &setSpacing>); - m.def("setSpacingD4", &setSpacing>); - m.def("setSpacingVUC2", &setSpacing>); - m.def("setSpacingVUC3", &setSpacing>); - m.def("setSpacingVUC4", &setSpacing>); - m.def("setSpacingVUI2", &setSpacing>); - m.def("setSpacingVUI3", &setSpacing>); - m.def("setSpacingVUI4", &setSpacing>); - m.def("setSpacingVF2", &setSpacing>); - m.def("setSpacingVF3", &setSpacing>); - m.def("setSpacingVF4", &setSpacing>); - m.def("setSpacingVD2", &setSpacing>); - m.def("setSpacingVD3", &setSpacing>); - m.def("setSpacingVD4", &setSpacing>); - m.def("setSpacingRGBUC2", &setSpacing,2>>); - m.def("setSpacingRGBUC3", &setSpacing,3>>); - m.def("setSpacingRGBF2", &setSpacing,2>>); - m.def("setSpacingRGBF3", &setSpacing,3>>); - - m.def("getDirectionUC2", &getDirection>); - m.def("getDirectionUC3", &getDirection>); - m.def("getDirectionUC4", &getDirection>); - m.def("getDirectionUI2", &getDirection>); - m.def("getDirectionUI3", &getDirection>); - m.def("getDirectionUI4", &getDirection>); - m.def("getDirectionF2", &getDirection>); - m.def("getDirectionF3", &getDirection>); - m.def("getDirectionF4", &getDirection>); - m.def("getDirectionD2", &getDirection>); - m.def("getDirectionD3", &getDirection>); - m.def("getDirectionD4", &getDirection>); - m.def("getDirectionVUC2", &getDirection>); - m.def("getDirectionVUC3", &getDirection>); - m.def("getDirectionVUC4", &getDirection>); - m.def("getDirectionVUI2", &getDirection>); - m.def("getDirectionVUI3", &getDirection>); - m.def("getDirectionVUI4", &getDirection>); - m.def("getDirectionVF2", &getDirection>); - m.def("getDirectionVF3", &getDirection>); - m.def("getDirectionVF4", &getDirection>); - m.def("getDirectionVD2", &getDirection>); - m.def("getDirectionVD3", &getDirection>); - m.def("getDirectionVD4", &getDirection>); - m.def("getDirectionRGBUC2", &getDirection,2>>); - m.def("getDirectionRGBUC3", &getDirection,3>>); - m.def("getDirectionRGBF2", &getDirection,2>>); - m.def("getDirectionRGBF3", &getDirection,3>>); - - m.def("setDirectionUC2", &setDirection>); - m.def("setDirectionUC3", &setDirection>); - m.def("setDirectionUC4", &setDirection>); - m.def("setDirectionUI2", &setDirection>); - m.def("setDirectionUI3", &setDirection>); - m.def("setDirectionUI4", &setDirection>); - m.def("setDirectionF2", &setDirection>); - m.def("setDirectionF3", &setDirection>); - m.def("setDirectionF4", &setDirection>); - m.def("setDirectionD2", &setDirection>); - m.def("setDirectionD3", &setDirection>); - m.def("setDirectionD4", &setDirection>); - m.def("setDirectionVUC2", &setDirection>); - m.def("setDirectionVUC3", &setDirection>); - m.def("setDirectionVUC4", &setDirection>); - m.def("setDirectionVUI2", &setDirection>); - m.def("setDirectionVUI3", &setDirection>); - m.def("setDirectionVUI4", &setDirection>); - m.def("setDirectionVF2", &setDirection>); - m.def("setDirectionVF3", &setDirection>); - m.def("setDirectionVF4", &setDirection>); - m.def("setDirectionVD2", &setDirection>); - m.def("setDirectionVD3", &setDirection>); - m.def("setDirectionVD4", &setDirection>); - m.def("setDirectionRGBUC2", &setDirection,2>>); - m.def("setDirectionRGBUC3", &setDirection,3>>); - m.def("setDirectionRGBF2", &setDirection,2>>); - m.def("setDirectionRGBF3", &setDirection,3>>); - - m.def("toFileUC2", &toFile>); - m.def("toFileUC3", &toFile>); - m.def("toFileUC4", &toFile>); - m.def("toFileUI2", &toFile>); - m.def("toFileUI3", &toFile>); - m.def("toFileUI4", &toFile>); - m.def("toFileF2", &toFile>); - m.def("toFileF3", &toFile>); - m.def("toFileF4", &toFile>); - m.def("toFileD2", &toFile>); - m.def("toFileD3", &toFile>); - m.def("toFileD4", &toFile>); - m.def("toFileVUC2", &toFile>); - m.def("toFileVUC3", &toFile>); - m.def("toFileVUC4", &toFile>); - m.def("toFileVUI2", &toFile>); - m.def("toFileVUI3", &toFile>); - m.def("toFileVUI4", &toFile>); - m.def("toFileVF2", &toFile>); - m.def("toFileVF3", &toFile>); - m.def("toFileVF4", &toFile>); - m.def("toFileVD2", &toFile>); - m.def("toFileVD3", &toFile>); - m.def("toFileVD4", &toFile>); - m.def("toFileRGBUC2", &toFile,2>>); - m.def("toFileRGBUC3", &toFile,3>>); - m.def("toFileRBGF2", &toFile,2>>); - m.def("toFileRBGF3", &toFile,3>>); - - m.def("toNumpyUC2", &toNumpy>); - m.def("toNumpyUC3", &toNumpy>); - m.def("toNumpyUC4", &toNumpy>); - m.def("toNumpyUI2", &toNumpy>); - m.def("toNumpyUI3", &toNumpy>); - m.def("toNumpyUI4", &toNumpy>); - m.def("toNumpyF2", &toNumpy>); - m.def("toNumpyF3", &toNumpy>); - m.def("toNumpyF4", &toNumpy>); - m.def("toNumpyD2", &toNumpy>); - m.def("toNumpyD3", &toNumpy>); - m.def("toNumpyD4", &toNumpy>); - m.def("toNumpyVUC2", &toNumpy>); - m.def("toNumpyVUC3", &toNumpy>); - m.def("toNumpyVUC4", &toNumpy>); - m.def("toNumpyVUI2", &toNumpy>); - m.def("toNumpyVUI3", &toNumpy>); - m.def("toNumpyVUI4", &toNumpy>); - m.def("toNumpyVF2", &toNumpy>); - m.def("toNumpyVF3", &toNumpy>); - m.def("toNumpyVF4", &toNumpy>); - m.def("toNumpyVD2", &toNumpy>); - m.def("toNumpyVD3", &toNumpy>); - m.def("toNumpyVD4", &toNumpy>); - m.def("toNumpyRGBUC2", &toNumpy,2>>); - m.def("toNumpyRGBUC3", &toNumpy,3>>); - m.def("toNumpyRGBF2", &toNumpy,2>>); - m.def("toNumpyRGBF3", &toNumpy,3>>); - -} diff --git a/ants/lib/LOCAL_antsImage.h b/ants/lib/LOCAL_antsImage.h deleted file mode 100644 index d2d83f86..00000000 --- a/ants/lib/LOCAL_antsImage.h +++ /dev/null @@ -1,380 +0,0 @@ -#ifndef __ANTSPYIMAGE_H -#define __ANTSPYIMAGE_H - -#include -#include -#include - -#include "itkImageIOBase.h" - -#include "itkImage.h" -#include "itkImageFileReader.h" -#include "itkImageFileWriter.h" -#include "itkPyBuffer.h" -#include "itkVectorImage.h" -#include "itkChangeInformationImageFilter.h" - -#include "itkMath.h" -#include "itkPyVnl.h" -#include "itkMatrix.h" -#include "vnl/vnl_matrix_fixed.hxx" -#include "vnl/vnl_transpose.h" -#include "vnl/algo/vnl_matrix_inverse.h" -#include "vnl/vnl_matrix.h" -#include "vnl/algo/vnl_determinant.h" - -namespace py = pybind11; - -/* -template -class ANTsImage { -public: - typedef ImageType itkImageType; - // standard image properties which can't be directly changed - std::string pixeltype; - std::string dtype; - unsigned int dimension; - unsigned int components; - //py::tuple shape; - py::array _ndarr; // needed for creating image from numpy array - - // VERY important - holds pointer to itk::Image - py::capsule pointer; - - // physical image properties which can be directly changed - - // SHAPE (can be changed through resampling) - py::tuple getShape(); - - // ORIGIN - py::tuple getOrigin(); - void setOrigin( std::vector ); - - // SPACING - py::tuple getSpacing(); - void setSpacing( std::vector ); - - // DIRECTION - py::array getDirection(); - void setDirection( py::array ); - - // convert to numpy array - py::array numpy(); - void toFile( std::string ); - -}; - - -// gets associated ITK pixel type as string -std::string getPixelTypeStringFromDummy( unsigned char dummyval ) { return "unsigned char"; } -std::string getPixelTypeStringFromDummy( unsigned int dummyval ) { return "unsigned int"; } -std::string getPixelTypeStringFromDummy( float dummyval ) { return "float"; } -std::string getPixelTypeStringFromDummy( double dummyval ) { return "double"; } - -std::string getPixelTypeStringFromDummy( itk::VariableLengthVector dummyval ) { return "unsigned char"; } -std::string getPixelTypeStringFromDummy( itk::VariableLengthVector dummyval ) { return "unsigned int"; } -std::string getPixelTypeStringFromDummy( itk::VariableLengthVectordummyval ) { return "float"; } -std::string getPixelTypeStringFromDummy( itk::VariableLengthVector dummyval ) { return "double"; } - -std::string getPixelTypeStringFromDummy( itk::RGBPixel dummyval ) { return "unsigned char"; } - -// gets associated NUMPY data type as string -std::string getDataTypeStringFromDummy( unsigned char dummyval ) { return "uint8"; } -std::string getDataTypeStringFromDummy( unsigned int dummyval ) { return "uint32"; } -std::string getDataTypeStringFromDummy( float dummyval ) { return "float32"; } -std::string getDataTypeStringFromDummy( double dummyval ) { return "float64"; } -std::string getDataTypeStringFromDummy( itk::VariableLengthVector dummyval ) { return "uint8"; } -std::string getDataTypeStringFromDummy( itk::VariableLengthVector dummyval ) { return "uint32"; } -std::string getDataTypeStringFromDummy( itk::VariableLengthVector dummyval ) { return "float32"; } -std::string getDataTypeStringFromDummy( itk::VariableLengthVector dummyval ) { return "float64"; } -std::string getDataTypeStringFromDummy( itk::RGBPixel dummyval ) { return "uint8"; } - - -template -py::capsule wrap( const typename ImageType::Pointer &image ) -{ - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType * ptr = new ImagePointerType( image ); - - std::string ptype; - std::string dtype; - - typename ImageType::PixelType dummyval; - ptype = getPixelTypeStringFromDummy(dummyval); - dtype = getDataTypeStringFromDummy(dummyval); - unsigned int ndim = ImageType::GetImageDimension(); - - ANTsImage antsimage; - antsimage.pixeltype = ptype; - antsimage.dtype = dtype; - antsimage.dimension = ndim; - antsimage.components = image->GetNumberOfComponentsPerPixel(); - antsimage.pointer = py::capsule(ptr, "itk::Image::Pointer"); - - return antsimage; -} -*/ - -template -void capsuleDestructor( void * f ) -{ - //std::cout << "calling capsule destructor" << std::endl; - typename ImageType::Pointer * foo = reinterpret_cast( f ); - *foo = ITK_NULLPTR; -} - -// converts an ITK image pointer to a py::capsule -template -py::capsule wrap( const typename ImageType::Pointer &image ) -{ - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType * ptr = new ImagePointerType( image ); - return py::capsule(ptr, capsuleDestructor); -} - -/* -// converts a py::capsule to an ITK image pointer -template -typename ImageType::Pointer as( py::capsule pointer ) -{ - return static_cast(pointer); -} -*/ -template -typename ImageType::Pointer as( void * ptr ) -{ - //void *ptr = image.pointer; - typename ImageType::Pointer * real = static_cast(ptr); // static_cast or reinterpret_cast ?? - return *real; -} - - -template -void toFile( py::capsule & myPointer, std::string filename ) -{ - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType image = ImageType::New(); - - image = as( myPointer ); - - typedef itk::ImageFileWriter< ImageType > ImageWriterType ; - typename ImageWriterType::Pointer image_writer = ImageWriterType::New() ; - image_writer->SetFileName( filename.c_str() ) ; - image_writer->SetInput( image ); - image_writer->Update(); -} - - -template -py::tuple getShapeHelper( typename ImageType::Pointer image ) -{ - unsigned int ndim = ImageType::GetImageDimension(); - image->UpdateOutputInformation(); - typename ImageType::SizeType shape = image->GetBufferedRegion().GetSize(); - py::list shapelist; - for (int i = 0; i < ndim; i++) - { - shapelist.append( shape[i] ); - } - return shapelist; -} - -template -py::tuple getShape( py::capsule & myPointer ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - return getShapeHelper( itkImage ); -} - - -template -py::tuple getOriginHelper( typename ImageType::Pointer image ) -{ - typename ImageType::PointType origin = image->GetOrigin(); - unsigned int ndim = ImageType::GetImageDimension(); - - py::list originlist; - for (int i = 0; i < ndim; i++) - { - originlist.append( origin[i] ); - } - - return originlist; -} - -template -py::tuple getOrigin( py::capsule & myPointer ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - return getOriginHelper( itkImage ); -} - -template -void setOriginHelper( typename ImageType::Pointer &itkImage, std::vector new_origin) -{ - unsigned int nvals = new_origin.size(); - typename ImageType::PointType origin = itkImage->GetOrigin(); - for (int i = 0; i < nvals; i++) - { - origin[i] = new_origin[i]; - } - itkImage->SetOrigin( origin ); -} - -template -void setOrigin( py::capsule & myPointer, std::vector new_origin ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - setOriginHelper( itkImage, new_origin ); -} - - - -template -py::array getDirectionHelper( typename ImageType::Pointer image ) -{ - typedef typename ImageType::DirectionType ImageDirectionType; - ImageDirectionType direction = image->GetDirection(); - - typedef typename ImageDirectionType::InternalMatrixType DirectionInternalMatrixType; - DirectionInternalMatrixType fixed_matrix = direction.GetVnlMatrix(); - - vnl_matrix vnlmat1 = fixed_matrix.as_matrix(); - - const unsigned int ndim = ImageType::SizeType::GetSizeDimension(); - - vnl_matrix * vnlmat2 = new vnl_matrix; - vnlmat2->set_size(ndim, ndim); - vnlmat2->fill(0); - for (int i = 0; i < ndim; i++) - { - for (int j = 0; j < ndim; j++) - { - vnlmat2->put(i, j, vnlmat1(i,j)); - } - } - - typedef itk::PyVnl PyVnlType; - PyObject * mymatrix = PyVnlType::_GetArrayViewFromVnlMatrix( vnlmat2 ); - py::array myarray = py::reinterpret_borrow( mymatrix ); - std::string viewtype( "float64" ); - py::array myarrayview = myarray.view( viewtype ).reshape({ndim, ndim}); - - return myarrayview; -} - -template -py::array getDirection( py::capsule & myPointer ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - return getDirectionHelper( itkImage ); -} - - -template -void setDirectionHelper( typename ImageType::Pointer &itkImage, py::array new_direction) -{ - // using FilterType = itk::ChangeInformationImageFilter; - // typename FilterType::Pointer filter = FilterType::New(); - // filter->SetInput( itkImage ); - // filter->ChangeDirectionOn(); - - PyObject * new_dir_obj = new_direction.ptr(); - - py::tuple shapetuple = py::make_tuple( new_direction.shape(0), new_direction.shape(1) ); - PyObject * new_dir_shape = shapetuple.ptr(); - - typedef itk::PyVnl PyVnlType; - vnl_matrix new_matrix = PyVnlType::_GetVnlMatrixViewFromArray( new_dir_obj, new_dir_shape ); - - typename ImageType::DirectionType new_matrix2 = itkImage->GetDirection( ); - for ( py::ssize_t i = 0; i < new_direction.shape(0); i++ ) - for ( py::ssize_t j = 0; j < new_direction.shape(1); j++ ) { - new_matrix2(i,j) = new_matrix(i,j); - } - itkImage->SetDirection( new_matrix2 ); -} - -template -void setDirection( py::capsule & myPointer, py::array new_direction ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - setDirectionHelper( itkImage, new_direction ); -} - -template -void setSpacingHelper( typename ImageType::Pointer &itkImage, std::vector new_spacing) -{ - unsigned int nvals = new_spacing.size(); - typename ImageType::SpacingType spacing = itkImage->GetSpacing(); - for (int i = 0; i < nvals; i++) - { - spacing[i] = new_spacing[i]; - } - itkImage->SetSpacing( spacing ); -} - -template -void setSpacing( py::capsule & myPointer, std::vector new_spacing ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - setSpacingHelper( itkImage, new_spacing ); -} - -template -py::tuple getSpacingHelper( typename ImageType::Pointer image ) -{ - typename ImageType::SpacingType spacing = image->GetSpacing(); - unsigned int ndim = ImageType::GetImageDimension(); - - py::list spacinglist; - for (int i = 0; i < ndim; i++) - { - spacinglist.append( spacing[i] ); - } - - return spacinglist; -} - -template -py::tuple getSpacing( py::capsule & myPointer ) -{ - typename ImageType::Pointer itkImage = as( myPointer ); - return getSpacingHelper( itkImage ); -} - -extern std::string ptrstr(py::capsule c); - -/* -This function resets the region of an image to index from zero if needed. This -keeps the voxel indices in the numpy matrix consistent with the ITK image, and -also keeps the origin of physical space of the consistent with how it will be -saved as NIFTI. -*/ -template -static void FixNonZeroIndex( typename ImageType::Pointer img ) -{ - assert(img); - - typename ImageType::RegionType r = img->GetLargestPossibleRegion(); - typename ImageType::IndexType idx = r.GetIndex(); - - for (unsigned int i = 0; i < ImageType::ImageDimension; ++i) - { - // if any index is non-zero, reset the origin and region - if ( idx[i] != 0 ) - { - typename ImageType::PointType o; - img->TransformIndexToPhysicalPoint( idx, o ); - img->SetOrigin( o ); - - idx.Fill( 0 ); - r.SetIndex( idx ); - img->SetRegions( r ); - - return; - } - } -} - -#endif diff --git a/ants/lib/LOCAL_antsImageClone.cxx b/ants/lib/LOCAL_antsImageClone.cxx deleted file mode 100644 index 307a1788..00000000 --- a/ants/lib/LOCAL_antsImageClone.cxx +++ /dev/null @@ -1,117 +0,0 @@ - -#include -#include - -#include -#include -#include - -#include "itkImage.h" -#include "itkImageFileWriter.h" - -#include "LOCAL_antsImage.h" - -namespace py = pybind11; - -template -py::capsule antsImageClone( py::capsule antsImage ) -{ - typedef typename InImageType::Pointer InImagePointerType; - InImagePointerType in_image = as< InImageType >( antsImage ); - - typename OutImageType::Pointer out_image = OutImageType::New() ; - out_image->SetRegions( in_image->GetLargestPossibleRegion() ) ; - out_image->SetSpacing( in_image->GetSpacing() ) ; - out_image->SetOrigin( in_image->GetOrigin() ) ; - out_image->SetDirection( in_image->GetDirection() ); - //out_image->CopyInformation( in_image ); - out_image->AllocateInitialized(); - - itk::ImageRegionConstIterator< InImageType > in_iterator( in_image , in_image->GetLargestPossibleRegion() ) ; - itk::ImageRegionIterator< OutImageType > out_iterator( out_image , out_image->GetLargestPossibleRegion() ) ; - for( in_iterator.GoToBegin() , out_iterator.GoToBegin() ; !in_iterator.IsAtEnd() ; ++in_iterator , ++out_iterator ) - { - out_iterator.Set( static_cast< typename OutImageType::PixelType >( in_iterator.Get() ) ) ; - } - return wrap< OutImageType >( out_image ); -} - -template -void wrapantsImageClone(py::module & m, std::string const & suffix) { - m.def(("antsImageClone"+suffix).c_str(), &antsImageClone); -} - -//pixels: Image, VectorImage -//types: unsigned char, unsigned int, float, double -//dims: 2, 3, 4 -PYBIND11_MODULE(antsImageClone, m) -{ - // dim = 2 - wrapantsImageClone,itk::Image>(m, "UC2UC2"); - wrapantsImageClone,itk::Image>(m, "UC2UI2"); - wrapantsImageClone,itk::Image>(m, "UC2F2"); - wrapantsImageClone,itk::Image>(m, "UC2D2"); - - wrapantsImageClone,itk::Image>(m, "UI2UC2"); - wrapantsImageClone,itk::Image>(m, "UI2UI2"); - wrapantsImageClone,itk::Image>(m, "UI2F2"); - wrapantsImageClone,itk::Image>(m, "UI2D2"); - - wrapantsImageClone,itk::Image>(m, "F2UC2"); - wrapantsImageClone,itk::Image>(m, "F2UI2"); - wrapantsImageClone,itk::Image>(m, "F2F2"); - wrapantsImageClone,itk::Image>(m, "F2D2"); - - wrapantsImageClone,itk::Image>(m, "D2UC2"); - wrapantsImageClone,itk::Image>(m, "D2UI2"); - wrapantsImageClone,itk::Image>(m, "D2F2"); - wrapantsImageClone,itk::Image>(m, "D2D2"); - - wrapantsImageClone,2>,itk::Image,2>>(m, "RGBUC2RGBUC2"); - - // dim = 3 - wrapantsImageClone,itk::Image>(m, "UC3UC3"); - wrapantsImageClone,itk::Image>(m, "UC3UI3"); - wrapantsImageClone,itk::Image>(m, "UC3F3"); - wrapantsImageClone,itk::Image>(m, "UC3D3"); - - wrapantsImageClone,itk::Image>(m, "UI3UC3"); - wrapantsImageClone,itk::Image>(m, "UI3UI3"); - wrapantsImageClone,itk::Image>(m, "UI3F3"); - wrapantsImageClone,itk::Image>(m, "UI3D3"); - - wrapantsImageClone,itk::Image>(m, "F3UC3"); - wrapantsImageClone,itk::Image>(m, "F3UI3"); - wrapantsImageClone,itk::Image>(m, "F3F3"); - wrapantsImageClone,itk::Image>(m, "F3D3"); - - wrapantsImageClone,itk::Image>(m, "D3UC3"); - wrapantsImageClone,itk::Image>(m, "D3UI3"); - wrapantsImageClone,itk::Image>(m, "D3F3"); - wrapantsImageClone,itk::Image>(m, "D3D3"); - wrapantsImageClone,3>,itk::Image,3>>(m, "RGBUC3RGBUC3"); - - // dim = 4 - wrapantsImageClone,itk::Image>(m, "UC4UC4"); - wrapantsImageClone,itk::Image>(m, "UC4UI4"); - wrapantsImageClone,itk::Image>(m, "UC4F4"); - wrapantsImageClone,itk::Image>(m, "UC4D4"); - - wrapantsImageClone,itk::Image>(m, "UI4UC4"); - wrapantsImageClone,itk::Image>(m, "UI4UI4"); - wrapantsImageClone,itk::Image>(m, "UI4F4"); - wrapantsImageClone,itk::Image>(m, "UI4D4"); - - wrapantsImageClone,itk::Image>(m, "F4UC4"); - wrapantsImageClone,itk::Image>(m, "F4UI4"); - wrapantsImageClone,itk::Image>(m, "F4F4"); - wrapantsImageClone,itk::Image>(m, "F4D4"); - - wrapantsImageClone,itk::Image>(m, "D4UC4"); - wrapantsImageClone,itk::Image>(m, "D4UI4"); - wrapantsImageClone,itk::Image>(m, "D4F4"); - wrapantsImageClone,itk::Image>(m, "D4D4"); - -} - - diff --git a/ants/lib/LOCAL_mergeChannels.cxx b/ants/lib/LOCAL_mergeChannels.cxx deleted file mode 100644 index e19cdf79..00000000 --- a/ants/lib/LOCAL_mergeChannels.cxx +++ /dev/null @@ -1,219 +0,0 @@ - -#include -#include - -#include -#include -#include - -#include "itkImage.h" -#include "itkVectorImage.h" -#include "itkImageRegionIteratorWithIndex.h" - -#include "LOCAL_antsImage.h" - -namespace py = pybind11; - -template< class ImageType, class VectorImageType > -py::capsule mergeChannels( std::vector imageList ) -{ - typedef typename ImageType::Pointer ImagePointerType; - typedef typename VectorImageType::Pointer VectorImagePointerType; - - unsigned int nImages = imageList.size(); - - std::vector images; - for ( unsigned int i=0; i( imageList[i] ) ); - } - - VectorImagePointerType vectorImage = VectorImageType::New(); - vectorImage->SetRegions( images[0]->GetLargestPossibleRegion() ); - vectorImage->SetSpacing( images[0]->GetSpacing() ); - vectorImage->SetOrigin( images[0]->GetOrigin() ); - vectorImage->SetDirection( images[0]->GetDirection() ); - vectorImage->SetNumberOfComponentsPerPixel( nImages ); - vectorImage->AllocateInitialized(); - - // Fill image data - itk::ImageRegionIteratorWithIndex it( vectorImage, - vectorImage->GetLargestPossibleRegion() ); - - while (!it.IsAtEnd() ) - { - typename VectorImageType::PixelType pix; - pix.SetSize( nImages ); - for (unsigned int i=0; iGetPixel(it.GetIndex()); - } - vectorImage->SetPixel(it.GetIndex(), pix); - ++it; - } - - return wrap( vectorImage ); -} - -template< class ImageType, class VectorImageType > -py::capsule mergeChannels2( std::vector imageList ) -{ - typedef typename ImageType::Pointer ImagePointerType; - typedef typename VectorImageType::Pointer VectorImagePointerType; - - unsigned int nImages = imageList.size(); - - std::vector images; - for ( unsigned int i=0; i( imageList[i] ) ); - } - - VectorImagePointerType vectorImage = VectorImageType::New(); - vectorImage->SetRegions( images[0]->GetLargestPossibleRegion() ); - vectorImage->SetSpacing( images[0]->GetSpacing() ); - vectorImage->SetOrigin( images[0]->GetOrigin() ); - vectorImage->SetDirection( images[0]->GetDirection() ); - vectorImage->SetNumberOfComponentsPerPixel( nImages ); - vectorImage->AllocateInitialized(); - - // Fill image data - itk::ImageRegionIteratorWithIndex it( vectorImage, - vectorImage->GetLargestPossibleRegion() ); - - while (!it.IsAtEnd() ) - { - typename VectorImageType::PixelType pix; - pix.SetSize( nImages ); - for (unsigned int i=0; iGetPixel(it.GetIndex()); - } - vectorImage->SetPixel(it.GetIndex(), pix); - ++it; - } - - return wrap( vectorImage ); -} - -template< class ImageType, class VectorImageType > -py::capsule mergeChannels3( std::vector imageList ) -{ - typedef typename ImageType::Pointer ImagePointerType; - typedef typename VectorImageType::Pointer VectorImagePointerType; - - unsigned int nImages = imageList.size(); - - std::vector images; - for ( unsigned int i=0; i( imageList[i] ) ); - } - - VectorImagePointerType vectorImage = VectorImageType::New(); - vectorImage->SetRegions( images[0]->GetLargestPossibleRegion() ); - vectorImage->SetSpacing( images[0]->GetSpacing() ); - vectorImage->SetOrigin( images[0]->GetOrigin() ); - vectorImage->SetDirection( images[0]->GetDirection() ); - //vectorImage->SetNumberOfComponentsPerPixel( nImages ); - vectorImage->AllocateInitialized(); - - // Fill image data - itk::ImageRegionIteratorWithIndex it( vectorImage, - vectorImage->GetLargestPossibleRegion() ); - - while (!it.IsAtEnd() ) - { - - typename VectorImageType::PixelType pix; - //pix.SetSize( nImages ); - for (unsigned int i=0; iGetPixel(it.GetIndex()); - } - vectorImage->SetPixel(it.GetIndex(), pix); - ++it; - } - - return wrap( vectorImage ); -} - -template< class VectorImageType, class ImageType> -std::vector splitChannels( py::capsule & antsimage ) -{ - typedef typename ImageType::Pointer ImagePointerType; - typedef typename VectorImageType::Pointer VectorImagePointerType; - - VectorImagePointerType input = as( antsimage ); - unsigned int nComponents = input->GetNumberOfComponentsPerPixel(); - - // Create output images - std::vector images; - for ( unsigned int i=0; iSetRegions( input->GetLargestPossibleRegion() ); - image->SetSpacing( input->GetSpacing() ); - image->SetOrigin( input->GetOrigin() ); - image->SetDirection( input->GetDirection() ); - image->AllocateInitialized(); - images.push_back( image ); - } - - // Fill image data - itk::ImageRegionIteratorWithIndex it( input, - input->GetLargestPossibleRegion() ); - - while (!it.IsAtEnd() ) - { - typename VectorImageType::PixelType pix = input->GetPixel(it.GetIndex()); - - for (unsigned int i=0; iSetPixel(it.GetIndex(), pix[i]); - } - ++it; - } - - std::vector outputList( nComponents ); - for (unsigned int i=0; i( images[i] ); - } - - return( outputList ); - -} - - -PYBIND11_MODULE(mergeChannels, m) -{ - m.def("mergeChannelsUC2", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsUC3", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsUC4", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsUI2", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsUI3", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsUI4", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsF2", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsF3", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsF4", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsD2", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsD3", &mergeChannels, itk::VectorImage >); - m.def("mergeChannelsD4", &mergeChannels, itk::VectorImage >); - - m.def("splitChannelsVUC2", &splitChannels, itk::Image >); - m.def("splitChannelsVUC3", &splitChannels, itk::Image >); - m.def("splitChannelsVUC4", &splitChannels, itk::Image >); - m.def("splitChannelsVUI2", &splitChannels, itk::Image >); - m.def("splitChannelsVUI3", &splitChannels, itk::Image >); - m.def("splitChannelsVUI4", &splitChannels, itk::Image >); - m.def("splitChannelsVF2", &splitChannels, itk::Image >); - m.def("splitChannelsVF3", &splitChannels, itk::Image >); - m.def("splitChannelsVF4", &splitChannels, itk::Image >); - m.def("splitChannelsVD2", &splitChannels, itk::Image >); - m.def("splitChannelsVD3", &splitChannels, itk::Image >); - m.def("splitChannelsVD4", &splitChannels, itk::Image >); - m.def("splitChannelsRGBUC2", &splitChannels< itk::Image, 2>, itk::Image >); - - -} diff --git a/ants/lib/LOCAL_mergeChannels.h b/ants/lib/LOCAL_mergeChannels.h deleted file mode 100644 index 6c9985b5..00000000 --- a/ants/lib/LOCAL_mergeChannels.h +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include - -#include -#include -#include - -#include "itkImage.h" -#include "itkVectorImage.h" -#include "itkImageRegionIteratorWithIndex.h" - -#include "LOCAL_antsImage.h" - - -template< class VectorImageType, class ImageType> -std::vector splitChannels( py::capsule & antsimage ); - -template< class ImageType, class VectorImageType > -py::capsule mergeChannels( std::vector imageList ); - -template< class ImageType, class VectorImageType > -py::capsule mergeChannels2( std::vector imageList ); - -template< class ImageType, class VectorImageType > -py::capsule mergeChannels3( std::vector imageList ); \ No newline at end of file diff --git a/ants/lib/LOCAL_readImage.cxx b/ants/lib/LOCAL_readImage.cxx deleted file mode 100644 index 535162bb..00000000 --- a/ants/lib/LOCAL_readImage.cxx +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include - -#include -#include "itkImageFileWriter.h" -#include "itkImageIOBase.h" -#include "itkNiftiImageIOFactory.h" -#include "itkMetaImageIOFactory.h" -#include "itkImageFileReader.h" -#include "itkImage.h" -#include "itkPyBuffer.h" - -#include "LOCAL_readImage.h" -#include "LOCAL_antsImage.h" - - -namespace py = pybind11; - - -template< typename ImageType > -py::capsule imageReadHelper( std::string filename ) -{ - //py::print("at imagereadhelper"); - typedef typename ImageType::Pointer ImagePointerType; - typedef itk::ImageFileReader< ImageType > ImageReaderType; - - typename ImageReaderType::Pointer image_reader = ImageReaderType::New() ; - image_reader->SetFileName( filename.c_str() ) ; - image_reader->Update(); - - ImagePointerType itkImage = image_reader->GetOutput(); - return wrap( itkImage ); -} - -template -py::capsule imageRead( std::string filename ) -{ - py::capsule antsImage; - antsImage = imageReadHelper( filename ); - return antsImage; -} - - -template -py::capsule fromNumpy( py::array data, py::tuple datashape ) -{ - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType myimage = ImageType::New(); - typedef itk::PyBuffer PyBufferType; - - //py::tuple datashape = py::getattr(data, "shape"); - myimage = PyBufferType::_GetImageViewFromArray( data.ptr(), datashape.ptr(), py::make_tuple(1)[0].ptr() ); - - return wrap( myimage ); -} - - -void testPrint( py::object &myImage ) -{ - unsigned int ndim = py::getattr(myImage, "dimension").cast(); - std::string pixeltype = py::getattr(myImage, "pixeltype").cast(); -} - - - -template -void wrapReadImage(py::module & m, std::string const & suffix) { - m.def(("imageRead" + suffix).c_str(), &imageRead, - "Read ANTsImage from file"); -} - - - -PYBIND11_MODULE(readImage, m) { - - wrapReadImage>(m, "UC2"); - wrapReadImage>(m, "UC3"); - wrapReadImage>(m, "UC4"); - wrapReadImage>(m, "UI2"); - wrapReadImage>(m, "UI3"); - wrapReadImage>(m, "UI4"); - wrapReadImage>(m, "F2"); - wrapReadImage>(m, "F3"); - wrapReadImage>(m, "F4"); - wrapReadImage>(m, "D2"); - wrapReadImage>(m, "D3"); - wrapReadImage>(m, "D4"); - - wrapReadImage>(m, "VUC2"); - wrapReadImage>(m, "VUC3"); - wrapReadImage>(m, "VUC4"); - wrapReadImage>(m, "VUI2"); - wrapReadImage>(m, "VUI3"); - wrapReadImage>(m, "VUI4"); - wrapReadImage>(m, "VF2"); - wrapReadImage>(m, "VF3"); - wrapReadImage>(m, "VF4"); - wrapReadImage>(m, "VD2"); - wrapReadImage>(m, "VD3"); - wrapReadImage>(m, "VD4"); - - wrapReadImage, 2>>(m, "RGBUC2"); - wrapReadImage, 3>>(m, "RGBUC3"); - - m.def("fromNumpyUC2", &fromNumpy>); - m.def("fromNumpyUC3", &fromNumpy>); - m.def("fromNumpyUC4", &fromNumpy>); - m.def("fromNumpyUI2", &fromNumpy>); - m.def("fromNumpyUI3", &fromNumpy>); - m.def("fromNumpyUI4", &fromNumpy>); - m.def("fromNumpyF2", &fromNumpy>); - m.def("fromNumpyF3", &fromNumpy>); - m.def("fromNumpyF4", &fromNumpy>); - m.def("fromNumpyD2", &fromNumpy>); - m.def("fromNumpyD3", &fromNumpy>); - m.def("fromNumpyD4", &fromNumpy>); - //m.def("fromNumpyRGBUC2", &fromNumpy, 2>>); - //m.def("fromNumpyRGBUC3", &fromNumpy, 3>>); - -} - - diff --git a/ants/lib/WRAP_Atropos.cxx b/ants/lib/WRAP_Atropos.cxx deleted file mode 100644 index 26bf9ff5..00000000 --- a/ants/lib/WRAP_Atropos.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/Atropos.h" - -namespace py = pybind11; - -int Atropos( std::vector instring ) -{ - return ants::Atropos(instring, NULL); -} - -PYBIND11_MODULE(Atropos, m) -{ - m.def("Atropos", &Atropos); -} diff --git a/ants/lib/WRAP_AverageAffineTransform.cxx b/ants/lib/WRAP_AverageAffineTransform.cxx deleted file mode 100644 index bbd2a025..00000000 --- a/ants/lib/WRAP_AverageAffineTransform.cxx +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -#include "antscore/AverageAffineTransform.h" -#include "antscore/AverageAffineTransformNoRigid.h" - -namespace py = pybind11; - -int AverageAffineTransform( std::vector instring ) -{ - return ants::AverageAffineTransform(instring, NULL); -} - -PYBIND11_MODULE(AverageAffineTransform, m) -{ - m.def("AverageAffineTransform", &AverageAffineTransform); -} diff --git a/ants/lib/WRAP_AverageAffineTransformNoRigid.cxx b/ants/lib/WRAP_AverageAffineTransformNoRigid.cxx deleted file mode 100644 index aef3c073..00000000 --- a/ants/lib/WRAP_AverageAffineTransformNoRigid.cxx +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include - -#include "antscore/AverageAffineTransformNoRigid.h" - -namespace py = pybind11; - -int AverageAffineTransformNoRigid( std::vector instring ) -{ - return ants::AverageAffineTransformNoRigid(instring, NULL); -} - -PYBIND11_MODULE(AverageAffineTransformNoRigid, m) -{ - m.def("AverageAffineTransformNoRigid", &AverageAffineTransformNoRigid); -} diff --git a/ants/lib/WRAP_ConvertScalarImageToRGB.cxx b/ants/lib/WRAP_ConvertScalarImageToRGB.cxx deleted file mode 100644 index b5d07fc8..00000000 --- a/ants/lib/WRAP_ConvertScalarImageToRGB.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/ConvertScalarImageToRGB.h" - -namespace py = pybind11; - -int ConvertScalarImageToRGB( std::vector instring ) -{ - return ants::ConvertScalarImageToRGB(instring, NULL); -} - -PYBIND11_MODULE(ConvertScalarImageToRGB, m) -{ - m.def("ConvertScalarImageToRGB", &ConvertScalarImageToRGB); -} \ No newline at end of file diff --git a/ants/lib/WRAP_CreateJacobianDeterminantImage.cxx b/ants/lib/WRAP_CreateJacobianDeterminantImage.cxx deleted file mode 100644 index d101076d..00000000 --- a/ants/lib/WRAP_CreateJacobianDeterminantImage.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/CreateJacobianDeterminantImage.h" - -namespace py = pybind11; - -int CreateJacobianDeterminantImage( std::vector instring ) -{ - return ants::CreateJacobianDeterminantImage(instring, NULL); -} - -PYBIND11_MODULE(CreateJacobianDeterminantImage, m) -{ - m.def("CreateJacobianDeterminantImage", &CreateJacobianDeterminantImage); -} \ No newline at end of file diff --git a/ants/lib/WRAP_CreateTiledMosaic.cxx b/ants/lib/WRAP_CreateTiledMosaic.cxx deleted file mode 100644 index 3c80724d..00000000 --- a/ants/lib/WRAP_CreateTiledMosaic.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/CreateTiledMosaic.h" - -namespace py = pybind11; - -int CreateTiledMosaic( std::vector instring ) -{ - return ants::CreateTiledMosaic(instring, NULL); -} - -PYBIND11_MODULE(CreateTiledMosaic, m) -{ - m.def("CreateTiledMosaic", &CreateTiledMosaic); -} \ No newline at end of file diff --git a/ants/lib/WRAP_DenoiseImage.cxx b/ants/lib/WRAP_DenoiseImage.cxx deleted file mode 100644 index 5d236743..00000000 --- a/ants/lib/WRAP_DenoiseImage.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/DenoiseImage.h" - -namespace py = pybind11; - -int DenoiseImage( std::vector instring ) -{ - return ants::DenoiseImage(instring, NULL); -} - -PYBIND11_MODULE(DenoiseImage, m) -{ - m.def("DenoiseImage", &DenoiseImage); -} \ No newline at end of file diff --git a/ants/lib/WRAP_KellyKapowski.cxx b/ants/lib/WRAP_KellyKapowski.cxx deleted file mode 100644 index 8a7a0fbb..00000000 --- a/ants/lib/WRAP_KellyKapowski.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/KellyKapowski.h" - -namespace py = pybind11; - -int KellyKapowski( std::vector instring ) -{ - return ants::KellyKapowski(instring, NULL); -} - -PYBIND11_MODULE(KellyKapowski, m) -{ - m.def("KellyKapowski", &KellyKapowski); -} \ No newline at end of file diff --git a/ants/lib/WRAP_LabelClustersUniquely.cxx b/ants/lib/WRAP_LabelClustersUniquely.cxx deleted file mode 100644 index a55043a1..00000000 --- a/ants/lib/WRAP_LabelClustersUniquely.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/LabelClustersUniquely.h" - -namespace py = pybind11; - -int LabelClustersUniquely( std::vector instring ) -{ - return ants::LabelClustersUniquely(instring, NULL); -} - -PYBIND11_MODULE(LabelClustersUniquely, m) -{ - m.def("LabelClustersUniquely", &LabelClustersUniquely); -} \ No newline at end of file diff --git a/ants/lib/WRAP_LabelGeometryMeasures.cxx b/ants/lib/WRAP_LabelGeometryMeasures.cxx deleted file mode 100644 index bd3e3217..00000000 --- a/ants/lib/WRAP_LabelGeometryMeasures.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/LabelGeometryMeasures.h" - -namespace py = pybind11; - -int LabelGeometryMeasures( std::vector instring ) -{ - return ants::LabelGeometryMeasures(instring, NULL); -} - -PYBIND11_MODULE(LabelGeometryMeasures, m) -{ - m.def("LabelGeometryMeasures", &LabelGeometryMeasures); -} \ No newline at end of file diff --git a/ants/lib/WRAP_LesionFilling.cxx b/ants/lib/WRAP_LesionFilling.cxx deleted file mode 100644 index 18de59f6..00000000 --- a/ants/lib/WRAP_LesionFilling.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/LesionFilling.h" - -namespace py = pybind11; - -int LesionFilling( std::vector instring ) -{ - return ants::LesionFilling(instring, NULL); -} - -PYBIND11_MODULE(LesionFilling, m) -{ - m.def("LesionFilling", &LesionFilling); -} \ No newline at end of file diff --git a/ants/lib/WRAP_N3BiasFieldCorrection.cxx b/ants/lib/WRAP_N3BiasFieldCorrection.cxx deleted file mode 100644 index eff5a662..00000000 --- a/ants/lib/WRAP_N3BiasFieldCorrection.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/N3BiasFieldCorrection.h" - -namespace py = pybind11; - -int N3BiasFieldCorrection( std::vector instring ) -{ - return ants::N3BiasFieldCorrection(instring, NULL); -} - -PYBIND11_MODULE(N3BiasFieldCorrection, m) -{ - m.def("N3BiasFieldCorrection", &N3BiasFieldCorrection); -} \ No newline at end of file diff --git a/ants/lib/WRAP_N4BiasFieldCorrection.cxx b/ants/lib/WRAP_N4BiasFieldCorrection.cxx deleted file mode 100644 index aa399e65..00000000 --- a/ants/lib/WRAP_N4BiasFieldCorrection.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/N4BiasFieldCorrection.h" - -namespace py = pybind11; - -int N4BiasFieldCorrection( std::vector instring ) -{ - return ants::N4BiasFieldCorrection(instring, NULL); -} - -PYBIND11_MODULE(N4BiasFieldCorrection, m) -{ - m.def("N4BiasFieldCorrection", &N4BiasFieldCorrection); -} \ No newline at end of file diff --git a/ants/lib/WRAP_NonLocalSuperResolution.cxx b/ants/lib/WRAP_NonLocalSuperResolution.cxx deleted file mode 100644 index f49822c8..00000000 --- a/ants/lib/WRAP_NonLocalSuperResolution.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/NonLocalSuperResolution.h" - -namespace py = pybind11; - -int NonLocalSuperResolution( std::vector instring ) -{ - return ants::NonLocalSuperResolution(instring, NULL); -} - -PYBIND11_MODULE(NonLocalSuperResolution, m) -{ - m.def("NonLocalSuperResolution", &NonLocalSuperResolution); -} \ No newline at end of file diff --git a/ants/lib/WRAP_ResampleImage.cxx b/ants/lib/WRAP_ResampleImage.cxx deleted file mode 100644 index fc70c58e..00000000 --- a/ants/lib/WRAP_ResampleImage.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/ResampleImage.h" - -namespace py = pybind11; - -int ResampleImage( std::vector instring ) -{ - return ants::ResampleImage(instring, NULL); -} - -PYBIND11_MODULE(ResampleImage, m) -{ - m.def("ResampleImage", &ResampleImage); -} \ No newline at end of file diff --git a/ants/lib/WRAP_SuperResolution.cxx b/ants/lib/WRAP_SuperResolution.cxx deleted file mode 100644 index 10c5cc6e..00000000 --- a/ants/lib/WRAP_SuperResolution.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/SuperResolution.h" - -namespace py = pybind11; - -int SuperResolution( std::vector instring ) -{ - return ants::SuperResolution(instring, NULL); -} - -PYBIND11_MODULE(SuperResolution, m) -{ - m.def("SuperResolution", &SuperResolution); -} \ No newline at end of file diff --git a/ants/lib/WRAP_ThresholdImage.cxx b/ants/lib/WRAP_ThresholdImage.cxx deleted file mode 100644 index 8ebc9936..00000000 --- a/ants/lib/WRAP_ThresholdImage.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/ThresholdImage.h" - -namespace py = pybind11; - -int ThresholdImage( std::vector instring ) -{ - return ants::ThresholdImage(instring, NULL); -} - -PYBIND11_MODULE(ThresholdImage, m) -{ - m.def("ThresholdImage", &ThresholdImage); -} \ No newline at end of file diff --git a/ants/lib/WRAP_TileImages.cxx b/ants/lib/WRAP_TileImages.cxx deleted file mode 100644 index 69d7d18a..00000000 --- a/ants/lib/WRAP_TileImages.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/TileImages.h" - -namespace py = pybind11; - -int TileImages( std::vector instring ) -{ - return ants::TileImages(instring, NULL); -} - -PYBIND11_MODULE(TileImages, m) -{ - m.def("TileImages", &TileImages); -} \ No newline at end of file diff --git a/ants/lib/WRAP_TimeSCCAN.cxx b/ants/lib/WRAP_TimeSCCAN.cxx deleted file mode 100644 index a3b7168e..00000000 --- a/ants/lib/WRAP_TimeSCCAN.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/TimeSCCAN.h" - -namespace py = pybind11; - -int TimeSCCAN( std::vector instring ) -{ - return ants::TimeSCCAN(instring, NULL); -} - -PYBIND11_MODULE(TimeSCCAN, m) -{ - m.def("TimeSCCAN", &TimeSCCAN); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsAffineInitializer.cxx b/ants/lib/WRAP_antsAffineInitializer.cxx deleted file mode 100644 index 693fd303..00000000 --- a/ants/lib/WRAP_antsAffineInitializer.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsAffineInitializer.h" - -namespace py = pybind11; - -int antsAffineInitializer( std::vector instring ) -{ - return ants::antsAffineInitializer(instring, NULL); -} - -PYBIND11_MODULE(antsAffineInitializer, m) -{ - m.def("antsAffineInitializer", &antsAffineInitializer); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsApplyTransforms.cxx b/ants/lib/WRAP_antsApplyTransforms.cxx deleted file mode 100644 index 8b32d0a0..00000000 --- a/ants/lib/WRAP_antsApplyTransforms.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsApplyTransforms.h" - -namespace py = pybind11; - -int antsApplyTransforms( std::vector instring ) -{ - return ants::antsApplyTransforms(instring, NULL); -} - -PYBIND11_MODULE(antsApplyTransforms, m) -{ - m.def("antsApplyTransforms", &antsApplyTransforms); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsJointFusion.cxx b/ants/lib/WRAP_antsJointFusion.cxx deleted file mode 100644 index a13c401c..00000000 --- a/ants/lib/WRAP_antsJointFusion.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsJointFusion.h" - -namespace py = pybind11; - -int antsJointFusion( std::vector instring ) -{ - return ants::antsJointFusion(instring, NULL); -} - -PYBIND11_MODULE(antsJointFusion, m) -{ - m.def("antsJointFusion", &antsJointFusion); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsLandmarkBasedTransformInitializer.cxx b/ants/lib/WRAP_antsLandmarkBasedTransformInitializer.cxx deleted file mode 100644 index 4467144a..00000000 --- a/ants/lib/WRAP_antsLandmarkBasedTransformInitializer.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsLandmarkBasedTransformInitializer.h" - -namespace py = pybind11; - -int antsLandmarkBasedTransformInitializer( std::vector instring ) -{ - return ants::antsLandmarkBasedTransformInitializer(instring, NULL); -} - -PYBIND11_MODULE(antsLandmarkBasedTransformInitializer, m) -{ - m.def("antsLandmarkBasedTransformInitializer", &antsLandmarkBasedTransformInitializer); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsMotionCorr.cxx b/ants/lib/WRAP_antsMotionCorr.cxx deleted file mode 100644 index a6bb5a13..00000000 --- a/ants/lib/WRAP_antsMotionCorr.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsMotionCorr.h" - -namespace py = pybind11; - -int antsMotionCorr( std::vector instring ) -{ - return ants::antsMotionCorr(instring, NULL); -} - -PYBIND11_MODULE(antsMotionCorr, m) -{ - m.def("antsMotionCorr", &antsMotionCorr); -} diff --git a/ants/lib/WRAP_antsMotionCorrStats.cxx b/ants/lib/WRAP_antsMotionCorrStats.cxx deleted file mode 100644 index ca7a7014..00000000 --- a/ants/lib/WRAP_antsMotionCorrStats.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsMotionCorrStats.h" - -namespace py = pybind11; - -int antsMotionCorrStats( std::vector instring ) -{ - return ants::antsMotionCorrStats(instring, NULL); -} - -PYBIND11_MODULE(antsMotionCorrStats, m) -{ - m.def("antsMotionCorrStats", &antsMotionCorrStats); -} diff --git a/ants/lib/WRAP_antsRegistration.cxx b/ants/lib/WRAP_antsRegistration.cxx deleted file mode 100644 index 6cf7bcef..00000000 --- a/ants/lib/WRAP_antsRegistration.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsRegistration.h" - -namespace py = pybind11; - -int antsRegistration( std::vector instring ) -{ - return ants::antsRegistration(instring, NULL); -} - -PYBIND11_MODULE(antsRegistration, m) -{ - m.def("antsRegistration", &antsRegistration); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsSliceRegularizedRegistration.cxx b/ants/lib/WRAP_antsSliceRegularizedRegistration.cxx deleted file mode 100644 index a33a0e03..00000000 --- a/ants/lib/WRAP_antsSliceRegularizedRegistration.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsSliceRegularizedRegistration.h" - -namespace py = pybind11; - -int antsSliceRegularizedRegistration( std::vector instring ) -{ - return ants::antsSliceRegularizedRegistration(instring, NULL); -} - -PYBIND11_MODULE(antsSliceRegularizedRegistration, m) -{ - m.def("antsSliceRegularizedRegistration", &antsSliceRegularizedRegistration); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsSurf.cxx b/ants/lib/WRAP_antsSurf.cxx deleted file mode 100644 index 15904672..00000000 --- a/ants/lib/WRAP_antsSurf.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsSurf.h" - -namespace py = pybind11; - -int antsSurf( std::vector instring ) -{ - return ants::antsSurf(instring, NULL); -} - -PYBIND11_MODULE(antsSurf, m) -{ - m.def("antsSurf", &antsSurf); -} \ No newline at end of file diff --git a/ants/lib/WRAP_antsVol.cxx b/ants/lib/WRAP_antsVol.cxx deleted file mode 100644 index bf151e30..00000000 --- a/ants/lib/WRAP_antsVol.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/antsVol.h" - -namespace py = pybind11; - -int antsVol( std::vector instring ) -{ - return ants::antsVol(instring, NULL); -} - -PYBIND11_MODULE(antsVol, m) -{ - m.def("antsVol", &antsVol); -} \ No newline at end of file diff --git a/ants/lib/WRAP_iMath.cxx b/ants/lib/WRAP_iMath.cxx deleted file mode 100644 index 5d096744..00000000 --- a/ants/lib/WRAP_iMath.cxx +++ /dev/null @@ -1,17 +0,0 @@ - -#include -#include - -#include "antscore/iMath.h" - -namespace py = pybind11; - -int iMath( std::vector instring ) -{ - return ants::iMath(instring, NULL); -} - -PYBIND11_MODULE(iMath, m) -{ - m.def("iMath", &iMath); -} diff --git a/ants/lib/__init__.py b/ants/lib/__init__.py deleted file mode 100644 index bba659c4..00000000 --- a/ants/lib/__init__.py +++ /dev/null @@ -1,89 +0,0 @@ -## LOCAL ## -from .addNoiseToImage import * -from .antiAlias import * -from .antsImage import * -from .antsImageClone import * -from .antsImageHeaderInfo import * -from .antsImageMutualInformation import * -from .antsImageToImageMetric import * -from .antsImageUtils import * -from .antsTransform import * -from .cropImage import * -from .composeDisplacementFields import * -from .fitBsplineObjectToScatteredData import * -from .fitBsplineDisplacementField import * -from .fitBsplineDisplacementFieldToScatteredData import * -from .fitThinPlateSplineDisplacementFieldToScatteredData import * -from .fsl2antstransform import * -from .getNeighborhoodMatrix import * -from .hausdorffDistance import * -from .histogramMatchImage import * -from .invertDisplacementField import * -from .labelOverlapMeasures import * -from .labelStats import * -from .mergeChannels import * -from .padImage import * -from .readImage import * -from .readTransform import * -from .reflectionMatrix import * -from .reorientImage import * -from .reorientImage2 import * -from .rgbToVector import * -from .sccaner import * -from .simulateDisplacementField import * -from .sliceImage import * -from .SmoothImage import * -from .weingartenImageCurvature import * - -## WRAP ## -from .antsAffineInitializer import * -from .antsApplyTransforms import * -from .antsApplyTransformsToPoints import * -from .antsJointFusion import * -from .antsRegistration import * -from .Atropos import * -from .CreateJacobianDeterminantImage import * -from .CreateTiledMosaic import * -from .DenoiseImage import * -from .iMath import * -from .KellyKapowski import * -from .LabelClustersUniquely import * -from .LabelGeometryMeasures import * -from .N3BiasFieldCorrection import * -from .N4BiasFieldCorrection import * -from .ResampleImage import * -from .ThresholdImage import * -from .integrateVelocityField import * -from .TileImages import * -from .AverageAffineTransform import * -from .AverageAffineTransformNoRigid import * - -## CONTRIB ## -# NOTE: contrib contains code which is experimental -from .antsImageAugment import * - - -## NOT WRAPPED ## -# from .antsLandmarkBasedTransformInitializer import * -# from .antsMotionCorr import * -# from .antsMotionCorrStats import * -# from .antsSliceRegularizedRegistration import * -# from .LesionFilling import * -# from .NonLocalSuperResolution import * -# from .SuperResolution import * -# from .TimeSCCAN import * - - -## VIZ ## -# try: -# from .antsSurf import * -# except: -# pass -# try: -# from .antsVol import * -# except: -# pass -try: - from .ConvertScalarImageToRGB import * -except: - pass diff --git a/ants/utils/channels.py b/ants/utils/channels.py index 3ccfc329..7f48facc 100644 --- a/ants/utils/channels.py +++ b/ants/utils/channels.py @@ -42,7 +42,7 @@ def merge_channels(image_list): if image.pixeltype != inpixeltype: raise ValueError('all images must have the same pixeltype') - libfn = utils.get_lib_fn('mergeChannels%s' % image_list[0]._libsuffix) + libfn = utils.get_lib_fn('mergeChannels') image_ptr = libfn([image.pointer for image in image_list]) return iio.ANTsImage(pixeltype=inpixeltype, @@ -80,7 +80,7 @@ def split_channels(image): dimension = image.dimension components = 1 - libfn = utils.get_lib_fn('splitChannels%s' % image._libsuffix) + libfn = utils.get_lib_fn('splitChannels') itkimages = libfn(image.pointer) antsimages = [iio.ANTsImage(pixeltype=inpixeltype, dimension=dimension, components=components, pointer=itkimage) for itkimage in itkimages] diff --git a/ants/utils/smooth_image.py b/ants/utils/smooth_image.py index e5260d39..0b5c55c1 100644 --- a/ants/utils/smooth_image.py +++ b/ants/utils/smooth_image.py @@ -24,7 +24,7 @@ def _smooth_image_helper(image, sigma, sigma_in_physical_coordinates=True, FWHM= max_kernel_width = int(math.ceil(max_kernel_width)) - smooth_image_fn = utils.get_lib_fn('SmoothImage%iD'%image.dimension) + smooth_image_fn = utils.get_lib_fn('SmoothImage') outimage = smooth_image_fn(image_float.pointer, sigma, sigma_in_physical_coordinates, max_kernel_width) ants_outimage = iio.ANTsImage(pixeltype='float', dimension=image.dimension, components=image.components, pointer=outimage) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..82330aa1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,50 @@ +[build-system] +requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"] +build-backend = "scikit_build_core.build" + +[project] +name = "antspy" +version = "0.6.0" +description = "A fast medical imaging library with comprehensive processing algorithms" +readme = "README.md" +requires-python = ">=3.8" +authors = [ + { name = "ANTs", email = "info@ants.dev" } +] +classifiers = [ + "License :: OSI Approved :: BSD License", +] + +[project.urls] +Homepage = "https://github.com/antsx/antspy" + + +[tool.scikit-build] +# Protect the configuration against future changes in scikit-build-core +minimum-version = "0.4" + +# Setuptools-style build caching in a local directory +build-dir = "build/{wheel_tag}" + +# Build stable ABI wheels for CPython 3.12+ +wheel.py-api = "cp311" + +cmake.args = [] + +wheel.packages = ["ants"] + + +[tool.cibuildwheel] +# Necessary to see build output from the actual compilation +build-verbosity = 1 + +# Run pytest to ensure that the package was correctly built +test-command = "pytest {project}/tests" +test-requires = "pytest" + +# Don't test Python 3.8 wheels on macOS/arm64 +test-skip="cp38-macosx_*:arm64" + +# Needed for full C++17 support +[tool.cibuildwheel.macos.environment] +MACOSX_DEPLOYMENT_TARGET = "10.14" diff --git a/scripts/configure_ANTsPy.bat b/scripts/configure_ANTs.bat similarity index 100% rename from scripts/configure_ANTsPy.bat rename to scripts/configure_ANTs.bat diff --git a/scripts/configure_ANTsPy.sh b/scripts/configure_ANTs.sh similarity index 82% rename from scripts/configure_ANTsPy.sh rename to scripts/configure_ANTs.sh index c369bbc7..b901ca25 100755 --- a/scripts/configure_ANTsPy.sh +++ b/scripts/configure_ANTs.sh @@ -1,15 +1,5 @@ #!/bin/bash -# --------------------------------------------- -# clone pybind11 into library directory - -cd ants/lib # go to lib dir -if [[ ! -d ./pybind11 ]]; then - git clone https://github.com/stnava/pybind11.git -# git clone https://github.com/ncullen93/pybind11.git -fi -cd ../../ # go back to main dir - # --------------------------------------------- # create local ~/.antspy dir and move package data to it @@ -26,7 +16,7 @@ antsgit=https://github.com/ANTsX/ANTs.git antstag=35d9381721b143c7bbd9d5f7f4ad853406351c1c # 04-01-2024 echo "ANTS;${antstag}" >> ./data/softwareVersions.csv -cd ants/lib # go to lib dir +cd src # go to lib dir # if antscore doesnt exist, create it if [[ ! -d antscore ]] ; then diff --git a/scripts/configure_ANTsPy_windows.sh b/scripts/configure_ANTs_windows.sh similarity index 100% rename from scripts/configure_ANTsPy_windows.sh rename to scripts/configure_ANTs_windows.sh diff --git a/scripts/configure_ITK.sh b/scripts/configure_ITK.sh index e3f31b88..c69f27bd 100755 --- a/scripts/configure_ITK.sh +++ b/scripts/configure_ITK.sh @@ -13,7 +13,6 @@ if [[ "$TRAVIS" == "true" ]] ; then JTHREADS=2 fi -#cd ./src itkgit=https://github.com/InsightSoftwareConsortium/ITK.git itktag=4535548a8539757c5fe9d81f8de5d804cd0a384f # 2024-03-12 # if there is a directory but no git, remove it @@ -32,11 +31,9 @@ if [[ -d .git ]]; then git checkout $itktag rm -rf .git fi + # go back to main dir cd ../ -#if [[ ! -d ../data/ ]] ; then -# mkdir -p ../data -#fi echo "Dependency;GitTag" > ./data/softwareVersions.csv echo "ITK;${itktag}" >> ./data/softwareVersions.csv @@ -79,4 +76,4 @@ cmake \ -DCMAKE_VISIBILITY_INLINES_HIDDEN:BOOL=ON ../itksource/ make -j ${j:-4} -cd ../ +cd ../../ diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 0f94f377..00000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[metadata] -description_file = README.md \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index 9ef6502b..00000000 --- a/setup.py +++ /dev/null @@ -1,206 +0,0 @@ -import os -import platform -import re -import shutil -import subprocess -import sys -import time -from functools import cmp_to_key - -import setuptools -import setuptools.command.build_ext -import setuptools.command.build_py -import setuptools.command.develop -import setuptools.command.install -from setuptools import Extension, find_packages, setup -from setuptools.command.build_ext import build_ext - -setup_py_dir = os.path.dirname(os.path.realpath(__file__)) -version = "0.5.2" # ANTsPy version - -if "--weekly" in sys.argv: - sys.argv.remove("--weekly") - version = "%sa0" % version - - -class CMakeExtension(Extension): - def __init__(self, name, sourcedir=""): - Extension.__init__(self, name, sources=[]) - self.sourcedir = os.path.abspath(sourcedir) - - -class install(setuptools.command.install.install): - def run(self): - setuptools.command.install.install.run(self) - - -class build_py(setuptools.command.build_py.build_py): - def run(self): - self.run_command("build_ext") - self.create_version_file() - setuptools.command.build_py.build_py.run(self) - - @staticmethod - def create_version_file(): - global version, setup_py_dir - print("-- Building version " + version) - version_path = os.path.join(setup_py_dir, "ants", "version.py") - with open(version_path, "w") as f: - f.write("__version__ = '{}'\n".format(version)) - - -class BuildExtFirst(setuptools.command.install.install): - def run(self): - self.run_command("build_py") - return setuptools.command.install.install.run(self) - - -class CMakeBuild(build_ext): - def run(self): - ## Find or Configure ITK ## - print("Configuring ITK") - if os.getenv("ITK_DIR"): - print("Using Local ITK Installation at:\n %s" % os.getenv("ITK_DIR")) - elif os.path.exists(os.path.join(setup_py_dir, "itkbuild/ITKConfig.cmake")): - print("Using local ITK already built for this package") - os.environ["ITK_DIR"] = os.path.join(setup_py_dir, "itkbuild") - else: - print("No local ITK installation found... Building ITK now...") - if platform.system() == "Windows": - subprocess.check_call( - [".\\scripts\\configure_ITK.bat"], cwd=setup_py_dir - ) - else: - subprocess.check_call(["./scripts/configure_ITK.sh"], cwd=setup_py_dir) - os.environ["ITK_DIR"] = os.path.join(setup_py_dir, "itkbuild") - - ## Find or Configure ANTs ## - print("Configuring ANTs core") - if platform.system() == "Windows": - subprocess.check_call( - [".\\scripts\\configure_ANTsPy.bat"], cwd=setup_py_dir - ) - else: - subprocess.check_call(["./scripts/configure_ANTsPy.sh"], cwd=setup_py_dir) - - ## Configure ANTsPy library ## - print("Configuring ANTsPy library") - try: - out = subprocess.check_output(["cmake", "--version"]) - except OSError: - raise RuntimeError( - "CMake must be installed to build the following extensions: " - + ", ".join(e.name for e in self.extensions) - ) - - cmake_version = re.search(r"version\s*([\d.]+)", out.decode()).group(1) - if cmake_version < "3.10.0": - raise RuntimeError("CMake >= 3.10.0 is required") - - for ext in self.extensions: - self.build_extension(ext) - - def build_extension(self, ext): - setup_py_dir = os.path.dirname(os.path.realpath(__file__)) - extdir = os.path.join(setup_py_dir, "ants", "lib") - - cmake_args = [ - "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + extdir, - "-DPYTHON_EXECUTABLE=" + sys.executable, - "-DCMAKE_BUILD_TYPE=Release", - ] - - cfg = "Release" - build_args = ["--config", cfg] - - if platform.system() == "Windows": - cmake_args += [ - "-DBUILD_SHARED_LIBS:BOOL=OFF", - "-DBUILD_ALL_ANTS_APPS:BOOL=OFF", - "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir), - ] - # cmake_args += [ - # "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir) - # ] - # if sys.maxsize > 2 ** 32: - # cmake_args += ["-A", "x64"] - # build_args += ["--", "/m"] - # else: - # cmake_args += ["-DCMAKE_BUILD_TYPE=" + cfg] - # build_args += ["--", "-j2"] - - env = os.environ.copy() - # if platform.system() != "Windows": - # env["CXXFLAGS"] = '{} {} -DVERSION_INFO=\\"{}\\"'.format( - # "-Wno-inconsistent-missing-override", - # env.get("CXXFLAGS", ""), - # self.distribution.get_version(), - # ) - # env["LINKFLAGS"] = "{}".format("-Wno-inconsistent-missing-override") - - print(cmake_args) - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) - subprocess.check_call( - [ - "cmake", - ] - + cmake_args - + [ - ext.sourcedir, - ], - cwd=self.build_temp, - env=env, - ) - subprocess.check_call( - ["cmake", "--build", "."] + build_args, cwd=self.build_temp - ) - - -long_description = open("README.md").read() - -setup( - name="antspyx", - version=version, - install_requires=[ - "pandas", - "numpy", - "scipy", - "scikit-image", - "scikit-learn", - "statsmodels", - "webcolors", - "matplotlib", - "pyyaml", - "chart_studio", - "Pillow", - "nibabel", - ], - author="Brian B. Avants and Nicholas Cullen", - author_email="stnava@gmail.com", - description="Advanced Normalization Tools in Python", - long_description="Advanced Normalization Tools in Python wraps core C++-based ANTs tools for registration, segmentation and other basic processing.", - long_description_content_type="text/markdown; charset=UTF-8; variant=GFM", - ext_modules=[ - CMakeExtension("ants", sourcedir=os.path.join(setup_py_dir, "ants/lib/")) - ], - cmdclass={"build_py": build_py, "build_ext": CMakeBuild, "install": BuildExtFirst}, - zip_safe=False, - packages=find_packages(), - package_data={"ants": [ - "ants/lib/*.so*", - "ants/lib/*.pyd", - "ants/lib/*.dll", - "lib/*.so*", - "lib/*.pyd", - "lib/*.dll", - "ants/lib/*.so", - "ants/lib/*.pyd", - "ants/lib/*.dll", - "lib/*.so" - "lib/*.pyd" - "lib/*.dll" - ]}, - url="https://github.com/ANTsX/ANTsPy", - classifiers=["Programming Language :: Python :: 3.9"], -) diff --git a/ants/lib/ANTsVersionConfig.h b/src/ANTsVersionConfig.h similarity index 100% rename from ants/lib/ANTsVersionConfig.h rename to src/ANTsVersionConfig.h diff --git a/ants/lib/LOCAL_SmoothImage.cxx b/src/LOCAL_SmoothImage.cxx similarity index 65% rename from ants/lib/LOCAL_SmoothImage.cxx rename to src/LOCAL_SmoothImage.cxx index 8a7e50ac..0b2442ec 100644 --- a/ants/lib/LOCAL_SmoothImage.cxx +++ b/src/LOCAL_SmoothImage.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -10,17 +15,17 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule smoothImage( py::capsule ants_inimg, +AntsImage smoothImage( AntsImage & myPointer, std::vector sigma, bool sigmaInPhysicalCoordinates, unsigned int kernelwidth) { - typedef typename ImageType::Pointer ImagePointerType; - typename ImageType::Pointer inimg = as< ImageType >( ants_inimg ); + typename ImageType::Pointer inimg = myPointer.ptr; typedef itk::DiscreteGaussianImageFilter< ImageType, ImageType > discreteGaussianImageFilterType; typename discreteGaussianImageFilterType::Pointer filter = discreteGaussianImageFilterType::New(); @@ -51,14 +56,14 @@ py::capsule smoothImage( py::capsule ants_inimg, filter->SetInput( inimg ); filter->Update(); - py::capsule ants_outimg = wrap( filter->GetOutput() ); + AntsImage ants_outimg = { filter->GetOutput() }; return ants_outimg; } -PYBIND11_MODULE(SmoothImage, m) +void local_SmoothImage(nb::module_ &m) { - m.def("SmoothImage2D", &smoothImage>); - m.def("SmoothImage3D", &smoothImage>); - m.def("SmoothImage4D", &smoothImage>); + m.def("SmoothImage", &smoothImage>); + m.def("SmoothImage", &smoothImage>); + m.def("SmoothImage", &smoothImage>); } diff --git a/ants/lib/LOCAL_addNoiseToImage.cxx b/src/LOCAL_addNoiseToImage.cxx similarity index 60% rename from ants/lib/LOCAL_addNoiseToImage.cxx rename to src/LOCAL_addNoiseToImage.cxx index 9f8428aa..c04ab59f 100644 --- a/ants/lib/LOCAL_addNoiseToImage.cxx +++ b/src/LOCAL_addNoiseToImage.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -15,16 +20,14 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule additiveGaussianNoise( py::capsule & antsImage, +void * additiveGaussianNoise( typename ImageType::Pointer itkImage, float mean, float standardDeviation ) { - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); - using NoiseFilterType = itk::AdditiveGaussianNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); noiser->SetInput( itkImage ); @@ -36,14 +39,11 @@ py::capsule additiveGaussianNoise( py::capsule & antsImage, } template -py::capsule saltAndPepperNoise( py::capsule & antsImage, +void * saltAndPepperNoise( typename ImageType::Pointer itkImage, float probability, float saltValue, float pepperValue ) { - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); - using NoiseFilterType = itk::SaltAndPepperNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); noiser->SetInput( itkImage ); @@ -56,13 +56,10 @@ py::capsule saltAndPepperNoise( py::capsule & antsImage, } template -py::capsule shotNoise( py::capsule & antsImage, +void * shotNoise( typename ImageType::Pointer itkImage, float scale ) { - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); - using NoiseFilterType = itk::ShotNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); noiser->SetInput( itkImage ); @@ -73,12 +70,10 @@ py::capsule shotNoise( py::capsule & antsImage, } template -py::capsule speckleNoise( py::capsule & antsImage, +void * speckleNoise( typename ImageType::Pointer itkImage, float scale ) { - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); using NoiseFilterType = itk::SpeckleNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); @@ -89,18 +84,18 @@ py::capsule speckleNoise( py::capsule & antsImage, return wrap( noiser->GetOutput() ); } -PYBIND11_MODULE(addNoiseToImage, m) +void local_addNoiseToImage(nb::module_ &m) { - m.def("additiveGaussianNoiseF2", &additiveGaussianNoise>); - m.def("additiveGaussianNoiseF3", &additiveGaussianNoise>); + m.def("additiveGaussianNoise", &additiveGaussianNoise>); + m.def("additiveGaussianNoise", &additiveGaussianNoise>); - m.def("saltAndPepperNoiseF2", &saltAndPepperNoise>); - m.def("saltAndPepperNoiseF3", &saltAndPepperNoise>); + m.def("saltAndPepperNoise", &saltAndPepperNoise>); + m.def("saltAndPepperNoise", &saltAndPepperNoise>); - m.def("shotNoiseF2", &shotNoise>); - m.def("shotNoiseF3", &shotNoise>); + m.def("shotNoise", &shotNoise>); + m.def("shotNoise", &shotNoise>); - m.def("speckleNoiseF2", &speckleNoise>); - m.def("speckleNoiseF3", &speckleNoise>); + m.def("speckleNoise", &speckleNoise>); + m.def("speckleNoise", &speckleNoise>); } diff --git a/ants/lib/LOCAL_antiAlias.cxx b/src/LOCAL_antiAlias.cxx similarity index 100% rename from ants/lib/LOCAL_antiAlias.cxx rename to src/LOCAL_antiAlias.cxx diff --git a/src/LOCAL_antsImage.cxx b/src/LOCAL_antsImage.cxx new file mode 100644 index 00000000..d3af969c --- /dev/null +++ b/src/LOCAL_antsImage.cxx @@ -0,0 +1,389 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "itkPyBuffer.h" +#include "itkImageIOBase.h" +#include "itkImage.h" +#include "itkImageFileWriter.h" +#include "itkImageIOBase.h" +#include "itkNiftiImageIOFactory.h" +#include "itkMetaImageIOFactory.h" +#include "itkImageFileReader.h" +#include "itkImage.h" +#include + +#include "LOCAL_antsImage.h" + + +namespace nb = nanobind; +using namespace nb::literals; + +template +nb::object toNumpy( AntsImage & myPointer ) +{ + typename ImageType::Pointer image = myPointer.ptr; + typedef itk::PyBuffer PyBufferType; + PyObject * itkArray = PyBufferType::_GetArrayViewFromImage( image ); + nb::object itkArrayObject = nb::steal( itkArray ); + return itkArrayObject; +} + + +std::string ptrstr2(void * c) +{ + std::stringstream ss; + ss << (void const *)c; + std::string s = ss.str(); + return s; +} + + +/* +The return value (const char * file) from this function should be able to go +through the following code block without segfaulting. This is what ANTs uses +to convert back to an itk image. + +void * ptr; +sscanf(file, "%p", (void **)&ptr); +typename ImageType::Pointer newImage = *(static_cast(ptr)); +*/ +template +std::string ptrstr(AntsImage & myPointer) +{ + typename ImageType::Pointer * itkImage = & myPointer.ptr; + std::stringstream ss; + ss << (void const *)itkImage; + std::string s = ss.str(); + //const char * file = s.c_str(); + return s; +} + +void local_antsImage(nb::module_ &m) { + + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr>); + m.def("ptrstr", &ptrstr,2>>); + m.def("ptrstr", &ptrstr,3>>); + m.def("ptrstr", &ptrstr,2>>); + m.def("ptrstr", &ptrstr,3>>); + + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape>); + m.def("getShape", &getShape,2>>); + m.def("getShape", &getShape,3>>); + m.def("getShape", &getShape,2>>); + m.def("getShape", &getShape,3>>); + + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin,2>>); + m.def("getOrigin", &getOrigin,3>>); + m.def("getOrigin", &getOrigin,2>>); + m.def("getOrigin", &getOrigin,3>>); + + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin>); + m.def("setOrigin", &setOrigin,2>>); + m.def("setOrigin", &setOrigin,3>>); + m.def("setOrigin", &setOrigin,2>>); + m.def("setOrigin", &setOrigin,3>>); + + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing>); + m.def("getSpacing", &getSpacing,2>>); + m.def("getSpacing", &getSpacing,3>>); + m.def("getSpacing", &getSpacing,2>>); + m.def("getSpacing", &getSpacing,3>>); + + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing>); + m.def("setSpacing", &setSpacing,2>>); + m.def("setSpacing", &setSpacing,3>>); + m.def("setSpacing", &setSpacing,2>>); + m.def("setSpacing", &setSpacing,3>>); + + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection>); + m.def("getDirection", &getDirection,2>>); + m.def("getDirection", &getDirection,3>>); + m.def("getDirection", &getDirection,2>>); + m.def("getDirection", &getDirection,3>>); + + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection>); + m.def("setDirection", &setDirection,2>>); + m.def("setDirection", &setDirection,3>>); + m.def("setDirection", &setDirection,2>>); + m.def("setDirection", &setDirection,3>>); + + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile>); + m.def("toFile", &toFile,2>>); + m.def("toFile", &toFile,3>>); + m.def("toFile", &toFile,2>>); + m.def("toFile", &toFile,3>>); + + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy>); + m.def("toNumpy", &toNumpy,2>>); + m.def("toNumpy", &toNumpy,3>>); + m.def("toNumpy", &toNumpy,2>>); + m.def("toNumpy", &toNumpy,3>>); + + nb::class_>>(m, "AntsImageUC2"); + nb::class_>>(m, "AntsImageUC3"); + nb::class_>>(m, "AntsImageUC4"); + nb::class_>>(m, "AntsImageUI2"); + nb::class_>>(m, "AntsImageUI3"); + nb::class_>>(m, "AntsImageUI4"); + nb::class_>>(m, "AntsImageF2"); + nb::class_>>(m, "AntsImageF3"); + nb::class_>>(m, "AntsImageF4"); + nb::class_>>(m, "AntsImageD2"); + nb::class_>>(m, "AntsImageD3"); + nb::class_>>(m, "AntsImageD4"); + nb::class_>>(m, "AntsImageVUC2"); + nb::class_>>(m, "AntsImageVUC3"); + nb::class_>>(m, "AntsImageVUC4"); + nb::class_>>(m, "AntsImageVUI2"); + nb::class_>>(m, "AntsImageVUI3"); + nb::class_>>(m, "AntsImageVUI4"); + nb::class_>>(m, "AntsImageVF2"); + nb::class_>>(m, "AntsImageVF3"); + nb::class_>>(m, "AntsImageVF4"); + nb::class_>>(m, "AntsImageVD2"); + nb::class_>>(m, "AntsImageVD3"); + nb::class_>>(m, "AntsImageVD4"); + nb::class_,2>>>(m, "AntsImageRGBUC2"); + nb::class_,3>>>(m, "AntsImageRGBUC3"); + nb::class_,2>>>(m, "AntsImageRGBF2"); + nb::class_,3>>>(m, "AntsImageRGBF3"); +} diff --git a/src/LOCAL_antsImage.h b/src/LOCAL_antsImage.h new file mode 100644 index 00000000..6a146b70 --- /dev/null +++ b/src/LOCAL_antsImage.h @@ -0,0 +1,226 @@ +#ifndef __ANTSPYIMAGE_H +#define __ANTSPYIMAGE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "itkImageIOBase.h" + +#include "itkImage.h" +#include "itkImageFileReader.h" +#include "itkImageFileWriter.h" +#include "itkPyBuffer.h" +#include "itkVectorImage.h" +#include "itkChangeInformationImageFilter.h" + +#include "itkMath.h" +#include "itkPyVnl.h" +#include "itkMatrix.h" +#include "vnl/vnl_matrix_fixed.hxx" +#include "vnl/vnl_transpose.h" +#include "vnl/algo/vnl_matrix_inverse.h" +#include "vnl/vnl_matrix.h" +#include "vnl/algo/vnl_determinant.h" + +namespace nb = nanobind; +using namespace nb::literals; + + +template +typename ImageType::Pointer as( void * ptr ) +{ + typename ImageType::Pointer * real = static_cast(ptr); // static_cast or reinterpret_cast ?? + return *real; +} + +template +void * wrap( const typename ImageType::Pointer &image ) +{ + typedef typename ImageType::Pointer ImagePointerType; + ImagePointerType * ptr = new ImagePointerType( image ); + return ptr; +} + +template +typename ImageType::Pointer asImage( void * ptr ) { + typename ImageType::Pointer itkImage = ImageType::New(); + itkImage = as( ptr ); + return itkImage; +} + + +template +struct AntsImage { + typename ImageType::Pointer ptr; +}; + + +template +void toFile( AntsImage & myPointer, std::string filename ) +{ + typename ImageType::Pointer image = myPointer.ptr; + + typedef itk::ImageFileWriter< ImageType > ImageWriterType ; + typename ImageWriterType::Pointer image_writer = ImageWriterType::New() ; + image_writer->SetFileName( filename.c_str() ) ; + image_writer->SetInput( image ); + image_writer->Update(); +} + + +template +std::list getShape( AntsImage & myPointer ) +{ + typename ImageType::Pointer image = myPointer.ptr; + unsigned int ndim = ImageType::GetImageDimension(); + image->UpdateOutputInformation(); + typename ImageType::SizeType shape = image->GetBufferedRegion().GetSize(); + std::list shapelist; + for (int i = 0; i < ndim; i++) + { + shapelist.push_back( shape[i] ); + } + return shapelist; +} + + +template +std::vector getOrigin( AntsImage & myPointer ) +{ + typename ImageType::Pointer image = myPointer.ptr; + typename ImageType::PointType origin = image->GetOrigin(); + unsigned int ndim = ImageType::GetImageDimension(); + + std::vector originlist; + for (int i = 0; i < ndim; i++) + { + originlist.push_back( origin[i] ); + } + + return originlist; +} + +template +void setOrigin( AntsImage & myPointer, std::vector new_origin) +{ + typename ImageType::Pointer itkImage = myPointer.ptr; + unsigned int nvals = new_origin.size(); + typename ImageType::PointType origin = itkImage->GetOrigin(); + for (int i = 0; i < nvals; i++) + { + origin[i] = new_origin[i]; + } + itkImage->SetOrigin( origin ); +} + + +template +std::vector getDirection( AntsImage & myPointer ) +{ + typename ImageType::Pointer image = myPointer.ptr; + typedef typename ImageType::DirectionType ImageDirectionType; + ImageDirectionType direction = image->GetDirection(); + + typedef typename ImageDirectionType::InternalMatrixType DirectionInternalMatrixType; + DirectionInternalMatrixType fixed_matrix = direction.GetVnlMatrix(); + + vnl_matrix vnlmat1 = fixed_matrix.as_matrix(); + + const unsigned int ndim = ImageType::SizeType::GetSizeDimension(); + + std::vector dvec; + + for (int i = 0; i < ndim; i++) + { + for (int j = 0; j < ndim; j++) + { + dvec.push_back(vnlmat1(i,j)); + } + } + return dvec; + +} + + +template +void setDirection( AntsImage & myPointer, std::vector> new_direction) +{ + + typename ImageType::Pointer itkImage = myPointer.ptr; + + typename ImageType::DirectionType new_matrix2 = itkImage->GetDirection( ); + for ( std::size_t i = 0; i < new_direction.size(); i++ ) + for ( std::size_t j = 0; j < new_direction[0].size(); j++ ) { + new_matrix2(i,j) = new_direction[i][j]; + } + itkImage->SetDirection( new_matrix2 ); +} + +template +void setSpacing( AntsImage & myPointer, std::vector new_spacing) +{ + typename ImageType::Pointer itkImage = myPointer.ptr; + unsigned int nvals = new_spacing.size(); + typename ImageType::SpacingType spacing = itkImage->GetSpacing(); + + for (int i = 0; i < nvals; i++) + { + spacing[i] = new_spacing[i]; + } + itkImage->SetSpacing( spacing ); +} + +template +std::vector getSpacing( AntsImage & myPointer ) +{ + typename ImageType::Pointer image = myPointer.ptr; + typename ImageType::SpacingType spacing = image->GetSpacing(); + unsigned int ndim = ImageType::GetImageDimension(); + + std::vector spacinglist; + for (int i = 0; i < ndim; i++) + { + spacinglist.push_back( spacing[i] ); + } + + return spacinglist; +} + +/* +This function resets the region of an image to index from zero if needed. This +keeps the voxel indices in the numpy matrix consistent with the ITK image, and +also keeps the origin of physical space of the consistent with how it will be +saved as NIFTI. +*/ +template +static void FixNonZeroIndex( typename ImageType::Pointer img ) +{ + assert(img); + + typename ImageType::RegionType r = img->GetLargestPossibleRegion(); + typename ImageType::IndexType idx = r.GetIndex(); + + for (unsigned int i = 0; i < ImageType::ImageDimension; ++i) + { + // if any index is non-zero, reset the origin and region + if ( idx[i] != 0 ) + { + typename ImageType::PointType o; + img->TransformIndexToPhysicalPoint( idx, o ); + img->SetOrigin( o ); + + idx.Fill( 0 ); + r.SetIndex( idx ); + img->SetRegions( r ); + + return; + } + } +} + +#endif diff --git a/src/LOCAL_antsImageClone.cxx b/src/LOCAL_antsImageClone.cxx new file mode 100644 index 00000000..bb2422ef --- /dev/null +++ b/src/LOCAL_antsImageClone.cxx @@ -0,0 +1,114 @@ + +#include +#include +#include + +#include +#include +#include + +#include "itkImage.h" +#include "itkImageFileWriter.h" + +#include "LOCAL_antsImage.h" + +namespace nb = nanobind; + +template +AntsImage antsImageClone( AntsImage & myPointer ) +{ + typename InImageType::Pointer in_image = myPointer.ptr; + + typename OutImageType::Pointer out_image = OutImageType::New() ; + out_image->SetRegions( in_image->GetLargestPossibleRegion() ) ; + out_image->SetSpacing( in_image->GetSpacing() ) ; + out_image->SetOrigin( in_image->GetOrigin() ) ; + out_image->SetDirection( in_image->GetDirection() ); + //out_image->CopyInformation( in_image ); + out_image->AllocateInitialized(); + + itk::ImageRegionConstIterator< InImageType > in_iterator( in_image , in_image->GetLargestPossibleRegion() ) ; + itk::ImageRegionIterator< OutImageType > out_iterator( out_image , out_image->GetLargestPossibleRegion() ) ; + for( in_iterator.GoToBegin() , out_iterator.GoToBegin() ; !in_iterator.IsAtEnd() ; ++in_iterator , ++out_iterator ) + { + out_iterator.Set( static_cast< typename OutImageType::PixelType >( in_iterator.Get() ) ) ; + } + AntsImage outImage = { out_image }; + return outImage; +} +void local_antsImageClone(nb::module_ &m) { + + // call the function based on the image type you are converting TO. + // the image type you are converting FROM should be automatically inferred by the template + + // dim = 2 + m.def("antsImageCloneUC2", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC2", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC2", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC2", &antsImageClone,itk::Image>); + + m.def("antsImageCloneUI2", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI2", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI2", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI2", &antsImageClone,itk::Image>); + + m.def("antsImageCloneF2", &antsImageClone,itk::Image>); + m.def("antsImageCloneF2", &antsImageClone,itk::Image>); + m.def("antsImageCloneF2", &antsImageClone,itk::Image>); + m.def("antsImageCloneF2", &antsImageClone,itk::Image>); + + m.def("antsImageCloneD2", &antsImageClone,itk::Image>); + m.def("antsImageCloneD2", &antsImageClone,itk::Image>); + m.def("antsImageCloneD2", &antsImageClone,itk::Image>); + m.def("antsImageCloneD2", &antsImageClone,itk::Image>); + + m.def("antsImageCloneRGBUC2", &antsImageClone,2>,itk::Image,2>>); + + // dim = 3 + + m.def("antsImageCloneUC3", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC3", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC3", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC3", &antsImageClone,itk::Image>); + + m.def("antsImageCloneUI3", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI3", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI3", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI3", &antsImageClone,itk::Image>); + + m.def("antsImageCloneF3", &antsImageClone,itk::Image>); + m.def("antsImageCloneF3", &antsImageClone,itk::Image>); + m.def("antsImageCloneF3", &antsImageClone,itk::Image>); + m.def("antsImageCloneF3", &antsImageClone,itk::Image>); + + m.def("antsImageCloneD3", &antsImageClone,itk::Image>); + m.def("antsImageCloneD3", &antsImageClone,itk::Image>); + m.def("antsImageCloneD3", &antsImageClone,itk::Image>); + m.def("antsImageCloneD3", &antsImageClone,itk::Image>); + + m.def("antsImageCloneRGBUC3", &antsImageClone,3>,itk::Image,3>>); + + // dim = 4 + + m.def("antsImageCloneUC4", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC4", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC4", &antsImageClone,itk::Image>); + m.def("antsImageCloneUC4", &antsImageClone,itk::Image>); + + m.def("antsImageCloneUI4", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI4", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI4", &antsImageClone,itk::Image>); + m.def("antsImageCloneUI4", &antsImageClone,itk::Image>); + + m.def("antsImageCloneF4", &antsImageClone,itk::Image>); + m.def("antsImageCloneF4", &antsImageClone,itk::Image>); + m.def("antsImageCloneF4", &antsImageClone,itk::Image>); + m.def("antsImageCloneF4", &antsImageClone,itk::Image>); + + m.def("antsImageCloneD4", &antsImageClone,itk::Image>); + m.def("antsImageCloneD4", &antsImageClone,itk::Image>); + m.def("antsImageCloneD4", &antsImageClone,itk::Image>); + m.def("antsImageCloneD4", &antsImageClone,itk::Image>); + + m.def("antsImageCloneRGBUC4", &antsImageClone,4>,itk::Image,4>>); +} \ No newline at end of file diff --git a/ants/lib/LOCAL_antsImageHeaderInfo.cxx b/src/LOCAL_antsImageHeaderInfo.cxx similarity index 80% rename from ants/lib/LOCAL_antsImageHeaderInfo.cxx rename to src/LOCAL_antsImageHeaderInfo.cxx index 930e2f93..1c4117e2 100644 --- a/ants/lib/LOCAL_antsImageHeaderInfo.cxx +++ b/src/LOCAL_antsImageHeaderInfo.cxx @@ -1,6 +1,10 @@ -#include -#include +#include +#include +#include +#include +#include +#include #include #include @@ -9,12 +13,11 @@ #include "itkImage.h" #include "itkImageFileReader.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; -using namespace py::literals; - -py::dict antsImageHeaderInfo( std::string fname ) +nb::dict antsImageHeaderInfo( std::string fname ) { itk::ImageIOBase::Pointer imageIO = @@ -92,18 +95,21 @@ py::dict antsImageHeaderInfo( std::string fname ) pixeltype = "invalid"; } - return py::dict("pixelclass"_a=pixelClass, - "pixeltype"_a=pixeltype, - "nDimensions"_a=numDimensions, - "nComponents"_a=numComponents, - "dimensions"_a=dimensions, - "spacing"_a=spacing, - "origin"_a=origin, - "direction"_a=direction); + nb::dict info; + info["pixelclass"] = pixelClass; + info["pixeltype"] = pixeltype; + info["nDimensions"] = numDimensions; + info["nComponents"] = numComponents; + info["dimensions"] = dimensions; + info["spacing"] = spacing; + info["origin"] = origin; + info["direction"] = direction; + + return info; } -PYBIND11_MODULE(antsImageHeaderInfo, m) +void local_antsImageHeaderInfo(nb::module_ &m) { m.def("antsImageHeaderInfo", &antsImageHeaderInfo); } diff --git a/ants/lib/LOCAL_antsImageMutualInformation.cxx b/src/LOCAL_antsImageMutualInformation.cxx similarity index 100% rename from ants/lib/LOCAL_antsImageMutualInformation.cxx rename to src/LOCAL_antsImageMutualInformation.cxx diff --git a/ants/lib/LOCAL_antsImageToImageMetric.cxx b/src/LOCAL_antsImageToImageMetric.cxx similarity index 100% rename from ants/lib/LOCAL_antsImageToImageMetric.cxx rename to src/LOCAL_antsImageToImageMetric.cxx diff --git a/ants/lib/LOCAL_antsImageToImageMetric.h b/src/LOCAL_antsImageToImageMetric.h similarity index 100% rename from ants/lib/LOCAL_antsImageToImageMetric.h rename to src/LOCAL_antsImageToImageMetric.h diff --git a/ants/lib/LOCAL_antsImageUtils.cxx b/src/LOCAL_antsImageUtils.cxx similarity index 100% rename from ants/lib/LOCAL_antsImageUtils.cxx rename to src/LOCAL_antsImageUtils.cxx diff --git a/ants/lib/LOCAL_antsImageWin.cxx b/src/LOCAL_antsImageWin.cxx similarity index 99% rename from ants/lib/LOCAL_antsImageWin.cxx rename to src/LOCAL_antsImageWin.cxx index 3c1b2099..9dc027b6 100644 --- a/ants/lib/LOCAL_antsImageWin.cxx +++ b/src/LOCAL_antsImageWin.cxx @@ -49,7 +49,7 @@ std::string ptrstr(py::capsule c) */ // version contributed by @SGotla -std::string ptrstr(py::capsule c) +std::string ptrstr(void * c) { char buffer[50]; int n = sprintf(buffer, "0x%p", (void const *)c); diff --git a/ants/lib/LOCAL_antsTransform.cxx b/src/LOCAL_antsTransform.cxx similarity index 100% rename from ants/lib/LOCAL_antsTransform.cxx rename to src/LOCAL_antsTransform.cxx diff --git a/ants/lib/LOCAL_antsTransform.h b/src/LOCAL_antsTransform.h similarity index 100% rename from ants/lib/LOCAL_antsTransform.h rename to src/LOCAL_antsTransform.h diff --git a/ants/lib/LOCAL_composeDisplacementFields.cxx b/src/LOCAL_composeDisplacementFields.cxx similarity index 100% rename from ants/lib/LOCAL_composeDisplacementFields.cxx rename to src/LOCAL_composeDisplacementFields.cxx diff --git a/ants/lib/LOCAL_cropImage.cxx b/src/LOCAL_cropImage.cxx similarity index 100% rename from ants/lib/LOCAL_cropImage.cxx rename to src/LOCAL_cropImage.cxx diff --git a/ants/lib/LOCAL_fitBsplineDisplacementField.cxx b/src/LOCAL_fitBsplineDisplacementField.cxx similarity index 100% rename from ants/lib/LOCAL_fitBsplineDisplacementField.cxx rename to src/LOCAL_fitBsplineDisplacementField.cxx diff --git a/ants/lib/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx b/src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx similarity index 100% rename from ants/lib/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx rename to src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx diff --git a/ants/lib/LOCAL_fitBsplineObjectToScatteredData.cxx b/src/LOCAL_fitBsplineObjectToScatteredData.cxx similarity index 100% rename from ants/lib/LOCAL_fitBsplineObjectToScatteredData.cxx rename to src/LOCAL_fitBsplineObjectToScatteredData.cxx diff --git a/ants/lib/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx b/src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx similarity index 100% rename from ants/lib/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx rename to src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx diff --git a/ants/lib/LOCAL_fsl2antstransform.cxx b/src/LOCAL_fsl2antstransform.cxx similarity index 100% rename from ants/lib/LOCAL_fsl2antstransform.cxx rename to src/LOCAL_fsl2antstransform.cxx diff --git a/ants/lib/LOCAL_getNeighborhoodMatrix.cxx b/src/LOCAL_getNeighborhoodMatrix.cxx similarity index 100% rename from ants/lib/LOCAL_getNeighborhoodMatrix.cxx rename to src/LOCAL_getNeighborhoodMatrix.cxx diff --git a/ants/lib/LOCAL_hausdorffDistance.cxx b/src/LOCAL_hausdorffDistance.cxx similarity index 100% rename from ants/lib/LOCAL_hausdorffDistance.cxx rename to src/LOCAL_hausdorffDistance.cxx diff --git a/ants/lib/LOCAL_histogramMatchImages.cxx b/src/LOCAL_histogramMatchImages.cxx similarity index 100% rename from ants/lib/LOCAL_histogramMatchImages.cxx rename to src/LOCAL_histogramMatchImages.cxx diff --git a/ants/lib/LOCAL_integrateVelocityField.cxx b/src/LOCAL_integrateVelocityField.cxx similarity index 100% rename from ants/lib/LOCAL_integrateVelocityField.cxx rename to src/LOCAL_integrateVelocityField.cxx diff --git a/ants/lib/LOCAL_invertDisplacementField.cxx b/src/LOCAL_invertDisplacementField.cxx similarity index 100% rename from ants/lib/LOCAL_invertDisplacementField.cxx rename to src/LOCAL_invertDisplacementField.cxx diff --git a/ants/lib/LOCAL_labelOverlapMeasures.cxx b/src/LOCAL_labelOverlapMeasures.cxx similarity index 100% rename from ants/lib/LOCAL_labelOverlapMeasures.cxx rename to src/LOCAL_labelOverlapMeasures.cxx diff --git a/ants/lib/LOCAL_labelStats.cxx b/src/LOCAL_labelStats.cxx similarity index 100% rename from ants/lib/LOCAL_labelStats.cxx rename to src/LOCAL_labelStats.cxx diff --git a/src/LOCAL_mergeChannels.cxx b/src/LOCAL_mergeChannels.cxx new file mode 100644 index 00000000..dd54ff1e --- /dev/null +++ b/src/LOCAL_mergeChannels.cxx @@ -0,0 +1,142 @@ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "itkImage.h" +#include "itkVectorImage.h" +#include "itkImageRegionIteratorWithIndex.h" + +#include "LOCAL_antsImage.h" + +namespace nb = nanobind; + +using namespace nb::literals; + +template< class ImageType, class VectorImageType > +AntsImage mergeChannels( std::vector> imageList ) +{ + typedef typename ImageType::Pointer ImagePointerType; + typedef typename VectorImageType::Pointer VectorImagePointerType; + + unsigned int nImages = imageList.size(); + + std::vector images; + for ( unsigned int i=0; iSetRegions( images[0]->GetLargestPossibleRegion() ); + vectorImage->SetSpacing( images[0]->GetSpacing() ); + vectorImage->SetOrigin( images[0]->GetOrigin() ); + vectorImage->SetDirection( images[0]->GetDirection() ); + vectorImage->SetNumberOfComponentsPerPixel( nImages ); + vectorImage->AllocateInitialized(); + + // Fill image data + itk::ImageRegionIteratorWithIndex it( vectorImage, + vectorImage->GetLargestPossibleRegion() ); + + while (!it.IsAtEnd() ) + { + typename VectorImageType::PixelType pix; + pix.SetSize( nImages ); + for (unsigned int i=0; iGetPixel(it.GetIndex()); + } + vectorImage->SetPixel(it.GetIndex(), pix); + ++it; + } + + AntsImage outImage = { vectorImage }; + return outImage; +} + +template< class VectorImageType, class ImageType> +std::vector> splitChannels( AntsImage & antsimage ) +{ + typedef typename ImageType::Pointer ImagePointerType; + typedef typename VectorImageType::Pointer VectorImagePointerType; + + VectorImagePointerType input = antsimage.ptr; + unsigned int nComponents = input->GetNumberOfComponentsPerPixel(); + + // Create output images + std::vector images; + for ( unsigned int i=0; iSetRegions( input->GetLargestPossibleRegion() ); + image->SetSpacing( input->GetSpacing() ); + image->SetOrigin( input->GetOrigin() ); + image->SetDirection( input->GetDirection() ); + image->AllocateInitialized(); + images.push_back( image ); + } + + // Fill image data + itk::ImageRegionIteratorWithIndex it( input, + input->GetLargestPossibleRegion() ); + + while (!it.IsAtEnd() ) + { + typename VectorImageType::PixelType pix = input->GetPixel(it.GetIndex()); + + for (unsigned int i=0; iSetPixel(it.GetIndex(), pix[i]); + } + ++it; + } + + std::vector> outputList( nComponents ); + for (unsigned int i=0; i tmpImage = { images[i] }; + outputList[i] = tmpImage; + } + + return( outputList ); + +} + + +void local_mergeChannels(nb::module_ &m) { + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + m.def("mergeChannels", &mergeChannels, itk::VectorImage >); + + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, itk::Image >); + m.def("splitChannels", &splitChannels, 2>, itk::Image >); + + +} diff --git a/src/LOCAL_mergeChannels.h b/src/LOCAL_mergeChannels.h new file mode 100644 index 00000000..ceae2fa6 --- /dev/null +++ b/src/LOCAL_mergeChannels.h @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "itkImage.h" +#include "itkVectorImage.h" +#include "itkImageRegionIteratorWithIndex.h" + +#include "LOCAL_antsImage.h" + + +template< class VectorImageType, class ImageType> +std::vector> splitChannels( AntsImage & antsimage ); + +template< class ImageType, class VectorImageType > +AntsImage mergeChannels( std::vector> imageList ); \ No newline at end of file diff --git a/ants/lib/LOCAL_padImage.cxx b/src/LOCAL_padImage.cxx similarity index 100% rename from ants/lib/LOCAL_padImage.cxx rename to src/LOCAL_padImage.cxx diff --git a/src/LOCAL_readImage.cxx b/src/LOCAL_readImage.cxx new file mode 100644 index 00000000..5dbc1208 --- /dev/null +++ b/src/LOCAL_readImage.cxx @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include + +#include +#include "itkImageFileWriter.h" +#include "itkImageIOBase.h" +#include "itkNiftiImageIOFactory.h" +#include "itkMetaImageIOFactory.h" +#include "itkImageFileReader.h" +#include "itkImage.h" +#include "itkPyBuffer.h" + +#include "LOCAL_readImage.h" +#include "LOCAL_antsImage.h" + + +namespace nb = nanobind; +using namespace nb::literals; + + +template +AntsImage imageRead( std::string filename ) +{ + typedef typename ImageType::Pointer ImagePointerType; + typedef itk::ImageFileReader< ImageType > ImageReaderType; + + typename ImageReaderType::Pointer image_reader = ImageReaderType::New() ; + image_reader->SetFileName( filename.c_str() ) ; + image_reader->Update(); + + ImagePointerType itkImage = image_reader->GetOutput(); + AntsImage myImage = { itkImage }; + return myImage; +} + + +template +AntsImage fromNumpy( nb::ndarray data, nb::tuple datashape ) +{ + typedef typename ImageType::Pointer ImagePointerType; + ImagePointerType antsImage = ImageType::New(); + typedef itk::PyBuffer PyBufferType; + + nb::object o = nb::cast(data); + antsImage = PyBufferType::_GetImageViewFromArray(o.ptr(), datashape.ptr(), nb::make_tuple(1)[0].ptr()); + + AntsImage myImage = { antsImage }; + return myImage; +} + + +void local_readImage(nb::module_ &m) { + + m.def("imageReadUC2", &imageRead>); + m.def("imageReadUC3", &imageRead>); + m.def("imageReadUC4", &imageRead>); + m.def("imageReadUI2", &imageRead>); + m.def("imageReadUI3", &imageRead>); + m.def("imageReadUI4", &imageRead>); + m.def("imageReadF2", &imageRead>); + m.def("imageReadF3", &imageRead>); + m.def("imageReadF4", &imageRead>); + m.def("imageReadD2", &imageRead>); + m.def("imageReadD3", &imageRead>); + m.def("imageReadD4", &imageRead>); + m.def("imageReadVUC2", &imageRead>); + m.def("imageReadVUC3", &imageRead>); + m.def("imageReadVUC4", &imageRead>); + m.def("imageReadVUI2", &imageRead>); + m.def("imageReadVUI3", &imageRead>); + m.def("imageReadVUI4", &imageRead>); + m.def("imageReadVF2", &imageRead>); + m.def("imageReadVF3", &imageRead>); + m.def("imageReadVF4", &imageRead>); + m.def("imageReadVD2", &imageRead>); + m.def("imageReadVD3", &imageRead>); + m.def("imageReadVD4", &imageRead>); + m.def("imageReadRGBUC2", &imageRead,2>>); + m.def("imageReadRGBUC3", &imageRead,3>>); + m.def("imageReadRGBF2", &imageRead,2>>); + m.def("imageReadRGBF3", &imageRead,3>>); + + + m.def("fromNumpyUC2", &fromNumpy>); + m.def("fromNumpyUC3", &fromNumpy>); + m.def("fromNumpyUC4", &fromNumpy>); + m.def("fromNumpyUI2", &fromNumpy>); + m.def("fromNumpyUI3", &fromNumpy>); + m.def("fromNumpyUI4", &fromNumpy>); + m.def("fromNumpyF2", &fromNumpy>); + m.def("fromNumpyF3", &fromNumpy>); + m.def("fromNumpyF4", &fromNumpy>); + m.def("fromNumpyD2", &fromNumpy>); + m.def("fromNumpyD3", &fromNumpy>); + m.def("fromNumpyD4", &fromNumpy>); +} \ No newline at end of file diff --git a/ants/lib/LOCAL_readImage.h b/src/LOCAL_readImage.h similarity index 55% rename from ants/lib/LOCAL_readImage.h rename to src/LOCAL_readImage.h index 3fd40acb..ecc28a9a 100644 --- a/ants/lib/LOCAL_readImage.h +++ b/src/LOCAL_readImage.h @@ -1,9 +1,11 @@ #ifndef ANTSPYREADIMAGE_H #define ANTSPYREADIMAGE_H -#include -#include -#include +#include +#include +#include +#include +#include #include #include "itkImageFileWriter.h" @@ -15,10 +17,12 @@ #include "itkPyBuffer.h" #include "LOCAL_antsImage.h" -#include "LOCAL_antsImage.h" + +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule fromNumpy( py::array data, py::tuple datashape ); +AntsImage fromNumpy( nb::ndarray data, nb::tuple datashape ); #endif // ANTSPYREADIMAGE_H \ No newline at end of file diff --git a/ants/lib/LOCAL_readTransform.cxx b/src/LOCAL_readTransform.cxx similarity index 100% rename from ants/lib/LOCAL_readTransform.cxx rename to src/LOCAL_readTransform.cxx diff --git a/ants/lib/LOCAL_readTransform.h b/src/LOCAL_readTransform.h similarity index 100% rename from ants/lib/LOCAL_readTransform.h rename to src/LOCAL_readTransform.h diff --git a/ants/lib/LOCAL_reflectionMatrix.cxx b/src/LOCAL_reflectionMatrix.cxx similarity index 100% rename from ants/lib/LOCAL_reflectionMatrix.cxx rename to src/LOCAL_reflectionMatrix.cxx diff --git a/ants/lib/LOCAL_reorientImage.cxx b/src/LOCAL_reorientImage.cxx similarity index 100% rename from ants/lib/LOCAL_reorientImage.cxx rename to src/LOCAL_reorientImage.cxx diff --git a/ants/lib/LOCAL_reorientImage2.cxx b/src/LOCAL_reorientImage2.cxx similarity index 100% rename from ants/lib/LOCAL_reorientImage2.cxx rename to src/LOCAL_reorientImage2.cxx diff --git a/ants/lib/LOCAL_rgbToVector.cxx b/src/LOCAL_rgbToVector.cxx similarity index 100% rename from ants/lib/LOCAL_rgbToVector.cxx rename to src/LOCAL_rgbToVector.cxx diff --git a/ants/lib/LOCAL_sccaner.cxx b/src/LOCAL_sccaner.cxx similarity index 100% rename from ants/lib/LOCAL_sccaner.cxx rename to src/LOCAL_sccaner.cxx diff --git a/ants/lib/LOCAL_simulateDisplacementField.cxx b/src/LOCAL_simulateDisplacementField.cxx similarity index 100% rename from ants/lib/LOCAL_simulateDisplacementField.cxx rename to src/LOCAL_simulateDisplacementField.cxx diff --git a/ants/lib/LOCAL_sliceImage.cxx b/src/LOCAL_sliceImage.cxx similarity index 100% rename from ants/lib/LOCAL_sliceImage.cxx rename to src/LOCAL_sliceImage.cxx diff --git a/ants/lib/LOCAL_weingartenImageCurvature.cxx b/src/LOCAL_weingartenImageCurvature.cxx similarity index 100% rename from ants/lib/LOCAL_weingartenImageCurvature.cxx rename to src/LOCAL_weingartenImageCurvature.cxx diff --git a/ants/lib/ReadWriteData.h b/src/ReadWriteData.h similarity index 100% rename from ants/lib/ReadWriteData.h rename to src/ReadWriteData.h diff --git a/src/WRAP_Atropos.cxx b/src/WRAP_Atropos.cxx new file mode 100644 index 00000000..eec3cfc7 --- /dev/null +++ b/src/WRAP_Atropos.cxx @@ -0,0 +1,20 @@ +#include +#include +#include + +#include "antscore/Atropos.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int Atropos( StrVector instring ) +{ + return ants::Atropos(instring, NULL); +} + +void wrap_Atropos(nb::module_ &m) { + m.def("Atropos", &Atropos); +} + diff --git a/src/WRAP_AverageAffineTransform.cxx b/src/WRAP_AverageAffineTransform.cxx new file mode 100644 index 00000000..debe378f --- /dev/null +++ b/src/WRAP_AverageAffineTransform.cxx @@ -0,0 +1,20 @@ +#include +#include +#include + +#include "antscore/AverageAffineTransform.h" +#include "antscore/AverageAffineTransformNoRigid.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int AverageAffineTransform( StrVector instring ) +{ + return ants::AverageAffineTransform(instring, NULL); +} + +void wrap_AverageAffineTransform(nb::module_ &m) { + m.def("AverageAffineTransform", &AverageAffineTransform); +} \ No newline at end of file diff --git a/src/WRAP_AverageAffineTransformNoRigid.cxx b/src/WRAP_AverageAffineTransformNoRigid.cxx new file mode 100644 index 00000000..af5ea5c5 --- /dev/null +++ b/src/WRAP_AverageAffineTransformNoRigid.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/AverageAffineTransformNoRigid.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int AverageAffineTransformNoRigid( StrVector instring ) +{ + return ants::AverageAffineTransformNoRigid(instring, NULL); +} + +void wrap_AverageAffineTransformNoRigid(nb::module_ &m) { + m.def("AverageAffineTransformNoRigid", &AverageAffineTransformNoRigid); +} \ No newline at end of file diff --git a/src/WRAP_CreateJacobianDeterminantImage.cxx b/src/WRAP_CreateJacobianDeterminantImage.cxx new file mode 100644 index 00000000..7528d252 --- /dev/null +++ b/src/WRAP_CreateJacobianDeterminantImage.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/CreateJacobianDeterminantImage.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int CreateJacobianDeterminantImage( StrVector instring ) +{ + return ants::CreateJacobianDeterminantImage(instring, NULL); +} + +void wrap_CreateJacobianDeterminantImage(nb::module_ &m) { + m.def("CreateJacobianDeterminantImage", &CreateJacobianDeterminantImage); +} \ No newline at end of file diff --git a/src/WRAP_DenoiseImage.cxx b/src/WRAP_DenoiseImage.cxx new file mode 100644 index 00000000..2f165643 --- /dev/null +++ b/src/WRAP_DenoiseImage.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/DenoiseImage.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int DenoiseImage( StrVector instring ) +{ + return ants::DenoiseImage(instring, NULL); +} + +void wrap_DenoiseImage(nb::module_ &m) { + m.def("DenoiseImage", &DenoiseImage); +} \ No newline at end of file diff --git a/src/WRAP_KellyKapowski.cxx b/src/WRAP_KellyKapowski.cxx new file mode 100644 index 00000000..e1a7d43f --- /dev/null +++ b/src/WRAP_KellyKapowski.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/KellyKapowski.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int KellyKapowski( StrVector instring ) +{ + return ants::KellyKapowski(instring, NULL); +} + +void wrap_KellyKapowski(nb::module_ &m) { + m.def("KellyKapowski", &KellyKapowski); +} \ No newline at end of file diff --git a/src/WRAP_LabelClustersUniquely.cxx b/src/WRAP_LabelClustersUniquely.cxx new file mode 100644 index 00000000..917a8f95 --- /dev/null +++ b/src/WRAP_LabelClustersUniquely.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/LabelClustersUniquely.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int LabelClustersUniquely( StrVector instring ) +{ + return ants::LabelClustersUniquely(instring, NULL); +} + +void wrap_LabelClustersUniquely(nb::module_ &m) { + m.def("LabelClustersUniquely", &LabelClustersUniquely); +} \ No newline at end of file diff --git a/src/WRAP_LabelGeometryMeasures.cxx b/src/WRAP_LabelGeometryMeasures.cxx new file mode 100644 index 00000000..db93280f --- /dev/null +++ b/src/WRAP_LabelGeometryMeasures.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/LabelGeometryMeasures.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int LabelGeometryMeasures( StrVector instring ) +{ + return ants::LabelGeometryMeasures(instring, NULL); +} + +void wrap_LabelGeometryMeasures(nb::module_ &m) { + m.def("LabelGeometryMeasures", &LabelGeometryMeasures); +} \ No newline at end of file diff --git a/src/WRAP_N3BiasFieldCorrection.cxx b/src/WRAP_N3BiasFieldCorrection.cxx new file mode 100644 index 00000000..6e73dcc0 --- /dev/null +++ b/src/WRAP_N3BiasFieldCorrection.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/N3BiasFieldCorrection.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int N3BiasFieldCorrection( StrVector instring ) +{ + return ants::N3BiasFieldCorrection(instring, NULL); +} + +void wrap_N3BiasFieldCorrection(nb::module_ &m) { + m.def("N3BiasFieldCorrection", &N3BiasFieldCorrection); +} \ No newline at end of file diff --git a/src/WRAP_N4BiasFieldCorrection.cxx b/src/WRAP_N4BiasFieldCorrection.cxx new file mode 100644 index 00000000..e998cada --- /dev/null +++ b/src/WRAP_N4BiasFieldCorrection.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/N4BiasFieldCorrection.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int N4BiasFieldCorrection( StrVector instring ) +{ + return ants::N4BiasFieldCorrection(instring, NULL); +} + +void wrap_N4BiasFieldCorrection(nb::module_ &m) { + m.def("N4BiasFieldCorrection", &N4BiasFieldCorrection); +} \ No newline at end of file diff --git a/src/WRAP_ResampleImage.cxx b/src/WRAP_ResampleImage.cxx new file mode 100644 index 00000000..7e103aa7 --- /dev/null +++ b/src/WRAP_ResampleImage.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/ResampleImage.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int ResampleImage( StrVector instring ) +{ + return ants::ResampleImage(instring, NULL); +} + +void wrap_ResampleImage(nb::module_ &m) { + m.def("ResampleImage", &ResampleImage); +} \ No newline at end of file diff --git a/src/WRAP_ThresholdImage.cxx b/src/WRAP_ThresholdImage.cxx new file mode 100644 index 00000000..1de1a5b5 --- /dev/null +++ b/src/WRAP_ThresholdImage.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/ThresholdImage.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int ThresholdImage( std::vector instring ) +{ + return ants::ThresholdImage(instring, NULL); +} + +void wrap_ThresholdImage(nb::module_ &m) { + m.def("ThresholdImage", &ThresholdImage); +} diff --git a/src/WRAP_TileImages.cxx b/src/WRAP_TileImages.cxx new file mode 100644 index 00000000..960ad1b9 --- /dev/null +++ b/src/WRAP_TileImages.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/TileImages.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int TileImages( StrVector instring ) +{ + return ants::TileImages(instring, NULL); +} + +void wrap_TileImages(nb::module_ &m) { + m.def("TileImages", &TileImages); +} \ No newline at end of file diff --git a/src/WRAP_antsAffineInitializer.cxx b/src/WRAP_antsAffineInitializer.cxx new file mode 100644 index 00000000..b848d180 --- /dev/null +++ b/src/WRAP_antsAffineInitializer.cxx @@ -0,0 +1,20 @@ +#include +#include +#include + +#include "antscore/antsAffineInitializer.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int antsAffineInitializer( StrVector instring ) +{ + return ants::antsAffineInitializer(instring, NULL); +} + +void wrap_antsAffineInitializer(nb::module_ &m) { + m.def("antsAffineInitializer", &antsAffineInitializer); +} + diff --git a/src/WRAP_antsApplyTransforms.cxx b/src/WRAP_antsApplyTransforms.cxx new file mode 100644 index 00000000..f85a2bd5 --- /dev/null +++ b/src/WRAP_antsApplyTransforms.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/antsApplyTransforms.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int antsApplyTransforms( std::vector instring ) +{ + return ants::antsApplyTransforms(instring, NULL); +} + +void wrap_antsApplyTransforms(nb::module_ &m) { + m.def("antsApplyTransforms", &antsApplyTransforms); +} \ No newline at end of file diff --git a/ants/lib/WRAP_antsApplyTransformsToPoints.cxx b/src/WRAP_antsApplyTransformsToPoints.cxx similarity index 50% rename from ants/lib/WRAP_antsApplyTransformsToPoints.cxx rename to src/WRAP_antsApplyTransformsToPoints.cxx index ed933c31..055583a9 100644 --- a/ants/lib/WRAP_antsApplyTransformsToPoints.cxx +++ b/src/WRAP_antsApplyTransformsToPoints.cxx @@ -1,17 +1,19 @@ - -#include -#include +#include +#include +#include #include "antscore/antsApplyTransformsToPoints.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; int antsApplyTransformsToPoints( std::vector instring ) { return ants::antsApplyTransformsToPoints(instring, NULL); } -PYBIND11_MODULE(antsApplyTransformsToPoints, m) -{ +void wrap_antsApplyTransformsToPoints(nb::module_ &m) { m.def("antsApplyTransformsToPoints", &antsApplyTransformsToPoints); -} +} \ No newline at end of file diff --git a/src/WRAP_antsJointFusion.cxx b/src/WRAP_antsJointFusion.cxx new file mode 100644 index 00000000..d9fdbe89 --- /dev/null +++ b/src/WRAP_antsJointFusion.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/antsJointFusion.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int antsJointFusion( std::vector instring ) +{ + return ants::antsJointFusion(instring, NULL); +} + +void wrap_antsJointFusion(nb::module_ &m) { + m.def("antsJointFusion", &antsJointFusion); +} \ No newline at end of file diff --git a/src/WRAP_antsRegistration.cxx b/src/WRAP_antsRegistration.cxx new file mode 100644 index 00000000..e101e281 --- /dev/null +++ b/src/WRAP_antsRegistration.cxx @@ -0,0 +1,20 @@ +#include +#include +#include + +#include "antscore/antsRegistration.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int antsRegistration( StrVector instring ) +{ + return ants::antsRegistration(instring, NULL); +} + +void wrap_antsRegistration(nb::module_ &m) { + m.def("antsRegistration", &antsRegistration); +} + diff --git a/src/WRAP_iMath.cxx b/src/WRAP_iMath.cxx new file mode 100644 index 00000000..3d95cc45 --- /dev/null +++ b/src/WRAP_iMath.cxx @@ -0,0 +1,19 @@ +#include +#include +#include + +#include "antscore/iMath.h" + +namespace nb = nanobind; +using namespace nb::literals; + +using StrVector = std::vector; + +int iMath( StrVector instring ) +{ + return ants::iMath(instring, NULL); +} + +void wrap_iMath(nb::module_ &m) { + m.def("iMath", &iMath); +} \ No newline at end of file diff --git a/ants/lib/itkPyBuffer.h b/src/itkPyBuffer.h similarity index 100% rename from ants/lib/itkPyBuffer.h rename to src/itkPyBuffer.h diff --git a/ants/lib/itkPyBuffer.hxx b/src/itkPyBuffer.hxx similarity index 100% rename from ants/lib/itkPyBuffer.hxx rename to src/itkPyBuffer.hxx diff --git a/ants/lib/itkPyVnl.h b/src/itkPyVnl.h similarity index 100% rename from ants/lib/itkPyVnl.h rename to src/itkPyVnl.h diff --git a/ants/lib/itkPyVnl.hxx b/src/itkPyVnl.hxx similarity index 100% rename from ants/lib/itkPyVnl.hxx rename to src/itkPyVnl.hxx diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 00000000..7aed8c83 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,89 @@ +#include + +#include "LOCAL_addNoiseToImage.cxx" +#include "LOCAL_antsImage.cxx" +#include "LOCAL_antsImageClone.cxx" +#include "LOCAL_antsImageHeaderInfo.cxx" +#include "LOCAL_mergeChannels.cxx" +#include "LOCAL_readImage.cxx" +#include "LOCAL_SmoothImage.cxx" + +#include "WRAP_antsAffineInitializer.cxx" +#include "WRAP_antsApplyTransforms.cxx" +#include "WRAP_antsApplyTransformsToPoints.cxx" +#include "WRAP_antsJointFusion.cxx" +#include "WRAP_antsRegistration.cxx" +#include "WRAP_Atropos.cxx" +#include "WRAP_AverageAffineTransform.cxx" +#include "WRAP_AverageAffineTransformNoRigid.cxx" +#include "WRAP_CreateJacobianDeterminantImage.cxx" +#include "WRAP_DenoiseImage.cxx" +#include "WRAP_iMath.cxx" +#include "WRAP_KellyKapowski.cxx" +#include "WRAP_LabelClustersUniquely.cxx" +#include "WRAP_LabelGeometryMeasures.cxx" +#include "WRAP_N3BiasFieldCorrection.cxx" +#include "WRAP_N4BiasFieldCorrection.cxx" +#include "WRAP_ResampleImage.cxx" +#include "WRAP_ThresholdImage.cxx" +#include "WRAP_TileImages.cxx" + +namespace nb = nanobind; + +void local_addNoiseToImage(nb::module_ &); +void local_antsImage(nb::module_ &); +void local_antsImageClone(nb::module_ &); +void local_antsImageHeaderInfo(nb::module_ &); +void local_mergeChannels(nb::module_ &); +void local_readImage(nb::module_ &); +void local_SmoothImage(nb::module_ &); + +void wrap_antsAffineInitializer(nb::module_ &); +void wrap_antsApplyTransforms(nb::module_ &); +void wrap_antsApplyTransformsToPoints(nb::module_ &); +void wrap_antsJointFusion(nb::module_ &); +void wrap_antsRegistration(nb::module_ &); +void wrap_Atropos(nb::module_ &); +void wrap_AverageAffineTransform(nb::module_ &); +void wrap_AverageAffineTransformNoRigid(nb::module_ &); +void wrap_CreateJacobianDeterminantImage(nb::module_ &); +void wrap_DenoiseImage(nb::module_ &); +void wrap_iMath(nb::module_ &); +void wrap_KellyKapowski(nb::module_ &); +void wrap_LabelClustersUniquely(nb::module_ &); +void wrap_LabelGeometryMeasures(nb::module_ &); +void wrap_N3BiasFieldCorrection(nb::module_ &); +void wrap_N4BiasFieldCorrection(nb::module_ &); +void wrap_ResampleImage(nb::module_ &); +void wrap_ThresholdImage(nb::module_ &); +void wrap_TileImages(nb::module_ &); + +NB_MODULE(lib, m) { + local_addNoiseToImage(m); + local_antsImage(m); + local_antsImageClone(m); + local_antsImageHeaderInfo(m); + local_mergeChannels(m); + local_readImage(m); + local_SmoothImage(m); + + wrap_antsAffineInitializer(m); + wrap_antsApplyTransforms(m); + wrap_antsApplyTransformsToPoints(m); + wrap_antsJointFusion(m); + wrap_antsRegistration(m); + wrap_Atropos(m); + wrap_AverageAffineTransform(m); + wrap_AverageAffineTransformNoRigid(m); + wrap_CreateJacobianDeterminantImage(m); + wrap_DenoiseImage(m); + wrap_iMath(m); + wrap_KellyKapowski(m); + wrap_LabelClustersUniquely(m); + wrap_LabelGeometryMeasures(m); + wrap_N3BiasFieldCorrection(m); + wrap_N4BiasFieldCorrection(m); + wrap_ResampleImage(m); + wrap_ThresholdImage(m); + wrap_TileImages(m); +} \ No newline at end of file diff --git a/ants/lib/register_transforms.h b/src/register_transforms.h similarity index 100% rename from ants/lib/register_transforms.h rename to src/register_transforms.h From 17c5e9eacd98e0a199395b6755f8fe2970752098 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 14:12:41 +0200 Subject: [PATCH 02/26] add scripts --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b4e98081..8b79cb7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,8 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) # otherwise you have to comment it out during development -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) # ITK set(ITK_DIR "./itkbuild") From ff4b7baee94908aa1cfcd84d310b1e0a0716dc36 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 14:45:08 +0200 Subject: [PATCH 03/26] add dependencies --- pyproject.toml | 3 +++ tests/run_tests.sh | 18 +++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 82330aa1..bc3f3c31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ authors = [ classifiers = [ "License :: OSI Approved :: BSD License", ] +dynamic = ["dependencies"] [project.urls] Homepage = "https://github.com/antsx/antspy" @@ -33,6 +34,8 @@ cmake.args = [] wheel.packages = ["ants"] +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} [tool.cibuildwheel] # Necessary to see build output from the actual compilation diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 61319cf5..843d5d57 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -23,27 +23,27 @@ pushd "$(dirname "$0")" echo "Running core tests" $PYCMD test_core_ants_image.py $@ $PYCMD test_core_ants_image_io.py $@ -$PYCMD test_core_ants_transform.py $@ -$PYCMD test_core_ants_transform_io.py $@ -$PYCMD test_core_ants_metric.py $@ +#$PYCMD test_core_ants_transform.py $@ +#$PYCMD test_core_ants_transform_io.py $@ +#$PYCMD test_core_ants_metric.py $@ echo "Running learn tests" -$PYCMD test_learn.py $@ +#$PYCMD test_learn.py $@ echo "Running registration tests" -$PYCMD test_registration.py $@ +#$PYCMD test_registration.py $@ echo "Running segmentation tests" -$PYCMD test_segmentation.py $@ +#$PYCMD test_segmentation.py $@ echo "Running utils tests" -$PYCMD test_utils.py $@ +#$PYCMD test_utils.py $@ echo "Running viz tests" -$PYCMD test_viz.py $@ +#$PYCMD test_viz.py $@ echo "Running bug tests" -$PYCMD test_bugs.py $@ +#$PYCMD test_bugs.py $@ From 2c191d34c6f13ab6e8be2e4865b72229d2e0a018 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 15:14:10 +0200 Subject: [PATCH 04/26] add deps --- CMakeLists.txt | 3 +-- pyproject.toml | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b79cb7c..45f333ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,9 +13,8 @@ find_package(Python 3.8 find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) -# TODO: make this handle different OS either here or within the configure script +# TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -# otherwise you have to comment it out during development execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) diff --git a/pyproject.toml b/pyproject.toml index bc3f3c31..35065a78 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,18 @@ authors = [ classifiers = [ "License :: OSI Approved :: BSD License", ] -dynamic = ["dependencies"] +dependenices = [ + "pandas", + "pyyaml", + "numpy", + "scikit-image", + "scikit-learn", + "statsmodels", + "webcolors", + "matplotlib", + "Pillow", + "nibabel" +] [project.urls] Homepage = "https://github.com/antsx/antspy" @@ -34,9 +45,6 @@ cmake.args = [] wheel.packages = ["ants"] -[tool.setuptools.dynamic] -dependencies = {file = ["requirements.txt"]} - [tool.cibuildwheel] # Necessary to see build output from the actual compilation build-verbosity = 1 From cf124085f4abcd552aa5ef0ea315a1ec2044589e Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 15:44:22 +0200 Subject: [PATCH 05/26] wrap more local functions --- CMakeLists.txt | 4 ++-- ants/utils/pad_image.py | 2 +- ants/utils/slice_image.py | 2 +- pyproject.toml | 2 +- src/LOCAL_padImage.cxx | 26 ++++++++++++++++---------- src/LOCAL_reorientImage2.cxx | 28 +++++++++++++++------------- src/LOCAL_sliceImage.cxx | 27 +++++++++++++++------------ src/main.cpp | 9 +++++++++ 8 files changed, 60 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f333ad..75e17056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) # TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) # ITK set(ITK_DIR "./itkbuild") diff --git a/ants/utils/pad_image.py b/ants/utils/pad_image.py index 3204c39e..86905f51 100644 --- a/ants/utils/pad_image.py +++ b/ants/utils/pad_image.py @@ -69,7 +69,7 @@ def pad_image(image, shape=None, pad_width=None, value=0.0, return_padvals=False lower_pad_vals.append(math.floor(p/2)) upper_pad_vals.append(math.ceil(p/2)) - libfn = utils.get_lib_fn('padImageF%i' % ndim) + libfn = utils.get_lib_fn('padImage') itkimage = libfn(image.pointer, lower_pad_vals, upper_pad_vals, value) new_image = iio.ANTsImage(pixeltype='float', dimension=ndim, diff --git a/ants/utils/slice_image.py b/ants/utils/slice_image.py index 05878693..3f50c5d9 100644 --- a/ants/utils/slice_image.py +++ b/ants/utils/slice_image.py @@ -42,7 +42,7 @@ def slice_image(image, axis, idx, collapse_strategy=0): if image.pixeltype != 'float': image = image.clone('float') - libfn = utils.get_lib_fn('sliceImageF%i' % ndim) + libfn = utils.get_lib_fn('sliceImage') itkimage = libfn(image.pointer, axis, idx, collapse_strategy) return iio.ANTsImage(pixeltype='float', dimension=ndim-1, diff --git a/pyproject.toml b/pyproject.toml index 35065a78..d99f9212 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"] +requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2", "numpy"] build-backend = "scikit_build_core.build" [project] diff --git a/src/LOCAL_padImage.cxx b/src/LOCAL_padImage.cxx index 6cb2d4ee..e25307e1 100644 --- a/src/LOCAL_padImage.cxx +++ b/src/LOCAL_padImage.cxx @@ -1,6 +1,9 @@ -#include -#include +#include +#include +#include +#include +#include #include #include @@ -11,16 +14,17 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template < typename ImageType > -py::capsule padImage( py::capsule & antsImage, +AntsImage padImage( AntsImage & antsImage, std::vector lowerPadDims, std::vector upperPadDims, float padValue ) { typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as< ImageType >( antsImage ); + typename ImageType::Pointer itkImage = antsImage.ptr; typename ImageType::SizeType lowerExtendRegion; @@ -48,13 +52,15 @@ py::capsule padImage( py::capsule & antsImage, padFilter->SetConstant( padValue ); padFilter->Update(); FixNonZeroIndex( padFilter->GetOutput() ); - return wrap< ImageType >( padFilter->GetOutput() ); + + AntsImage myImage = { padFilter->GetOutput() }; + return myImage; } -PYBIND11_MODULE(padImage, m) +void local_padImage(nb::module_ &m) { - m.def("padImageF2", &padImage>); - m.def("padImageF3", &padImage>); - m.def("padImageF4", &padImage>); + m.def("padImage", &padImage>); + m.def("padImage", &padImage>); + m.def("padImage", &padImage>); } diff --git a/src/LOCAL_reorientImage2.cxx b/src/LOCAL_reorientImage2.cxx index 3b1e3eb7..5dd4c0ae 100644 --- a/src/LOCAL_reorientImage2.cxx +++ b/src/LOCAL_reorientImage2.cxx @@ -1,24 +1,25 @@ -#include -#include +#include +#include +#include +#include +#include #include "itkImage.h" #include "itkOrientImageFilter.h" #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; - -py::capsule reorientImage2( py::capsule antsImage , std::string newOrientation ) +template +AntsImage reorientImage2( AntsImage & antsImage , std::string newOrientation ) { - typedef itk::Image ImageType; - typedef typename ImageType::Pointer ImagePointerType; - - ImagePointerType itkImage = as< ImageType >( antsImage ); + typename ImageType::Pointer itkImage = antsImage.ptr; - itk::OrientImageFilter::Pointer orienter = itk::OrientImageFilter::New(); + typename itk::OrientImageFilter::Pointer orienter = itk::OrientImageFilter::New(); orienter->UseImageDirectionOn(); if (newOrientation == "RIP") { @@ -167,10 +168,11 @@ py::capsule reorientImage2( py::capsule antsImage , std::string newOrientation ) } orienter->SetInput( itkImage ); orienter->Update(); - return wrap< ImageType >( orienter->GetOutput() ); + AntsImage myImage = { orienter->GetOutput() }; + return myImage; } -PYBIND11_MODULE(reorientImage2, m) +void local_reorientImage2(nb::module_ &m) { - m.def("reorientImage2", reorientImage2); + m.def("reorientImage2", &reorientImage2>); } \ No newline at end of file diff --git a/src/LOCAL_sliceImage.cxx b/src/LOCAL_sliceImage.cxx index dd25ac3a..f3390c3b 100644 --- a/src/LOCAL_sliceImage.cxx +++ b/src/LOCAL_sliceImage.cxx @@ -1,21 +1,23 @@ -#include -#include +#include +#include +#include +#include +#include #include "itkImage.h" #include "itkExtractImageFilter.h" #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; -template < typename ImageType, typename PixelType, unsigned int NewDimension > -py::capsule sliceImage( py::capsule antsImage, int plane, int slice, int collapseStrategy) +template < typename ImageType, typename SliceImageType> +AntsImage sliceImage( AntsImage & antsImage, int plane, int slice, int collapseStrategy) { - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as< ImageType >( antsImage ); + typename ImageType::Pointer itkImage = antsImage.ptr; - typedef itk::Image SliceImageType; typedef itk::ExtractImageFilter< ImageType, SliceImageType > FilterType; typename FilterType::Pointer filter = FilterType::New(); @@ -48,12 +50,13 @@ py::capsule sliceImage( py::capsule antsImage, int plane, int slice, int collaps filter->Update(); - return wrap( filter->GetOutput() ); + AntsImage myImage = { filter->GetOutput() }; + return myImage; } -PYBIND11_MODULE(sliceImage, m) +void local_sliceImage(nb::module_ &m) { - m.def("sliceImageF3", &sliceImage, float, 2>); - m.def("sliceImageF4", &sliceImage, float, 3>); + m.def("sliceImage", &sliceImage, itk::Image>); + m.def("sliceImage", &sliceImage, itk::Image>); } diff --git a/src/main.cpp b/src/main.cpp index 7aed8c83..4367844b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,10 @@ #include "LOCAL_antsImageClone.cxx" #include "LOCAL_antsImageHeaderInfo.cxx" #include "LOCAL_mergeChannels.cxx" +#include "LOCAL_padImage.cxx" #include "LOCAL_readImage.cxx" +#include "LOCAL_reorientImage2.cxx" +#include "LOCAL_sliceImage.cxx" #include "LOCAL_SmoothImage.cxx" #include "WRAP_antsAffineInitializer.cxx" @@ -35,7 +38,10 @@ void local_antsImage(nb::module_ &); void local_antsImageClone(nb::module_ &); void local_antsImageHeaderInfo(nb::module_ &); void local_mergeChannels(nb::module_ &); +void local_padImage(nb::module_ &); void local_readImage(nb::module_ &); +void local_reorientImage2(nb::module_ &); +void local_sliceImage(nb::module_ &); void local_SmoothImage(nb::module_ &); void wrap_antsAffineInitializer(nb::module_ &); @@ -64,7 +70,10 @@ NB_MODULE(lib, m) { local_antsImageClone(m); local_antsImageHeaderInfo(m); local_mergeChannels(m); + local_padImage(m); local_readImage(m); + local_reorientImage2(m); + local_sliceImage(m); local_SmoothImage(m); wrap_antsAffineInitializer(m); From 39bc6052113715eb8db44bafed0604292879650d Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 15:44:38 +0200 Subject: [PATCH 06/26] update cmake --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75e17056..45f333ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) # TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) # ITK set(ITK_DIR "./itkbuild") From 8ae38607ec109e403801d3c895f373439d583861 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 15:48:29 +0200 Subject: [PATCH 07/26] fix typo --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d99f9212..46a638ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2", "numpy"] +requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"] build-backend = "scikit_build_core.build" [project] @@ -14,7 +14,7 @@ authors = [ classifiers = [ "License :: OSI Approved :: BSD License", ] -dependenices = [ +dependencies = [ "pandas", "pyyaml", "numpy", From 5f58140acc3405cf26a977be8ed14293826ea50d Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 16:38:53 +0200 Subject: [PATCH 08/26] add functions for plotting --- .vscode/settings.json | 3 +- CMakeLists.txt | 4 +- ants/core/ants_transform.py | 22 ++-- ants/utils/crop_image.py | 6 +- pyproject.toml | 3 +- src/LOCAL_antsImageClone.cxx | 1 + src/LOCAL_antsTransform.cxx | 243 +++++++++++++++++++---------------- src/LOCAL_antsTransform.h | 119 ++++++++--------- src/LOCAL_cropImage.cxx | 36 +++--- src/LOCAL_readTransform.cxx | 56 +++++--- src/LOCAL_readTransform.h | 17 ++- src/main.cpp | 9 ++ tests/run_tests.sh | 2 +- 13 files changed, 284 insertions(+), 237 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 43896c1b..4d64aeb5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -83,6 +83,7 @@ "unordered_set": "cpp", "valarray": "cpp", "variant": "cpp", - "*.in": "cpp" + "*.in": "cpp", + "*.inc": "cpp" } } diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f333ad..75e17056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) # TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) # ITK set(ITK_DIR "./itkbuild") diff --git a/ants/core/ants_transform.py b/ants/core/ants_transform.py index 1465fcd7..c208a309 100644 --- a/ants/core/ants_transform.py +++ b/ants/core/ants_transform.py @@ -55,7 +55,7 @@ def __init__(self, precision='float', dimension=3, transform_type='AffineTransfo @property def parameters(self): """ Get parameters of transform """ - libfn = utils.get_lib_fn('getTransformParameters%s'%self._libsuffix) + libfn = utils.get_lib_fn('getTransformParameters') return np.asarray(libfn(self.pointer), order='F')#.reshape((self.dimension, self.dimension+1), order='F') def set_parameters(self, parameters): @@ -67,13 +67,13 @@ def set_parameters(self, parameters): if parameters.ndim > 1: parameters = parameters.flatten(order='F') - libfn = utils.get_lib_fn('setTransformParameters%s'%self._libsuffix) + libfn = utils.get_lib_fn('setTransformParameters') libfn(self.pointer, parameters.tolist()) @property def fixed_parameters(self): """ Get parameters of transform """ - libfn = utils.get_lib_fn('getTransformFixedParameters%s'%self._libsuffix) + libfn = utils.get_lib_fn('getTransformFixedParameters') return np.asarray(libfn(self.pointer)) def set_fixed_parameters(self, parameters): @@ -81,12 +81,12 @@ def set_fixed_parameters(self, parameters): if not isinstance(parameters, np.ndarray): parameters = np.asarray(parameters) - libfn = utils.get_lib_fn('setTransformFixedParameters%s'%self._libsuffix) + libfn = utils.get_lib_fn('setTransformFixedParameters') libfn(self.pointer, parameters.tolist()) def invert(self): """ Invert the transform """ - libfn = utils.get_lib_fn('inverseTransform%s' % (self._libsuffix)) + libfn = utils.get_lib_fn('inverseTransform') inv_tx_ptr = libfn(self.pointer) new_tx = ANTsTransform(precision=self.precision, dimension=self.dimension, @@ -127,7 +127,7 @@ def apply_to_point(self, point): >>> tx.set_parameters(params*2) >>> pt2 = tx.apply_to_point((1,2,3)) # should be (2,4,6) """ - libfn = utils.get_lib_fn('transformPoint%s' % (self._libsuffix)) + libfn = utils.get_lib_fn('transformPoint') return tuple(libfn(self.pointer, point)) def apply_to_vector(self, vector): @@ -146,7 +146,7 @@ def apply_to_vector(self, vector): if isinstance(vector, np.ndarray): vector = vector.tolist() - libfn = utils.get_lib_fn('transformVector%s' % (self._libsuffix)) + libfn = utils.get_lib_fn('transformVector') return np.asarray(libfn(self.pointer, vector)) def apply_to_image(self, image, reference=None, interpolation='linear'): @@ -184,7 +184,7 @@ def apply_to_image(self, image, reference=None, interpolation='linear'): interpolation = interpolation.lower() - tform_fn = utils.get_lib_fn('transformImage%s%s' % (self._libsuffix, image._libsuffix)) + tform_fn = utils.get_lib_fn('transformImage') reference = reference.clone(image.pixeltype) img_ptr = tform_fn(self.pointer, image.pointer, reference.pointer, interpolation) @@ -416,7 +416,7 @@ def compose_ants_transforms(transform_list): raise ValueError('All transforms must have the same dimension') tx_ptr_list = list(reversed([tf.pointer for tf in transform_list])) - libfn = utils.get_lib_fn('composeTransforms%s' % (transform_list[0]._libsuffix)) + libfn = utils.get_lib_fn('composeTransforms') itk_composed_tx = libfn(tx_ptr_list, precision, dimension) return ANTsTransform(precision=precision, dimension=dimension, transform_type='CompositeTransform', pointer=itk_composed_tx) @@ -462,7 +462,7 @@ def transform_index_to_physical_point(image, index): index = [i+1 for i in index] ndim = image.dimension ptype = image.pixeltype - libfn = utils.get_lib_fn('TransformIndexToPhysicalPoint%s%i' % (utils.short_ptype(ptype), ndim)) + libfn = utils.get_lib_fn('TransformIndexToPhysicalPoint') point = libfn(image.pointer, [list(index)]) return np.array(point[0]) @@ -509,7 +509,7 @@ def transform_physical_point_to_index(image, point): ndim = image.dimension ptype = image.pixeltype - libfn = utils.get_lib_fn('TransformPhysicalPointToIndex%s%i'%(utils.short_ptype(ptype),ndim)) + libfn = utils.get_lib_fn('TransformPhysicalPointToIndex') index = libfn(image.pointer, [list(point)]) index = [i-1 for i in index[0]] diff --git a/ants/utils/crop_image.py b/ants/utils/crop_image.py index d0759a4c..a65bc7c2 100644 --- a/ants/utils/crop_image.py +++ b/ants/utils/crop_image.py @@ -50,7 +50,7 @@ def crop_image(image, label_image=None, label=1): if label_image.pixeltype != 'float': label_image = label_image.clone('float') - libfn = utils.get_lib_fn('cropImageF%i' % ndim) + libfn = utils.get_lib_fn('cropImage') itkimage = libfn(image.pointer, label_image.pointer, label, 0, [], []) return iio.ANTsImage(pixeltype='float', dimension=ndim, components=image.components, pointer=itkimage).clone(inpixeltype) @@ -96,7 +96,7 @@ def crop_indices(image, lowerind, upperind): if (image.dimension != len(lowerind)) or (image.dimension != len(upperind)): raise ValueError('image dimensionality and index length must match') - libfn = utils.get_lib_fn('cropImageF%i' % image.dimension) + libfn = utils.get_lib_fn('cropImage') itkimage = libfn(image.pointer, image.pointer, 1, 2, lowerind, upperind) ants_image = iio.ANTsImage(pixeltype='float', dimension=image.dimension, components=image.components, pointer=itkimage) @@ -139,7 +139,7 @@ def decrop_image(cropped_image, full_image): if full_image.pixeltype != 'float': full_image = full_image.clone('float') - libfn = utils.get_lib_fn('cropImageF%i' % cropped_image.dimension) + libfn = utils.get_lib_fn('cropImage') itkimage = libfn(cropped_image.pointer, full_image.pointer, 1, 1, [], []) ants_image = iio.ANTsImage(pixeltype='float', dimension=cropped_image.dimension, components=cropped_image.components, pointer=itkimage) diff --git a/pyproject.toml b/pyproject.toml index 46a638ce..4f3eefb1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,8 @@ dependencies = [ "webcolors", "matplotlib", "Pillow", - "nibabel" + "nibabel", + "requests" ] [project.urls] diff --git a/src/LOCAL_antsImageClone.cxx b/src/LOCAL_antsImageClone.cxx index bb2422ef..c5277616 100644 --- a/src/LOCAL_antsImageClone.cxx +++ b/src/LOCAL_antsImageClone.cxx @@ -13,6 +13,7 @@ #include "LOCAL_antsImage.h" namespace nb = nanobind; +using namespace nb::literals; template AntsImage antsImageClone( AntsImage & myPointer ) diff --git a/src/LOCAL_antsTransform.cxx b/src/LOCAL_antsTransform.cxx index b9021610..10f17b16 100644 --- a/src/LOCAL_antsTransform.cxx +++ b/src/LOCAL_antsTransform.cxx @@ -1,7 +1,11 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -60,10 +64,11 @@ #include "LOCAL_antsTransform.h" #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule antsTransformFromDisplacementField( py::capsule field ) +AntsTransform antsTransformFromDisplacementField( AntsImage & field ) { //typedef itk::Transform TransformType; typedef typename TransformType::Pointer TransformPointerType; @@ -77,7 +82,7 @@ py::capsule antsTransformFromDisplacementField( py::capsule field ) //typedef itk::VectorImage AntsrFieldType; //typedef typename AntsrFieldType::Pointer AntsrFieldPointerType; typedef typename VectorImageType::Pointer VectorImagePointerType; - VectorImagePointerType antsrField = as< VectorImageType >( field ); + VectorImagePointerType antsrField = field.ptr; typename DisplacementFieldType::Pointer itkField = DisplacementFieldType::New(); itkField->SetRegions( antsrField->GetLargestPossibleRegion() ); @@ -118,11 +123,13 @@ py::capsule antsTransformFromDisplacementField( py::capsule field ) return antsrTransform; */ - return wrap_transform< TransformType >( displacementTransform.GetPointer() ); + AntsTransform outTransform = { displacementTransform.GetPointer() }; + return outTransform; } template -py::capsule antsTransformToDisplacementField( py::capsule xfrm, py::capsule ref ) +AntsImage antsTransformToDisplacementField( AntsTransform & xfrm, + AntsImage> & ref ) { //typedef itk::Transform TransformType; using ImageType = typename itk::Image; @@ -133,10 +140,10 @@ py::capsule antsTransformToDisplacementField( py::capsule xfrm, py::capsule ref using DisplacementFieldType = typename DisplacementFieldTransformType::DisplacementFieldType; using VectorType = typename DisplacementFieldType::PixelType; - TransformPointerType itkTransform = as_transform( xfrm ); + TransformPointerType itkTransform = xfrm.ptr; DisplacementFieldTransformPointerType warp = dynamic_cast( itkTransform.GetPointer() ) ; - ImagePointerType domainImage = as( ref ); + ImagePointerType domainImage = ref.ptr; typedef typename VectorImageType::Pointer VectorImagePointerType; VectorImagePointerType antsrField = VectorImageType::New(); @@ -160,94 +167,95 @@ py::capsule antsTransformToDisplacementField( py::capsule xfrm, py::capsule ref ++it; } - return wrap< VectorImageType >( antsrField ); + AntsImage outImage = { antsrField }; + return outImage; } -PYBIND11_MODULE(antsTransform, m) { - - m.def("getTransformParametersF2", &getTransformParameters>); - m.def("getTransformParametersF3", &getTransformParameters>); - m.def("getTransformParametersF4", &getTransformParameters>); - m.def("getTransformParametersD2", &getTransformParameters>); - m.def("getTransformParametersD3", &getTransformParameters>); - m.def("getTransformParametersD4", &getTransformParameters>); - - m.def("setTransformParametersF2", &setTransformParameters>); - m.def("setTransformParametersF3", &setTransformParameters>); - m.def("setTransformParametersF4", &setTransformParameters>); - m.def("setTransformParametersD2", &setTransformParameters>); - m.def("setTransformParametersD3", &setTransformParameters>); - m.def("setTransformParametersD4", &setTransformParameters>); - - m.def("getTransformFixedParametersF2", &getTransformFixedParameters>); - m.def("getTransformFixedParametersF3", &getTransformFixedParameters>); - m.def("getTransformFixedParametersF4", &getTransformFixedParameters>); - m.def("getTransformFixedParametersD2", &getTransformFixedParameters>); - m.def("getTransformFixedParametersD3", &getTransformFixedParameters>); - m.def("getTransformFixedParametersD4", &getTransformFixedParameters>); - - m.def("setTransformFixedParametersF2", &setTransformFixedParameters>); - m.def("setTransformFixedParametersF3", &setTransformFixedParameters>); - m.def("setTransformFixedParametersF4", &setTransformFixedParameters>); - m.def("setTransformFixedParametersD2", &setTransformFixedParameters>); - m.def("setTransformFixedParametersD3", &setTransformFixedParameters>); - m.def("setTransformFixedParametersD4", &setTransformFixedParameters>); - - m.def("transformPointF2", &transformPoint>); - m.def("transformPointF3", &transformPoint>); - m.def("transformPointF4", &transformPoint>); - m.def("transformPointD2", &transformPoint>); - m.def("transformPointD3", &transformPoint>); - m.def("transformPointD4", &transformPoint>); - - m.def("transformVectorF2", &transformVector>); - m.def("transformVectorF3", &transformVector>); - m.def("transformVectorF4", &transformVector>); - m.def("transformVectorD2", &transformVector>); - m.def("transformVectorD3", &transformVector>); - m.def("transformVectorD4", &transformVector>); - - m.def("transformImageF2UC2", &transformImage, itk::Image>); - m.def("transformImageF3UC3", &transformImage, itk::Image>); - m.def("transformImageF4UC4", &transformImage, itk::Image>); - m.def("transformImageD2UC4", &transformImage, itk::Image>); - m.def("transformImageD3UC4", &transformImage, itk::Image>); - m.def("transformImageD4UC4", &transformImage, itk::Image>); - - m.def("transformImageF2UI2", &transformImage, itk::Image>); - m.def("transformImageF3UI3", &transformImage, itk::Image>); - m.def("transformImageF4UI4", &transformImage, itk::Image>); - m.def("transformImageD2UI4", &transformImage, itk::Image>); - m.def("transformImageD3UI4", &transformImage, itk::Image>); - m.def("transformImageD4UI4", &transformImage, itk::Image>); - - m.def("transformImageF2F2", &transformImage, itk::Image>); - m.def("transformImageF3F3", &transformImage, itk::Image>); - m.def("transformImageF4F4", &transformImage, itk::Image>); - m.def("transformImageD2F4", &transformImage, itk::Image>); - m.def("transformImageD3F4", &transformImage, itk::Image>); - m.def("transformImageD4F4", &transformImage, itk::Image>); - - m.def("transformImageF2D2", &transformImage, itk::Image>); - m.def("transformImageF3D3", &transformImage, itk::Image>); - m.def("transformImageF4D4", &transformImage, itk::Image>); - m.def("transformImageD2D4", &transformImage, itk::Image>); - m.def("transformImageD3D4", &transformImage, itk::Image>); - m.def("transformImageD4D4", &transformImage, itk::Image>); - - m.def("inverseTransformF2", &inverseTransform, itk::Transform>); - m.def("inverseTransformF3", &inverseTransform, itk::Transform>); - m.def("inverseTransformF4", &inverseTransform, itk::Transform>); - m.def("inverseTransformD2", &inverseTransform, itk::Transform>); - m.def("inverseTransformD3", &inverseTransform, itk::Transform>); - m.def("inverseTransformD4", &inverseTransform, itk::Transform>); - - m.def("composeTransformsF2", &composeTransforms, float, 2>); - m.def("composeTransformsF3", &composeTransforms, float, 3>); - m.def("composeTransformsF4", &composeTransforms, float, 4>); - m.def("composeTransformsD2", &composeTransforms, double,2> ); - m.def("composeTransformsD3", &composeTransforms, double,3> ); - m.def("composeTransformsD4", &composeTransforms, double,4> ); +void local_antsTransform(nb::module_ &m) { + + m.def("getTransformParameters", &getTransformParameters>); + m.def("getTransformParameters", &getTransformParameters>); + m.def("getTransformParameters", &getTransformParameters>); + m.def("getTransformParameters", &getTransformParameters>); + m.def("getTransformParameters", &getTransformParameters>); + m.def("getTransformParameters", &getTransformParameters>); + + m.def("setTransformParameters", &setTransformParameters>); + m.def("setTransformParameters", &setTransformParameters>); + m.def("setTransformParameters", &setTransformParameters>); + m.def("setTransformParameters", &setTransformParameters>); + m.def("setTransformParameters", &setTransformParameters>); + m.def("setTransformParameters", &setTransformParameters>); + + m.def("getTransformFixedParameters", &getTransformFixedParameters>); + m.def("getTransformFixedParameters", &getTransformFixedParameters>); + m.def("getTransformFixedParameters", &getTransformFixedParameters>); + m.def("getTransformFixedParameters", &getTransformFixedParameters>); + m.def("getTransformFixedParameters", &getTransformFixedParameters>); + m.def("getTransformFixedParameters", &getTransformFixedParameters>); + + m.def("setTransformFixedParameters", &setTransformFixedParameters>); + m.def("setTransformFixedParameters", &setTransformFixedParameters>); + m.def("setTransformFixedParameters", &setTransformFixedParameters>); + m.def("setTransformFixedParameters", &setTransformFixedParameters>); + m.def("setTransformFixedParameters", &setTransformFixedParameters>); + m.def("setTransformFixedParameters", &setTransformFixedParameters>); + + m.def("transformPoint", &transformPoint>); + m.def("transformPoint", &transformPoint>); + m.def("transformPoint", &transformPoint>); + m.def("transformPoint", &transformPoint>); + m.def("transformPoint", &transformPoint>); + m.def("transformPoint", &transformPoint>); + + m.def("transformVector", &transformVector>); + m.def("transformVector", &transformVector>); + m.def("transformVector", &transformVector>); + m.def("transformVector", &transformVector>); + m.def("transformVector", &transformVector>); + m.def("transformVector", &transformVector>); + + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + m.def("transformImage", &transformImage, itk::Image>); + + m.def("inverseTransform", &inverseTransform, itk::Transform>); + m.def("inverseTransform", &inverseTransform, itk::Transform>); + m.def("inverseTransform", &inverseTransform, itk::Transform>); + m.def("inverseTransform", &inverseTransform, itk::Transform>); + m.def("inverseTransform", &inverseTransform, itk::Transform>); + m.def("inverseTransform", &inverseTransform, itk::Transform>); + + m.def("composeTransforms", &composeTransforms, float, 2>); + m.def("composeTransforms", &composeTransforms, float, 3>); + m.def("composeTransforms", &composeTransforms, float, 4>); + m.def("composeTransforms", &composeTransforms, double,2> ); + m.def("composeTransforms", &composeTransforms, double,3> ); + m.def("composeTransforms", &composeTransforms, double,4> ); m.def("readTransformF2", &readTransform, float, 2>); m.def("readTransformF3", &readTransform, float, 3>); @@ -256,24 +264,31 @@ PYBIND11_MODULE(antsTransform, m) { m.def("readTransformD3", &readTransform, double,3> ); m.def("readTransformD4", &readTransform, double,4> ); - m.def("writeTransformF2", &writeTransform>); - m.def("writeTransformF3", &writeTransform>); - m.def("writeTransformF4", &writeTransform>); - m.def("writeTransformD2", &writeTransform>); - m.def("writeTransformD3", &writeTransform>); - m.def("writeTransformD4", &writeTransform>); - - m.def("matrixOffsetF2", &matrixOffset, float, 2>); - m.def("matrixOffsetF3", &matrixOffset, float, 3>); - m.def("matrixOffsetF4", &matrixOffset, float, 4>); - m.def("matrixOffsetD2", &matrixOffset, double,2>); - m.def("matrixOffsetD3", &matrixOffset, double,3>); - m.def("matrixOffsetD4", &matrixOffset, double,4>); - - m.def("antsTransformFromDisplacementFieldF2", &antsTransformFromDisplacementField, itk::VectorImage,float,2>); - m.def("antsTransformFromDisplacementFieldF3", &antsTransformFromDisplacementField, itk::VectorImage,float,3>); - m.def("antsTransformToDisplacementFieldF2", &antsTransformToDisplacementField, itk::VectorImage,float,2>); - m.def("antsTransformToDisplacementFieldF3", &antsTransformToDisplacementField, itk::VectorImage,float,3>); + m.def("writeTransform", &writeTransform>); + m.def("writeTransform", &writeTransform>); + m.def("writeTransform", &writeTransform>); + m.def("writeTransform", &writeTransform>); + m.def("writeTransform", &writeTransform>); + m.def("writeTransform", &writeTransform>); + + m.def("matrixOffset", &matrixOffset, float, 2>); + m.def("matrixOffset", &matrixOffset, float, 3>); + m.def("matrixOffset", &matrixOffset, float, 4>); + m.def("matrixOffset", &matrixOffset, double,2>); + m.def("matrixOffset", &matrixOffset, double,3>); + m.def("matrixOffset", &matrixOffset, double,4>); + + m.def("antsTransformFromDisplacementField", &antsTransformFromDisplacementField, itk::VectorImage,float,2>); + m.def("antsTransformFromDisplacementField", &antsTransformFromDisplacementField, itk::VectorImage,float,3>); + m.def("antsTransformToDisplacementField", &antsTransformToDisplacementField, itk::VectorImage,float,2>); + m.def("antsTransformToDisplacementField", &antsTransformToDisplacementField, itk::VectorImage,float,3>); + + nb::class_>>(m, "AntsTransformF22"); + nb::class_>>(m, "AntsTransformF33"); + nb::class_>>(m, "AntsTransformF44"); + nb::class_>>(m, "AntsTransformD22"); + nb::class_>>(m, "AntsTransformD33"); + nb::class_>>(m, "AntsTransformD44"); } diff --git a/src/LOCAL_antsTransform.h b/src/LOCAL_antsTransform.h index b0d08c10..97d243b0 100644 --- a/src/LOCAL_antsTransform.h +++ b/src/LOCAL_antsTransform.h @@ -3,9 +3,14 @@ #ifndef __ANTSPYTRANSFORM_H #define __ANTSPYTRANSFORM_H -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -65,39 +70,23 @@ #include "LOCAL_antsImage.h" #include "register_transforms.h" -namespace py = pybind11; - +namespace nb = nanobind; +using namespace nb::literals; -template -void capsuleDestructor_transform( void * f ) -{ - //std::cout << "calling capsule destructor" << std::endl; - typename TransformType::Pointer * foo = reinterpret_cast( f ); - *foo = nullptr; -} -template -py::capsule wrap_transform( const typename TransformType::Pointer & itkTransform ) -{ - typedef typename TransformType::Pointer TransformPointerType; - TransformPointerType * ptr = new TransformPointerType( itkTransform ); - return py::capsule(ptr, capsuleDestructor_transform); -} +template +struct AntsTransform { + typename TransformType::Pointer ptr; +}; -template -typename TransformType::Pointer as_transform( void * ptr ) -{ - typename TransformType::Pointer * real = static_cast(ptr); // static_cast or reinterpret_cast ?? - return *real; -} // -------------------------------------------------------------- template -std::vector getTransformParameters( py::capsule & myTx) +std::vector getTransformParameters( AntsTransform & myTx) { - typename TransformType::Pointer itkTransform = as_transform( myTx ); + typename TransformType::Pointer itkTransform = myTx.ptr; std::vector parameterslist; for (unsigned int i = 0; i < itkTransform->GetNumberOfParameters(); i++ ) @@ -109,9 +98,9 @@ std::vector getTransformParameters( py::capsule & myTx) template -void setTransformParameters( py::capsule & myTx, std::vector new_parameters ) +void setTransformParameters( AntsTransform & myTx, std::vector new_parameters ) { - typename TransformType::Pointer itkTransform = as_transform( myTx ); + typename TransformType::Pointer itkTransform = myTx.ptr; typename TransformType::ParametersType itkParameters; itkParameters.SetSize( itkTransform->GetNumberOfParameters() ); @@ -127,9 +116,9 @@ void setTransformParameters( py::capsule & myTx, std::vector new_paramete // -------------------------------------------------------------- template -std::vector getTransformFixedParameters( py::capsule & myTx ) +std::vector getTransformFixedParameters( AntsTransform & myTx ) { - typename TransformType::Pointer itkTransform = as_transform( myTx ); + typename TransformType::Pointer itkTransform = myTx.ptr; std::vector parameterslist; for (unsigned int i = 0; i < itkTransform->GetNumberOfFixedParameters(); i++ ) @@ -141,9 +130,9 @@ std::vector getTransformFixedParameters( py::capsule & myTx ) template -void setTransformFixedParameters( py::capsule & myTx, std::vector new_parameters ) +void setTransformFixedParameters( AntsTransform& myTx, std::vector new_parameters ) { - typename TransformType::Pointer itkTransform = as_transform( myTx ); + typename TransformType::Pointer itkTransform = myTx.ptr; typename TransformType::FixedParametersType itkParameters; itkParameters.SetSize( itkTransform->GetNumberOfFixedParameters() ); @@ -159,13 +148,13 @@ void setTransformFixedParameters( py::capsule & myTx, std::vector new_par // -------------------------------------------------------------- template -std::vector< float > transformPoint( py::capsule & myTx, std::vector< double > inPoint ) +std::vector< float > transformPoint( AntsTransform & myTx, std::vector< double > inPoint ) { typedef typename TransformType::Pointer TransformPointerType; typedef typename TransformType::InputPointType InputPointType; typedef typename TransformType::OutputPointType OutputPointType; - TransformPointerType itkTransform = as_transform( myTx ); + TransformPointerType itkTransform = myTx.ptr; InputPointType inItkPoint; for (unsigned int i = 0; i < InputPointType::PointDimension; i++) @@ -185,13 +174,13 @@ std::vector< float > transformPoint( py::capsule & myTx, std::vector< double > i } template -std::vector< float > transformVector( py::capsule myTx, std::vector< float > inVector ) +std::vector< float > transformVector( AntsTransform myTx, std::vector< float > inVector ) { typedef typename TransformType::Pointer TransformPointerType; typedef typename TransformType::InputVectorType InputVectorType; typedef typename TransformType::OutputVectorType OutputVectorType; - TransformPointerType itkTransform = as_transform( myTx ); + TransformPointerType itkTransform = myTx.ptr; InputVectorType inItkVector; for (unsigned int i = 0; i < InputVectorType::Dimension; i++) @@ -211,10 +200,10 @@ std::vector< float > transformVector( py::capsule myTx, std::vector< float > inV } template -py::capsule inverseTransform( py::capsule & myTx ) +AntsTransform inverseTransform( AntsTransform & myTx ) { typedef typename TransformType::Pointer TransformPointerType; - TransformPointerType itkTransform = as_transform< TransformType >( myTx ); + TransformPointerType itkTransform = myTx.ptr; if ( !itkTransform->IsLinear() ) { @@ -222,24 +211,20 @@ py::capsule inverseTransform( py::capsule & myTx ) } TransformPointerType inverse = itkTransform->GetInverseTransform(); - return wrap_transform< ReturnTransformType >( inverse ); -} - -template -py::capsule wrapHelper( typename ImageType::Pointer & image ) -{ - return wrap( image ); + AntsTransform outTransform = { inverse }; + return outTransform; } - template -py::capsule transformImage( py::capsule & myTx, py::capsule & image, py::capsule & ref, std::string interp) +AntsImage transformImage( AntsTransform & myTx, + AntsImage & image, + AntsImage & ref, std::string interp) { typedef typename TransformType::Pointer TransformPointerType; const unsigned int Dimension = TransformType::InputSpaceDimension; - TransformPointerType transform = as_transform( myTx ); + TransformPointerType transform = myTx.ptr; typedef typename TransformType::ParametersValueType PrecisionType; @@ -250,9 +235,8 @@ py::capsule transformImage( py::capsule & myTx, py::capsule & image, py::capsule typedef itk::ImageBase ImageBaseType; typedef typename ImageBaseType::Pointer ImageBasePointerType; - ImagePointerType inputImage = as( image ); - //ImageBasePointerType refImage = as( ref ); - ImagePointerType refImage = as( ref ); + ImagePointerType inputImage = image.ptr; + ImagePointerType refImage = ref.ptr; typedef itk::ResampleImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); @@ -355,12 +339,13 @@ py::capsule transformImage( py::capsule & myTx, py::capsule & image, py::capsule ImagePointerType filterOutput = filter->GetOutput(); - return wrapHelper( filterOutput ); + AntsImage outImage = { filterOutput }; + return outImage; } template -py::capsule composeTransforms( std::vector tformlist, +AntsTransform composeTransforms( std::vector> tformlist, std::string precision, unsigned int dimension) { typedef typename TransformBaseType::Pointer TransformBasePointerType; @@ -370,14 +355,15 @@ py::capsule composeTransforms( std::vector tformlist, for ( unsigned int i = 0; i < tformlist.size(); i++ ) { - TransformBasePointerType t = as_transform( tformlist[i] ); + TransformBasePointerType t = tformlist[i].ptr; comp_transform->AddTransform( t ); } - return wrap_transform< TransformBaseType >( comp_transform.GetPointer() ); + AntsTransform outTransform = { comp_transform.GetPointer() }; + return outTransform; } template -py::capsule readTransform( std::string filename, unsigned int dimension, std::string precision ) +AntsTransform readTransform( std::string filename, unsigned int dimension, std::string precision ) { register_transforms(); @@ -404,23 +390,26 @@ py::capsule readTransform( std::string filename, unsigned int dimension, std::st comp_transform->AddTransform( dynamic_cast( i->GetPointer()) ); } transform = dynamic_cast(comp_transform.GetPointer()); - return wrap_transform< TransformBaseType >( transform ); + AntsTransform outTransform = { transform }; + return outTransform; } else { transform = dynamic_cast( transformList->front().GetPointer() ); - return wrap_transform< TransformBaseType >( transform ); + AntsTransform outTransform = { transform }; + return outTransform; } - return wrap_transform< TransformBaseType >( transform ); + AntsTransform outTransform = { transform }; + return outTransform; } template -void writeTransform( py::capsule & transform, std::string filename ) +void writeTransform( AntsTransform & transform, std::string filename ) { typedef typename TransformType::Pointer TransformPointerType; - TransformPointerType itkTransform = as_transform( transform ); + TransformPointerType itkTransform = transform.ptr; typedef itk::TransformFileWriter TransformWriterType; typename TransformWriterType::Pointer transformWriter = TransformWriterType::New(); transformWriter->SetInput( itkTransform ); @@ -433,7 +422,7 @@ void writeTransform( py::capsule & transform, std::string filename ) // ------------------------------------------------------------------ template< typename TransformBaseType, class PrecisionType, unsigned int Dimension > -py::capsule matrixOffset( std::string type, std::string precision, unsigned int dimension, +AntsTransform matrixOffset( std::string type, std::string precision, unsigned int dimension, std::vector > matrix, std::vector offset, std::vector center, @@ -595,7 +584,9 @@ py::capsule matrixOffset( std::string type, std::string precision, unsigned int TransformBasePointerType itkTransform = dynamic_cast( matrixOffset.GetPointer() ); - return wrap_transform< TransformBaseType >( itkTransform ); + AntsTransform outTransform = { itkTransform }; + + return outTransform; } diff --git a/src/LOCAL_cropImage.cxx b/src/LOCAL_cropImage.cxx index c6120276..6e75e716 100644 --- a/src/LOCAL_cropImage.cxx +++ b/src/LOCAL_cropImage.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -15,7 +20,8 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template< class ImageType > typename ImageType::Pointer cropImageHelper( typename ImageType::Pointer image, @@ -125,8 +131,8 @@ typename ImageType::Pointer decropImageHelper( typename ImageType::Pointer cima } template -py::capsule cropImage( py::capsule &in_image1, - py::capsule &in_image2, +AntsImage cropImage( AntsImage &in_image1, + AntsImage &in_image2, unsigned int label, unsigned int decrop, std::vector loind, @@ -134,38 +140,36 @@ py::capsule cropImage( py::capsule &in_image1, { typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType antsimage1 = as< ImageType >( in_image1 ); - ImagePointerType antsimage2 = as< ImageType >( in_image2 ); + ImagePointerType antsimage1 = in_image1.ptr; + ImagePointerType antsimage2 = in_image2.ptr; if ( decrop == 0 ) { ImagePointerType out_image = cropImageHelper(antsimage1, antsimage2, label); - py::capsule out_ants_image = wrap( out_image ); + AntsImage out_ants_image = { out_image }; return out_ants_image; } else if ( decrop == 1 ) { ImagePointerType out_image = decropImageHelper(antsimage1, antsimage2); - py::capsule out_ants_image = wrap( out_image ); + AntsImage out_ants_image = { out_image }; return out_ants_image; } else if ( decrop == 2 ) { ImagePointerType out_image = cropIndHelper(antsimage1, loind, upind); - py::capsule out_ants_image = wrap( out_image ); + AntsImage out_ants_image = { out_image }; return out_ants_image; } ImagePointerType out_image = ImageType::New(); - py::capsule out_ants_image = wrap( out_image ); + AntsImage out_ants_image = { out_image }; return out_ants_image; } - - -PYBIND11_MODULE(cropImage, m) { - m.def("cropImageF2", &cropImage>); - m.def("cropImageF3", &cropImage>); +void local_cropImage(nb::module_ &m) { + m.def("cropImage", &cropImage>); + m.def("cropImage", &cropImage>); } diff --git a/src/LOCAL_readTransform.cxx b/src/LOCAL_readTransform.cxx index eec1fa38..0030c32a 100644 --- a/src/LOCAL_readTransform.cxx +++ b/src/LOCAL_readTransform.cxx @@ -1,6 +1,10 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "itkMacro.h" #include "itkImage.h" @@ -56,7 +60,8 @@ #include "register_transforms.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; unsigned int getTransformDimensionFromFile( std::string filename ) { @@ -86,7 +91,7 @@ std::string getTransformNameFromFile( std::string filename ) template -py::capsule newAntsTransform( std::string precision, unsigned int dimension, std::string type) +AntsTransform> newAntsTransform( std::string precision, unsigned int dimension, std::string type) { //auto transformPointer = TransformType::New(); @@ -100,7 +105,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "CenteredAffineTransform" ) { @@ -111,7 +117,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "Euler3DTransform" ) { @@ -122,7 +129,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "Euler2DTransform" ) @@ -134,7 +142,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "QuaternionRigidTransform" ) { @@ -145,7 +154,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "Rigid2DTransform" ) { @@ -156,7 +166,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "Rigid3DTransform" ) { @@ -167,7 +178,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "CenteredEuler3DTransform" ) { @@ -178,7 +190,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "CenteredRigid2DTransform" ) { @@ -189,7 +202,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "Similarity3DTransform" ) { @@ -200,7 +214,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "Similarity2DTransform" ) { @@ -211,7 +226,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } else if ( type == "CenteredSimilarity2DTransform" ) { @@ -222,7 +238,8 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } typedef itk::AffineTransform TransformType; @@ -232,11 +249,12 @@ py::capsule newAntsTransform( std::string precision, unsigned int dimension, std typedef typename TransformBaseType::Pointer TransformBasePointerType; TransformBasePointerType basePointer = dynamic_cast( transformPointer.GetPointer() ); - return wrap_transform< TransformBaseType >( basePointer ); + AntsTransform outTransform = { basePointer }; + return outTransform; } -PYBIND11_MODULE(readTransform, m) +void local_readTransform(nb::module_ &m) { m.def("newAntsTransformF2", &newAntsTransform); m.def("newAntsTransformF3", &newAntsTransform); diff --git a/src/LOCAL_readTransform.h b/src/LOCAL_readTransform.h index 30b4e4e8..84e757a1 100644 --- a/src/LOCAL_readTransform.h +++ b/src/LOCAL_readTransform.h @@ -1,9 +1,13 @@ #ifndef ANTSPYREADIMAGE_H #define ANTSPYREADIMAGE_H -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "itkMacro.h" #include "itkImage.h" @@ -55,8 +59,11 @@ #include "LOCAL_antsTransform.h" -template -py::capsule newAntsTransform( std::string precision, unsigned int dimension, std::string type); +namespace nb = nanobind; +using namespace nb::literals; + +template +AntsTransform> newAntsTransform( std::string precision, unsigned int dimension, std::string type); diff --git a/src/main.cpp b/src/main.cpp index 4367844b..5b1d88ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,9 +4,12 @@ #include "LOCAL_antsImage.cxx" #include "LOCAL_antsImageClone.cxx" #include "LOCAL_antsImageHeaderInfo.cxx" +#include "LOCAL_antsTransform.cxx" +#include "LOCAL_cropImage.cxx" #include "LOCAL_mergeChannels.cxx" #include "LOCAL_padImage.cxx" #include "LOCAL_readImage.cxx" +#include "LOCAL_readTransform.cxx" #include "LOCAL_reorientImage2.cxx" #include "LOCAL_sliceImage.cxx" #include "LOCAL_SmoothImage.cxx" @@ -37,9 +40,12 @@ void local_addNoiseToImage(nb::module_ &); void local_antsImage(nb::module_ &); void local_antsImageClone(nb::module_ &); void local_antsImageHeaderInfo(nb::module_ &); +void local_antsTransform(nb::module_ &); +void local_cropImage(nb::module_ &); void local_mergeChannels(nb::module_ &); void local_padImage(nb::module_ &); void local_readImage(nb::module_ &); +void local_readTransform(nb::module_ &); void local_reorientImage2(nb::module_ &); void local_sliceImage(nb::module_ &); void local_SmoothImage(nb::module_ &); @@ -69,9 +75,12 @@ NB_MODULE(lib, m) { local_antsImage(m); local_antsImageClone(m); local_antsImageHeaderInfo(m); + local_antsTransform(m); + local_cropImage(m); local_mergeChannels(m); local_padImage(m); local_readImage(m); + local_readTransform(m); local_reorientImage2(m); local_sliceImage(m); local_SmoothImage(m); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 843d5d57..165d0449 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -40,7 +40,7 @@ echo "Running utils tests" #$PYCMD test_utils.py $@ echo "Running viz tests" -#$PYCMD test_viz.py $@ +$PYCMD test_viz.py $@ echo "Running bug tests" #$PYCMD test_bugs.py $@ From 69114508cbfb66bbb3342abf03d23b4ef4306261 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 16:40:39 +0200 Subject: [PATCH 09/26] update cmake --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75e17056..45f333ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) # TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) # ITK set(ITK_DIR "./itkbuild") From 78e2c3b3bdccf4d366a650449db1bf579141cb36 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Wed, 8 May 2024 22:43:07 +0200 Subject: [PATCH 10/26] wrap transforms --- ants/core/ants_transform.py | 2 +- ants/core/ants_transform_io.py | 6 +-- src/LOCAL_antsImageUtils.cxx | 73 +++++++++++++++------------- src/LOCAL_antsTransform.cxx | 27 +++++----- src/main.cpp | 3 ++ tests/run_tests.sh | 4 +- tests/test_core_ants_transform_io.py | 46 +++++++++++++----- 7 files changed, 99 insertions(+), 62 deletions(-) diff --git a/ants/core/ants_transform.py b/ants/core/ants_transform.py index c208a309..19ac4624 100644 --- a/ants/core/ants_transform.py +++ b/ants/core/ants_transform.py @@ -416,7 +416,7 @@ def compose_ants_transforms(transform_list): raise ValueError('All transforms must have the same dimension') tx_ptr_list = list(reversed([tf.pointer for tf in transform_list])) - libfn = utils.get_lib_fn('composeTransforms') + libfn = utils.get_lib_fn('composeTransforms%s' % (transform_list[0]._libsuffix)) itk_composed_tx = libfn(tx_ptr_list, precision, dimension) return ANTsTransform(precision=precision, dimension=dimension, transform_type='CompositeTransform', pointer=itk_composed_tx) diff --git a/ants/core/ants_transform_io.py b/ants/core/ants_transform_io.py index 99232d20..5c7a8214 100644 --- a/ants/core/ants_transform_io.py +++ b/ants/core/ants_transform_io.py @@ -253,7 +253,7 @@ def transform_from_displacement_field(field): """ if not isinstance(field, iio.ANTsImage): raise ValueError("field must be ANTsImage type") - libfn = utils.get_lib_fn("antsTransformFromDisplacementFieldF%i" % field.dimension) + libfn = utils.get_lib_fn("antsTransformFromDisplacementField") field = field.clone("float") txptr = libfn(field.pointer) return tio.ANTsTransform( @@ -295,7 +295,7 @@ def transform_to_displacement_field(xfrm, ref): if not xfrm.type == 'DisplacementFieldTransform': raise ValueError("Transform must be of DisplacementFieldTransform type") - libfn = utils.get_lib_fn("antsTransformToDisplacementFieldF%i" % xfrm.dimension) + libfn = utils.get_lib_fn("antsTransformToDisplacementField") field_ptr = libfn(xfrm.pointer, ref.pointer) return iio.ANTsImage( pixeltype=xfrm.precision, dimension=xfrm.dimension, @@ -379,5 +379,5 @@ def write_transform(transform, filename): >>> tx2 = ants.read_transform('~/desktop/tx.mat') """ filename = os.path.expanduser(filename) - libfn = utils.get_lib_fn("writeTransform%s" % (transform._libsuffix)) + libfn = utils.get_lib_fn("writeTransform") libfn(transform.pointer, filename) diff --git a/src/LOCAL_antsImageUtils.cxx b/src/LOCAL_antsImageUtils.cxx index c4e01817..90635d4a 100644 --- a/src/LOCAL_antsImageUtils.cxx +++ b/src/LOCAL_antsImageUtils.cxx @@ -1,6 +1,12 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -25,11 +31,12 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template < typename ImageType > -std::vector > TransformIndexToPhysicalPoint( py::capsule antsImage, +std::vector > TransformIndexToPhysicalPoint( AntsImage & antsImage, std::vector > indices ) { typedef typename ImageType::Pointer ImagePointerType ; @@ -40,7 +47,7 @@ std::vector > TransformIndexToPhysicalPoint( py::capsule ants const unsigned int nDim = ImageType::ImageDimension; - ImagePointerType image = as< ImageType >( antsImage ); + ImagePointerType image = antsImage.ptr; unsigned long N = indices.size(); // number of indices to convert //Rcpp::NumericMatrix points( N, nDim ) ; @@ -70,7 +77,7 @@ std::vector > TransformIndexToPhysicalPoint( py::capsule ants template < typename ImageType > -std::vector > TransformPhysicalPointToIndex( py::capsule antsImage, +std::vector > TransformPhysicalPointToIndex( AntsImage & antsImage, std::vector > points ) { typedef typename ImageType::Pointer ImagePointerType ; @@ -80,7 +87,7 @@ std::vector > TransformPhysicalPointToIndex( py::capsule ants typedef typename itk::ContinuousIndex IndexType; const unsigned int nDim = ImageType::ImageDimension; - ImagePointerType image = as< ImageType >( antsImage ); + ImagePointerType image = antsImage.ptr; unsigned long N = points.size(); std::vector > indices( N, std::vector(nDim) ); @@ -108,32 +115,32 @@ std::vector > TransformPhysicalPointToIndex( py::capsule ants } -PYBIND11_MODULE(antsImageUtils, m) +void local_antsImageUtils(nb::module_ &m) { - m.def("TransformIndexToPhysicalPointUC2", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointUC3", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointUC4", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointUI2", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointUI3", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointUI4", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointF2", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointF3", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointF4", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointD2", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointD3", &TransformIndexToPhysicalPoint>); - m.def("TransformIndexToPhysicalPointD4", &TransformIndexToPhysicalPoint>); - - m.def("TransformPhysicalPointToIndexUC2", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexUC3", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexUC4", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexUI2", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexUI3", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexUI4", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexF2", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexF3", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexF4", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexD2", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexD3", &TransformPhysicalPointToIndex>); - m.def("TransformPhysicalPointToIndexD4", &TransformPhysicalPointToIndex>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + m.def("TransformIndexToPhysicalPoint", &TransformIndexToPhysicalPoint>); + + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); + m.def("TransformPhysicalPointToIndex", &TransformPhysicalPointToIndex>); } diff --git a/src/LOCAL_antsTransform.cxx b/src/LOCAL_antsTransform.cxx index 10f17b16..49f70edd 100644 --- a/src/LOCAL_antsTransform.cxx +++ b/src/LOCAL_antsTransform.cxx @@ -250,12 +250,12 @@ void local_antsTransform(nb::module_ &m) { m.def("inverseTransform", &inverseTransform, itk::Transform>); m.def("inverseTransform", &inverseTransform, itk::Transform>); - m.def("composeTransforms", &composeTransforms, float, 2>); - m.def("composeTransforms", &composeTransforms, float, 3>); - m.def("composeTransforms", &composeTransforms, float, 4>); - m.def("composeTransforms", &composeTransforms, double,2> ); - m.def("composeTransforms", &composeTransforms, double,3> ); - m.def("composeTransforms", &composeTransforms, double,4> ); + m.def("composeTransformsF2", &composeTransforms, float, 2>); + m.def("composeTransformsF3", &composeTransforms, float, 3>); + m.def("composeTransformsF4", &composeTransforms, float, 4>); + m.def("composeTransformsD2", &composeTransforms, double,2> ); + m.def("composeTransformsD3", &composeTransforms, double,3> ); + m.def("composeTransformsD4", &composeTransforms, double,4> ); m.def("readTransformF2", &readTransform, float, 2>); m.def("readTransformF3", &readTransform, float, 3>); @@ -271,18 +271,21 @@ void local_antsTransform(nb::module_ &m) { m.def("writeTransform", &writeTransform>); m.def("writeTransform", &writeTransform>); - m.def("matrixOffset", &matrixOffset, float, 2>); - m.def("matrixOffset", &matrixOffset, float, 3>); - m.def("matrixOffset", &matrixOffset, float, 4>); - m.def("matrixOffset", &matrixOffset, double,2>); - m.def("matrixOffset", &matrixOffset, double,3>); - m.def("matrixOffset", &matrixOffset, double,4>); + m.def("matrixOffsetF2", &matrixOffset, float, 2>); + m.def("matrixOffsetF3", &matrixOffset, float, 3>); + m.def("matrixOffsetF4", &matrixOffset, float, 4>); + m.def("matrixOffsetD2", &matrixOffset, double,2>); + m.def("matrixOffsetD3", &matrixOffset, double,3>); + m.def("matrixOffsetD4", &matrixOffset, double,4>); m.def("antsTransformFromDisplacementField", &antsTransformFromDisplacementField, itk::VectorImage,float,2>); m.def("antsTransformFromDisplacementField", &antsTransformFromDisplacementField, itk::VectorImage,float,3>); m.def("antsTransformToDisplacementField", &antsTransformToDisplacementField, itk::VectorImage,float,2>); m.def("antsTransformToDisplacementField", &antsTransformToDisplacementField, itk::VectorImage,float,3>); + + nb::class_>>(m, "AntsTransformDF2"); + nb::class_>>(m, "AntsTransformDF3"); nb::class_>>(m, "AntsTransformF22"); nb::class_>>(m, "AntsTransformF33"); nb::class_>>(m, "AntsTransformF44"); diff --git a/src/main.cpp b/src/main.cpp index 5b1d88ea..98bc38b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,7 @@ #include "LOCAL_antsImage.cxx" #include "LOCAL_antsImageClone.cxx" #include "LOCAL_antsImageHeaderInfo.cxx" +#include "LOCAL_antsImageUtils.cxx" #include "LOCAL_antsTransform.cxx" #include "LOCAL_cropImage.cxx" #include "LOCAL_mergeChannels.cxx" @@ -40,6 +41,7 @@ void local_addNoiseToImage(nb::module_ &); void local_antsImage(nb::module_ &); void local_antsImageClone(nb::module_ &); void local_antsImageHeaderInfo(nb::module_ &); +void local_antsImageUtils(nb::module_ &); void local_antsTransform(nb::module_ &); void local_cropImage(nb::module_ &); void local_mergeChannels(nb::module_ &); @@ -75,6 +77,7 @@ NB_MODULE(lib, m) { local_antsImage(m); local_antsImageClone(m); local_antsImageHeaderInfo(m); + local_antsImageUtils(m); local_antsTransform(m); local_cropImage(m); local_mergeChannels(m); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 165d0449..297ac20d 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -23,8 +23,8 @@ pushd "$(dirname "$0")" echo "Running core tests" $PYCMD test_core_ants_image.py $@ $PYCMD test_core_ants_image_io.py $@ -#$PYCMD test_core_ants_transform.py $@ -#$PYCMD test_core_ants_transform_io.py $@ +$PYCMD test_core_ants_transform.py $@ +$PYCMD test_core_ants_transform_io.py $@ #$PYCMD test_core_ants_metric.py $@ echo "Running learn tests" diff --git a/tests/test_core_ants_transform_io.py b/tests/test_core_ants_transform_io.py index b33c6f21..025685ec 100644 --- a/tests/test_core_ants_transform_io.py +++ b/tests/test_core_ants_transform_io.py @@ -31,12 +31,18 @@ def setUp(self): self.txs = [tx2d, tx3d] self.pixeltypes = ['unsigned char', 'unsigned int', 'float'] - self.matrix_offset_types = {'AffineTransform', 'CenteredAffineTransform', - 'Euler2DTransform', 'Euler3DTransform', - 'Rigid2DTransform', 'QuaternionRigidTransform', - 'Similarity2DTransform', 'CenteredSimilarity2DTransform', - 'Similarity3DTransform', 'CenteredRigid2DTransform', - 'CenteredEuler3DTransform', 'Rigid3DTransform'} + self.matrix_offset_types = ['AffineTransform', + 'CenteredAffineTransform', + 'Euler2DTransform', + 'Euler3DTransform', + 'Rigid2DTransform', + 'QuaternionRigidTransform', + 'Similarity2DTransform', + 'CenteredSimilarity2DTransform', + 'Similarity3DTransform', + 'CenteredRigid2DTransform', + 'CenteredEuler3DTransform', + 'Rigid3DTransform'] def tearDown(self): pass @@ -50,9 +56,9 @@ def test_new_ants_transform(self): def test_create_ants_transform(self): for mtype in self.matrix_offset_types: - for ptype in {'float','double'}: - for ndim in {2,3}: - tx = ants.create_ants_transform(transform_type=mtype, precision=ptype, dimension=ndim) + for ptype in {'float', 'double'}: + for ndim in {2, 3}: + ants.create_ants_transform(transform_type=mtype, precision=ptype, dimension=ndim) # supported types tx = ants.create_ants_transform(supported_types=True) @@ -61,7 +67,7 @@ def test_create_ants_transform(self): translation = (3,4,5) tx = ants.create_ants_transform( transform_type='Euler3DTransform', translation=translation ) - translation = np.array([3,4,5]) + #translation = np.array([3,4,5]) tx = ants.create_ants_transform( transform_type='Euler3DTransform', translation=translation ) # invalid dimension @@ -89,7 +95,25 @@ def test_read_write_transform(self): # file doesnt exist with self.assertRaises(Exception): ants.read_transform('blah-blah.mat') - + + def test_from_displacement(self): + fi = ants.image_read(ants.get_ants_data('r16') ) + mi = ants.image_read(ants.get_ants_data('r64') ) + fi = ants.resample_image(fi,(60,60),1,0) + mi = ants.resample_image(mi,(60,60),1,0) # speed up + mytx = ants.registration(fixed=fi, moving=mi, type_of_transform = ('SyN') ) + vec = ants.image_read( mytx['fwdtransforms'][0] ) + atx = ants.transform_from_displacement_field( vec ) + + def test_to_displacement(self): + fi = ants.image_read(ants.get_ants_data('r16') ) + mi = ants.image_read(ants.get_ants_data('r64') ) + fi = ants.resample_image(fi,(60,60),1,0) + mi = ants.resample_image(mi,(60,60),1,0) # speed up + mytx = ants.registration(fixed=fi, moving=mi, type_of_transform = ('SyN') ) + vec = ants.image_read( mytx['fwdtransforms'][0] ) + atx = ants.transform_from_displacement_field( vec ) + field = ants.transform_to_displacement_field( atx, fi ) if __name__ == '__main__': From 2eff700aa7e00c71d5f9d5abc2fd43d01bff3730 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Thu, 9 May 2024 16:45:25 +0200 Subject: [PATCH 11/26] registration and segmentation tests pass --- CMakeLists.txt | 4 +- ants/registration/reflect_image.py | 2 +- ants/registration/reorient_image.py | 2 +- ants/utils/fit_bspline_displacement_field.py | 8 +- .../fit_bspline_object_to_scattered_data.py | 19 ++--- src/LOCAL_antsImageMutualInformation.cxx | 23 +++--- src/LOCAL_antsTransform.cxx | 3 + src/LOCAL_composeDisplacementFields.cxx | 25 ++++--- ...splineDisplacementFieldToScatteredData.cxx | 64 +++++++++------- src/LOCAL_fitBsplineObjectToScatteredData.cxx | 75 ++++++++++--------- src/LOCAL_fsl2antstransform.cxx | 27 ++++--- src/LOCAL_getNeighborhoodMatrix.cxx | 49 ++++++++---- src/LOCAL_integrateVelocityField.cxx | 21 ++++-- src/LOCAL_invertDisplacementField.cxx | 25 ++++--- src/LOCAL_labelOverlapMeasures.cxx | 40 +++++----- src/LOCAL_reflectionMatrix.cxx | 44 ++++++----- src/LOCAL_reorientImage.cxx | 25 ++++--- src/main.cpp | 33 ++++++++ tests/run_tests.sh | 4 +- 19 files changed, 302 insertions(+), 191 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f333ad..75e17056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) # TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) # ITK set(ITK_DIR "./itkbuild") diff --git a/ants/registration/reflect_image.py b/ants/registration/reflect_image.py index c7a98b22..030c8a22 100644 --- a/ants/registration/reflect_image.py +++ b/ants/registration/reflect_image.py @@ -49,7 +49,7 @@ def reflect_image(image, axis=None, tx=None, metric='mattes'): rflct = mktemp(suffix='.mat') - libfn = utils.get_lib_fn('reflectionMatrix%s'%image._libsuffix) + libfn = utils.get_lib_fn('reflectionMatrix') libfn(image.pointer, axis, rflct) if tx is not None: diff --git a/ants/registration/reorient_image.py b/ants/registration/reorient_image.py index fc87b09c..40e2fb72 100644 --- a/ants/registration/reorient_image.py +++ b/ants/registration/reorient_image.py @@ -104,7 +104,7 @@ def get_center_of_mass(image): if image.pixeltype != 'float': image = image.clone('float') - libfn = utils.get_lib_fn('centerOfMass%s' % image._libsuffix) + libfn = utils.get_lib_fn('centerOfMass') com = libfn(image.pointer) return tuple(com) diff --git a/ants/utils/fit_bspline_displacement_field.py b/ants/utils/fit_bspline_displacement_field.py index 3ff69fbc..7b69e5e6 100644 --- a/ants/utils/fit_bspline_displacement_field.py +++ b/ants/utils/fit_bspline_displacement_field.py @@ -97,13 +97,13 @@ def fit_bspline_displacement_field(displacement_field=None, Example ------- >>> import ants - >>> import numpy - >>> points = numpy.array([[-50, -50]]) - >>> deltas = numpy.array([[10, 10]]) + >>> import numpy as np + >>> points = np.array([[-50, -50]]) + >>> deltas = np.array([[10, 10]]) >>> bspline_field = ants.fit_bspline_displacement_field( >>> displacement_origins=points, displacements=deltas, >>> origin=[0.0, 0.0], spacing=[1.0, 1.0], size=[100, 100], - >>> direction=numpy.array([[-1, 0], [0, -1]]), + >>> direction=np.array([[-1, 0], [0, -1]]), >>> number_of_fitting_levels=4, mesh_size=(1, 1)) """ diff --git a/ants/utils/fit_bspline_object_to_scattered_data.py b/ants/utils/fit_bspline_object_to_scattered_data.py index 15eb8ee8..0c88b547 100644 --- a/ants/utils/fit_bspline_object_to_scattered_data.py +++ b/ants/utils/fit_bspline_object_to_scattered_data.py @@ -93,19 +93,17 @@ def fit_bspline_object_to_scattered_data(scattered_data, >>> >>> import ants, numpy >>> import matplotlib.pyplot as plt - >>> >>> x = numpy.linspace(-4, 4, num=100) >>> y = numpy.exp(-numpy.multiply(x, x)) + numpy.random.uniform(-0.1, 0.1, len(x)) >>> u = numpy.linspace(0, 1.0, num=len(x)) >>> scattered_data = numpy.column_stack((x, y)) >>> parametric_data = numpy.expand_dims(u, axis=-1) >>> spacing = 1/(len(x)-1) * 1.0; - >>> - >>> bspline_curve = ants.fit_bspline_object_to_scattered_data(scattered_data, parametric_data, + >>> bspline_curve = ants.fit_bspline_object_to_scattered_data(scattered_data, + >>> parametric_data, >>> parametric_domain_origin=[0.0], parametric_domain_spacing=[spacing], >>> parametric_domain_size=[len(x)], is_parametric_dimension_closed=None, >>> number_of_fitting_levels=5, mesh_size=1) - >>> >>> plt.plot(x, y, label='Noisy points') >>> plt.plot(bspline_curve[:,0], bspline_curve[:,1], label='B-spline curve') >>> plt.grid(True) @@ -118,22 +116,17 @@ def fit_bspline_object_to_scattered_data(scattered_data, >>> # Perform 2-D scalar field (i.e., image) example >>> >>> import ants, numpy - >>> >>> number_of_random_points = 10000 - >>> >>> img = ants.image_read( ants.get_ants_data("r16")) >>> img_array = img.numpy() >>> row_indices = numpy.random.choice(range(2, img_array.shape[0]), number_of_random_points) >>> col_indices = numpy.random.choice(range(2, img_array.shape[1]), number_of_random_points) - >>> >>> scattered_data = numpy.zeros((number_of_random_points, 1)) >>> parametric_data = numpy.zeros((number_of_random_points, 2)) - >>> >>> for i in range(number_of_random_points): >>> scattered_data[i,0] = img_array[row_indices[i], col_indices[i]] >>> parametric_data[i,0] = row_indices[i] >>> parametric_data[i,1] = col_indices[i] - >>> >>> bspline_img = ants.fit_bspline_object_to_scattered_data( >>> scattered_data, parametric_data, >>> parametric_domain_origin=[0.0, 0.0], @@ -181,14 +174,14 @@ def fit_bspline_object_to_scattered_data(scattered_data, raise ValueError("The number of weights is not the same as the number of points.") libfn = utils.get_lib_fn("fitBsplineObjectToScatteredDataP%iD%i" % (parametric_dimension, data_dimension)) - bspline_object = libfn(scattered_data, parametric_data, data_weights, + bspline_object = libfn(scattered_data.tolist(), parametric_data.tolist(), data_weights.tolist(), parametric_domain_origin, parametric_domain_spacing, - parametric_domain_size, is_parametric_dimension_closed, - number_of_fitting_levels, number_of_control_points, + parametric_domain_size, is_parametric_dimension_closed.tolist(), + number_of_fitting_levels, number_of_control_points.tolist(), spline_order) if parametric_dimension == 1: - return bspline_object + return np.array(bspline_object) else: bspline_image = iio.ANTsImage(pixeltype='float', dimension=parametric_dimension, components=data_dimension, diff --git a/src/LOCAL_antsImageMutualInformation.cxx b/src/LOCAL_antsImageMutualInformation.cxx index 08b1146a..c6e847b2 100644 --- a/src/LOCAL_antsImageMutualInformation.cxx +++ b/src/LOCAL_antsImageMutualInformation.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -13,18 +18,19 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -double antsImageMutualInformation( py::capsule in_image1, - py::capsule in_image2 ) +double antsImageMutualInformation( AntsImage> & in_image1, + AntsImage> & in_image2 ) { double mi = 1; typedef itk::Image< float , Dimension > ImageType; typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage1 = as( in_image1 ); - ImagePointerType itkImage2 = as( in_image2 ); + ImagePointerType itkImage1 = in_image1.ptr; + ImagePointerType itkImage2 = in_image2.ptr; typedef itk::MattesMutualInformationImageToImageMetricv4 MetricType; @@ -39,8 +45,7 @@ double antsImageMutualInformation( py::capsule in_image1, } - -PYBIND11_MODULE(antsImageMutualInformation, m) +void local_antsImageMutualInformation(nb::module_ &m) { m.def("antsImageMutualInformation2D", &antsImageMutualInformation<2>); m.def("antsImageMutualInformation3D", &antsImageMutualInformation<3>); diff --git a/src/LOCAL_antsTransform.cxx b/src/LOCAL_antsTransform.cxx index 49f70edd..f250e7e1 100644 --- a/src/LOCAL_antsTransform.cxx +++ b/src/LOCAL_antsTransform.cxx @@ -201,6 +201,9 @@ void local_antsTransform(nb::module_ &m) { m.def("setTransformFixedParameters", &setTransformFixedParameters>); m.def("setTransformFixedParameters", &setTransformFixedParameters>); + + m.def("transformPoint", &transformPoint>); + m.def("transformPoint", &transformPoint>); m.def("transformPoint", &transformPoint>); m.def("transformPoint", &transformPoint>); m.def("transformPoint", &transformPoint>); diff --git a/src/LOCAL_composeDisplacementFields.cxx b/src/LOCAL_composeDisplacementFields.cxx index fda4a3ec..76711a0d 100644 --- a/src/LOCAL_composeDisplacementFields.cxx +++ b/src/LOCAL_composeDisplacementFields.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -14,11 +19,12 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule composeDisplacementFields( py::capsule & antsDisplacementField, - py::capsule & antsWarpingField ) +AntsImage> composeDisplacementFields( AntsImage> & antsDisplacementField, + AntsImage> & antsWarpingField ) { using RealType = float; @@ -33,8 +39,8 @@ py::capsule composeDisplacementFields( py::capsule & antsDisplacementField, using IteratorType = itk::ImageRegionIteratorWithIndex; using ConstIteratorType = itk::ImageRegionConstIteratorWithIndex; - ANTsFieldPointerType inputDisplacementField = as( antsDisplacementField ); - ANTsFieldPointerType inputWarpingField = as( antsWarpingField ); + ANTsFieldPointerType inputDisplacementField = antsDisplacementField.ptr;// as( antsDisplacementField ); + ANTsFieldPointerType inputWarpingField = antsWarpingField.ptr; //as( antsWarpingField ); typename ITKFieldType::PointType fieldOrigin; typename ITKFieldType::SpacingType fieldSpacing; @@ -116,10 +122,11 @@ py::capsule composeDisplacementFields( py::capsule & antsDisplacementField, antsField->SetPixel( ItI.GetIndex(), antsVector ); } - return wrap< ANTsFieldType >( antsField ); + AntsImage out_ants_image = { antsField }; + return out_ants_image; } -PYBIND11_MODULE(composeDisplacementFields, m) +void local_composeDisplacementFields(nb::module_ &m) { m.def("composeDisplacementFieldsD2", &composeDisplacementFields<2>); m.def("composeDisplacementFieldsD3", &composeDisplacementFields<3>); diff --git a/src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx b/src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx index 29dd1b23..95bb020a 100644 --- a/src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx +++ b/src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx @@ -1,7 +1,11 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -13,17 +17,18 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule fitBsplineVectorImageToScatteredDataHelper( - py::array_t displacementOrigins, - py::array_t displacements, +AntsImage> fitBsplineVectorImageToScatteredDataHelper( + std::vector> displacementOrigins, + std::vector> displacements, std::vector displacementWeights, - py::array_t origin, - py::array_t spacing, - py::array_t size, - py::array_t direction, + std::vector origin, + std::vector spacing, + std::vector size, + std::vector> direction, unsigned int numberOfFittingLevels, std::vector numberOfControlPoints, unsigned int splineOrder, @@ -55,12 +60,12 @@ py::capsule fitBsplineVectorImageToScatteredDataHelper( // Define the output B-spline field domain // - auto originP = origin.unchecked<1>(); - auto spacingP = spacing.unchecked<1>(); - auto sizeP = size.unchecked<1>(); - auto directionP = direction.unchecked<2>(); + auto originP = origin;//.unchecked<1>(); + auto spacingP = spacing;//.unchecked<1>(); + auto sizeP = size;//.unchecked<1>(); + auto directionP = direction;//.unchecked<2>(); - if( originP.shape(0) == 0 || sizeP.shape(0) == 0 || spacingP.shape(0) == 0 || directionP.shape(0) == 0 ) + if( originP.size() == 0 || sizeP.size() == 0 || spacingP.size() == 0 || directionP.size() == 0 ) { throw std::invalid_argument( "one or more b-spline domain definitions are not specified." ); } @@ -73,12 +78,12 @@ py::capsule fitBsplineVectorImageToScatteredDataHelper( for( unsigned int d = 0; d < Dimension; d++ ) { - fieldOrigin[d] = originP(d); - fieldSpacing[d] = spacingP(d); - fieldSize[d] = sizeP(d); + fieldOrigin[d] = originP[d]; + fieldSpacing[d] = spacingP[d]; + fieldSize[d] = sizeP[d]; for( unsigned int e = 0; e < Dimension; e++ ) { - fieldDirection(d, e) = directionP(d, e); + fieldDirection(d, e) = directionP[d][e]; } } bsplineFilter->SetBSplineDomain( fieldOrigin, fieldSpacing, fieldSize, fieldDirection ); @@ -89,14 +94,14 @@ py::capsule fitBsplineVectorImageToScatteredDataHelper( // Add the inputs (if they are specified) // - auto displacementOriginsP = displacementOrigins.unchecked<2>(); - auto displacementsP = displacements.unchecked<2>(); + auto displacementOriginsP = displacementOrigins;//.unchecked<2>(); + auto displacementsP = displacements;//.unchecked<2>(); typename PointSetType::Pointer pointSet = PointSetType::New(); pointSet->Initialize(); typename WeightsContainerType::Pointer weights = WeightsContainerType::New(); - unsigned int numberOfPoints = displacementsP.shape(0); + unsigned int numberOfPoints = displacementsP.size(); if( rasterizePoints ) { @@ -129,8 +134,8 @@ py::capsule fitBsplineVectorImageToScatteredDataHelper( VectorType imageDisplacement; for( unsigned int d = 0; d < Dimension; d++ ) { - imagePoint[d] = displacementOriginsP(n, d); - imageDisplacement[d] = displacementsP(n, d); + imagePoint[d] = displacementOriginsP[n][d];//displacementOriginsP(n, d); + imageDisplacement[d] = displacementsP[n][d]; } typename ITKFieldType::IndexType imageIndex = weightImage->TransformPhysicalPointToIndex( imagePoint ); @@ -170,14 +175,14 @@ py::capsule fitBsplineVectorImageToScatteredDataHelper( typename PointSetType::PointType point; for( unsigned int d = 0; d < Dimension; d++ ) { - point[d] = displacementOriginsP(n, d); + point[d] = displacementOriginsP[n][d]; } pointSet->SetPoint( n, point ); VectorType data( 0.0 ); for( unsigned int d = 0; d < Dimension; d++ ) { - data[d] = displacementsP(n, d); + data[d] = displacementsP[n][d]; } pointSet->SetPointData( n, data ); weights->InsertElement( n, displacementWeights[n] ); @@ -226,10 +231,11 @@ py::capsule fitBsplineVectorImageToScatteredDataHelper( antsField->SetPixel( It.GetIndex(), antsVector ); } - return wrap< ANTsFieldType >( antsField ); + AntsImage out_ants_image = { antsField }; + return out_ants_image; } -PYBIND11_MODULE(fitBsplineDisplacementFieldToScatteredData, m) +void local_fitBsplineDisplacementFieldToScatteredData(nb::module_ &m) { m.def("fitBsplineDisplacementFieldToScatteredDataD2", &fitBsplineVectorImageToScatteredDataHelper<2>); m.def("fitBsplineDisplacementFieldToScatteredDataD3", &fitBsplineVectorImageToScatteredDataHelper<3>); diff --git a/src/LOCAL_fitBsplineObjectToScatteredData.cxx b/src/LOCAL_fitBsplineObjectToScatteredData.cxx index 09da4dd5..87805cea 100644 --- a/src/LOCAL_fitBsplineObjectToScatteredData.cxx +++ b/src/LOCAL_fitBsplineObjectToScatteredData.cxx @@ -1,7 +1,11 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -14,12 +18,13 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::array_t fitBsplineCurveHelper( - py::array_t scatteredData, - py::array_t parametricData, +std::vector> fitBsplineCurveHelper( + std::vector> scatteredData, + std::vector> parametricData, std::vector dataWeights, std::vector parametricDomainOrigin, std::vector parametricDomainSpacing, @@ -44,24 +49,24 @@ py::array_t fitBsplineCurveHelper( pointSet->Initialize(); typename WeightsContainerType::Pointer weights = WeightsContainerType::New(); - auto scatteredDataR = scatteredData.unchecked<2>(); - auto parametricDataR = parametricData.unchecked<2>(); + auto scatteredDataR = scatteredData;//.unchecked<2>(); + auto parametricDataR = parametricData;//.unchecked<2>(); - unsigned int numberOfPoints = scatteredDataR.shape(0); + unsigned int numberOfPoints = scatteredDataR.size(); for( unsigned int n = 0; n < numberOfPoints; n++ ) { typename PointSetType::PointType point; for( unsigned int d = 0; d < ParametricDimension; d++ ) { - point[d] = parametricDataR(n, d); + point[d] = parametricDataR[n][d]; } pointSet->SetPoint( n, point ); ScatteredDataType data( 0.0 ); for( unsigned int d = 0; d < DataDimension; d++ ) { - data[d] = scatteredDataR(n, d); + data[d] = scatteredDataR[n][d]; } pointSet->SetPointData( n, data ); @@ -102,8 +107,8 @@ py::array_t fitBsplineCurveHelper( // is the return type. // - py::array_t bsplineCurve({ parametricDomainSize[0], DataDimension }); - auto bsplineCurveR = bsplineCurve.mutable_unchecked<2>(); + std::vector> bsplineCurve(parametricDomainSize[0], std::vector(DataDimension) ); + auto bsplineCurveR = bsplineCurve;//.mutable_unchecked<2>(); unsigned int count = 0; IteratorType It( bsplineFilter->GetOutput(), @@ -113,7 +118,7 @@ py::array_t fitBsplineCurveHelper( ScatteredDataType data = It.Value(); for( unsigned int d = 0; d < DataDimension; d++ ) { - bsplineCurveR(count, d) = data[d]; + bsplineCurveR[count][d] = data[d]; } count++; } @@ -122,9 +127,9 @@ py::array_t fitBsplineCurveHelper( } template -py::capsule fitBsplineImageHelper( - py::array_t scatteredData, - py::array_t parametricData, +AntsImage> fitBsplineImageHelper( + std::vector> scatteredData, + std::vector> parametricData, std::vector dataWeights, std::vector parametricDomainOrigin, std::vector parametricDomainSpacing, @@ -149,24 +154,24 @@ py::capsule fitBsplineImageHelper( pointSet->Initialize(); typename WeightsContainerType::Pointer weights = WeightsContainerType::New(); - auto scatteredDataR = scatteredData.unchecked<2>(); - auto parametricDataR = parametricData.unchecked<2>(); + auto scatteredDataR = scatteredData;//.unchecked<2>(); + auto parametricDataR = parametricData;//.unchecked<2>(); - unsigned int numberOfPoints = scatteredDataR.shape(0); + unsigned int numberOfPoints = scatteredDataR.size(); for( unsigned int n = 0; n < numberOfPoints; n++ ) { typename PointSetType::PointType point; for( unsigned int d = 0; d < ParametricDimension; d++ ) { - point[d] = parametricDataR(n, d); + point[d] = parametricDataR[n][d]; } pointSet->SetPoint( n, point ); ScatteredDataType data( 0.0 ); for( unsigned int d = 0; d < DataDimension; d++ ) { - data[d] = scatteredDataR(n, d); + data[d] = scatteredDataR[n][d]; } pointSet->SetPointData( n, data ); @@ -214,13 +219,14 @@ py::capsule fitBsplineImageHelper( selectionFilter->SetInput( bsplineFilter->GetOutput() ); selectionFilter->Update(); - return wrap< ScalarImageType >( selectionFilter->GetOutput() ); + AntsImage out_ants_image = { selectionFilter->GetOutput() }; + return out_ants_image; } template -py::capsule fitBsplineVectorImageHelper( - py::array_t scatteredData, - py::array_t parametricData, +AntsImage> fitBsplineVectorImageHelper( + std::vector> scatteredData, + std::vector> parametricData, std::vector dataWeights, std::vector parametricDomainOrigin, std::vector parametricDomainSpacing, @@ -243,24 +249,24 @@ py::capsule fitBsplineVectorImageHelper( pointSet->Initialize(); typename WeightsContainerType::Pointer weights = WeightsContainerType::New(); - auto scatteredDataR = scatteredData.unchecked<2>(); - auto parametricDataR = parametricData.unchecked<2>(); + auto scatteredDataR = scatteredData;//.unchecked<2>(); + auto parametricDataR = parametricData;//.unchecked<2>(); - unsigned int numberOfPoints = scatteredDataR.shape(0); + unsigned int numberOfPoints = scatteredDataR.size(); for( unsigned int n = 0; n < numberOfPoints; n++ ) { typename PointSetType::PointType point; for( unsigned int d = 0; d < ParametricDimension; d++ ) { - point[d] = parametricDataR(n, d); + point[d] = parametricDataR[n][d]; } pointSet->SetPoint( n, point ); ScatteredDataType data( 0.0 ); for( unsigned int d = 0; d < DataDimension; d++ ) { - data[d] = scatteredDataR(n, d); + data[d] = scatteredDataR[n][d]; } pointSet->SetPointData( n, data ); @@ -329,10 +335,11 @@ py::capsule fitBsplineVectorImageHelper( antsField->SetPixel( It.GetIndex(), antsVector ); } - return wrap< VectorImageType >( antsField ); + AntsImage out_ants_image = { antsField }; + return out_ants_image; } -PYBIND11_MODULE(fitBsplineObjectToScatteredData, m) +void local_fitBsplineObjectToScatteredData(nb::module_ &m) { m.def("fitBsplineObjectToScatteredDataP1D1", &fitBsplineCurveHelper<1>); m.def("fitBsplineObjectToScatteredDataP1D2", &fitBsplineCurveHelper<2>); diff --git a/src/LOCAL_fsl2antstransform.cxx b/src/LOCAL_fsl2antstransform.cxx index 6050d6c1..d56ab7a8 100644 --- a/src/LOCAL_fsl2antstransform.cxx +++ b/src/LOCAL_fsl2antstransform.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -23,7 +28,8 @@ #define RAS_TO_FSL 0 #define FSL_TO_RAS 1 -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; /** * Get a matrix that maps points voxel coordinates to RAS coordinates @@ -61,9 +67,9 @@ TransformMatrixType GetVoxelSpaceToRASPhysicalSpaceMatrix(typename ImageType::Po template< class PixelType, unsigned int Dimension > -py::capsule fsl2antstransform( std::vector > matrix, - py::capsule ants_reference, - py::capsule ants_moving, +AntsTransform> fsl2antstransform( std::vector > matrix, + AntsImage> & ants_reference, + AntsImage> & ants_moving, int flag ) { typedef vnl_matrix_fixed MatrixType; @@ -77,8 +83,8 @@ py::capsule fsl2antstransform( std::vector > matrix, typedef itk::Transform TransformBaseType; typedef typename TransformBaseType::Pointer TransformBasePointerType; - ImagePointerType ref = as< ImageType >( ants_reference ); - ImagePointerType mov = as< ImageType >( ants_moving ); + ImagePointerType ref = ants_reference.ptr; + ImagePointerType mov = ants_moving.ptr; MatrixType m_fsl, m_spcref, m_spcmov, m_swpref, m_swpmov, mat, m_ref, m_mov; @@ -155,11 +161,12 @@ py::capsule fsl2antstransform( std::vector > matrix, TransformBasePointerType itkTransform = dynamic_cast( atran.GetPointer() ); - return wrap_transform< TransformBaseType >( itkTransform ); + AntsTransform out_ants_tx = { itkTransform }; + return out_ants_tx; } -PYBIND11_MODULE(fsl2antstransform, m) +void local_fsl2antstransform(nb::module_ &m) { m.def("fsl2antstransformF3", &fsl2antstransform); } diff --git a/src/LOCAL_getNeighborhoodMatrix.cxx b/src/LOCAL_getNeighborhoodMatrix.cxx index de3d6c36..21b8cd20 100644 --- a/src/LOCAL_getNeighborhoodMatrix.cxx +++ b/src/LOCAL_getNeighborhoodMatrix.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -26,12 +31,12 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; -using namespace py::literals; +namespace nb = nanobind; +using namespace nb::literals; template< class PixelType , unsigned int Dimension > -py::dict getNeighborhoodMatrix( py::capsule ants_image, - py::capsule ants_mask, +nb::dict getNeighborhoodMatrix( AntsImage> & ants_image, + AntsImage> & ants_mask, std::vector radius, int physical, int boundary, @@ -47,8 +52,8 @@ py::dict getNeighborhoodMatrix( py::capsule ants_image, typedef itk::CentralDifferenceImageFunction< ImageType, RealType > GradientCalculatorType; typedef itk::CovariantVector CovariantVectorType; - ImagePointerType image = as< ImageType >( ants_image ); - ImagePointerType mask = as< ImageType >( ants_mask ); + ImagePointerType image = ants_image.ptr; + ImagePointerType mask = ants_mask.ptr; //Rcpp::NumericVector radius( r_radius ) ; //int physical = Rcpp::as( r_physical ); @@ -141,7 +146,10 @@ py::dict getNeighborhoodMatrix( py::capsule ants_image, ++it; ++nit; } - return py::dict("matrix"_a=matrix ); + + nb::dict mymat; + mymat["matrix"] = matrix; + return mymat; } if ( ( ! spatial ) && ( getgradient ) ) @@ -218,7 +226,10 @@ py::dict getNeighborhoodMatrix( py::capsule ants_image, } //return Rcpp::List::create( Rcpp::Named("values") = matrix, // Rcpp::Named("gradients") = gradients ); - return py::dict("values"_a=matrix, "gradients"_a=gradients); + nb::dict res; + res["values"] = matrix; + res["gradients"] = gradients; + return res; } // if spatial and gradient, then just use spatial - no gradient ... @@ -321,12 +332,16 @@ py::dict getNeighborhoodMatrix( py::capsule ants_image, //return Rcpp::List::create( Rcpp::Named("values") = matrix, // Rcpp::Named("indices") = indices, // Rcpp::Named("offsets") = offsets ); - return py::dict("values"_a=matrix, "indices"_a=indices, "offsets"_a=offsets); + nb::dict res; + res["values"] = matrix; + res["indices"] = indices; + res["offsets"] = offsets; + return res; } template< class PixelType , unsigned int Dimension > -py::dict getNeighborhood( py::capsule ants_image, +nb::dict getNeighborhood( AntsImage> & ants_image, std::vector index, std::vector kernel, std::vector radius, @@ -338,7 +353,7 @@ py::dict getNeighborhood( py::capsule ants_image, typedef typename ImageType::RegionType RegionType; typedef typename ImageType::IndexType IndexType; - ImagePointerType image = as< ImageType >( ants_image ); + ImagePointerType image = ants_image.ptr; //Rcpp::NumericVector kernel( r_kernel ); //Rcpp::NumericVector radius( r_radius ); @@ -419,12 +434,16 @@ py::dict getNeighborhood( py::capsule ants_image, //return Rcpp::List::create( Rcpp::Named("values") = pixels, // Rcpp::Named("indices") = indices ); - return py::dict("values"_a=pixels, "indices"_a=indices); + + nb::dict res; + res["values"] = pixels; + res["indices"] = indices; + return res; } -PYBIND11_MODULE(getNeighborhoodMatrix, m) +void local_getNeighborhoodMatrix(nb::module_ &m) { m.def("getNeighborhoodMatrixUC2", &getNeighborhoodMatrix); m.def("getNeighborhoodMatrixUC3", &getNeighborhoodMatrix); diff --git a/src/LOCAL_integrateVelocityField.cxx b/src/LOCAL_integrateVelocityField.cxx index 53475b1e..a1660750 100644 --- a/src/LOCAL_integrateVelocityField.cxx +++ b/src/LOCAL_integrateVelocityField.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -15,10 +20,11 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule integrateVelocityField( py::capsule & antsVelocityField, +AntsImage> integrateVelocityField( AntsImage> & antsVelocityField, float lowerBound, float upperBound, unsigned int numberOfIntegrationSteps ) @@ -40,7 +46,7 @@ py::capsule integrateVelocityField( py::capsule & antsVelocityField, using IteratorType = itk::ImageRegionIteratorWithIndex; using ConstIteratorType = itk::ImageRegionConstIteratorWithIndex; - ANTsVelocityFieldPointerType inputVelocityField = as( antsVelocityField ); + ANTsVelocityFieldPointerType inputVelocityField = antsVelocityField.ptr; ITKVelocityFieldPointerType inputITKVelocityField = ITKVelocityFieldType::New(); inputITKVelocityField->CopyInformation( inputVelocityField ); @@ -95,10 +101,11 @@ py::capsule integrateVelocityField( py::capsule & antsVelocityField, antsField->SetPixel( ItI.GetIndex(), antsVector ); } - return wrap< ANTsFieldType >( antsField ); + AntsImage out_ants_image = { antsField }; + return out_ants_image; } -PYBIND11_MODULE(integrateVelocityField, m) +void local_integrateVelocityField(nb::module_ &m) { m.def("integrateVelocityFieldD2", &integrateVelocityField<2>); m.def("integrateVelocityFieldD3", &integrateVelocityField<3>); diff --git a/src/LOCAL_invertDisplacementField.cxx b/src/LOCAL_invertDisplacementField.cxx index 1cdfecc7..185f64ef 100644 --- a/src/LOCAL_invertDisplacementField.cxx +++ b/src/LOCAL_invertDisplacementField.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -14,11 +19,12 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule invertDisplacementField( py::capsule & antsDisplacementField, - py::capsule & antsInverseFieldInitialEstimate, +AntsImage> invertDisplacementField( AntsImage> & antsDisplacementField, + AntsImage> & antsInverseFieldInitialEstimate, unsigned int maximumNumberOfIterations, float meanErrorToleranceThreshold, float maxErrorToleranceThreshold, @@ -37,8 +43,8 @@ py::capsule invertDisplacementField( py::capsule & antsDisplacementField, using IteratorType = itk::ImageRegionIteratorWithIndex; using ConstIteratorType = itk::ImageRegionConstIteratorWithIndex; - ANTsFieldPointerType inputDisplacementField = as( antsDisplacementField ); - ANTsFieldPointerType inputInverseFieldInitialEstimate = as( antsInverseFieldInitialEstimate ); + ANTsFieldPointerType inputDisplacementField = antsDisplacementField.ptr; + ANTsFieldPointerType inputInverseFieldInitialEstimate = antsInverseFieldInitialEstimate.ptr; typename ITKFieldType::PointType fieldOrigin; typename ITKFieldType::SpacingType fieldSpacing; @@ -124,10 +130,11 @@ py::capsule invertDisplacementField( py::capsule & antsDisplacementField, antsField->SetPixel( ItI.GetIndex(), antsVector ); } - return wrap< ANTsFieldType >( antsField ); + AntsImage out_ants_image = { antsField }; + return out_ants_image; } -PYBIND11_MODULE(invertDisplacementField, m) +void local_invertDisplacementField(nb::module_ &m) { m.def("invertDisplacementFieldD2", &invertDisplacementField<2>); m.def("invertDisplacementFieldD3", &invertDisplacementField<3>); diff --git a/src/LOCAL_labelOverlapMeasures.cxx b/src/LOCAL_labelOverlapMeasures.cxx index 520815b9..2570c085 100644 --- a/src/LOCAL_labelOverlapMeasures.cxx +++ b/src/LOCAL_labelOverlapMeasures.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -11,18 +16,18 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; -using namespace py::literals; +namespace nb = nanobind; +using namespace nb::literals; template -py::dict labelOverlapMeasures( py::capsule & antsSourceImage, - py::capsule & antsTargetImage ) +nb::dict labelOverlapMeasures( AntsImage> & antsSourceImage, + AntsImage> & antsTargetImage ) { using ImageType = itk::Image; using ImagePointerType = typename ImageType::Pointer; - ImagePointerType itkSourceImage = as< ImageType >( antsSourceImage ); - ImagePointerType itkTargetImage = as< ImageType >( antsTargetImage ); + typename ImageType::Pointer itkSourceImage = antsSourceImage.ptr; + typename ImageType::Pointer itkTargetImage = antsTargetImage.ptr; using FilterType = itk::LabelOverlapMeasuresImageFilter; typename FilterType::Pointer filter = FilterType::New(); @@ -85,18 +90,19 @@ py::dict labelOverlapMeasures( py::capsule & antsSourceImage, i++; } - py::dict labelOverlapMeasures = py::dict( "Label"_a=labels, - "TotalOrTargetOverlap"_a=totalOrTargetOverlap, - "UnionOverlap"_a=unionOverlap, - "MeanOverlap"_a=meanOverlap, - "VolumeSimilarity"_a=volumeSimilarity, - "FalseNegativeError"_a=falseNegativeError, - "FalsePositiveError"_a=falsePositiveError ); + nb::dict labelOverlapMeasures; + labelOverlapMeasures["Label"] = labels; + labelOverlapMeasures["TotalOrTargetOverlap"] = totalOrTargetOverlap; + labelOverlapMeasures["UnionOverlap"] = unionOverlap; + labelOverlapMeasures["MeanOverlap"] = meanOverlap; + labelOverlapMeasures["VolumeSimilarity"] = volumeSimilarity; + labelOverlapMeasures["FalseNegativeError"] = falseNegativeError; + labelOverlapMeasures["FalsePositiveError"] = falsePositiveError; - return (labelOverlapMeasures); + return labelOverlapMeasures; } -PYBIND11_MODULE(labelOverlapMeasures, m) +void local_labelOverlapMeasures(nb::module_ &m) { m.def("labelOverlapMeasures2D", &labelOverlapMeasures); m.def("labelOverlapMeasures3D", &labelOverlapMeasures); diff --git a/src/LOCAL_reflectionMatrix.cxx b/src/LOCAL_reflectionMatrix.cxx index 170110b7..1c1e3e3a 100644 --- a/src/LOCAL_reflectionMatrix.cxx +++ b/src/LOCAL_reflectionMatrix.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -15,15 +20,16 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template< class ImageType > -int reflectionMatrixHelper( py::capsule py_image, unsigned int axis, std::string filename ) +int reflectionMatrixHelper( AntsImage & py_image, unsigned int axis, std::string filename ) { typedef typename ImageType::Pointer ImagePointerType; typedef itk::AffineTransform AffineTransformType; - ImagePointerType image = as( py_image ); + ImagePointerType image = py_image.ptr; typedef typename itk::ImageMomentsCalculator ImageCalculatorType; typename ImageCalculatorType::Pointer calculator = ImageCalculatorType::New(); @@ -63,26 +69,26 @@ int reflectionMatrixHelper( py::capsule py_image, unsigned int axis, std::string template -int reflectionMatrixEntry( py::capsule image, unsigned int axis, std::string filename) +int reflectionMatrixEntry( AntsImage & image, unsigned int axis, std::string filename) { return reflectionMatrixHelper( image, axis, filename ); } -PYBIND11_MODULE(reflectionMatrix, m) +void local_reflectionMatrix(nb::module_ &m) { - m.def("reflectionMatrixUC2", &reflectionMatrixEntry>); - m.def("reflectionMatrixUC3", &reflectionMatrixEntry>); - m.def("reflectionMatrixUC4", &reflectionMatrixEntry>); - m.def("reflectionMatrixUI2", &reflectionMatrixEntry>); - m.def("reflectionMatrixUI3", &reflectionMatrixEntry>); - m.def("reflectionMatrixUI4", &reflectionMatrixEntry>); - m.def("reflectionMatrixF2", &reflectionMatrixEntry>); - m.def("reflectionMatrixF3", &reflectionMatrixEntry>); - m.def("reflectionMatrixF4", &reflectionMatrixEntry>); - m.def("reflectionMatrixD2", &reflectionMatrixEntry>); - m.def("reflectionMatrixD3", &reflectionMatrixEntry>); - m.def("reflectionMatrixD4", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); + m.def("reflectionMatrix", &reflectionMatrixEntry>); } diff --git a/src/LOCAL_reorientImage.cxx b/src/LOCAL_reorientImage.cxx index 01a59891..f07cf925 100644 --- a/src/LOCAL_reorientImage.cxx +++ b/src/LOCAL_reorientImage.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -16,7 +21,8 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; /* template< unsigned int ImageDimension > @@ -155,10 +161,10 @@ int reorientImage( py::capsule in_image, std::string txfn, template -std::vector centerOfMass( py::capsule & image ) +std::vector centerOfMass( AntsImage & image ) { typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkimage = as( image ); + ImagePointerType itkimage = image.ptr; typedef typename itk::ImageMomentsCalculator ImageCalculatorType; typename ImageCalculatorType::VectorType com( Dimension ); @@ -179,14 +185,13 @@ std::vector centerOfMass( py::capsule & image ) return myCoM; } - -PYBIND11_MODULE(reorientImage, m) +void local_reorientImage(nb::module_ &m) { // m.def("reorientImageF2", &reorientImage, 2>); // m.def("reorientImageF3", &reorientImage, 3>); // m.def("reorientImageF4", &reorientImage, 4>); - m.def("centerOfMassF2", ¢erOfMass, 2>); - m.def("centerOfMassF3", ¢erOfMass, 3>); - m.def("centerOfMassF4", ¢erOfMass, 4>); + m.def("centerOfMass", ¢erOfMass, 2>); + m.def("centerOfMass", ¢erOfMass, 3>); + m.def("centerOfMass", ¢erOfMass, 4>); } diff --git a/src/main.cpp b/src/main.cpp index 98bc38b7..9bc5a1f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,13 +4,24 @@ #include "LOCAL_antsImage.cxx" #include "LOCAL_antsImageClone.cxx" #include "LOCAL_antsImageHeaderInfo.cxx" +#include "LOCAL_antsImageMutualInformation.cxx" #include "LOCAL_antsImageUtils.cxx" #include "LOCAL_antsTransform.cxx" +#include "LOCAL_composeDisplacementFields.cxx" #include "LOCAL_cropImage.cxx" +#include "LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx" +#include "LOCAL_fitBsplineObjectToScatteredData.cxx" +#include "LOCAL_fsl2antstransform.cxx" +#include "LOCAL_getNeighborhoodMatrix.cxx" +#include "LOCAL_integrateVelocityField.cxx" +#include "LOCAL_invertDisplacementField.cxx" +#include "LOCAL_labelOverlapMeasures.cxx" #include "LOCAL_mergeChannels.cxx" #include "LOCAL_padImage.cxx" #include "LOCAL_readImage.cxx" #include "LOCAL_readTransform.cxx" +#include "LOCAL_reflectionMatrix.cxx" +#include "LOCAL_reorientImage.cxx" #include "LOCAL_reorientImage2.cxx" #include "LOCAL_sliceImage.cxx" #include "LOCAL_SmoothImage.cxx" @@ -41,13 +52,24 @@ void local_addNoiseToImage(nb::module_ &); void local_antsImage(nb::module_ &); void local_antsImageClone(nb::module_ &); void local_antsImageHeaderInfo(nb::module_ &); +void local_antsImageMutualInformation(nb::module_ &); void local_antsImageUtils(nb::module_ &); void local_antsTransform(nb::module_ &); void local_cropImage(nb::module_ &); +void local_composeDisplacementFields(nb::module_ &); +void local_fitBsplineDisplacementFieldToScatteredData(nb::module_ &); +void local_fitBsplineObjectToScatteredData(nb::module_ &); +void local_fsl2antstransform(nb::module_ &); +void local_getNeighborhoodMatrix(nb::module_ &); +void local_integrateVelocityField(nb::module_ &); +void local_invertDisplacementField(nb::module_ &); +void local_labelOverlapMeasures(nb::module_ &); void local_mergeChannels(nb::module_ &); void local_padImage(nb::module_ &); void local_readImage(nb::module_ &); void local_readTransform(nb::module_ &); +void local_reflectionMatrix(nb::module_ &); +void local_reorientImage(nb::module_ &); void local_reorientImage2(nb::module_ &); void local_sliceImage(nb::module_ &); void local_SmoothImage(nb::module_ &); @@ -77,13 +99,24 @@ NB_MODULE(lib, m) { local_antsImage(m); local_antsImageClone(m); local_antsImageHeaderInfo(m); + local_antsImageMutualInformation(m); local_antsImageUtils(m); local_antsTransform(m); + local_composeDisplacementFields(m); local_cropImage(m); + local_fitBsplineDisplacementFieldToScatteredData(m); + local_fitBsplineObjectToScatteredData(m); + local_fsl2antstransform(m); + local_getNeighborhoodMatrix(m); + local_integrateVelocityField(m); + local_invertDisplacementField(m); + local_labelOverlapMeasures(m); local_mergeChannels(m); local_padImage(m); local_readImage(m); local_readTransform(m); + local_reflectionMatrix(m); + local_reorientImage(m); local_reorientImage2(m); local_sliceImage(m); local_SmoothImage(m); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 297ac20d..97813847 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -31,10 +31,10 @@ echo "Running learn tests" #$PYCMD test_learn.py $@ echo "Running registration tests" -#$PYCMD test_registration.py $@ +$PYCMD test_registration.py $@ echo "Running segmentation tests" -#$PYCMD test_segmentation.py $@ +$PYCMD test_segmentation.py $@ echo "Running utils tests" #$PYCMD test_utils.py $@ From dcd2fc65574a2c340a6500999f51ef8006c25f10 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Thu, 9 May 2024 16:51:48 +0200 Subject: [PATCH 12/26] update gha --- .github/workflows/ci-pytest.yml | 122 +++++++++++--------------------- 1 file changed, 40 insertions(+), 82 deletions(-) diff --git a/.github/workflows/ci-pytest.yml b/.github/workflows/ci-pytest.yml index 7400d9f8..8f203da7 100644 --- a/.github/workflows/ci-pytest.yml +++ b/.github/workflows/ci-pytest.yml @@ -11,7 +11,7 @@ on: env: # Updates or changes to this, or the runner OS or arch will invalidate the cache - python_version: '3.10' # Python version to use for testing - update when needed + python_version: "3.10" # Python version to use for testing - update when needed jobs: test: @@ -19,85 +19,43 @@ jobs: # Default shell needs to be bash for conda # https://github.com/conda-incubator/setup-miniconda?tab=readme-ov-file#important defaults: - run: - shell: bash -el {0} + run: + shell: bash -el {0} steps: - - name: Setup Miniconda - uses: conda-incubator/setup-miniconda@030178870c779d9e5e1b4e563269f3aa69b04081 # v3.0.3, devs recommend using hash - with: - miniconda-version: "latest" - python-version: ${{ env.python_version }} - auto-update-conda: true - activate-environment: "test-env" - - - name: Configure Conda to use only .tar.bz2 - run: | - conda config --set use_only_tar_bz2 true - - - name: Checkout code - uses: actions/checkout@v4 # Checkout PR code to 'antspy-pr' - with: - path: antspy-pr - - - name: Load conda environment from cache if available - id: cache-env - uses: actions/cache@v4 - with: - path: ~/conda-env.tar.bz2 - key: >- - ${{ runner.os }}-conda-${{ env.python_version }}-${{ hashFiles('antspy-pr/ants/environment.yml', - 'antspy-pr/ants/requirements.txt', 'antspy-pr/ants/setup.py', 'antspy-pr/scripts/configure_ITK.sh', - 'antspy-pr/scripts/configure_ANTsPy.sh', 'antspy-pr/ants/lib/*') }} - - - name: Unpack cached environment - if: steps.cache-env.outputs.cache-hit == 'true' - run: | - mkdir -p ${CONDA}/envs/antspy-env - tar -xjf ~/conda-env.tar.bz2 -C ${CONDA}/envs/antspy-env - conda activate antspy-env - conda-unpack - - - name: Install dependencies and ANTsPy from PR - if: steps.cache-env.outputs.cache-hit != 'true' - run: | - conda create -n antspy-env python=${{ env.python_version }} -y - conda activate antspy-env - conda install -c conda-forge conda-pack coverage - conda info - pip install ./antspy-pr - conda list - antspy-pr/tests/run_tests.sh -c - conda pack -n antspy-env -o ~/conda-env.tar.bz2 - - - name: Cache Conda environment - if: steps.cache-env.outputs.cache-hit != 'true' - uses: actions/cache@v4 - with: - path: ~/conda-env.tar.bz2 - key: >- - ${{ runner.os }}-conda-${{ env.python_version }}-${{ hashFiles('antspy-pr/ants/environment.yml', - 'antspy-pr/ants/requirements.txt', 'antspy-pr/ants/setup.py', 'antspy-pr/scripts/configure_ITK.sh', - 'antspy-pr/scripts/configure_ANTsPy.sh', 'antspy-pr/ants/lib/*') }}) }} - - - name: Replace installed ANTsPy with PR code - if: steps.cache-env.outputs.cache-hit == 'true' - run: | - conda activate antspy-env - ANTS_SITE_PACKAGES="${CONDA}/envs/antspy-env/lib/python${{ env.python_version }}/site-packages/ants" - for d in contrib core learn registration segmentation utils viz; do - rm -rf $ANTS_SITE_PACKAGES/$d; - cp -r antspy-pr/ants/$d $ANTS_SITE_PACKAGES/$d; - done - find $ANTS_SITE_PACKAGES -name '__pycache__' -exec rm -rf {} + - - - name: Run tests - if: steps.cache-env.outputs.cache-hit == 'true' - run: | - conda activate antspy-env - bash antspy-pr/tests/run_tests.sh -c - - - name: Coveralls - uses: coverallsapp/github-action@v2 - with: - files: antspy-pr/tests/coverage.xml - + - name: Setup Miniconda + uses: conda-incubator/setup-miniconda@030178870c779d9e5e1b4e563269f3aa69b04081 # v3.0.3, devs recommend using hash + with: + miniconda-version: "latest" + python-version: ${{ env.python_version }} + auto-update-conda: true + activate-environment: "test-env" + + - name: Configure Conda to use only .tar.bz2 + run: | + conda config --set use_only_tar_bz2 true + + - name: Checkout code + uses: actions/checkout@v4 # Checkout PR code to 'antspy-pr' + with: + path: antspy-pr + + - name: Install dependencies and ANTsPy from PR + run: | + conda create -n antspy-env python=${{ env.python_version }} -y + conda activate antspy-env + conda install -c conda-forge conda-pack coverage + conda info + pip install ./antspy-pr + conda list + antspy-pr/tests/run_tests.sh -c + conda pack -n antspy-env -o ~/conda-env.tar.bz2 + + - name: Run tests + run: | + conda activate antspy-env + bash antspy-pr/tests/run_tests.sh -c + + - name: Coveralls + uses: coverallsapp/github-action@v2 + with: + files: antspy-pr/tests/coverage.xml From 913d618cd7c8899ac19c49813e9be64615617a53 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Thu, 9 May 2024 16:53:28 +0200 Subject: [PATCH 13/26] update cmake --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 75e17056..45f333ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) # TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -#execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) +execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) # ITK set(ITK_DIR "./itkbuild") From e71582cb1d7ce1aed9fa943893bd16ad56182a33 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Fri, 10 May 2024 17:35:32 +0200 Subject: [PATCH 14/26] wrap more utils functions --- .vscode/settings.json | 3 +- ants/utils/add_noise_to_image.py | 8 +-- src/LOCAL_addNoiseToImage.cxx | 27 +++++---- ...SplineDisplacementFieldToScatteredData.cxx | 60 ++++++++++--------- src/LOCAL_histogramMatchImages.cxx | 25 +++++--- src/LOCAL_labelStats.cxx | 53 +++++++++------- src/LOCAL_weingartenImageCurvature.cxx | 24 +++++--- src/main.cpp | 12 ++++ 8 files changed, 129 insertions(+), 83 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4d64aeb5..0383074a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -84,6 +84,7 @@ "valarray": "cpp", "variant": "cpp", "*.in": "cpp", - "*.inc": "cpp" + "*.inc": "cpp", + "*.tmpl": "cpp" } } diff --git a/ants/utils/add_noise_to_image.py b/ants/utils/add_noise_to_image.py index 7bc57f30..5a2dd7a7 100644 --- a/ants/utils/add_noise_to_image.py +++ b/ants/utils/add_noise_to_image.py @@ -45,7 +45,7 @@ def add_noise_to_image(image, if len(noise_parameters) != 2: raise ValueError("Incorrect number of parameters.") - libfn = utils.get_lib_fn("additiveGaussianNoiseF%i" % image_dimension) + libfn = utils.get_lib_fn("additiveGaussianNoise") noise = libfn(image.pointer, noise_parameters[0], noise_parameters[1]) output_image = iio.ANTsImage(pixeltype='float', dimension=image_dimension, components=1, @@ -55,7 +55,7 @@ def add_noise_to_image(image, if len(noise_parameters) != 3: raise ValueError("Incorrect number of parameters.") - libfn = utils.get_lib_fn("saltAndPepperNoiseF%i" % image_dimension) + libfn = utils.get_lib_fn("saltAndPepperNoise") noise = libfn(image.pointer, noise_parameters[0], noise_parameters[1], noise_parameters[2]) output_image = iio.ANTsImage(pixeltype='float', dimension=image_dimension, components=1, @@ -65,7 +65,7 @@ def add_noise_to_image(image, if not isinstance(noise_parameters, (int, float)): raise ValueError("Incorrect parameter specification.") - libfn = utils.get_lib_fn("shotNoiseF%i" % image_dimension) + libfn = utils.get_lib_fn("shotNoise") noise = libfn(image.pointer, noise_parameters) output_image = iio.ANTsImage(pixeltype='float', dimension=image_dimension, components=1, @@ -75,7 +75,7 @@ def add_noise_to_image(image, if not isinstance(noise_parameters, (int, float)): raise ValueError("Incorrect parameter specification.") - libfn = utils.get_lib_fn("speckleNoiseF%i" % image_dimension) + libfn = utils.get_lib_fn("speckleNoise") noise = libfn(image.pointer, noise_parameters) output_image = iio.ANTsImage(pixeltype='float', dimension=image_dimension, components=1, diff --git a/src/LOCAL_addNoiseToImage.cxx b/src/LOCAL_addNoiseToImage.cxx index c04ab59f..69a7675c 100644 --- a/src/LOCAL_addNoiseToImage.cxx +++ b/src/LOCAL_addNoiseToImage.cxx @@ -24,26 +24,28 @@ namespace nb = nanobind; using namespace nb::literals; template -void * additiveGaussianNoise( typename ImageType::Pointer itkImage, +AntsImage additiveGaussianNoise( AntsImage & antsImage, float mean, float standardDeviation ) { + typename ImageType::Pointer itkImage = antsImage.ptr; using NoiseFilterType = itk::AdditiveGaussianNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); noiser->SetInput( itkImage ); noiser->SetMean( mean ); noiser->SetStandardDeviation( standardDeviation ); noiser->Update(); - - return wrap( noiser->GetOutput() ); + AntsImage outImage = { noiser->GetOutput() }; + return outImage; } template -void * saltAndPepperNoise( typename ImageType::Pointer itkImage, +AntsImage saltAndPepperNoise( AntsImage & antsImage, float probability, float saltValue, float pepperValue ) { + typename ImageType::Pointer itkImage = antsImage.ptr; using NoiseFilterType = itk::SaltAndPepperNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); noiser->SetInput( itkImage ); @@ -51,37 +53,40 @@ void * saltAndPepperNoise( typename ImageType::Pointer itkImage, noiser->SetSaltValue( saltValue ); noiser->SetPepperValue( pepperValue ); noiser->Update(); - - return wrap( noiser->GetOutput() ); + AntsImage outImage = { noiser->GetOutput() }; + return outImage; } template -void * shotNoise( typename ImageType::Pointer itkImage, +AntsImage shotNoise( AntsImage & antsImage, float scale ) { + typename ImageType::Pointer itkImage = antsImage.ptr; using NoiseFilterType = itk::ShotNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); noiser->SetInput( itkImage ); noiser->SetScale( scale ); noiser->Update(); - return wrap( noiser->GetOutput() ); + AntsImage outImage = { noiser->GetOutput() }; + return outImage; } template -void * speckleNoise( typename ImageType::Pointer itkImage, +AntsImage speckleNoise( AntsImage & antsImage, float scale ) { - + typename ImageType::Pointer itkImage = antsImage.ptr; using NoiseFilterType = itk::SpeckleNoiseImageFilter; typename NoiseFilterType::Pointer noiser = NoiseFilterType::New(); noiser->SetInput( itkImage ); noiser->SetStandardDeviation( scale ); noiser->Update(); - return wrap( noiser->GetOutput() ); + AntsImage outImage = { noiser->GetOutput() }; + return outImage; } void local_addNoiseToImage(nb::module_ &m) diff --git a/src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx b/src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx index 94ff15f0..d31e511d 100644 --- a/src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx +++ b/src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx @@ -1,7 +1,11 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -14,16 +18,17 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule fitThinPlateSplineVectorImageToScatteredDataHelper( - py::array_t displacementOrigins, - py::array_t displacements, - py::array_t origin, - py::array_t spacing, - py::array_t size, - py::array_t direction +AntsImage> fitThinPlateSplineVectorImageToScatteredDataHelper( + std::vector> displacementOrigins, + std::vector> displacements, + std::vector origin, + std::vector spacing, + std::vector size, + std::vector> direction ) { using RealType = float; @@ -50,12 +55,12 @@ py::capsule fitThinPlateSplineVectorImageToScatteredDataHelper( auto field = ITKFieldType::New(); - auto originP = origin.unchecked<1>(); - auto spacingP = spacing.unchecked<1>(); - auto sizeP = size.unchecked<1>(); - auto directionP = direction.unchecked<2>(); + auto originP = origin;//.unchecked<1>(); + auto spacingP = spacing;//.unchecked<1>(); + auto sizeP = size;//.unchecked<1>(); + auto directionP = direction;//.unchecked<2>(); - if( originP.shape(0) == 0 || sizeP.shape(0) == 0 || spacingP.shape(0) == 0 || directionP.shape(0) == 0 ) + if( originP.size() == 0 || sizeP.size() == 0 || spacingP.size() == 0 || directionP.size() == 0 ) { throw std::invalid_argument( "Thin-plate spline domain is not specified." ); } @@ -68,12 +73,12 @@ py::capsule fitThinPlateSplineVectorImageToScatteredDataHelper( for( unsigned int d = 0; d < Dimension; d++ ) { - fieldOrigin[d] = originP(d); - fieldSpacing[d] = spacingP(d); - fieldSize[d] = sizeP(d); + fieldOrigin[d] = originP[d]; + fieldSpacing[d] = spacingP[d]; + fieldSize[d] = sizeP[d]; for( unsigned int e = 0; e < Dimension; e++ ) { - fieldDirection(d, e) = directionP(d, e); + fieldDirection[d][e] = directionP[d][e]; } } field->SetRegions( fieldSize ); @@ -91,16 +96,16 @@ py::capsule fitThinPlateSplineVectorImageToScatteredDataHelper( PointType sourcePoint; PointType targetPoint; - auto displacementOriginsP = displacementOrigins.unchecked<2>(); - auto displacementsP = displacements.unchecked<2>(); - unsigned int numberOfPoints = displacementsP.shape(0); + auto displacementOriginsP = displacementOrigins;//.unchecked<2>(); + auto displacementsP = displacements;//.unchecked<2>(); + unsigned int numberOfPoints = displacementsP.size();//.shape(0); for( unsigned int n = 0; n < numberOfPoints; n++ ) { for( unsigned int d = 0; d < Dimension; d++ ) { - sourcePoint[d] = displacementOriginsP(n, d); - targetPoint[d] = displacementOriginsP(n, d) + displacementsP(n, d); + sourcePoint[d] = displacementOriginsP[n][d]; + targetPoint[d] = displacementOriginsP[n][d] + displacementsP[n][d]; } sourceLandmarkContainer->InsertElement( n, sourcePoint ); targetLandmarkContainer->InsertElement( n, targetPoint ); @@ -138,10 +143,11 @@ py::capsule fitThinPlateSplineVectorImageToScatteredDataHelper( antsField->SetPixel( It.GetIndex(), antsVector ); } - return wrap< ANTsFieldType >( antsField ); + AntsImage out_ants_image = { antsField }; + return out_ants_image; } -PYBIND11_MODULE(fitThinPlateSplineDisplacementFieldToScatteredData, m) +void local_fitThinPlateSplineDisplacementFieldToScatteredData(nb::module_ &m) { m.def("fitThinPlateSplineDisplacementFieldToScatteredDataD2", &fitThinPlateSplineVectorImageToScatteredDataHelper<2>); m.def("fitThinPlateSplineDisplacementFieldToScatteredDataD3", &fitThinPlateSplineVectorImageToScatteredDataHelper<3>); diff --git a/src/LOCAL_histogramMatchImages.cxx b/src/LOCAL_histogramMatchImages.cxx index 1ae95d01..9fea7252 100644 --- a/src/LOCAL_histogramMatchImages.cxx +++ b/src/LOCAL_histogramMatchImages.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -11,18 +16,19 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template < typename ImageType > -py::capsule histogramMatchImage( py::capsule & antsSourceImage, - py::capsule & antsReferenceImage, +AntsImage histogramMatchImage( AntsImage & antsSourceImage, + AntsImage & antsReferenceImage, unsigned int numberOfHistogramBins, unsigned int numberOfMatchPoints, bool useThresholdAtMeanIntensity ) { typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkSourceImage = as< ImageType >( antsSourceImage ); - ImagePointerType itkReferenceImage = as< ImageType >( antsReferenceImage ); + ImagePointerType itkSourceImage = antsSourceImage.ptr; + ImagePointerType itkReferenceImage = antsReferenceImage.ptr; typedef itk::HistogramMatchingImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); @@ -37,10 +43,11 @@ py::capsule histogramMatchImage( py::capsule & antsSourceImage, filter->SetNumberOfMatchPoints( numberOfMatchPoints ); filter->Update(); - return wrap< ImageType >( filter->GetOutput() ); + AntsImage out_ants_image = { filter->GetOutput() }; + return out_ants_image; } -PYBIND11_MODULE(histogramMatchImage, m) +void local_histogramMatchImages(nb::module_ &m) { m.def("histogramMatchImageF2", &histogramMatchImage>); m.def("histogramMatchImageF3", &histogramMatchImage>); diff --git a/src/LOCAL_labelStats.cxx b/src/LOCAL_labelStats.cxx index b66c9734..e6e2461f 100644 --- a/src/LOCAL_labelStats.cxx +++ b/src/LOCAL_labelStats.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "itkImage.h" #include "itkLabelStatisticsImageFilter.h" @@ -8,11 +13,11 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; -using namespace py::literals; +namespace nb = nanobind; +using namespace nb::literals; template< unsigned int Dimension > -py::dict labelStatsHelper( +nb::dict labelStatsHelper( typename itk::Image< float, Dimension >::Pointer image, typename itk::Image< unsigned int, Dimension>::Pointer labelImage) { @@ -112,38 +117,40 @@ py::dict labelStatsHelper( if ( Dimension > 3 ) t[labelcount]=comvec[ labelcount ][3]; } - py::dict labelStats = py::dict( "LabelValue"_a=labelvals, - "Mean"_a=means, - "Min"_a=mins, - "Max"_a=maxes, - "Variance"_a=variances, - "Count"_a=counts, - "Volume"_a=volumes, - "Mass"_a=mass, - "x"_a=x, - "y"_a=y, - "z"_a=z, - "t"_a=t ); + nb::dict labelStats; + labelStats["LabelValue"] = labelvals; + labelStats["Mean"] = means; + labelStats["Min"] = mins; + labelStats["Max"] = maxes; + labelStats["Variance"] = variances; + labelStats["Count"] = counts; + labelStats["Volume"] = volumes; + labelStats["Mass"] = mass; + labelStats["x"] = x; + labelStats["y"] = y; + labelStats["z"] = z; + labelStats["t"] = t; + return (labelStats); } template -py::dict labelStats(py::capsule py_image, - py::capsule py_labelImage) +nb::dict labelStats(AntsImage> & py_image, + AntsImage> & py_labelImage) { typedef itk::Image FloatImageType; typedef itk::Image IntImageType; typedef typename FloatImageType::Pointer FloatImagePointerType; typedef typename IntImageType::Pointer IntImagePointerType; - FloatImagePointerType myimage = as>( py_image ); - IntImagePointerType mylabelimage = as>( py_labelImage ); + + FloatImagePointerType myimage = py_image.ptr; + IntImagePointerType mylabelimage = py_labelImage.ptr; return labelStatsHelper( myimage, mylabelimage ); } - -PYBIND11_MODULE(labelStats, m) +void local_labelStats(nb::module_ &m) { m.def("labelStats2D", &labelStats<2>); m.def("labelStats3D", &labelStats<3>); diff --git a/src/LOCAL_weingartenImageCurvature.cxx b/src/LOCAL_weingartenImageCurvature.cxx index cd88b15f..c4c26278 100644 --- a/src/LOCAL_weingartenImageCurvature.cxx +++ b/src/LOCAL_weingartenImageCurvature.cxx @@ -1,6 +1,12 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -13,10 +19,10 @@ #include "LOCAL_antsImage.h" +namespace nb = nanobind; +using namespace nb::literals; -namespace py = pybind11; - -py::capsule weingartenImageCurvature( py::capsule myimage, +AntsImage> weingartenImageCurvature( AntsImage> myimage, float sigma, int opt ) { typedef itk::Image ImageType; @@ -25,7 +31,7 @@ py::capsule weingartenImageCurvature( py::capsule myimage, enum { ImageDimension = ImageType::ImageDimension }; typedef itk::SurfaceImageCurvature ParamType; typename ParamType::Pointer Parameterizer = ParamType::New(); - typename ImageType::Pointer input = as( myimage ); + typename ImageType::Pointer input = myimage.ptr; typename ImageType::DirectionType imgdir = input->GetDirection(); typename ImageType::DirectionType iddir = input->GetDirection(); iddir.SetIdentity(); @@ -52,12 +58,14 @@ py::capsule weingartenImageCurvature( py::capsule myimage, } typename ImageType::Pointer output = Parameterizer->GetFunctionImage(); output->SetDirection( imgdir ); - return wrap( output ); + + AntsImage outImage = { output }; + return outImage; } -PYBIND11_MODULE(weingartenImageCurvature, m) +void local_weingartenImageCurvature(nb::module_ &m) { m.def("weingartenImageCurvature", &weingartenImageCurvature); } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 9bc5a1f8..76597b03 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,11 +11,14 @@ #include "LOCAL_cropImage.cxx" #include "LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx" #include "LOCAL_fitBsplineObjectToScatteredData.cxx" +#include "LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx" #include "LOCAL_fsl2antstransform.cxx" #include "LOCAL_getNeighborhoodMatrix.cxx" +#include "LOCAL_histogramMatchImages.cxx" #include "LOCAL_integrateVelocityField.cxx" #include "LOCAL_invertDisplacementField.cxx" #include "LOCAL_labelOverlapMeasures.cxx" +#include "LOCAL_labelStats.cxx" #include "LOCAL_mergeChannels.cxx" #include "LOCAL_padImage.cxx" #include "LOCAL_readImage.cxx" @@ -25,6 +28,7 @@ #include "LOCAL_reorientImage2.cxx" #include "LOCAL_sliceImage.cxx" #include "LOCAL_SmoothImage.cxx" +#include "LOCAL_weingartenImageCurvature.cxx" #include "WRAP_antsAffineInitializer.cxx" #include "WRAP_antsApplyTransforms.cxx" @@ -59,11 +63,14 @@ void local_cropImage(nb::module_ &); void local_composeDisplacementFields(nb::module_ &); void local_fitBsplineDisplacementFieldToScatteredData(nb::module_ &); void local_fitBsplineObjectToScatteredData(nb::module_ &); +void local_fitThinPlateSplineDisplacementFieldToScatteredData(nb::module_ &); void local_fsl2antstransform(nb::module_ &); void local_getNeighborhoodMatrix(nb::module_ &); +void local_histogramMatchImages(nb::module_ &); void local_integrateVelocityField(nb::module_ &); void local_invertDisplacementField(nb::module_ &); void local_labelOverlapMeasures(nb::module_ &); +void local_labelStats(nb::module_ &); void local_mergeChannels(nb::module_ &); void local_padImage(nb::module_ &); void local_readImage(nb::module_ &); @@ -73,6 +80,7 @@ void local_reorientImage(nb::module_ &); void local_reorientImage2(nb::module_ &); void local_sliceImage(nb::module_ &); void local_SmoothImage(nb::module_ &); +void local_weingartenImageCurvature(nb::module_ &); void wrap_antsAffineInitializer(nb::module_ &); void wrap_antsApplyTransforms(nb::module_ &); @@ -106,11 +114,14 @@ NB_MODULE(lib, m) { local_cropImage(m); local_fitBsplineDisplacementFieldToScatteredData(m); local_fitBsplineObjectToScatteredData(m); + local_fitThinPlateSplineDisplacementFieldToScatteredData(m); local_fsl2antstransform(m); local_getNeighborhoodMatrix(m); + local_histogramMatchImages(m); local_integrateVelocityField(m); local_invertDisplacementField(m); local_labelOverlapMeasures(m); + local_labelStats(m); local_mergeChannels(m); local_padImage(m); local_readImage(m); @@ -120,6 +131,7 @@ NB_MODULE(lib, m) { local_reorientImage2(m); local_sliceImage(m); local_SmoothImage(m); + local_weingartenImageCurvature(m); wrap_antsAffineInitializer(m); wrap_antsApplyTransforms(m); From 5d9344b69cd60eb964b8dc49f1f5b9d06d8f54a8 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Sat, 11 May 2024 21:49:34 +0200 Subject: [PATCH 15/26] utils and metrics tests passing --- src/LOCAL_antsImageToImageMetric.cxx | 29 +++++--- src/LOCAL_antsImageToImageMetric.h | 38 ++++++----- src/LOCAL_mergeChannels.cxx | 89 +++++++++++++++++++++++++ src/LOCAL_mergeChannels.h | 8 ++- src/LOCAL_rgbToVector.cxx | 48 +++++++------ src/LOCAL_simulateDisplacementField.cxx | 29 +++++--- src/main.cpp | 9 +++ tests/run_tests.sh | 6 +- tests/test_utils.py | 7 +- 9 files changed, 198 insertions(+), 65 deletions(-) diff --git a/src/LOCAL_antsImageToImageMetric.cxx b/src/LOCAL_antsImageToImageMetric.cxx index 0abd2e6a..706ddf27 100644 --- a/src/LOCAL_antsImageToImageMetric.cxx +++ b/src/LOCAL_antsImageToImageMetric.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -21,19 +26,21 @@ #include "LOCAL_antsImageToImageMetric.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; + template -void wrapANTsImageToImageMetric(py::module & m, std::string const & suffix) { - py::class_, std::shared_ptr>>(m, ("ANTsImageToImageMetric" + suffix).c_str()) +void wrapANTsImageToImageMetric(nb::module_ & m, std::string const & suffix) { + nb::class_>(m, ("ANTsImageToImageMetric" + suffix).c_str()) //.def(py::init<>()) // read only properties - .def_readonly("precision", &ANTsImageToImageMetric::precision) - .def_readonly("metrictype", &ANTsImageToImageMetric::metrictype) - .def_readonly("dimension", &ANTsImageToImageMetric::dimension) - .def_readonly("isVector", &ANTsImageToImageMetric::isVector) - .def_readonly("pointer", &ANTsImageToImageMetric::pointer) + .def_ro("precision", &ANTsImageToImageMetric::precision) + .def_ro("metrictype", &ANTsImageToImageMetric::metrictype) + .def_ro("dimension", &ANTsImageToImageMetric::dimension) + .def_ro("isVector", &ANTsImageToImageMetric::isVector) + .def_ro("pointer", &ANTsImageToImageMetric::pointer) .def("setFixedImage", &ANTsImageToImageMetric::template setFixedImage>) .def("setMovingImage", &ANTsImageToImageMetric::template setMovingImage>) @@ -43,7 +50,7 @@ void wrapANTsImageToImageMetric(py::module & m, std::string const & suffix) { } -PYBIND11_MODULE(antsImageToImageMetric, m) { +void local_antsImageToImageMetric(nb::module_ &m) { wrapANTsImageToImageMetric,itk::Image>,2>(m, "F2"); wrapANTsImageToImageMetric,itk::Image>,3>(m, "F3"); diff --git a/src/LOCAL_antsImageToImageMetric.h b/src/LOCAL_antsImageToImageMetric.h index 4e981789..2b788327 100644 --- a/src/LOCAL_antsImageToImageMetric.h +++ b/src/LOCAL_antsImageToImageMetric.h @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -22,7 +27,8 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template class ANTsImageToImageMetric { @@ -32,13 +38,13 @@ class ANTsImageToImageMetric { unsigned int dimension; std::string metrictype; unsigned int isVector; - py::capsule pointer; + nb::capsule pointer; template - void setFixedImage( py::capsule &, bool); + void setFixedImage( AntsImage &, bool); template - void setMovingImage( py::capsule &, bool); + void setMovingImage( AntsImage &, bool); void setSampling(std::string, float); void initialize(); @@ -61,7 +67,7 @@ ANTsImageToImageMetric wrap_metric( const typename MetricType::Point antsMetric.dimension = MetricType::FixedImageDimension; antsMetric.metrictype = itkMetric->GetNameOfClass(); antsMetric.isVector = 0; - antsMetric.pointer = py::capsule(ptr, capsuleDestructor); + antsMetric.pointer = nb::capsule(ptr); return antsMetric; } @@ -69,7 +75,7 @@ ANTsImageToImageMetric wrap_metric( const typename MetricType::Point template typename MetricType::Pointer as_metric( ANTsImageToImageMetric & metric ) { - void *ptr = metric.pointer; + void *ptr = metric.pointer.data(); typename MetricType::Pointer * real = reinterpret_cast(ptr); // static_cast or reinterpret_cast ?? return *real; @@ -78,7 +84,7 @@ typename MetricType::Pointer as_metric( ANTsImageToImageMetric & met template template -void ANTsImageToImageMetric< MetricType >::setFixedImage( py::capsule & antsImage, +void ANTsImageToImageMetric< MetricType >::setFixedImage( AntsImage & antsImage, bool isMask ) { typedef typename MetricType::FixedImageType ImageType; @@ -88,7 +94,7 @@ void ANTsImageToImageMetric< MetricType >::setFixedImage( py::capsule & antsImag typedef typename ImageMaskSpatialObjectType::ImageType MaskImageType; MetricPointerType metric = as_metric< MetricType >( *this ); - ImagePointerType image = as< ImageType >( antsImage ); + ImagePointerType image = antsImage.ptr; if ( isMask ) { typename ImageMaskSpatialObjectType::Pointer mask = ImageMaskSpatialObjectType::New(); @@ -107,7 +113,7 @@ void ANTsImageToImageMetric< MetricType >::setFixedImage( py::capsule & antsImag template template -void ANTsImageToImageMetric< MetricType >::setMovingImage( py::capsule & antsImage, +void ANTsImageToImageMetric< MetricType >::setMovingImage( AntsImage & antsImage, bool isMask ) { typedef typename MetricType::MovingImageType ImageType; @@ -118,7 +124,7 @@ void ANTsImageToImageMetric< MetricType >::setMovingImage( py::capsule & antsIma MetricPointerType metric = as_metric< MetricType >( *this ); - ImagePointerType image = as< ImageType >( antsImage ); + ImagePointerType image = antsImage.ptr; if ( isMask ) { typename ImageMaskSpatialObjectType::Pointer mask = ImageMaskSpatialObjectType::New(); @@ -318,14 +324,14 @@ ANTsImageToImageMetric< MetricBaseType > create_ants_metric(std::string pixeltyp unsigned int dimension, std::string metrictype, unsigned int isVector, - py::capsule fixed_img, - py::capsule moving_img ) + AntsImage> & fixed_img, + AntsImage> & moving_img ) { typedef itk::Image ImageType; typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType fixed = as< ImageType >( fixed_img ); - ImagePointerType moving = as< ImageType >( moving_img ); + ImagePointerType fixed = fixed_img.ptr; + ImagePointerType moving = moving_img.ptr; typedef typename MetricBaseType::Pointer MetricBasePointerType; diff --git a/src/LOCAL_mergeChannels.cxx b/src/LOCAL_mergeChannels.cxx index dd54ff1e..42222f97 100644 --- a/src/LOCAL_mergeChannels.cxx +++ b/src/LOCAL_mergeChannels.cxx @@ -61,6 +61,95 @@ AntsImage mergeChannels( std::vector> imag return outImage; } + +template< class ImageType, class VectorImageType > +typename VectorImageType::Pointer mergeChannels2( std::vector> imageList ) +{ + typedef typename ImageType::Pointer ImagePointerType; + typedef typename VectorImageType::Pointer VectorImagePointerType; + + unsigned int nImages = imageList.size(); + + std::vector images; + for ( unsigned int i=0; iSetRegions( images[0]->GetLargestPossibleRegion() ); + vectorImage->SetSpacing( images[0]->GetSpacing() ); + vectorImage->SetOrigin( images[0]->GetOrigin() ); + vectorImage->SetDirection( images[0]->GetDirection() ); + vectorImage->SetNumberOfComponentsPerPixel( nImages ); + vectorImage->AllocateInitialized(); + + // Fill image data + itk::ImageRegionIteratorWithIndex it( vectorImage, + vectorImage->GetLargestPossibleRegion() ); + + while (!it.IsAtEnd() ) + { + typename VectorImageType::PixelType pix; + pix.SetSize( nImages ); + for (unsigned int i=0; iGetPixel(it.GetIndex()); + } + vectorImage->SetPixel(it.GetIndex(), pix); + ++it; + } + + //return wrap( vectorImage ); + //AntsImage outImage = { vectorImage }; + return vectorImage; +} + +template< class ImageType, class VectorImageType > +typename VectorImageType::Pointer mergeChannels3( std::vector> imageList ) +{ + typedef typename ImageType::Pointer ImagePointerType; + typedef typename VectorImageType::Pointer VectorImagePointerType; + + unsigned int nImages = imageList.size(); + + std::vector images; + for ( unsigned int i=0; iSetRegions( images[0]->GetLargestPossibleRegion() ); + vectorImage->SetSpacing( images[0]->GetSpacing() ); + vectorImage->SetOrigin( images[0]->GetOrigin() ); + vectorImage->SetDirection( images[0]->GetDirection() ); + //vectorImage->SetNumberOfComponentsPerPixel( nImages ); + vectorImage->AllocateInitialized(); + + // Fill image data + itk::ImageRegionIteratorWithIndex it( vectorImage, + vectorImage->GetLargestPossibleRegion() ); + + while (!it.IsAtEnd() ) + { + + typename VectorImageType::PixelType pix; + //pix.SetSize( nImages ); + for (unsigned int i=0; iGetPixel(it.GetIndex()); + } + vectorImage->SetPixel(it.GetIndex(), pix); + ++it; + } + + //return wrap( vectorImage ); + //AntsImage outImage = { vectorImage }; + return vectorImage; +} + + template< class VectorImageType, class ImageType> std::vector> splitChannels( AntsImage & antsimage ) { diff --git a/src/LOCAL_mergeChannels.h b/src/LOCAL_mergeChannels.h index ceae2fa6..f4230118 100644 --- a/src/LOCAL_mergeChannels.h +++ b/src/LOCAL_mergeChannels.h @@ -19,4 +19,10 @@ template< class VectorImageType, class ImageType> std::vector> splitChannels( AntsImage & antsimage ); template< class ImageType, class VectorImageType > -AntsImage mergeChannels( std::vector> imageList ); \ No newline at end of file +AntsImage mergeChannels( std::vector> imageList ); + +template< class ImageType, class VectorImageType > +typename VectorImageType::Pointer mergeChannels2( std::vector> imageList ); + +template< class ImageType, class VectorImageType > +typename VectorImageType::Pointer mergeChannels3( std::vector> imageList ); \ No newline at end of file diff --git a/src/LOCAL_rgbToVector.cxx b/src/LOCAL_rgbToVector.cxx index c7ffa16c..ad9fe0e1 100644 --- a/src/LOCAL_rgbToVector.cxx +++ b/src/LOCAL_rgbToVector.cxx @@ -1,7 +1,11 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "itkImage.h" #include "itkImageFileReader.h" @@ -10,10 +14,11 @@ #include "itkRGBToVectorImageAdaptor.h" #include "itkCastImageFilter.h" -#include "LOCAL_mergeChannels.cxx" +#include "LOCAL_mergeChannels.h" #include "LOCAL_antsImage.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; template typename VectorImageType::Pointer imageOfVectors_to_VectorImage( typename ImageOfVectorsType::Pointer imageOfVectors ) @@ -24,13 +29,13 @@ typename VectorImageType::Pointer imageOfVectors_to_VectorImage( typename ImageO typedef itk::Image ImageType; // split channels - std::vector myChannels; - py::capsule myCapsule = wrap(imageOfVectors); + std::vector> myChannels; + AntsImage myCapsule = { imageOfVectors }; myChannels = splitChannels( myCapsule ); // now merge channels into a vectorimage - py::capsule finalImage = mergeChannels2( myChannels ); - return as( finalImage ); + VectorImagePointerType finalImage = mergeChannels2( myChannels ); + return finalImage; } template @@ -42,18 +47,18 @@ typename ImageOfVectorsType::Pointer VectorImage_to_imageOfVectors( typename Vec typedef itk::Image ImageType; // split channels - std::vector myChannels; - py::capsule myCapsule = wrap(vectorImage); + std::vector> myChannels; + AntsImage myCapsule = { vectorImage }; myChannels = splitChannels( myCapsule ); // now merge channels into a vectorimage - py::capsule finalImage = mergeChannels3( myChannels ); - return as( finalImage ); + ImageOfVectorsPointerType finalImage = mergeChannels3( myChannels ); + return finalImage; } template -py::capsule RgbToVector( py::capsule antsImage ) +AntsImage> RgbToVector( AntsImage & antsImage ) { typedef typename RGBImageType::Pointer RGBImagePointerType; @@ -61,7 +66,7 @@ py::capsule RgbToVector( py::capsule antsImage ) typedef itk::Image, Dimension> VectorImageType; typedef typename VectorImageType::Pointer VectorImagePointerType; - RGBImagePointerType rgbImage = as< RGBImageType >( antsImage ); + RGBImagePointerType rgbImage = antsImage.ptr;//as< RGBImageType >( antsImage ); // 2) Cast to Vector image for processing typedef itk::RGBToVectorImageAdaptor AdaptorInputType; @@ -81,15 +86,16 @@ py::capsule RgbToVector( py::capsule antsImage ) typedef typename VectorImageType2::Pointer VectorImagePointerType2; VectorImagePointerType2 newVectorImage = imageOfVectors_to_VectorImage(vectorImage); - return wrap( newVectorImage ); + AntsImage outImage = { newVectorImage }; + return outImage; } template -py::capsule VectorToRgb( py::capsule antsImage ) +AntsImage, Dimension >> VectorToRgb( AntsImage & antsImage ) { // cast VectorImage to ImageOfVectors typedef typename VectorImageType::Pointer VectorImagePointerType; - VectorImagePointerType vectorImage = as( antsImage ); + VectorImagePointerType vectorImage = antsImage.ptr;//as( antsImage ); typedef itk::Image, Dimension> VectorImageType2; typedef typename VectorImageType2::Pointer VectorImagePointerType2; @@ -109,11 +115,13 @@ py::capsule VectorToRgb( py::capsule antsImage ) castInput->SetInput( adaptInput ); castInput->Update(); - return wrap( castInput->GetOutput() ); + //return wrap( castInput->GetOutput() ); + AntsImage outImage = { castInput->GetOutput() }; + return outImage; } -PYBIND11_MODULE(rgbToVector, m) +void local_rgbToVector(nb::module_ &m) { m.def("RgbToVector2", &RgbToVector, 2>, 2>); m.def("RgbToVector3", &RgbToVector, 3>, 3>); diff --git a/src/LOCAL_simulateDisplacementField.cxx b/src/LOCAL_simulateDisplacementField.cxx index 8ce19ec6..d2ee0ffc 100644 --- a/src/LOCAL_simulateDisplacementField.cxx +++ b/src/LOCAL_simulateDisplacementField.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -12,11 +17,11 @@ #include "antscore/itkSimulatedExponentialDisplacementFieldSource.h" #include "LOCAL_antsImage.h" -namespace py = pybind11; -using namespace py::literals; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule simulateBsplineDisplacementField(py::capsule & antsDomainImage, +AntsImage> simulateBsplineDisplacementField(AntsImage> & antsDomainImage, unsigned int numberOfRandomPoints, float standardDeviationDisplacementField, bool enforceStationaryBoundary, @@ -26,7 +31,7 @@ py::capsule simulateBsplineDisplacementField(py::capsule & antsDomainImage, using ImageType = itk::Image; using ImagePointerType = typename ImageType::Pointer; - ImagePointerType domainImage = as< ImageType >( antsDomainImage ); + ImagePointerType domainImage = antsDomainImage.ptr; using VectorType = itk::Vector; using DisplacementFieldType = itk::Image; @@ -76,11 +81,12 @@ py::capsule simulateBsplineDisplacementField(py::capsule & antsDomainImage, antsField->SetPixel( It.GetIndex(), antsVector ); } - return wrap< ANTsFieldType >( antsField ); + AntsImage outImage = { antsField }; + return outImage; } template -py::capsule simulateExponentialDisplacementField(py::capsule & antsDomainImage, +AntsImage> simulateExponentialDisplacementField(AntsImage> & antsDomainImage, unsigned int numberOfRandomPoints, float standardDeviationDisplacementField, bool enforceStationaryBoundary, @@ -89,7 +95,7 @@ py::capsule simulateExponentialDisplacementField(py::capsule & antsDomainImage, using ImageType = itk::Image; using ImagePointerType = typename ImageType::Pointer; - ImagePointerType domainImage = as< ImageType >( antsDomainImage ); + ImagePointerType domainImage = antsDomainImage.ptr; using VectorType = itk::Vector; using DisplacementFieldType = itk::Image; @@ -132,10 +138,11 @@ py::capsule simulateExponentialDisplacementField(py::capsule & antsDomainImage, antsField->SetPixel( It.GetIndex(), antsVector ); } - return wrap< ANTsFieldType >( antsField ); + AntsImage outImage = { antsField }; + return outImage; } -PYBIND11_MODULE(simulateDisplacementField, m) +void local_simulateDisplacementField(nb::module_ &m) { m.def("simulateBsplineDisplacementField2D", &simulateBsplineDisplacementField); m.def("simulateBsplineDisplacementField3D", &simulateBsplineDisplacementField); diff --git a/src/main.cpp b/src/main.cpp index 76597b03..6e811cd7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include "LOCAL_antsImageClone.cxx" #include "LOCAL_antsImageHeaderInfo.cxx" #include "LOCAL_antsImageMutualInformation.cxx" +#include "LOCAL_antsImageToImageMetric.cxx" #include "LOCAL_antsImageUtils.cxx" #include "LOCAL_antsTransform.cxx" #include "LOCAL_composeDisplacementFields.cxx" @@ -26,6 +27,8 @@ #include "LOCAL_reflectionMatrix.cxx" #include "LOCAL_reorientImage.cxx" #include "LOCAL_reorientImage2.cxx" +#include "LOCAL_rgbToVector.cxx" +#include "LOCAL_simulateDisplacementField.cxx" #include "LOCAL_sliceImage.cxx" #include "LOCAL_SmoothImage.cxx" #include "LOCAL_weingartenImageCurvature.cxx" @@ -57,6 +60,7 @@ void local_antsImage(nb::module_ &); void local_antsImageClone(nb::module_ &); void local_antsImageHeaderInfo(nb::module_ &); void local_antsImageMutualInformation(nb::module_ &); +void local_antsImageToImageMetric(nb::module_ &); void local_antsImageUtils(nb::module_ &); void local_antsTransform(nb::module_ &); void local_cropImage(nb::module_ &); @@ -78,6 +82,8 @@ void local_readTransform(nb::module_ &); void local_reflectionMatrix(nb::module_ &); void local_reorientImage(nb::module_ &); void local_reorientImage2(nb::module_ &); +void local_rgbToVector(nb::module_ &); +void local_simulateDisplacementField(nb::module_ &); void local_sliceImage(nb::module_ &); void local_SmoothImage(nb::module_ &); void local_weingartenImageCurvature(nb::module_ &); @@ -108,6 +114,7 @@ NB_MODULE(lib, m) { local_antsImageClone(m); local_antsImageHeaderInfo(m); local_antsImageMutualInformation(m); + local_antsImageToImageMetric(m); local_antsImageUtils(m); local_antsTransform(m); local_composeDisplacementFields(m); @@ -129,6 +136,8 @@ NB_MODULE(lib, m) { local_reflectionMatrix(m); local_reorientImage(m); local_reorientImage2(m); + local_rgbToVector(m); + local_simulateDisplacementField(m); local_sliceImage(m); local_SmoothImage(m); local_weingartenImageCurvature(m); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 97813847..8b7099e8 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -25,7 +25,7 @@ $PYCMD test_core_ants_image.py $@ $PYCMD test_core_ants_image_io.py $@ $PYCMD test_core_ants_transform.py $@ $PYCMD test_core_ants_transform_io.py $@ -#$PYCMD test_core_ants_metric.py $@ +$PYCMD test_core_ants_metric.py $@ echo "Running learn tests" #$PYCMD test_learn.py $@ @@ -37,13 +37,13 @@ echo "Running segmentation tests" $PYCMD test_segmentation.py $@ echo "Running utils tests" -#$PYCMD test_utils.py $@ +$PYCMD test_utils.py $@ echo "Running viz tests" $PYCMD test_viz.py $@ echo "Running bug tests" -#$PYCMD test_bugs.py $@ +$PYCMD test_bugs.py $@ diff --git a/tests/test_utils.py b/tests/test_utils.py index 57438726..f8363fad 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -530,6 +530,7 @@ def test_image_similarity_example(self): x = ants.image_read(ants.get_ants_data("r16")) y = ants.image_read(ants.get_ants_data("r30")) metric = ants.image_similarity(x, y, metric_type="MeanSquares") + self.assertTrue(metric > 0) class TestModule_image_to_cluster_images(unittest.TestCase): @@ -839,7 +840,7 @@ def test1(self): # rgb_arr = img_rgb.numpy() # vec_arr = img_vec.numpy() - print(np.allclose(img.numpy(), img.numpy())) + self.assertTrue(np.allclose(img.numpy(), img.numpy())) def test2(self): import ants @@ -849,13 +850,13 @@ def test2(self): np.random.randint(0, 255, (20, 20, 3)).astype("uint8"), is_rgb=True ) vec_img = rgb_img.rgb_to_vector() - print(ants.allclose(rgb_img, vec_img)) + self.assertTrue(ants.allclose(rgb_img, vec_img)) vec_img = ants.from_numpy( np.random.randint(0, 255, (20, 20, 3)).astype("uint8"), has_components=True ) rgb_img = vec_img.vector_to_rgb() - print(ants.allclose(rgb_img, vec_img)) + self.assertTrue(ants.allclose(rgb_img, vec_img)) class TestRandom(unittest.TestCase): From 5f285ffeed56be7c8e7f8e3a2627612c6571a0f6 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Sat, 11 May 2024 22:20:06 +0200 Subject: [PATCH 16/26] all tests passing --- ants/learn/decomposition.py | 5 +- src/LOCAL_sccaner.cxx | 129 ++++++++++++++++++++++-------------- src/main.cpp | 3 + tests/run_tests.sh | 2 +- 4 files changed, 86 insertions(+), 53 deletions(-) diff --git a/ants/learn/decomposition.py b/ants/learn/decomposition.py index dddbc897..49690033 100644 --- a/ants/learn/decomposition.py +++ b/ants/learn/decomposition.py @@ -197,7 +197,8 @@ def sparse_decom2(inmatrix, initialization_list, initialization_list2, ell1, verbose, prior_weight, mycoption, max_based) - + outval['eig1'] = np.array(outval['eig1']) + outval['eig2'] = np.array(outval['eig2']) p1 = np.dot(input_matrices[0], outval['eig1'].T) p2 = np.dot(input_matrices[1], outval['eig2'].T) @@ -229,6 +230,8 @@ def sparse_decom2(inmatrix, initialization_list, initialization_list2, ell1, verbose, prior_weight, mycoption, max_based) + outvalperm['eig1'] = np.array(outvalperm['eig1']) + outvalperm['eig2'] = np.array(outvalperm['eig2']) p1perm = np.dot(m1, outvalperm['eig1'].T) p2perm = np.dot(m2, outvalperm['eig2'].T) outcorrsperm = np.array([pearsonr(p1perm[:,i],p2perm[:,i])[0] for i in range(p1perm.shape[1])]) diff --git a/src/LOCAL_sccaner.cxx b/src/LOCAL_sccaner.cxx index 257f56e0..b1a37bb9 100644 --- a/src/LOCAL_sccaner.cxx +++ b/src/LOCAL_sccaner.cxx @@ -1,7 +1,11 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -13,15 +17,15 @@ #include "antscore/antsSCCANObject.h" #include "LOCAL_antsImage.h" -namespace py = pybind11; -using namespace py::literals; +namespace nb = nanobind; +using namespace nb::literals; template< class ImageType, class IntType, class RealType > -py::dict sccanCppHelper( - py::array_t X, - py::array_t Y, - py::capsule maskXimage, - py::capsule maskYimage, +nb::dict sccanCppHelper( + std::vector> X, + std::vector> Y, + AntsImage & maskXimage, + AntsImage & maskYimage, int maskxisnull, int maskyisnull, RealType sparsenessx, @@ -32,8 +36,8 @@ py::dict sccanCppHelper( IntType cthreshy, RealType z, RealType smooth, - std::vector initializationListx, - std::vector initializationListy, + std::vector> initializationListx, + std::vector> initializationListy, IntType covering, RealType ell1, IntType verbose, @@ -54,12 +58,12 @@ py::dict sccanCppHelper( typename ImageType::Pointer maskx = ITK_NULLPTR; if (maskxisnull > 0) { - maskx = as< ImageType >( maskXimage ); + maskx = maskXimage.ptr; } typename ImageType::Pointer masky = ITK_NULLPTR; if (maskyisnull > 0) { - masky = as< ImageType >( maskYimage ); + masky = maskYimage.ptr; } // deal with the initializationList, if any @@ -68,11 +72,11 @@ py::dict sccanCppHelper( { itk::ImageRegionIteratorWithIndex it( maskx, maskx->GetLargestPossibleRegion() ); - vMatrix priorROIMatx( nImagesx , X.shape(1) ); + vMatrix priorROIMatx( nImagesx , X[0].size() ); priorROIMatx.fill( 0 ); for ( unsigned int i = 0; i < nImagesx; i++ ) { - typename ImageType::Pointer init = as( initializationListx[i] ); + typename ImageType::Pointer init = initializationListx[i].ptr; unsigned long ct = 0; it.GoToBegin(); while ( !it.IsAtEnd() ) @@ -95,11 +99,11 @@ py::dict sccanCppHelper( { itk::ImageRegionIteratorWithIndex it( masky, masky->GetLargestPossibleRegion() ); - vMatrix priorROIMaty( nImagesy , Y.shape(1) ); + vMatrix priorROIMaty( nImagesy , Y[0].size() ); priorROIMaty.fill( 0 ); for ( unsigned int i = 0; i < nImagesy; i++ ) { - typename ImageType::Pointer init = as( initializationListy[i] ); + typename ImageType::Pointer init = initializationListy[i].ptr; unsigned long ct = 0; it.GoToBegin(); while ( !it.IsAtEnd() ) @@ -120,14 +124,31 @@ py::dict sccanCppHelper( sccanobj->SetPriorWeight( priorWeight ); sccanobj->SetLambda( priorWeight ); // cast hack from Python type to sccan type - std::vector xdat = X.reshape({-1}).cast >(); - const double* _xdata = &xdat[0]; - vMatrix vnlX( _xdata , X.shape(0), X.shape(1) ); + //std::vector xdat = X;//.reshape({-1}).cast >(); + //const double* _xdata = &xdat[0]; + + vMatrix vnlX( X.size(), X[0].size() ); + for (int i = 0; i < X.size(); i++) + { + for (int j = 0; j < X[0].size(); j++) + { + vnlX(i,j) = X[i][j]; + } + } + //vnlX = vnlX.transpose(); - std::vector ydat = Y.reshape({-1}).cast >(); - const double* _ydata = &ydat[0]; - vMatrix vnlY( _ydata , Y.shape(0), Y.shape(1) ); + //std::vector ydat = Y.reshape({-1}).cast >(); + //const double* _ydata = &ydat[0]; + //vMatrix vnlY( _ydata , Y.shape(0), Y.shape(1) ); + vMatrix vnlY( Y.size(), Y[0].size() ); + for (int i = 0; i < Y.size(); i++) + { + for (int j = 0; j < Y[0].size(); j++) + { + vnlY(i,j) = Y[i][j]; + } + } //vnlY = vnlY.transpose(); // cast hack done sccanobj->SetGetSmall( false ); @@ -183,18 +204,21 @@ py::dict sccanCppHelper( } } - py::array_t eanatMatpList = py::cast(eanatMatp); - py::array_t eanatMatqList = py::cast(eanatMatq); + //nb::ndarray eanatMatpList = nb::cast(eanatMatp); + //nb::ndarray eanatMatqList = nb::cast(eanatMatq); - return py::dict("eig1"_a=eanatMatpList, "eig2"_a=eanatMatqList); + nb::dict res; + res["eig1"] = eanatMatp; + res["eig2"] = eanatMatq; + return res; } template -py::dict sccanCpp(py::array_t X, - py::array_t Y, - py::capsule maskXimage, - py::capsule maskYimage, +nb::dict sccanCpp(std::vector> X, + std::vector> Y, + AntsImage & maskXimage, + AntsImage & maskYimage, int maskxisnull, int maskyisnull, float sparsenessx, @@ -205,8 +229,8 @@ py::dict sccanCpp(py::array_t X, unsigned int cthreshy, float z, float smooth, - std::vector initializationListx, - std::vector initializationListy, + std::vector> initializationListx, + std::vector> initializationListy, float ell1, unsigned int verbose, float priorWeight, @@ -243,11 +267,11 @@ py::dict sccanCpp(py::array_t X, template< class ImageType, class IntType, class RealType > -py::dict sccanCppHelperV2( +nb::dict sccanCppHelperV2( std::vector > X, std::vector > Y, - py::capsule maskXimage, - py::capsule maskYimage, + AntsImage & maskXimage, + AntsImage & maskYimage, int maskxisnull, int maskyisnull, RealType sparsenessx, @@ -258,8 +282,8 @@ py::dict sccanCppHelperV2( IntType cthreshy, RealType z, RealType smooth, - std::vector initializationListx, - std::vector initializationListy, + std::vector> initializationListx, + std::vector> initializationListy, IntType covering, RealType ell1, IntType verbose, @@ -280,12 +304,12 @@ py::dict sccanCppHelperV2( typename ImageType::Pointer maskx = ITK_NULLPTR; if (maskxisnull > 0) { - maskx = as< ImageType >( maskXimage ); + maskx = maskXimage.ptr; } typename ImageType::Pointer masky = ITK_NULLPTR; if (maskyisnull > 0) { - masky = as< ImageType >( maskYimage ); + masky = maskYimage.ptr; } // deal with the initializationList, if any @@ -298,7 +322,7 @@ py::dict sccanCppHelperV2( priorROIMatx.fill( 0 ); for ( unsigned int i = 0; i < nImagesx; i++ ) { - typename ImageType::Pointer init = as( initializationListx[i] ); + typename ImageType::Pointer init = initializationListx[i].ptr; unsigned long ct = 0; it.GoToBegin(); while ( !it.IsAtEnd() ) @@ -325,7 +349,7 @@ py::dict sccanCppHelperV2( priorROIMaty.fill( 0 ); for ( unsigned int i = 0; i < nImagesy; i++ ) { - typename ImageType::Pointer init = as( initializationListy[i] ); + typename ImageType::Pointer init = initializationListy[i].ptr; unsigned long ct = 0; it.GoToBegin(); while ( !it.IsAtEnd() ) @@ -422,18 +446,21 @@ py::dict sccanCppHelperV2( } } - py::array_t eanatMatpList = py::cast(eanatMatp); - py::array_t eanatMatqList = py::cast(eanatMatq); + //nb::ndarray eanatMatpList = nb::cast(eanatMatp); + //nb::ndarray eanatMatqList = nb::cast(eanatMatq); - return py::dict("eig1"_a=eanatMatpList, "eig2"_a=eanatMatqList); + nb::dict res; + res["eig1"] = eanatMatp; + res["eig2"] = eanatMatq; + return res; } template -py::dict sccanCppV2(std::vector > X, +nb::dict sccanCppV2(std::vector > X, std::vector > Y, - py::capsule maskXimage, - py::capsule maskYimage, + AntsImage & maskXimage, + AntsImage & maskYimage, int maskxisnull, int maskyisnull, float sparsenessx, @@ -444,8 +471,8 @@ py::dict sccanCppV2(std::vector > X, unsigned int cthreshy, float z, float smooth, - std::vector initializationListx, - std::vector initializationListy, + std::vector> initializationListx, + std::vector> initializationListy, float ell1, unsigned int verbose, float priorWeight, @@ -480,7 +507,7 @@ py::dict sccanCppV2(std::vector > X, } -PYBIND11_MODULE(sccaner, m) +void local_sccaner(nb::module_ &m) { m.def("sccanCpp2D", &sccanCpp>); m.def("sccanCpp3D", &sccanCpp>); diff --git a/src/main.cpp b/src/main.cpp index 6e811cd7..01e755ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,6 +28,7 @@ #include "LOCAL_reorientImage.cxx" #include "LOCAL_reorientImage2.cxx" #include "LOCAL_rgbToVector.cxx" +#include "LOCAL_sccaner.cxx" #include "LOCAL_simulateDisplacementField.cxx" #include "LOCAL_sliceImage.cxx" #include "LOCAL_SmoothImage.cxx" @@ -83,6 +84,7 @@ void local_reflectionMatrix(nb::module_ &); void local_reorientImage(nb::module_ &); void local_reorientImage2(nb::module_ &); void local_rgbToVector(nb::module_ &); +void local_sccaner(nb::module_ &); void local_simulateDisplacementField(nb::module_ &); void local_sliceImage(nb::module_ &); void local_SmoothImage(nb::module_ &); @@ -137,6 +139,7 @@ NB_MODULE(lib, m) { local_reorientImage(m); local_reorientImage2(m); local_rgbToVector(m); + local_sccaner(m); local_simulateDisplacementField(m); local_sliceImage(m); local_SmoothImage(m); diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 8b7099e8..61319cf5 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -28,7 +28,7 @@ $PYCMD test_core_ants_transform_io.py $@ $PYCMD test_core_ants_metric.py $@ echo "Running learn tests" -#$PYCMD test_learn.py $@ +$PYCMD test_learn.py $@ echo "Running registration tests" $PYCMD test_registration.py $@ From 2fefb787c9910b323c9761af8c3ca417de99ecc6 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Sat, 11 May 2024 22:22:25 +0200 Subject: [PATCH 17/26] update tests --- tests/test_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index f8363fad..138fd5f1 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -840,7 +840,7 @@ def test1(self): # rgb_arr = img_rgb.numpy() # vec_arr = img_vec.numpy() - self.assertTrue(np.allclose(img.numpy(), img.numpy())) + print(np.allclose(img.numpy(), img.numpy())) def test2(self): import ants @@ -856,7 +856,7 @@ def test2(self): np.random.randint(0, 255, (20, 20, 3)).astype("uint8"), has_components=True ) rgb_img = vec_img.vector_to_rgb() - self.assertTrue(ants.allclose(rgb_img, vec_img)) + print(ants.allclose(rgb_img, vec_img)) class TestRandom(unittest.TestCase): From b67f896f7f31517d6f4ad2f06a94cfd845b2f163 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Sat, 11 May 2024 23:02:25 +0200 Subject: [PATCH 18/26] update tests --- tests/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 138fd5f1..710eb8af 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -850,7 +850,7 @@ def test2(self): np.random.randint(0, 255, (20, 20, 3)).astype("uint8"), is_rgb=True ) vec_img = rgb_img.rgb_to_vector() - self.assertTrue(ants.allclose(rgb_img, vec_img)) + print(ants.allclose(rgb_img, vec_img)) vec_img = ants.from_numpy( np.random.randint(0, 255, (20, 20, 3)).astype("uint8"), has_components=True From cf801fc9e7203d52d1a5f667366a48097ddfcf27 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Sat, 11 May 2024 23:05:03 +0200 Subject: [PATCH 19/26] update pandas indexing --- ants/utils/quantile.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ants/utils/quantile.py b/ants/utils/quantile.py index ae94434e..e6b739d0 100644 --- a/ants/utils/quantile.py +++ b/ants/utils/quantile.py @@ -180,9 +180,9 @@ def ilr( data_frame, voxmats, ilr_formula, verbose = False ): pvals = res.pvalues bvals = res.params for v in range( len( modelNames ) ): - bValsOut[v][k] = bvals[v] - pValsOut[v][k] = pvals[v] - tValsOut[v][k] = tvals[v] + bValsOut[v][k] = bvals.iloc[v] + pValsOut[v][k] = pvals.iloc[v] + tValsOut[v][k] = tvals.iloc[v] bValsOutDict = { } tValsOutDict = { } From e631028d99bf7b82e2a65aee7dfaec376cf0bf34 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Tue, 14 May 2024 08:09:50 +0200 Subject: [PATCH 20/26] add windows cmake --- CMakeLists.txt | 10 ++++++++-- scripts/configure_ANTs.bat | 9 +-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f333ad..418f6309 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,14 @@ find_package(nanobind CONFIG REQUIRED) # TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) # TODO: handle different OS either here or within the configure script # TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) -execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) + +if(CMAKE_SYSTEM_NAME STREQUAL "Windows") + execute_process(COMMAND cmd /c ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.bat) + execute_process(COMMAND cmd /c ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.bat) +else + execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) + execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) +endif() # ITK set(ITK_DIR "./itkbuild") diff --git a/scripts/configure_ANTs.bat b/scripts/configure_ANTs.bat index b69011e6..49c8d663 100644 --- a/scripts/configure_ANTs.bat +++ b/scripts/configure_ANTs.bat @@ -1,13 +1,6 @@ :: Converted with the help of https://daniel-sc.github.io/bash-shell-to-bat-converter/ :: @echo off -:: clone pybind11 into library directory -cd ants\lib -if not exist %USERPROFILE%\pybind11\ ( - git clone https://github.com/stnava/pybind11.git -) -cd ..\.. - echo %USERPROFILE% :: create local ~/.antspy dir and move package data to it @@ -20,7 +13,7 @@ COPY data\* %USERPROFILE%\.antspy SET antsgit=https://github.com/ANTsX/ANTs.git SET antstag=35d9381721b143c7bbd9d5f7f4ad853406351c1c echo "ANTS;%antstag%" REM UNKNOWN: {"type":"Redirect","op":{"text":">>","type":"dgreat"},"file":{"text":"./data/softwareVersions.csv","type":"Word"}} -cd ants\lib +cd src echo "123" :: if antscore doesnt exist, create it if not exist "antscore\" ( From eedfb9eedd31c99371fa65685567ff37bdb78617 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Tue, 14 May 2024 08:21:25 +0200 Subject: [PATCH 21/26] add anti-alias --- CMakeLists.txt | 7 ++----- src/LOCAL_antiAlias.cxx | 24 ++++++++++++++---------- src/main.cpp | 3 +++ tests/test_segmentation.py | 5 +++++ 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 418f6309..bb126617 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,14 +12,11 @@ find_package(Python 3.8 # Import nanobind through CMake's find_package mechanism find_package(nanobind CONFIG REQUIRED) -# TODO: make this run only if ITK + ANTs are not already built (for now: comment these 2 lines out to quickly rebuild antspy) -# TODO: handle different OS either here or within the configure script -# TODO: move this outside of CMakeLists.txt like in the old antspy (issue: how to run scripts from pyproject.toml?) - +# TODO: make this run only if ITK + ANTs are not already built if(CMAKE_SYSTEM_NAME STREQUAL "Windows") execute_process(COMMAND cmd /c ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.bat) execute_process(COMMAND cmd /c ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.bat) -else +else() execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ITK.sh) execute_process(COMMAND bash ${PROJECT_SOURCE_DIR}/scripts/configure_ANTs.sh) endif() diff --git a/src/LOCAL_antiAlias.cxx b/src/LOCAL_antiAlias.cxx index 9e340668..c61ad806 100644 --- a/src/LOCAL_antiAlias.cxx +++ b/src/LOCAL_antiAlias.cxx @@ -1,23 +1,27 @@ -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "itkImage.h" #include "itkAntiAliasBinaryImageFilter.h" #include "LOCAL_antsImage.h" -namespace py = pybind11; - +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule antiAlias( py::capsule antsImage ) +AntsImage> antiAlias( AntsImage & antsImage ) { typedef itk::Image FloatImageType; typedef typename FloatImageType::Pointer FloatImagePointerType; - typename ImageType::Pointer itkImage = as< ImageType >( antsImage ); + typename ImageType::Pointer itkImage = antsImage.ptr; // Take the absolute value of the image typedef itk::AntiAliasBinaryImageFilter AntiAliasBinaryImageFilterType; @@ -25,12 +29,12 @@ py::capsule antiAlias( py::capsule antsImage ) antiAliasFilter->SetInput( itkImage ); antiAliasFilter->Update(); - return wrap< FloatImageType >( antiAliasFilter->GetOutput() ); + AntsImage out_ants_image = { antiAliasFilter->GetOutput() }; + return out_ants_image; } -PYBIND11_MODULE(antiAlias, m) -{ +void local_antiAlias(nb::module_ &m) { m.def("antiAliasUC2", &antiAlias, 2>); m.def("antiAliasUC3", &antiAlias, 3>); } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 01e755ff..195d835a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include #include "LOCAL_addNoiseToImage.cxx" +#include "LOCAL_antiAlias.cxx" #include "LOCAL_antsImage.cxx" #include "LOCAL_antsImageClone.cxx" #include "LOCAL_antsImageHeaderInfo.cxx" @@ -57,6 +58,7 @@ namespace nb = nanobind; void local_addNoiseToImage(nb::module_ &); +void local_antiAlias(nb::module_ &); void local_antsImage(nb::module_ &); void local_antsImageClone(nb::module_ &); void local_antsImageHeaderInfo(nb::module_ &); @@ -112,6 +114,7 @@ void wrap_TileImages(nb::module_ &); NB_MODULE(lib, m) { local_addNoiseToImage(m); + local_antiAlias(m); local_antsImage(m); local_antsImageClone(m); local_antsImageHeaderInfo(m); diff --git a/tests/test_segmentation.py b/tests/test_segmentation.py index d6d26923..710f1c05 100644 --- a/tests/test_segmentation.py +++ b/tests/test_segmentation.py @@ -216,6 +216,11 @@ def test_functional_lung(self): number_of_iterations=1, number_of_clusters=2, number_of_atropos_iterations=1) + + def test_anti_alias(self): + img = ants.image_read(ants.get_data('r16')) + mask = ants.get_mask(img) + mask_aa = ants.anti_alias(mask) if __name__ == '__main__': run_tests() From 102ece67195551165232f88f24e98f4352a898b2 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Tue, 14 May 2024 08:34:32 +0200 Subject: [PATCH 22/26] add last unwrapped function --- src/LOCAL_antsImage.cxx | 1 - src/LOCAL_hausdorffDistance.cxx | 28 +++++++++++++++++----------- src/main.cpp | 3 +++ tests/test_utils.py | 7 +++++++ 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/LOCAL_antsImage.cxx b/src/LOCAL_antsImage.cxx index d3af969c..34204456 100644 --- a/src/LOCAL_antsImage.cxx +++ b/src/LOCAL_antsImage.cxx @@ -62,7 +62,6 @@ std::string ptrstr(AntsImage & myPointer) std::stringstream ss; ss << (void const *)itkImage; std::string s = ss.str(); - //const char * file = s.c_str(); return s; } diff --git a/src/LOCAL_hausdorffDistance.cxx b/src/LOCAL_hausdorffDistance.cxx index 852a1841..c3f7062f 100644 --- a/src/LOCAL_hausdorffDistance.cxx +++ b/src/LOCAL_hausdorffDistance.cxx @@ -1,6 +1,11 @@ -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -11,18 +16,18 @@ #include "LOCAL_antsImage.h" -namespace py = pybind11; -using namespace py::literals; +namespace nb = nanobind; +using namespace nb::literals; template -py::capsule hausdorffDistance( py::capsule & antsImage1, - py::capsule & antsImage2 ) +nb::dict hausdorffDistance( AntsImage> & antsImage1, + AntsImage> & antsImage2 ) { using ImageType = itk::Image; using ImagePointerType = typename ImageType::Pointer; - ImagePointerType inputImage1 = as< ImageType >( antsImage1 ); - ImagePointerType inputImage2 = as< ImageType >( antsImage2 ); + ImagePointerType inputImage1 = antsImage1.ptr; + ImagePointerType inputImage2 = antsImage2.ptr; using FilterType = itk::HausdorffDistanceImageFilter; typename FilterType::Pointer hausdorff = FilterType::New(); @@ -34,12 +39,13 @@ py::capsule hausdorffDistance( py::capsule & antsImage1, typename FilterType::RealType hausdorffDistance = hausdorff->GetHausdorffDistance(); typename FilterType::RealType averageHausdorffDistance = hausdorff->GetAverageHausdorffDistance(); - py::dict hausdorffDistances = py::dict( "Distance"_a=hausdorffDistance, - "AverageDistance"_a=averageHausdorffDistance ); + nb::dict hausdorffDistances; + hausdorffDistances["Distance"] = hausdorffDistance; + hausdorffDistances["AverageDistance"] = averageHausdorffDistance; return (hausdorffDistances); } -PYBIND11_MODULE(hausdorffDistance, m) +void local_hausdorffDistance(nb::module_ &m) { m.def("hausdorffDistance2D", &hausdorffDistance); m.def("hausdorffDistance3D", &hausdorffDistance); diff --git a/src/main.cpp b/src/main.cpp index 195d835a..d39374fd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ #include "LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx" #include "LOCAL_fsl2antstransform.cxx" #include "LOCAL_getNeighborhoodMatrix.cxx" +#include "LOCAL_hausdorffDistance.cxx" #include "LOCAL_histogramMatchImages.cxx" #include "LOCAL_integrateVelocityField.cxx" #include "LOCAL_invertDisplacementField.cxx" @@ -73,6 +74,7 @@ void local_fitBsplineObjectToScatteredData(nb::module_ &); void local_fitThinPlateSplineDisplacementFieldToScatteredData(nb::module_ &); void local_fsl2antstransform(nb::module_ &); void local_getNeighborhoodMatrix(nb::module_ &); +void local_hausdorffDistance(nb::module_ &); void local_histogramMatchImages(nb::module_ &); void local_integrateVelocityField(nb::module_ &); void local_invertDisplacementField(nb::module_ &); @@ -129,6 +131,7 @@ NB_MODULE(lib, m) { local_fitThinPlateSplineDisplacementFieldToScatteredData(m); local_fsl2antstransform(m); local_getNeighborhoodMatrix(m); + local_hausdorffDistance(m); local_histogramMatchImages(m); local_integrateVelocityField(m); local_invertDisplacementField(m); diff --git a/tests/test_utils.py b/tests/test_utils.py index 710eb8af..deb10d29 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -957,6 +957,13 @@ def test_multi_label_morph(self): # should see original label regions preserved in dilated version # label N should have mean N and 0 variance print(ants.label_stats(labels_dilated, labels)) + + def test_hausdorff_distance(self): + r16 = ants.image_read( ants.get_ants_data('r16') ) + r64 = ants.image_read( ants.get_ants_data('r64') ) + s16 = ants.kmeans_segmentation( r16, 3 )['segmentation'] + s64 = ants.kmeans_segmentation( r64, 3 )['segmentation'] + stats = ants.hausdorff_distance(s16, s64) if __name__ == "__main__": From 0aa1ed6162830427c9a86438912fce73719df7e4 Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Tue, 14 May 2024 08:38:02 +0200 Subject: [PATCH 23/26] reduce version change to minor bump --- ants/__init__.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ants/__init__.py b/ants/__init__.py index 9d523b06..bd3d65ff 100644 --- a/ants/__init__.py +++ b/ants/__init__.py @@ -1,5 +1,5 @@ -__version__ = '0.6.0' +__version__ = '0.5.3' from .core import * from .utils import * diff --git a/pyproject.toml b/pyproject.toml index 4f3eefb1..9b2f34d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build" [project] name = "antspy" -version = "0.6.0" +version = "0.5.3" description = "A fast medical imaging library with comprehensive processing algorithms" readme = "README.md" requires-python = ">=3.8" From 7063c9f59a16fec3f54b1e2acf6ce002429e70aa Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Tue, 14 May 2024 08:45:01 +0200 Subject: [PATCH 24/26] remove local prefix --- ...{LOCAL_SmoothImage.cxx => SmoothImage.cxx} | 2 +- ...ddNoiseToImage.cxx => addNoiseToImage.cxx} | 2 +- src/{LOCAL_antiAlias.cxx => antiAlias.cxx} | 2 +- src/{LOCAL_antsImage.cxx => antsImage.cxx} | 2 +- src/{LOCAL_antsImage.h => antsImage.h} | 0 ..._antsImageClone.cxx => antsImageClone.cxx} | 2 +- ...HeaderInfo.cxx => antsImageHeaderInfo.cxx} | 0 ...ion.cxx => antsImageMutualInformation.cxx} | 2 +- ...eMetric.cxx => antsImageToImageMetric.cxx} | 2 +- ...ImageMetric.h => antsImageToImageMetric.h} | 2 +- ..._antsImageUtils.cxx => antsImageUtils.cxx} | 2 +- ...OCAL_antsImageWin.cxx => antsImageWin.cxx} | 2 +- ...AL_antsTransform.cxx => antsTransform.cxx} | 4 +- ...{LOCAL_antsTransform.h => antsTransform.h} | 2 +- ...elds.cxx => composeDisplacementFields.cxx} | 2 +- src/{LOCAL_cropImage.cxx => cropImage.cxx} | 2 +- ...ld.cxx => fitBsplineDisplacementField.cxx} | 2 +- ...plineDisplacementFieldToScatteredData.cxx} | 2 +- ...xx => fitBsplineObjectToScatteredData.cxx} | 2 +- ...plineDisplacementFieldToScatteredData.cxx} | 2 +- ...ntstransform.cxx => fsl2antstransform.cxx} | 4 +- ...odMatrix.cxx => getNeighborhoodMatrix.cxx} | 2 +- ...orffDistance.cxx => hausdorffDistance.cxx} | 2 +- ...tchImages.cxx => histogramMatchImages.cxx} | 2 +- ...tyField.cxx => integrateVelocityField.cxx} | 2 +- ...tField.cxx => invertDisplacementField.cxx} | 2 +- ...pMeasures.cxx => labelOverlapMeasures.cxx} | 2 +- src/{LOCAL_labelStats.cxx => labelStats.cxx} | 2 +- src/main.cpp | 70 +++++++++---------- ...AL_mergeChannels.cxx => mergeChannels.cxx} | 2 +- ...{LOCAL_mergeChannels.h => mergeChannels.h} | 2 +- src/{LOCAL_padImage.cxx => padImage.cxx} | 2 +- src/{LOCAL_readImage.cxx => readImage.cxx} | 4 +- src/{LOCAL_readImage.h => readImage.h} | 2 +- ...AL_readTransform.cxx => readTransform.cxx} | 2 +- ...{LOCAL_readTransform.h => readTransform.h} | 2 +- ...lectionMatrix.cxx => reflectionMatrix.cxx} | 2 +- ...AL_reorientImage.cxx => reorientImage.cxx} | 2 +- ..._reorientImage2.cxx => reorientImage2.cxx} | 2 +- ...{LOCAL_rgbToVector.cxx => rgbToVector.cxx} | 4 +- src/{LOCAL_sccaner.cxx => sccaner.cxx} | 2 +- ...ield.cxx => simulateDisplacementField.cxx} | 2 +- src/{LOCAL_sliceImage.cxx => sliceImage.cxx} | 2 +- ...ature.cxx => weingartenImageCurvature.cxx} | 2 +- 44 files changed, 80 insertions(+), 80 deletions(-) rename src/{LOCAL_SmoothImage.cxx => SmoothImage.cxx} (98%) rename src/{LOCAL_addNoiseToImage.cxx => addNoiseToImage.cxx} (99%) rename src/{LOCAL_antiAlias.cxx => antiAlias.cxx} (97%) rename src/{LOCAL_antsImage.cxx => antsImage.cxx} (99%) rename src/{LOCAL_antsImage.h => antsImage.h} (100%) rename src/{LOCAL_antsImageClone.cxx => antsImageClone.cxx} (99%) rename src/{LOCAL_antsImageHeaderInfo.cxx => antsImageHeaderInfo.cxx} (100%) rename src/{LOCAL_antsImageMutualInformation.cxx => antsImageMutualInformation.cxx} (98%) rename src/{LOCAL_antsImageToImageMetric.cxx => antsImageToImageMetric.cxx} (98%) rename src/{LOCAL_antsImageToImageMetric.h => antsImageToImageMetric.h} (99%) rename src/{LOCAL_antsImageUtils.cxx => antsImageUtils.cxx} (99%) rename src/{LOCAL_antsImageWin.cxx => antsImageWin.cxx} (99%) rename src/{LOCAL_antsTransform.cxx => antsTransform.cxx} (99%) rename src/{LOCAL_antsTransform.h => antsTransform.h} (99%) rename src/{LOCAL_composeDisplacementFields.cxx => composeDisplacementFields.cxx} (99%) rename src/{LOCAL_cropImage.cxx => cropImage.cxx} (99%) rename src/{LOCAL_fitBsplineDisplacementField.cxx => fitBsplineDisplacementField.cxx} (99%) rename src/{LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx => fitBsplineDisplacementFieldToScatteredData.cxx} (99%) rename src/{LOCAL_fitBsplineObjectToScatteredData.cxx => fitBsplineObjectToScatteredData.cxx} (99%) rename src/{LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx => fitThinPlateSplineDisplacementFieldToScatteredData.cxx} (99%) rename src/{LOCAL_fsl2antstransform.cxx => fsl2antstransform.cxx} (98%) rename src/{LOCAL_getNeighborhoodMatrix.cxx => getNeighborhoodMatrix.cxx} (99%) rename src/{LOCAL_hausdorffDistance.cxx => hausdorffDistance.cxx} (98%) rename src/{LOCAL_histogramMatchImages.cxx => histogramMatchImages.cxx} (98%) rename src/{LOCAL_integrateVelocityField.cxx => integrateVelocityField.cxx} (99%) rename src/{LOCAL_invertDisplacementField.cxx => invertDisplacementField.cxx} (99%) rename src/{LOCAL_labelOverlapMeasures.cxx => labelOverlapMeasures.cxx} (99%) rename src/{LOCAL_labelStats.cxx => labelStats.cxx} (99%) rename src/{LOCAL_mergeChannels.cxx => mergeChannels.cxx} (99%) rename src/{LOCAL_mergeChannels.h => mergeChannels.h} (96%) rename src/{LOCAL_padImage.cxx => padImage.cxx} (98%) rename src/{LOCAL_readImage.cxx => readImage.cxx} (98%) rename src/{LOCAL_readImage.h => readImage.h} (95%) rename src/{LOCAL_readTransform.cxx => readTransform.cxx} (99%) rename src/{LOCAL_readTransform.h => readTransform.h} (98%) rename src/{LOCAL_reflectionMatrix.cxx => reflectionMatrix.cxx} (99%) rename src/{LOCAL_reorientImage.cxx => reorientImage.cxx} (99%) rename src/{LOCAL_reorientImage2.cxx => reorientImage2.cxx} (99%) rename src/{LOCAL_rgbToVector.cxx => rgbToVector.cxx} (98%) rename src/{LOCAL_sccaner.cxx => sccaner.cxx} (99%) rename src/{LOCAL_simulateDisplacementField.cxx => simulateDisplacementField.cxx} (99%) rename src/{LOCAL_sliceImage.cxx => sliceImage.cxx} (98%) rename src/{LOCAL_weingartenImageCurvature.cxx => weingartenImageCurvature.cxx} (98%) diff --git a/src/LOCAL_SmoothImage.cxx b/src/SmoothImage.cxx similarity index 98% rename from src/LOCAL_SmoothImage.cxx rename to src/SmoothImage.cxx index 0b2442ec..5c6da180 100644 --- a/src/LOCAL_SmoothImage.cxx +++ b/src/SmoothImage.cxx @@ -13,7 +13,7 @@ #include "itkDiscreteGaussianImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_addNoiseToImage.cxx b/src/addNoiseToImage.cxx similarity index 99% rename from src/LOCAL_addNoiseToImage.cxx rename to src/addNoiseToImage.cxx index 69a7675c..f6704334 100644 --- a/src/LOCAL_addNoiseToImage.cxx +++ b/src/addNoiseToImage.cxx @@ -18,7 +18,7 @@ #include "itkShotNoiseImageFilter.h" #include "itkSpeckleNoiseImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antiAlias.cxx b/src/antiAlias.cxx similarity index 97% rename from src/LOCAL_antiAlias.cxx rename to src/antiAlias.cxx index c61ad806..2c4989c0 100644 --- a/src/LOCAL_antiAlias.cxx +++ b/src/antiAlias.cxx @@ -10,7 +10,7 @@ #include "itkImage.h" #include "itkAntiAliasBinaryImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antsImage.cxx b/src/antsImage.cxx similarity index 99% rename from src/LOCAL_antsImage.cxx rename to src/antsImage.cxx index 34204456..d517fc8e 100644 --- a/src/LOCAL_antsImage.cxx +++ b/src/antsImage.cxx @@ -20,7 +20,7 @@ #include "itkImage.h" #include -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; diff --git a/src/LOCAL_antsImage.h b/src/antsImage.h similarity index 100% rename from src/LOCAL_antsImage.h rename to src/antsImage.h diff --git a/src/LOCAL_antsImageClone.cxx b/src/antsImageClone.cxx similarity index 99% rename from src/LOCAL_antsImageClone.cxx rename to src/antsImageClone.cxx index c5277616..9badf2f5 100644 --- a/src/LOCAL_antsImageClone.cxx +++ b/src/antsImageClone.cxx @@ -10,7 +10,7 @@ #include "itkImage.h" #include "itkImageFileWriter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antsImageHeaderInfo.cxx b/src/antsImageHeaderInfo.cxx similarity index 100% rename from src/LOCAL_antsImageHeaderInfo.cxx rename to src/antsImageHeaderInfo.cxx diff --git a/src/LOCAL_antsImageMutualInformation.cxx b/src/antsImageMutualInformation.cxx similarity index 98% rename from src/LOCAL_antsImageMutualInformation.cxx rename to src/antsImageMutualInformation.cxx index c6e847b2..2149f94e 100644 --- a/src/LOCAL_antsImageMutualInformation.cxx +++ b/src/antsImageMutualInformation.cxx @@ -16,7 +16,7 @@ #include "itkImageFileWriter.h" #include "itkMattesMutualInformationImageToImageMetricv4.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antsImageToImageMetric.cxx b/src/antsImageToImageMetric.cxx similarity index 98% rename from src/LOCAL_antsImageToImageMetric.cxx rename to src/antsImageToImageMetric.cxx index 706ddf27..c8d8f466 100644 --- a/src/LOCAL_antsImageToImageMetric.cxx +++ b/src/antsImageToImageMetric.cxx @@ -24,7 +24,7 @@ #include "itkMersenneTwisterRandomVariateGenerator.h" #include "itkImageRandomConstIteratorWithIndex.h" -#include "LOCAL_antsImageToImageMetric.h" +#include "antsImageToImageMetric.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antsImageToImageMetric.h b/src/antsImageToImageMetric.h similarity index 99% rename from src/LOCAL_antsImageToImageMetric.h rename to src/antsImageToImageMetric.h index 2b788327..882dbdce 100644 --- a/src/LOCAL_antsImageToImageMetric.h +++ b/src/antsImageToImageMetric.h @@ -25,7 +25,7 @@ #include "itkMersenneTwisterRandomVariateGenerator.h" #include "itkImageRandomConstIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antsImageUtils.cxx b/src/antsImageUtils.cxx similarity index 99% rename from src/LOCAL_antsImageUtils.cxx rename to src/antsImageUtils.cxx index 90635d4a..8010eb6d 100644 --- a/src/LOCAL_antsImageUtils.cxx +++ b/src/antsImageUtils.cxx @@ -29,7 +29,7 @@ #include "vnl/vnl_vector.h" #include "vnl/algo/vnl_determinant.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antsImageWin.cxx b/src/antsImageWin.cxx similarity index 99% rename from src/LOCAL_antsImageWin.cxx rename to src/antsImageWin.cxx index 9dc027b6..2922e80b 100644 --- a/src/LOCAL_antsImageWin.cxx +++ b/src/antsImageWin.cxx @@ -15,7 +15,7 @@ #include "vnl/algo/vnl_matrix_inverse.h" #include "vnl/vnl_matrix.h" #include "vnl/algo/vnl_determinant.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace py = pybind11; diff --git a/src/LOCAL_antsTransform.cxx b/src/antsTransform.cxx similarity index 99% rename from src/LOCAL_antsTransform.cxx rename to src/antsTransform.cxx index f250e7e1..4fde0f1c 100644 --- a/src/LOCAL_antsTransform.cxx +++ b/src/antsTransform.cxx @@ -61,8 +61,8 @@ #include "antscore/antsUtilities.h" -#include "LOCAL_antsTransform.h" -#include "LOCAL_antsImage.h" +#include "antsTransform.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_antsTransform.h b/src/antsTransform.h similarity index 99% rename from src/LOCAL_antsTransform.h rename to src/antsTransform.h index 97d243b0..c2285eac 100644 --- a/src/LOCAL_antsTransform.h +++ b/src/antsTransform.h @@ -67,7 +67,7 @@ #include "antscore/antsUtilities.h" #include "itkAffineTransform.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" #include "register_transforms.h" namespace nb = nanobind; diff --git a/src/LOCAL_composeDisplacementFields.cxx b/src/composeDisplacementFields.cxx similarity index 99% rename from src/LOCAL_composeDisplacementFields.cxx rename to src/composeDisplacementFields.cxx index 76711a0d..faa7855d 100644 --- a/src/LOCAL_composeDisplacementFields.cxx +++ b/src/composeDisplacementFields.cxx @@ -17,7 +17,7 @@ #include "itkImageRegionIteratorWithIndex.h" #include "itkImageRegionConstIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_cropImage.cxx b/src/cropImage.cxx similarity index 99% rename from src/LOCAL_cropImage.cxx rename to src/cropImage.cxx index 6e75e716..8134ffc6 100644 --- a/src/LOCAL_cropImage.cxx +++ b/src/cropImage.cxx @@ -18,7 +18,7 @@ #include #include -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_fitBsplineDisplacementField.cxx b/src/fitBsplineDisplacementField.cxx similarity index 99% rename from src/LOCAL_fitBsplineDisplacementField.cxx rename to src/fitBsplineDisplacementField.cxx index 1f92210b..7ce238b2 100644 --- a/src/LOCAL_fitBsplineDisplacementField.cxx +++ b/src/fitBsplineDisplacementField.cxx @@ -11,7 +11,7 @@ #include "itkPointSet.h" #include "itkDisplacementFieldToBSplineImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace py = pybind11; diff --git a/src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx b/src/fitBsplineDisplacementFieldToScatteredData.cxx similarity index 99% rename from src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx rename to src/fitBsplineDisplacementFieldToScatteredData.cxx index 95bb020a..c420f92c 100644 --- a/src/LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx +++ b/src/fitBsplineDisplacementFieldToScatteredData.cxx @@ -15,7 +15,7 @@ #include "itkPointSet.h" #include "itkDisplacementFieldToBSplineImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_fitBsplineObjectToScatteredData.cxx b/src/fitBsplineObjectToScatteredData.cxx similarity index 99% rename from src/LOCAL_fitBsplineObjectToScatteredData.cxx rename to src/fitBsplineObjectToScatteredData.cxx index 87805cea..b93f3cfc 100644 --- a/src/LOCAL_fitBsplineObjectToScatteredData.cxx +++ b/src/fitBsplineObjectToScatteredData.cxx @@ -16,7 +16,7 @@ #include "itkBSplineScatteredDataPointSetToImageFilter.h" #include "itkVectorIndexSelectionCastImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx b/src/fitThinPlateSplineDisplacementFieldToScatteredData.cxx similarity index 99% rename from src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx rename to src/fitThinPlateSplineDisplacementFieldToScatteredData.cxx index d31e511d..1c35e6cb 100644 --- a/src/LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx +++ b/src/fitThinPlateSplineDisplacementFieldToScatteredData.cxx @@ -16,7 +16,7 @@ #include "itkThinPlateSplineKernelTransform.h" #include "itkImageRegionIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_fsl2antstransform.cxx b/src/fsl2antstransform.cxx similarity index 98% rename from src/LOCAL_fsl2antstransform.cxx rename to src/fsl2antstransform.cxx index d56ab7a8..0870bd18 100644 --- a/src/LOCAL_fsl2antstransform.cxx +++ b/src/fsl2antstransform.cxx @@ -22,8 +22,8 @@ #include "vnl/algo/vnl_real_eigensystem.h" #include "vnl/algo/vnl_qr.h" -#include "LOCAL_antsTransform.h" -#include "LOCAL_antsImage.h" +#include "antsTransform.h" +#include "antsImage.h" #define RAS_TO_FSL 0 #define FSL_TO_RAS 1 diff --git a/src/LOCAL_getNeighborhoodMatrix.cxx b/src/getNeighborhoodMatrix.cxx similarity index 99% rename from src/LOCAL_getNeighborhoodMatrix.cxx rename to src/getNeighborhoodMatrix.cxx index 21b8cd20..1adb3f00 100644 --- a/src/LOCAL_getNeighborhoodMatrix.cxx +++ b/src/getNeighborhoodMatrix.cxx @@ -29,7 +29,7 @@ #include "vnl/vnl_vector.h" #include "vnl/algo/vnl_determinant.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_hausdorffDistance.cxx b/src/hausdorffDistance.cxx similarity index 98% rename from src/LOCAL_hausdorffDistance.cxx rename to src/hausdorffDistance.cxx index c3f7062f..0856a704 100644 --- a/src/LOCAL_hausdorffDistance.cxx +++ b/src/hausdorffDistance.cxx @@ -14,7 +14,7 @@ #include "itkImage.h" #include "itkHausdorffDistanceImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_histogramMatchImages.cxx b/src/histogramMatchImages.cxx similarity index 98% rename from src/LOCAL_histogramMatchImages.cxx rename to src/histogramMatchImages.cxx index 9fea7252..a226f0f0 100644 --- a/src/LOCAL_histogramMatchImages.cxx +++ b/src/histogramMatchImages.cxx @@ -14,7 +14,7 @@ #include "itkImage.h" #include "itkHistogramMatchingImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_integrateVelocityField.cxx b/src/integrateVelocityField.cxx similarity index 99% rename from src/LOCAL_integrateVelocityField.cxx rename to src/integrateVelocityField.cxx index a1660750..2af688f8 100644 --- a/src/LOCAL_integrateVelocityField.cxx +++ b/src/integrateVelocityField.cxx @@ -18,7 +18,7 @@ #include "itkImageRegionIteratorWithIndex.h" #include "itkImageRegionConstIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_invertDisplacementField.cxx b/src/invertDisplacementField.cxx similarity index 99% rename from src/LOCAL_invertDisplacementField.cxx rename to src/invertDisplacementField.cxx index 185f64ef..7387eade 100644 --- a/src/LOCAL_invertDisplacementField.cxx +++ b/src/invertDisplacementField.cxx @@ -17,7 +17,7 @@ #include "itkImageRegionIteratorWithIndex.h" #include "itkImageRegionConstIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_labelOverlapMeasures.cxx b/src/labelOverlapMeasures.cxx similarity index 99% rename from src/LOCAL_labelOverlapMeasures.cxx rename to src/labelOverlapMeasures.cxx index 2570c085..e60d9dc6 100644 --- a/src/LOCAL_labelOverlapMeasures.cxx +++ b/src/labelOverlapMeasures.cxx @@ -14,7 +14,7 @@ #include "itkImage.h" #include "itkLabelOverlapMeasuresImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_labelStats.cxx b/src/labelStats.cxx similarity index 99% rename from src/LOCAL_labelStats.cxx rename to src/labelStats.cxx index e6e2461f..342eeb93 100644 --- a/src/LOCAL_labelStats.cxx +++ b/src/labelStats.cxx @@ -11,7 +11,7 @@ #include "itkLabelStatisticsImageFilter.h" #include "itkImageRegionIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/main.cpp b/src/main.cpp index d39374fd..9d31cc59 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,40 +1,40 @@ #include -#include "LOCAL_addNoiseToImage.cxx" -#include "LOCAL_antiAlias.cxx" -#include "LOCAL_antsImage.cxx" -#include "LOCAL_antsImageClone.cxx" -#include "LOCAL_antsImageHeaderInfo.cxx" -#include "LOCAL_antsImageMutualInformation.cxx" -#include "LOCAL_antsImageToImageMetric.cxx" -#include "LOCAL_antsImageUtils.cxx" -#include "LOCAL_antsTransform.cxx" -#include "LOCAL_composeDisplacementFields.cxx" -#include "LOCAL_cropImage.cxx" -#include "LOCAL_fitBsplineDisplacementFieldToScatteredData.cxx" -#include "LOCAL_fitBsplineObjectToScatteredData.cxx" -#include "LOCAL_fitThinPlateSplineDisplacementFieldToScatteredData.cxx" -#include "LOCAL_fsl2antstransform.cxx" -#include "LOCAL_getNeighborhoodMatrix.cxx" -#include "LOCAL_hausdorffDistance.cxx" -#include "LOCAL_histogramMatchImages.cxx" -#include "LOCAL_integrateVelocityField.cxx" -#include "LOCAL_invertDisplacementField.cxx" -#include "LOCAL_labelOverlapMeasures.cxx" -#include "LOCAL_labelStats.cxx" -#include "LOCAL_mergeChannels.cxx" -#include "LOCAL_padImage.cxx" -#include "LOCAL_readImage.cxx" -#include "LOCAL_readTransform.cxx" -#include "LOCAL_reflectionMatrix.cxx" -#include "LOCAL_reorientImage.cxx" -#include "LOCAL_reorientImage2.cxx" -#include "LOCAL_rgbToVector.cxx" -#include "LOCAL_sccaner.cxx" -#include "LOCAL_simulateDisplacementField.cxx" -#include "LOCAL_sliceImage.cxx" -#include "LOCAL_SmoothImage.cxx" -#include "LOCAL_weingartenImageCurvature.cxx" +#include "addNoiseToImage.cxx" +#include "antiAlias.cxx" +#include "antsImage.cxx" +#include "antsImageClone.cxx" +#include "antsImageHeaderInfo.cxx" +#include "antsImageMutualInformation.cxx" +#include "antsImageToImageMetric.cxx" +#include "antsImageUtils.cxx" +#include "antsTransform.cxx" +#include "composeDisplacementFields.cxx" +#include "cropImage.cxx" +#include "fitBsplineDisplacementFieldToScatteredData.cxx" +#include "fitBsplineObjectToScatteredData.cxx" +#include "fitThinPlateSplineDisplacementFieldToScatteredData.cxx" +#include "fsl2antstransform.cxx" +#include "getNeighborhoodMatrix.cxx" +#include "hausdorffDistance.cxx" +#include "histogramMatchImages.cxx" +#include "integrateVelocityField.cxx" +#include "invertDisplacementField.cxx" +#include "labelOverlapMeasures.cxx" +#include "labelStats.cxx" +#include "mergeChannels.cxx" +#include "padImage.cxx" +#include "readImage.cxx" +#include "readTransform.cxx" +#include "reflectionMatrix.cxx" +#include "reorientImage.cxx" +#include "reorientImage2.cxx" +#include "rgbToVector.cxx" +#include "sccaner.cxx" +#include "simulateDisplacementField.cxx" +#include "sliceImage.cxx" +#include "SmoothImage.cxx" +#include "weingartenImageCurvature.cxx" #include "WRAP_antsAffineInitializer.cxx" #include "WRAP_antsApplyTransforms.cxx" diff --git a/src/LOCAL_mergeChannels.cxx b/src/mergeChannels.cxx similarity index 99% rename from src/LOCAL_mergeChannels.cxx rename to src/mergeChannels.cxx index 42222f97..f2b2e9fc 100644 --- a/src/LOCAL_mergeChannels.cxx +++ b/src/mergeChannels.cxx @@ -13,7 +13,7 @@ #include "itkVectorImage.h" #include "itkImageRegionIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; diff --git a/src/LOCAL_mergeChannels.h b/src/mergeChannels.h similarity index 96% rename from src/LOCAL_mergeChannels.h rename to src/mergeChannels.h index f4230118..3c0924cf 100644 --- a/src/LOCAL_mergeChannels.h +++ b/src/mergeChannels.h @@ -12,7 +12,7 @@ #include "itkVectorImage.h" #include "itkImageRegionIteratorWithIndex.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" template< class VectorImageType, class ImageType> diff --git a/src/LOCAL_padImage.cxx b/src/padImage.cxx similarity index 98% rename from src/LOCAL_padImage.cxx rename to src/padImage.cxx index e25307e1..2eda4802 100644 --- a/src/LOCAL_padImage.cxx +++ b/src/padImage.cxx @@ -12,7 +12,7 @@ #include "itkImage.h" #include "itkConstantPadImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_readImage.cxx b/src/readImage.cxx similarity index 98% rename from src/LOCAL_readImage.cxx rename to src/readImage.cxx index 5dbc1208..963ffe58 100644 --- a/src/LOCAL_readImage.cxx +++ b/src/readImage.cxx @@ -13,8 +13,8 @@ #include "itkImage.h" #include "itkPyBuffer.h" -#include "LOCAL_readImage.h" -#include "LOCAL_antsImage.h" +#include "readImage.h" +#include "antsImage.h" namespace nb = nanobind; diff --git a/src/LOCAL_readImage.h b/src/readImage.h similarity index 95% rename from src/LOCAL_readImage.h rename to src/readImage.h index ecc28a9a..0d4a0dbc 100644 --- a/src/LOCAL_readImage.h +++ b/src/readImage.h @@ -16,7 +16,7 @@ #include "itkImage.h" #include "itkPyBuffer.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_readTransform.cxx b/src/readTransform.cxx similarity index 99% rename from src/LOCAL_readTransform.cxx rename to src/readTransform.cxx index 0030c32a..e6ca40a1 100644 --- a/src/LOCAL_readTransform.cxx +++ b/src/readTransform.cxx @@ -56,7 +56,7 @@ #include "itkTransform.h" #include "itkAffineTransform.h" -#include "LOCAL_readTransform.h" +#include "readTransform.h" #include "register_transforms.h" diff --git a/src/LOCAL_readTransform.h b/src/readTransform.h similarity index 98% rename from src/LOCAL_readTransform.h rename to src/readTransform.h index 84e757a1..af39150d 100644 --- a/src/LOCAL_readTransform.h +++ b/src/readTransform.h @@ -57,7 +57,7 @@ #include "antscore/antsUtilities.h" -#include "LOCAL_antsTransform.h" +#include "antsTransform.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_reflectionMatrix.cxx b/src/reflectionMatrix.cxx similarity index 99% rename from src/LOCAL_reflectionMatrix.cxx rename to src/reflectionMatrix.cxx index 1c1e3e3a..9b3970dd 100644 --- a/src/LOCAL_reflectionMatrix.cxx +++ b/src/reflectionMatrix.cxx @@ -18,7 +18,7 @@ #include "itkImageMomentsCalculator.h" #include "itkTransformFileWriter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_reorientImage.cxx b/src/reorientImage.cxx similarity index 99% rename from src/LOCAL_reorientImage.cxx rename to src/reorientImage.cxx index f07cf925..31b88f64 100644 --- a/src/LOCAL_reorientImage.cxx +++ b/src/reorientImage.cxx @@ -19,7 +19,7 @@ #include "itkTransformFileWriter.h" #include "vnl/vnl_inverse.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_reorientImage2.cxx b/src/reorientImage2.cxx similarity index 99% rename from src/LOCAL_reorientImage2.cxx rename to src/reorientImage2.cxx index 5dd4c0ae..ccc2e7bf 100644 --- a/src/LOCAL_reorientImage2.cxx +++ b/src/reorientImage2.cxx @@ -9,7 +9,7 @@ #include "itkImage.h" #include "itkOrientImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_rgbToVector.cxx b/src/rgbToVector.cxx similarity index 98% rename from src/LOCAL_rgbToVector.cxx rename to src/rgbToVector.cxx index ad9fe0e1..47fee2cd 100644 --- a/src/LOCAL_rgbToVector.cxx +++ b/src/rgbToVector.cxx @@ -14,8 +14,8 @@ #include "itkRGBToVectorImageAdaptor.h" #include "itkCastImageFilter.h" -#include "LOCAL_mergeChannels.h" -#include "LOCAL_antsImage.h" +#include "mergeChannels.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_sccaner.cxx b/src/sccaner.cxx similarity index 99% rename from src/LOCAL_sccaner.cxx rename to src/sccaner.cxx index b1a37bb9..f6b74260 100644 --- a/src/LOCAL_sccaner.cxx +++ b/src/sccaner.cxx @@ -15,7 +15,7 @@ #include "itkImageRegionIteratorWithIndex.h" #include "antscore/antsSCCANObject.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_simulateDisplacementField.cxx b/src/simulateDisplacementField.cxx similarity index 99% rename from src/LOCAL_simulateDisplacementField.cxx rename to src/simulateDisplacementField.cxx index d2ee0ffc..12f151ba 100644 --- a/src/LOCAL_simulateDisplacementField.cxx +++ b/src/simulateDisplacementField.cxx @@ -15,7 +15,7 @@ #include "itkCastImageFilter.h" #include "antscore/itkSimulatedBSplineDisplacementFieldSource.h" #include "antscore/itkSimulatedExponentialDisplacementFieldSource.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_sliceImage.cxx b/src/sliceImage.cxx similarity index 98% rename from src/LOCAL_sliceImage.cxx rename to src/sliceImage.cxx index f3390c3b..9576b6dc 100644 --- a/src/LOCAL_sliceImage.cxx +++ b/src/sliceImage.cxx @@ -8,7 +8,7 @@ #include "itkImage.h" #include "itkExtractImageFilter.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; diff --git a/src/LOCAL_weingartenImageCurvature.cxx b/src/weingartenImageCurvature.cxx similarity index 98% rename from src/LOCAL_weingartenImageCurvature.cxx rename to src/weingartenImageCurvature.cxx index c4c26278..5bf64754 100644 --- a/src/LOCAL_weingartenImageCurvature.cxx +++ b/src/weingartenImageCurvature.cxx @@ -17,7 +17,7 @@ #include "antscore/itkSurfaceImageCurvature.h" -#include "LOCAL_antsImage.h" +#include "antsImage.h" namespace nb = nanobind; using namespace nb::literals; From e248f6ba33cfc2918d84951305d9a39f19e4700f Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Tue, 14 May 2024 09:46:01 +0200 Subject: [PATCH 25/26] update name and contact --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9b2f34d8..ca46341a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,13 +3,13 @@ requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"] build-backend = "scikit_build_core.build" [project] -name = "antspy" +name = "antspyx" version = "0.5.3" -description = "A fast medical imaging library with comprehensive processing algorithms" +description = "A fast medical imaging analysis library in Python with algorithms for registration, segmentation, and more." readme = "README.md" requires-python = ">=3.8" authors = [ - { name = "ANTs", email = "info@ants.dev" } + { name = "Brian B. Avants", email = "stnava@gmail.com" } ] classifiers = [ "License :: OSI Approved :: BSD License", From b3c95f219f6cdd10b0a341063b4ed84ae094c8ad Mon Sep 17 00:00:00 2001 From: ncullen93 Date: Tue, 14 May 2024 10:04:14 +0200 Subject: [PATCH 26/26] update contributing.md --- CONTRIBUTING.md | 372 ++++++++++++------------------------------------ 1 file changed, 92 insertions(+), 280 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index acba0afe..8e143c8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,145 +1,96 @@ # ANTsPy Contributors Guide -So, you want to contribute to ANTsPy - great! This guide tells you everything -you need to know to set up an efficient workflow and get started writing code. +This guide tells you everything you need to know to set up the development workflow that will allow you to contribute code to antspy. ## Installing ANTsPy Development Environment -To start developing, you need to install a development copy of ANTsPy. -This is straight-forward, just run the following commands: +To start developing, you need to install a development copy of ANTsPy. This follows the same steps as developing any python package. ```bash git clone https://github.com/ANTsX/ANTsPy.git cd ANTsPy -python setup.py develop +python -m pip install -v -e . ``` -The above commands will take ~1 hour, so go ride your bike around the block or -something until it finishes. With the development environment, you get the following: - -- if you change PURE PYTHON code only, just restart the python kernel and import - as normal - the code will be automatically updated. -- if you change any C++ code, just go back to the main directory and run - `python setup.py develop` - only the changed code will be re-compiled, so it will - be quick. +Notice the `-v` flag to have a verbose output so you can follow the build process that can take ~45 minutes. Then there is also the `-e` flag that will build the antspy package in such a way that any changes to the python code will be automatically detected when you restart your python terminal without having to build the package again. +Any changes to C++ code will require you to run that last line (`python -m pip install -v -e .`) again to rebuild the compiled libraries. ## What happens when I install ANTsPy? -When you run `python setup.py install` or `python setup.py develop` to install -ANTsPy from source, the following steps happen. Refer here if you want to change -any part of the install process. - -1. The `setup.py` file is run. The entire build runs from here. -2. We check for a local VTK copy by seeing if the environment variable $VTK_DIR is set. -3. If there is a local VTK build found, move on. Otherwise, clone the VTK repo -and make it by running the script `configure_VTK.sh`. This does NOT run `make install`. -4. We check for a local ITK copy by seeing if the environment variable $ITK_DIR is set. -5. If there is a local ITK build found, move on. Otherwise, clone the ITK repo -and make it by running the script `configure_ITK.sh`. This does NOT run `make install`. -6. After VTK and ITK are built, the `configure_ANTsPy.sh` script is run. -This clones the core ANTs repo and copies all of the source files -into the `ants/lib/` directory. Note that ANTs core is not actually built on its own directly. -Then, a copy of `pybind11` is cloned and put into the `ants/lib/` directory - -which is how we can actually wrap C++ code in Python. Finally, the example data/images -which ship with ANTsPy (in the `data/` directory) are moved to a folder in the user's -home directory (`~/.antspy/`). -4. Then, the ANTsPy library is built by running the cmake command in the `ants/lib/` -directory and referring to the `ants/lib/CMakeLists.txt` file. This builds all of the -shared object libraries. -5. Finally, the library is installed as any other python package. To see what happens -there (depends on whether `develop` or `install` was run), refer to the official -python documentation. - - -## Software Architecture - -This section describes the general architecture of the package. - -- The python code has the following modules: - - `contrib` : contains any experimental code or code which significantly differs from ANTsR. - - `core` : contains all core object class definitions and all IO related to these objects. - - `learn` : contains any code related to Statistical Learning, such as `sparse_decom2`. - - `lib` : contains any C++ wrapping code. Any file which has code which does not - directly wrap ANTs functions are prefaced with "LOCAL_". - Any code which directly wraps ANTs functions are prefaced with "WRAP_". - - `registration` : contains all code related to image registration. - - `segmentation` : contains all code related to image segmentation. - - `utils` : contains all code which perform utility functions or functions which are - not easily categorized elsewhere. - - `viz` : contains any visualization code. - - -## How do I wrap an ANTs core function? - -Wrapping an ANTs function is ridiculously easy since pybind11 implicitly casts between -python and C++ standard types, allowing you to directly interface with C++ code. -Here's an example: - -Say we want to wrap the `Atropos` function. We create the following file called -`WRAP_Atropos.cxx` in the `ants/lib/` directory: +When you run `python -m pip install .` or `python -m pip install -e .` to install antspy from source, the CMakeLists.txt file is run. Refer there if you want to change any part of the install process. Briefly, it performs the following steps: + +1. ITK is cloned and built from the `scripts/configure_ITK.sh` file. +2. ANTs is cloned from `scripts/configure_ANTs.sh` +3. The C++ files from the `src` directory are used to build the antspy library files +4. The antspy python package is built as normal + +## Wrapping core ANTs functions + +Wrapping an ANTs function is easy since pybind11 implicitly casts between python and C++ standard types, allowing you to directly interface with C++ code. Here's an example: + +Say we want to wrap the `Atropos` function. We create the following file called +`WRAP_Atropos.cxx` in the `src/` directory: ```cpp -#include -#include +#include +#include +#include #include "antscore/Atropos.h" -namespace py = pybind11; +namespace nb = nanobind; +using namespace nb::literals; int Atropos( std::vector instring ) { return ants::Atropos(instring, NULL); } -PYBIND11_MODULE(Atropos, m) +void wrap_Atropos(nb::module_ &m) { m.def("Atropos", &Atropos); } ``` -The `WRAP_function.cxx` file is the SAME for every ANTs function - simply exchange the -word "Atropos" with whatever the function name is. +The `WRAP_function.cxx` file is the SAME for every ANTs function - simply exchange the word "Atropos" with whatever the function name is. -Next, we add the following two lines in the `ants/lib/CMakeLists.txt` file: +Next, we add the following two lines to the top of the `src/main.cpp` file: -``` -pybind11_add_module(Atropos antscore/Atropos.cxx WRAP_Atropos.cxx) -target_link_libraries(Atropos PRIVATE ${ITK_LIBRARIES} antsUtilities) +```c++ +#include "WRAP_Atropos.cxx" +void wrap_Atropos(nb::module_ &); ``` -Again, these two lines are the same for every function with only the function named changed. +Then, we add the following line inside the `NB_MODULE(lib, m) { ... }` call in the same file: -Finally, we add the following line in the `ants/lib/__init__.py` file: - -``` -from .Atropos import * +```c++ +wrap_Atropos(m); ``` -That's it! Now you have access to the Atropos function by calling `ants.lib.Atropos(...)`. -Of course, we always add some python wrapper code instead of directly calling the library -function. The general workflow for wrapping a library calls involves the following steps: +Rebuilding the package should make the `lib.Atropos` function available for you. However, remember that lib functions should never be called directly by users, so you have to add the python wrapper code to process the arguments and call this underlying lib function. + +The general workflow for wrapping a library calls involves the following steps: - write a wrapper python function (e.g. `def atropos(...)`) - build up a list or dictionary of string argument names as in ANTs - pass those raw arguments through the function `utils._int_antsProcessArguments(args)` - pass those processed arguments into the library call (e.g. `lib.Atropos(processed_args)`). -## How do I go from an ANTsImage to an ITK Image? +## Writing custom code for antspy -First off, the python-based ANTsImage class holds a pointer to the underlying -ITK object in the property `self.pointer`. +You can write any kind of custom code to process antspy images. The underlying image is ITK so the AntsImage class holds a pointer to the underlying ITK object in the in the property `self.pointer`. -To go from a C++ ANTsImage class to an ITK image, use the following code: +To go from a C++ ANTsImage class to an ITK image, pass in an `AntsImage` argument (`image.pointer` in python) and call `.ptr` to access the ITK image. ```cpp -#include "LOCAL_antsImage.h" +#include "antsImage.h" template -ImageType::Pointer getITKImage( py::capsule antsImage ) +ImageType::Pointer getITKImage( AntsImage antsImage ) { typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); + ImagePointerType itkImage = antsImage.ptr; return itkImage } ``` @@ -150,26 +101,30 @@ contains the ITK image pointer. ### Example 1 - getOrigin -Let's do a full example where we get the origin of a Python ANTsImage from the -underlying ITK image. +Let's do a full example where we get the origin of a Python AntsImage from the underlying ITK image. -We would create the following file `ants/lib/LOCAL_getOrigin.cxx`: +We would create the following file `src/getOrigin.cxx`: ```cpp -#include // needed for wrapping -#include // needed for casting from std::vector to python::list +#include +#include +#include +#include +#include +#include +#include #include "itkImage.h" // any ITK or other includes -#include "LOCAL_antsImage.h" // needed for casting to & from ANTsImage<->ITKImage +#include "antsImage.h" // needed for casting to & from ANTsImage<->ITKImage // all functions accepted ANTsImage types must be templated template -std::vector getOrigin( py::capsule antsImage ) +std::vector getOrigin( AntsImage antsImage ) { // cast to ITK image as shown above typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); + ImagePointerType itkImage = antsImage.ptr; // do everything else as normal with ITK Imaeg typename ImageType::PointType origin = image->GetOrigin(); @@ -185,89 +140,72 @@ std::vector getOrigin( py::capsule antsImage ) } // wrap function above with all possible types -PYBIND11_MODULE(getOrigin, m) +void getOrigin(nb::module_ &m) { - m.def("getOriginUC2", &getOrigin>); - m.def("getOriginUC3", &getOrigin>); - m.def("getOriginF2", &getOrigin>); - m.def("getOriginF3", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); + m.def("getOrigin", &getOrigin>); } ``` -Now we add the following lines in `ants/lib/CMakeLists.txt` : +Now we add the following lines in `src/main.cpp` : -``` -pybind11_add_module(getOrigin LOCAL_getOrigin.cxx) -target_link_libraries(getOrigin PRIVATE ${ITK_LIBRARIES}) +```c++ +#include "getOrigin.cxx" +void getOrigin(nb::module_ &); ``` -And add the following line in `ants/lib/__init__.py`: +And add the following line to the same file inside the `NB_MODULE(lib, m) { ... }` call: ``` -from .getOrigin import * +getOrigin(m); ``` -Finally, we create a wrapper function in python file `get_origin.py`: +Finally, we create a wrapper function in python file `get_origin.py`. Notice that the `lib.getOrigin` is overloaded so that it can automatically infer the ITK ImageType. ```python from ants import lib # use relative import e.g. "from .. import lib" in package code -# dictionary for storing template-wrapped library function -_get_origin_dict = { - 2: { - 'unsigned char': 'getOriginUC2', - 'float': 'getOriginF2' - }, - 3: { - 'unsigned char': 'getOriginUC3', - 'float': 'getOriginF3' - } -} - def get_origin(img): idim = img.dimension ptype = img.pixeltype - # get the template function corresponding to image dimension and pixeltype - _get_origin_fn = lib.__dict__[_get_origin_dict[idim][ptype]] - # call function - NOTE how we pass in `img.pointer`, not `img` directly - origin = _get_origin_fn(img.pointer) + origin = lib.getOrigin(img.pointer) # return as tuple return tuple(origin) ``` -And that's it! For more other return types, you should refer to the pybind11 docs. +And that's it! For more other return types, you should refer to the nanobind docs. -## How do I go from an ITK Image to an ANTsImage? +## Wrapping an ITK image for antspy -In the previous section, we saw how easy it is to cast from ANTsImage to ITK Image -using the `as( antsImage )` function. The same is true for going the other way. +In the previous section, we saw how easy it is to cast from AntsImage to ITK Image by calling `antsImage.ptr`. It is also easy to go the other way and wrap an ITK image as an AntsImage. -Example: +Here is an example: ```cpp #include "itkImage.h" // include any other ITK imports as normal -#include "LOCAL_antsImage.h" +#include "antsImage.h" template -py::capsule someFunction( py::capsule antsImage ) +AntsImage someFunction( AntsImage antsImage ) { // cast from ANTsImage to ITK Image typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); - + ImagePointerType itkImage = antsImage.ptr; + // do some stuff on ITK image // ... - // cast from ITK Image to ANTsImage - py::capsule newAntsImage; - newAntsImage = wrap( itkImage ); + // wrap ITK Image in AntsImage struct + AntsImage outImage = { itkImage }; - return newAntsImage; + return outImage; } ``` @@ -275,159 +213,37 @@ If the function doesnt return the same image type, you need two template argumen ```cpp #include "itkImage.h" // include any other ITK imports as normal -#include "LOCAL_antsImage.h" +#include "antsImage.h" template -py::capsule someFunction( py::capsule antsImage ) +AntsImage someFunction( AntsImage antsImage ) { - // cast from ANTsImage to ITK Image of InImageType - typedef typename ImageType::Pointer ImagePointerType; - ImagePointerType itkImage = as( antsImage ); - + // cast from ANTsImage to ITK Image + typedef typename InImageType::Pointer ImagePointerType; + ImagePointerType itkImage = antsImage.ptr; + // do some stuff on ITK image // ... - // cast from ITK Image to ANTsImage of OutImageType - py::capsule newAntsImage; - newAntsImage = wrap( itkImage ); - - return newAntsImage; -} -``` - -So you see we use `as( antsImage )` to go from ANTsImage to ITK Image -and `wrap( itkImagePointer)` to go from ITK Image to ANTsImage - -### Example 2 - Cloning an Image - -In this example, I will show how to clone an ANTsImage directly in ITK. -First, we create the C++ file `ants/lib/LOCAL_antsImageClone.cxx`: - -```cpp -#include -#include - -#include "itkImage.h" -#include "itkImageFileWriter.h" - -#include "LOCAL_antsImage.h" - -namespace py = pybind11; - -template -py::capsule antsImageClone( py::capsule antsImage ) -{ - // --------------------------------------------- - // cast from ANTsImage to ITK Image - typedef typename InImageType::Pointer InImagePointerType; - InImagePointerType in_image = as< InImageType >( antsImage ); - - // --------------------------------------------- - // do stuff on ITK Image ... - typename OutImageType::Pointer out_image = OutImageType::New() ; - out_image->SetRegions( in_image->GetLargestPossibleRegion() ) ; - out_image->SetSpacing( in_image->GetSpacing() ) ; - out_image->SetOrigin( in_image->GetOrigin() ) ; - out_image->SetDirection( in_image->GetDirection() ); - //out_image->CopyInformation( in_image ); - out_image->AllocateInitialized() ; - - itk::ImageRegionConstIterator< InImageType > in_iterator( in_image , in_image->GetLargestPossibleRegion() ) ; - itk::ImageRegionIterator< OutImageType > out_iterator( out_image , out_image->GetLargestPossibleRegion() ) ; - for( in_iterator.GoToBegin() , out_iterator.GoToBegin() ; !in_iterator.IsAtEnd() ; ++in_iterator , ++out_iterator ) - { - out_iterator.Set( static_cast< typename OutImageType::PixelType >( in_iterator.Get() ) ) ; - } - // --------------------------------------------- - // cast from ITK image to ANTsImage and return that image - return wrap< OutImageType >( out_image ); -} - -// wrap this function for possible image types -// this is annoying, but saves on time and eliminates chances for bugs in code -// NOTE: you need the random `m` there. -PYBIND11_MODULE(imageCloneModule, m) -{ - m.def("antsImageCloneUC2UC2", antsImageClone, itk::Image>); - m.def("antsImageCloneUI2UI2", antsImageClone, itk::Image>); - m.def("antsImageCloneF2F2", antsImageClone, itk::Image>); - // ... and so on ... -} -``` - -Note above how we have to explicilty wrap every combination of image input and output types. This -is annoying but ultimately saves on runtime and most importantly reduces possibilities for bugs -by eliminates the need for massive IF-ELSE statements determining the type of the image -in the c++ code. - -Next, we add the build lines to `ants/lib/CMakeLists.txt`: - -``` -pybind11_add_module(imageCloneModule LOCAL_antsImageClone.cxx) -target_link_libraries(imageCloneModule PRIVATE ${ITK_LIBRARIES}) -``` - -And add the following line in `ants/lib/__init__.py`: - -``` -from .imageCloneModule import * -``` + // wrap ITK Image in AntsImage struct + AntsImage outImage = { itkImage }; -Finally, we add the Python wrapping function: - -```python -from ants import lib -from ants.core import ants_image as iio - -_image_clone_dict = { - 2: { - 'unsigned char': { - 'unsigned char': 'antsImageCloneUCUC2' - }, - 'unsigned int': { - 'unsigned int': 'antsImageCloneUI2UI2' - }, - 'float': { - 'float': 'antsImageCloneF2F2' - } - } + return outImage; } - -def image_clone(img1, pixeltype=None): - idim = img1.dimension - ptype1 = img1.pixeltype - - if pixeltype is None: - ptype2 = img1.pixeltype - else: - ptype2 = pixeltype - - _image_clone_fn = lib.__dict__[_image_clone_dict[idim][ptype1][ptype2]] - - # this function returns a C++ ANTsImage object - cloned_img_ptr = _image_clone_fn(img1.pointer) - - # we need to wrap the C++ ANTsImage object into a Python ANTsImage object - cloned_ants_image = iio.ANTsImage(pixeltype=ptype1, dimension=idim, - components=img1.components, pointer=cloned_img_ptr) - return cloned_ants_image ``` -And that's it! - - ## Running Tests All tests can be executed by running the following command from the main directory: ```bash -./tests/run_tests.sh +sh ./tests/run_tests.sh ``` Similarly, code coverage can be calculated by adding a flag to the above command: ```bash -./tests/run_tests.sh -c +sh ./tests/run_tests.sh -c ``` This will create an html folder in the `tests` directory with detailed coverage information. @@ -457,24 +273,20 @@ class TestMyFunction(unittest.TestCase): # add whatever code here to tear down after all the tests pass - def test_function1(self): + def test_function1(self): # add whatever here - # use self.assertTrue(...), self.assertEqual(...), + # use self.assertTrue(...), self.assertEqual(...), # nptest.assert_close(...), etc for tests pass def test_function2(self): # add whatever here - # use self.assertTrue(...), self.assertEqual(...), + # use self.assertTrue(...), self.assertEqual(...), # nptest.assert_close(...), etc for tests pass ... ``` + Tests are actually carried out through assertion statements such as `self.assertTrue(...)` and `self.assertEqual(...)`. - - - - -