Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/docs/tutorials/progress-callback.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"\n",
"from easyscience import AvailableMinimizers\n",
"from easyscience import EasyList\n",
"from easyscience import Fitter\n",
"from easyscience import Minimizers\n",
"from easyscience import ModelBase\n",
"from easyscience import Parameter"
]
Expand Down Expand Up @@ -264,7 +264,7 @@
},
"outputs": [],
"source": [
"def fit_with(backend: AvailableMinimizers):\n",
"def fit_with(backend: Minimizers):\n",
" model = make_initial_model()\n",
" fitter = Fitter(model, model)\n",
" fitter.switch_minimizer(backend)\n",
Expand All @@ -277,7 +277,7 @@
"\n",
"results = {}\n",
"histories = {}\n",
"for backend in (AvailableMinimizers.LMFit, AvailableMinimizers.Bumps, AvailableMinimizers.DFO):\n",
"for backend in (Minimizers.LMFit, Minimizers.Bumps, Minimizers.DFO):\n",
" res, hist = fit_with(backend)\n",
" results[backend.name] = res\n",
" histories[backend.name] = hist\n",
Expand Down Expand Up @@ -370,7 +370,7 @@
"else:\n",
" model = make_initial_model()\n",
" fitter = Fitter(model, model)\n",
" fitter.switch_minimizer(AvailableMinimizers.LMFit)\n",
" fitter.switch_minimizer(Minimizers.LMFit)\n",
" fitter.max_evaluations = 108\n",
"\n",
" pbar = tqdm(total=fitter.max_evaluations, desc='LMFit', unit='eval')\n",
Expand Down
4 changes: 3 additions & 1 deletion docs/docs/user-guide/external-calculators.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,9 @@ It is polled during the optimizer loop and once more after it finishes,
so it must have no side effects:

```python
fitter.switch_minimizer('Bumps')
from easyscience import Minimizers

fitter.switch_minimizer(Minimizers.Bumps)
result = fitter.fit(
x=x, y=y, weights=np.ones_like(x), abort_test=lambda: stop_requested
)
Expand Down
18 changes: 9 additions & 9 deletions src/easyscience/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@

from .base_classes import EasyList # noqa: E402
from .base_classes import ModelBase # noqa: E402
from .fitting import AvailableMinimizers # noqa: E402
from .fitting import Fitter # noqa: E402
from .fitting.available_minimizers import Minimizers # noqa: E402
from .variable import DescriptorNumber # noqa: E402
from .variable import Parameter # noqa: E402

__version__ = version('easyscience')

__all__ = [
'__version__',
'global_object',
'ModelBase',
'EasyList',
'AvailableMinimizers',
'Fitter',
'DescriptorNumber',
'Parameter',
__version__,
global_object,
ModelBase,
EasyList,
Minimizers,
Fitter,
DescriptorNumber,
Parameter,
]
1 change: 0 additions & 1 deletion src/easyscience/fitting/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# SPDX-FileCopyrightText: 2026 EasyScience contributors <https://github.com/easyscience>
# SPDX-License-Identifier: BSD-3-Clause

from .available_minimizers import AvailableMinimizers
from .fitter import Fitter
from .minimizers.utils import FitResults
from .sampler import Sampler
Expand Down
38 changes: 1 addition & 37 deletions src/easyscience/fitting/available_minimizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class AvailableMinimizer:
enum_id: int


class AvailableMinimizers(AvailableMinimizer, Enum):
class Minimizers(AvailableMinimizer, Enum):
if lmfit_engine_available:
LMFit = 'lm', 'leastsq', 11
LMFit_leastsq = 'lm', 'leastsq', 12
Expand All @@ -66,39 +66,3 @@ class AvailableMinimizers(AvailableMinimizer, Enum):
if dfo_engine_available:
DFO = 'dfo', 'leastsq', 31
DFO_leastsq = 'dfo', 'leastsq', 32


# Temporary solution to convert string to enum
def from_string_to_enum(minimizer_name: str) -> AvailableMinimizers:
if minimizer_name == 'LMFit':
minmizer_enum = AvailableMinimizers.LMFit
elif minimizer_name == 'LMFit_leastsq':
minmizer_enum = AvailableMinimizers.LMFit_leastsq
elif minimizer_name == 'LMFit_powell':
minmizer_enum = AvailableMinimizers.LMFit_powell
elif minimizer_name == 'LMFit_cobyla':
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
elif minimizer_name == 'Bumps_simplex':
minmizer_enum = AvailableMinimizers.Bumps_simplex
elif minimizer_name == 'Bumps_newton':
minmizer_enum = AvailableMinimizers.Bumps_newton
elif minimizer_name == 'Bumps_lm':
minmizer_enum = AvailableMinimizers.Bumps_lm

elif minimizer_name == 'DFO':
minmizer_enum = AvailableMinimizers.DFO
elif minimizer_name == 'DFO_leastsq':
minmizer_enum = AvailableMinimizers.DFO_leastsq
else:
raise ValueError(
f'Invalid minimizer name: {minimizer_name}. The following minimizers are available: {[minimize.name for minimize in AvailableMinimizers]}' # noqa: E501
)

return minmizer_enum
57 changes: 20 additions & 37 deletions src/easyscience/fitting/fitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,17 @@
import functools
from typing import Callable
from typing import List
from typing import Union

import numpy as np

from easyscience import global_object

from .available_minimizers import AvailableMinimizers
from .available_minimizers import from_string_to_enum
from .available_minimizers import Minimizers
from .minimizers import FitResults
from .minimizers import MinimizerBase
from .minimizers.factory import factory
from .reshaping import inject_x
from .reshaping import reshape_dataset

DEFAULT_MINIMIZER = AvailableMinimizers.LMFit_leastsq
DEFAULT_MINIMIZER = Minimizers.LMFit_leastsq


class Fitter:
Expand All @@ -35,7 +31,7 @@ def __init__(self, fit_object, fit_function: Callable):
self._max_evaluations: int = None

self._minimizer: MinimizerBase = None # set in _update_minimizer
self._enum_current_minimizer: AvailableMinimizers = None # set in _update_minimizer
self._enum_current_minimizer: Minimizers = None # set in _update_minimizer
self._update_minimizer(DEFAULT_MINIMIZER)

def make_model(self, pars=None) -> Callable:
Expand All @@ -60,42 +56,29 @@ def initialize(self, fit_object: object, fit_function: Callable) -> None:
self._fit_function = fit_function
self._update_minimizer(DEFAULT_MINIMIZER)

# TODO: remove this method when we are ready to adjust the dependent products
def create(self, minimizer_enum: Union[AvailableMinimizers, str] = DEFAULT_MINIMIZER) -> None:
"""
Create the required minimizer.

Parameters
----------
minimizer_enum : Union[AvailableMinimizers, str], default=DEFAULT_MINIMIZER
The enum of the minimization engine to create. By default,
DEFAULT_MINIMIZER.
"""
if isinstance(minimizer_enum, str):
global_object.log.getLogger('fitting').warning(
'minimizer should be set with enum %s', minimizer_enum
)
minimizer_enum = from_string_to_enum(minimizer_enum)
self._update_minimizer(minimizer_enum)

def switch_minimizer(self, minimizer_enum: Union[AvailableMinimizers, str]) -> None:
def switch_minimizer(self, minimizer_enum: Minimizers) -> None:
"""
Switch minimizer and initialize.

Parameters
----------
minimizer_enum : Union[AvailableMinimizers, str]
minimizer_enum : Minimizers
The enum of the minimizer to create and instantiate.

Raises
------
TypeError
If ``minimizer_enum`` is not a ``Minimizers``
member.
"""
if isinstance(minimizer_enum, str):
global_object.log.getLogger('fitting').warning(
'minimizer should be set with enum %s', minimizer_enum
if not isinstance(minimizer_enum, Minimizers):
raise TypeError(
f'minimizer must be a Minimizers member, got {minimizer_enum!r}; '
f'use Minimizers[name] to convert a name'
)
minimizer_enum = from_string_to_enum(minimizer_enum)

self._update_minimizer(minimizer_enum)

def _update_minimizer(self, minimizer_enum: AvailableMinimizers) -> None:
def _update_minimizer(self, minimizer_enum: Minimizers) -> None:
self._minimizer = factory(
minimizer_enum=minimizer_enum,
fit_object=self._fit_object,
Expand All @@ -104,16 +87,16 @@ def _update_minimizer(self, minimizer_enum: AvailableMinimizers) -> None:
self._enum_current_minimizer = minimizer_enum

@property
def available_minimizers(self) -> List[str]:
def available_minimizers(self) -> List[Minimizers]:
"""
Get a list of the names of available fitting minimizers.
Get a list of the available fitting minimizers.

Returns
-------
List[str]
List[Minimizers]
List of available fitting minimizers.
"""
return [minimize.name for minimize in AvailableMinimizers]
return list(Minimizers)

@property
def minimizer(self) -> MinimizerBase:
Expand Down
6 changes: 2 additions & 4 deletions src/easyscience/fitting/minimizers/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import Callable

from .. import available_minimizers
from ..available_minimizers import AvailableMinimizers
from ..available_minimizers import Minimizers
from .minimizer_base import MinimizerBase

if available_minimizers.lmfit_engine_available:
Expand All @@ -15,9 +15,7 @@
from .minimizer_bumps import Bumps


def factory(
minimizer_enum: AvailableMinimizers, fit_object, fit_function: Callable
) -> MinimizerBase:
def factory(minimizer_enum: Minimizers, fit_object, fit_function: Callable) -> MinimizerBase:
if minimizer_enum.package == 'lm':
minimizer = LMFit(obj=fit_object, fit_function=fit_function, minimizer_enum=minimizer_enum)

Expand Down
6 changes: 3 additions & 3 deletions src/easyscience/fitting/minimizers/minimizer_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from easyscience.variable import Parameter

from ..available_minimizers import AvailableMinimizers
from ..available_minimizers import Minimizers
from ..engine_base import EngineBase
from .utils import FitError
from .utils import FitResults
Expand All @@ -26,7 +26,7 @@ def __init__(
self,
obj, #: ModelBase,
fit_function: Callable,
minimizer_enum: AvailableMinimizers,
minimizer_enum: Minimizers,
): # todo after constraint changes, add type hint: obj: ModelBase # noqa: E501
if minimizer_enum.method not in self.supported_methods():
raise FitError(f'Method {minimizer_enum.method} not available in {self.__class__}')
Expand All @@ -36,7 +36,7 @@ def __init__(
self._cached_model = None

@property
def enum(self) -> AvailableMinimizers:
def enum(self) -> Minimizers:
return self._minimizer_enum

@property
Expand Down
6 changes: 3 additions & 3 deletions src/easyscience/fitting/minimizers/minimizer_bumps.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from easyscience.variable import Parameter

from ..available_minimizers import AvailableMinimizers
from ..available_minimizers import Minimizers
from ..engine_base import PARAMETER_PREFIX
from .bumps_utils import BumpsProgressMonitor
from .bumps_utils import EvalCounter
Expand Down Expand Up @@ -49,7 +49,7 @@ def __init__(
self,
obj: object,
fit_function: Callable,
minimizer_enum: AvailableMinimizers | None = None,
minimizer_enum: Minimizers | None = None,
):
"""
Initialize the fitting engine.
Expand All @@ -60,7 +60,7 @@ def __init__(
Object containing the ``Parameter`` instances to fit.
fit_function : Callable
Callable returning model y values for the supplied x values.
minimizer_enum : AvailableMinimizers | None, default=None
minimizer_enum : Minimizers | None, default=None
Selected BUMPS minimizer configuration. By default, None.
"""
super().__init__(obj=obj, fit_function=fit_function, minimizer_enum=minimizer_enum)
Expand Down
6 changes: 3 additions & 3 deletions src/easyscience/fitting/minimizers/minimizer_dfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from easyscience.variable import Parameter

from ..available_minimizers import AvailableMinimizers
from ..available_minimizers import Minimizers
from ..engine_base import PARAMETER_PREFIX
from .minimizer_base import MinimizerBase
from .utils import FitError
Expand Down Expand Up @@ -46,7 +46,7 @@ def __init__(
self,
obj: object, #: ModelBase,
fit_function: Callable,
minimizer_enum: AvailableMinimizers | None = None,
minimizer_enum: Minimizers | None = None,
): # todo after constraint changes, add type hint: obj: ModelBase # noqa: E501
"""
Initialize the fitting engine.
Expand All @@ -57,7 +57,7 @@ def __init__(
Object containing the ``Parameter`` instances to fit.
fit_function : Callable
Callable returning model y values for the supplied x values.
minimizer_enum : AvailableMinimizers | None, default=None
minimizer_enum : Minimizers | None, default=None
Selected DFO minimizer configuration. By default, None.
"""
super().__init__(obj=obj, fit_function=fit_function, minimizer_enum=minimizer_enum)
Expand Down
6 changes: 3 additions & 3 deletions src/easyscience/fitting/minimizers/minimizer_lmfit.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from easyscience.variable import Parameter

from ..available_minimizers import AvailableMinimizers
from ..available_minimizers import Minimizers
from ..engine_base import PARAMETER_PREFIX
from .minimizer_base import MinimizerBase
from .utils import FitError
Expand All @@ -34,7 +34,7 @@ def __init__(
self,
obj: object, #: ModelBase,
fit_function: Callable,
minimizer_enum: AvailableMinimizers | None = None,
minimizer_enum: Minimizers | None = None,
): # todo after constraint changes, add type hint: obj: ModelBase # noqa: E501
"""
Initialize the minimizer.
Expand All @@ -45,7 +45,7 @@ def __init__(
Object containing the ``Parameter`` instances to fit.
fit_function : Callable
Callable returning model y values for the supplied x values.
minimizer_enum : AvailableMinimizers | None, default=None
minimizer_enum : Minimizers | None, default=None
Selected LMFit minimizer configuration. By default, None.
"""
super().__init__(obj=obj, fit_function=fit_function, minimizer_enum=minimizer_enum)
Expand Down
Loading
Loading