From 3b9b43fbab4d9b9968e267eeb7df82ef9b116271 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 22 Sep 2026 09:29:12 -0500 Subject: [PATCH 1/3] COMP: Build the executables and wrapping outside an ITK source tree The src/ executables include the module's own headers, which only reach the compiler when the module is built inside an ITK source tree. Name the include directory so they also build against an installed ITK. The example programs enable ITK's IO factory register manager, which references every IO module the ITK build enables, so they must link ITK_LIBRARIES rather than only the module's own dependencies. The wrapping instantiated VesselEnhancingDiffusion3DImageFilter as an image filter with two image types; the template takes a pixel type and a dimension. Wrap it over the scalar pixel types in three dimensions. SWIG runs with -Werror, so a filter whose superclass is not wrapped fails with warning 401. DescoteauxSheetness and FrangiTubularness derive from UnaryFunctorImageFilter; wrap them POINTER_WITH_SUPERCLASS like LocalStructureImageFilter and ITK's own UnaryFunctor subclasses. itkSatoVesselnessFeatureGenerator.wrap wrapped the derived Sigmoid class instead of SatoVesselnessFeatureGenerator, so no interface existed for the base. Wrap the right class, and list base classes first in WRAPPER_SUBMODULE_ORDER so each derived interface imports a wrapped base. The sheetness, tubularness, and local-structure functors index their input pixel, so wrap them over covariant-vector images (the eigenvalue image type ITK wraps) instead of scalar images. RegionCompetitionImageFilter indexes an array with its output pixel, so wrap integer outputs only. The Sato vesselness generators and LesionSegmentationImageFilter8 embed VesselEnhancingDiffusion3DImageFilter, so wrap them in three dimensions only; the segmentation modules produce float images, so the lesion filter's output is real. --- src/CMakeLists.txt | 21 ++++++++++--------- wrapping/CMakeLists.txt | 16 +++++++------- .../itkDescoteauxSheetnessImageFilter.wrap | 4 ++-- wrapping/itkFrangiTubularnessImageFilter.wrap | 4 ++-- .../itkLesionSegmentationImageFilter8.wrap | 2 +- wrapping/itkLocalStructureImageFilter.wrap | 2 +- wrapping/itkRegionCompetitionImageFilter.wrap | 2 +- .../itkSatoVesselnessFeatureGenerator.wrap | 11 +++++----- ...SatoVesselnessSigmoidFeatureGenerator.wrap | 11 +++++----- ...VesselEnhancingDiffusion3DImageFilter.wrap | 11 +++++++--- 10 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 35315832..3de6d09e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,30 +1,31 @@ include_directories("${LesionSizingToolkit_SOURCE_DIR}/src") # to include itkIncludeRequiredIOFactories.h +include_directories("${LesionSizingToolkit_SOURCE_DIR}/include") add_executable(itkCannyEdgeDetectionImageFilter1 itkCannyEdgeDetectionImageFilter1.cxx ) -target_link_libraries(itkCannyEdgeDetectionImageFilter1 ITK::LesionSizingToolkitModule) +target_link_libraries(itkCannyEdgeDetectionImageFilter1 ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkCannyEdgeDetectionImageFilter2 itkCannyEdgeDetectionImageFilter2.cxx ) -target_link_libraries(itkCannyEdgeDetectionImageFilter2 ITK::LesionSizingToolkitModule) +target_link_libraries(itkCannyEdgeDetectionImageFilter2 ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkDicomSeriesReadImageWrite itkDicomSeriesReadImageWrite.cxx) -target_link_libraries(itkDicomSeriesReadImageWrite ITK::LesionSizingToolkitModule) +target_link_libraries(itkDicomSeriesReadImageWrite ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkGradientMagnitudeImageFilter itkGradientMagnitudeImageFilter.cxx) -target_link_libraries(itkGradientMagnitudeImageFilter ITK::LesionSizingToolkitModule) +target_link_libraries(itkGradientMagnitudeImageFilter ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkGradientMagnitudeRecursiveGaussianImageFilter itkGradientMagnitudeRecursiveGaussianImageFilter.cxx) -target_link_libraries(itkGradientMagnitudeRecursiveGaussianImageFilter ITK::LesionSizingToolkitModule) +target_link_libraries(itkGradientMagnitudeRecursiveGaussianImageFilter ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkImageReadRegionOfInterestAroundSeedWrite itkImageReadRegionOfInterestAroundSeedWrite.cxx) -target_link_libraries(itkImageReadRegionOfInterestAroundSeedWrite ITK::LesionSizingToolkitModule) +target_link_libraries(itkImageReadRegionOfInterestAroundSeedWrite ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkImageReadRegionOfInterestWrite itkImageReadRegionOfInterestWrite.cxx) -target_link_libraries(itkImageReadRegionOfInterestWrite ITK::LesionSizingToolkitModule) +target_link_libraries(itkImageReadRegionOfInterestWrite ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkImageReadWrite itkImageReadWrite.cxx) -target_link_libraries(itkImageReadWrite ITK::LesionSizingToolkitModule) +target_link_libraries(itkImageReadWrite ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkLaplacianRecursiveGaussianImageFilter itkLaplacianRecursiveGaussianImageFilter.cxx) -target_link_libraries(itkLaplacianRecursiveGaussianImageFilter ITK::LesionSizingToolkitModule) +target_link_libraries(itkLaplacianRecursiveGaussianImageFilter ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) add_executable(itkResampleVolumeToBeIsotropic itkResampleVolumeToBeIsotropic.cxx) -target_link_libraries(itkResampleVolumeToBeIsotropic ITK::LesionSizingToolkitModule) +target_link_libraries(itkResampleVolumeToBeIsotropic ITK::LesionSizingToolkitModule ${ITK_LIBRARIES}) diff --git a/wrapping/CMakeLists.txt b/wrapping/CMakeLists.txt index dbdc8c4f..d564480d 100644 --- a/wrapping/CMakeLists.txt +++ b/wrapping/CMakeLists.txt @@ -1,6 +1,14 @@ itk_wrap_module(LesionSizingToolkit) set(WRAPPER_SUBMODULE_ORDER + itkFeatureGenerator + itkFeatureAggregator + itkSatoVesselnessFeatureGenerator + itkSegmentationModule + itkRegionGrowingSegmentationModule + itkSinglePhaseLevelSetSegmentationModule + itkFastMarchingSegmentationModule + itkSegmentationVolumeEstimator itkBinaryThresholdFeatureGenerator itkCannyEdgeDetectionRecursiveGaussianImageFilter itkCannyEdgesDistanceAdvectionFieldFeatureGenerator @@ -12,9 +20,6 @@ set(WRAPPER_SUBMODULE_ORDER itkDescoteauxSheetnessImageFilter itkFastMarchingAndGeodesicActiveContourLevelSetSegmentationModule itkFastMarchingAndShapeDetectionLevelSetSegmentationModule - itkFastMarchingSegmentationModule - itkFeatureAggregator - itkFeatureGenerator itkFrangiTubularnessFeatureGenerator itkFrangiTubularnessImageFilter itkGeodesicActiveContourLevelSetSegmentationModule @@ -31,15 +36,10 @@ set(WRAPPER_SUBMODULE_ORDER itkMinimumFeatureAggregator itkMorphologicalOpeningFeatureGenerator itkRegionCompetitionImageFilter - itkRegionGrowingSegmentationModule itkSatoLocalStructureFeatureGenerator - itkSatoVesselnessFeatureGenerator itkSatoVesselnessSigmoidFeatureGenerator - itkSegmentationModule - itkSegmentationVolumeEstimator itkShapeDetectionLevelSetSegmentationModule itkSigmoidFeatureGenerator - itkSinglePhaseLevelSetSegmentationModule itkVesselEnhancingDiffusion3DImageFilter itkVotingBinaryHoleFillFloodingImageFilter itkWeightedSumFeatureAggregator diff --git a/wrapping/itkDescoteauxSheetnessImageFilter.wrap b/wrapping/itkDescoteauxSheetnessImageFilter.wrap index ced7428d..387a0bff 100644 --- a/wrapping/itkDescoteauxSheetnessImageFilter.wrap +++ b/wrapping/itkDescoteauxSheetnessImageFilter.wrap @@ -1,3 +1,3 @@ -itk_wrap_class("itk::DescoteauxSheetnessImageFilter" POINTER) - itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2+) +itk_wrap_class("itk::DescoteauxSheetnessImageFilter" POINTER_WITH_SUPERCLASS) + itk_wrap_image_filter_combinations("${WRAP_ITK_COV_VECTOR_REAL}" "${WRAP_ITK_REAL}") itk_end_wrap_class() diff --git a/wrapping/itkFrangiTubularnessImageFilter.wrap b/wrapping/itkFrangiTubularnessImageFilter.wrap index 392b4d63..f6ca14c9 100644 --- a/wrapping/itkFrangiTubularnessImageFilter.wrap +++ b/wrapping/itkFrangiTubularnessImageFilter.wrap @@ -1,3 +1,3 @@ -itk_wrap_class("itk::FrangiTubularnessImageFilter" POINTER) - itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2+) +itk_wrap_class("itk::FrangiTubularnessImageFilter" POINTER_WITH_SUPERCLASS) + itk_wrap_image_filter_combinations("${WRAP_ITK_COV_VECTOR_REAL}" "${WRAP_ITK_REAL}") itk_end_wrap_class() diff --git a/wrapping/itkLesionSegmentationImageFilter8.wrap b/wrapping/itkLesionSegmentationImageFilter8.wrap index b4735928..b0f8f8c6 100644 --- a/wrapping/itkLesionSegmentationImageFilter8.wrap +++ b/wrapping/itkLesionSegmentationImageFilter8.wrap @@ -1,3 +1,3 @@ itk_wrap_class("itk::LesionSegmentationImageFilter8" POINTER) - itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2+) + itk_wrap_image_filter_combinations("${WRAP_ITK_SCALAR}" "${WRAP_ITK_REAL}" 3) itk_end_wrap_class() diff --git a/wrapping/itkLocalStructureImageFilter.wrap b/wrapping/itkLocalStructureImageFilter.wrap index cd29f9cc..34c8952a 100644 --- a/wrapping/itkLocalStructureImageFilter.wrap +++ b/wrapping/itkLocalStructureImageFilter.wrap @@ -1,3 +1,3 @@ itk_wrap_class("itk::LocalStructureImageFilter" POINTER_WITH_SUPERCLASS) - itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2) + itk_wrap_image_filter_combinations("${WRAP_ITK_COV_VECTOR_REAL}" "${WRAP_ITK_REAL}") itk_end_wrap_class() diff --git a/wrapping/itkRegionCompetitionImageFilter.wrap b/wrapping/itkRegionCompetitionImageFilter.wrap index 551aba7a..3a36f44c 100644 --- a/wrapping/itkRegionCompetitionImageFilter.wrap +++ b/wrapping/itkRegionCompetitionImageFilter.wrap @@ -1,3 +1,3 @@ itk_wrap_class("itk::RegionCompetitionImageFilter" POINTER) - itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2+) + itk_wrap_image_filter("${WRAP_ITK_INT}" 2 2+) itk_end_wrap_class() diff --git a/wrapping/itkSatoVesselnessFeatureGenerator.wrap b/wrapping/itkSatoVesselnessFeatureGenerator.wrap index fcf1945e..64fefe3d 100644 --- a/wrapping/itkSatoVesselnessFeatureGenerator.wrap +++ b/wrapping/itkSatoVesselnessFeatureGenerator.wrap @@ -1,5 +1,6 @@ -itk_wrap_class("itk::SatoVesselnessSigmoidFeatureGenerator" POINTER) - foreach(d ${ITK_WRAP_IMAGE_DIMS}) - itk_wrap_template(${d} ${d}) - endforeach() -itk_end_wrap_class() +itk_wrap_filter_dims(has_d_3 3) +if(has_d_3) + itk_wrap_class("itk::SatoVesselnessFeatureGenerator" POINTER) + itk_wrap_template(3 3) + itk_end_wrap_class() +endif() diff --git a/wrapping/itkSatoVesselnessSigmoidFeatureGenerator.wrap b/wrapping/itkSatoVesselnessSigmoidFeatureGenerator.wrap index fcf1945e..1867004b 100644 --- a/wrapping/itkSatoVesselnessSigmoidFeatureGenerator.wrap +++ b/wrapping/itkSatoVesselnessSigmoidFeatureGenerator.wrap @@ -1,5 +1,6 @@ -itk_wrap_class("itk::SatoVesselnessSigmoidFeatureGenerator" POINTER) - foreach(d ${ITK_WRAP_IMAGE_DIMS}) - itk_wrap_template(${d} ${d}) - endforeach() -itk_end_wrap_class() +itk_wrap_filter_dims(has_d_3 3) +if(has_d_3) + itk_wrap_class("itk::SatoVesselnessSigmoidFeatureGenerator" POINTER) + itk_wrap_template(3 3) + itk_end_wrap_class() +endif() diff --git a/wrapping/itkVesselEnhancingDiffusion3DImageFilter.wrap b/wrapping/itkVesselEnhancingDiffusion3DImageFilter.wrap index 6a949f59..9b38bfd6 100644 --- a/wrapping/itkVesselEnhancingDiffusion3DImageFilter.wrap +++ b/wrapping/itkVesselEnhancingDiffusion3DImageFilter.wrap @@ -1,3 +1,8 @@ -itk_wrap_class("itk::VesselEnhancingDiffusion3DImageFilter" POINTER) - itk_wrap_image_filter("${WRAP_ITK_SCALAR}" 2+) -itk_end_wrap_class() +itk_wrap_filter_dims(has_d_3 3) +if(has_d_3) + itk_wrap_class("itk::VesselEnhancingDiffusion3DImageFilter" POINTER) + foreach(t ${WRAP_ITK_SCALAR}) + itk_wrap_template("${ITKM_${t}}3" "${ITKT_${t}}, 3") + endforeach() + itk_end_wrap_class() +endif() From d53082b6aaefbd3833327ed01bc16b16badb0ecf Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Tue, 22 Sep 2026 10:04:18 -0500 Subject: [PATCH 2/3] BUG: Define FeatureGenerator::GetInput and drop redeclarations FeatureGenerator and thirteen subclasses declared GetInput() const, but only SegmentationModule defined it. C++ callers never used it, so the missing definitions went unnoticed; SWIG wraps every declared method, so the Python module failed to load with undefined symbols. Define it in FeatureGenerator and IsotropicResampler, and let the feature generators inherit it. --- .../itkCannyEdgesDistanceAdvectionFieldFeatureGenerator.h | 2 -- include/itkCannyEdgesDistanceFeatureGenerator.h | 2 -- include/itkCannyEdgesFeatureGenerator.h | 2 -- include/itkDescoteauxSheetnessFeatureGenerator.h | 2 -- include/itkFeatureGenerator.hxx | 7 +++++++ include/itkFrangiTubularnessFeatureGenerator.h | 2 -- include/itkGradientMagnitudeSigmoidFeatureGenerator.h | 2 -- include/itkIsotropicResampler.hxx | 7 +++++++ include/itkLungWallFeatureGenerator.h | 2 -- include/itkMorphologicalOpeningFeatureGenerator.h | 2 -- include/itkMorphologicalOpenningFeatureGenerator.h | 2 -- include/itkSatoLocalStructureFeatureGenerator.h | 2 -- include/itkSatoVesselnessFeatureGenerator.h | 2 -- include/itkSigmoidFeatureGenerator.h | 2 -- 14 files changed, 14 insertions(+), 24 deletions(-) diff --git a/include/itkCannyEdgesDistanceAdvectionFieldFeatureGenerator.h b/include/itkCannyEdgesDistanceAdvectionFieldFeatureGenerator.h index ea6d0798..e0cdc1a6 100644 --- a/include/itkCannyEdgesDistanceAdvectionFieldFeatureGenerator.h +++ b/include/itkCannyEdgesDistanceAdvectionFieldFeatureGenerator.h @@ -99,8 +99,6 @@ class ITK_TEMPLATE_EXPORT CannyEdgesDistanceAdvectionFieldFeatureGenerator : pub using ProcessObject::SetInput; void SetInput(const SpatialObjectType * input); - const SpatialObjectType * - GetInput() const; /** Output data that carries the feature in the form of a * SpatialObject. */ diff --git a/include/itkCannyEdgesDistanceFeatureGenerator.h b/include/itkCannyEdgesDistanceFeatureGenerator.h index 2c06a54e..1ad4f8be 100644 --- a/include/itkCannyEdgesDistanceFeatureGenerator.h +++ b/include/itkCannyEdgesDistanceFeatureGenerator.h @@ -95,8 +95,6 @@ class ITK_TEMPLATE_EXPORT CannyEdgesDistanceFeatureGenerator : public FeatureGen using ProcessObject::SetInput; void SetInput(const SpatialObjectType * input); - const SpatialObjectType * - GetInput() const; /** Output data that carries the feature in the form of a * SpatialObject. */ diff --git a/include/itkCannyEdgesFeatureGenerator.h b/include/itkCannyEdgesFeatureGenerator.h index 972472b1..fa228f08 100644 --- a/include/itkCannyEdgesFeatureGenerator.h +++ b/include/itkCannyEdgesFeatureGenerator.h @@ -93,8 +93,6 @@ class ITK_TEMPLATE_EXPORT CannyEdgesFeatureGenerator : public FeatureGenerator::SetInput(const SpatialObjectType * spatialObject) this->SetNthInput(0, const_cast(spatialObject)); } +template +const typename FeatureGenerator::SpatialObjectType * +FeatureGenerator::GetInput() const +{ + return dynamic_cast(this->ProcessObject::GetInput(0)); +} + template const typename FeatureGenerator::SpatialObjectType * FeatureGenerator::GetFeature() const diff --git a/include/itkFrangiTubularnessFeatureGenerator.h b/include/itkFrangiTubularnessFeatureGenerator.h index 37a394e2..749e324b 100644 --- a/include/itkFrangiTubularnessFeatureGenerator.h +++ b/include/itkFrangiTubularnessFeatureGenerator.h @@ -72,8 +72,6 @@ class ITK_TEMPLATE_EXPORT FrangiTubularnessFeatureGenerator : public FeatureGene using ProcessObject::SetInput; void SetInput(const SpatialObjectType * input); - const SpatialObjectType * - GetInput() const; /** Output data that carries the feature in the form of a * SpatialObject. */ diff --git a/include/itkGradientMagnitudeSigmoidFeatureGenerator.h b/include/itkGradientMagnitudeSigmoidFeatureGenerator.h index a26100b6..c9615245 100644 --- a/include/itkGradientMagnitudeSigmoidFeatureGenerator.h +++ b/include/itkGradientMagnitudeSigmoidFeatureGenerator.h @@ -72,8 +72,6 @@ class ITK_TEMPLATE_EXPORT GradientMagnitudeSigmoidFeatureGenerator : public Feat using ProcessObject::SetInput; void SetInput(const SpatialObjectType * input); - const SpatialObjectType * - GetInput() const; /** Output data that carries the feature in the form of a * SpatialObject. */ diff --git a/include/itkIsotropicResampler.hxx b/include/itkIsotropicResampler.hxx index 565f7f79..18bfd66a 100644 --- a/include/itkIsotropicResampler.hxx +++ b/include/itkIsotropicResampler.hxx @@ -50,6 +50,13 @@ IsotropicResampler::SetInput(const SpatialObjectType * spatialObject this->SetNthInput(0, const_cast(spatialObject)); } +template +const typename IsotropicResampler::SpatialObjectType * +IsotropicResampler::GetInput() const +{ + return dynamic_cast(this->ProcessObject::GetInput(0)); +} + template const typename IsotropicResampler::SpatialObjectType * IsotropicResampler::GetOutput() const diff --git a/include/itkLungWallFeatureGenerator.h b/include/itkLungWallFeatureGenerator.h index ea17c327..fd2ce434 100644 --- a/include/itkLungWallFeatureGenerator.h +++ b/include/itkLungWallFeatureGenerator.h @@ -73,8 +73,6 @@ class ITK_TEMPLATE_EXPORT LungWallFeatureGenerator : public FeatureGenerator Date: Thu, 24 Sep 2026 10:23:22 -0500 Subject: [PATCH 3/3] COMP: Pin the reusable CI workflow to an existing release @v5.4.6 no longer resolves to a tag; every job failed identically after a ~9-minute build, in a second, flag-less CMake reconfigure of the same binary directory that could not find ITK::LesionSizingToolkitModule, which is not present at v5.4.4 or on the workflow's current main branch. Most likely v5.4.6 was itself a since-reverted release. Pin to v5.4.4, the latest tag confirmed to exist. --- .github/workflows/build-test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-test-package.yml b/.github/workflows/build-test-package.yml index 3bf47f1e..7a8e4a12 100644 --- a/.github/workflows/build-test-package.yml +++ b/.github/workflows/build-test-package.yml @@ -12,10 +12,10 @@ on: jobs: cxx-build-workflow: - uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@v5.4.6 + uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@v5.4.4 python-build-workflow: - uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.6 + uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.4 with: itk-wheel-tag: 'v5.4.5' itk-python-package-tag: 'v5.4.5'