From b922c8f036f95954e28667a066645ff76dfecca9 Mon Sep 17 00:00:00 2001 From: Andreas Pedersen Date: Mon, 2 Sep 2024 12:43:21 +0200 Subject: [PATCH 1/2] added support for scipy least square --- src/easyscience/fitting/available_minimizers.py | 3 +++ src/easyscience/fitting/minimizers/minimizer_lmfit.py | 4 ++-- tests/unit_tests/Fitting/minimizers/test_factory.py | 3 ++- .../unit_tests/Fitting/minimizers/test_minimizer_lmfit.py | 8 ++++---- tests/unit_tests/Fitting/test_fitter.py | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/easyscience/fitting/available_minimizers.py b/src/easyscience/fitting/available_minimizers.py index c432de85..13216415 100644 --- a/src/easyscience/fitting/available_minimizers.py +++ b/src/easyscience/fitting/available_minimizers.py @@ -39,6 +39,7 @@ class AvailableMinimizers(Enum): LMFit_powell = auto() LMFit_cobyla = auto() LMFit_differential_evolution = auto() + LMFit_scipy_least_squares = auto() if bumps_engine_available: Bumps = auto() @@ -63,6 +64,8 @@ def from_string_to_enum(minimizer_name: str) -> AvailableMinimizers: minmizer_enum = AvailableMinimizers.LMFit_cobyla elif minimizer_name == 'LMFit_differential_evolution': minmizer_enum = AvailableMinimizers.LMFit_differential_evolution + elif minimizer_name == 'LMFit_scipy_least_squares': + minmizer_enum = AvailableMinimizers.LMFit_scipy_least_squares elif minimizer_name == 'Bumps': minmizer_enum = AvailableMinimizers.Bumps diff --git a/src/easyscience/fitting/minimizers/minimizer_lmfit.py b/src/easyscience/fitting/minimizers/minimizer_lmfit.py index 514a9c23..60743894 100644 --- a/src/easyscience/fitting/minimizers/minimizer_lmfit.py +++ b/src/easyscience/fitting/minimizers/minimizer_lmfit.py @@ -52,7 +52,7 @@ def __init__( @staticmethod def all_methods() -> List[str]: return [ - 'least_squares', + 'least_squares (scipy)', 'leastsq', 'differential_evolution', 'basinhopping', @@ -69,7 +69,7 @@ def all_methods() -> List[str]: @staticmethod def supported_methods() -> List[str]: return [ - 'least_squares', + 'least_squares (scipy)', 'leastsq', 'differential_evolution', 'powell', diff --git a/tests/unit_tests/Fitting/minimizers/test_factory.py b/tests/unit_tests/Fitting/minimizers/test_factory.py index 8a0095a3..6376c536 100644 --- a/tests/unit_tests/Fitting/minimizers/test_factory.py +++ b/tests/unit_tests/Fitting/minimizers/test_factory.py @@ -52,10 +52,11 @@ def test_available_minimizers(): assert AvailableMinimizers.LMFit_powell assert AvailableMinimizers.LMFit_cobyla assert AvailableMinimizers.LMFit_differential_evolution + assert AvailableMinimizers.LMFit_scipy_least_squares assert AvailableMinimizers.Bumps assert AvailableMinimizers.Bumps_simplex assert AvailableMinimizers.Bumps_newton assert AvailableMinimizers.Bumps_lm assert AvailableMinimizers.DFO assert AvailableMinimizers.DFO_leastsq - assert len(AvailableMinimizers) == 11 \ No newline at end of file + assert len(AvailableMinimizers) == 12 \ No newline at end of file diff --git a/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py b/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py index cf0dc6cc..7f3e225e 100644 --- a/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py +++ b/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py @@ -16,7 +16,7 @@ def minimizer(self) -> LMFit: minimizer = LMFit( obj='obj', fit_function='fit_function', - method='least_squares' + method='leastsq' ) return minimizer @@ -99,7 +99,7 @@ def test_fit(self, minimizer: LMFit) -> None: # Expect assert result == 'gen_fit_results' - mock_model.fit.assert_called_once_with(2.0, x=1.0, weights=0.7071067811865475, method='least_squares') + mock_model.fit.assert_called_once_with(2.0, x=1.0, weights=0.7071067811865475, method='leastsq') minimizer._make_model.assert_called_once_with() minimizer._set_parameter_fit_result.assert_called_once_with('fit', False) minimizer._gen_fit_results.assert_called_once_with('fit') @@ -116,7 +116,7 @@ def test_fit_model(self, minimizer: LMFit) -> None: minimizer.fit(x=1.0, y=2.0, model=mock_model) # Expect - mock_model.fit.assert_called_once_with(2.0, x=1.0, weights=0.7071067811865475, method='least_squares') + mock_model.fit.assert_called_once_with(2.0, x=1.0, weights=0.7071067811865475, method='leastsq') minimizer._make_model.assert_not_called() def test_fit_method(self, minimizer: LMFit) -> None: @@ -148,7 +148,7 @@ def test_fit_kwargs(self, minimizer: LMFit) -> None: minimizer.fit(x=1.0, y=2.0, minimizer_kwargs={'minimizer_key': 'minimizer_val'}, engine_kwargs={'engine_key': 'engine_val'}) # Expect - mock_model.fit.assert_called_once_with(2.0, x=1.0, weights=0.7071067811865475, method='least_squares', fit_kws={'minimizer_key': 'minimizer_val'}, engine_key='engine_val') + mock_model.fit.assert_called_once_with(2.0, x=1.0, weights=0.7071067811865475, method='leastsq', fit_kws={'minimizer_key': 'minimizer_val'}, engine_key='engine_val') def test_fit_exception(self, minimizer: LMFit) -> None: # When diff --git a/tests/unit_tests/Fitting/test_fitter.py b/tests/unit_tests/Fitting/test_fitter.py index 2095fb99..471cbb7a 100644 --- a/tests/unit_tests/Fitting/test_fitter.py +++ b/tests/unit_tests/Fitting/test_fitter.py @@ -166,7 +166,7 @@ def test_available_minimizers(self, fitter: Fitter): # Then Expect assert minimizers == [ - 'LMFit', 'LMFit_leastsq', 'LMFit_powell', 'LMFit_cobyla', 'LMFit_differential_evolution', + 'LMFit', 'LMFit_leastsq', 'LMFit_powell', 'LMFit_cobyla', 'LMFit_differential_evolution', 'LMFit_scipy_least_squares', 'Bumps', 'Bumps_simplex', 'Bumps_newton', 'Bumps_lm', 'DFO', 'DFO_leastsq' ] From b9e1f254693b4f97b7c7484d96972c3a2626d044 Mon Sep 17 00:00:00 2001 From: Andreas Pedersen Date: Mon, 2 Sep 2024 13:00:29 +0200 Subject: [PATCH 2/2] fix to tests --- src/easyscience/fitting/minimizers/factory.py | 2 ++ src/easyscience/fitting/minimizers/minimizer_lmfit.py | 4 ++-- tests/unit_tests/Fitting/minimizers/test_factory.py | 4 ++-- tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py | 1 - 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/easyscience/fitting/minimizers/factory.py b/src/easyscience/fitting/minimizers/factory.py index 026a6c9c..5c141edf 100644 --- a/src/easyscience/fitting/minimizers/factory.py +++ b/src/easyscience/fitting/minimizers/factory.py @@ -23,6 +23,8 @@ def factory(minimizer_enum: AvailableMinimizers, fit_object, fit_function: Calla minimizer = LMFit(obj=fit_object, fit_function=fit_function, method='cobyla') elif minimizer_enum == AvailableMinimizers.LMFit_differential_evolution: minimizer = LMFit(obj=fit_object, fit_function=fit_function, method='differential_evolution') + elif minimizer_enum == AvailableMinimizers.LMFit_scipy_least_squares: + minimizer = LMFit(obj=fit_object, fit_function=fit_function, method='least_squares') elif minimizer_enum == AvailableMinimizers.Bumps: minimizer = Bumps(obj=fit_object, fit_function=fit_function, method='amoeba') diff --git a/src/easyscience/fitting/minimizers/minimizer_lmfit.py b/src/easyscience/fitting/minimizers/minimizer_lmfit.py index 60743894..514a9c23 100644 --- a/src/easyscience/fitting/minimizers/minimizer_lmfit.py +++ b/src/easyscience/fitting/minimizers/minimizer_lmfit.py @@ -52,7 +52,7 @@ def __init__( @staticmethod def all_methods() -> List[str]: return [ - 'least_squares (scipy)', + 'least_squares', 'leastsq', 'differential_evolution', 'basinhopping', @@ -69,7 +69,7 @@ def all_methods() -> List[str]: @staticmethod def supported_methods() -> List[str]: return [ - 'least_squares (scipy)', + 'least_squares', 'leastsq', 'differential_evolution', 'powell', diff --git a/tests/unit_tests/Fitting/minimizers/test_factory.py b/tests/unit_tests/Fitting/minimizers/test_factory.py index 6376c536..db749c4e 100644 --- a/tests/unit_tests/Fitting/minimizers/test_factory.py +++ b/tests/unit_tests/Fitting/minimizers/test_factory.py @@ -12,7 +12,7 @@ def pull_minminizer(self, minimizer: AvailableMinimizers) -> MinimizerBase: minimizer = factory(minimizer, mock_fit_object, mock_fit_function) return minimizer - @pytest.mark.parametrize('minimizer_method,minimizer_enum', [('leastsq', AvailableMinimizers.LMFit), ('leastsq', AvailableMinimizers.LMFit_leastsq), ('powell', AvailableMinimizers.LMFit_powell), ('cobyla', AvailableMinimizers.LMFit_cobyla)]) + @pytest.mark.parametrize('minimizer_method,minimizer_enum', [('leastsq', AvailableMinimizers.LMFit), ('leastsq', AvailableMinimizers.LMFit_leastsq), ('powell', AvailableMinimizers.LMFit_powell), ('cobyla', AvailableMinimizers.LMFit_cobyla), ('differential_evolution', AvailableMinimizers.LMFit_differential_evolution), ('least_squares', AvailableMinimizers.LMFit_scipy_least_squares)]) def test_factory_lm_fit(self, minimizer_method, minimizer_enum): minimizer = self.pull_minminizer(minimizer_enum) assert minimizer._method == minimizer_method @@ -31,7 +31,7 @@ def test_factory_dfo_fit(self, minimizer_method, minimizer_enum): assert minimizer.wrapping == 'dfo' -@pytest.mark.parametrize('minimizer_name,expected', [('LMFit', AvailableMinimizers.LMFit), ('LMFit_leastsq', AvailableMinimizers.LMFit_leastsq), ('LMFit_powell', AvailableMinimizers.LMFit_powell), ('LMFit_cobyla', AvailableMinimizers.LMFit_cobyla), ]) +@pytest.mark.parametrize('minimizer_name,expected', [('LMFit', AvailableMinimizers.LMFit), ('LMFit_leastsq', AvailableMinimizers.LMFit_leastsq), ('LMFit_powell', AvailableMinimizers.LMFit_powell), ('LMFit_cobyla', AvailableMinimizers.LMFit_cobyla), ('LMFit_differential_evolution', AvailableMinimizers.LMFit_differential_evolution), ('LMFit_scipy_least_squares', AvailableMinimizers.LMFit_scipy_least_squares) ]) def test_from_string_to_enum_lmfit(minimizer_name, expected): assert from_string_to_enum(minimizer_name) == expected diff --git a/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py b/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py index 7f3e225e..9c055aa4 100644 --- a/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py +++ b/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py @@ -3,7 +3,6 @@ from unittest.mock import MagicMock import easyscience.fitting.minimizers.minimizer_lmfit -from easyscience.fitting import AvailableMinimizers from easyscience.fitting.minimizers.minimizer_lmfit import LMFit from easyscience.Objects.new_variable import Parameter from lmfit import Parameter as LMParameter