Exemplo n.º 1
0
    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
Exemplo n.º 2
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
Exemplo n.º 3
0
    def test_user_defined_gaussian_plus_constant(self):
        data = self.data + 5.0
        model = self.model + models.ConstantModel()
        guess = self.guess()
        pars = model.make_params(c=10.1, **guess)
        true_values = self.true_values()
        true_values['c'] = 5.0

        result = model.fit(data, pars, x=self.x)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)
Exemplo n.º 4
0
    def test_composite_with_expression(self):
        expression_model = models.ExpressionModel("exp(-x/x0)", name='exp')
        amp_model = models.ConstantModel(prefix='amp_')
        off_model = models.ConstantModel(prefix='off_', name="off")

        comp_model = off_model + amp_model * expression_model

        x = self.x
        true_values = self.true_values()
        data = comp_model.eval(x=x, **true_values) + self.noise
        # data = 0.25 + 1 * np.exp(-x / 2.)

        params = comp_model.make_params(**self.guess())

        result = comp_model.fit(data, x=x, params=params)
        assert_results_close(result.values, true_values, rtol=0.01, atol=0.01)

        data_components = comp_model.eval_components(x=x)
        self.assertIn('exp', data_components)
Exemplo n.º 5
0
    def diagnostic(self):
        ###---------------------------------------------------------------------
        self.read_param()
        self.reduction()

        print 'Fit the input data'

        model = lfm.ConstantModel()
        param = model.make_params()

        for name in model.param_names:
            param.add(name,
                      vary=True,
                      value=self.parval,
                      min=self.parmin,
                      max=self.parmax)

        result = model.fit(x=self.xd,
                           data=self.yd,
                           weights=self.ye**(-1),
                           params=param,
                           method='leastsq')
        chisqr = result.chisqr
        dgfrdm = result.nfree  #d.o.f.
        redchi = result.redchi
        prbrty = TMath.Prob(chisqr, dgfrdm)  #p-value

        log = open(self.flogfl, 'w')
        log.write(
            "--------------------------------------------------------------------\n"
        )
        log.write(result.fit_report())
        #log.write("[[Confidence Intervals]]\n")
        #log.write(result.ci_report())
        log.write("\n")
        log.write(
            "--------------------------------------------------------------------\n"
        )
        log.write(" Chi-squared value / d.o.f. = %.5f / %d\n" %
                  (chisqr, dgfrdm))
        log.write(" Reduced Chi-squared value  = %.5f\n" % (redchi))
        log.write(" p-value                    = %7.5e\n" % (prbrty))
        log.write("\n")
        log.close()
        print 'Fitting results were recorded to %s.' % (self.flogfl)
Exemplo n.º 6
0
def fit_spectrum(x, y, num_resonances):
    """
    Iteratively identifies canditate resonances, performs a least-squares regression,
    and removes the identified resonance from the data. This function is `dumb'
    in the sense that it abdicates responsibility for hypothesis testing.

    Having both find_resonance and find_resonances might be a bad naming convention.

    Args:
        x (numpy.ndarray): A one-dimensional real-valued numpy array, the frequency domain variable.
        y (numpy.ndarray): A one-dimensional real-valued numpy array, the signal variable.
        num_resonances (type): Description of parameter `num_resonances`.

    Returns:
        type: Description of returned object.

    """

    # First pass, picking out resonances one-by-one.
    # Build model for whole spectrum along the way.
    resonance_fit_results = []
    spectrum_model = models.ConstantModel()
    y_copy = y
    for i in range(num_resonances):
        resonance_fit_results.append(find_resonance(x, y_copy))
        y_copy = remove_resonance_from_data(y_copy, resonance_fit_results[-1])

        # Make a Lorentzian model for each resonance, with prefixes for proper name-mangling.
        lorentzian_model = models.LorentzianModel()
        lorentzian_model.prefix = '_' + str(i) + '_'
        spectrum_model += lorentzian_model

    # Sum up all the offsets from each resonance model
    net_offset = sum(resonance_fit_results[i].params['c'].value for i in range(num_resonances))
    # Build a dict of all the Lorentzian parameters
    lorentzian_params = {}
    for i in range(num_resonances):
        lorentzian_params['_' + str(i) + '_amplitude'] = resonance_fit_results[i].params['amplitude'].value
        lorentzian_params['_' + str(i) + '_center'] = resonance_fit_results[i].params['center'].value
        lorentzian_params['_' + str(i) + '_sigma'] = resonance_fit_results[i].params['sigma'].value
    # And re-adjust the best fit.
    spectrum_fit_result = spectrum_model.fit(y, x=x, c=net_offset, **lorentzian_params)
    return spectrum_fit_result
