diff --git a/src/easyscience/fitting/minimizers/minimizer_base.py b/src/easyscience/fitting/minimizers/minimizer_base.py index 10006da0..9836bdfb 100644 --- a/src/easyscience/fitting/minimizers/minimizer_base.py +++ b/src/easyscience/fitting/minimizers/minimizer_base.py @@ -40,7 +40,7 @@ def __init__( fit_function: Callable, method: Optional[str] = None, ): # todo after constraint changes, add type hint: obj: BaseObj # noqa: E501 - if method not in self.available_methods(): + if method not in self.supported_methods(): raise FitError(f'Method {method} not available in {self.__class__}') self._object = obj self._original_fit_function = fit_function @@ -132,12 +132,23 @@ def convert_to_pars_obj(self, par_list: Optional[Union[list]] = None): :return: engine Parameters compatible object """ + @staticmethod + @abstractmethod + def supported_methods() -> List[str]: + """ + Return a list of supported methods for the minimizer. + + :return: List of supported methods + :rtype: List[str] + """ + + @staticmethod @abstractmethod - def available_methods(self) -> List[str]: + def all_methods() -> List[str]: """ - Return a list of available methods for the engine. + Return a list of all available methods for the minimizer. - :return: List of available methods + :return: List of all available methods :rtype: List[str] """ diff --git a/src/easyscience/fitting/minimizers/minimizer_bumps.py b/src/easyscience/fitting/minimizers/minimizer_bumps.py index 52ee4dcd..1840dddc 100644 --- a/src/easyscience/fitting/minimizers/minimizer_bumps.py +++ b/src/easyscience/fitting/minimizers/minimizer_bumps.py @@ -55,9 +55,16 @@ def __init__( super().__init__(obj=obj, fit_function=fit_function, method=method) self._p_0 = {} - def available_methods(self) -> List[str]: + @staticmethod + def all_methods() -> List[str]: return FIT_AVAILABLE_IDS_FILTERED + @staticmethod + def supported_methods() -> List[str]: + # only a small subset + methods = ['scipy.leastsq','amoeba', 'newton', 'lm'] + return methods + def fit( self, x: np.ndarray, @@ -92,7 +99,7 @@ def fit( default_method = {} if self._method is not None: default_method = {'method': self._method} - if method is not None and method in self.available_methods(): + if method is not None and method in self.supported_methods(): default_method['method'] = method if weights is None: diff --git a/src/easyscience/fitting/minimizers/minimizer_dfo.py b/src/easyscience/fitting/minimizers/minimizer_dfo.py index a57f5d24..fa65e481 100644 --- a/src/easyscience/fitting/minimizers/minimizer_dfo.py +++ b/src/easyscience/fitting/minimizers/minimizer_dfo.py @@ -46,9 +46,16 @@ def __init__( super().__init__(obj=obj, fit_function=fit_function, method=method) self._p_0 = {} - def available_methods(self) -> List[str]: + @staticmethod + def supported_methods() -> List[str]: return ['leastsq'] + @staticmethod + def all_methods() -> List[str]: + return [ + 'leastsq', + ] + def fit( self, x: np.ndarray, @@ -83,7 +90,7 @@ def fit( default_method = {} if self._method is not None: default_method = {'method': self._method} - if method is not None and method in self.available_methods(): + if method is not None and method in self.supported_methods(): default_method['method'] = method if weights is None: diff --git a/src/easyscience/fitting/minimizers/minimizer_lmfit.py b/src/easyscience/fitting/minimizers/minimizer_lmfit.py index 4f82a711..59164047 100644 --- a/src/easyscience/fitting/minimizers/minimizer_lmfit.py +++ b/src/easyscience/fitting/minimizers/minimizer_lmfit.py @@ -49,7 +49,8 @@ def __init__( """ super().__init__(obj=obj, fit_function=fit_function, method=method) - def available_methods(self) -> List[str]: + @staticmethod + def all_methods() -> List[str]: return [ 'least_squares', 'leastsq', @@ -65,6 +66,15 @@ def available_methods(self) -> List[str]: 'bfgs', ] + @staticmethod + def supported_methods() -> List[str]: + return [ + 'least_squares', + 'leastsq', + 'powell', + 'cobyla', + ] + def fit( self, x: np.ndarray, @@ -102,7 +112,7 @@ def fit( if self._method is not None: default_method = {'method': self._method} if method is not None: - if method in self.available_methods(): + if method in self.supported_methods(): default_method['method'] = method else: raise FitError(f'Method {method} not available in {self.__class__}') diff --git a/tests/integration_tests/Fitting/test_fitter.py b/tests/integration_tests/Fitting/test_fitter.py index b6b8179f..1dbcb6ed 100644 --- a/tests/integration_tests/Fitting/test_fitter.py +++ b/tests/integration_tests/Fitting/test_fitter.py @@ -152,7 +152,7 @@ def test_lmfit_methods(fit_method): sp_sin.phase.fixed = False f = Fitter(sp_sin, sp_sin) - assert fit_method in f._minimizer.available_methods() + assert fit_method in f._minimizer.supported_methods() result = f.fit(x, y, method=fit_method) check_fit_results(result, sp_sin, ref_sin, x) @@ -171,7 +171,7 @@ def test_bumps_methods(fit_method): f = Fitter(sp_sin, sp_sin) f.switch_minimizer("Bumps") - assert fit_method in f._minimizer.available_methods() + assert fit_method in f._minimizer.supported_methods() result = f.fit(x, y, method=fit_method) check_fit_results(result, sp_sin, ref_sin, x) diff --git a/tests/integration_tests/Fitting/test_fitter_legacy_parameter.py b/tests/integration_tests/Fitting/test_fitter_legacy_parameter.py index 5dc040ff..acafae5b 100644 --- a/tests/integration_tests/Fitting/test_fitter_legacy_parameter.py +++ b/tests/integration_tests/Fitting/test_fitter_legacy_parameter.py @@ -152,7 +152,7 @@ def test_lmfit_methods(fit_method): sp_sin.phase.fixed = False f = Fitter(sp_sin, sp_sin) - assert fit_method in f._minimizer.available_methods() + assert fit_method in f._minimizer.supported_methods() result = f.fit(x, y, method=fit_method) check_fit_results(result, sp_sin, ref_sin, x) @@ -171,7 +171,7 @@ def test_bumps_methods(fit_method): f = Fitter(sp_sin, sp_sin) f.switch_minimizer("Bumps") - assert fit_method in f._minimizer.available_methods() + assert fit_method in f._minimizer.supported_methods() result = f.fit(x, y, method=fit_method) check_fit_results(result, sp_sin, ref_sin, x) diff --git a/tests/unit_tests/Fitting/minimizers/test_minimizer_base.py b/tests/unit_tests/Fitting/minimizers/test_minimizer_base.py index c036d4f9..3f483dd5 100644 --- a/tests/unit_tests/Fitting/minimizers/test_minimizer_base.py +++ b/tests/unit_tests/Fitting/minimizers/test_minimizer_base.py @@ -15,7 +15,7 @@ class TestMinimizerBase(): def minimizer(self): # This avoids the error: TypeError: Can't instantiate abstract class with abstract methods __init__ MinimizerBase.__abstractmethods__ = set() - MinimizerBase.available_methods = MagicMock(return_value=['method']) + MinimizerBase.supported_methods = MagicMock(return_value=['method']) minimizer = MinimizerBase( obj='obj', @@ -27,7 +27,7 @@ def minimizer(self): def test_init_exception(self): # When Then MinimizerBase.__abstractmethods__ = set() - MinimizerBase.available_methods = MagicMock(return_value=['method']) + MinimizerBase.supported_methods = MagicMock(return_value=['method']) # Expect with pytest.raises(FitError): diff --git a/tests/unit_tests/Fitting/minimizers/test_minimizer_bumps.py b/tests/unit_tests/Fitting/minimizers/test_minimizer_bumps.py index 558b9b60..bed4f6bb 100644 --- a/tests/unit_tests/Fitting/minimizers/test_minimizer_bumps.py +++ b/tests/unit_tests/Fitting/minimizers/test_minimizer_bumps.py @@ -32,9 +32,13 @@ def test_init_exception(self) -> None: method='not_leastsq' ) - def test_available_methods(self, minimizer: Bumps) -> None: + def test_all_methods(self, minimizer: Bumps) -> None: # When Then Expect - assert minimizer.available_methods() == ['amoeba', 'de', 'dream', 'newton', 'scipy.leastsq', 'lm'] + assert minimizer.all_methods() == ['amoeba', 'de', 'dream', 'newton', 'scipy.leastsq', 'lm'] + + def test_supported_methods(self, minimizer: Bumps) -> None: + # When Then Expect + assert set(minimizer.supported_methods()) == set(['scipy.leastsq','newton', 'lm', 'amoeba']) def test_fit(self, minimizer: Bumps, monkeypatch) -> None: # When diff --git a/tests/unit_tests/Fitting/minimizers/test_minimizer_dfo.py b/tests/unit_tests/Fitting/minimizers/test_minimizer_dfo.py index 676d9e8a..1be679c5 100644 --- a/tests/unit_tests/Fitting/minimizers/test_minimizer_dfo.py +++ b/tests/unit_tests/Fitting/minimizers/test_minimizer_dfo.py @@ -32,9 +32,13 @@ def test_init_exception(self) -> None: method='not_leastsq' ) - def test_available_methods(self, minimizer: DFO) -> None: + def test_supported_methods(self, minimizer: DFO) -> None: # When Then Expect - assert minimizer.available_methods() == ['leastsq'] + assert minimizer.supported_methods() == ['leastsq'] + + def test_supported_methods(self, minimizer: DFO) -> None: + # When Then Expect + assert minimizer.supported_methods() == ['leastsq'] def test_fit(self, minimizer: DFO) -> None: # When diff --git a/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py b/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py index b8b42f28..0a6c8db9 100644 --- a/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py +++ b/tests/unit_tests/Fitting/minimizers/test_minimizer_lmfit.py @@ -127,14 +127,15 @@ def test_fit_method(self, minimizer: LMFit) -> None: minimizer._make_model = MagicMock(return_value=mock_model) minimizer._set_parameter_fit_result = MagicMock() minimizer._gen_fit_results = MagicMock(return_value='gen_fit_results') - minimizer.available_methods = MagicMock(return_value=['method_passed']) + minimizer.supported_methods = MagicMock(return_value=['method_passed']) + minimizer.all_methods = MagicMock(return_value=['method_passed']) # Then minimizer.fit(x=1.0, y=2.0, method='method_passed') # Expect mock_model.fit.assert_called_once_with(2.0, x=1.0, weights=0.7071067811865475, method='method_passed') - minimizer.available_methods.assert_called_once_with() + minimizer.supported_methods.assert_called_once_with() def test_fit_kwargs(self, minimizer: LMFit) -> None: # When