def test_eval_components(self):
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')
        model3 = models.ConstantModel(prefix='bkg_')
        mod = model1 + model2 + model3
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data = (1.01 + gaussian(x=self.x, **values1) +
                gaussian(x=self.x, **values2) + 0.05*self.noise)

        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1, max=1.5)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.6, min=2.0)
        pars['g2_amplitude'].set(1)
        pars['bkg_c'].set(1.88)

        result = mod.fit(data, params=pars, x=self.x)

        self.assertTrue(abs(result.params['g1_amplitude'].value - 7.1) < 1.5)
        self.assertTrue(abs(result.params['g2_amplitude'].value - 12.2) < 1.5)
        self.assertTrue(abs(result.params['g1_center'].value - 1.1) < 0.2)
        self.assertTrue(abs(result.params['g2_center'].value - 2.5) < 0.2)
        self.assertTrue(abs(result.params['bkg_c'].value - 1.0) < 0.25)

        comps = mod.eval_components(x=self.x)
        assert 'bkg_' in comps
    def test_composite_has_bestvalues(self):
        # test that a composite model has non-empty best_values
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')

        mod = model1 + model2
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data = (gaussian(x=self.x, **values1) + gaussian(x=self.x, **values2)
                + 0.1*self.noise)

        pars['g1_sigma'].set(value=2)
        pars['g1_center'].set(value=1, max=1.5)
        pars['g1_amplitude'].set(value=3)
        pars['g2_sigma'].set(value=1)
        pars['g2_center'].set(value=2.6, min=2.0)
        pars['g2_amplitude'].set(value=1)

        result = mod.fit(data, params=pars, x=self.x)

        self.assertTrue(len(result.best_values) == 6)

        self.assertTrue(abs(result.params['g1_amplitude'].value - 7.1) < 0.5)
        self.assertTrue(abs(result.params['g2_amplitude'].value - 12.2) < 0.5)
        self.assertTrue(abs(result.params['g1_center'].value - 1.1) < 0.2)
        self.assertTrue(abs(result.params['g2_center'].value - 2.5) < 0.2)

        for _, par in pars.items():
            assert len(repr(par)) > 5
    def test_composite_plotting(self):
        # test that a composite model has non-empty best_values
        pytest.importorskip("matplotlib")
        import matplotlib
        matplotlib.use('Agg')

        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')

        mod = model1 + model2
        pars = mod.make_params()

        values1 = dict(amplitude=7.10, center=1.1, sigma=2.40)
        values2 = dict(amplitude=12.2, center=2.5, sigma=0.5)
        data = (gaussian(x=self.x, **values1) + gaussian(x=self.x, **values2)
                + 0.1*self.noise)

        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1, max=1.5)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.6, min=2.0)
        pars['g2_amplitude'].set(1)

        result = mod.fit(data, params=pars, x=self.x)
        fig, ax = result.plot(show_init=True)

        assert isinstance(fig, matplotlib.figure.Figure)
        assert isinstance(ax, matplotlib.axes.GridSpec)

        comps = result.eval_components(x=self.x)
        assert len(comps) == 2
        assert 'g1_' in comps
Exemple #4
0
    def test_sum_of_two_gaussians(self):
        # two user-defined gaussians
        model1 = self.model
        f2 = lambda x, amp, cen, sig: gaussian(
            x, amplitude=amp, center=cen, sigma=sig)
        model2 = Model(f2)
        values1 = self.true_values()
        values2 = {'cen': 2.45, 'sig': 0.8, 'amp': 3.15}

        data = gaussian(x=self.x, **values1) + f2(x=self.x, **
                                                  values2) + self.noise / 3.0
        model = self.model + model2
        pars = model.make_params()
        pars['sigma'].set(value=2, min=0)
        pars['center'].set(value=1, min=0.2, max=1.8)
        pars['amplitude'].set(value=3, min=0)
        pars['sig'].set(value=1, min=0)
        pars['cen'].set(value=2.4, min=2, max=3.5)
        pars['amp'].set(value=1, min=0)

        true_values = dict(list(values1.items()) + list(values2.items()))
        result = model.fit(data, pars, x=self.x)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)

        # user-defined models with common parameter names
        # cannot be added, and should raise
        f = lambda: model1 + model1
        self.assertRaises(NameError, f)

        # two predefined_gaussians, using suffix to differentiate
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')
        model = model1 + model2
        true_values = {
            'g1_center': values1['center'],
            'g1_amplitude': values1['amplitude'],
            'g1_sigma': values1['sigma'],
            'g2_center': values2['cen'],
            'g2_amplitude': values2['amp'],
            'g2_sigma': values2['sig']
        }
        pars = model.make_params()
        pars['g1_sigma'].set(2)
        pars['g1_center'].set(1)
        pars['g1_amplitude'].set(3)
        pars['g2_sigma'].set(1)
        pars['g2_center'].set(2.4)
        pars['g2_amplitude'].set(1)

        result = model.fit(data, pars, x=self.x)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)

        # without suffix, the names collide and Model should raise
        model1 = models.GaussianModel()
        model2 = models.GaussianModel()
        f = lambda: model1 + model2
        self.assertRaises(NameError, f)
Exemple #5
0
def trfit2G(x, y, hints):
    model = models.GaussianModel(prefix='one_') + models.GaussianModel(
        prefix='two_')
    parnames = model.param_names
    pars = model.make_params()
    for j, n in enumerate(parnames):
        pars[n].set(value=hints[j], vary=True)
    result = model.fit(y, pars, x=x)
    print(result.fit_report())
    return result
