示例#1
0
def test_fittingUndoRedo():
    m_value = 6
    c_value = 2
    x = np.linspace(-5, 5, 100)
    dy = np.random.rand(*x.shape)

    class Line(BaseObj):
        def __init__(self, m: Parameter, c: Parameter):
            super(Line, self).__init__('basic_line', m=m, c=c)

        @classmethod
        def default(cls):
            m = Parameter('m', m_value)
            c = Parameter('c', c_value)
            return cls(m=m, c=c)

        @classmethod
        def from_pars(cls, m_value: float, c_value: float):
            m = Parameter('m', m_value)
            c = Parameter('c', c_value)
            return cls(m=m, c=c)

        def __call__(self, x: np.ndarray) -> np.ndarray:
            return self.m.raw_value * x + self.c.raw_value

    l1 = Line.default()
    m_sp = 4
    c_sp = -3

    l2 = Line.from_pars(m_sp, c_sp)
    l2.m.fixed = False
    l2.c.fixed = False

    y = l1(x) + 0.125 * (dy - 0.5)

    from easyCore.Fitting.Fitting import Fitter
    f = Fitter(l2, l2)
    from easyCore import borg
    borg.stack.enabled = True
    res = f.fit(x, y)

    assert l1.c.raw_value == pytest.approx(l2.c.raw_value, rel=l2.c.error * 2)
    assert l1.m.raw_value == pytest.approx(l2.m.raw_value, rel=l2.m.error * 2)
    assert borg.stack.undoText() == 'Fitting routine'

    borg.stack.undo()
    assert l2.m.raw_value == m_sp
    assert l2.c.raw_value == c_sp
    assert borg.stack.redoText() == 'Fitting routine'

    borg.stack.redo()
    assert l2.m.raw_value == res.p[f'p{borg.map.convert_id_to_key(l2.m)}']
    assert l2.c.raw_value == res.p[f'p{borg.map.convert_id_to_key(l2.c)}']
示例#2
0
    def __init__(self, parent=None, sample=None, fit_func=""):
        super().__init__(parent)
        self.fitter = CoreFitter(sample, fit_func)

        self.parent = parent

        # Multithreading
        # self._fitter_thread = None
        self._fit_finished = True
        self._fit_results = self._defaultFitResults()

        self._current_minimizer_method_index = 0
        self._current_minimizer_method_name = self.fitter.available_methods()[0]  # noqa: E501

        self.fit_thread = Thread(target=self.fit_threading)
        self.finished.connect(self._setFitResults)
示例#3
0
from easyCore.Objects.ObjectClasses import Parameter, BaseObj
from easyCore.Fitting.Fitting import Fitter

import matplotlib.pyplot as plt

d = xr.Dataset()

b = BaseObj('line', m=Parameter('m', 1), c=Parameter('c', 1))


def fit_fun(x, *args, **kwargs):
    # In the real case we would gust call the evaluation fn without reference to the BaseObj
    return b.c.raw_value + b.m.raw_value * x


f = Fitter()
f.initialize(b, fit_fun)

nx = 1E3
x_min = 0
x_max = 100

x = np.linspace(x_min, x_max, num=int(nx))
y1 = 2 * x - 1 + 5 * (np.random.random(size=x.shape) - 0.5)
x2 = x + 20
y2 = 2 * x2 - 1 + 5 * (np.random.random(size=x2.shape) - 0.5)

d.easyCore.add_coordinate('x1', x)
d.easyCore.add_variable('y1', ['x1'], y1, auto_sigma=True)
d.easyCore.add_coordinate('x2', x2)
d.easyCore.add_variable('y2', ['x2'], y2, auto_sigma=True)
示例#4
0
            return self.m.raw_value

    @property
    def intercept(self):
        if self.interface:
            return self.interface().get_value('c')
        else:
            return self.c.raw_value

    def __repr__(self):
        return f'Line: m={self.m}, c={self.c}'


interface = InterfaceFactory()
line = Line(interface_factory=interface)
f = Fitter(line, interface.fit_func)

