From def3f61dbd63bac3c808cbf3cb8890e6b246eec3 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Tue, 11 Nov 2025 17:01:28 -0600 Subject: [PATCH 1/6] COMP: Update RemoteModulePackageAction and Python 3.10+ Update github actions to v5.4.5 and package management for python 3.10 Bump workflow action from v5.4.4 to v5.4.5 to use the v5.4.5 ITKPythonBuilds release. --- .github/workflows/build-test-package.yml | 4 ++-- pyproject.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-test-package.yml b/.github/workflows/build-test-package.yml index 19b97f5..5741517 100644 --- a/.github/workflows/build-test-package.yml +++ b/.github/workflows/build-test-package.yml @@ -5,10 +5,10 @@ on: [push,pull_request] jobs: cxx-build-workflow: - uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@v5.4.0 + uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@v5.4.5 python-build-workflow: - uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.0 + uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.5 with: test-notebooks: false secrets: diff --git a/pyproject.toml b/pyproject.toml index 7854661..488adec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ classifiers = [ "Topic :: Scientific/Engineering :: Medical Science Apps.", "Topic :: Software Development :: Libraries", ] -requires-python = ">=3.8" +requires-python = ">=3.10" dependencies = [ "itk == 5.4.*", ] @@ -47,7 +47,7 @@ Homepage = "https://github.com/InsightSoftwareConsortium/ITKBioCell" # The versions of CMake to allow. If CMake is not present on the system or does # not pass this specifier, it will be downloaded via PyPI if possible. An empty # string will disable this check. -cmake.version = ">=3.16.3" +cmake.version = ">=3.22.1" # A list of args to pass to CMake when configuring the project. Setting this in # config or envvar will override toml. See also ``cmake.define``. From 83c12d6eb132045b31b5b46b6ee86e4dd63904f5 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Fri, 27 Mar 2026 10:35:05 -0500 Subject: [PATCH 2/6] ENH: Add Python wrapping for CellularAggregateBase and CellularAggregate BioCell was the only ITKRemoteModule with a pyproject.toml but no wrapping/ directory, causing the Python wheel build CI to fail: the manylinux build script found no .whl to repair and exited with an error. Add wrapping for the two itk::Object-derived classes: - itk::bio::CellularAggregateBase (non-templated) - itk::bio::CellularAggregate<2> and <3> Adding this simple wrapping allows the standard python wrapping infrastructure to be tested and consistent with other remote modules. Generative AI was used to diagnose and recommend this solution. --- wrapping/CMakeLists.txt | 3 +++ wrapping/itkBioCellularAggregate.wrap | 4 ++++ wrapping/itkBioCellularAggregateBase.wrap | 2 ++ 3 files changed, 9 insertions(+) create mode 100644 wrapping/CMakeLists.txt create mode 100644 wrapping/itkBioCellularAggregate.wrap create mode 100644 wrapping/itkBioCellularAggregateBase.wrap diff --git a/wrapping/CMakeLists.txt b/wrapping/CMakeLists.txt new file mode 100644 index 0000000..853ad59 --- /dev/null +++ b/wrapping/CMakeLists.txt @@ -0,0 +1,3 @@ +itk_wrap_module(BioCell) +itk_auto_load_submodules() +itk_end_wrap_module() diff --git a/wrapping/itkBioCellularAggregate.wrap b/wrapping/itkBioCellularAggregate.wrap new file mode 100644 index 0000000..cc0c0eb --- /dev/null +++ b/wrapping/itkBioCellularAggregate.wrap @@ -0,0 +1,4 @@ +itk_wrap_class("itk::bio::CellularAggregate" POINTER) + itk_wrap_template("2" "2") + itk_wrap_template("3" "3") +itk_end_wrap_class() diff --git a/wrapping/itkBioCellularAggregateBase.wrap b/wrapping/itkBioCellularAggregateBase.wrap new file mode 100644 index 0000000..7300c9a --- /dev/null +++ b/wrapping/itkBioCellularAggregateBase.wrap @@ -0,0 +1,2 @@ +itk_wrap_class("itk::bio::CellularAggregateBase" POINTER) +itk_end_wrap_class() From 6fba2c6d7135da6d2a86a46a7eb7bc1003f8e4d8 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Fri, 27 Mar 2026 10:58:25 -0500 Subject: [PATCH 3/6] BUG: Fix castxml header resolution for itk::bio namespace classes The ITK wrapping machinery derives include filenames from the class name by stripping all but the leaf name: itk::bio::CellularAggregate -> itkCellularAggregate.h. The actual headers use the Bio prefix (itkBioCellularAggregate.h), causing castxml to abort with "file not found". Add explicit itk_wrap_include() directives so the generated castxml input files include the correct headers. Generative AI was used to diagnose and recommend this solution. --- wrapping/itkBioCellularAggregate.wrap | 1 + wrapping/itkBioCellularAggregateBase.wrap | 1 + 2 files changed, 2 insertions(+) diff --git a/wrapping/itkBioCellularAggregate.wrap b/wrapping/itkBioCellularAggregate.wrap index cc0c0eb..1c19881 100644 --- a/wrapping/itkBioCellularAggregate.wrap +++ b/wrapping/itkBioCellularAggregate.wrap @@ -1,3 +1,4 @@ +itk_wrap_include("itkBioCellularAggregate.h") itk_wrap_class("itk::bio::CellularAggregate" POINTER) itk_wrap_template("2" "2") itk_wrap_template("3" "3") diff --git a/wrapping/itkBioCellularAggregateBase.wrap b/wrapping/itkBioCellularAggregateBase.wrap index 7300c9a..5c97501 100644 --- a/wrapping/itkBioCellularAggregateBase.wrap +++ b/wrapping/itkBioCellularAggregateBase.wrap @@ -1,2 +1,3 @@ +itk_wrap_include("itkBioCellularAggregateBase.h") itk_wrap_class("itk::bio::CellularAggregateBase" POINTER) itk_end_wrap_class() From d8fb0dd639aafef849dca2c7592f0bf9a866e6cb Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Wed, 1 Apr 2026 16:40:36 -0500 Subject: [PATCH 4/6] BUG: Fix Python wrapping for itk::bio namespace classes Three issues prevented the Python wrapping from building: 1. WRAPPER_AUTO_INCLUDE_HEADERS was ON, causing itk_wrap_class to auto-derive wrong header filenames (itkCellularAggregateBase.h instead of itkBioCellularAggregateBase.h). Disable auto-include and rely on the explicit itk_wrap_include() directives, matching the pattern used by Ultrasound (BlockMatching) and ITK Statistics. 2. CellularAggregateBase is a non-template class but was wrapped with itk_wrap_class/itk_end_wrap_class (no itk_wrap_template calls), producing an empty SWIG interface. Use itk_wrap_simple_class instead so the class is properly registered. 3. itk_auto_load_submodules() processes .wrap files alphabetically, causing CellularAggregate to load before its base class. Add WRAPPER_SUBMODULE_ORDER to enforce correct dependency ordering. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/build-test-package.yml | 4 ++-- wrapping/CMakeLists.txt | 4 ++++ wrapping/itkBioCellularAggregate.wrap | 2 ++ wrapping/itkBioCellularAggregateBase.wrap | 5 +++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-test-package.yml b/.github/workflows/build-test-package.yml index 5741517..4f5f9b9 100644 --- a/.github/workflows/build-test-package.yml +++ b/.github/workflows/build-test-package.yml @@ -5,10 +5,10 @@ on: [push,pull_request] jobs: cxx-build-workflow: - uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@v5.4.5 + uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-cxx.yml@v5.4.6 python-build-workflow: - uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.5 + uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.6 with: test-notebooks: false secrets: diff --git a/wrapping/CMakeLists.txt b/wrapping/CMakeLists.txt index 853ad59..7d69d43 100644 --- a/wrapping/CMakeLists.txt +++ b/wrapping/CMakeLists.txt @@ -1,3 +1,7 @@ itk_wrap_module(BioCell) +set(WRAPPER_SUBMODULE_ORDER + itkBioCellularAggregateBase + itkBioCellularAggregate +) itk_auto_load_submodules() itk_end_wrap_module() diff --git a/wrapping/itkBioCellularAggregate.wrap b/wrapping/itkBioCellularAggregate.wrap index 1c19881..8709453 100644 --- a/wrapping/itkBioCellularAggregate.wrap +++ b/wrapping/itkBioCellularAggregate.wrap @@ -1,5 +1,7 @@ +set(WRAPPER_AUTO_INCLUDE_HEADERS OFF) itk_wrap_include("itkBioCellularAggregate.h") itk_wrap_class("itk::bio::CellularAggregate" POINTER) itk_wrap_template("2" "2") itk_wrap_template("3" "3") itk_end_wrap_class() +set(WRAPPER_AUTO_INCLUDE_HEADERS ON) diff --git a/wrapping/itkBioCellularAggregateBase.wrap b/wrapping/itkBioCellularAggregateBase.wrap index 5c97501..65c6913 100644 --- a/wrapping/itkBioCellularAggregateBase.wrap +++ b/wrapping/itkBioCellularAggregateBase.wrap @@ -1,3 +1,4 @@ +set(WRAPPER_AUTO_INCLUDE_HEADERS OFF) itk_wrap_include("itkBioCellularAggregateBase.h") -itk_wrap_class("itk::bio::CellularAggregateBase" POINTER) -itk_end_wrap_class() +itk_wrap_simple_class("itk::bio::CellularAggregateBase" POINTER) +set(WRAPPER_AUTO_INCLUDE_HEADERS ON) From 13f7ede97fafe1a68724a3619c40edae409eb03a Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Thu, 2 Apr 2026 21:21:44 -0500 Subject: [PATCH 5/6] COMP: Fix nodiscard warning in CellularAggregate::GetSubstrateValue Use the bool return value of TransformPhysicalPointToIndex instead of ignoring it. The return value indicates whether the physical point maps to a valid index, so incorporate it into the existing bounds check. Co-Authored-By: Claude Opus 4.6 (1M context) --- include/itkBioCellularAggregate.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/itkBioCellularAggregate.hxx b/include/itkBioCellularAggregate.hxx index 987e30b..e82bc45 100644 --- a/include/itkBioCellularAggregate.hxx +++ b/include/itkBioCellularAggregate.hxx @@ -606,10 +606,10 @@ CellularAggregate::GetSubstrateValue(IdentifierType cellId, uns typename SubstrateType::IndexType index; - substrate->TransformPhysicalPointToIndex(cellPosition, index); + const bool isInside = substrate->TransformPhysicalPointToIndex(cellPosition, index); SubstrateValueType value = 0; - if (substrate->GetBufferedRegion().IsInside(index)) + if (isInside && substrate->GetBufferedRegion().IsInside(index)) { value = substrate->GetPixel(index); } From 99bab165e78e02a17ea6eecddc86e71e45600e8c Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Thu, 2 Apr 2026 21:46:58 -0500 Subject: [PATCH 6/6] COMP: Pin ITK wheel build to v5.4.5 for Python packaging --- .github/workflows/build-test-package.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build-test-package.yml b/.github/workflows/build-test-package.yml index 4f5f9b9..4696eca 100644 --- a/.github/workflows/build-test-package.yml +++ b/.github/workflows/build-test-package.yml @@ -10,6 +10,8 @@ jobs: python-build-workflow: uses: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction/.github/workflows/build-test-package-python.yml@v5.4.6 with: + itk-wheel-tag: 'v5.4.5' + itk-python-package-tag: 'v5.4.5' test-notebooks: false secrets: pypi_password: ${{ secrets.pypi_password }}