Exemple #6
0
def histogram(hist_data, bins, minimum, maximum):
    """Method for fitting a Gaussian curve to the histogram data.
    
    Arguments:
        hist_data (array like): list or array containing the data for which to make a histogram.
        bins (int): ammount of bins for the histogram.
        minimum (float): the minimum value to contain in the histogram.
        maximum (float): the maximum value to contain in the histogram.

    Returns:
        The data for the histogram plot as well as the Gaussian curve plot.
    """
    hist_data2 = [x for x in hist_data if x <= maximum and x >= minimum]
    y, x = np.histogram(hist_data2, bins=bins)
    x_new = [((x[i] + x[i - 1]) / 2) for i in range(1, len(x))]
    max_freq = max(y)
    mean = x_new[y.argmax()]
    sigma = (x[1] - x[0]) * 4

    gauss = models.GaussianModel()
    fit = gauss.fit(y,
                    x=x_new,
                    center=mean,
                    amplitude=max_freq,
                    sigma=sigma,
                    nan_policy='omit')

    return x, y, x_new, fit.best_fit
Exemple #7
0
 def test_change_prefix(self):
     mod = models.GaussianModel(prefix='b')
     mod.prefix = 'c'
     params = mod.make_params()
     names = params.keys()
     all_begin_with_c = all([n.startswith('c') for n in names])
     self.assertTrue(all_begin_with_c)
def make_peak_model(settings):
    
    if settings.peak_model == "GaussDerivative":
        return lmfit_custom_models.GaussDerivativeModel()
    elif settings.peak_model == "Voigt": 
        return lmfit_models.PseudoVoigtModel()
    else:
        return lmfit_models.GaussianModel()
    def test_sum_composite_models(self):
        # test components of composite model created adding composite model
        model1 = models.GaussianModel(prefix='g1_')
        model2 = models.GaussianModel(prefix='g2_')
        model3 = models.GaussianModel(prefix='g3_')
        model4 = models.GaussianModel(prefix='g4_')

        model_total1 = (model1 + model2) + model3
        for mod in [model1, model2, model3]:
            self.assertTrue(mod in model_total1.components)

        model_total2 = model1 + (model2 + model3)
        for mod in [model1, model2, model3]:
            self.assertTrue(mod in model_total2.components)

        model_total3 = (model1 + model2) + (model3 + model4)
        for mod in [model1, model2, model3, model4]:
            self.assertTrue(mod in model_total3.components)
Exemple #10
0
    def test_model_with_prefix(self):
        # model with prefix of 'a' and 'b'
        mod = models.GaussianModel(prefix='a')
        vals = {'center': 2.45, 'sigma': 0.8, 'amplitude': 3.15}
        data = gaussian(x=self.x, **vals) + self.noise/3.0
        pars = mod.guess(data, x=self.x)
        self.assertTrue('aamplitude' in pars)
        self.assertTrue('asigma' in pars)
        out = mod.fit(data, pars, x=self.x)
        self.assertTrue(out.params['aamplitude'].value > 2.0)
        self.assertTrue(out.params['acenter'].value > 2.0)
        self.assertTrue(out.params['acenter'].value < 3.0)

        mod = models.GaussianModel(prefix='b')
        data = gaussian(x=self.x, **vals) + self.noise/3.0
        pars = mod.guess(data, x=self.x)
        self.assertTrue('bamplitude' in pars)
        self.assertTrue('bsigma' in pars)
Exemple #11
0
def fit_correlation(A, rr=None, ax=None):
    """ Fit a Gaussian + a constant to the horizontal and vertical cental 
    lineout cut of A. 
    
    Args:
        A: autocorrelation image
        rr: +/- number of pixel around the central point to consider. If None the entire 
            lineout is fitted
    """
    xx = A.shape[0] // 2
    yy = A.shape[1] // 2
    if rr is None:
        horiz = A[xx, :]
        vert = A[:, yy]
    else:
        horiz = A[xx, yy - rr:yy + rr]
        vert = A[xx - rr:xx + rr, yy]
    data = [vert, horiz]
    titles = ['vertical', 'horizontal']

    if ax is None:
        fig, ax = plt.subplots(nrows=2, figsize=(10, 10))

    for ii, dat in enumerate(data):
        center = np.where(np.isnan(dat))[0][0]

        gmodel = models.GaussianModel(
            nan_policy='omit') + models.ConstantModel(nan_policy='omit')
        params = gmodel.make_params()
        params['amplitude'].set(value=1.)
        params['sigma'].set(value=1.)
        params['center'].set(value=center)
        params['c'].set(value=1.)

        x = np.arange(dat.shape[0])
        res = gmodel.fit(
            dat, params, x=x,
            method='leastsq')  #, fit_kws={'ftol':1e-10, 'xtol':1e-10})

        xfit = np.arange(0, 2 * center, 0.1)
        ax[ii].plot(xfit,
                    res.eval(x=xfit),
                    color='purple',
                    linewidth=2,
                    label='sigma = {:.2f} +/- {:.2f}'.format(
                        res.params['sigma'].value, res.params['sigma'].stderr))
        ax[ii].plot(dat, 'o', color='orange')
        ax[ii].legend(loc='upper right')
        ax[ii].set_title(titles[ii])
        ax[ii].set_xlabel('Pixel')
        ax[ii].set_ylabel('Correlation')
        print(res.fit_report())
        print('\n')

    plt.tight_layout()
    plt.show()
    return res
Exemple #12
0
 def test_change_prefix(self):
     "should fail"
     mod = models.GaussianModel(prefix='b')
     set_prefix_failed = None
     try:
         mod.prefix = 'c'
         set_prefix_failed = False
     except AttributeError:
         set_prefix_failed = True
     except:
         set_prefix_failed = None
     self.assertTrue(set_prefix_failed)
