Esempio n. 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)}']
Esempio n. 2
0
        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)
# Reset the values so we don't cheat
line.m.value = 1
line.c.value = 0
f_res = f.fit(x, y)

print('\n######### Interface 2 #########\n')
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))
    print("The gooodness of fit is: {}".format(result.goodness_of_fit))

sim_y_data = interface.fit_func(data_x)

import matplotlib.pyplot as plt

plt.plot(data_x, data_y, label='Data')
plt.plot(data_x, result.y_calc, label='Calculate')
plt.show()
Esempio n. 4
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
Esempio n. 5
0
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
line.c = 0

f_res = f.fit(x, y, weights=0.1*np.ones_like(x))

print('\n######### bumps fitting #########\n')
Esempio n. 6
0
# 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)]
}

f_res = f.fit(x, y, method='dream', minimizer_kwargs=dream_kwargs)

print(f_res.goodness_of_fit)