# y = 2x -1
x = np.array([1, 2, 3])
y = np.array([2, 4, 6]) - 1

f_res = f.fit(x, y)

print('\n######### Interface 1 #########\n')
print(f_res)
print(line)

# This gets the interface name `'Interface2'`
other_interface = interface.available_interfaces[1]
# Switch over the interfaces
line.interface.switch(other_interface)
示例#5
0
__author__ = 'github.com/wardsimon'
__version__ = '0.0.1'

import numpy as np
from easyCore.Objects.Base import Parameter, BaseObj
from easyCore.Fitting.Fitting import Fitter

# This is a simple example of creating an object which has fitable parameters

b = BaseObj('line', m=Parameter('m', 1), c=Parameter('c', 1))


def fit_fun(x):
    # In the real case we would gust call the evaluation fn without reference to the BaseObj
    return b.c.raw_value + b.m.raw_value * x


f = Fitter()
f.initialize(b, fit_fun)

x = np.array([1, 2, 3])
y = np.array([2, 4, 6]) - 1

f_res = f.fit(x, y)

print(f_res.fit_report())
data_set.easyCore.add_variable('I', ['tth'], data_y)
data_set.easyCore.sigma_attach('I', data_e)

S.parameters.wavelength = 1.912
S.parameters.u_resolution = 1.4
S.parameters.v_resolution = -0.42
S.parameters.w_resolution = 0.38
S.parameters.x_resolution = 0.0
S.parameters.y_resolution = 0.0

bg = PointBackground(linked_experiment='PbSO4')
bg.append(BackgroundPoint.from_pars(data_x[0], 200))
bg.append(BackgroundPoint.from_pars(data_x[-1], 200))

S.set_background(bg)
f = Fitter(S, interface.fit_func)

# Vary the scale and the BG points
S.pattern.scale.fixed = False
S.pattern.zero_shift.fixed = False
S.parameters.resolution_u.fixed = False
S.parameters.resolution_v.fixed = False
S.parameters.resolution_w.fixed = False
S.backgrounds[0][0].y.fixed = True
S.backgrounds[0][1].y.fixed = True

result = f.fit(data_x, data_y)
# result = data_set['I'].easyCore.fit(f)

if result.success:
    print("The fit has been successful: {}".format(result.success))
示例#7
0
            raise NotImplementedError

    def __repr__(self):
        return f'Line: m={self.m}, c={self.c}'

    @staticmethod
    def __gitem(key: str) -> Callable:
        def inner(obj):
            obj.interface.get_value(key)

        return lambda obj: inner(obj)

    @staticmethod
    def __sitem(obj, key):
        def inner(value):
            obj.interface.set_value(key, value)

        return inner


l = Line(interface=Interface())
l.interface
f = Fitter(l, l.fit_func)

x = np.array([1, 2, 3])
y = np.array([2, 4, 6]) - 1

f_res = f.fit(x, y)

print(f_res)
print(l)
示例#8
0
 def fit_experiment(self, experiment_name, fitter=None):
     dataarray_name = self.name + '_' + experiment_name + '_I'
     if fitter is None:
         fitter = Fitter(self, self.interface.fit_func)
     return self.datastore.store[dataarray_name].easyCore.fit(fitter)