Exemple #13
0
    def test_change_prefix(self):
        "should pass!"
        mod = models.GaussianModel(prefix='b')
        set_prefix_failed = None
        try:
            mod.prefix = 'c'
            set_prefix_failed = False
        except AttributeError:
            set_prefix_failed = True
        except Exception:
            set_prefix_failed = None
        self.assertFalse(set_prefix_failed)

        new_expr = mod.param_hints['fwhm']['expr']
        self.assertTrue('csigma' in new_expr)
        self.assertFalse('bsigma' in new_expr)
Exemple #14
0
    def test_hints_for_peakmodels(self):
        # test that height/fwhm do not cause asteval errors.

        x = np.linspace(-10, 10, 101)
        y = np.sin(x / 3) + x/100.

        m1 = models.LinearModel(prefix='m1_')
        params = m1.guess(y, x=x)

        m2 = models.GaussianModel(prefix='m2_')
        params.update(m2.make_params())

        _m = m1 + m2  # noqa: F841

        param_values = {name: p.value for name, p in params.items()}
        self.assertTrue(param_values['m1_intercept'] < -0.0)
        self.assertEqual(param_values['m2_amplitude'], 1)
Exemple #15
0
    def gaussian(self, oversample_multiplier=1, delta_rp=0, mz_overlay=1):
        '''
        Legacy gaussian lineshape analysis function
        '''

        # check if MSPeak contains the resolving power info
        if self.resolving_power:
            # full width half maximum distance
            self.fwhm = (self.mz_exp / (self.resolving_power + delta_rp)
                         )  #self.resolving_power)

            # stardart deviation
            sigma = self.fwhm / (2 * sqrt(2 * log(2)))

            # half width baseline distance
            #hw_base_distance = (3.2 * s)

            #match_loz_factor = 3

            #n_d = hw_base_distance * match_loz_factor

            #mz_domain = linspace(
            #    self.mz_exp - n_d, self.mz_exp + n_d, datapoint)

            mz_domain = self.get_mz_domain(oversample_multiplier, mz_overlay)

            # gaussian_pdf = lambda x0, x, s: (1/ math.sqrt(2*math.pi*math.pow(s,2))) * math.exp(-1 * math.pow(x-x0,2) / 2*math.pow(s,2) )

            #calc_abundance = norm.pdf(mz_domain, self.mz_exp, s)

            model = models.GaussianModel()

            amplitude = (sqrt(2 * pi) * sigma) * self.abundance

            params = model.make_params(center=self.mz_exp,
                                       amplitude=amplitude,
                                       sigma=sigma)

            calc_abundance = model.eval(params=params, x=mz_domain)

            return mz_domain, calc_abundance

        else:
            raise LookupError(
                'resolving power is not defined, try to use set_max_resolving_power()'
            )
Exemple #16
0
def get_model(model_name, model_prefix=''):
    if model_name == 'voigt':
        mdl = models.VoigtModel(prefix=model_prefix)
    elif model_name == 'gauss':
        mdl = models.GaussianModel(prefix=model_prefix)
    elif model_name == 'constant':
        mdl = models.ConstantModel(prefix=model_prefix)
    elif model_name == 'linear':
        mdl = models.LinearModel(prefix=model_prefix)
    elif model_name == 'exp':
        mdl = models.ExponentialModel(prefix=model_prefix)
    elif model_name == 'logistic':
        mdl = models.StepModel(prefix=model_prefix, form='logistic')
    elif model_name == 'sine':
        mdl = models.SineModel(prefix=model_prefix)
    else:
        raise ValueError('Model name not recognized.')

    return mdl
Exemple #17
0
def test_guess_modelparams():
    """Tests for the 'guess' function of built-in models."""
    x = np.linspace(-10, 10, 501)

    mod = models.ConstantModel()
    y = 6.0 + x*0.005
    pars = mod.guess(y)
    assert_allclose(pars['c'].value, 6.0, rtol=0.01)

    mod = models.ComplexConstantModel(prefix='f_')
    y = 6.0 + x*0.005 + (4.0 - 0.02*x)*1j
    pars = mod.guess(y)
    assert_allclose(pars['f_re'].value, 6.0, rtol=0.01)
    assert_allclose(pars['f_im'].value, 4.0, rtol=0.01)

    mod = models.QuadraticModel(prefix='g_')
    y = -0.2 + 3.0*x + 0.005*x**2
    pars = mod.guess(y, x=x)
    assert_allclose(pars['g_a'].value, 0.005, rtol=0.01)
    assert_allclose(pars['g_b'].value, 3.0, rtol=0.01)
    assert_allclose(pars['g_c'].value, -0.2, rtol=0.01)

    mod = models.PolynomialModel(4, prefix='g_')
    y = -0.2 + 3.0*x + 0.005*x**2 - 3.3e-6*x**3 + 1.e-9*x**4
    pars = mod.guess(y, x=x)
    assert_allclose(pars['g_c0'].value, -0.2, rtol=0.01)
    assert_allclose(pars['g_c1'].value, 3.0, rtol=0.01)
    assert_allclose(pars['g_c2'].value, 0.005, rtol=0.1)
    assert_allclose(pars['g_c3'].value, -3.3e-6, rtol=0.1)
    assert_allclose(pars['g_c4'].value, 1.e-9, rtol=0.1)

    mod = models.GaussianModel(prefix='g_')
    y = lineshapes.gaussian(x, amplitude=2.2, center=0.25, sigma=1.3)
    y += np.random.normal(size=len(x), scale=0.004)
    pars = mod.guess(y, x=x)
    assert_allclose(pars['g_amplitude'].value, 3, rtol=2)
    assert_allclose(pars['g_center'].value, 0.25, rtol=1)
    assert_allclose(pars['g_sigma'].value, 1.3, rtol=1)

    mod = models.LorentzianModel(prefix='l_')
    pars = mod.guess(y, x=x)
    assert_allclose(pars['l_amplitude'].value, 3, rtol=2)
    assert_allclose(pars['l_center'].value, 0.25, rtol=1)
    assert_allclose(pars['l_sigma'].value, 1.3, rtol=1)

    mod = models.SplitLorentzianModel(prefix='s_')
    pars = mod.guess(y, x=x)
    assert_allclose(pars['s_amplitude'].value, 3, rtol=2)
    assert_allclose(pars['s_center'].value, 0.25, rtol=1)
    assert_allclose(pars['s_sigma'].value, 1.3, rtol=1)
    assert_allclose(pars['s_sigma_r'].value, 1.3, rtol=1)

    mod = models.VoigtModel(prefix='l_')
    pars = mod.guess(y, x=x)
    assert_allclose(pars['l_amplitude'].value, 3, rtol=2)
    assert_allclose(pars['l_center'].value, 0.25, rtol=1)
    assert_allclose(pars['l_sigma'].value, 1.3, rtol=1)

    mod = models.SkewedVoigtModel(prefix='l_')
    pars = mod.guess(y, x=x)
    assert_allclose(pars['l_amplitude'].value, 3, rtol=2)
    assert_allclose(pars['l_center'].value, 0.25, rtol=1)
    assert_allclose(pars['l_sigma'].value, 1.3, rtol=1)
