コード例 #1
0
def test_guess_from_peak():
    """Regression test for guess_from_peak function (see GH #627)."""
    x = np.linspace(-5, 5)
    amplitude = 0.8
    center = 1.7
    sigma = 0.3
    y = lineshapes.lorentzian(x, amplitude=amplitude, center=center, sigma=sigma)

    model = models.LorentzianModel()
    guess_increasing_x = model.guess(y, x=x)
    guess_decreasing_x = model.guess(y[::-1], x=x[::-1])

    assert guess_increasing_x == guess_decreasing_x

    for param, value in zip(['amplitude', 'center', 'sigma'],
                            [amplitude, center, sigma]):
        assert np.abs((guess_increasing_x[param].value - value)/value) < 0.5
コード例 #2
0
ファイル: spectra.py プロジェクト: warrench/dysart
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
コード例 #3
0
ファイル: spectra.py プロジェクト: warrench/dysart
    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)
コード例 #4
0
ファイル: MSPeakCalc.py プロジェクト: hechth/CoreMS
    def lorentz(self, oversample_multiplier=1, delta_rp=0, mz_overlay=1):
        '''
        Legacy lorentz lineshape analysis function
        '''
        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

            # half width baseline distance
            hw_base_distance = (8 * sigma)

            #mz_domain = linspace(self.mz_exp - hw_base_distance,
            #                     self.mz_exp + hw_base_distance, 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) )
            model = models.LorentzianModel()

            amplitude = sigma * pi * 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()'
            )
コード例 #5
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()
コード例 #6
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)
コード例 #7
0
ファイル: xrd_fit.py プロジェクト: Relm-Arrowny/dataAnalysis
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
コード例 #8
0
ファイル: MSPeakCalc.py プロジェクト: hechth/CoreMS
    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()'
            )
コード例 #9
0
ファイル: spectra.py プロジェクト: warrench/dysart
# 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.

    """