示例#9
0
class FitterLogic(QObject):
    """
    Logic related to the fitter setup
    """
    fitFinished = Signal()
    fitStarted = Signal()
    currentMinimizerChanged = Signal()
    finished = Signal(dict)

    def __init__(self, parent=None, sample=None, fit_func=""):
        super().__init__(parent)
        self.fitter = CoreFitter(sample, fit_func)

        self.parent = parent

        # Multithreading
        # self._fitter_thread = None
        self._fit_finished = True
        self._fit_results = self._defaultFitResults()

        self._current_minimizer_method_index = 0
        self._current_minimizer_method_name = self.fitter.available_methods()[0]  # noqa: E501

        self.fit_thread = Thread(target=self.fit_threading)
        self.finished.connect(self._setFitResults)

    def fit_threading(self):
        data = self.data
        method = self.minimizer_name

        self._fit_finished = False
        self.fitStarted.emit()
        exp_data = data.experiments[0]

        x = exp_data.x
        y = exp_data.y
        weights = 1 / exp_data.e

        res = self.fitter.fit(x, y, weights=weights, method=method)
        self.finished.emit(res)

    def _defaultFitResults(self):
        return {
            "success": None,
            "nvarys":  None,
            "GOF":     None,
            "redchi2": None
        }

    def _setFitResults(self, res):
        if self.fit_thread.is_alive():
            self.fit_thread.join()
        self._fit_results = {
            "success": res.success,
            "nvarys":  res.n_pars,
            "GOF":     float(res.goodness_of_fit),
            "redchi2": float(res.reduced_chi)
        }
        self._fit_finished = True
        self.fitFinished.emit()
        # must reinstantiate the thread object
        self.fit_thread = Thread(target=self.fit_threading)

    def fit(self, data):
        self.data = data
        self.minimizer_name = self._current_minimizer_method_name
        if not self.fit_thread.is_alive():
            self.is_fitting_now = True
            self.fit_thread.start()

    ########### QTHREADS #################
    # def fit_qthreads(self, data, minimizer_name):
    #     # if running, stop the thread
    #     if not self._fit_finished:
    #         self.onStopFit()
    #         borg.stack.endMacro()  # need this to close the undo stack properly
    #         return

    #     self._fit_finished = False
    #     self.fitStarted.emit()
    #     exp_data = data.experiments[0]

    #     x = exp_data.x
    #     y = exp_data.y
    #     weights = 1 / exp_data.e
    #     method = minimizer_name

    #     args = (x, y)
    #     kwargs = {"weights": weights, "method": method}
    #     self._fitter_thread = Fitter(self.parent, self.fitter, 'fit', *args, **kwargs)  # noqa: E501
    #     self._fitter_thread.finished.connect(self._setFitResults)
    #     self._fitter_thread.setTerminationEnabled(True)
    #     self._fitter_thread.failed.connect(self._setFitResultsFailed)
    #     self._fitter_thread.start()
    # def _setFitResultsFailed(self, res):
    #     self.finishFitting()

    # def finishFitting(self):
    #     self._fit_finished = True
    #     self.fitFinished.emit()

    # def onStopFit(self):
    #     """
    #     Slot for thread cancelling and reloading parameters
    #     """
    #     self._fitter_thread.terminate()
    #     self._fitter_thread.wait()
    #     self._fitter_thread = None

    #     self._fit_results['success'] = 'cancelled'
    #     self._fit_results['nvarys'] = None
    #     self._fit_results['GOF'] = None
    #     self._fit_results['redchi2'] = None
    #     self._setFitResultsFailed("Fitting stopped")
    # def setFitFinished(self, fit_finished: bool):
    #     if self._fit_finished == fit_finished:
    #         return
    #     self._fit_finished = fit_finished

    def currentMinimizerIndex(self):
        current_name = self.fitter.current_engine.name
        index = self.fitter.available_engines.index(current_name)
        return index

    def setCurrentMinimizerIndex(self, new_index: int):
        if self.currentMinimizerIndex() == new_index:
            return
        new_name = self.fitter.available_engines[new_index]
        self.fitter.switch_engine(new_name)
        self.currentMinimizerChanged.emit()

    def onCurrentMinimizerChanged(self):
        idx = 0
        minimizer_name = self.fitter.current_engine.name
        if minimizer_name == 'lmfit':
            idx = self.minimizerMethodNames().index('leastsq')
        elif minimizer_name == 'bumps':
            idx = self.minimizerMethodNames().index('lm')
        if -1 < idx != self._current_minimizer_method_index:
            # Bypass the property as it would be added to the stack.
            self._current_minimizer_method_index = idx
            self._current_minimizer_method_name = self.minimizerMethodNames()[idx]  # noqa: E501
            self.currentMinimizerChanged.emit()
        return

    def minimizerMethodNames(self):
        current_minimizer = self.fitter.available_engines[self.currentMinimizerIndex()]  # noqa: E501
        tested_methods = {
            'lmfit': ['leastsq', 'powell', 'cobyla'],
            'bumps': ['newton', 'lm'],
            'DFO_LS': ['leastsq']
        }
        return tested_methods[current_minimizer]

    def currentMinimizerMethodIndex(self, new_index: int):
        if self._current_minimizer_method_index == new_index:
            return

        self._current_minimizer_method_index = new_index
        self._current_minimizer_method_name = self.minimizerMethodNames()[new_index]  # noqa: E501