Exemple #18
0
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from lmfit import models

spectrum_cs = pd.read_csv('Cs137_spectrum.csv')
spectrum_cs['y_err'] = np.sqrt(spectrum_cs['counts'])

sel1 = spectrum_cs.query('pulseheight >= 1000 and pulseheight <= 1500')

model = models.GaussianModel() + models.LinearModel()
fit = model.fit(sel1['counts'], x=sel1['pulseheight'], weights=1/sel1['y_err'], center=1200, slope=0)
# fit.plot(numpoints=100)
center_cs = fit.params['center']
# print(center_cs.value, center_cs.stderr)

spectrum_na = pd.read_csv('Na22_spectrum.csv')
spectrum_na['y_err'] = np.sqrt(spectrum_na['counts'])

sel2 = spectrum_na.query('pulseheight >= 800 and pulseheight <= 1200')

fit2 = model.fit(sel2['counts'], x=sel2['pulseheight'], weights=1/sel2['y_err'], center=980, sigma=40, amplitude=1000, slope=0)
# fit2.plot(numpoints=100)
center_na_1 = fit2.params['center']
# print(center_na_1.value, center_na_1.stderr)

sel3 = spectrum_na.query('pulseheight >= 2200 and pulseheight <= 2700')

fit3 = model.fit(sel3['counts'], x=sel3['pulseheight'], weights=1/sel3['y_err'], center=2400, sigma=40, amplitude=110, slope=0)
# fit3.plot(numpoints=100)
center_na_2 = fit3.params['center']
Exemple #19
0
    def fit_peak(self, mz_extend=6, delta_rp=0, model='Gaussian'):
        '''
        Model and fit peak lineshape by defined function - using lmfit module
        Do not oversample/resample/interpolate data points 
        Better to go back to time domain and perform more zero filling
        Models allowed: Gaussian, Lorentz, Voigt
        Returns the calculated mz domain, initial defined abundance profile, and the fit peak results object from lmfit module
        mz_extend here extends the x-axis domain so that we have sufficient points either side of the apex to fit.
        Takes about 10ms per peak
        '''
        start_index = self.start_scan - mz_extend if not self.start_scan == 0 else 0
        final_index = self.final_scan + mz_extend if not self.final_scan == len(
            self._ms_parent.mz_exp_profile) else self.final_scan

        # check if MSPeak contains the resolving power info
        if self.resolving_power:
            # full width half maximum distance
            self.fwhm = (self.mz_exp / (self.resolving_power + delta_rp))

            mz_domain = self._ms_parent.mz_exp_profile[start_index:final_index]
            abundance_domain = self._ms_parent.abundance_profile[
                start_index:final_index]

            if model == 'Gaussian':
                # stardard deviation
                sigma = self.fwhm / (2 * sqrt(2 * log(2)))
                amplitude = (sqrt(2 * pi) * sigma) * self.abundance
                model = models.GaussianModel()
                params = model.make_params(center=self.mz_exp,
                                           amplitude=amplitude,
                                           sigma=sigma)

            elif model == 'Lorentz':
                # stardard deviation
                sigma = self.fwhm / 2
                amplitude = sigma * pi * self.abundance
                model = models.LorentzianModel()
                params = model.make_params(center=self.mz_exp,
                                           amplitude=amplitude,
                                           sigma=sigma)

            elif model == 'Voigt':
                # stardard deviation
                sigma = self.fwhm / 3.6013
                amplitude = (sqrt(2 * pi) * sigma) * self.abundance
                model = models.VoigtModel()
                params = model.make_params(center=self.mz_exp,
                                           amplitude=amplitude,
                                           sigma=sigma,
                                           gamma=sigma)
            else:
                raise LookupError('model lineshape not known or defined')

            #calc_abundance = model.eval(params=params, x=mz_domain) #Same as initial fit, returned in fit_peak object
            fit_peak = model.fit(abundance_domain, params=params, x=mz_domain)
            return mz_domain, fit_peak

        else:
            raise LookupError(
                'resolving power is not defined, try to use set_max_resolving_power()'
            )
Exemple #20
0
 def test_model_name(self):
     # test setting the name for built-in models
     mod = models.GaussianModel(name='user_name')
     self.assertEqual(mod.name, "Model(user_name)")
