From 4e063955047ed54273a15c791d8f7af337d065d5 Mon Sep 17 00:00:00 2001 From: neuronflow Date: Sun, 31 Mar 2024 12:06:59 +0200 Subject: [PATCH 1/8] activate tests Signed-off-by: neuronflow --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 98dd597..a22fe94 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,6 +34,6 @@ jobs: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - # - name: Test with pytest - # run: | - # pytest + - name: Test with pytest + run: | + pytest From ff0165b57adef315c166d7c7f9c422c94345b842 Mon Sep 17 00:00:00 2001 From: sarthakpati Date: Sun, 31 Mar 2024 12:25:29 -0400 Subject: [PATCH 2/8] added a whole bunch of defaults in case the config is not passed through correctly --- ereg/registration.py | 369 ++++++++++++++++++++++++------------------- 1 file changed, 209 insertions(+), 160 deletions(-) diff --git a/ereg/registration.py b/ereg/registration.py index 5c27ba1..6e3e9e5 100644 --- a/ereg/registration.py +++ b/ereg/registration.py @@ -389,7 +389,9 @@ def _register_image_and_get_transform( self.logger.info("Initializing registration.") R = sitk.ImageRegistrationMethod() - metric = self.parameters["metric"].lower() + metric = ( + self.parameters["metric_parameters"].get("type", "mean_squares").lower() + ) if ( (metric == "mattesmutualinformation") or (metric == "mattes") @@ -397,9 +399,9 @@ def _register_image_and_get_transform( or ("mattes" in metric) ): R.SetMetricAsMattesMutualInformation( - numberOfHistogramBins=self.parameters["metric_parameters"][ - "histogram_bins" - ] + numberOfHistogramBins=self.parameters["metric_parameters"].get( + "histogram_bins", 50 + ), ) elif ( (metric == "antsneighborhoodcorrelation") @@ -407,15 +409,15 @@ def _register_image_and_get_transform( or ("ants" in metric) ): R.SetMetricAsANTSNeighborhoodCorrelation( - radius=self.parameters["metric_parameters"]["radius"] + radius=self.parameters["metric_parameters"].get("radius", 5) ) elif metric == "correlation": R.SetMetricAsCorrelation() elif metric == "demons": R.SetMetricAsDemons( - intensityDifferenceThreshold=self.parameters["metric_parameters"][ - "intensityDifferenceThreshold" - ] + intensityDifferenceThreshold=self.parameters["metric_parameters"].get( + "intensityDifferenceThreshold", 0.001 + ), ) elif ( (metric == "joint_histogram_mutual_information") @@ -423,12 +425,12 @@ def _register_image_and_get_transform( or ("joint" in metric) ): R.SetMetricAsJointHistogramMutualInformation( - numberOfHistogramBins=self.parameters["metric_parameters"][ - "histogram_bins" - ], - varianceForJointPDFSmoothing=self.parameters["metric_parameters"][ - "varianceForJointPDFSmoothing" - ], + numberOfHistogramBins=self.parameters["metric_parameters"].get( + "histogram_bins", 50 + ), + varianceForJointPDFSmoothing=self.parameters["metric_parameters"].get( + "varianceForJointPDFSmoothing", 1.5 + ), ) else: R.SetMetricAsMeanSquares() @@ -439,197 +441,243 @@ def _register_image_and_get_transform( "none": R.NONE, } R.SetMetricSamplingStrategy( - sampling_strategy_parsed[self.parameters["sampling_strategy"]] + sampling_strategy_parsed[ + self.parameters.get("sampling_strategy", "random").lower() + ] ) R.SetMetricSamplingPercentagePerLevel(self.parameters["sampling_percentage"]) - if self.parameters["optimizer"] == "regular_step_gradient_descent": + self.parameters["optimizer_parameters"] = self.parameters.get( + "optimizer_parameters", {} + ) + if ( + self.parameters["optimizer_parameters"].get("type").lower() + == "regular_step_gradient_descent" + ): R.SetOptimizerAsRegularStepGradientDescent( - minStep=self.parameters["optimizer_parameters"]["min_step"], - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - learningRate=self.parameters["optimizer_parameters"]["learningrate"], - # gradientMagnitudeTolerance=grad_tolerance, - relaxationFactor=self.parameters["optimizer_parameters"]["relaxation"], - gradientMagnitudeTolerance=self.parameters["optimizer_parameters"][ - "tolerance" - ], + minStep=self.parameters["optimizer_parameters"].get("min_step", 1e-6), + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + learningRate=self.parameters["optimizer_parameters"].get( + "learningrate", 2.0 + ), + relaxationFactor=self.parameters["optimizer_parameters"].get( + "relaxation", 0.5 + ), + gradientMagnitudeTolerance=self.parameters["optimizer_parameters"].get( + "tolerance", 1e-4 + ), estimateLearningRate=R.EachIteration, - maximumStepSizeInPhysicalUnits=self.parameters["optimizer_parameters"][ - "max_step" - ] + maximumStepSizeInPhysicalUnits=self.parameters[ + "optimizer_parameters" + ].get("max_step", 1.0) * physical_units, ) - elif self.parameters["optimizer"] == "gradient_descent": + elif ( + self.parameters["optimizer_parameters"].get("type").lower() + == "gradient_descent" + ): R.SetOptimizerAsGradientDescent( - learningRate=self.parameters["optimizer_parameters"]["learningrate"], - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - convergenceMinimumValue=self.parameters["optimizer_parameters"][ - "convergence_minimum" - ], - convergenceWindowSize=self.parameters["optimizer_parameters"][ - "convergence_window_size" - ], + learningRate=self.parameters["optimizer_parameters"].get( + "learningrate", 1.0 + ), + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + convergenceMinimumValue=self.parameters["optimizer_parameters"].get( + "convergence_minimum", 1e-6 + ), + convergenceWindowSize=self.parameters["optimizer_parameters"].get( + "convergence_window_size", 10 + ), estimateLearningRate=R.EachIteration, - maximumStepSizeInPhysicalUnits=self.parameters["optimizer_parameters"][ - "max_step" - ] + maximumStepSizeInPhysicalUnits=self.parameters[ + "optimizer_parameters" + ].get("max_step", 1.0) * physical_units, ) - elif self.parameters["optimizer"] == "gradient_descent_line_search": + elif ( + self.parameters["optimizer_parameters"].get("type").lower() + == "gradient_descent_line_search" + ): R.SetOptimizerAsGradientDescentLineSearch( - learningRate=self.parameters["optimizer_parameters"]["learningrate"], - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - convergenceMinimumValue=self.parameters["optimizer_parameters"][ - "convergence_minimum" - ], - convergenceWindowSize=self.parameters["optimizer_parameters"][ - "convergence_window_size" - ], - lineSearchLowerLimit=self.parameters["optimizer_parameters"][ - "line_search_lower_limit" - ], - lineSearchUpperLimit=self.parameters["optimizer_parameters"][ - "line_search_upper_limit" - ], - lineSearchEpsilon=self.parameters["optimizer_parameters"][ - "line_search_epsilon" - ], - lineSearchMaximumIterations=self.parameters["optimizer_parameters"][ - "line_search_maximum_iterations" - ], + learningRate=self.parameters["optimizer_parameters"].get( + "learningrate", 1.0 + ), + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + convergenceMinimumValue=self.parameters["optimizer_parameters"].get( + "convergence_minimum", 1e-6 + ), + convergenceWindowSize=self.parameters["optimizer_parameters"].get( + "convergence_window_size", 10 + ), + lineSearchLowerLimit=self.parameters["optimizer_parameters"].get( + "line_search_lower_limit", 0.0 + ), + lineSearchUpperLimit=self.parameters["optimizer_parameters"].get( + "line_search_upper_limit", 1.0 + ), + lineSearchEpsilon=self.parameters["optimizer_parameters"].get( + "line_search_epsilon", 0.01 + ), + lineSearchMaximumIterations=self.parameters["optimizer_parameters"].get( + "line_search_maximum_iterations", 20 + ), estimateLearningRate=R.EachIteration, - maximumStepSizeInPhysicalUnits=self.parameters["optimizer_parameters"][ - "max_step" - ] + maximumStepSizeInPhysicalUnits=self.parameters[ + "optimizer_parameters" + ].get("max_step", 1.0) * physical_units, ) elif ( - self.parameters["optimizer"] + self.parameters["optimizer_parameters"].get("type").lower() == "Conjugate_step_gradient_descent_line_search" ): R.SetOptimizerAsConjugateGradientLineSearch( - learningRate=self.parameters["optimizer_parameters"]["learningrate"], - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - convergenceMinimumValue=self.parameters["optimizer_parameters"][ - "convergence_minimum" - ], - convergenceWindowSize=self.parameters["optimizer_parameters"][ - "convergence_window_size" - ], - lineSearchLowerLimit=self.parameters["optimizer_parameters"][ - "line_search_lower_limit" - ], - lineSearchUpperLimit=self.parameters["optimizer_parameters"][ - "line_search_upper_limit" - ], - lineSearchEpsilon=self.parameters["optimizer_parameters"][ - "line_search_epsilon" - ], - lineSearchMaximumIterations=self.parameters["optimizer_parameters"][ - "line_search_maximum_iterations" - ], + learningRate=self.parameters["optimizer_parameters"].get( + "learningrate", 1.0 + ), + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + convergenceMinimumValue=self.parameters["optimizer_parameters"].get( + "convergence_minimum", 1e-6 + ), + convergenceWindowSize=self.parameters["optimizer_parameters"].get( + "convergence_window_size", 10 + ), + lineSearchLowerLimit=self.parameters["optimizer_parameters"].get( + "line_search_lower_limit", 0.0 + ), + lineSearchUpperLimit=self.parameters["optimizer_parameters"].get( + "line_search_upper_limit", 1.0 + ), + lineSearchEpsilon=self.parameters["optimizer_parameters"].get( + "line_search_epsilon", 0.01 + ), + lineSearchMaximumIterations=self.parameters["optimizer_parameters"].get( + "line_search_maximum_iterations", 20 + ), estimateLearningRate=R.EachIteration, - maximumStepSizeInPhysicalUnits=self.parameters["optimizer_parameters"][ - "max_step" - ] + maximumStepSizeInPhysicalUnits=self.parameters[ + "optimizer_parameters" + ].get("max_step", 1.0) * physical_units, ) - elif self.parameters["optimizer"] == "exhaustive": + elif ( + self.parameters["optimizer_parameters"].get("type").lower() == "exhaustive" + ): R.SetOptimizerAsExhaustive( - numberOfSteps=self.parameters["optimizer_parameters"]["iterations"], - stepLength=self.parameters["optimizer_parameters"]["step_length"], + numberOfSteps=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + stepLength=self.parameters["optimizer_parameters"].get( + "step_length", 0.1 + ), ) - elif self.parameters["optimizer"] == "amoeba": + elif self.parameters["optimizer_parameters"].get("type").lower() == "amoeba": R.SetOptimizerAsAmoeba( numberOfIterations=self.parameters["optimizer_parameters"][ "iterations" ], simplexDelta=self.parameters["optimizer_parameters"]["simplex_delta"], ) - elif self.parameters["optimizer"] == "lbfgsb": + elif self.parameters["optimizer_parameters"].get("type").lower() == "lbfgsb": R.SetOptimizerAsLBFGSB( - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - maximumNumberOfCorrections=self.parameters["optimizer_parameters"][ - "maximum_number_of_corrections" - ], + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + maximumNumberOfCorrections=self.parameters["optimizer_parameters"].get( + "maximum_number_of_corrections", 5 + ), maximumNumberOfFunctionEvaluations=self.parameters[ "optimizer_parameters" - ]["maximum_number_of_function_evaluations"], - costFunctionConvergenceFactor=self.parameters["optimizer_parameters"][ - "cost_function_convergence_factor" - ], + ].get("maximum_number_of_function_evaluations", 2000), + costFunctionConvergenceFactor=self.parameters[ + "optimizer_parameters" + ].get("cost_function_convergence_factor", 1e7), ) - elif self.parameters["optimizer"] == "lbfgs2": + elif self.parameters["optimizer_parameters"].get("type").lower() == "lbfgs2": R.SetOptimizerAsLBFGS2( - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - solutionAccuracy=self.parameters["optimizer_parameters"][ - "solution_accuracy" - ], - hessianApproximateAccuracy=self.parameters["optimizer_parameters"][ - "hessian_approximate_accuracy" - ], - deltaConvergenceDistance=self.parameters["optimizer_parameters"][ - "delta_convergence_distance" - ], - deltaConvergenceTolerance=self.parameters["optimizer_parameters"][ - "delta_convergence_tolerance" - ], - lineSearchMaximumEvaluations=self.parameters["optimizer_parameters"][ - "line_search_maximum_evaluations" - ], - lineSearchMinimumStep=self.parameters["optimizer_parameters"][ - "line_search_minimum_step" - ], - lineSearchMaximumStep=self.parameters["optimizer_parameters"][ - "line_search_maximum_step" - ], - lineSearchAccuracy=self.parameters["optimizer_parameters"][ - "line_search_accuracy" - ], + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + solutionAccuracy=self.parameters["optimizer_parameters"].get( + "solution_accuracy", 1e-7 + ), + hessianApproximateAccuracy=self.parameters["optimizer_parameters"].get( + "hessian_approximate_accuracy", 1e-7 + ), + deltaConvergenceDistance=self.parameters["optimizer_parameters"].get( + "delta_convergence_distance", 1e-5 + ), + deltaConvergenceTolerance=self.parameters["optimizer_parameters"].get( + "delta_convergence_tolerance", 1e-4 + ), + lineSearchMaximumEvaluations=self.parameters[ + "optimizer_parameters" + ].get("line_search_maximum_evaluations", 20), + lineSearchMinimumStep=self.parameters["optimizer_parameters"].get( + "line_search_minimum_step", 1e-20 + ), + lineSearchMaximumStep=self.parameters["optimizer_parameters"].get( + "line_search_maximum_step", 1e20 + ), + lineSearchAccuracy=self.parameters["optimizer_parameters"].get( + "line_search_accuracy", 0.9 + ), ) - elif self.parameters["optimizer"] == "one_plus_one_evolutionary": + elif ( + self.parameters["optimizer_parameters"].get("type").lower() + == "one_plus_one_evolutionary" + ): R.SetOptimizerAsOnePlusOneEvolutionary( - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - epsilon=self.parameters["optimizer_parameters"]["epsilon"], - initialRadius=self.parameters["optimizer_parameters"]["initial_radius"], - growthFactor=self.parameters["optimizer_parameters"]["growth_factor"], - shrinkFactor=self.parameters["optimizer_parameters"]["shrink_factor"], + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + epsilon=self.parameters["optimizer_parameters"].get("epsilon", 1e-6), + initialRadius=self.parameters["optimizer_parameters"].get( + "initial_radius", 1.0 + ), + growthFactor=self.parameters["optimizer_parameters"].get( + "growth_factor", 2.0 + ), + shrinkFactor=self.parameters["optimizer_parameters"].get( + "shrink_factor", 0.7 + ), ) - elif self.parameters["optimizer"] == "powell": + elif self.parameters["optimizer_parameters"].get("type").lower() == "powell": R.SetOptimizerAsPowell( - numberOfIterations=self.parameters["optimizer_parameters"][ - "iterations" - ], - maximumLineIterations=self.parameters["optimizer_parameters"][ - "maximum_line_iterations" - ], - stepLength=self.parameters["optimizer_parameters"]["step_length"], - stepTolerance=self.parameters["optimizer_parameters"]["step_tolerance"], - valueTolerance=self.parameters["optimizer_parameters"][ - "value_tolerance" - ], + numberOfIterations=self.parameters["optimizer_parameters"].get( + "iterations", 200 + ), + maximumLineIterations=self.parameters["optimizer_parameters"].get( + "maximum_line_iterations", 20 + ), + stepLength=self.parameters["optimizer_parameters"].get( + "step_length", 1.0 + ), + stepTolerance=self.parameters["optimizer_parameters"].get( + "step_tolerance", 0.001 + ), + valueTolerance=self.parameters["optimizer_parameters"].get( + "value_tolerance", 0.001 + ), ) # R.SetOptimizerScalesFromJacobian() R.SetOptimizerScalesFromPhysicalShift() - R.SetShrinkFactorsPerLevel(self.parameters["shrink_factors"]) - R.SetSmoothingSigmasPerLevel(self.parameters["smoothing_sigmas"]) + R.SetShrinkFactorsPerLevel(self.parameters.get("shrink_factors", [8, 4, 2])) + R.SetSmoothingSigmasPerLevel(self.parameters.get("smoothing_sigmas", [3, 2, 1])) R.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn() + + assert ( + self.parameters.get("transform", "") in self.available_transforms + ), f"`transform`needs to be set to one of the following: {self.available_transforms}" transform_function = self._get_transform_wrapper( self.parameters["transform"], dimension ) @@ -658,6 +706,7 @@ def _register_image_and_get_transform( # self.initialization_type.get(initialization.lower(), "geometry"), # ) + self.parameters["initialization"] = self.parameters.get("initialization", None) if self.parameters["initialization"] is not None: temp_moving = moving_image temp_initialization = self.parameters["initialization"].upper() From 65414d2d6a71aea0d37cf64b1267d65d243b9f81 Mon Sep 17 00:00:00 2001 From: sarthakpati Date: Sun, 31 Mar 2024 12:27:23 -0400 Subject: [PATCH 3/8] added more defaults --- ereg/registration.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ereg/registration.py b/ereg/registration.py index 6e3e9e5..92afa2e 100644 --- a/ereg/registration.py +++ b/ereg/registration.py @@ -179,6 +179,9 @@ def register( sitk.WriteTransform(self.transform, transform_file) # apply composite transform if provided + self.parameters["composite_transform"] = self.parameters.get( + "composite_transform", None + ) if self.parameters["composite_transform"] is not None: self.logger.info("Applying composite transform.") transform_composite = sitk.ReadTransform( @@ -256,7 +259,8 @@ def resample_image( resampler = sitk.ResampleImageFilter() resampler.SetReferenceImage(target_image) interpolator_type = self.interpolator_type.get( - self.parameters["interpolator"] + self.parameters.get("interpolator", "linear").lower(), + sitk.sitkLinear, ) resampler.SetInterpolator(interpolator_type) resampler.SetDefaultPixelValue(0) @@ -389,6 +393,7 @@ def _register_image_and_get_transform( self.logger.info("Initializing registration.") R = sitk.ImageRegistrationMethod() + self.parameters["metric_parameters"] = self.parameters.get("metric_parameters", {}) metric = ( self.parameters["metric_parameters"].get("type", "mean_squares").lower() ) @@ -445,7 +450,7 @@ def _register_image_and_get_transform( self.parameters.get("sampling_strategy", "random").lower() ] ) - R.SetMetricSamplingPercentagePerLevel(self.parameters["sampling_percentage"]) + R.SetMetricSamplingPercentagePerLevel(self.parameters.get("sampling_percentage", 0.01))) self.parameters["optimizer_parameters"] = self.parameters.get( "optimizer_parameters", {} From 460a483f3d1e2a542cb56c17700e3590e6e94451 Mon Sep 17 00:00:00 2001 From: sarthakpati Date: Sun, 31 Mar 2024 12:33:57 -0400 Subject: [PATCH 4/8] syntax fix --- ereg/registration.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ereg/registration.py b/ereg/registration.py index 92afa2e..4850f9f 100644 --- a/ereg/registration.py +++ b/ereg/registration.py @@ -393,7 +393,9 @@ def _register_image_and_get_transform( self.logger.info("Initializing registration.") R = sitk.ImageRegistrationMethod() - self.parameters["metric_parameters"] = self.parameters.get("metric_parameters", {}) + self.parameters["metric_parameters"] = self.parameters.get( + "metric_parameters", {} + ) metric = ( self.parameters["metric_parameters"].get("type", "mean_squares").lower() ) @@ -450,7 +452,9 @@ def _register_image_and_get_transform( self.parameters.get("sampling_strategy", "random").lower() ] ) - R.SetMetricSamplingPercentagePerLevel(self.parameters.get("sampling_percentage", 0.01))) + R.SetMetricSamplingPercentagePerLevel( + self.parameters.get("sampling_percentage", 0.01) + ) self.parameters["optimizer_parameters"] = self.parameters.get( "optimizer_parameters", {} From 63d70c8c3937af24504f4b68b0246ba997030917 Mon Sep 17 00:00:00 2001 From: sarthakpati Date: Sun, 31 Mar 2024 13:52:00 -0400 Subject: [PATCH 5/8] fixed syntax --- ereg/registration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ereg/registration.py b/ereg/registration.py index 4850f9f..ac2cd21 100644 --- a/ereg/registration.py +++ b/ereg/registration.py @@ -452,7 +452,7 @@ def _register_image_and_get_transform( self.parameters.get("sampling_strategy", "random").lower() ] ) - R.SetMetricSamplingPercentagePerLevel( + R.SetMetricSamplingPercentage( self.parameters.get("sampling_percentage", 0.01) ) From 7d37b973cb45cc5be315b94b898915cfa85cfe88 Mon Sep 17 00:00:00 2001 From: sarthakpati Date: Sun, 31 Mar 2024 13:53:12 -0400 Subject: [PATCH 6/8] ensure sampling can be done for different levels --- ereg/registration.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ereg/registration.py b/ereg/registration.py index ac2cd21..2470b3e 100644 --- a/ereg/registration.py +++ b/ereg/registration.py @@ -452,9 +452,11 @@ def _register_image_and_get_transform( self.parameters.get("sampling_strategy", "random").lower() ] ) - R.SetMetricSamplingPercentage( - self.parameters.get("sampling_percentage", 0.01) - ) + sampling_rate = self.parameters.get("sampling_percentage", 0.01) + if isinstance(sampling_rate, float): + R.SetMetricSamplingPercentage(sampling_rate) + elif type(sampling_rate) in [np.ndarray, list]: + R.SetMetricSamplingPercentagePerLevel(sampling_rate) self.parameters["optimizer_parameters"] = self.parameters.get( "optimizer_parameters", {} From c05e9f15de5b20f031aa58f4af8b5160313765fb Mon Sep 17 00:00:00 2001 From: sarthakpati Date: Mon, 1 Apr 2024 08:05:21 -0400 Subject: [PATCH 7/8] renamed `R` --> `registration` --- ereg/registration.py | 82 ++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/ereg/registration.py b/ereg/registration.py index 2470b3e..10260d2 100644 --- a/ereg/registration.py +++ b/ereg/registration.py @@ -392,7 +392,7 @@ def _register_image_and_get_transform( physical_units *= target_image.GetSpacing()[dim] self.logger.info("Initializing registration.") - R = sitk.ImageRegistrationMethod() + registration = sitk.ImageRegistrationMethod() self.parameters["metric_parameters"] = self.parameters.get( "metric_parameters", {} ) @@ -405,7 +405,7 @@ def _register_image_and_get_transform( or (metric == "mmi") or ("mattes" in metric) ): - R.SetMetricAsMattesMutualInformation( + registration.SetMetricAsMattesMutualInformation( numberOfHistogramBins=self.parameters["metric_parameters"].get( "histogram_bins", 50 ), @@ -415,13 +415,13 @@ def _register_image_and_get_transform( or (metric == "ants") or ("ants" in metric) ): - R.SetMetricAsANTSNeighborhoodCorrelation( + registration.SetMetricAsANTSNeighborhoodCorrelation( radius=self.parameters["metric_parameters"].get("radius", 5) ) elif metric == "correlation": - R.SetMetricAsCorrelation() + registration.SetMetricAsCorrelation() elif metric == "demons": - R.SetMetricAsDemons( + registration.SetMetricAsDemons( intensityDifferenceThreshold=self.parameters["metric_parameters"].get( "intensityDifferenceThreshold", 0.001 ), @@ -431,7 +431,7 @@ def _register_image_and_get_transform( or (metric == "joint") or ("joint" in metric) ): - R.SetMetricAsJointHistogramMutualInformation( + registration.SetMetricAsJointHistogramMutualInformation( numberOfHistogramBins=self.parameters["metric_parameters"].get( "histogram_bins", 50 ), @@ -440,23 +440,23 @@ def _register_image_and_get_transform( ), ) else: - R.SetMetricAsMeanSquares() + registration.SetMetricAsMeanSquares() sampling_strategy_parsed = { - "random": R.RANDOM, - "regular": R.REGULAR, - "none": R.NONE, + "random": registration.RANDOM, + "regular": registration.REGULAR, + "none": registration.NONE, } - R.SetMetricSamplingStrategy( + registration.SetMetricSamplingStrategy( sampling_strategy_parsed[ self.parameters.get("sampling_strategy", "random").lower() ] ) sampling_rate = self.parameters.get("sampling_percentage", 0.01) if isinstance(sampling_rate, float): - R.SetMetricSamplingPercentage(sampling_rate) + registration.SetMetricSamplingPercentage(sampling_rate) elif type(sampling_rate) in [np.ndarray, list]: - R.SetMetricSamplingPercentagePerLevel(sampling_rate) + registration.SetMetricSamplingPercentagePerLevel(sampling_rate) self.parameters["optimizer_parameters"] = self.parameters.get( "optimizer_parameters", {} @@ -465,13 +465,13 @@ def _register_image_and_get_transform( self.parameters["optimizer_parameters"].get("type").lower() == "regular_step_gradient_descent" ): - R.SetOptimizerAsRegularStepGradientDescent( + registration.SetOptimizerAsRegularStepGradientDescent( minStep=self.parameters["optimizer_parameters"].get("min_step", 1e-6), numberOfIterations=self.parameters["optimizer_parameters"].get( "iterations", 200 ), learningRate=self.parameters["optimizer_parameters"].get( - "learningrate", 2.0 + "learningrate", 1.0 ), relaxationFactor=self.parameters["optimizer_parameters"].get( "relaxation", 0.5 @@ -479,7 +479,7 @@ def _register_image_and_get_transform( gradientMagnitudeTolerance=self.parameters["optimizer_parameters"].get( "tolerance", 1e-4 ), - estimateLearningRate=R.EachIteration, + estimateLearningRate=registration.EachIteration, maximumStepSizeInPhysicalUnits=self.parameters[ "optimizer_parameters" ].get("max_step", 1.0) @@ -489,7 +489,7 @@ def _register_image_and_get_transform( self.parameters["optimizer_parameters"].get("type").lower() == "gradient_descent" ): - R.SetOptimizerAsGradientDescent( + registration.SetOptimizerAsGradientDescent( learningRate=self.parameters["optimizer_parameters"].get( "learningrate", 1.0 ), @@ -502,7 +502,7 @@ def _register_image_and_get_transform( convergenceWindowSize=self.parameters["optimizer_parameters"].get( "convergence_window_size", 10 ), - estimateLearningRate=R.EachIteration, + estimateLearningRate=registration.EachIteration, maximumStepSizeInPhysicalUnits=self.parameters[ "optimizer_parameters" ].get("max_step", 1.0) @@ -512,7 +512,7 @@ def _register_image_and_get_transform( self.parameters["optimizer_parameters"].get("type").lower() == "gradient_descent_line_search" ): - R.SetOptimizerAsGradientDescentLineSearch( + registration.SetOptimizerAsGradientDescentLineSearch( learningRate=self.parameters["optimizer_parameters"].get( "learningrate", 1.0 ), @@ -537,7 +537,7 @@ def _register_image_and_get_transform( lineSearchMaximumIterations=self.parameters["optimizer_parameters"].get( "line_search_maximum_iterations", 20 ), - estimateLearningRate=R.EachIteration, + estimateLearningRate=registration.EachIteration, maximumStepSizeInPhysicalUnits=self.parameters[ "optimizer_parameters" ].get("max_step", 1.0) @@ -547,7 +547,7 @@ def _register_image_and_get_transform( self.parameters["optimizer_parameters"].get("type").lower() == "Conjugate_step_gradient_descent_line_search" ): - R.SetOptimizerAsConjugateGradientLineSearch( + registration.SetOptimizerAsConjugateGradientLineSearch( learningRate=self.parameters["optimizer_parameters"].get( "learningrate", 1.0 ), @@ -572,7 +572,7 @@ def _register_image_and_get_transform( lineSearchMaximumIterations=self.parameters["optimizer_parameters"].get( "line_search_maximum_iterations", 20 ), - estimateLearningRate=R.EachIteration, + estimateLearningRate=registration.EachIteration, maximumStepSizeInPhysicalUnits=self.parameters[ "optimizer_parameters" ].get("max_step", 1.0) @@ -581,7 +581,7 @@ def _register_image_and_get_transform( elif ( self.parameters["optimizer_parameters"].get("type").lower() == "exhaustive" ): - R.SetOptimizerAsExhaustive( + registration.SetOptimizerAsExhaustive( numberOfSteps=self.parameters["optimizer_parameters"].get( "iterations", 200 ), @@ -590,14 +590,14 @@ def _register_image_and_get_transform( ), ) elif self.parameters["optimizer_parameters"].get("type").lower() == "amoeba": - R.SetOptimizerAsAmoeba( + registration.SetOptimizerAsAmoeba( numberOfIterations=self.parameters["optimizer_parameters"][ "iterations" ], simplexDelta=self.parameters["optimizer_parameters"]["simplex_delta"], ) elif self.parameters["optimizer_parameters"].get("type").lower() == "lbfgsb": - R.SetOptimizerAsLBFGSB( + registration.SetOptimizerAsLBFGSB( numberOfIterations=self.parameters["optimizer_parameters"].get( "iterations", 200 ), @@ -612,7 +612,7 @@ def _register_image_and_get_transform( ].get("cost_function_convergence_factor", 1e7), ) elif self.parameters["optimizer_parameters"].get("type").lower() == "lbfgs2": - R.SetOptimizerAsLBFGS2( + registration.SetOptimizerAsLBFGS2( numberOfIterations=self.parameters["optimizer_parameters"].get( "iterations", 200 ), @@ -645,7 +645,7 @@ def _register_image_and_get_transform( self.parameters["optimizer_parameters"].get("type").lower() == "one_plus_one_evolutionary" ): - R.SetOptimizerAsOnePlusOneEvolutionary( + registration.SetOptimizerAsOnePlusOneEvolutionary( numberOfIterations=self.parameters["optimizer_parameters"].get( "iterations", 200 ), @@ -661,7 +661,7 @@ def _register_image_and_get_transform( ), ) elif self.parameters["optimizer_parameters"].get("type").lower() == "powell": - R.SetOptimizerAsPowell( + registration.SetOptimizerAsPowell( numberOfIterations=self.parameters["optimizer_parameters"].get( "iterations", 200 ), @@ -679,12 +679,12 @@ def _register_image_and_get_transform( ), ) - # R.SetOptimizerScalesFromJacobian() - R.SetOptimizerScalesFromPhysicalShift() + # registration.SetOptimizerScalesFromJacobian() + registration.SetOptimizerScalesFromPhysicalShift() - R.SetShrinkFactorsPerLevel(self.parameters.get("shrink_factors", [8, 4, 2])) - R.SetSmoothingSigmasPerLevel(self.parameters.get("smoothing_sigmas", [3, 2, 1])) - R.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn() + registration.SetShrinkFactorsPerLevel(self.parameters.get("shrink_factors", [8, 4, 2])) + registration.SetSmoothingSigmasPerLevel(self.parameters.get("smoothing_sigmas", [3, 2, 1])) + registration.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn() assert ( self.parameters.get("transform", "") in self.available_transforms @@ -738,17 +738,17 @@ def _register_image_and_get_transform( transform_function, eval("sitk.CenteredTransformInitializerFilter.%s" % (initializer_type)), ) - R.SetInitialTransform(final_transform, inPlace=False) + registration.SetInitialTransform(final_transform, inPlace=False) ## set the interpolator - all options: https://simpleitk.org/doxygen/latest/html/namespaceitk_1_1simple.html#a7cb1ef8bd02c669c02ea2f9f5aa374e5 # this should be linear to optimize results and computational efficacy - R.SetInterpolator(sitk.sitkLinear) + registration.SetInterpolator(sitk.sitkLinear) - # R.AddCommand(sitk.sitkIterationEvent, lambda: R) + # registration.AddCommand(sitk.sitkIterationEvent, lambda: R) self.logger.info("Starting registration.") output_transform = None for _ in range(self.parameters["attempts"]): try: - output_transform = R.Execute(target_image, moving_image) + output_transform = registration.Execute(target_image, moving_image) break except RuntimeError as e: self.logger.warning( @@ -779,14 +779,14 @@ def _register_image_and_get_transform( tmp.SetCenter(registration_transform_sitk.GetCenter()) registration_transform_sitk = tmp ## additional information - # print("Metric: ", R.MetricEvaluate(target_image, moving_image), flush=True) + # print("Metric: ", registration.MetricEvaluate(target_image, moving_image), flush=True) # print( # "Optimizer stop condition: ", - # R.GetOptimizerStopConditionDescription(), + # registration.GetOptimizerStopConditionDescription(), # flush=True, # ) - # print("Number of iterations: ", R.GetOptimizerIteration(), flush=True) - # print("Final metric value: ", R.GetMetricValue(), flush=True) + # print("Number of iterations: ", registration.GetOptimizerIteration(), flush=True) + # print("Final metric value: ", registration.GetMetricValue(), flush=True) # if rigid_registration: # if target_image.GetDimension() == 2: From 8d53051b9df1d1a6ee714c9b2f61da20682725f4 Mon Sep 17 00:00:00 2001 From: sarthakpati Date: Mon, 1 Apr 2024 08:44:38 -0400 Subject: [PATCH 8/8] appropriate defaults (`float` and `int` instead of `str`), added final logging info, --- ereg/registration.py | 65 +++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/ereg/registration.py b/ereg/registration.py index 10260d2..1913cc1 100644 --- a/ereg/registration.py +++ b/ereg/registration.py @@ -182,7 +182,7 @@ def register( self.parameters["composite_transform"] = self.parameters.get( "composite_transform", None ) - if self.parameters["composite_transform"] is not None: + if self.parameters.get("composite_transform"): self.logger.info("Applying composite transform.") transform_composite = sitk.ReadTransform( self.parameters["composite_transform"] @@ -191,7 +191,6 @@ def register( transform_composite, self.transform ) - if self.parameters["composite_transform"]: self.logger.info("Applying previous transforms.") current_transform = None for previous_transform in self.parameters["previous_transforms"]: @@ -458,9 +457,23 @@ def _register_image_and_get_transform( elif type(sampling_rate) in [np.ndarray, list]: registration.SetMetricSamplingPercentagePerLevel(sampling_rate) + # initialize some defaults self.parameters["optimizer_parameters"] = self.parameters.get( "optimizer_parameters", {} ) + self.parameters["optimizer_parameters"]["type"] = self.parameters[ + "optimizer_parameters" + ].get("type", "regular_step_gradient_descent") + # set the optimizer parameters as either floats or integers + for key in self.parameters["optimizer_parameters"]: + if key not in ["type"]: + self.parameters["optimizer_parameters"][key] = float( + self.parameters["optimizer_parameters"][key] + ) + if key == "iterations": + self.parameters["optimizer_parameters"][key] = int( + self.parameters["optimizer_parameters"][key] + ) if ( self.parameters["optimizer_parameters"].get("type").lower() == "regular_step_gradient_descent" @@ -682,8 +695,12 @@ def _register_image_and_get_transform( # registration.SetOptimizerScalesFromJacobian() registration.SetOptimizerScalesFromPhysicalShift() - registration.SetShrinkFactorsPerLevel(self.parameters.get("shrink_factors", [8, 4, 2])) - registration.SetSmoothingSigmasPerLevel(self.parameters.get("smoothing_sigmas", [3, 2, 1])) + registration.SetShrinkFactorsPerLevel( + self.parameters.get("shrink_factors", [8, 4, 2]) + ) + registration.SetSmoothingSigmasPerLevel( + self.parameters.get("smoothing_sigmas", [3, 2, 1]) + ) registration.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn() assert ( @@ -756,11 +773,16 @@ def _register_image_and_get_transform( ) continue - if output_transform is None: - raise RuntimeError("Registration failed.") + assert output_transform is not None, "Registration failed." + + self.logger.info( + f"Final Optimizer Parameters:: convergence={registration.GetOptimizerConvergenceValue()}, iterations={registration.GetOptimizerIteration()}, metric={registration.GetMetricValue()}, stop condition={registration.GetOptimizerStopConditionDescription()}" + ) registration_transform_sitk = output_transform # if user is requesting a rigid registration, convert the transform to a rigid transform + if isinstance(output_transform, sitk.CompositeTransform): + registration_transform_sitk = output_transform.GetNthTransform(0) if self.parameters["transform"] in ["euler", "versorrigid"]: try: # Euler Transform used: @@ -778,35 +800,4 @@ def _register_image_and_get_transform( tmp.SetTranslation(registration_transform_sitk.GetTranslation()) tmp.SetCenter(registration_transform_sitk.GetCenter()) registration_transform_sitk = tmp - ## additional information - # print("Metric: ", registration.MetricEvaluate(target_image, moving_image), flush=True) - # print( - # "Optimizer stop condition: ", - # registration.GetOptimizerStopConditionDescription(), - # flush=True, - # ) - # print("Number of iterations: ", registration.GetOptimizerIteration(), flush=True) - # print("Final metric value: ", registration.GetMetricValue(), flush=True) - - # if rigid_registration: - # if target_image.GetDimension() == 2: - # output_transform = eval( - # "sitk.Euler%dDTransform(output_transform)" - # % (target_image.GetDimension()) - # ) - # elif target_image.GetDimension() == 3: - # output_transform = eval( - # "sitk.Euler%dDTransform(output_transform)" - # % (target_image.GetDimension()) - # ) - # # VersorRigid used: Transform from VersorRigid to Euler - # output_transform = eval( - # "sitk.VersorRigid%dDTransform(output_transform)" - # % (target_image.GetDimension()) - # ) - # tmp = eval("sitk.Euler%dDTransform()" % (target_image.GetDimension())) - # tmp.SetMatrix(output_transform.GetMatrix()) - # tmp.SetTranslation(output_transform.GetTranslation()) - # tmp.SetCenter(output_transform.GetCenter()) - # output_transform = tmp return registration_transform_sitk