示例#10
0
    _defaults = [Parameter('m', 1), Parameter('c', 0)]

    def __init__(self):
        super().__init__(self.__class__.__name__, *self._defaults)

    @property
    def gradient(self):
        return self.m.raw_value

    @property
    def intercept(self):
        return self.c.raw_value

    def fit_func(self, x: np.ndarray) -> np.ndarray:
        return self.gradient * x + self.intercept

    def __repr__(self):
        return f'Line: m={self.m}, c={self.c}'


l = Line()
f = Fitter()
f.initialize(l, l.fit_func)

x = np.array([1, 2, 3])
y = np.array([2, 4, 6]) - 1

f_res = f.fit(x, y)

print(f_res.fit_report())
print(l)
示例#11
0
import numpy as np

from easyCore.Fitting.Fitting import Fitter

from Example1.interface import InterfaceFactory
from Example1.Line import Line

# This is a much more complex case where we have calculators, interfaces, interface factory and an
# inherited object (from `BaseObj`). In this case the Line class is available with/without an interface
# With an interface it connects to one of the calculator interfaces. This calculator interface then translates
# interface commands to calculator specific commands


interface = InterfaceFactory()
line = Line(interface_factory=interface)
f = Fitter(line, interface.fit_func)

x = np.array([1, 2, 3])
y = 2*x - 1

f_res = f.fit(x, y)

print('\n######### Interface 1 #########\n')
print(f_res)
print(line)

# Now lets change fitting engine
f.switch_engine('bumps')

# Reset the values so we don't cheat
line.m = 1
def fit_fun(x, *args, **kwargs):
    # In the real case we would gust call the evaluation fn without reference to the BaseObj
    return b.c.raw_value + b.m.raw_value * x


nx = 1E3
x_min = 0
x_max = 100

x = np.linspace(x_min, x_max, num=int(nx))
y = 2 * x - 1 + 5 * (np.random.random(size=x.shape) - 0.5)

d.easyCore.add_coordinate('x', x)
d.easyCore.add_variable('y', ['x'], y, auto_sigma=False)

f = Fitter()
f.initialize(b, fit_fun)

fig, ax = plt.subplots(2, 3, sharey='row')
for idx, minimizer in enumerate(['lmfit', 'bumps', 'DFO_LS']):

    b.m = m_starting_point
    b.c = c_starting_point
    f.switch_engine(minimizer)

    f_res = d['y'].easyCore.fit(f, vectorize=True)
    print(f_res.p)

    d['y'].plot(ax=ax[0, idx])
    f_res.y_calc.unstack().plot(ax=ax[0, idx])
    temp = d['y'] - f_res.y_calc
示例#13
0
import numpy as np
from easyCore.Objects.ObjectClasses import Parameter, BaseObj
from easyCore.Fitting.Fitting import Fitter

# This is a simple example of creating an object which has fitable parameters

b = BaseObj('line', m=Parameter('m', 1), c=Parameter('c', 1))


def fit_fun(x):
    # In the real case we would gust call the evaluation fn without reference to the BaseObj
    return b.c.raw_value + b.m.raw_value * x


f = Fitter()
f.initialize(b, fit_fun)
f.switch_engine('bumps')

x = np.array([1, 2, 3])
y = np.array([2, 4, 6]) - 1

method = 'dream'
dream_kwargs = {
    k: v
    for k, v in [('samples', 10000), ('burn', 100), ('pop', 10), (
        'init', 'eps'), ('thin', 1), ('alpha',
                                      0.01), ('outliers',
                                              'none'), ('trim',
                                                        False), ('steps', 0)]
}