Exemple #21
0
def model_gen(V_series, dQdV_series, cd, i, cyc, thresh):
    """Develops initial model and parameters for battery data fitting.
    V_series = Pandas series of voltage data
    dQdV_series = Pandas series of differential capacity data
    cd = either 'c' for charge and 'd' for discharge.
    i = list of peak indices found by peak finder
    Output:
    par = lmfit parameters object
    mod = lmfit model object"""

    # generates numpy arrays for use in fitting
    sigx_bot, sigy_bot = cd_dataframe(V_series, dQdV_series, cd)
    if len(sigx_bot) > 5 and sigx_bot[5] > sigx_bot[1]:
        # check if the voltage values are increasing - the right order for
        # gaussian
        sigx_bot_new = sigx_bot
        sigy_bot_new = sigy_bot
        newi = i
    else:
        sigx_bot_new = sigx_bot[::-1]
        # reverses the order of elements in the array
        sigy_bot_new = sigy_bot[::-1]
        newi = np.array([], dtype=int)
        for elem in i:
            # append a new index, because now everything is backwards
            newi = np.append(newi, int(len(sigx_bot_new) - elem - 1))
    if all(newi) is False or len(newi) < 1:
        base_mod = models.GaussianModel(prefix='base_')
        mod = base_mod
        par = mod.make_params()
    else:
        # have to convert from inputted voltages to indices of peaks within
        # sigx_bot
        user_appended_ind = []
        rev_user_append = []
        if not isinstance(i, list):
            i = i.tolist()
        if not isinstance(newi, list):
            newi = newi.tolist()
        count = 0
        for index in newi:

            # generates unique parameter strings based on index of peak
            center, sigma, amplitude, fraction, comb = label_gen(index)
            # generates a pseudo voigt fitting model
            gaus_loop = models.PseudoVoigtModel(prefix=comb)
            if count == 0:
                mod = gaus_loop
                par = mod.make_params()
                count = count + 1
            else:
                mod = mod + gaus_loop
                par.update(gaus_loop.make_params())
                count = count + 1
            par[center].set(sigx_bot_new[index], vary=False)
            par[sigma].set((np.max(sigx_bot_new) - np.min(sigx_bot_new)) / 100)
            par[amplitude].set((np.mean(sigy_bot_new)) / 50, min=0)
            par[fraction].set(.5, min=0, max=1)

    # then add the gaussian after the peaks
        base_mod = models.GaussianModel(prefix='base_')
        mod = mod + base_mod
        base_par = base_mod.make_params()
        base_par['base_amplitude'].set(np.mean(sigy_bot_new))
        # these are initial guesses for the base
        base_par['base_center'].set(np.mean(sigx_bot_new))
        base_par['base_sigma'].set(
            (np.max(sigx_bot_new) - np.min(sigx_bot_new)) / 2)
        par.update(base_par)
    return par, mod, i
Exemple #22
0
    def model_gen(V_series, dQdV_series, cd, i, cyc, v_toappend, thresh):
        """Develops initial model and parameters for battery data fitting.
        V_series = Pandas series of voltage data
        dQdV_series = Pandas series of differential capacity data
        cd = either 'c' for charge and 'd' for discharge.
        v_toappend is the list of voltages to append to the peak indices 
        Output:
        par = lmfit parameters object
        mod = lmfit model object"""

        
        # generates numpy arrays for use in fitting
        sigx_bot, sigy_bot = fitters.cd_dataframe(V_series, dQdV_series, cd)
        if len(sigx_bot)>5 and sigx_bot[5]>sigx_bot[1]:
            # check if the voltage values are increasing - the right order for gaussian
            sigx_bot_new = sigx_bot
            sigy_bot_new = sigy_bot
            newi = i
        else:
            sigx_bot_new = sigx_bot[::-1] # reverses the order of elements in the array
            sigy_bot_new = sigy_bot[::-1]
            newi = np.array([], dtype = int)
            for elem in i:
                # append a new index, because now everything is backwards
                newi = np.append(newi, int(len(sigx_bot_new) - elem - 1))

        # creates a polynomial fitting object
        # prints a notice if no peaks are found
        if all(newi) is False or len(newi) < 1:
            notice = 'Cycle ' + str(cyc) + cd + \
                ' in battery ' + ' has no peaks.'
            print(notice)
            base_mod = models.GaussianModel(prefix = 'base_')
            mod = base_mod
            # changed from PolynomialModel to Gaussian on 10-10-18
            # Gaussian params are A, mew, and sigma
            # sets polynomial parameters based on a
            # guess of a polynomial fit to the data with no peaks
            #mod.set_param_hint('base_amplitude', min = 0)
            #mod.set_param_hint('base_sigma', min = 0.001)
            par = mod.make_params()
        # iterates over all peak indices
        else:
            # have to convert from inputted voltages to indices of peaks within sigx_bot
            user_appended_ind = []
            rev_user_append = []
            if len(v_toappend) > 0: 
                for vapp in v_toappend:
                    if sigx_bot.min()<=vapp<=sigx_bot.max():
                        #check if voltage given is valid
                        ind_app= np.where(np.isclose(sigx_bot, float(vapp), atol = 0.1))[0][0]
                        user_appended_ind.append(ind_app)
                        rev_user_app = np.where(np.isclose(sigx_bot_new, float(vapp), atol = 0.1))[0][0]
                        rev_user_append.append(rev_user_app)
                    # this gives a final list of user appended indices 
                i = i.tolist() + user_appended_ind
                newi = newi.tolist() + rev_user_append # combine the two lists of indices to get the final set of peak locations
            else:
                i = i.tolist()
                newi = newi.tolist()
            count = 0
            for index in newi:

                # generates unique parameter strings based on index of peak
                center, sigma, amplitude, fraction, comb = fitters.label_gen(
                    index)
                # generates a pseudo voigt fitting model
                gaus_loop = models.PseudoVoigtModel(prefix=comb)
                if count == 0:
                    mod = gaus_loop 
                    #mod.set_param_hint(amplitude, min = 0.001)
                    par = mod.make_params()
                    #par = mod.guess(sigy_bot_new, x=sigx_bot_new)
                    count = count + 1
                else: 
                    mod = mod + gaus_loop
                    #gaus_loop.set_param_hint(amplitude, min = 0.001)
                    par.update(gaus_loop.make_params())
                    count = count + 1 

                # uses unique parameter strings to generate parameters
                # with initial guesses
                # in this model, the center of the peak is locked at the
                # peak location determined from PeakUtils
                par[center].set(sigx_bot_new[index], vary=False)
                    # don't allow the centers of the peaks found by peakutsils to vary 
                par[sigma].set((np.max(sigx_bot_new)-np.min(sigx_bot_new))/100)
                par[amplitude].set((np.mean(sigy_bot_new))/50, min=0)
                par[fraction].set(.5, min=0, max=1)

        # then add the gaussian after the peaks
            base_mod = models.GaussianModel(prefix = 'base_')
            mod = mod + base_mod
            base_par = base_mod.make_params()
            base_par['base_amplitude'].set(np.mean(sigy_bot_new))
            # these are initial guesses for the base
            base_par['base_center'].set(np.mean(sigx_bot_new))
            base_par['base_sigma'].set((np.max(sigx_bot_new)-np.min(sigx_bot_new))/2)
            # changed from PolynomialModel to Gaussian on 10-10-18
            # Gaussian params are A, mew, and sigma
            # sets polynomial parameters based on a
            # guess of a polynomial fit to the data with no peaks
            #base_mod.set_param_hint('base_amplitude', min = 0)
            #base_mod.set_param_hint('base_sigma', min = 0.001)
            par.update(base_par)
        #mod.set_param_hint('base_height', min = 0, max = 0.01) 

        #par = mod.guess(sigy_bot_new, x=sigx_bot_new)
        #print(cyc)
        return par, mod, i
