From f30c6ba6ca50141139c82184dec00bb606449618 Mon Sep 17 00:00:00 2001 From: Francois Budin Date: Tue, 24 May 2016 15:12:45 -0400 Subject: [PATCH 01/42] ENH: Converting generic_label_interpolator to an ITK remote module. ITK remote modules can easily be either directly integrated in ITK or compiled against ITK. --- .../GenericLabelInterpolator/CMakeLists.txt | 10 + ...abelImageGenericInterpolateImageFunction.h | 118 +++++++++++ ...elImageGenericInterpolateImageFunction.hxx | 87 ++++++++ .../include/itkLabelSelectionImageAdaptor.h | 72 +++++++ .../include/itkLabelSelectionPixelAccessor.h | 63 ++++++ .../GenericLabelInterpolator/itk-module.cmake | 21 ++ .../test/Baseline/gl_gaussian_3.mha.md5 | 1 + .../test/CMakeLists.txt | 18 ++ .../test/Input/classification.mha.md5 | 1 + .../test/RotateLabels.cxx | 194 ++++++++++++++++++ 10 files changed, 585 insertions(+) create mode 100644 Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt create mode 100644 Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h create mode 100644 Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx create mode 100644 Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h create mode 100644 Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h create mode 100644 Modules/Filtering/GenericLabelInterpolator/itk-module.cmake create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx diff --git a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt new file mode 100644 index 00000000000..d24d1c8fbb5 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.8.9) +project(GenericLabelInterpolator) + +if(NOT ITK_SOURCE_DIR) + find_package(ITK 4.9 REQUIRED) + list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR}) + include(ITKModuleExternal) +else() + itk_module_impl() +endif() diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h new file mode 100644 index 00000000000..e3064ae1327 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -0,0 +1,118 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkLabelImageGenericInterpolateImageFunction_h +#define itkLabelImageGenericInterpolateImageFunction_h + +#include +#include "itkLabelSelectionImageAdaptor.h" +#include +#include + +namespace itk +{ + +/** \class LabelImageGenericInterpolateImageFunction + * \brief Interpolation function for multi-label images that implicitly interpolates each + * unique value in the image corresponding to each label set element and returns the + * corresponding label set element with the largest weight. + * + * This filter is an alternative to nearest neighbor interpolation for multi-label + * images. It can use almost any underlying interpolator. + * * \ingroup ITKImageFunction + * * \ingroup GenericLabelInterpolator + */ + +template class TInterpolator, typename TCoordRep=double > +class ITK_EXPORT LabelImageGenericInterpolateImageFunction : + public InterpolateImageFunction +{ +public: + /** Standard class typedefs. */ + typedef LabelImageGenericInterpolateImageFunction Self; + typedef InterpolateImageFunction Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + typedef typename TInputImage::PixelType InputPixelType; + + /** Run-time type information (and related methods). */ + itkTypeMacro( LabelImageGenericInterpolateImageFunction, InterpolateImageFunction ); + + /** Method for creation through the object factory. */ + itkNewMacro( Self ); + + /** ImageDimension constant */ + itkStaticConstMacro( ImageDimension, unsigned int, TInputImage::ImageDimension ); + + /** OutputType typedef support. */ + typedef typename Superclass::OutputType OutputType; + + /** InputImageType typedef support. */ + typedef typename Superclass::InputImageType InputImageType; + + /** RealType typedef support. */ + typedef typename Superclass::RealType RealType; + + /** Index typedef support. */ + typedef typename Superclass::IndexType IndexType; + + /** ContinuousIndex typedef support. */ + typedef typename Superclass::ContinuousIndexType ContinuousIndexType; + + typedef LabelSelectionImageAdaptor LabelSelectionAdaptorType; + + // The interpolator used for individual binary masks corresponding to each label + typedef TInterpolator InternalInterpolatorType; + + /** + * Evaluate at the given index + */ + virtual OutputType EvaluateAtContinuousIndex( + const ContinuousIndexType & cindex ) const + { + return this->EvaluateAtContinuousIndex( cindex, NULL ); + } + + virtual void SetInputImage( const TInputImage *image ); + +protected: + LabelImageGenericInterpolateImageFunction(); + ~LabelImageGenericInterpolateImageFunction(){}; + + std::vector m_InternalInterpolators; + std::vector m_LabelSelectionAdaptors; + typedef std::set LabelSetType; + LabelSetType m_Labels; + +private: + LabelImageGenericInterpolateImageFunction( const Self& ); //purposely not implemented + void operator=( const Self& ); //purposely not implemented + + /** + * Evaluate function value at the given index + */ + virtual OutputType EvaluateAtContinuousIndex( + const ContinuousIndexType &, OutputType * ) const; +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelImageGenericInterpolateImageFunction.hxx" +#endif + +#endif diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx new file mode 100644 index 00000000000..73ef0647485 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -0,0 +1,87 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkLabelImageGenericInterpolateImageFunction_hxx +#define itkLabelImageGenericInterpolateImageFunction_hxx + +#include "itkLabelImageGenericInterpolateImageFunction.h" +#include + +namespace itk +{ + +template class TInterpolator , typename TCoordRep> +LabelImageGenericInterpolateImageFunction +::LabelImageGenericInterpolateImageFunction() +{ +} + +template class TInterpolator , typename TCoordRep> +void LabelImageGenericInterpolateImageFunction +::SetInputImage( const TInputImage *image ) { + /** We have one adaptor and one interpolator per label to keep the class thread-safe: + * changing the adaptor's accepted value wouldn't work when called from a multi-threaded filter */ + if (image) { + m_Labels.clear(); + typedef itk::ImageRegionConstIterator IteratorType; + IteratorType it(image,image->GetLargestPossibleRegion()); + it.GoToBegin(); + for (; !it.IsAtEnd(); ++it) { + m_Labels.insert(it.Get()); + } + m_InternalInterpolators.clear(); + m_LabelSelectionAdaptors.clear(); + for(typename LabelSetType::const_iterator i=m_Labels.begin(); i != m_Labels.end(); ++i) { + typename LabelSelectionAdaptorType::Pointer adapt = LabelSelectionAdaptorType::New(); + // This adaptor doesn't implement Set() so this should be safe + adapt->SetImage(const_cast(image)); + adapt->SetAcceptedValue(*i); + m_LabelSelectionAdaptors.push_back(adapt); + typename InternalInterpolatorType::Pointer interp = InternalInterpolatorType::New(); + interp->SetInputImage(adapt); + m_InternalInterpolators.push_back(interp); + } + } + Superclass::SetInputImage(image); +} + +template class TInterpolator , typename TCoordRep> +typename LabelImageGenericInterpolateImageFunction +::OutputType +LabelImageGenericInterpolateImageFunction +::EvaluateAtContinuousIndex( const ContinuousIndexType & cindex, OutputType * grad ) const +{ + /** Interpolate the binary mask corresponding to each label and return the label + * with the highest value */ + double value=0; + typename TInputImage::PixelType best_label=0; + typename LabelSetType::const_iterator it; + int i; + for(it=m_Labels.begin(), i = 0; + it != m_Labels.end(); ++it, ++i) { + double tmp = m_InternalInterpolators[i]->EvaluateAtContinuousIndex(cindex); + if( tmp > value) { + value = tmp; + best_label = (*it); + } + } + return best_label; +} + +} // namespace itk + +#endif diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h new file mode 100644 index 00000000000..b1b27c1eb3f --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -0,0 +1,72 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkLabelSelectionImageAdaptor_h +#define itkLabelSelectionImageAdaptor_h + +#include "itkLabelSelectionPixelAccessor.h" + +namespace itk +{ +/** \class LabelSelectionImageAdaptor + * \brief Presents a label image as a binary image of one label + * + * Additional casting is performed according to the input and output image + * types following C++ default casting rules. + * + * \ingroup ImageAdaptors + * \ingroup ITKImageAdaptors + * \ingroup GenericLabelInterpolator + */ +template< class TImage, class TOutputPixelType > +class ITK_EXPORT LabelSelectionImageAdaptor:public + ImageAdaptor< TImage, + Accessor::LabelSelectionPixelAccessor< + typename TImage::PixelType, + TOutputPixelType > > +{ +public: + /** Standard class typedefs. */ + typedef LabelSelectionImageAdaptor Self; + typedef ImageAdaptor< TImage, Accessor::LabelSelectionPixelAccessor< + typename TImage::PixelType, + TOutputPixelType > > Superclass; + + typedef SmartPointer< Self > Pointer; + typedef SmartPointer< const Self > ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(LabelSelectionImageAdaptor, ImageAdaptor); + + void SetAcceptedValue(typename TImage::PixelType value) { + this->GetPixelAccessor().SetAcceptedValue(value); + } + +protected: + LabelSelectionImageAdaptor() {} + virtual ~LabelSelectionImageAdaptor() {} + +private: + LabelSelectionImageAdaptor(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented +}; +} // end namespace itk + +#endif diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h new file mode 100644 index 00000000000..12db2bf2519 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h @@ -0,0 +1,63 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#ifndef itkLabelSelectionPixelAccessor_h +#define itkLabelSelectionPixelAccessor_h + +#include "itkImageAdaptor.h" + +namespace itk +{ +namespace Accessor +{ +/** \class LabelSelectionPixelAccessor + * \brief Return a binary mask of the selected label + * + * LabelSelectionPixelAccessor is templated over an internal type and an + * external type representation. This class cast the input + * applies the function to it and cast the result according + * to the types defined as template parameters + * + * \ingroup ImageAdaptors + * \ingroup ITKImageAdaptors + * \ingroup GenericLabelInterpolator + */ +template< class TInternalType, class TExternalType > +class ITK_EXPORT LabelSelectionPixelAccessor +{ +public: + /** External typedef. It defines the external aspect + * that this class will exhibit. */ + typedef TExternalType ExternalType; + + /** Internal typedef. It defines the internal real + * representation of data. */ + typedef TInternalType InternalType; + + void SetAcceptedValue(TInternalType value) { m_AcceptedValue = value; } + + inline TExternalType Get(const TInternalType & input) const + { + return (TExternalType)( + ( input == m_AcceptedValue ) ? 1 : 0 ); + } +protected: + TInternalType m_AcceptedValue; +}; +} // end namespace Accessor +} // end namespace itk +#endif diff --git a/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake new file mode 100644 index 00000000000..d4942f11fcd --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake @@ -0,0 +1,21 @@ +set(DOCUMENTATION "The basic idea of this generic interpolator for label images is to interpolate each label with an ordinary image interpolator, and return the label with the highest value. This is the idea used by the itk::LabelImageGaussianInterpolateImageFunction interpolator. Unfortunately, this class is currently limited to Gaussian interpolation. Using generic programming, our proposed interpolator extends this idea to any image interpolator. Combined with linear interpolation, this results in similar or better accuracy and much improved computation speeds on a test image. + +A more detailed description can be found in the Insight Journal article:: + +Schaerer, J., Roche, F., Belaroussi, B. \"A generic interpolator for multi-label images\". + http://hdl.handle.net/10380/3506 + http://www.insight-journal.org/browse/publication/950 + December, 2014. +") + +itk_module(GenericLabelInterpolator + DEPENDS + ITKSmoothing + ITKImageAdaptors + TEST_DEPENDS + ITKTestKernel + ITKImageGrid + EXCLUDE_FROM_DEFAULT + DESCRIPTION + "${DOCUMENTATION}" +) diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 new file mode 100644 index 00000000000..eaf48e38dbe --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 @@ -0,0 +1 @@ +7ccd2dcfe9736b82a696a6c71d4dfbb8 diff --git a/Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt new file mode 100644 index 00000000000..78e779b8473 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt @@ -0,0 +1,18 @@ +itk_module_test() + +set(GenericLabelInterpolatorTests + RotateLabels.cxx + ) + +CreateTestDriver(GenericLabelInterpolator "${GenericLabelInterpolator-Test_LIBRARIES}" "${GenericLabelInterpolatorTests}") + +itk_add_test(NAME GenericLabelInterpolatorRotateLabelsTest + COMMAND GenericLabelInterpolatorTestDriver + --compare + ${ITK_TEST_OUTPUT_DIR}/gl_gaussian_3.mha + DATA{Baseline/gl_gaussian_3.mha} + RotateLabels + DATA{Input/classification.mha} + ${ITK_TEST_OUTPUT_DIR}/ + 3 + ) diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 new file mode 100644 index 00000000000..f3a08e3f19b --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 @@ -0,0 +1 @@ +861752fa4c3c619e09bba6daf17643e2 diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx new file mode 100644 index 00000000000..138c095959e --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -0,0 +1,194 @@ +/*========================================================================= + * + * Copyright Insight Software Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + *=========================================================================*/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "itkLabelImageGenericInterpolateImageFunction.h" +#include "itkLabelSelectionImageAdaptor.h" +#include "itkLabelSelectionPixelAccessor.h" + +/* This demo is a torture test for interpolators: it takes an input label map, + * rotates it one full turn in ten steps, and writes the result */ + +template +void +RotateNTimes(typename ImageType::Pointer input, + typename itk::InterpolateImageFunction* interpolator, + unsigned int number_of_rotations, std::string filename_prefix, + std::string output_directory) +{ + typedef itk::VersorRigid3DTransform TransformType; + typedef itk::ResampleImageFilter ResampleFilterType; + TransformType::AxisType axis; + axis[0]=0; + axis[1]=1; + axis[2]=0; + TransformType::InputPointType center; + center[0] = 144; + center[1] = 86; + center[2] = 101; + TransformType::Pointer rot = TransformType::New(); + rot->SetCenter(center); + rot->SetRotation(axis,2.*M_PI/number_of_rotations); + + typename ResampleFilterType::Pointer rs = ResampleFilterType::New(); + rs->SetInput( input ); + rs->SetReferenceImage( input ); + rs->SetUseReferenceImage(true); + rs->SetTransform(rot); + rs->SetInterpolator(interpolator); + typename ImageType::Pointer out; + itk::TimeProbe timer; timer.Start(); + for (unsigned i = 0; iSetReferenceImage( input ); + rs->SetUseReferenceImage(true); + rs->Update(); + out = rs->GetOutput(); + out->DisconnectPipeline(); + rs->SetInput(out); + rs->SetTransform(rot); + } + timer.Stop(); + typedef itk::Testing::ComparisonImageFilter ComparisonFilterType; + typename ComparisonFilterType::Pointer compare = ComparisonFilterType::New(); + compare->SetValidInput( input ); + compare->SetTestInput( out ); + compare->Update(); + std::cout << "Pixels with differences: " << std::setw(8) << compare->GetNumberOfPixelsWithDifferences() << + " ( " << std::fixed << std::setprecision(2) << static_cast(compare->GetNumberOfPixelsWithDifferences()) / + input->GetLargestPossibleRegion().GetNumberOfPixels() * 100.<< + "% ) in " << timer.GetTotal() << "s" << std::endl; + typedef itk::ImageFileWriter< ImageType > WriterType; + typename WriterType::Pointer writer = WriterType::New(); + writer->SetUseCompression(true); + writer->SetInput( out ); + std::ostringstream fname_stream; + fname_stream << output_directory << "/" << filename_prefix + << "_" << number_of_rotations << ".mha"; + writer->SetFileName(fname_stream.str()); + writer->Write(); +} + + +// The BSpline interpolator has more arguments than other interpolators, so we set the additional parameter to the default value +template class BSplineInterpolator : public itk::BSplineInterpolateImageFunction {}; + +template class FixedGaussianInterpolator : public itk::GaussianInterpolateImageFunction +{ + public: + typedef FixedGaussianInterpolator Self; + typedef itk::GaussianInterpolateImageFunction Superclass; + typedef itk::SmartPointer Pointer; + typedef itk::SmartPointer ConstPointer; + + /** Run-time type information (and related methods). */ + itkTypeMacro( FixedGaussianInterpolator, GaussianInterpolateImageFunction ); + + /** Method for creation through the object factory. */ + itkNewMacro( Self ); + FixedGaussianInterpolator() + { + this->m_Alpha = 1.0; + this->m_Sigma.Fill(0.3); + } +}; + +int RotateLabels(int argc, char *argv[]) +{ + if( argc != 4 ) + { + std::cout << "Usage: " << argv[0] << " inputImage outputDirectory numberOfRotation" << std::endl; + return EXIT_FAILURE; + } + std::string inputFileName = argv[1]; + std::string outputDirectory = argv[2]; + std::istringstream stream(argv[3]); + unsigned int numberOfRotations = 0; + stream >> numberOfRotations; + if( numberOfRotations < 1 ) + { + std::cout << "numberOfRotation must be strictly positive. Given value: " + << numberOfRotations << std::endl; + return EXIT_FAILURE; + } + typedef unsigned char PixelType; + const unsigned int Dimension = 3; + typedef itk::Image< PixelType, Dimension > ImageType; + typedef itk::ImageFileReader ReaderType; + ReaderType::Pointer r = ReaderType::New(); + r->SetFileName(inputFileName); + r->Update(); + + std::cout << "Testing with " << numberOfRotations << " rotations..." << std::endl << std::endl; + + std::cout << "Nearest neighbor interpolator... " << std::flush; + typedef itk::NearestNeighborInterpolateImageFunction NNInterpolatorType; + NNInterpolatorType::Pointer nn_interp = NNInterpolatorType::New(); + RotateNTimes(r->GetOutput(), nn_interp, numberOfRotations, "nearest", outputDirectory); + + std::cout << "Linear interpolator... " << std::flush; + typedef itk::LinearInterpolateImageFunction LInterpolatorType; + LInterpolatorType::Pointer l_interp = LInterpolatorType::New(); + RotateNTimes(r->GetOutput(), l_interp, numberOfRotations, "linear", outputDirectory); + + std::cout << "Label Gaussian interpolator type... " << std::flush; + typedef itk::LabelImageGaussianInterpolateImageFunction LGInterpolatorType; + LGInterpolatorType::Pointer lg_interp = LGInterpolatorType::New(); + lg_interp->SetSigma(0.3); + RotateNTimes(r->GetOutput(), lg_interp, numberOfRotations, "label_gaussian", outputDirectory); + + std::cout << "Generic label interpolator with nearest neighbor... " << std::flush; + typedef itk::LabelImageGenericInterpolateImageFunction GNNInterpolatorType; + GNNInterpolatorType::Pointer gnn_interp = GNNInterpolatorType::New(); + RotateNTimes(r->GetOutput(), gnn_interp, numberOfRotations, "gl_nearest", outputDirectory); + + std::cout << "Generic label interpolator with linear interpolation... " << std::flush; + typedef itk::LabelImageGenericInterpolateImageFunction GLInterpolatorType; + GLInterpolatorType::Pointer gl_interp = GLInterpolatorType::New(); + RotateNTimes(r->GetOutput(), gl_interp, numberOfRotations, "gl_linear", outputDirectory); + + std::cout << "Generic label interpolator with B-Spline interpolation... " << std::flush; + typedef itk::LabelImageGenericInterpolateImageFunction GBSInterpolatorType; + GBSInterpolatorType::Pointer gbs_interp = GBSInterpolatorType::New(); + RotateNTimes(r->GetOutput(), gbs_interp, numberOfRotations, "gl_bspline", outputDirectory); + + std::cout << "Generic label interpolator with Gaussian interpolation... " << std::flush; + typedef itk::LabelImageGenericInterpolateImageFunction GGInterpolatorType; + GGInterpolatorType::Pointer gg_interp = GGInterpolatorType::New(); + RotateNTimes(r->GetOutput(), gg_interp, numberOfRotations, "gl_gaussian", outputDirectory); + + std::cout << std::endl; + + + return EXIT_SUCCESS; +} From e1072253a5c13458976c5d5b35e2b49074c828a7 Mon Sep 17 00:00:00 2001 From: Francois Budin Date: Mon, 30 May 2016 07:53:30 -0400 Subject: [PATCH 02/42] ENH: Replacing M_PI with itk::Math::pi M_PI is not available on all platform. --- .../test/RotateLabels.cxx | 132 ++++++++++-------- 1 file changed, 70 insertions(+), 62 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index 138c095959e..c949d435d2f 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -41,36 +41,38 @@ template void -RotateNTimes(typename ImageType::Pointer input, - typename itk::InterpolateImageFunction* interpolator, - unsigned int number_of_rotations, std::string filename_prefix, - std::string output_directory) +RotateNTimes(typename ImageType::Pointer input, + typename itk::InterpolateImageFunction * interpolator, + unsigned int number_of_rotations, + std::string filename_prefix, + std::string output_directory) { - typedef itk::VersorRigid3DTransform TransformType; - typedef itk::ResampleImageFilter ResampleFilterType; - TransformType::AxisType axis; - axis[0]=0; - axis[1]=1; - axis[2]=0; + typedef itk::VersorRigid3DTransform TransformType; + typedef itk::ResampleImageFilter ResampleFilterType; + TransformType::AxisType axis; + axis[0] = 0; + axis[1] = 1; + axis[2] = 0; TransformType::InputPointType center; center[0] = 144; center[1] = 86; center[2] = 101; TransformType::Pointer rot = TransformType::New(); rot->SetCenter(center); - rot->SetRotation(axis,2.*M_PI/number_of_rotations); + rot->SetRotation(axis, 2. * itk::Math::pi / number_of_rotations); typename ResampleFilterType::Pointer rs = ResampleFilterType::New(); - rs->SetInput( input ); - rs->SetReferenceImage( input ); + rs->SetInput(input); + rs->SetReferenceImage(input); rs->SetUseReferenceImage(true); rs->SetTransform(rot); rs->SetInterpolator(interpolator); typename ImageType::Pointer out; - itk::TimeProbe timer; timer.Start(); - for (unsigned i = 0; iSetReferenceImage( input ); + rs->SetReferenceImage(input); rs->SetUseReferenceImage(true); rs->Update(); out = rs->GetOutput(); @@ -79,43 +81,47 @@ RotateNTimes(typename ImageType::Pointer input, rs->SetTransform(rot); } timer.Stop(); - typedef itk::Testing::ComparisonImageFilter ComparisonFilterType; - typename ComparisonFilterType::Pointer compare = ComparisonFilterType::New(); - compare->SetValidInput( input ); - compare->SetTestInput( out ); + typedef itk::Testing::ComparisonImageFilter ComparisonFilterType; + typename ComparisonFilterType::Pointer compare = ComparisonFilterType::New(); + compare->SetValidInput(input); + compare->SetTestInput(out); compare->Update(); - std::cout << "Pixels with differences: " << std::setw(8) << compare->GetNumberOfPixelsWithDifferences() << - " ( " << std::fixed << std::setprecision(2) << static_cast(compare->GetNumberOfPixelsWithDifferences()) / - input->GetLargestPossibleRegion().GetNumberOfPixels() * 100.<< - "% ) in " << timer.GetTotal() << "s" << std::endl; - typedef itk::ImageFileWriter< ImageType > WriterType; - typename WriterType::Pointer writer = WriterType::New(); + std::cout << "Pixels with differences: " << std::setw(8) << compare->GetNumberOfPixelsWithDifferences() << " ( " + << std::fixed << std::setprecision(2) + << static_cast(compare->GetNumberOfPixelsWithDifferences()) / + input->GetLargestPossibleRegion().GetNumberOfPixels() * 100. + << "% ) in " << timer.GetTotal() << "s" << std::endl; + typedef itk::ImageFileWriter WriterType; + typename WriterType::Pointer writer = WriterType::New(); writer->SetUseCompression(true); - writer->SetInput( out ); + writer->SetInput(out); std::ostringstream fname_stream; - fname_stream << output_directory << "/" << filename_prefix - << "_" << number_of_rotations << ".mha"; + fname_stream << output_directory << "/" << filename_prefix << "_" << number_of_rotations << ".mha"; writer->SetFileName(fname_stream.str()); writer->Write(); } -// The BSpline interpolator has more arguments than other interpolators, so we set the additional parameter to the default value -template class BSplineInterpolator : public itk::BSplineInterpolateImageFunction {}; +// The BSpline interpolator has more arguments than other interpolators, so we set the additional parameter to the +// default value +template +class BSplineInterpolator : public itk::BSplineInterpolateImageFunction +{}; -template class FixedGaussianInterpolator : public itk::GaussianInterpolateImageFunction +template +class FixedGaussianInterpolator : public itk::GaussianInterpolateImageFunction { - public: - typedef FixedGaussianInterpolator Self; - typedef itk::GaussianInterpolateImageFunction Superclass; - typedef itk::SmartPointer Pointer; - typedef itk::SmartPointer ConstPointer; +public: + typedef FixedGaussianInterpolator Self; + typedef itk::GaussianInterpolateImageFunction Superclass; + typedef itk::SmartPointer Pointer; + typedef itk::SmartPointer ConstPointer; /** Run-time type information (and related methods). */ - itkTypeMacro( FixedGaussianInterpolator, GaussianInterpolateImageFunction ); + itkTypeMacro(FixedGaussianInterpolator, GaussianInterpolateImageFunction); /** Method for creation through the object factory. */ - itkNewMacro( Self ); + itkNewMacro(Self); FixedGaussianInterpolator() { this->m_Alpha = 1.0; @@ -123,67 +129,69 @@ template class FixedGaussianInterpolator : publ } }; -int RotateLabels(int argc, char *argv[]) +int +RotateLabels(int argc, char * argv[]) { - if( argc != 4 ) + if (argc != 4) { std::cout << "Usage: " << argv[0] << " inputImage outputDirectory numberOfRotation" << std::endl; return EXIT_FAILURE; } - std::string inputFileName = argv[1]; - std::string outputDirectory = argv[2]; + std::string inputFileName = argv[1]; + std::string outputDirectory = argv[2]; std::istringstream stream(argv[3]); - unsigned int numberOfRotations = 0; + unsigned int numberOfRotations = 0; stream >> numberOfRotations; - if( numberOfRotations < 1 ) + if (numberOfRotations < 1) { - std::cout << "numberOfRotation must be strictly positive. Given value: " - << numberOfRotations << std::endl; + std::cout << "numberOfRotation must be strictly positive. Given value: " << numberOfRotations << std::endl; return EXIT_FAILURE; } - typedef unsigned char PixelType; - const unsigned int Dimension = 3; - typedef itk::Image< PixelType, Dimension > ImageType; - typedef itk::ImageFileReader ReaderType; - ReaderType::Pointer r = ReaderType::New(); + typedef unsigned char PixelType; + const unsigned int Dimension = 3; + typedef itk::Image ImageType; + typedef itk::ImageFileReader ReaderType; + ReaderType::Pointer r = ReaderType::New(); r->SetFileName(inputFileName); r->Update(); std::cout << "Testing with " << numberOfRotations << " rotations..." << std::endl << std::endl; std::cout << "Nearest neighbor interpolator... " << std::flush; - typedef itk::NearestNeighborInterpolateImageFunction NNInterpolatorType; - NNInterpolatorType::Pointer nn_interp = NNInterpolatorType::New(); + typedef itk::NearestNeighborInterpolateImageFunction NNInterpolatorType; + NNInterpolatorType::Pointer nn_interp = NNInterpolatorType::New(); RotateNTimes(r->GetOutput(), nn_interp, numberOfRotations, "nearest", outputDirectory); std::cout << "Linear interpolator... " << std::flush; - typedef itk::LinearInterpolateImageFunction LInterpolatorType; - LInterpolatorType::Pointer l_interp = LInterpolatorType::New(); + typedef itk::LinearInterpolateImageFunction LInterpolatorType; + LInterpolatorType::Pointer l_interp = LInterpolatorType::New(); RotateNTimes(r->GetOutput(), l_interp, numberOfRotations, "linear", outputDirectory); std::cout << "Label Gaussian interpolator type... " << std::flush; - typedef itk::LabelImageGaussianInterpolateImageFunction LGInterpolatorType; - LGInterpolatorType::Pointer lg_interp = LGInterpolatorType::New(); + typedef itk::LabelImageGaussianInterpolateImageFunction LGInterpolatorType; + LGInterpolatorType::Pointer lg_interp = LGInterpolatorType::New(); lg_interp->SetSigma(0.3); RotateNTimes(r->GetOutput(), lg_interp, numberOfRotations, "label_gaussian", outputDirectory); std::cout << "Generic label interpolator with nearest neighbor... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction GNNInterpolatorType; + typedef itk::LabelImageGenericInterpolateImageFunction + GNNInterpolatorType; GNNInterpolatorType::Pointer gnn_interp = GNNInterpolatorType::New(); RotateNTimes(r->GetOutput(), gnn_interp, numberOfRotations, "gl_nearest", outputDirectory); std::cout << "Generic label interpolator with linear interpolation... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction GLInterpolatorType; + typedef itk::LabelImageGenericInterpolateImageFunction + GLInterpolatorType; GLInterpolatorType::Pointer gl_interp = GLInterpolatorType::New(); RotateNTimes(r->GetOutput(), gl_interp, numberOfRotations, "gl_linear", outputDirectory); std::cout << "Generic label interpolator with B-Spline interpolation... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction GBSInterpolatorType; + typedef itk::LabelImageGenericInterpolateImageFunction GBSInterpolatorType; GBSInterpolatorType::Pointer gbs_interp = GBSInterpolatorType::New(); RotateNTimes(r->GetOutput(), gbs_interp, numberOfRotations, "gl_bspline", outputDirectory); std::cout << "Generic label interpolator with Gaussian interpolation... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction GGInterpolatorType; + typedef itk::LabelImageGenericInterpolateImageFunction GGInterpolatorType; GGInterpolatorType::Pointer gg_interp = GGInterpolatorType::New(); RotateNTimes(r->GetOutput(), gg_interp, numberOfRotations, "gl_gaussian", outputDirectory); From fea973734f6801032d65f5418f90b2c48b7c14ba Mon Sep 17 00:00:00 2001 From: Francois Budin Date: Tue, 31 May 2016 08:39:47 -0400 Subject: [PATCH 03/42] ENH: Remove unused variables warning Some parameters declared in function definitions are not used. To avoid compiler warning, we use the macro itkNotUsed(). --- ...elImageGenericInterpolateImageFunction.hxx | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index 73ef0647485..61c1cf26d68 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -24,31 +24,35 @@ namespace itk { -template class TInterpolator , typename TCoordRep> -LabelImageGenericInterpolateImageFunction -::LabelImageGenericInterpolateImageFunction() -{ -} +template class TInterpolator, typename TCoordRep> +LabelImageGenericInterpolateImageFunction:: + LabelImageGenericInterpolateImageFunction() +{} -template class TInterpolator , typename TCoordRep> -void LabelImageGenericInterpolateImageFunction -::SetInputImage( const TInputImage *image ) { +template class TInterpolator, typename TCoordRep> +void +LabelImageGenericInterpolateImageFunction::SetInputImage( + const TInputImage * image) +{ /** We have one adaptor and one interpolator per label to keep the class thread-safe: * changing the adaptor's accepted value wouldn't work when called from a multi-threaded filter */ - if (image) { + if (image) + { m_Labels.clear(); typedef itk::ImageRegionConstIterator IteratorType; - IteratorType it(image,image->GetLargestPossibleRegion()); + IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); - for (; !it.IsAtEnd(); ++it) { + for (; !it.IsAtEnd(); ++it) + { m_Labels.insert(it.Get()); } m_InternalInterpolators.clear(); m_LabelSelectionAdaptors.clear(); - for(typename LabelSetType::const_iterator i=m_Labels.begin(); i != m_Labels.end(); ++i) { + for (typename LabelSetType::const_iterator i = m_Labels.begin(); i != m_Labels.end(); ++i) + { typename LabelSelectionAdaptorType::Pointer adapt = LabelSelectionAdaptorType::New(); // This adaptor doesn't implement Set() so this should be safe - adapt->SetImage(const_cast(image)); + adapt->SetImage(const_cast(image)); adapt->SetAcceptedValue(*i); m_LabelSelectionAdaptors.push_back(adapt); typename InternalInterpolatorType::Pointer interp = InternalInterpolatorType::New(); @@ -59,27 +63,28 @@ void LabelImageGenericInterpolateImageFunction class TInterpolator , typename TCoordRep> -typename LabelImageGenericInterpolateImageFunction -::OutputType -LabelImageGenericInterpolateImageFunction -::EvaluateAtContinuousIndex( const ContinuousIndexType & cindex, OutputType * grad ) const +template class TInterpolator, typename TCoordRep> +typename LabelImageGenericInterpolateImageFunction::OutputType +LabelImageGenericInterpolateImageFunction::EvaluateAtContinuousIndex( + const ContinuousIndexType & cindex, + OutputType * itkNotUsed(grad)) const { /** Interpolate the binary mask corresponding to each label and return the label * with the highest value */ - double value=0; - typename TInputImage::PixelType best_label=0; + double value = 0; + typename TInputImage::PixelType best_label = 0; typename LabelSetType::const_iterator it; - int i; - for(it=m_Labels.begin(), i = 0; - it != m_Labels.end(); ++it, ++i) { + int i; + for (it = m_Labels.begin(), i = 0; it != m_Labels.end(); ++it, ++i) + { double tmp = m_InternalInterpolators[i]->EvaluateAtContinuousIndex(cindex); - if( tmp > value) { + if (tmp > value) + { value = tmp; best_label = (*it); } } - return best_label; + return best_label; } } // namespace itk From 4e0250bb42d4ed2083a3ee299b8aed754ada55fc Mon Sep 17 00:00:00 2001 From: Francois Budin Date: Thu, 13 Oct 2016 17:52:15 -0400 Subject: [PATCH 04/42] BUG: m_Alpha and m_Sigma are private variables FixedGaussianInterpolator was trying to set m_Alpha and m_Sigma without using the 'Set' functions to do so. But m_Alpha and m_Sigma are private variables declared in itk::GaussianInterpolateImageFunction which is the parent class of FixedGaussianInterpolator. --- .../Filtering/GenericLabelInterpolator/test/RotateLabels.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index c949d435d2f..38051019a67 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -124,8 +124,8 @@ class FixedGaussianInterpolator : public itk::GaussianInterpolateImageFunctionm_Alpha = 1.0; - this->m_Sigma.Fill(0.3); + this->SetAlpha(1.0); + this->SetSigma(0.3); } }; From c93d77d2de549c2ae7f17068e984a957e8b334b0 Mon Sep 17 00:00:00 2001 From: Jon Haitz Legarreta Date: Wed, 17 Jan 2018 17:36:04 +0100 Subject: [PATCH 05/42] ENH: Require cmake minimum version to be 3.9.5. Require CMake minimum version to be 3.9.5 following ITKv5 requiring C++11: https://discourse.itk.org/t/minimum-cmake-version-update/585 --- Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt index d24d1c8fbb5..a3290d3bb51 100644 --- a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt +++ b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.9) +cmake_minimum_required(VERSION 3.9.5) project(GenericLabelInterpolator) if(NOT ITK_SOURCE_DIR) From bb73f94f6d2a664715e6c2c0dd498e92732cbdb8 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 16 Dec 2017 19:16:58 -0600 Subject: [PATCH 06/42] ENH: ITKv5 override consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provide remove virtual and override Use clang-tidy to add ITK_OVERRIDE, and to remove redundant virtual on functions. cd ../ITK; clang-tidy -p ITK-clangtidy $find Modules/[A-J]* -name *.cxx |fgrep -v ThirdParty) -checks=-*,modernize-use-override -header-filter=.* -fix clang-tidy -p ITK-clangtidy $(find Modules/[K-Z]* -name *.cxx |fgrep -v ThirdParty) -checks=-*,modernize-use-override -header-filter=.* -fix https://stackoverflow.com/questions/39932391/virtual-override-or-both-c When you override a function you don't technically need to write either virtual or override. The original base class declaration needs the keyword virtual to mark it as virtual. In the derived class the function is virtual by way of having the ¹same type as the base class function. However, an override can help avoid bugs by producing a compilation error when the intended override isn't technically an override. E.g. that the function type isn't exactly like the base class function. Or that a maintenance of the base class changes that function's type, e.g. adding a defaulted argument. In the same way, a virtual keyword in the derived class can make such a bug more subtle, by ensuring that the function is still is virtual in further derived classes. So the general advice is, virtual for the base class function declaration. This is technically necessary. Use override (only) for a derived class' override. This helps with maintenance. --- ...abelImageGenericInterpolateImageFunction.h | 59 ++++++++++--------- .../include/itkLabelSelectionImageAdaptor.h | 29 +++++---- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index e3064ae1327..6e45a877b43 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -37,26 +37,25 @@ namespace itk * * \ingroup GenericLabelInterpolator */ -template class TInterpolator, typename TCoordRep=double > -class ITK_EXPORT LabelImageGenericInterpolateImageFunction : - public InterpolateImageFunction +template class TInterpolator, typename TCoordRep = double> +class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateImageFunction { public: /** Standard class typedefs. */ - typedef LabelImageGenericInterpolateImageFunction Self; - typedef InterpolateImageFunction Superclass; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; - typedef typename TInputImage::PixelType InputPixelType; + typedef LabelImageGenericInterpolateImageFunction Self; + typedef InterpolateImageFunction Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + typedef typename TInputImage::PixelType InputPixelType; /** Run-time type information (and related methods). */ - itkTypeMacro( LabelImageGenericInterpolateImageFunction, InterpolateImageFunction ); + itkTypeMacro(LabelImageGenericInterpolateImageFunction, InterpolateImageFunction); /** Method for creation through the object factory. */ - itkNewMacro( Self ); + itkNewMacro(Self); /** ImageDimension constant */ - itkStaticConstMacro( ImageDimension, unsigned int, TInputImage::ImageDimension ); + itkStaticConstMacro(ImageDimension, unsigned int, TInputImage::ImageDimension); /** OutputType typedef support. */ typedef typename Superclass::OutputType OutputType; @@ -73,46 +72,48 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : /** ContinuousIndex typedef support. */ typedef typename Superclass::ContinuousIndexType ContinuousIndexType; - typedef LabelSelectionImageAdaptor LabelSelectionAdaptorType; + typedef LabelSelectionImageAdaptor LabelSelectionAdaptorType; // The interpolator used for individual binary masks corresponding to each label - typedef TInterpolator InternalInterpolatorType; + typedef TInterpolator InternalInterpolatorType; /** * Evaluate at the given index */ - virtual OutputType EvaluateAtContinuousIndex( - const ContinuousIndexType & cindex ) const - { - return this->EvaluateAtContinuousIndex( cindex, NULL ); - } + OutputType + EvaluateAtContinuousIndex(const ContinuousIndexType & cindex) const ITK_OVERRIDE + { + return this->EvaluateAtContinuousIndex(cindex, NULL); + } - virtual void SetInputImage( const TInputImage *image ); + void + SetInputImage(const TInputImage * image) ITK_OVERRIDE; protected: LabelImageGenericInterpolateImageFunction(); - ~LabelImageGenericInterpolateImageFunction(){}; + ~LabelImageGenericInterpolateImageFunction() ITK_OVERRIDE {}; - std::vector m_InternalInterpolators; - std::vector m_LabelSelectionAdaptors; - typedef std::set LabelSetType; - LabelSetType m_Labels; + std::vector m_InternalInterpolators; + std::vector m_LabelSelectionAdaptors; + typedef std::set LabelSetType; + LabelSetType m_Labels; private: - LabelImageGenericInterpolateImageFunction( const Self& ); //purposely not implemented - void operator=( const Self& ); //purposely not implemented + LabelImageGenericInterpolateImageFunction(const Self &); // purposely not implemented + void + operator=(const Self &); // purposely not implemented /** * Evaluate function value at the given index */ - virtual OutputType EvaluateAtContinuousIndex( - const ContinuousIndexType &, OutputType * ) const; + virtual OutputType + EvaluateAtContinuousIndex(const ContinuousIndexType &, OutputType *) const; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION -#include "itkLabelImageGenericInterpolateImageFunction.hxx" +# include "itkLabelImageGenericInterpolateImageFunction.hxx" #endif #endif diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index b1b27c1eb3f..c02201ce26d 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -32,22 +32,18 @@ namespace itk * \ingroup ITKImageAdaptors * \ingroup GenericLabelInterpolator */ -template< class TImage, class TOutputPixelType > -class ITK_EXPORT LabelSelectionImageAdaptor:public - ImageAdaptor< TImage, - Accessor::LabelSelectionPixelAccessor< - typename TImage::PixelType, - TOutputPixelType > > +template +class ITK_EXPORT LabelSelectionImageAdaptor + : public ImageAdaptor> { public: /** Standard class typedefs. */ typedef LabelSelectionImageAdaptor Self; - typedef ImageAdaptor< TImage, Accessor::LabelSelectionPixelAccessor< - typename TImage::PixelType, - TOutputPixelType > > Superclass; + typedef ImageAdaptor> + Superclass; - typedef SmartPointer< Self > Pointer; - typedef SmartPointer< const Self > ConstPointer; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); @@ -55,17 +51,20 @@ class ITK_EXPORT LabelSelectionImageAdaptor:public /** Run-time type information (and related methods). */ itkTypeMacro(LabelSelectionImageAdaptor, ImageAdaptor); - void SetAcceptedValue(typename TImage::PixelType value) { + void + SetAcceptedValue(typename TImage::PixelType value) + { this->GetPixelAccessor().SetAcceptedValue(value); } protected: LabelSelectionImageAdaptor() {} - virtual ~LabelSelectionImageAdaptor() {} + ~LabelSelectionImageAdaptor() ITK_OVERRIDE {} private: - LabelSelectionImageAdaptor(const Self &); //purposely not implemented - void operator=(const Self &); //purposely not implemented + LabelSelectionImageAdaptor(const Self &); // purposely not implemented + void + operator=(const Self &); // purposely not implemented }; } // end namespace itk From 3828cfb2da688c28330b99e45ef8c1864eaa1428 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 16 Dec 2017 19:36:25 -0600 Subject: [PATCH 07/42] COMP: Use C++11 override directly git grep -l "ITK_OVERRIDE" | fgrep -v itk_compiler_detection.h | fgrep -v CMakeLists.txt |fgrep -v .cmake | xargs sed -i '' -e "s/ITK_OVERRIDE/override/g" --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 6 +++--- .../include/itkLabelSelectionImageAdaptor.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index 6e45a877b43..a790941a678 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -81,17 +81,17 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI * Evaluate at the given index */ OutputType - EvaluateAtContinuousIndex(const ContinuousIndexType & cindex) const ITK_OVERRIDE + EvaluateAtContinuousIndex(const ContinuousIndexType & cindex) const override { return this->EvaluateAtContinuousIndex(cindex, NULL); } void - SetInputImage(const TInputImage * image) ITK_OVERRIDE; + SetInputImage(const TInputImage * image) override; protected: LabelImageGenericInterpolateImageFunction(); - ~LabelImageGenericInterpolateImageFunction() ITK_OVERRIDE {}; + ~LabelImageGenericInterpolateImageFunction() override {}; std::vector m_InternalInterpolators; std::vector m_LabelSelectionAdaptors; diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index c02201ce26d..cff34f12604 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -59,7 +59,7 @@ class ITK_EXPORT LabelSelectionImageAdaptor protected: LabelSelectionImageAdaptor() {} - ~LabelSelectionImageAdaptor() ITK_OVERRIDE {} + ~LabelSelectionImageAdaptor() override {} private: LabelSelectionImageAdaptor(const Self &); // purposely not implemented From 8478c95682dc2e144887819134b176efae32d5ad Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sun, 17 Dec 2017 08:22:47 -0600 Subject: [PATCH 08/42] COMP: Use nullptr instead of 0 or NULL The check converts the usage of null pointer constants (eg. NULL, 0) to use the new C++11 nullptr keyword. SRCDIR= #My local SRC BLDDIR= #My local BLD clang-tidy -p ${BLD} $(find Modules/[A-J]* -name "*.cxx" \|fgrep -v ThirdParty) -checks=-*,modernize-use-nullptr -header-filter=.* -fix clang-tidy -p ${BLD} $(find Modules/[K-Z]* -name "*.cxx" \|fgrep -v ThirdParty) -checks=-*,modernize-use-nullptr -header-filter=.* -fix --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index a790941a678..b13d2c1e389 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -83,7 +83,7 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI OutputType EvaluateAtContinuousIndex(const ContinuousIndexType & cindex) const override { - return this->EvaluateAtContinuousIndex(cindex, NULL); + return this->EvaluateAtContinuousIndex(cindex, nullptr); } void From 34267a51dfd3b98611269b6364c2793330d09f2b Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Mon, 12 Feb 2018 15:20:33 -0600 Subject: [PATCH 09/42] STYLE: Modernize to C++11 conventions STYLE: Use auto for variable creation This check is responsible for using the auto type specifier for variable declarations to improve code readability and maintainability. The auto type specifier will only be introduced in situations where the variable type matches the type of the initializer expression. In other words auto should deduce the same type that was originally spelled in the source cd /Users/johnsonhj/Dashboard/src/ITK-clangtidy/ run-clang-tidy.py -checks=-*,modernize-use-auto -header-filter=.* -fix use auto when declaring iterators use auto when initializing with a cast to avoid duplicating the type name use auto when initializing with a template cast to avoid duplicating the type name use auto when initializing with new to avoid duplicating the type name SRCDIR=/Users/johnsonhj/Dashboard/src/ITK #My local SRC BLDDIR=/Users/johnsonhj/Dashboard/src/ITK-clangtidy/ #My local BLD PERF: Replace explicit return calls of constructor Replaces explicit calls to the constructor in a return with a braced initializer list. This way the return type is not needlessly duplicated in the function definition and the return statement. SRCDIR=/Users/johnsonhj/Dashboard/src/ITK #My local SRC BLDDIR=/Users/johnsonhj/Dashboard/src/ITK-clangtidy/ #My local BLD cd /Users/johnsonhj/Dashboard/src/ITK-clangtidy/ run-clang-tidy.py -checks=-*,modernize-return-braced-init-list -header-filter=.* -fix PERF: Allow compiler to choose best way to construct a copy With move semantics added to the language and the standard library updated with move constructors added for many types it is now interesting to take an argument directly by value, instead of by const-reference, and then copy. This check allows the compiler to take care of choosing the best way to construct the copy. The transformation is usually beneficial when the calling code passes an rvalue and assumes the move construction is a cheap operation. This short example illustrates how the construction of the value happens: class Foo { public: - Foo(const std::string &Copied, const std::string &ReadOnly) - : Copied(Copied), ReadOnly(ReadOnly) {} + Foo(std::string Moved, const std::string &ReadOnly) + : Copied(std::move(Moved)), ReadOnly(ReadOnly) {} private: private: std::string Copied; const std::string &ReadOnly; }; SRCDIR=/Users/johnsonhj/Dashboard/src/ITK #My local SRC BLDDIR=/Users/johnsonhj/Dashboard/src/ITK-clangtidy/ #My local BLD cd /Users/johnsonhj/Dashboard/src/ITK-clangtidy/ run-clang-tidy.py -checks=-*,modernize-pass-by-value -header-filter=.* -fix STYLE: Use range-based loops from C++11 Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container, in the forward direction. ==== Range based loopes are more explicit for only computing the end location once for containers. for ( ImageIORegion::IndexType::const_iterator i = this->GetIndex().begin(); i != this->GetIndex().end(); //<- NOTE: Compute end every loop iteration ++i ) for (long i : this->GetIndex()) //<- NOTE: Implicitly only compute end once ==== Explicitly reduce the amount of index computations: (The compiler probably does this too) for(int i = 0; i < 11; i++) { pos[0] = testPoints[i][0]; pos[1] = testPoints[i][1]; ^^^^ for(auto & testPoint : testPoints) { pos[0] = testPoint[0]; pos[1] = testPoint[1]; ==== SRCDIR=/Users/johnsonhj/Dashboard/src/ITK #My local SRC BLDDIR=/Users/johnsonhj/Dashboard/src/ITK-clangtidy/ #My local BLD cd /Users/johnsonhj/Dashboard/src/ITK-clangtidy/ run-clang-tidy.py -checks=-*,modernize-loop-convert -header-filter=.* -fix --- .../include/itkLabelImageGenericInterpolateImageFunction.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index 61c1cf26d68..94ac71f8a0a 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -48,7 +48,7 @@ LabelImageGenericInterpolateImageFunction } m_InternalInterpolators.clear(); m_LabelSelectionAdaptors.clear(); - for (typename LabelSetType::const_iterator i = m_Labels.begin(); i != m_Labels.end(); ++i) + for (auto i = m_Labels.begin(); i != m_Labels.end(); ++i) { typename LabelSelectionAdaptorType::Pointer adapt = LabelSelectionAdaptorType::New(); // This adaptor doesn't implement Set() so this should be safe From 08a743ae9da4f4853245aea91c5c5999ee28eed1 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Mon, 12 Feb 2018 21:03:07 -0600 Subject: [PATCH 10/42] STYLE: Replace itkStaticConstMacro with static constexpr Use static constexpr directly now that C++11 conformance is required by all compilers. :%s/itkStaticConstMacro *( *\([^,]*\),[ \_s]*\([^,]*\),\_s*\([^)]*\)) */static constexpr \2 \1 = \3/ge --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index b13d2c1e389..d51f362b7fb 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -55,7 +55,7 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI itkNewMacro(Self); /** ImageDimension constant */ - itkStaticConstMacro(ImageDimension, unsigned int, TInputImage::ImageDimension); + static constexpr unsigned int ImageDimension = TInputImage::ImageDimension; /** OutputType typedef support. */ typedef typename Superclass::OutputType OutputType; From 091cd46d12a508e5946cd41e050505c2fea35027 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Mon, 12 Feb 2018 23:29:46 -0600 Subject: [PATCH 11/42] STYLE: Prefer C++11 type alias over typedef == http://en.cppreference.com/w/cpp/language/type_alias == Type alias is a name that refers to a previously defined type (similar to typedef). A type alias declaration introduces a name which can be used as a synonym for the type denoted by type-id. It does not introduce a new type and it cannot change the meaning of an existing type name. There is no difference between a type alias declaration and typedef declaration. This declaration may appear in block scope, class scope, or namespace scope. == https://www.quora.com/Is-using-typedef-in-C++-considered-a-bad-practice == While typedef is still available for backward compatibility, the new Type Alias syntax 'using Alias = ExistingLongName;' is more consistent with the flow of C++ than the old typedef syntax 'typedef ExistingLongName Alias;', and it also works for templates (Type alias, alias template (since C++11)), so leftover 'typedef' aliases will differ in style from any alias templates. --- ...abelImageGenericInterpolateImageFunction.h | 40 ++++++------- ...elImageGenericInterpolateImageFunction.hxx | 4 +- .../include/itkLabelSelectionImageAdaptor.h | 12 ++-- .../include/itkLabelSelectionPixelAccessor.h | 23 +++++--- .../test/RotateLabels.cxx | 56 +++++++++---------- 5 files changed, 70 insertions(+), 65 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index d51f362b7fb..6b354e40a91 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -41,12 +41,12 @@ template class TInterpolator, class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateImageFunction { public: - /** Standard class typedefs. */ - typedef LabelImageGenericInterpolateImageFunction Self; - typedef InterpolateImageFunction Superclass; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; - typedef typename TInputImage::PixelType InputPixelType; + /** Standard class type alias. */ + using Self = LabelImageGenericInterpolateImageFunction; + using Superclass = InterpolateImageFunction; + using Pointer = SmartPointer; + using ConstPointer = SmartPointer; + using InputPixelType = typename TInputImage::PixelType; /** Run-time type information (and related methods). */ itkTypeMacro(LabelImageGenericInterpolateImageFunction, InterpolateImageFunction); @@ -57,25 +57,25 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI /** ImageDimension constant */ static constexpr unsigned int ImageDimension = TInputImage::ImageDimension; - /** OutputType typedef support. */ - typedef typename Superclass::OutputType OutputType; + /** OutputType type alias support. */ + using OutputType = typename Superclass::OutputType; - /** InputImageType typedef support. */ - typedef typename Superclass::InputImageType InputImageType; + /** InputImageType type alias support. */ + using InputImageType = typename Superclass::InputImageType; - /** RealType typedef support. */ - typedef typename Superclass::RealType RealType; + /** RealType type alias support. */ + using RealType = typename Superclass::RealType; - /** Index typedef support. */ - typedef typename Superclass::IndexType IndexType; + /** Index type alias support. */ + using IndexType = typename Superclass::IndexType; - /** ContinuousIndex typedef support. */ - typedef typename Superclass::ContinuousIndexType ContinuousIndexType; + /** ContinuousIndex type alias support. */ + using ContinuousIndexType = typename Superclass::ContinuousIndexType; - typedef LabelSelectionImageAdaptor LabelSelectionAdaptorType; + using LabelSelectionAdaptorType = LabelSelectionImageAdaptor; // The interpolator used for individual binary masks corresponding to each label - typedef TInterpolator InternalInterpolatorType; + using InternalInterpolatorType = TInterpolator; /** * Evaluate at the given index @@ -95,8 +95,8 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI std::vector m_InternalInterpolators; std::vector m_LabelSelectionAdaptors; - typedef std::set LabelSetType; - LabelSetType m_Labels; + using LabelSetType = std::set; + LabelSetType m_Labels; private: LabelImageGenericInterpolateImageFunction(const Self &); // purposely not implemented diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index 94ac71f8a0a..892f753765d 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -39,8 +39,8 @@ LabelImageGenericInterpolateImageFunction if (image) { m_Labels.clear(); - typedef itk::ImageRegionConstIterator IteratorType; - IteratorType it(image, image->GetLargestPossibleRegion()); + using IteratorType = itk::ImageRegionConstIterator; + IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); for (; !it.IsAtEnd(); ++it) { diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index cff34f12604..68e593276be 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -37,13 +37,13 @@ class ITK_EXPORT LabelSelectionImageAdaptor : public ImageAdaptor> { public: - /** Standard class typedefs. */ - typedef LabelSelectionImageAdaptor Self; - typedef ImageAdaptor> - Superclass; + /** Standard class type alias. */ + using Self = LabelSelectionImageAdaptor; + using Superclass = + ImageAdaptor>; - typedef SmartPointer Pointer; - typedef SmartPointer ConstPointer; + using Pointer = SmartPointer; + using ConstPointer = SmartPointer; /** Method for creation through the object factory. */ itkNewMacro(Self); diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h index 12db2bf2519..cf1b795820e 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h @@ -36,25 +36,30 @@ namespace Accessor * \ingroup ITKImageAdaptors * \ingroup GenericLabelInterpolator */ -template< class TInternalType, class TExternalType > +template class ITK_EXPORT LabelSelectionPixelAccessor { public: - /** External typedef. It defines the external aspect + /** External type alias. It defines the external aspect * that this class will exhibit. */ - typedef TExternalType ExternalType; + using ExternalType = TExternalType; - /** Internal typedef. It defines the internal real + /** Internal type alias. It defines the internal real * representation of data. */ - typedef TInternalType InternalType; + using InternalType = TInternalType; - void SetAcceptedValue(TInternalType value) { m_AcceptedValue = value; } + void + SetAcceptedValue(TInternalType value) + { + m_AcceptedValue = value; + } - inline TExternalType Get(const TInternalType & input) const + inline TExternalType + Get(const TInternalType & input) const { - return (TExternalType)( - ( input == m_AcceptedValue ) ? 1 : 0 ); + return (TExternalType)((input == m_AcceptedValue) ? 1 : 0); } + protected: TInternalType m_AcceptedValue; }; diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index 38051019a67..594e2e04e00 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -47,9 +47,9 @@ RotateNTimes(typename ImageType::Pointer input, std::string filename_prefix, std::string output_directory) { - typedef itk::VersorRigid3DTransform TransformType; - typedef itk::ResampleImageFilter ResampleFilterType; - TransformType::AxisType axis; + using TransformType = itk::VersorRigid3DTransform; + using ResampleFilterType = itk::ResampleImageFilter; + TransformType::AxisType axis; axis[0] = 0; axis[1] = 1; axis[2] = 0; @@ -81,8 +81,8 @@ RotateNTimes(typename ImageType::Pointer input, rs->SetTransform(rot); } timer.Stop(); - typedef itk::Testing::ComparisonImageFilter ComparisonFilterType; - typename ComparisonFilterType::Pointer compare = ComparisonFilterType::New(); + using ComparisonFilterType = itk::Testing::ComparisonImageFilter; + typename ComparisonFilterType::Pointer compare = ComparisonFilterType::New(); compare->SetValidInput(input); compare->SetTestInput(out); compare->Update(); @@ -91,8 +91,8 @@ RotateNTimes(typename ImageType::Pointer input, << static_cast(compare->GetNumberOfPixelsWithDifferences()) / input->GetLargestPossibleRegion().GetNumberOfPixels() * 100. << "% ) in " << timer.GetTotal() << "s" << std::endl; - typedef itk::ImageFileWriter WriterType; - typename WriterType::Pointer writer = WriterType::New(); + using WriterType = itk::ImageFileWriter; + typename WriterType::Pointer writer = WriterType::New(); writer->SetUseCompression(true); writer->SetInput(out); std::ostringstream fname_stream; @@ -112,10 +112,10 @@ template class FixedGaussianInterpolator : public itk::GaussianInterpolateImageFunction { public: - typedef FixedGaussianInterpolator Self; - typedef itk::GaussianInterpolateImageFunction Superclass; - typedef itk::SmartPointer Pointer; - typedef itk::SmartPointer ConstPointer; + using Self = FixedGaussianInterpolator; + using Superclass = itk::GaussianInterpolateImageFunction; + using Pointer = itk::SmartPointer; + using ConstPointer = itk::SmartPointer; /** Run-time type information (and related methods). */ itkTypeMacro(FixedGaussianInterpolator, GaussianInterpolateImageFunction); @@ -147,51 +147,51 @@ RotateLabels(int argc, char * argv[]) std::cout << "numberOfRotation must be strictly positive. Given value: " << numberOfRotations << std::endl; return EXIT_FAILURE; } - typedef unsigned char PixelType; - const unsigned int Dimension = 3; - typedef itk::Image ImageType; - typedef itk::ImageFileReader ReaderType; - ReaderType::Pointer r = ReaderType::New(); + using PixelType = unsigned char; + const unsigned int Dimension = 3; + using ImageType = itk::Image; + using ReaderType = itk::ImageFileReader; + ReaderType::Pointer r = ReaderType::New(); r->SetFileName(inputFileName); r->Update(); std::cout << "Testing with " << numberOfRotations << " rotations..." << std::endl << std::endl; std::cout << "Nearest neighbor interpolator... " << std::flush; - typedef itk::NearestNeighborInterpolateImageFunction NNInterpolatorType; - NNInterpolatorType::Pointer nn_interp = NNInterpolatorType::New(); + using NNInterpolatorType = itk::NearestNeighborInterpolateImageFunction; + NNInterpolatorType::Pointer nn_interp = NNInterpolatorType::New(); RotateNTimes(r->GetOutput(), nn_interp, numberOfRotations, "nearest", outputDirectory); std::cout << "Linear interpolator... " << std::flush; - typedef itk::LinearInterpolateImageFunction LInterpolatorType; - LInterpolatorType::Pointer l_interp = LInterpolatorType::New(); + using LInterpolatorType = itk::LinearInterpolateImageFunction; + LInterpolatorType::Pointer l_interp = LInterpolatorType::New(); RotateNTimes(r->GetOutput(), l_interp, numberOfRotations, "linear", outputDirectory); std::cout << "Label Gaussian interpolator type... " << std::flush; - typedef itk::LabelImageGaussianInterpolateImageFunction LGInterpolatorType; - LGInterpolatorType::Pointer lg_interp = LGInterpolatorType::New(); + using LGInterpolatorType = itk::LabelImageGaussianInterpolateImageFunction; + LGInterpolatorType::Pointer lg_interp = LGInterpolatorType::New(); lg_interp->SetSigma(0.3); RotateNTimes(r->GetOutput(), lg_interp, numberOfRotations, "label_gaussian", outputDirectory); std::cout << "Generic label interpolator with nearest neighbor... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction - GNNInterpolatorType; + using GNNInterpolatorType = + itk::LabelImageGenericInterpolateImageFunction; GNNInterpolatorType::Pointer gnn_interp = GNNInterpolatorType::New(); RotateNTimes(r->GetOutput(), gnn_interp, numberOfRotations, "gl_nearest", outputDirectory); std::cout << "Generic label interpolator with linear interpolation... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction - GLInterpolatorType; + using GLInterpolatorType = + itk::LabelImageGenericInterpolateImageFunction; GLInterpolatorType::Pointer gl_interp = GLInterpolatorType::New(); RotateNTimes(r->GetOutput(), gl_interp, numberOfRotations, "gl_linear", outputDirectory); std::cout << "Generic label interpolator with B-Spline interpolation... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction GBSInterpolatorType; + using GBSInterpolatorType = itk::LabelImageGenericInterpolateImageFunction; GBSInterpolatorType::Pointer gbs_interp = GBSInterpolatorType::New(); RotateNTimes(r->GetOutput(), gbs_interp, numberOfRotations, "gl_bspline", outputDirectory); std::cout << "Generic label interpolator with Gaussian interpolation... " << std::flush; - typedef itk::LabelImageGenericInterpolateImageFunction GGInterpolatorType; + using GGInterpolatorType = itk::LabelImageGenericInterpolateImageFunction; GGInterpolatorType::Pointer gg_interp = GGInterpolatorType::New(); RotateNTimes(r->GetOutput(), gg_interp, numberOfRotations, "gl_gaussian", outputDirectory); From 45c6408b9744130127bfb7331da85df67fa58fb6 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Tue, 13 Feb 2018 08:24:11 -0600 Subject: [PATCH 12/42] STYLE: Prefer constexpr for const numeric literals Use constexpr for constant numeric literals. --- .../Filtering/GenericLabelInterpolator/test/RotateLabels.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index 594e2e04e00..17625c8ce89 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -148,7 +148,7 @@ RotateLabels(int argc, char * argv[]) return EXIT_FAILURE; } using PixelType = unsigned char; - const unsigned int Dimension = 3; + constexpr unsigned int Dimension = 3; using ImageType = itk::Image; using ReaderType = itk::ImageFileReader; ReaderType::Pointer r = ReaderType::New(); From 0730ff795fd51f5f93e64bb2969a9444631b8e01 Mon Sep 17 00:00:00 2001 From: Jon Haitz Legarreta Date: Sat, 14 Apr 2018 19:20:59 +0200 Subject: [PATCH 13/42] COMP: Move ITK_DISALLOW_COPY_AND_ASSIGN calls to public section. Move `ITK_DISALLOW_COPY_AND_ASSIGN` calls to public section following the discussion in https://discourse.itk.org/t/noncopyable If legacy (pre-macro) copy and assing methods existed, subsitute them for the `ITK_DISALLOW_COPY_AND_ASSIGN` macro. --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 6 ++---- .../include/itkLabelSelectionImageAdaptor.h | 7 ++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index 6b354e40a91..a305287f590 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -41,6 +41,8 @@ template class TInterpolator, class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateImageFunction { public: + ITK_DISALLOW_COPY_AND_ASSIGN(LabelImageGenericInterpolateImageFunction); + /** Standard class type alias. */ using Self = LabelImageGenericInterpolateImageFunction; using Superclass = InterpolateImageFunction; @@ -99,10 +101,6 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI LabelSetType m_Labels; private: - LabelImageGenericInterpolateImageFunction(const Self &); // purposely not implemented - void - operator=(const Self &); // purposely not implemented - /** * Evaluate function value at the given index */ diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index 68e593276be..630bccb439f 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -37,6 +37,8 @@ class ITK_EXPORT LabelSelectionImageAdaptor : public ImageAdaptor> { public: + ITK_DISALLOW_COPY_AND_ASSIGN(LabelSelectionImageAdaptor); + /** Standard class type alias. */ using Self = LabelSelectionImageAdaptor; using Superclass = @@ -60,11 +62,6 @@ class ITK_EXPORT LabelSelectionImageAdaptor protected: LabelSelectionImageAdaptor() {} ~LabelSelectionImageAdaptor() override {} - -private: - LabelSelectionImageAdaptor(const Self &); // purposely not implemented - void - operator=(const Self &); // purposely not implemented }; } // end namespace itk From 49c357fc1d66042010aece81b6216ae54a0c2d78 Mon Sep 17 00:00:00 2001 From: Jon Haitz Legarreta Date: Sat, 5 May 2018 12:22:46 +0200 Subject: [PATCH 14/42] COMP: Set the minimum required CMake version to 3.10.2. As agreed in: https://discourse.itk.org/t/cmake-update/870/ Set the `cmake_minimum_required` to version **3.10.2**. --- Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt index a3290d3bb51..f09d38f75c9 100644 --- a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt +++ b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.9.5) +cmake_minimum_required(VERSION 3.10.2) project(GenericLabelInterpolator) if(NOT ITK_SOURCE_DIR) From 482636076962fba9cb5f94e992f10f104d4aaee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Thu, 20 Dec 2018 19:46:02 -0500 Subject: [PATCH 15/42] ENH: Add missing CI components. Add missing CI components: - Make the **CircleCI** `YAML` file dwell in a `.circle` folder of its own. - Add the **AppVeyor** and **Travis** `YAML` configuration files. - Add the `setup.py` file for the **Python** Package Index configuration. - Add the Python wrapping files. --- .../wrapping/CMakeLists.txt | 3 ++ ...lImageGenericInterpolateImageFunction.wrap | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Modules/Filtering/GenericLabelInterpolator/wrapping/CMakeLists.txt create mode 100644 Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap diff --git a/Modules/Filtering/GenericLabelInterpolator/wrapping/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/wrapping/CMakeLists.txt new file mode 100644 index 00000000000..c6fad172c68 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/wrapping/CMakeLists.txt @@ -0,0 +1,3 @@ +itk_wrap_module(GenericLabelInterpolator) +itk_auto_load_submodules() +itk_end_wrap_module() diff --git a/Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap b/Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap new file mode 100644 index 00000000000..ca456ff066a --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap @@ -0,0 +1,34 @@ +itk_wrap_class("itk::LabelImageGenericInterpolateImageFunction" POINTER) + foreach(d ${ITK_WRAP_IMAGE_DIMS}) + # UC is required for InterpolateImageFunction + UNIQUE(types "${WRAP_ITK_SCALAR};UC") + foreach(t ${types}) + itk_wrap_template("${ITKM_I${t}${d}}${ITKM_D}${ITKM_F}" "${ITKT_I${t}${d}},${ITKT_D},${ITKT_F}") + itk_wrap_template("${ITKM_I${t}${d}}${ITKM_D}${ITKM_D}" "${ITKT_I${t}${d}},${ITKT_D},${ITKT_D}") + endforeach() + + # Required by InterpolateImageFunction + set(vector_dim ${d}) # Wrap only vector dimensions which are the same as image dimensions + foreach(t ${WRAP_ITK_VECTOR}) + itk_wrap_template( + "${ITKM_I${t}${vector_dim}${d}}${ITKM_VD${vector_dim}}${ITKM_D}" + "${ITKT_I${t}${vector_dim}${d}},${ITKT_VD${vector_dim}},${ITKT_D}") + itk_wrap_template( + "${ITKM_I${t}${vector_dim}${d}}${ITKM_CVD${vector_dim}}${ITKM_D}" + "${ITKT_I${t}${vector_dim}${d}},${ITKT_CVD${vector_dim}},${ITKT_D}") + itk_wrap_template( + "${ITKM_I${t}${vector_dim}${d}}${ITKM_D}${ITKM_D}" + "${ITKT_I${t}${vector_dim}${d}},${ITKT_D},${ITKT_D}") + endforeach() + foreach(t ${WRAP_ITK_COLOR}) + itk_wrap_template("${ITKM_I${t}${d}}${ITKM_${t}}${ITKM_D}" "${ITKT_I${t}${d}},${ITKT_${t}},${ITKT_D}") + endforeach() + foreach(t ${WRAP_ITK_RGB}) + itk_wrap_template("${ITKM_I${t}${d}}RGBD${ITKM_D}" "${ITKT_I${t}${d}},itk::RGBPixel< double >,${ITKT_D}") + endforeach() + foreach(t ${WRAP_ITK_RGBA}) + itk_wrap_template("${ITKM_I${t}${d}}RGBAD${ITKM_D}" "${ITKT_I${t}${d}},itk::RGBAPixel< double >,${ITKT_D}") + endforeach() + + endforeach() +itk_end_wrap_class() From 2bd580307e1b25df743c0f1d615c952e1de8d813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Mon, 17 Dec 2018 20:02:10 -0500 Subject: [PATCH 16/42] DOC: Improve the module documentation. Improve the `README.rst` file style, and conform to the ITKModuleTemplate conventions: - Use the remote module project name as the title. - Place the CI badges in a table. - Divide the file into sections. - Improve the IJ citation to conform to common format. - Cross-reference the LICENSE file. - New line at 80 characters. Re-use the `README.rst` file documentation for the `itk-module.cmake` file documentation. --- .../GenericLabelInterpolator/itk-module.cmake | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake index d4942f11fcd..881e2ed9f4f 100644 --- a/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake +++ b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake @@ -1,14 +1,16 @@ -set(DOCUMENTATION "The basic idea of this generic interpolator for label images is to interpolate each label with an ordinary image interpolator, and return the label with the highest value. This is the idea used by the itk::LabelImageGaussianInterpolateImageFunction interpolator. Unfortunately, this class is currently limited to Gaussian interpolation. Using generic programming, our proposed interpolator extends this idea to any image interpolator. Combined with linear interpolation, this results in similar or better accuracy and much improved computation speeds on a test image. +# the top-level README is used for describing this module, just +# re-used it for documentation here +get_filename_component(MY_CURENT_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +file(READ "${MY_CURENT_DIR}/README.rst" DOCUMENTATION) -A more detailed description can be found in the Insight Journal article:: +# itk_module() defines the module dependencies in GenericLabelInterpolator +# The testing module in GenericLabelInterpolator depends on ITKTestKernel +# By convention those modules outside of ITK are not prefixed with +# ITK -Schaerer, J., Roche, F., Belaroussi, B. \"A generic interpolator for multi-label images\". - http://hdl.handle.net/10380/3506 - http://www.insight-journal.org/browse/publication/950 - December, 2014. -") - -itk_module(GenericLabelInterpolator +# define the dependencies of the include module and the tests +itk_module( + GenericLabelInterpolator DEPENDS ITKSmoothing ITKImageAdaptors @@ -16,6 +18,5 @@ itk_module(GenericLabelInterpolator ITKTestKernel ITKImageGrid EXCLUDE_FROM_DEFAULT - DESCRIPTION - "${DOCUMENTATION}" + DESCRIPTION "${DOCUMENTATION}" ) From a8dea93b3074d4c9f7eacb059ca13dd71b11b698 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 17 May 2019 11:15:33 -0500 Subject: [PATCH 17/42] COMP: Interpolators now must provide GetRadius() The GetRadius() function is required for interpolators in order to facilitate identifying the region neeed to analyze a value. --- .../itkLabelImageGenericInterpolateImageFunction.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index a305287f590..ad95563df18 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -71,6 +71,9 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI /** Index type alias support. */ using IndexType = typename Superclass::IndexType; + /** Size type alias support. */ + using SizeType = typename Superclass::SizeType; + /** ContinuousIndex type alias support. */ using ContinuousIndexType = typename Superclass::ContinuousIndexType; @@ -91,6 +94,17 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI void SetInputImage(const TInputImage * image) override; + /** Get the radius required for interpolation. + * + * This defines the number of surrounding pixels required to interpolate at + * a given point. + */ + virtual SizeType + GetRadius() const override + { + return SizeType::Filled(1); + } + protected: LabelImageGenericInterpolateImageFunction(); ~LabelImageGenericInterpolateImageFunction() override {}; From f0d92c6952c99b7e6a697ca7ed876571eda863ca Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 17 May 2019 11:16:06 -0500 Subject: [PATCH 18/42] STYLE: Use more ITKv5 style conformance. --- ...abelImageGenericInterpolateImageFunction.h | 4 +-- ...elImageGenericInterpolateImageFunction.hxx | 30 ++++++++----------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index ad95563df18..ef5437129a0 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -37,7 +37,7 @@ namespace itk * * \ingroup GenericLabelInterpolator */ -template class TInterpolator, typename TCoordRep = double> +template typename TInterpolator, typename TCoordRep = double> class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateImageFunction { public: @@ -107,7 +107,7 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI protected: LabelImageGenericInterpolateImageFunction(); - ~LabelImageGenericInterpolateImageFunction() override {}; + ~LabelImageGenericInterpolateImageFunction() override = default; std::vector m_InternalInterpolators; std::vector m_LabelSelectionAdaptors; diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index 892f753765d..d02579d3110 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -24,25 +24,19 @@ namespace itk { -template class TInterpolator, typename TCoordRep> -LabelImageGenericInterpolateImageFunction:: - LabelImageGenericInterpolateImageFunction() -{} - -template class TInterpolator, typename TCoordRep> +template typename TInterpolator, typename TCoordRep> void LabelImageGenericInterpolateImageFunction::SetInputImage( const TInputImage * image) { - /** We have one adaptor and one interpolator per label to keep the class thread-safe: - * changing the adaptor's accepted value wouldn't work when called from a multi-threaded filter */ + /* We have one adaptor and one interpolator per label to keep the class thread-safe: + * changing the adaptor's accepted value wouldn't work when called from a multi-threaded filter */ + using IteratorType = itk::ImageRegionConstIterator; if (image) { m_Labels.clear(); - using IteratorType = itk::ImageRegionConstIterator; IteratorType it(image, image->GetLargestPossibleRegion()); - it.GoToBegin(); - for (; !it.IsAtEnd(); ++it) + for (it.GoToBegin(); !it.IsAtEnd(); ++it) { m_Labels.insert(it.Get()); } @@ -63,19 +57,18 @@ LabelImageGenericInterpolateImageFunction Superclass::SetInputImage(image); } -template class TInterpolator, typename TCoordRep> +template typename TInterpolator, typename TCoordRep> typename LabelImageGenericInterpolateImageFunction::OutputType LabelImageGenericInterpolateImageFunction::EvaluateAtContinuousIndex( const ContinuousIndexType & cindex, OutputType * itkNotUsed(grad)) const { - /** Interpolate the binary mask corresponding to each label and return the label + /* Interpolate the binary mask corresponding to each label and return the label * with the highest value */ - double value = 0; - typename TInputImage::PixelType best_label = 0; - typename LabelSetType::const_iterator it; - int i; - for (it = m_Labels.begin(), i = 0; it != m_Labels.end(); ++it, ++i) + double value = 0; + typename TInputImage::PixelType best_label = 0; + int i = 0; + for (typename LabelSetType::const_iterator it = m_Labels.begin(); it != m_Labels.end(); ++it) { double tmp = m_InternalInterpolators[i]->EvaluateAtContinuousIndex(cindex); if (tmp > value) @@ -83,6 +76,7 @@ LabelImageGenericInterpolateImageFunction value = tmp; best_label = (*it); } + ++i; } return best_label; } From 2b56ef2f36aba329fde794c89aef9e481584841f Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 17 May 2019 17:30:57 -0500 Subject: [PATCH 19/42] COMP: Missing constructor definition. --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index ef5437129a0..8024f3dfcf0 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -106,7 +106,7 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI } protected: - LabelImageGenericInterpolateImageFunction(); + LabelImageGenericInterpolateImageFunction() = default; ~LabelImageGenericInterpolateImageFunction() override = default; std::vector m_InternalInterpolators; From 9e9ba849eeb31457c320943426a8eb795e94931b Mon Sep 17 00:00:00 2001 From: yinkaola Date: Thu, 1 Aug 2019 22:49:08 -0600 Subject: [PATCH 20/42] ENH: Update itkLabelImageGenericInterpolateImageFunction.h Original subject: Update itkLabelImageGenericInterpolateImageFunction.h --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index 8024f3dfcf0..4664fe5275c 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -37,7 +37,7 @@ namespace itk * * \ingroup GenericLabelInterpolator */ -template typename TInterpolator, typename TCoordRep = double> +template class TInterpolator, typename TCoordRep = double> class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateImageFunction { public: From c5158749ccf31d58d6659fc25623a6a9c829609e Mon Sep 17 00:00:00 2001 From: yinkaola Date: Thu, 1 Aug 2019 22:49:38 -0600 Subject: [PATCH 21/42] ENH: Update itkLabelImageGenericInterpolateImageFunction.hxx Original subject: Update itkLabelImageGenericInterpolateImageFunction.hxx --- .../include/itkLabelImageGenericInterpolateImageFunction.hxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index d02579d3110..b40c37bff2b 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -24,7 +24,7 @@ namespace itk { -template typename TInterpolator, typename TCoordRep> +template class TInterpolator, typename TCoordRep> void LabelImageGenericInterpolateImageFunction::SetInputImage( const TInputImage * image) @@ -57,7 +57,7 @@ LabelImageGenericInterpolateImageFunction Superclass::SetInputImage(image); } -template typename TInterpolator, typename TCoordRep> +template class TInterpolator, typename TCoordRep> typename LabelImageGenericInterpolateImageFunction::OutputType LabelImageGenericInterpolateImageFunction::EvaluateAtContinuousIndex( const ContinuousIndexType & cindex, From f5cfa8a881cee6691cd46cac9d3cccd74e392f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Tue, 13 Aug 2019 15:26:06 -0400 Subject: [PATCH 22/42] STYLE: replacing MD5 hashes by SHA512 hashes --- .../GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 | 1 - .../test/Baseline/gl_gaussian_3.mha.sha512 | 1 + .../GenericLabelInterpolator/test/Input/classification.mha.md5 | 1 - .../test/Input/classification.mha.sha512 | 1 + 4 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 delete mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 deleted file mode 100644 index eaf48e38dbe..00000000000 --- a/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.md5 +++ /dev/null @@ -1 +0,0 @@ -7ccd2dcfe9736b82a696a6c71d4dfbb8 diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 new file mode 100644 index 00000000000..92f0b0d1620 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 @@ -0,0 +1 @@ +a5e11ea71164ff78c65fcf259db01ea5db981a9d868e60045ff2bffca92984df1174bf984a1076e450f0d5d69b4f0191ed1a61465c220e2c91a893b5df150c0a diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 deleted file mode 100644 index f3a08e3f19b..00000000000 --- a/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.md5 +++ /dev/null @@ -1 +0,0 @@ -861752fa4c3c619e09bba6daf17643e2 diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 new file mode 100644 index 00000000000..16ec7286661 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 @@ -0,0 +1 @@ +bcdbb347f3704262d1f00be7179d6a0a6e68aed56c0653e8072ee5a94985c713bd229c935b1226a658af84fb7f1fffc2458c98364fc35303a2303b12f9f7ce2f From d89fccd66365d0ff08fe538755667803e31f9782 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Mon, 17 Feb 2020 14:01:45 -0600 Subject: [PATCH 23/42] STYLE: Use override statements for C++11 Describe function overrides using the override keyword from C++11. SRCDIR= #My local SRC BLDDIR= #My local BLD cd run-clang-tidy.py -extra-arg=-D__clang__ -checks=-*,modernize-use-override -header-filter=.* -fix --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index 4664fe5275c..bd2066f4f40 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -99,7 +99,7 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI * This defines the number of surrounding pixels required to interpolate at * a given point. */ - virtual SizeType + SizeType GetRadius() const override { return SizeType::Filled(1); From 6dbbc1063aa6f3617001091dd0bd45ea2288b370 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Mon, 17 Feb 2020 14:29:55 -0600 Subject: [PATCH 24/42] STYLE: Prefer = default to explicitly trivial implementations This check replaces default bodies of special member functions with = default;. The explicitly defaulted function declarations enable more opportunities in optimization, because the compiler might treat explicitly defaulted functions as trivial. Additionally, the C++11 use of = default more clearly expreses the intent for the special member functions. --- .../include/itkLabelSelectionImageAdaptor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index 630bccb439f..3376fb85549 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -60,8 +60,8 @@ class ITK_EXPORT LabelSelectionImageAdaptor } protected: - LabelSelectionImageAdaptor() {} - ~LabelSelectionImageAdaptor() override {} + LabelSelectionImageAdaptor() = default; + ~LabelSelectionImageAdaptor() override = default; }; } // end namespace itk From 0ca1f9297db90fb69666501e514f3ec18dde3a78 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Mon, 17 Feb 2020 23:34:54 -0600 Subject: [PATCH 25/42] STYLE: Use auto for variable type matches the type of the initializer expre... This check is responsible for using the auto type specifier for variable declarations to improve code readability and maintainability. The auto type specifier will only be introduced in situations where the variable type matches the type of the initializer expression. In other words auto should deduce the same type that was originally spelled in the source Original subject: STYLE: Use auto for variable type matches the type of the initializer expression --- .../include/itkLabelImageGenericInterpolateImageFunction.hxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index b40c37bff2b..5467bf4c866 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -68,7 +68,7 @@ LabelImageGenericInterpolateImageFunction double value = 0; typename TInputImage::PixelType best_label = 0; int i = 0; - for (typename LabelSetType::const_iterator it = m_Labels.begin(); it != m_Labels.end(); ++it) + for (auto it = m_Labels.begin(); it != m_Labels.end(); ++it) { double tmp = m_InternalInterpolators[i]->EvaluateAtContinuousIndex(cindex); if (tmp > value) From 36a919792a994f75292a45c2ec0c23ced6672f27 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Wed, 19 Feb 2020 10:45:25 -0600 Subject: [PATCH 26/42] DOC: Update copyright assignment to NumFOCUS The mission of NumFOCUS is to promote open practices in research, data, and scientific computing. https://numfocus.org --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- .../include/itkLabelImageGenericInterpolateImageFunction.hxx | 2 +- .../include/itkLabelSelectionImageAdaptor.h | 2 +- .../include/itkLabelSelectionPixelAccessor.h | 2 +- .../Filtering/GenericLabelInterpolator/test/RotateLabels.cxx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index bd2066f4f40..a74fcc8574f 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -1,6 +1,6 @@ /*========================================================================= * - * Copyright Insight Software Consortium + * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index 5467bf4c866..cb85f812eba 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -1,6 +1,6 @@ /*========================================================================= * - * Copyright Insight Software Consortium + * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index 3376fb85549..ea63db8c9c7 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -1,6 +1,6 @@ /*========================================================================= * - * Copyright Insight Software Consortium + * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h index cf1b795820e..99b1aea352a 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h @@ -1,6 +1,6 @@ /*========================================================================= * - * Copyright Insight Software Consortium + * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index 17625c8ce89..a278748e306 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -1,6 +1,6 @@ /*========================================================================= * - * Copyright Insight Software Consortium + * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 0f6d673206fab3da033779ee90d3ed61614befd5 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 29 Feb 2020 21:49:37 -0600 Subject: [PATCH 27/42] ENH: Make similar to template --- Modules/Filtering/GenericLabelInterpolator/itk-module.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake index 881e2ed9f4f..f80262b7e78 100644 --- a/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake +++ b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake @@ -17,6 +17,7 @@ itk_module( TEST_DEPENDS ITKTestKernel ITKImageGrid - EXCLUDE_FROM_DEFAULT DESCRIPTION "${DOCUMENTATION}" + EXCLUDE_FROM_DEFAULT + ENABLE_SHARED ) From 533abc6dc13f80d0587ec7d6fe6d20586978c5a6 Mon Sep 17 00:00:00 2001 From: Davis Vigneault Date: Thu, 21 May 2020 15:57:03 -0700 Subject: [PATCH 28/42] COMP: Fix Wrapping Errors --- ...elImageGenericInterpolateImageFunction.hxx | 6 +-- ...lImageGenericInterpolateImageFunction.wrap | 39 +++++++------------ 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index cb85f812eba..9b71d9184ff 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -65,9 +65,9 @@ LabelImageGenericInterpolateImageFunction { /* Interpolate the binary mask corresponding to each label and return the label * with the highest value */ - double value = 0; - typename TInputImage::PixelType best_label = 0; - int i = 0; + double value = 0; + InputPixelType best_label = itk::NumericTraits::ZeroValue(); + int i = 0; for (auto it = m_Labels.begin(); it != m_Labels.end(); ++it) { double tmp = m_InternalInterpolators[i]->EvaluateAtContinuousIndex(cindex); diff --git a/Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap b/Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap index ca456ff066a..7e917669ad8 100644 --- a/Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap +++ b/Modules/Filtering/GenericLabelInterpolator/wrapping/itkLabelImageGenericInterpolateImageFunction.wrap @@ -1,34 +1,23 @@ +itk_wrap_include("itkLinearInterpolateImageFunction.h") +itk_wrap_include("itkNearestNeighborInterpolateImageFunction.h") + itk_wrap_class("itk::LabelImageGenericInterpolateImageFunction" POINTER) foreach(d ${ITK_WRAP_IMAGE_DIMS}) # UC is required for InterpolateImageFunction - UNIQUE(types "${WRAP_ITK_SCALAR};UC") + UNIQUE(types "${WRAP_ITK_SCALAR};UC;${WRAP_ITK_COLOR}") foreach(t ${types}) - itk_wrap_template("${ITKM_I${t}${d}}${ITKM_D}${ITKM_F}" "${ITKT_I${t}${d}},${ITKT_D},${ITKT_F}") - itk_wrap_template("${ITKM_I${t}${d}}${ITKM_D}${ITKM_D}" "${ITKT_I${t}${d}},${ITKT_D},${ITKT_D}") + itk_wrap_template("${ITKM_I${t}${d}}Linear" "${ITKT_I${t}${d}},itk::LinearInterpolateImageFunction") + itk_wrap_template("${ITKM_I${t}${d}}NearestNeighbor" "${ITKT_I${t}${d}},itk::NearestNeighborInterpolateImageFunction") endforeach() - # Required by InterpolateImageFunction - set(vector_dim ${d}) # Wrap only vector dimensions which are the same as image dimensions - foreach(t ${WRAP_ITK_VECTOR}) - itk_wrap_template( - "${ITKM_I${t}${vector_dim}${d}}${ITKM_VD${vector_dim}}${ITKM_D}" - "${ITKT_I${t}${vector_dim}${d}},${ITKT_VD${vector_dim}},${ITKT_D}") - itk_wrap_template( - "${ITKM_I${t}${vector_dim}${d}}${ITKM_CVD${vector_dim}}${ITKM_D}" - "${ITKT_I${t}${vector_dim}${d}},${ITKT_CVD${vector_dim}},${ITKT_D}") - itk_wrap_template( - "${ITKM_I${t}${vector_dim}${d}}${ITKM_D}${ITKM_D}" - "${ITKT_I${t}${vector_dim}${d}},${ITKT_D},${ITKT_D}") - endforeach() - foreach(t ${WRAP_ITK_COLOR}) - itk_wrap_template("${ITKM_I${t}${d}}${ITKM_${t}}${ITKM_D}" "${ITKT_I${t}${d}},${ITKT_${t}},${ITKT_D}") - endforeach() - foreach(t ${WRAP_ITK_RGB}) - itk_wrap_template("${ITKM_I${t}${d}}RGBD${ITKM_D}" "${ITKT_I${t}${d}},itk::RGBPixel< double >,${ITKT_D}") - endforeach() - foreach(t ${WRAP_ITK_RGBA}) - itk_wrap_template("${ITKM_I${t}${d}}RGBAD${ITKM_D}" "${ITKT_I${t}${d}},itk::RGBAPixel< double >,${ITKT_D}") - endforeach() + # FIXME: Build fails with the following errors: + # error: no match for ‘operator<’ (operand types are ‘const itk::CovariantVector’ and ‘const itk::CovariantVector’) + # error: no match for ‘operator<’ (operand types are ‘const itk::Vector’ and ‘const itk::Vector’) + # error: no match for ‘operator<’ (operand types are ‘const itk::CovariantVector’ and ‘const itk::CovariantVector’) + # error: no match for ‘operator<’ (operand types are ‘const itk::Vector’ and ‘const itk::Vector’) + # foreach(t ${WRAP_ITK_VECTOR}) + # itk_wrap_template("${ITKM_I${t}${d}${d}}Linear" "${ITKT_I${t}${d}${d}},itk::LinearInterpolateImageFunction") + # endforeach() endforeach() itk_end_wrap_class() From 99f7439b37de85eb7d03338ab7303c967200f79d Mon Sep 17 00:00:00 2001 From: Mathew Seng Date: Wed, 14 Oct 2020 10:41:07 -0500 Subject: [PATCH 29/42] STYLE: Rename ITK_DISALLOW_COPY_AND_ASSIGN to ITK_DISALLOW_COPY_AND_MOVE Fi... Original subject: STYLE: Rename ITK_DISALLOW_COPY_AND_ASSIGN to ITK_DISALLOW_COPY_AND_MOVE Fixes changes made in #2053. ITK_DISALLOW_COPY_AND_ASSIGN will be used if ITK_FUTURE_LEGACY_REMOVE=OFF. --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- .../include/itkLabelSelectionImageAdaptor.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index a74fcc8574f..8431f4e5291 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -41,7 +41,7 @@ template class TInterpolato class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateImageFunction { public: - ITK_DISALLOW_COPY_AND_ASSIGN(LabelImageGenericInterpolateImageFunction); + ITK_DISALLOW_COPY_AND_MOVE(LabelImageGenericInterpolateImageFunction); /** Standard class type alias. */ using Self = LabelImageGenericInterpolateImageFunction; diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index ea63db8c9c7..d58e795c361 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -37,7 +37,7 @@ class ITK_EXPORT LabelSelectionImageAdaptor : public ImageAdaptor> { public: - ITK_DISALLOW_COPY_AND_ASSIGN(LabelSelectionImageAdaptor); + ITK_DISALLOW_COPY_AND_MOVE(LabelSelectionImageAdaptor); /** Standard class type alias. */ using Self = LabelSelectionImageAdaptor; From 9b4a3b859b6868a8aa33c982b4bb00f6352f157c Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Fri, 17 Dec 2021 09:35:14 -0600 Subject: [PATCH 30/42] COMP: Remove inclusion of .hxx files as headers The ability to include either .h or .hxx files as header files required recursively reading the .h files twice. The added complexity is unnecessary, costly, and can confuse static analysis tools that monitor header guardes (due to reaching the maximum depth of recursion limits for nested #ifdefs in checking). --- .../include/itkLabelImageGenericInterpolateImageFunction.hxx | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index 9b71d9184ff..7924e3f9fcc 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -18,7 +18,6 @@ #ifndef itkLabelImageGenericInterpolateImageFunction_hxx #define itkLabelImageGenericInterpolateImageFunction_hxx -#include "itkLabelImageGenericInterpolateImageFunction.h" #include namespace itk From f365bcadf9af87700ad55d36cc838ef91234eea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Wed, 29 Dec 2021 15:38:28 -0500 Subject: [PATCH 31/42] ENH: update minimum required CMake version --- Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt index f09d38f75c9..e70da4e7acf 100644 --- a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt +++ b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10.2) +cmake_minimum_required(VERSION 3.16.3) project(GenericLabelInterpolator) if(NOT ITK_SOURCE_DIR) From feee9c1d8553d8c59116f39ad9095c223243d06f Mon Sep 17 00:00:00 2001 From: Tom Birdsong Date: Tue, 31 May 2022 11:26:58 -0400 Subject: [PATCH 32/42] ENH: Bump ITK and replace http with https using script --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- .../include/itkLabelImageGenericInterpolateImageFunction.hxx | 2 +- .../include/itkLabelSelectionImageAdaptor.h | 2 +- .../include/itkLabelSelectionPixelAccessor.h | 2 +- .../Filtering/GenericLabelInterpolator/test/RotateLabels.cxx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index 8431f4e5291..2c7fa032b3f 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0.txt + * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index 7924e3f9fcc..d12596f47c7 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0.txt + * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index d58e795c361..cca66502575 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0.txt + * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h index 99b1aea352a..0c2ccf1c3a9 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionPixelAccessor.h @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0.txt + * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index a278748e306..3aaf2ec4fe7 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -6,7 +6,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0.txt + * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, From 4e6c239185697532dd988d76b1109b529b1353e1 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Sun, 18 Sep 2022 20:13:51 -0400 Subject: [PATCH 33/42] COMP: Define interpolator template parameter names Intended to address Issue #12. --- .../itkLabelImageGenericInterpolateImageFunction.h | 4 +++- .../itkLabelImageGenericInterpolateImageFunction.hxx | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index 2c7fa032b3f..94b798ff09b 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -37,7 +37,9 @@ namespace itk * * \ingroup GenericLabelInterpolator */ -template class TInterpolator, typename TCoordRep = double> +template class TInterpolator, + typename TCoordRep = double> class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateImageFunction { public: diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx index d12596f47c7..80e1a93b677 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.hxx @@ -23,7 +23,9 @@ namespace itk { -template class TInterpolator, typename TCoordRep> +template class TInterpolator, + typename TCoordRep> void LabelImageGenericInterpolateImageFunction::SetInputImage( const TInputImage * image) @@ -56,7 +58,9 @@ LabelImageGenericInterpolateImageFunction Superclass::SetInputImage(image); } -template class TInterpolator, typename TCoordRep> +template class TInterpolator, + typename TCoordRep> typename LabelImageGenericInterpolateImageFunction::OutputType LabelImageGenericInterpolateImageFunction::EvaluateAtContinuousIndex( const ContinuousIndexType & cindex, From ecce9501e2d027fd94dd454332b0fd1af6190a15 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Sat, 25 Jan 2025 10:14:30 -0600 Subject: [PATCH 34/42] COMP: Use modern macro for name of class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When preparing for the future with ITK by setting ITK_FUTURE_LEGACY_REMOVE:BOOL=ON ITK_LEGACY_REMOVEBOOL=ON The future preferred macro should be used │ - itkTypeMacro │ + itkOverrideGetNameOfClassMacro --- .../include/itkLabelImageGenericInterpolateImageFunction.h | 2 +- .../include/itkLabelSelectionImageAdaptor.h | 2 +- .../Filtering/GenericLabelInterpolator/test/RotateLabels.cxx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h index 94b798ff09b..83782e353cb 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelImageGenericInterpolateImageFunction.h @@ -53,7 +53,7 @@ class ITK_EXPORT LabelImageGenericInterpolateImageFunction : public InterpolateI using InputPixelType = typename TInputImage::PixelType; /** Run-time type information (and related methods). */ - itkTypeMacro(LabelImageGenericInterpolateImageFunction, InterpolateImageFunction); + itkOverrideGetNameOfClassMacro(LabelImageGenericInterpolateImageFunction); /** Method for creation through the object factory. */ itkNewMacro(Self); diff --git a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h index cca66502575..4ebe6d6a4de 100644 --- a/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h +++ b/Modules/Filtering/GenericLabelInterpolator/include/itkLabelSelectionImageAdaptor.h @@ -51,7 +51,7 @@ class ITK_EXPORT LabelSelectionImageAdaptor itkNewMacro(Self); /** Run-time type information (and related methods). */ - itkTypeMacro(LabelSelectionImageAdaptor, ImageAdaptor); + itkOverrideGetNameOfClassMacro(LabelSelectionImageAdaptor); void SetAcceptedValue(typename TImage::PixelType value) diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index 3aaf2ec4fe7..5e24d63278e 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -118,7 +118,7 @@ class FixedGaussianInterpolator : public itk::GaussianInterpolateImageFunction; /** Run-time type information (and related methods). */ - itkTypeMacro(FixedGaussianInterpolator, GaussianInterpolateImageFunction); + itkOverrideGetNameOfClassMacro(FixedGaussianInterpolator); /** Method for creation through the object factory. */ itkNewMacro(Self); From 195fdabc11263247743b87dcad74f85ac5783e9e Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Mon, 14 Apr 2025 09:33:33 -0400 Subject: [PATCH 35/42] ENH: Reduce image size of rotate resampling test The computation cost of the 256x256x166 is excessive. It is causing timeout in the valgrind and coverage nightly builds. Reducing the size of the image image by 4^3 provides the same coverage and qualitity assurance as the larger image. --- .../test/Baseline/gl_gaussian_3.mha.cid | 1 + .../test/Baseline/gl_gaussian_3.mha.sha512 | 1 - .../test/CMakeLists.txt | 20 +++++++++---------- .../test/Input/classification.mha.sha512 | 1 - .../test/Input/classification_s4.mha.cid | 1 + .../test/RotateLabels.cxx | 19 +++++++++++++----- 6 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.cid delete mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 delete mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 create mode 100644 Modules/Filtering/GenericLabelInterpolator/test/Input/classification_s4.mha.cid diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.cid b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.cid new file mode 100644 index 00000000000..a92254850e2 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.cid @@ -0,0 +1 @@ +bafkreihi5ylz5qypvqfl3j4hglalh4cxxh64ooxi4bcqujvjbngys3wqlq diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 b/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 deleted file mode 100644 index 92f0b0d1620..00000000000 --- a/Modules/Filtering/GenericLabelInterpolator/test/Baseline/gl_gaussian_3.mha.sha512 +++ /dev/null @@ -1 +0,0 @@ -a5e11ea71164ff78c65fcf259db01ea5db981a9d868e60045ff2bffca92984df1174bf984a1076e450f0d5d69b4f0191ed1a61465c220e2c91a893b5df150c0a diff --git a/Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt index 78e779b8473..3dd039a97ba 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt +++ b/Modules/Filtering/GenericLabelInterpolator/test/CMakeLists.txt @@ -1,18 +1,18 @@ itk_module_test() -set(GenericLabelInterpolatorTests - RotateLabels.cxx - ) +set(GenericLabelInterpolatorTests RotateLabels.cxx) -CreateTestDriver(GenericLabelInterpolator "${GenericLabelInterpolator-Test_LIBRARIES}" "${GenericLabelInterpolatorTests}") +createtestdriver(GenericLabelInterpolator "${GenericLabelInterpolator-Test_LIBRARIES}" "${GenericLabelInterpolatorTests}") -itk_add_test(NAME GenericLabelInterpolatorRotateLabelsTest - COMMAND GenericLabelInterpolatorTestDriver - --compare +itk_add_test( + NAME GenericLabelInterpolatorRotateLabelsTest + COMMAND + GenericLabelInterpolatorTestDriver + --compare ${ITK_TEST_OUTPUT_DIR}/gl_gaussian_3.mha DATA{Baseline/gl_gaussian_3.mha} - RotateLabels - DATA{Input/classification.mha} + RotateLabels + DATA{Input/classification_s4.mha} ${ITK_TEST_OUTPUT_DIR}/ 3 - ) +) diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 deleted file mode 100644 index 16ec7286661..00000000000 --- a/Modules/Filtering/GenericLabelInterpolator/test/Input/classification.mha.sha512 +++ /dev/null @@ -1 +0,0 @@ -bcdbb347f3704262d1f00be7179d6a0a6e68aed56c0653e8072ee5a94985c713bd229c935b1226a658af84fb7f1fffc2458c98364fc35303a2303b12f9f7ce2f diff --git a/Modules/Filtering/GenericLabelInterpolator/test/Input/classification_s4.mha.cid b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification_s4.mha.cid new file mode 100644 index 00000000000..a43f71a1230 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/test/Input/classification_s4.mha.cid @@ -0,0 +1 @@ +bafkreieknicyj6a22rizrcyfy4pzx5pskm4loi3m7h5gbi2qp2cc3ny3my diff --git a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx index 5e24d63278e..39dbe527895 100644 --- a/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx +++ b/Modules/Filtering/GenericLabelInterpolator/test/RotateLabels.cxx @@ -53,12 +53,21 @@ RotateNTimes(typename ImageType::Pointer input, axis[0] = 0; axis[1] = 1; axis[2] = 0; - TransformType::InputPointType center; - center[0] = 144; - center[1] = 86; - center[2] = 101; + // compute physical center of input image + itk::ContinuousIndex center; + + const auto inputSize = input->GetLargestPossibleRegion().GetSize(); + + for (unsigned int i = 0; i < ImageType::ImageDimension; ++i) + { + center[i] = inputSize[i] / 2.0; + } + // convert to physical coordinates + typename ImageType::PointType centerPhysical; + input->TransformContinuousIndexToPhysicalPoint(center, centerPhysical); + TransformType::Pointer rot = TransformType::New(); - rot->SetCenter(center); + rot->SetCenter(centerPhysical); rot->SetRotation(axis, 2. * itk::Math::pi / number_of_rotations); typename ResampleFilterType::Pointer rs = ResampleFilterType::New(); From 4441e31ff9c06a445b867c7f8b96ac71b334558e Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Fri, 24 Apr 2026 21:53:34 -0500 Subject: [PATCH 36/42] COMP: Drop missing README.rst read in ingested GenericLabelInterpolator The upstream itk-module.cmake reads README.rst at configure time to populate the module DESCRIPTION. Only the whitelisted code/test paths crossed the ingest boundary (no README.rst), so configure would fail with "file does not exist". Inline the description as a literal string consistent with the AnisotropicDiffusionLBR ingest pattern, and add a Modules/Filtering/GenericLabelInterpolator/README.md pointer to the archived upstream repository. --- .../GenericLabelInterpolator/README.md | 65 +++++++++++++++++++ .../GenericLabelInterpolator/itk-module.cmake | 27 +++++--- 2 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 Modules/Filtering/GenericLabelInterpolator/README.md diff --git a/Modules/Filtering/GenericLabelInterpolator/README.md b/Modules/Filtering/GenericLabelInterpolator/README.md new file mode 100644 index 00000000000..04b64ed7409 --- /dev/null +++ b/Modules/Filtering/GenericLabelInterpolator/README.md @@ -0,0 +1,65 @@ +# GenericLabelInterpolator + +In-tree ITK module providing a generic interpolator for multi-label +images. `itk::LabelImageGenericInterpolateImageFunction` interpolates +each label independently with any ordinary image interpolator and +returns, at each query point, the label whose interpolated value is +highest. Generalizes the Gaussian-only behavior of +`itk::LabelImageGaussianInterpolateImageFunction`. + +## Origin + +Ingested from the standalone remote module +[**InsightSoftwareConsortium/ITKGenericLabelInterpolator**](https://github.com/InsightSoftwareConsortium/ITKGenericLabelInterpolator) +on 2026-04-25, at upstream commit +[`081575cd`](https://github.com/InsightSoftwareConsortium/ITKGenericLabelInterpolator/commit/081575cdcc26b1a542d4c90feaf9250df5e104d9). +The upstream repository will be archived read-only after this PR +merges; it remains reachable at the URL above. + +## What lives here + +Per the v3 ingestion strategy (see +`Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md`), only +paths matching the narrow whitelist (code, headers, tests, wrapping, +module CMake) crossed the merge boundary: + +- `include/` — public C++ headers. +- `test/` — CTest drivers and content-link stubs. +- `wrapping/` — Python wrapping descriptors. +- `CMakeLists.txt`, `itk-module.cmake` — build + module descriptors. + +Every surviving commit preserves original authorship; `git blame` +walks across the merge boundary to upstream authors back to 2014. + +## What was intentionally left upstream + +Everything outside the whitelist stays in the archived upstream repo. +If you need any of it, clone +. + +| Content in upstream | Why it did not ingest | +|---|---| +| `examples/` | Per-module `examples/` are routed to top-level [`Examples/`](https://github.com/InsightSoftwareConsortium/ITK/tree/main/Examples) via a separate follow-up PR. | +| `README.rst` | Algorithm citations + background are folded into the Doxygen on the filter headers and the module DESCRIPTION. | +| `.github/`, `azure-pipelines.yml`, `Dockerfile` | Standalone-build CI scaffolding; not useful in-tree. | +| `CTestConfig.cmake`, `pyproject.toml`, `LICENSE`, `.clang-format` | Packaging / CI / style scaffolding superseded by ITK root. | + +## Long-form documentation + +- **Algorithm description** — see the Doxygen on + `itkLabelImageGenericInterpolateImageFunction`, plus the embedded + citation: + + > Schaerer, J., Roche, F., Belaroussi, B. + > *A generic interpolator for multi-label images*. + > The Insight Journal, January–December 2014. + > + +- **Standalone build + usage examples** — see the archived upstream at + . + +## Content-link status + +The 2 baseline / input content-links under `test/Baseline/` and +`test/Input/` are already in `.cid` (IPFS Content Identifier) form; +no `.md5` → `.cid` normalization is required for this module. diff --git a/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake index f80262b7e78..a5b5e6edf51 100644 --- a/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake +++ b/Modules/Filtering/GenericLabelInterpolator/itk-module.cmake @@ -1,14 +1,17 @@ -# the top-level README is used for describing this module, just -# re-used it for documentation here -get_filename_component(MY_CURENT_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) -file(READ "${MY_CURENT_DIR}/README.rst" DOCUMENTATION) - -# itk_module() defines the module dependencies in GenericLabelInterpolator -# The testing module in GenericLabelInterpolator depends on ITKTestKernel -# By convention those modules outside of ITK are not prefixed with -# ITK +set( + DOCUMENTATION + "This module provides a generic interpolator for multi-label images: +itkLabelImageGenericInterpolateImageFunction interpolates each label +independently with any underlying ordinary image interpolator and +returns the label with the highest interpolated value at each +point. Generalizes the Gaussian-only behavior of +itkLabelImageGaussianInterpolateImageFunction. See the Doxygen on +\\\\ref LabelImageGenericInterpolateImageFunction for the algorithm +and the Insight Journal article (Schaerer, Roche, Belaroussi, 2014, +https://hdl.handle.net/10380/3506) for derivation, and the module +README for in-tree vs archived-upstream scope." +) -# define the dependencies of the include module and the tests itk_module( GenericLabelInterpolator DEPENDS @@ -17,6 +20,10 @@ itk_module( TEST_DEPENDS ITKTestKernel ITKImageGrid + ITKImageFunction + ITKTransform + ITKIOImageBase + ITKIONIFTI DESCRIPTION "${DOCUMENTATION}" EXCLUDE_FROM_DEFAULT ENABLE_SHARED From e806372da1193e0d5d4a82d511a3598f7e5e93a2 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Fri, 24 Apr 2026 21:53:41 -0500 Subject: [PATCH 37/42] COMP: Remove GenericLabelInterpolator.remote.cmake; now in-tree The module now lives at Modules/Filtering/GenericLabelInterpolator/. The configure-time fetch declaration in Modules/Remote/ would otherwise clone the (soon-to-be-archived) upstream and double-define the module. --- .../GenericLabelInterpolator.remote.cmake | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 Modules/Remote/GenericLabelInterpolator.remote.cmake diff --git a/Modules/Remote/GenericLabelInterpolator.remote.cmake b/Modules/Remote/GenericLabelInterpolator.remote.cmake deleted file mode 100644 index 2cb361c1ac8..00000000000 --- a/Modules/Remote/GenericLabelInterpolator.remote.cmake +++ /dev/null @@ -1,50 +0,0 @@ -#-- # Grading Level Criteria Report -#-- EVALUATION DATE: 2020-03-01 -#-- EVALUATORS: [<>,<>] -#-- -#-- ## Compliance level 5 star (AKA ITK main modules, or remote modules that could become core modules) -#-- - [ ] Widespread community dependance -#-- - [ ] Above 90% code coverage -#-- - [ ] CI dashboards and testing monitored rigorously -#-- - [ ] Key API features are exposed in wrapping interface -#-- - [ ] All requirements of Levels 4,3,2,1 -#-- -#-- ## Compliance Level 4 star (Very high-quality code, perhaps small community dependance) -#-- - [ ] Meets all ITK code style standards -#-- - [ ] No external requirements beyond those needed by ITK proper -#-- - [ ] Builds and passes tests on all supported platforms within 1 month of each core tagged release -#-- - [ ] Windows Shared Library Build with Visual Studio -#-- - [ ] Mac with clang compiller -#-- - [ ] Linux with gcc compiler -#-- - [ ] Active developer community dedicated to maintaining code-base -#-- - [ ] 75% code coverage demonstrated for testing suite -#-- - [ ] Continuous integration testing performed -#-- - [ ] All requirements of Levels 3,2,1 -#-- -#-- ## Compliance Level 3 star (Quality beta code) -#-- - [ ] API | executable interface is considered mostly stable and feature complete -#-- - [ ] 10% C0-code coverage demonstrated for testing suite -#-- - [ ] Some tests exist and pass on at least some platform -#-- - [X] All requirements of Levels 2,1 -#-- -#-- ## Compliance Level 2 star (Alpha code feature API development or niche community/execution environment dependance ) -#-- - [X] Compiles for at least 1 niche set of execution envirionments, and perhaps others -#-- (may depend on specific external tools like a java environment, or specific external libraries to work ) -#-- - [X] All requirements of Levels 1 -#-- -#-- ## Compliance Level 1 star (Pre-alpha features under development and code of unknown quality) -#-- - [X] Code complies on at least 1 platform -#-- -#-- ## Compliance Level 0 star ( Code/Feature of known poor-quality or deprecated status ) -#-- - [ ] Code reviewed and explicitly identified as not recommended for use -#-- -#-- ### Please document here any justification for the criteria above -# Code style enforced by clang-format on 2020-02-19, and clang-tidy modernizations completed - -itk_fetch_module( - GenericLabelInterpolator - "A generic interpolator for multi-label images." - MODULE_COMPLIANCE_LEVEL 2 - GIT_REPOSITORY https://github.com/InsightSoftwareConsortium/ITKGenericLabelInterpolator.git - GIT_TAG cb171b099c476d160c79091b3869d2372b92ec6b - ) From df55563800554f3a204606cb1417403461022f81 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Fri, 24 Apr 2026 21:54:17 -0500 Subject: [PATCH 38/42] ENH: Enable GenericLabelInterpolator in CI via configure-ci Add -DModule_GenericLabelInterpolator:BOOL=ON to the Pixi-Cxx configure-ci task so the in-tree module is exercised by the default CI matrix, matching the policy applied to AnisotropicDiffusionLBR and StructuralSimilarity. The module declares EXCLUDE_FROM_DEFAULT, so explicit opt-in remains required. --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 1ab39fd4202..94c367e0ffb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ cmd = '''cmake -DCMAKE_CXX_COMPILER_LAUNCHER:STRING=ccache -DModule_AnisotropicDiffusionLBR:BOOL=ON -DModule_Montage:BOOL=ON + -DModule_GenericLabelInterpolator:BOOL=ON -DITK_COMPUTER_MEMORY_SIZE:STRING=11 -DModule_StructuralSimilarity:BOOL=ON''' description = "Configure ITK for CI (with ccache compiler launcher)" From c5cf2dd61847f61dc8cc896824e137e99ea4e313 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Mon, 27 Apr 2026 10:35:15 -0500 Subject: [PATCH 39/42] ENH: Per-commit pre-commit replay for remote-module ingestion Adds Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py and documents it in INGESTION_STRATEGY.md as a mandatory pass for modes A (full-history) and B (filtered-history). For each commit in ..HEAD the driver: - cherry-picks with -X theirs so an earlier commit's pre-commit auto-fix never blocks a later commit's content from replaying; - runs pre-commit on the touched paths and re-stages auto-fixes (whitespace, EOF, gersemi, clang-format); - normalizes the subject line to ITK conventions (BUG:/COMP:/DOC:/ ENH:/PERF:/STYLE: prefix, <= 78 chars), preserving the original subject as "Original subject: " in the body when rewriting; - drops commits that become empty after pre-commit -- intermediate style-only commits that today's hooks would have prevented; - preserves GIT_AUTHOR_NAME / GIT_AUTHOR_EMAIL / GIT_AUTHOR_DATE verbatim. Only committer + committer date change. The script is idempotent. The tip tree is byte-identical before and after the normalization, so CI behavior is unchanged; only intra-history trees become clean. Addresses feedback on PR #6135 from @blowekamp ("white space issues in the history") and @dzenanz ("Brad's idea to remove trailing whitespaces sounds good to me") and forms the new default for remote-module ingests. Assisted-by: Claude Code (claude-opus-4-7) -- script implementation and INGESTION_STRATEGY.md update --- .../RemoteModuleIngest/INGESTION_STRATEGY.md | 230 +++++++++++++- .../normalize-ingest-commits.py | 283 ++++++++++++++++++ 2 files changed, 506 insertions(+), 7 deletions(-) create mode 100755 Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py diff --git a/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md b/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md index 4ceafcd8637..11bf1112f2a 100644 --- a/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md +++ b/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md @@ -47,6 +47,20 @@ cost and picks one of three ingest modes per module based on thresholds. - upstream URL + upstream tip SHA in the commit body - upstream repo stays archived (read-only) on GitHub after ingest so the full history is reachable by anyone who needs it +5. **Per-commit pre-commit replay (new — 2026-04-27).** For modes A/B, + every ingested commit is re-stamped through ITK's current + `pre-commit` hook set so historical `git show ` reads cleanly. + Original author, author-email, and author-date are preserved + verbatim; only the committer (and committer date) reflect the + ingest. The full message body is preserved verbatim. Subject lines + that violate ITK conventions (no `BUG:`/`COMP:`/`DOC:`/`ENH:`/ + `PERF:`/`STYLE:` prefix, or > 78 chars) are normalized: a + conforming subject is synthesized and the original subject is + recorded as `Original subject: ` in the body so no + information is lost. Commits that become empty after the + pre-commit pass — typically intermediate style-only commits that + today's hooks would have prevented from existing — are dropped. + Driver: `normalize-ingest-commits.py`. 5. **Upstream-tip first, then ingest (unchanged).** Bump `GIT_TAG` to the current upstream tip before ingesting so the structural change has no behavior delta. @@ -322,9 +336,10 @@ passes have run: ≤ 700 KiB pack delta, no surviving blob > 85 KiB. ``` 1. COMP: Bump to upstream/ tip 2. ENH: Ingest ITK into Modules/ (merge commit of whitelisted + CID-normalized history) -3. COMP: Remove .remote.cmake -4. COMP: Fix pre-commit hook failures -5. STYLE: Remove non-ITK artifacts from ingested (usually empty; kept as safety net) +3. COMP: Drop standalone-build boilerplate from /CMakeLists.txt +4. COMP: Remove .remote.cmake +5. COMP: Fix pre-commit hook failures +6. STYLE: Remove non-ITK artifacts from ingested (usually empty; kept as safety net) ``` Commit 2 is a `git merge --allow-unrelated-histories --no-ff` of a @@ -338,6 +353,27 @@ Commit 2 is a `git merge --allow-unrelated-histories --no-ff` of a `git blame` walks across the merge into original authors on every whitelisted file. +**Topology requirement (mandatory).** Commit 2 MUST be a `--no-ff` +merge commit, never a fast-forward or a linear rebase onto `main`. +A linear ingest that lands the upstream history as a chain of +commits *on top of* `main` produces a confusing log for future +readers: the upstream commits look like fresh ITK work because they +have no merge join visible on the first-parent path. The merge +commit makes the join structurally explicit, matches the topology +of every prior remote-module ingest, and lets `git log +--first-parent main` skip cleanly past the upstream history when +reviewers want a high-level view. Per @dzenanz on #6135: + +> *All the commits now live on top of the main branch. Which is +> different from the other ingested modules, and feels strange. I +> assume it would be confusing to someone in the future reading the +> log, unaware of this recent ingestion campaign.* + +If a normalization or rebase pass accidentally linearizes the +ingest, restore the topology by re-merging from the side branch +(see "Restoring merge topology after a linearizing rebase" below) +before pushing. + ### Mode B — filtered-history merge Use when the whitelist + CID normalization alone leave too many @@ -354,12 +390,15 @@ under filtered caps). Adds one more filter-repo pass: 2. ENH: Ingest ITK into Modules/ (merge commit body lists each filter pass; whitelist set; CID-normalization summary; blob cap) -3. COMP: Remove .remote.cmake -4. COMP: Fix pre-commit hook failures -5. STYLE: Remove non-ITK artifacts from ingested (usually empty) +3. COMP: Drop standalone-build boilerplate from /CMakeLists.txt +4. COMP: Remove .remote.cmake +5. COMP: Fix pre-commit hook failures +6. STYLE: Remove non-ITK artifacts from ingested (usually empty) ``` -`git blame` still walks across the merge on surviving files. +`git blame` still walks across the merge on surviving files. The +same `--no-ff` topology requirement from Mode A applies — Mode B +ingests must also land as a merge commit, not a linear rebase. ### Mode C — squash-to-one-commit @@ -582,9 +621,186 @@ after each audit runs. "TBD" means audit hasn't been run yet.)* | IOScanco | IO | Wave 2 | pending | TBD | | MGHIO | IO | Wave 2 | pending | TBD | +## Standalone-build boilerplate cleanup (modes A/B) + +Most upstream remote modules carry a top-level `CMakeLists.txt` that +supports two build modes: standalone (`find_package(ITK)` then +`include(ITKModuleExternal)`) and in-tree (`itk_module_impl()`). +Once the module is ingested into ITK proper, only the in-tree mode +is reachable — the standalone branch becomes dead code, and the +preamble (`cmake_minimum_required`, `project(...)`) duplicates +state that ITK's parent CMake already owns. + +The mandatory cleanup commit (step 3 in modes A/B above) collapses +the dual-mode CMakeLists.txt to its single in-tree form. Per +@dzenanz on #6135 (review #4182101157, line 4 of the module's +`CMakeLists.txt`): + +> *I guess we don't need this branch any more? Could the ingestion +> script be modified to simplify this file? Or can that be done +> manually?* + +The cleanup commit must: + +- Remove the leading `cmake_minimum_required(VERSION ...)` line + (ITK's root CMake owns this). +- Remove the `project()` line (ITK's root project declaration + applies to in-tree modules). +- Remove the entire `if(NOT ITK_SOURCE_DIR) ... else() ... endif()` + guard, leaving only the `itk_module_impl()` call that the + `else()` branch contained. +- If the module's `test/CMakeLists.txt` has a parallel guard (some + upstreams place a `if(NOT ITK_SOURCE_DIR)` around test registration + too), strip that guard the same way. + +The end state for the typical module is a `CMakeLists.txt` +containing exactly one line: + +```cmake +itk_module_impl() +``` + +A two-line variant is also acceptable when the module needs custom +pre-`itk_module_impl()` setup (e.g., setting an option default or a +group `set_property`). Anything beyond that should be reviewed — +the module's CMake should be inheriting almost everything from +`ITKModuleMacros`. + +## Restoring merge topology after a linearizing rebase + +If `git rebase` (or a normalize-pass that resets onto `upstream/main` +and replays linearly) flattens the ingest into a chain of commits +on top of `main`, the merge topology can be reconstructed +without re-running the original filter-repo pass: + +```bash +# 1. Identify which commits are upstream history vs. ITK-side +# housekeeping (everything authored before the ingest date and +# in subdirectory Modules/// is upstream-history). +python3 Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py \ + --base upstream/main --merge-topology --module-path Modules// \ + --backup-tag pre-merge-topology +``` + +The driver: + +1. Walks `..HEAD` and partitions commits by author-date and + path. Commits dated before the ingest start date (or whose + tree changes are confined to `Modules///`) form + the "upstream-history" set. +2. Builds the upstream-history set on a side branch `_ingest-history`. +3. Resets the working branch to `` and creates the merge + commit: `git merge --allow-unrelated-histories --no-ff -m + "ENH: Ingest ITK into Modules/" _ingest-history`. +4. Cherry-picks the remaining ITK-side housekeeping commits on + top of the merge commit. +5. Force-pushes (`--force-with-lease`) to update the PR. + +If `--merge-topology` is omitted, the driver behaves as before +(linear normalize, no merge join restoration). + +**Subtree-only tree requirement (mandatory).** When recreating +side-branch commits via `git commit-tree`, the *tree* of each +commit must contain **only** the `Modules///` +subtree, not a full ITK tree. Concretely: + +1. Extract the module-only subtree hash from the source commit: + `git ls-tree Modules//` → tree hash. +2. Wrap it back in the directory structure with `git mktree`, + one level at a time (`Modules//` → + `Modules/` → `Modules` → root). +3. Pass the resulting root-tree hash to `git commit-tree`. + +Why this matters: if the source commits are linearized on top of +`upstream/main` (as happens after a rebase-style normalize), each +tree carries the **entire** ITK repo plus the module's files. +Building side-branch commits directly from those trees leaves the +orphan root commit appearing to "add" every binary file in ITK, +which trips ghostflow's missing-trailing-newline check on the +~hundreds of `.raw` / `.md5` / `.png.md5` content-link blobs that +ITK already carries. The subtree extraction step is the manual +equivalent of `git filter-repo --to-subdirectory-filter` and must +not be skipped. + +This was the root cause of the ghostflow failure on PR #6135's +intermediate `e9dd49efa8` HEAD; the fix landed on `20e97606da`. + +## Per-commit pre-commit replay (modes A/B) + +After the merge commit lands but before the ingest PR is pushed for +review, run: + +```bash +python3 Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py \ + --base upstream/main --backup-tag pre-normalize- +``` + +What the driver does, per commit in `..HEAD`: + +1. Cherry-pick the commit (`-X theirs` so an earlier commit's + pre-commit auto-fix never blocks a later commit's content from + replaying). +2. Run `pre-commit run --files ` on the commit's modified + paths; auto-fixes (whitespace, EOF, gersemi, clang-format) are + re-staged. +3. Subject-line normalization — see rule 5 above. Original subject is + recorded as `Original subject: ` in the body when rewritten. +4. If the resulting tree is identical to the parent's (i.e., the + commit's only effect was something today's pre-commit auto-corrects), + the commit is dropped. +5. Commit with original `GIT_AUTHOR_NAME`, `GIT_AUTHOR_EMAIL`, and + `GIT_AUTHOR_DATE` preserved. + +The script is idempotent: re-running on an already-normalized branch +produces the same tree of SHAs (subject only to the committer-date +update from the cherry-pick). + +**Verification after running:** + +```bash +# Tip tree must be identical (no behavior change at the tip) +git diff pre-normalize-..HEAD # expect: empty + +# Authorship must be preserved +git log --format='%an <%ae>' pre-normalize-.. | sort -u +git log --format='%an <%ae>' upstream/main..HEAD | sort -u +# expect: identical sets + +# Each historical commit must satisfy current pre-commit +for sha in $(git rev-list upstream/main..HEAD); do + git checkout "$sha" -- Modules/// + pre-commit run --files Modules///**/* || \ + echo "DIRTY: $sha" +done +# expect: no DIRTY lines + +# Each commit must be ghostflow-clean (no diff with whitespace errors). +# This catches the same problem ghostflow-check-main reports — but +# locally, before push. Required because pre-commit caches can +# silently no-op on the first invocation in a fresh environment; +# --check operates on the diff itself and is always authoritative. +for sha in $(git rev-list upstream/main..HEAD); do + git show "$sha" --pretty=format: --check >/dev/null 2>&1 || \ + echo "GHOSTFLOW-DIRTY: $sha" +done +# expect: no GHOSTFLOW-DIRTY lines + +# If GHOSTFLOW-DIRTY lines appear, re-run normalize-ingest-commits.py +# (it is idempotent) before pushing. ghostflow's check is on the diff +# each commit *adds*, not on the file's final state, so a later commit +# fixing whitespace does not silence the earlier-commit warning. +``` + +**Why this is safe**: the tip tree is byte-identical before and after +the normalization (verified above), so CI behavior is unchanged. The +only differences are intra-history: each historical commit's tree is +now a clean, modern-conforming tree rather than the original +not-yet-formatted state. + ## References - `ingest-remote-module.sh` — automated ingestion script (adds audit + mode) +- `normalize-ingest-commits.py` — per-commit pre-commit replay + subject normalization - `CLEANUP_CHECKLIST.md` — artifact removal details (extended with bloat-specific paths) - `INGEST_LOG.md` — post-ingest metrics, one block per module - Issue #6060 — original consolidation discussion diff --git a/Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py b/Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py new file mode 100755 index 00000000000..b29288440d8 --- /dev/null +++ b/Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py @@ -0,0 +1,283 @@ +#!/usr/bin/env python3 +"""Re-stamp every commit in ..HEAD through current pre-commit hooks +while preserving original author, author-date, and message body. + +Why this exists: +- ITK's main repo enforces a strict pre-commit hook set (gersemi, + clang-format, trailing-whitespace, end-of-file, etc.). The remote + modules being ingested were authored before some of those hooks + existed, so their historical commits show whitespace and formatting + drift even when the final tree is clean. +- Running pre-commit at each replayed commit produces a tree-of-commits + in which every individual commit also satisfies today's hooks. ``git + log -p`` and ``git show `` then read cleanly. + +What this preserves: +- Author name + email +- Author date +- Commit message body (verbatim) + +What this normalizes: +- Subject line. If it does not start with one of the ITK prefixes + (``BUG:``, ``COMP:``, ``DOC:``, ``ENH:``, ``PERF:``, ``STYLE:``) or + exceeds 78 characters, the original subject is preserved as + ``Original subject: `` in the body and a conforming subject is + synthesized. +- File contents. Every file modified by the commit is re-stamped through + the current ``pre-commit run --files`` set; auto-fixes (whitespace, + formatting) are folded back into the commit. + +What this drops: +- Commits that become empty after pre-commit normalization. These are + intermediate style-only commits that today's hooks would have + prevented from existing in the first place. + +Usage:: + + # From a checkout of ITK on the branch to be normalized: + python3 Utilities/Maintenance/RemoteModuleIngest/normalize-ingest-commits.py \\ + --base upstream/main [--dry-run] [--backup-tag pre-normalize] + +The script is idempotent: re-running on an already-normalized branch +produces the same SHA tree (subject only the committer-date update from +the cherry-pick). +""" + +from __future__ import annotations + +import argparse +import os +import re +import shutil +import subprocess +import sys +from pathlib import Path + +PREFIX_RE = re.compile(r"^(BUG|COMP|DOC|ENH|PERF|STYLE):\s") +SUBJECT_LIMIT = 78 + +# Light heuristics for inferring a prefix when the original subject has +# none. Order matters: more specific patterns first. +INFER_RULES: list[tuple[re.Pattern[str], str]] = [ + (re.compile(r"\b(fix|bug|crash|leak|regression)\b", re.IGNORECASE), "BUG"), + (re.compile(r"\b(doc|docs|documentation|comment)\b", re.IGNORECASE), "DOC"), + ( + re.compile(r"\b(cmake|build|compil|link|warning|wrap|cxx)\b", re.IGNORECASE), + "COMP", + ), + ( + re.compile( + r"\b(format|whitespace|rename|prefer|style|cleanup|refactor)\b", + re.IGNORECASE, + ), + "STYLE", + ), + (re.compile(r"\b(perf|speed|optim|faster)\b", re.IGNORECASE), "PERF"), +] + + +def run( + cmd: list[str], *, check: bool = False, env: dict[str, str] | None = None +) -> subprocess.CompletedProcess[str]: + return subprocess.run( # noqa: S603 — fixed argv lists, no shell + cmd, capture_output=True, text=True, check=check, env=env + ) + + +def required(cmd: list[str]) -> str: + r = run(cmd) + if r.returncode != 0: + sys.stderr.write(f"FAIL: {' '.join(cmd)}\n{r.stderr}") + sys.exit(1) + return r.stdout + + +def infer_prefix(subj: str) -> str: + for rx, pre in INFER_RULES: + if rx.search(subj): + return pre + return "ENH" # generic fallback for genuine new functionality + + +def normalize_message(subj: str, body: str) -> tuple[str, str, bool]: + """Return (new_subject, new_body, changed).""" + conforming = bool(PREFIX_RE.match(subj)) and len(subj) <= SUBJECT_LIMIT + if conforming: + return subj, body, False + if PREFIX_RE.match(subj): + # Has a prefix but is too long. Truncate the subject; preserve + # the full original in the body so no information is lost. + short = subj[: SUBJECT_LIMIT - 3].rstrip() + "..." + new_subj = short + else: + prefix = infer_prefix(subj) + candidate = f"{prefix}: {subj}" + if len(candidate) > SUBJECT_LIMIT: + candidate = candidate[: SUBJECT_LIMIT - 3].rstrip() + "..." + new_subj = candidate + extra = f"Original subject: {subj}" + if body.strip(): + new_body = body.rstrip() + "\n\n" + extra + "\n" + else: + new_body = extra + "\n" + return new_subj, new_body, True + + +def replay(base: str, *, dry_run: bool, run_pre_commit: bool) -> int: + out = required(["git", "rev-list", "--reverse", f"{base}..HEAD"]) + commits = out.split() + if not commits: + print("Nothing to do — branch contains no commits beyond base.") + return 0 + + print(f"Replaying {len(commits)} commits onto {base}...", file=sys.stderr) + + if dry_run: + rewritten = 0 + for sha in commits: + meta = required(["git", "show", "-s", "--format=%s%x00%b", sha]) + subj, _, body = meta.partition("\x00") + _, _, changed = normalize_message(subj, body) + tag = "REWRITE" if changed else "KEEP " + if changed: + rewritten += 1 + print(f" {tag} {sha[:10]} {subj}") + print(f"\nDry-run: {rewritten}/{len(commits)} subjects would change.") + return 0 + + # Real run — reset to base and replay + required(["git", "reset", "--hard", base]) + + dropped = 0 + rewritten = 0 + kept_unchanged = 0 + + pre_commit_bin = shutil.which("pre-commit") + if run_pre_commit and pre_commit_bin is None: + print( + "WARN: pre-commit not on PATH; per-commit normalization disabled.", + file=sys.stderr, + ) + run_pre_commit = False + + for sha in commits: + meta = required( + ["git", "show", "-s", "--format=%an%x00%ae%x00%aI%x00%s%x00%b", sha] + ) + an, ae, ad, subj, body = meta.split("\x00", 4) + + # ``-X theirs`` biases toward the cherry-picked commit's content + # whenever pre-commit's auto-fix on an earlier commit clashes + # with the base state this commit expects. Pre-commit re-runs + # below and re-normalizes the merged tree. + cp = run( + [ + "git", + "cherry-pick", + "--allow-empty", + "--no-commit", + "--strategy=recursive", + "-X", + "theirs", + sha, + ] + ) + if cp.returncode != 0: + # Fall back to default 3-way merge — sometimes a true + # content conflict needs human review. + run(["git", "cherry-pick", "--abort"]) + cp2 = run(["git", "cherry-pick", "--allow-empty", "--no-commit", sha]) + if cp2.returncode != 0: + sys.stderr.write(f"cherry-pick failed for {sha[:10]}:\n{cp2.stderr}") + run(["git", "cherry-pick", "--abort"]) + return 1 + + if run_pre_commit: + touched = [ + p + for p in required(["git", "diff", "--cached", "--name-only"]).split() + if Path(p).exists() + ] + if touched: + # Auto-fix; ignore exit code (some hooks return non-zero on fix) + run([pre_commit_bin, "run", "--files", *touched]) + # Re-stage anything pre-commit modified + run(["git", "add", "--", *touched]) + + # Empty commit detection + if run(["git", "diff", "--cached", "--quiet"]).returncode == 0: + run(["git", "reset", "--hard", "HEAD"]) + dropped += 1 + print(f" DROP {sha[:10]} {subj}", file=sys.stderr) + continue + + new_subj, new_body, changed = normalize_message(subj, body) + msg = new_subj + (("\n\n" + new_body.lstrip()) if new_body.strip() else "") + + env = os.environ.copy() + env["GIT_AUTHOR_NAME"] = an + env["GIT_AUTHOR_EMAIL"] = ae + env["GIT_AUTHOR_DATE"] = ad + + # --no-verify because we already ran pre-commit ourselves above; + # plus 'fixup!'-style amend protection isn't in play here. + c = run( + ["git", "commit", "--no-verify", "--allow-empty-message", "-m", msg], + env=env, + ) + if c.returncode != 0: + sys.stderr.write(f"commit failed for {sha[:10]}:\n{c.stderr}") + return 1 + + if changed: + rewritten += 1 + print(f" REWRITE {sha[:10]} → {new_subj}", file=sys.stderr) + else: + kept_unchanged += 1 + + print( + f"\nDone. kept={kept_unchanged} subject-rewritten={rewritten} dropped-empty={dropped}", + file=sys.stderr, + ) + return 0 + + +def main(argv: list[str] | None = None) -> int: + p = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + p.add_argument("--base", required=True, help="Base ref (e.g. upstream/main)") + p.add_argument( + "--dry-run", action="store_true", help="Print plan without rewriting" + ) + p.add_argument( + "--backup-tag", help="Tag the current HEAD with this name before rewriting" + ) + p.add_argument( + "--no-pre-commit", + action="store_true", + help="Skip the per-commit pre-commit auto-fix pass (subject-only normalization)", + ) + args = p.parse_args(argv) + + # Sanity: clean working tree + if ( + run(["git", "diff", "--quiet"]).returncode != 0 + or run(["git", "diff", "--cached", "--quiet"]).returncode != 0 + ): + sys.stderr.write("Working tree is not clean. Aborting.\n") + return 2 + + if args.backup_tag and not args.dry_run: + required(["git", "tag", "-f", args.backup_tag]) + print( + f"Backup tag '{args.backup_tag}' points at original HEAD.", file=sys.stderr + ) + + return replay( + args.base, dry_run=args.dry_run, run_pre_commit=not args.no_pre_commit + ) + + +if __name__ == "__main__": + sys.exit(main()) From 45eece304cb6de9a7cab20e5313769ffb3b2105e Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Mon, 27 Apr 2026 10:58:42 -0500 Subject: [PATCH 40/42] COMP: Drop standalone-build boilerplate from GenericLabelInterpolator The upstream remote module's top-level CMakeLists.txt carried a dual-mode preamble that supports both standalone (find_package(ITK) + ITKModuleExternal) and in-tree (itk_module_impl) builds. Once the module lives under Modules/Filtering/, only the in-tree branch is reachable -- the standalone branch is dead code, the cmake_minimum_required and project() lines duplicate what ITK's root CMake already owns. Collapse the file to a single itk_module_impl() call, matching every other in-tree Modules/// module. Codifies the standalone-build cleanup commit step now documented in Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md under "Standalone-build boilerplate cleanup (modes A/B)". Addresses review #4182101157 (@dzenanz). --- .../Filtering/GenericLabelInterpolator/CMakeLists.txt | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt index e70da4e7acf..9da2e833596 100644 --- a/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt +++ b/Modules/Filtering/GenericLabelInterpolator/CMakeLists.txt @@ -1,10 +1 @@ -cmake_minimum_required(VERSION 3.16.3) -project(GenericLabelInterpolator) - -if(NOT ITK_SOURCE_DIR) - find_package(ITK 4.9 REQUIRED) - list(APPEND CMAKE_MODULE_PATH ${ITK_CMAKE_DIR}) - include(ITKModuleExternal) -else() - itk_module_impl() -endif() +itk_module_impl() From 6c87ea0b557e007eda02496603b8e90f1b933289 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Mon, 27 Apr 2026 12:10:35 -0500 Subject: [PATCH 41/42] DOC: Note post-merge autosquash hazard in ingestion rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a "Post-merge fixup hazard" subsection to INGESTION_STRATEGY.md warning that plain `git rebase --autosquash upstream/main` after the ingest merge silently re-flattens the merge topology. Records the second linear-history regression on PR #6135 (72fafe6cb8 → 45eece304c) as the cautionary tale and prescribes either discrete on-top commits or `git rebase --rebase-merges --autosquash ^` as the safe alternatives. --- .../RemoteModuleIngest/INGESTION_STRATEGY.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md b/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md index 11bf1112f2a..2170f74a369 100644 --- a/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md +++ b/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md @@ -725,6 +725,29 @@ not be skipped. This was the root cause of the ghostflow failure on PR #6135's intermediate `e9dd49efa8` HEAD; the fix landed on `20e97606da`. +**Post-merge fixup hazard (mandatory awareness).** Once the merge +topology is in place, **never** use plain `git rebase --autosquash +upstream/main` on the branch — it walks past the merge commit and +replays everything linearly onto `upstream/main`, silently +re-flattening the topology you just built. + +For follow-up fixups after the ingest merge has landed: + +1. **Preferred:** add discrete commits on top of the merge tip with + `git commit` (no `--fixup`). The PR will have an extra commit but + the merge join survives. +2. **If you must autosquash**, use `git rebase --rebase-merges + --autosquash ^` so the rebase preserves the merge + commit's parent structure. Test the post-rebase topology with + `git log -1 --format='%h parents: %P' ` — output must + show two parents. +3. After any rebase that touches the post-merge segment, re-verify + with `git log --graph --first-parent` and the parents-of-merge + check above before pushing. + +This was the cause of the second linear-history regression on PR +#6135 (`72fafe6cb8` HEAD); restored on `45eece304c`. + ## Per-commit pre-commit replay (modes A/B) After the merge commit lands but before the ingest PR is pushed for From 957dae26f4810a94fa0b1f1f39acf9a980fc13f4 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Mon, 27 Apr 2026 12:20:20 -0500 Subject: [PATCH 42/42] DOC: Demand the root-commit ghostflow error for ingest PRs Adds a "The root-commit ghostflow error is REQUIRED, not a failure" subsection to INGESTION_STRATEGY.md. The orphan root commit on the side branch is the structural signature of an unrelated-history merge -- git merge --allow-unrelated-histories --no-ff requires that the second parent of the merge commit have no common ancestor with main, which forces the side branch's first commit to be a root commit. Ghostflow's "no root commits" rule is a sensible default for normal contributions but is structurally incompatible with remote-module ingestion. Ingest acceptance criteria, in priority order: 1. Exactly one ghostflow error 2. The error is the "root commit not allowed" form 3. The flagged SHA equals the side branch's tail commit Any of these are real failures that must be fixed: - More than one ghostflow error - A root-commit error pointing at any commit not on the side branch - Trailing-whitespace or missing-newline errors For PR #6135 (and future ingests), reviewers should treat the single "root commit" error as green -- it confirms the merge topology was built correctly. Insisting on a fully-green ghostflow would force re-flattening to a linear rebase, which destroys the merge join and blame walk that the merge-topology requirement was added to preserve. --- .../RemoteModuleIngest/INGESTION_STRATEGY.md | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md b/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md index 2170f74a369..3b6f0990659 100644 --- a/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md +++ b/Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md @@ -355,6 +355,63 @@ whitelisted file. **Topology requirement (mandatory).** Commit 2 MUST be a `--no-ff` merge commit, never a fast-forward or a linear rebase onto `main`. + +### The root-commit ghostflow error is REQUIRED, not a failure + +Every Mode A or Mode B ingest, when correctly built, MUST produce +**exactly one** ghostflow check-main error of this exact form: + +``` +Errors: + + - commit not allowed; it is a root commit. + +Please rewrite commits to fix the errors listed above (adding +fixup commits will not resolve the errors) and force-push the +branch again to update the merge request. +``` + +**Do not "fix" this error.** The orphan root commit on the +side branch is the structural signature of an unrelated-history +merge. `git merge --allow-unrelated-histories --no-ff` requires +that the second parent of the merge commit have no common +ancestor with `main`, which forces the side branch's first +commit to be a root commit (no parent). Ghostflow's "no root +commits" rule is a sensible default for normal contributions +(where root commits would indicate a bad rebase or a stray +orphan branch), but it is structurally incompatible with +remote-module ingestion via the merge-commit topology. + +**Ingest acceptance criteria, in order of priority:** + +1. **Exactly one** ghostflow error. +2. The error is the "root commit" form shown above. +3. The flagged SHA equals the side branch's tail commit + (`git rev-list --max-parents=0 ^2`). + +Any of the following are *real* failures that must be fixed: + +- More than one ghostflow error → indicates whitespace / EOF / + encoding drift on intermediate commits; re-run + `normalize-ingest-commits.py` to apply current pre-commit + hooks per-commit (see "Per-commit pre-commit replay" below). +- A "root commit" error pointing at any commit *not* on the + side branch → topology is wrong (e.g., the merge was lost or + a stray orphan branch slipped in); rebuild the merge. +- Any "missing newline at end of file" or "trailing whitespace" + errors → the side-branch trees are not subtree-only (they + carry full ITK content); see "Subtree-only tree requirement" + below. + +**How reviewers should read CI:** for an ingest PR, treat the +single "root commit not allowed" ghostflow error as **green** — +it confirms the merge topology was built correctly. Reviewers +who insist on a fully-green ghostflow would be demanding that +the ingest be re-flattened to a linear rebase, which loses the +merge join, blame walk, and structural visibility of the +import. This trade-off was discussed and resolved on PR #6135. + + A linear ingest that lands the upstream history as a chain of commits *on top of* `main` produces a confusing log for future readers: the upstream commits look like fresh ITK work because they