Exemplo n.º 7
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
Exemplo n.º 8
0
    def __init__(self, independent_vars=['x'], prefix='', nan_policy='raise',
                 name=None, num_resonances=1, **kwargs):

        kwargs.update({'prefix': prefix, 'nan_policy': nan_policy,
                       'independent_vars': independent_vars})

        # This method might be a little bit kludgy. I'm guessing there's a more
        # pythonic way to achieve the same end.
        constant_model = models.ConstantModel(**kwargs)

        # Creates a sequence of LorentzianModel objects with prefixes `_i_`, for
        # i = 0, 1, ..., num_resonances - 1, and sums them.

        # TODO: is there a more elegant way to achieve this behavior? CompositeModel
        # doesn't accept null operands; but maybe there's a better way.
        resonance_model = Model(lambda x: 0)
        for i in range(num_resonances):
            lorentzian_model = models.LorentzianModel(**kwargs)
            lorentzian_model.prefix = '_' + str(i) + '_'
            resonance_model += lorentzian_model

        super(SpectrumModel, self).__init__(constant_model, resonance_model, operator.add, **kwargs)
Exemplo n.º 9
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)
e_g_err = geometrisch_err(0.015, 0.15, 0.001, 0.001)

strontium_totaal = 960 * 1400
strontium_totaal_err = 960

df_1['efficientie'] = df_1['strontium'] / strontium_totaal
df_1['efficientie_err'] = np.sqrt(
    (df_1['strontium_err'] / strontium_totaal)**2 +
    (-(df_1['strontium'] * strontium_totaal_err) / strontium_totaal**2)**2)

df_1['intrinsiek'] = df_1['efficientie'] / e_g
df_1['intrinsiek_err'] = np.sqrt((df_1['efficientie_err'] / e_g)**2 +
                                 (-(df_1['efficientie'] * e_g_err) /
                                  e_g**2)**2)

mod_linear = models.ConstantModel()
fit = mod_linear.fit(df_1['strontium'],
                     x=df_1['GM'],
                     weights=1 / df_1['strontium_err'])

# print(lmfit.report_fit(fit))

# print(fit.redchi)
## referentie: https://stackoverflow.com/questions/43381833/lmfit-extract-fit-statistics-parameters-after-fitting
# print(fit.params['c'].value)

intrinsiek = df_1['intrinsiek'].tolist()
intrinsiek_err = df_1['intrinsiek_err'].tolist()

intrinsiek_err_sqrd = []
Exemplo n.º 11
0
# in this test version are nearly as naive as possible. Since this is a module that is
# worth getting Right with a capital 'R', and since a lot of people have reinvented
# this wheel before, it would behoove me to review prior art. In particular, it's likely
# that there are standard algorithms and hypothesis tests that are well-known in
# the NMR, HEP, and astronomy communities. Check out any CERN docs on spectrum-fitting;
# they're probably the gold standard. In short, this is abeing written to be deprecated.

# TODO: Review and fix redundancy between SpectrumModel class and spectrum model
# building in fit_spectrum. DRY it out!
# TODO: SpectrumModel constructor is ugly.
# TODO: spectrum_fit is really quite slow.
# TODO: this actually can be rewritten more intelligently.
# Make the guessing functions the guess method of the SpectrumModel class.

# Global definitions
RESONANCE_MODEL = models.ConstantModel() + models.LorentzianModel()


# Classes

class SpectrumModel(CompositeModel):
    """
    An lmfit Model representing a spectrum of finitely-many Lorentzian resonances
    with parameters ``c'', ``_i_amplitude``, ``_i_center``, ``_i_sigma`` for
    i = 0, 1, ..., num_resonances - 1

    Args:
        num_resonances (int): The number of Lorentzian resonances.

    """
Exemplo n.º 12
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))