Exemple #23
0
 def fit_peak(self,
              roi=None,
              xpeak=None,
              sigma_guess=None,
              model_name='gauss-erf-const',
              **kwargs):
     """
     Main routine
     """
     # Exit if no roi
     if roi is None:
         self.fit = None
         self.model_name = None
     else:
         self.model_name = model_name
         # Start timer
         tic = time.time()
         # ---------
         # Setup ROI
         # ---------
         self.set_roi(roi)
         x = self.get_x_roi()
         y = self.get_y_roi()
         y_sig = self.get_y_sig_roi()
         x_widths = self.get_x_widths_roi()
         # ---------------------------
         # Guesses based on input data
         # ---------------------------
         # Set peak center to center of ROI if not given
         if xpeak is None:
             xpeak = (x[0] + x[-1]) / 2.
         # Guess sigma if not provided
         if sigma_guess is None:
             fwhm_guess = self.guess_fwhm(xpeak)
             sigma_guess = fwhm_guess / FWHM_SIG_RATIO
         # Heights at the sides of the ROI
         left_shelf_height = y[0]
         right_shelf_height = y[-1]
         # Line guess
         lin_slope = (y[-1] - y[0]) / (x[-1] - x[0])
         lin_intercept = y[0] - lin_slope * x[0]
         # Two peaks guess (33 and 66 percent through ROI)
         xpeak0 = x[0] + (x[-1] - x[0]) * 0.33
         xpeak1 = x[0] + (x[-1] - x[0]) * 0.66
         # Index of at the ROI center
         ix_half = int(round(float(len(x)) / 2.))
         # -------------------
         # Setup fitting model
         # -------------------
         if model_name == 'gauss-erf-const':
             # Models
             erf_mod = models.StepModel(form='erf', prefix='erf_')
             gauss_mod = models.GaussianModel(prefix='gauss_')
             bk_mod = models.ConstantModel(prefix='bk_')
             # Initialize parameters
             pars = erf_mod.make_params()
             pars.update(gauss_mod.make_params())
             pars.update(bk_mod.make_params())
             # Erfc (sigma and center are locked to gauss below)
             pars['erf_amplitude'].set(right_shelf_height -
                                       left_shelf_height,
                                       max=0.)
             # Gauss
             pars['gauss_center'].set(
                 xpeak
             )  # , min=xpeak - 2 * fwhm_guess, max=xpeak + 2 * fwhm_guess)
             pars['gauss_sigma'].set(sigma_guess)
             pars['gauss_amplitude'].set(np.sum(y * x_widths), min=0)
             # Background
             pars['bk_c'].set(left_shelf_height, min=0.)
             # Same center and sigma
             pars.add('erf_center', expr='gauss_center')
             pars.add('erf_sigma',
                      expr='gauss_sigma * {}'.format(FWHM_SIG_RATIO))
             self.model = gauss_mod + erf_mod + bk_mod
         elif model_name == 'double-gauss-line':
             # Models
             lin_mod = models.LinearModel(prefix='lin_')
             g0_mod = models.GaussianModel(prefix='gauss0_')
             g1_mod = models.GaussianModel(prefix='gauss1_')
             # Initialize parameters
             pars = lin_mod.make_params()
             pars.update(g0_mod.make_params())
             pars.update(g1_mod.make_params())
             # Line (background)
             pars['lin_slope'].set(lin_slope, max=0.)
             pars['lin_intercept'].set(lin_intercept)
             # Gauss 0 (left)
             pars['gauss0_center'].set(
                 xpeak0
             )  # , min=xpeak - 2 * fwhm_guess, max=xpeak + 2 * fwhm_guess)
             pars['gauss0_sigma'].set(sigma_guess)
             pars['gauss0_amplitude'].set(np.sum(y[:ix_half] *
                                                 x_widths[:ix_half]),
                                          min=0)
             # Gauss 1 (right)
             pars['gauss1_center'].set(
                 xpeak1
             )  # , min=xpeak - 2 * fwhm_guess, max=xpeak + 2 * fwhm_guess)
             pars['gauss1_sigma'].set(sigma_guess)
             pars['gauss1_amplitude'].set(np.sum(y[ix_half:] *
                                                 x_widths[ix_half:]),
                                          min=0)
             self.model = lin_mod + g0_mod + g1_mod
         else:
             raise NotImplementedError(
                 'Model ({}) not recognized'.format(model_name))
         # -----------
         # Perform fit
         # -----------
         try:
             self.fit = self.model.fit(y, pars, x=x, weights=1. / y_sig)
         except:
             print("[ERROR] Couldn't fit peak")
             self.fit = None
         if self.verbosity > 0:
             print('Fit time: {:.3f} seconds'.format(time.time() - tic))
