// Factory method returns SmartPointer — never use new/delete
auto filter = FilterType::New();
filter->SetInput(image);
filter->Update(); // Lazy: nothing runs until here
auto output = filter->GetOutput();
// Parameters changed after Update() require another Update()
filter->SetRadius(3);
filter->Update();Use iterators, not raw buffer access:
itk::ImageRegionIterator<ImageType> it(image, region);
for (; !it.IsAtEnd(); ++it) {
it.Set(it.Get() * 2);
}class MyFilter : public BaseFilter {
public:
using Self = MyFilter;
using Superclass = BaseFilter;
using Pointer = itk::SmartPointer<Self>;
itkNewMacro(Self); // Provides New()
itkTypeMacro(MyFilter, BaseFilter); // RTTI
itkSetMacro(Radius, unsigned int); // Generates SetRadius()
itkGetConstMacro(Radius, unsigned int); // Generates GetRadius()
itkBooleanMacro(UseSpacing); // Generates UseSpacingOn/Off()When extending a class with embedded Python in a .i file, use the
verbatim form %pythoncode %{ ... %} for any code that contains
# comments:
// BAD — `# Foo` is parsed as a SWIG preprocessor directive named "Foo":
%pythoncode {
def __array__(self, dtype=None, copy=None):
# Explicit copy requested. <-- SWIG error
return ...
}
// GOOD — verbatim block is passed through unchanged:
%pythoncode %{
def __array__(self, dtype=None, copy=None):
# Explicit copy requested.
return ...
%}The single-brace form %pythoncode { ... } runs its body through
SWIG's preprocessor and emits errors like:
Error: Unknown SWIG preprocessor directive: Explicit
The verbatim %{ ... %} form is the safe default for any non-trivial
Python code block. References: PR #6027 commit fix.
When adding a new ITK class to a wrapped module (anything under
Modules/ that has a wrapping/ subdirectory), every step below is
required to keep CI green:
include/itkXxx.h— class declaration, with\class Xxxdoxygeninclude/itkXxx.hxx— template implementations (header-only)src/itkXxx.cxx— non-template implementations + entry insrc/CMakeLists.txtwrapping/itkXxx.wrap—itk_wrap_simple_class("itk::Xxx" POINTER)(oritk_wrap_class+itk_wrap_image_filterfor templates). Missing this file producesKeyError: 'Xxx'in Python tests — the C++ build still passes, butARMBUILD-Python,ITK.Linux.Python, andITK.macOS.Pythonwill fail.- For new
ImageIOclasses: add the factory toFACTORY_NAMESinitk-module.cmakeand register the factory inImageIOFactory.cxx. - New module dependencies →
DEPENDS(public) orPRIVATE_DEPENDS(implementation-only) initk-module.cmake. test/itkXxxGTest.cxx— at least one round-trip / identity test, plus an exception-validation test.- KWStyle: every header has the doxygen
\class Xxxtag (see enforced-code-style.md and compiler-cautions.md section 12a).
References: PR #6032 (VTI factory wrapping fix), PR #6034 (SSIM filter add).
ModuleName/
├── itk-module.cmake # Module metadata and dependency declarations
├── include/
│ ├── itkClassName.h # Class declaration
│ └── itkClassName.hxx # Template method implementations (included by .h)
├── src/
│ └── itkClassName.cxx # Non-template implementations (compiled into lib)
├── test/
│ ├── CMakeLists.txt
│ └── itkClassNameGTest.cxx # Preferred: GoogleTest
└── wrapping/
└── itkClassName.wrap # Python wrapping (if applicable)
In itk-module.cmake:
DEPENDS— public (propagated to consumers)PRIVATE_DEPENDS— implementation-onlyTEST_DEPENDS— test-only
Modules/ThirdParty/ uses git subtree, not submodules. Update with:
git subtree pull --prefix=Modules/ThirdParty/Foo upstream-foo mainTo create an external module:
itk-module.cmake— declare dependenciesMyModule.remote.cmakeinModules/Remote/— fetch URL + hashCMakeLists.txtusingitk_module_impl()