From 8bcee9ae4179085aabe3aaf10e9b542fd498cbfa Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Sat, 29 Jun 2024 00:40:45 +0200 Subject: [PATCH] ENH: Replace "SubtractMean" with "UseZeroAverageDisplacementConstraint" Sets its default "true". (For the affected elastix metrics (`PCAMetric`, `PCAMetric2`, `SumOfPairwiseCorrelationCoefficients`, `VarianceOverLastDimension`), the SubtractMean parameter originally had "false" as default.) The term "UseZeroAverageDisplacementConstraint" is more specific than "SubtractMean", so it appears preferably. Discussed with Marius Staring and Stefan Klein. Added a warning about this change to the `Initialize()` member functions of the affected elastix metrics. If "SubtractMean" is specified, now using its value as default for "UseZeroAverageDisplacementConstraint", for backward compatibility. --- Components/Metrics/PCAMetric/elxPCAMetric.h | 8 +++++--- Components/Metrics/PCAMetric/elxPCAMetric.hxx | 20 ++++++++++++++++--- Components/Metrics/PCAMetric/itkPCAMetric.h | 4 ++-- Components/Metrics/PCAMetric/itkPCAMetric.hxx | 2 +- .../PCAMetric/itkPCAMetric_F_multithreaded.h | 4 ++-- .../itkPCAMetric_F_multithreaded.hxx | 4 ++-- Components/Metrics/PCAMetric2/elxPCAMetric2.h | 8 +++++--- .../Metrics/PCAMetric2/elxPCAMetric2.hxx | 20 ++++++++++++++++--- Components/Metrics/PCAMetric2/itkPCAMetric2.h | 4 ++-- .../Metrics/PCAMetric2/itkPCAMetric2.hxx | 2 +- ...mOfPairwiseCorrelationCoefficientsMetric.h | 8 +++++--- ...fPairwiseCorrelationCoefficientsMetric.hxx | 20 ++++++++++++++++--- ...mOfPairwiseCorrelationCoefficientsMetric.h | 4 ++-- ...fPairwiseCorrelationCoefficientsMetric.hxx | 2 +- .../elxVarianceOverLastDimensionMetric.h | 8 +++++--- .../elxVarianceOverLastDimensionMetric.hxx | 20 ++++++++++++++++--- .../itkVarianceOverLastDimensionImageMetric.h | 4 ++-- ...tkVarianceOverLastDimensionImageMetric.hxx | 2 +- 18 files changed, 104 insertions(+), 40 deletions(-) diff --git a/Components/Metrics/PCAMetric/elxPCAMetric.h b/Components/Metrics/PCAMetric/elxPCAMetric.h index 26938a032..4a90d6f61 100644 --- a/Components/Metrics/PCAMetric/elxPCAMetric.h +++ b/Components/Metrics/PCAMetric/elxPCAMetric.h @@ -49,9 +49,11 @@ namespace elastix * be set with parameter NumSamplesLastDimension. \n * \parameter NumSamplesLastDimension: the number of random samples to take in the time * time direction of the data when SampleLastDimensionRandomly is set to true. - * \parameter SubtractMean: subtract the over time computed mean parameter value from - * each parameter. This should be used when registration is performed directly on the moving - * image, without using a fixed image. Possible values are "true" or "false". + * \parameter UseZeroAverageDisplacementConstraint: uses the zero average displacement constraint, as described in + * Nonrigid registration of dynamic medical imaging data using nD+t B-splines and a groupwise optimization + * approach, Metz et al., Medical Image Analysis, 2011. Subtract the over time computed mean parameter value + * from each parameter. This should be used when registration is performed directly on the moving image, without + * using a fixed image. Possible values are "true" or "false". Default is "true". * \parameter NumEigenValues: number of eigenvalues used in the metric: sum(e) - e, where sum(e) * is the sum of all eigenvalues and e is the sum of the first highest NumEigenValues eigenvalues. * diff --git a/Components/Metrics/PCAMetric/elxPCAMetric.hxx b/Components/Metrics/PCAMetric/elxPCAMetric.hxx index 068edc904..08531f6a4 100644 --- a/Components/Metrics/PCAMetric/elxPCAMetric.hxx +++ b/Components/Metrics/PCAMetric/elxPCAMetric.hxx @@ -36,6 +36,17 @@ PCAMetric::Initialize() itk::TimeProbe timer; timer.Start(); this->Superclass1::Initialize(); + + const Configuration & configuration = itk::Deref(Superclass2::GetConfiguration()); + + if (configuration.HasParameter("SubtractMean")) + { + log::warn(std::string("WARNING: From elastix version 5.2, the ") + elxGetClassNameStatic() + + " parameter `SubtractMean` (default \"false\") is " + "replaced with `UseZeroAverageDisplacementConstraint` " + "(default \"true\")."); + } + timer.Stop(); log::info(std::ostringstream{} << "Initialization of PCAMetric metric took: " << static_cast(timer.GetMean() * 1000) << " ms."); @@ -62,9 +73,12 @@ PCAMetric::BeforeEachResolution() this->SetNumEigenValues(NumEigenValues); /** Get and set if we want to subtract the mean from the derivative. */ - bool subtractMean = false; - configuration.ReadParameter(subtractMean, "SubtractMean", componentLabel, 0, 0); - this->SetSubtractMean(subtractMean); + bool useZeroAverageDisplacementConstraint = true; + // The parameter name "SubtractMean" is obsolete, so just use it as initial value, for backward compatibility. + configuration.ReadParameter(useZeroAverageDisplacementConstraint, "SubtractMean", componentLabel, 0, 0); + configuration.ReadParameter( + useZeroAverageDisplacementConstraint, "UseZeroAverageDisplacementConstraint", componentLabel, 0, 0); + this->SetUseZeroAverageDisplacementConstraint(useZeroAverageDisplacementConstraint); /** Get and set the number of additional samples sampled at the fixed timepoint. */ // unsigned int numAdditionalSamplesFixed = 0; diff --git a/Components/Metrics/PCAMetric/itkPCAMetric.h b/Components/Metrics/PCAMetric/itkPCAMetric.h index e10e3f076..2d56c96d2 100644 --- a/Components/Metrics/PCAMetric/itkPCAMetric.h +++ b/Components/Metrics/PCAMetric/itkPCAMetric.h @@ -53,7 +53,7 @@ class ITK_TEMPLATE_EXPORT PCAMetric : public AdvancedImageToImageMetric::GetValueAndDerivative(const TransformParam derivative = -tracevKvdmu; /** Subtract mean from derivative elements. */ - if (m_SubtractMean) + if (m_UseZeroAverageDisplacementConstraint) { if (!m_TransformIsStackTransform) { diff --git a/Components/Metrics/PCAMetric/itkPCAMetric_F_multithreaded.h b/Components/Metrics/PCAMetric/itkPCAMetric_F_multithreaded.h index 23e7e57a2..8b29c48b6 100644 --- a/Components/Metrics/PCAMetric/itkPCAMetric_F_multithreaded.h +++ b/Components/Metrics/PCAMetric/itkPCAMetric_F_multithreaded.h @@ -50,7 +50,7 @@ class ITK_TEMPLATE_EXPORT PCAMetric : public AdvancedImageToImageMetric::GetValueAndDerivativeSingleThreaded(const measure = m_G - sumEigenValuesUsed; /** Subtract mean from derivative elements. */ - if (m_SubtractMean) + if (m_UseZeroAverageDisplacementConstraint) { if (!m_TransformIsStackTransform) { @@ -958,7 +958,7 @@ PCAMetric::AfterThreadedComputeDerivative(DerivativeT derivative *= -(2.0 / (DerivativeValueType(Superclass::m_NumberOfPixelsCounted) - 1.0)); // normalize /** Subtract mean from derivative elements. */ - if (m_SubtractMean) + if (m_UseZeroAverageDisplacementConstraint) { if (!m_TransformIsStackTransform) { diff --git a/Components/Metrics/PCAMetric2/elxPCAMetric2.h b/Components/Metrics/PCAMetric2/elxPCAMetric2.h index c4a0dabab..20fe2d285 100644 --- a/Components/Metrics/PCAMetric2/elxPCAMetric2.h +++ b/Components/Metrics/PCAMetric2/elxPCAMetric2.h @@ -49,9 +49,11 @@ namespace elastix * be set with parameter NumSamplesLastDimension. \n * \parameter NumSamplesLastDimension: the number of random samples to take in the time * time direction of the data when SampleLastDimensionRandomly is set to true. - * \parameter SubtractMean: subtract the over time computed mean parameter value from - * each parameter. This should be used when registration is performed directly on the moving - * image, without using a fixed image. Possible values are "true" or "false". + * \parameter UseZeroAverageDisplacementConstraint: uses the zero average displacement constraint, as described in + * Nonrigid registration of dynamic medical imaging data using nD+t B-splines and a groupwise optimization + * approach, Metz et al., Medical Image Analysis, 2011. Subtract the over time computed mean parameter value + * from each parameter. This should be used when registration is performed directly on the moving image, without + * using a fixed image. Possible values are "true" or "false". Default is "true". * \parameter NumEigenValues: number of eigenvalues used in the metric: sum(e) - e, where sum(e) * is the sum of all eigenvalues and e is the sum of the first highest NumEigenValues eigenvalues. * diff --git a/Components/Metrics/PCAMetric2/elxPCAMetric2.hxx b/Components/Metrics/PCAMetric2/elxPCAMetric2.hxx index 72573e6d8..6bd28aa60 100644 --- a/Components/Metrics/PCAMetric2/elxPCAMetric2.hxx +++ b/Components/Metrics/PCAMetric2/elxPCAMetric2.hxx @@ -36,6 +36,17 @@ PCAMetric2::Initialize() itk::TimeProbe timer; timer.Start(); this->Superclass1::Initialize(); + + const Configuration & configuration = itk::Deref(Superclass2::GetConfiguration()); + + if (configuration.HasParameter("SubtractMean")) + { + log::warn(std::string("WARNING: From elastix version 5.2, the ") + elxGetClassNameStatic() + + " parameter `SubtractMean` (default \"false\") is " + "replaced with `UseZeroAverageDisplacementConstraint` " + "(default \"true\")."); + } + timer.Stop(); log::info(std::ostringstream{} << "Initialization of PCAMetric2 metric took: " << static_cast(timer.GetMean() * 1000) << " ms."); @@ -58,9 +69,12 @@ PCAMetric2::BeforeEachResolution() unsigned int level = (this->m_Registration->GetAsITKBaseType())->GetCurrentLevel(); /** Get and set if we want to subtract the mean from the derivative. */ - bool subtractMean = false; - configuration.ReadParameter(subtractMean, "SubtractMean", componentLabel, 0, 0); - this->SetSubtractMean(subtractMean); + bool useZeroAverageDisplacementConstraint = true; + // The parameter name "SubtractMean" is obsolete, so just use it as initial value, for backward compatibility. + configuration.ReadParameter(useZeroAverageDisplacementConstraint, "SubtractMean", componentLabel, 0, 0); + configuration.ReadParameter( + useZeroAverageDisplacementConstraint, "UseZeroAverageDisplacementConstraint", componentLabel, 0, 0); + this->SetUseZeroAverageDisplacementConstraint(useZeroAverageDisplacementConstraint); /** Get and set the number of additional samples sampled at the fixed timepoint. */ unsigned int numAdditionalSamplesFixed = 0; diff --git a/Components/Metrics/PCAMetric2/itkPCAMetric2.h b/Components/Metrics/PCAMetric2/itkPCAMetric2.h index 71dc6f301..6710c87b4 100644 --- a/Components/Metrics/PCAMetric2/itkPCAMetric2.h +++ b/Components/Metrics/PCAMetric2/itkPCAMetric2.h @@ -51,7 +51,7 @@ class ITK_TEMPLATE_EXPORT PCAMetric2 : public AdvancedImageToImageMetric::GetValueAndDerivative(const TransformPara measure = sumWeightedEigenValues; /** Subtract mean from derivative elements. */ - if (m_SubtractMean) + if (m_UseZeroAverageDisplacementConstraint) { if (!m_TransformIsStackTransform) { diff --git a/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.h b/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.h index 8713634ca..40b370ae0 100644 --- a/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.h +++ b/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.h @@ -51,9 +51,11 @@ namespace elastix * be set with parameter NumSamplesLastDimension. \n * \parameter NumSamplesLastDimension: the number of random samples to take in the time * time direction of the data when SampleLastDimensionRandomly is set to true. - * \parameter SubtractMean: subtract the over time computed mean parameter value from - * each parameter. This should be used when registration is performed directly on the moving - * image, without using a fixed image. Possible values are "true" or "false". + * \parameter UseZeroAverageDisplacementConstraint: uses the zero average displacement constraint, as described in + * Nonrigid registration of dynamic medical imaging data using nD+t B-splines and a groupwise optimization + * approach, Metz et al., Medical Image Analysis, 2011. Subtract the over time computed mean parameter value + * from each parameter. This should be used when registration is performed directly on the moving image, without + * using a fixed image. Possible values are "true" or "false". Default is "true". * * \ingroup RegistrationMetrics * \ingroup Metrics diff --git a/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.hxx b/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.hxx index 3cf8be920..b1f1cf9d0 100644 --- a/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.hxx +++ b/Components/Metrics/SumOfPairwiseCorrelationsMetric/elxSumOfPairwiseCorrelationCoefficientsMetric.hxx @@ -37,6 +37,17 @@ SumOfPairwiseCorrelationCoefficientsMetric::Initialize() itk::TimeProbe timer; timer.Start(); this->Superclass1::Initialize(); + + const Configuration & configuration = itk::Deref(Superclass2::GetConfiguration()); + + if (configuration.HasParameter("SubtractMean")) + { + log::warn(std::string("WARNING: From elastix version 5.2, the ") + elxGetClassNameStatic() + + " parameter `SubtractMean` (default \"false\") is " + "replaced with `UseZeroAverageDisplacementConstraint` " + "(default \"true\")."); + } + timer.Stop(); log::info(std::ostringstream{} << "Initialization of SumOfPairwiseCorrelationCoefficientsMetric metric took: " << static_cast(timer.GetMean() * 1000) << " ms."); @@ -59,9 +70,12 @@ SumOfPairwiseCorrelationCoefficientsMetric::BeforeEachResolution() unsigned int level = (this->m_Registration->GetAsITKBaseType())->GetCurrentLevel(); /** Get and set if we want to subtract the mean from the derivative. */ - bool subtractMean = false; - configuration.ReadParameter(subtractMean, "SubtractMean", componentLabel, 0, 0); - this->SetSubtractMean(subtractMean); + bool useZeroAverageDisplacementConstraint = true; + // The parameter name "SubtractMean" is obsolete, so just use it as initial value, for backward compatibility. + configuration.ReadParameter(useZeroAverageDisplacementConstraint, "SubtractMean", componentLabel, 0, 0); + configuration.ReadParameter( + useZeroAverageDisplacementConstraint, "UseZeroAverageDisplacementConstraint", componentLabel, 0, 0); + this->SetUseZeroAverageDisplacementConstraint(useZeroAverageDisplacementConstraint); /** Get and set the number of additional samples sampled at the fixed timepoint. */ unsigned int numAdditionalSamplesFixed = 0; diff --git a/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.h b/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.h index 213af5d8a..bc312c0b7 100644 --- a/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.h +++ b/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.h @@ -52,7 +52,7 @@ class ITK_TEMPLATE_EXPORT SumOfPairwiseCorrelationCoefficientsMetric /** Set functions. */ itkSetMacro(NumAdditionalSamplesFixed, unsigned int); itkSetMacro(ReducedDimensionIndex, unsigned int); - itkSetMacro(SubtractMean, bool); + itkSetMacro(UseZeroAverageDisplacementConstraint, bool); itkSetMacro(GridSize, FixedImageSizeType); itkSetMacro(TransformIsStackTransform, bool); @@ -161,7 +161,7 @@ class ITK_TEMPLATE_EXPORT SumOfPairwiseCorrelationCoefficientsMetric unsigned int m_ReducedDimensionIndex{}; /** Bool to determine if we want to subtract the mean derivate from the derivative elements. */ - bool m_SubtractMean{ true }; + bool m_UseZeroAverageDisplacementConstraint{ true }; /** GridSize of B-spline transform. */ FixedImageSizeType m_GridSize{}; diff --git a/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.hxx b/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.hxx index 29afae65d..be4b0be10 100644 --- a/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.hxx +++ b/Components/Metrics/SumOfPairwiseCorrelationsMetric/itkSumOfPairwiseCorrelationCoefficientsMetric.hxx @@ -481,7 +481,7 @@ SumOfPairwiseCorrelationCoefficientsMetric::GetValueA measure = RealType(1.0 - (K.fro_norm() / RealType(G))); /** Subtract mean from derivative elements. */ - if (m_SubtractMean) + if (m_UseZeroAverageDisplacementConstraint) { if (!m_TransformIsStackTransform) { diff --git a/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.h b/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.h index 472c67f8d..30765d291 100644 --- a/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.h +++ b/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.h @@ -55,9 +55,11 @@ namespace elastix * be set with parameter NumSamplesLastDimension. \n * \parameter NumSamplesLastDimension: the number of random samples to take in the time * time direction of the data when SampleLastDimensionRandomly is set to true. - * \parameter SubtractMean: subtract the over time computed mean parameter value from - * each parameter. This should be used when registration is performed directly on the moving - * image, without using a fixed image. Possible values are "true" or "false". + * \parameter UseZeroAverageDisplacementConstraint: uses the zero average displacement constraint, as described in + * Nonrigid registration of dynamic medical imaging data using nD+t B-splines and a groupwise optimization + * approach, Metz et al., Medical Image Analysis, 2011. Subtract the over time computed mean parameter value + * from each parameter. This should be used when registration is performed directly on the moving image, without + * using a fixed image. Possible values are "true" or "false". Default is "true". * * \ingroup RegistrationMetrics * \ingroup Metrics diff --git a/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.hxx b/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.hxx index e5da10d0a..e0f3fdc15 100644 --- a/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.hxx +++ b/Components/Metrics/VarianceOverLastDimension/elxVarianceOverLastDimensionMetric.hxx @@ -36,6 +36,17 @@ VarianceOverLastDimensionMetric::Initialize() itk::TimeProbe timer; timer.Start(); this->Superclass1::Initialize(); + + const Configuration & configuration = itk::Deref(Superclass2::GetConfiguration()); + + if (configuration.HasParameter("SubtractMean")) + { + log::warn(std::string("WARNING: From elastix version 5.2, the ") + elxGetClassNameStatic() + + " parameter `SubtractMean` (default \"false\") is " + "replaced with `UseZeroAverageDisplacementConstraint` " + "(default \"true\")."); + } + timer.Stop(); log::info(std::ostringstream{} << "Initialization of VarianceOverLastDimensionMetric metric took: " << static_cast(timer.GetMean() * 1000) << " ms."); @@ -100,9 +111,12 @@ VarianceOverLastDimensionMetric::BeforeEachResolution() this->SetSampleLastDimensionRandomly(useRandomSampling); /** Get and set if we want to subtract the mean from the derivative. */ - bool subtractMean = false; - configuration.ReadParameter(subtractMean, "SubtractMean", componentLabel, 0, 0); - this->SetSubtractMean(subtractMean); + bool useZeroAverageDisplacementConstraint = true; + // The parameter name "SubtractMean" is obsolete, so just use it as initial value, for backward compatibility. + configuration.ReadParameter(useZeroAverageDisplacementConstraint, "SubtractMean", componentLabel, 0, 0); + configuration.ReadParameter( + useZeroAverageDisplacementConstraint, "UseZeroAverageDisplacementConstraint", componentLabel, 0, 0); + this->SetUseZeroAverageDisplacementConstraint(useZeroAverageDisplacementConstraint); /** Get and set the number of random samples for the last dimension. */ int numSamplesLastDimension = 10; diff --git a/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.h b/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.h index 5858d5ed4..6227da7bd 100644 --- a/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.h +++ b/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.h @@ -75,7 +75,7 @@ class ITK_TEMPLATE_EXPORT VarianceOverLastDimensionImageMetric itkSetMacro(NumSamplesLastDimension, unsigned int); itkSetMacro(NumAdditionalSamplesFixed, unsigned int); itkSetMacro(ReducedDimensionIndex, unsigned int); - itkSetMacro(SubtractMean, bool); + itkSetMacro(UseZeroAverageDisplacementConstraint, bool); itkSetMacro(GridSize, FixedImageSizeType); itkSetMacro(TransformIsStackTransform, bool); @@ -189,7 +189,7 @@ class ITK_TEMPLATE_EXPORT VarianceOverLastDimensionImageMetric unsigned int m_ReducedDimensionIndex{}; /** Bool to determine if we want to subtract the mean derivate from the derivative elements. */ - bool m_SubtractMean{ false }; + bool m_UseZeroAverageDisplacementConstraint{ true }; /** Initial variance in last dimension, used as normalization factor. */ float m_InitialVariance{}; diff --git a/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.hxx b/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.hxx index a70ca3b65..9c019fda6 100644 --- a/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.hxx +++ b/Components/Metrics/VarianceOverLastDimension/itkVarianceOverLastDimensionImageMetric.hxx @@ -490,7 +490,7 @@ VarianceOverLastDimensionImageMetric::GetValueAndDeri derivative /= static_cast(Superclass::m_NumberOfPixelsCounted * m_InitialVariance); /** Subtract mean from derivative elements. */ - if (m_SubtractMean) + if (m_UseZeroAverageDisplacementConstraint) { if (!m_TransformIsStackTransform) {