Exemple #24
0
    def gaussian_fit(self):
        """Method for fitting a gaussian curve to the spectrum of possible quantum dots.
        
        Returns:
            A data frame containing the spectrum of a quantum dot as well as the gaussian curve plot data for that quantum dot.
            This method also returns a data frame with the fit statistics of all the fits.
        """

        self.df5 = pd.DataFrame(columns=[
            'Slit Number', 'Centre', 'Centre_err', 'Sigma', 'Sigma_err',
            'FWHM', 'FWHM_err', 'Height', 'Height_err'
        ])
        QDot_slits = self.QDot_detection()

        if len(QDot_slits) > 0:
            self.plot_data = pd.DataFrame(columns=[f"{QDot_slits[0]}"],
                                          index=self.energies)
        else:
            self.plot_data = pd.DataFrame(index=self.energies)

        for slit_number in QDot_slits:
            sel = self.df4[f'{slit_number}']
            self.plot_data[f'{slit_number}'] = sel

            # Makes a good first guess for the fit values of the gaussian
            max_intensity = max(sel)
            central_energy = sel[sel == max_intensity].index.values
            central_energy = central_energy[0]

            # Fits a gaussian model to the selected data and shows the output
            gauss = models.GaussianModel()
            fit = gauss.fit(sel,
                            x=self.energies,
                            weights=1 / np.sqrt(sel),
                            center=central_energy,
                            amplitude=max_intensity,
                            sigma=1,
                            nan_policy='omit')

            self.plot_data[f'{slit_number} best fit'] = fit.best_fit

            # Appends the fit data for the variables to a new dataframe and shows the fit results with errors
            fit_variables = [slit_number]
            for key in fit.params:
                if key in ['center', 'sigma', 'fwhm', 'height']:
                    fit_variables.append(fit.params[key].value)
                    fit_variables.append(fit.params[key].stderr)

            self.df5 = self.df5.append(
                {
                    'Slit Number': fit_variables[0],
                    'Centre': fit_variables[1],
                    'Centre_err': fit_variables[2],
                    'Sigma': fit_variables[3],
                    'Sigma_err': fit_variables[4],
                    'FWHM': fit_variables[5],
                    'FWHM_err': fit_variables[6],
                    'Height': fit_variables[7],
                    'Height_err': fit_variables[8]
                },
                ignore_index=True)

        return self.plot_data, self.df5
Exemple #25
0
def fit_gaussian(data,
                 bins,
                 ax,
                 labels=True,
                 basecolor='red',
                 xy=(0, 0.9),
                 gamma=-0.5):
    ###########################################
    """
    Fit a Gaussian distribution to wind speed data
    paramters:
    data - input wind speed data to fit
    ax - axis to plot onto
    bins - x locations of bins from histogram
    """

    colors = utils.get_nrelcolors()

    if basecolor == 'red':
        pcolor = colors['red'][1]
    elif basecolor is 'blue':
        pcolor = colors['blue'][0]
    else:
        pcolor = 'k'

    # get x and y data
    yvals, xvals = np.histogram(data, bins=bins)
    # center x values
    xvals = np.array([(xvals[i] + xvals[i + 1]) / 2
                      for i in range(len(xvals) - 1)])

    model = lmfmodels.GaussianModel()

    # set initial parameter values
    params = model.make_params(amplitude=10,
                               center=data.mean(),
                               sigma=data.std(),
                               gamma=gamma)

    # adjust parameters  to best fit data.
    result = model.fit(yvals, params, x=xvals)
    fitdat = result.best_fit / len(data)

    ax.plot(xvals,
            result.best_fit * 1.0 / float(len(data)),
            color=pcolor,
            linewidth=2.5)
    if labels is True:

        # gamma = np.round(result.params['gamma'].value,2)
        sigma = np.round(result.params['sigma'].value, 2)
        center = np.round(result.params['center'].value, 2)
        amp = np.round(result.params['amplitude'].value, 2)

        if gamma > 0:
            xcoord = 0.95
        else:
            xcoord = 0.05
        if xy[0] > 1:
            xcoord = 0

        xy = (xcoord + xy[0], xy[1])
        ax.annotate(
            s='$A = {}$\n$\mu = {}$\n$\gamma = {}$\n$\sigma = {}$'.format(
                amp, center, gamma, sigma),
            xy=xy,
            xycoords='axes fraction',
            ha='right',
            va='top')
Exemple #26
0
lCounts = np.array([])
lEnergy = np.array([])
lPicked = np.array([])
scanNo = 6386
date = 20
picked = 0

#marcroFilename = "C:\\Users\\wvx67826\\Desktop\\beam8 data\\MapNight2.txt"
energyCalFilename = "C:\\Users\\wvx67826\\Desktop\\beam8 data\\energycalibration_Ru.dat"
backgroundFilename = "C:\\Users\\wvx67826\\Desktop\\beam8 data\\backgound_Flux.dat"
folderName = "C:\\Users\\wvx67826\\Desktop\\beam8 data\\2019 12 %s\\" %date
metaFilename = folderName +"CCD Scan %i\\C_%i-AI.txt" %(scanNo,scanNo)
Rd.read_file(metaFilename, metaStopKey = str(scanNo))
metaData = Rd.get_data()
from lmfit import models
model_1 = models.GaussianModel(prefix='peak_')
model_2 = models.LinearModel(prefix='background_')
model = model_1 + model_2 


#print np.full((1,50),macroData["BL 8 Energy"][0])

def onpick(event):
    thisline = event.artist
    xdata = thisline.get_xdata()
    ydata = thisline.get_ydata()
    ind = event.ind
    
    points = np.array([xdata[ind]])
    
    global lPicked
Exemple #27
0
def test_height_and_fwhm_expression_evalution_in_builtin_models():
    """Assert models do not throw an ZeroDivisionError."""
    mod = models.GaussianModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9)
    params.update_constraints()

    mod = models.LorentzianModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9)
    params.update_constraints()

    mod = models.SplitLorentzianModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, sigma_r=1.0)
    params.update_constraints()

    mod = models.VoigtModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, gamma=1.0)
    params.update_constraints()

    mod = models.PseudoVoigtModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, fraction=0.5)
    params.update_constraints()

    mod = models.MoffatModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, beta=0.0)
    params.update_constraints()

    mod = models.Pearson7Model()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, expon=1.0)
    params.update_constraints()

    mod = models.StudentsTModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9)
    params.update_constraints()

    mod = models.BreitWignerModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, q=0.0)
    params.update_constraints()

    mod = models.LognormalModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9)
    params.update_constraints()

    mod = models.DampedOscillatorModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9)
    params.update_constraints()

    mod = models.DampedHarmonicOscillatorModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, gamma=0.0)
    params.update_constraints()

    mod = models.ExponentialGaussianModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, gamma=0.0)
    params.update_constraints()

    mod = models.SkewedGaussianModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, gamma=0.0)
    params.update_constraints()

    mod = models.SkewedVoigtModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, gamma=0.0,
                             skew=0.0)
    params.update_constraints()

    mod = models.DoniachModel()
    params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, gamma=0.0)
    params.update_constraints()

    mod = models.StepModel()
    for f in ('linear', 'arctan', 'erf', 'logistic'):
        params = mod.make_params(amplitude=1.0, center=0.0, sigma=0.9, form=f)
        params.update_constraints()

    mod = models.RectangleModel()
    for f in ('linear', 'arctan', 'erf', 'logistic'):
        params = mod.make_params(amplitude=1.0, center1=0.0, sigma1=0.0,
                                 center2=0.0, sigma2=0.0, form=f)
        params.update_constraints()
Exemple #28
0
def fitData(x, y):
    peaks, _ = signal.find_peaks(y, height=0.01, width=5)

    print peaks
    model_1 = models.GaussianModel(prefix='m1_')
    model_2 = models.GaussianModel(prefix='m2_')
    model_3 = models.GaussianModel(prefix='m3_')
    model_4 = models.LinearModel(prefix='l3_')
    model_5 = models.LorentzianModel(prefix='m4_')

    model = model_1 + model_2 + model_3 + model_4 + model_5

    model_1.set_param_hint("amplitude", min=0.002, max=0.1)
    model_1.set_param_hint("sigma", min=0.00, max=0.025)
    model_1.set_param_hint("center",
                           min=x[peaks[1]] - 0.05,
                           max=x[peaks[1]] + 0.05)
    params_1 = model_1.make_params(amplitude=0.05,
                                   center=x[peaks[1]],
                                   sigma=0.01)

    model_2.set_param_hint("amplitude", min=1e-5, max=1e-3)
    model_2.set_param_hint("sigma", min=0.0005, max=0.08)
    model_2.set_param_hint("center",
                           min=x[peaks[2]] - 0.075,
                           max=x[peaks[2]] + 0.075)
    params_2 = model_2.make_params(amplitude=0.005,
                                   center=x[peaks[2]],
                                   sigma=0.03)

    model_3.set_param_hint("amplitude", min=1e-6, max=1e-2)
    model_3.set_param_hint("sigma", min=0.005, max=0.08)
    model_3.set_param_hint("center",
                           min=x[peaks[1]] - 0.05,
                           max=x[peaks[1]] + 0.1)
    params_3 = model_3.make_params(amplitude=1e-3,
                                   center=x[peaks[1]] + 0.040,
                                   sigma=0.04)
    """    model_4.set_param_hint("intercept", min = 1e-15, max = np.min(y)*1.5)
    model_4.set_param_hint("slope", min = 1e-16)"""
    params_4 = model_4.make_params(slope=1e-9, intercept=np.min(y))

    model_5.set_param_hint("amplitude", min=1e-6, max=0.06)
    model_5.set_param_hint("sigma", min=0.00, max=0.025)
    model_5.set_param_hint("center",
                           min=x[peaks[0]] - 0.05,
                           max=x[peaks[0]] + 0.05)
    params_5 = model_5.make_params(amplitude=0.05,
                                   center=x[peaks[0]],
                                   sigma=0.01)

    params_1.update(params_2)
    params_1.update(params_3)
    params_1.update(params_4)
    params_1.update(params_5)

    params = params_1

    output = model.fit(y, params, x=x)
    print output.fit_report()
    output.plot(data_kws={'markersize': 1})
    plt.plot(x, y)
    plt.semilogy()
    plt.show(block=False)

    return output