def test_constraints1():
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model =  yg +  yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data)/sigma


    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) +
            lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23,  size=n) +
            x*0.5)


    pfit = Parameters()
    pfit.add(name='amp_g',  value=10)
    pfit.add(name='cen_g',  value=9)
    pfit.add(name='wid_g',  value=1)

    pfit.add(name='amp_tot',  value=20)
    pfit.add(name='amp_l',  expr='amp_tot - amp_g')
    pfit.add(name='cen_l',  expr='1.5+cen_g')
    pfit.add(name='wid_l',  expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual, pfit,
                      fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data},
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)

    report_fit(result.params)
    pfit= result.params
    fit = residual(result.params, x)
    assert(pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert(pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert(pfit['wid_l'].value == 2 * pfit['wid_g'].value)
Exemple #2
0
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model = yg + yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model =  yg +  yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma
def residual(pars, x, data):
    model =  gaussian(x,
                      pars['amp_g'].value,
                      pars['cen_g'].value,
                      pars['wid_g'].value)
    model += lorentzian(x,
                        pars['amp_l'].value,
                        pars['cen_l'].value,
                        pars['wid_l'].value)
    return (model - data)
def residual_GC(pars, x, sigma=None, data=None):
    yg = gaussian(x)  #, pars['amp_g'], pars['cen_g'], pars['wid_g'])
    yl = lorentzian(x)  #, pars['amp_l'], pars['cen_l'], pars['wid_l'])

    slope = pars['line_slope']
    offset = pars['line_off']
    model = yg + yl + offset + x * slope

    if data is None:
        return model
    if sigma is None:
        return (model - data / sigma)
Exemple #6
0
def conv_rotations_pvoigt(left, right, params, **kwargs):
    """Convolution between the rotation model and a pseudo-Voigt profile."""
    # set left to rotations component if not so
    if left.func.__name__ == "pvoigt":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        frac = rp["fraction_%i" % qId]
        lsigma = lp["sigma"] if "sigma" in lglob else lp["sigma_%i" % qId]
        rsigma = rp["sigma_%i" % qId]
        sigma_v = rsigma / np.sqrt(2 * np.log(2))
        bondDist = lp["bondDist"]

        eisf = spherical_jn(0, bondDist * qVal) ** 2
        eisf *= pvoigt(x, amplitude, center, rsigma, frac)
        qisf = np.sum(
            [
                spherical_jn(i, bondDist * qVal) ** 2
                * (2 * i + 1)
                * (
                    frac
                    * voigt(
                        x, amplitude, center, sigma_v, i * (i + 1) * lsigma
                    )
                    * (1 - frac)
                    * lorentzian(
                        amplitude, center, rsigma + i * (i + 1) * lsigma
                    )
                )
                for i in range(1, 5)
            ],
            axis=0,
        )

        out.append(eisf + qisf)

    return np.array(out)
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value,
                      pars['wid_g'].value)
        yl = lorentzian(x, pars['amp_l'].value, pars['cen_l'].value,
                        pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model = yg + yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value,
                      pars['cen_g'].value, pars['wid_g'].value)
        yl = lorentzian(x, pars['amp_l'].value,
                   pars['cen_l'].value, pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model =  yg +  yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data)/sigma
Exemple #9
0
def test_constraints1():
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model = yg + yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data)/sigma

    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) +
            lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23, size=n) +
            x*0.5)

    pfit = Parameters()
    pfit.add(name='amp_g', value=10)
    pfit.add(name='cen_g', value=9)
    pfit.add(name='wid_g', value=1)

    pfit.add(name='amp_tot', value=20)
    pfit.add(name='amp_l', expr='amp_tot - amp_g')
    pfit.add(name='cen_l', expr='1.5+cen_g')
    pfit.add(name='wid_l', expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual, pfit,
                      fcn_args=(x,), fcn_kws={'sigma': sigma, 'data': data},
                      scale_covar=True)

    myfit.prepare_fit()
    result = myfit.leastsq()

    pfit = result.params
    assert(pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert(pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert(pfit['wid_l'].value == 2 * pfit['wid_g'].value)
Exemple #10
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
def minimizer():
    """Return the Minimizer object."""
    def residual(pars, x, sigma=None, data=None):
        """Define objective function."""
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model = yg + yl + pars['line_off'] + x * pars['line_slope']

        if data is None:
            return model
        if sigma is None:
            return model - data
        return (model-data) / sigma

    # generate synthetic data
    n = 601
    xmin = 0.
    xmax = 20.0
    x = np.linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
            np.random.normal(scale=0.23, size=n) + x*0.5)

    # create initial Parameters
    pars = Parameters()
    pars.add(name='amp_g', value=10)
    pars.add(name='cen_g', value=9)
    pars.add(name='wid_g', value=1)
    pars.add(name='amp_tot', value=20)
    pars.add(name='amp_l', expr='amp_tot - amp_g')
    pars.add(name='cen_l', expr='1.5+cen_g')
    pars.add(name='wid_l', expr='2*wid_g')
    pars.add(name='line_slope', value=0.0)
    pars.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    mini = Minimizer(residual, pars, fcn_args=(x,), fcn_kws={'sigma': sigma,
                                                             'data': data})

    return mini
Exemple #12
0
def lorentzian2d(x,
                 y,
                 amplitude=1.,
                 centerx=0.,
                 centery=0.,
                 sigmax=1.,
                 sigmay=1.,
                 rotation=0):
    """Return a two dimensional lorentzian.

    The maximum of the peak occurs at ``centerx`` and ``centery``
    with widths ``sigmax`` and ``sigmay`` in the x and y directions
    respectively. The peak can be rotated by choosing the value of ``rotation``
    in radians.
    """
    xp = (x - centerx) * np.cos(rotation) - (y - centery) * np.sin(rotation)
    yp = (x - centerx) * np.sin(rotation) + (y - centery) * np.cos(rotation)
    R = (xp / sigmax)**2 + (yp / sigmay)**2

    return 2 * amplitude * lorentzian(R) / (np.pi * sigmax * sigmay)
Exemple #13
0
def conv_lorentzian_lorentzian(left, right, params, **kwargs):
    r"""Convolution between two Lorentzians.

    .. math::

        a_1 \mathcal{L}_{\sigma_1, center_1}
        \otimes a_2 \mathcal{L}_{sigma_2, center_2} =
            a_1 a_2 . \mathcal{L}_{\sigma_1 + \sigma_2, center_1 + center_2}

    """
    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        lsigma = (
            lp["sigma"] * qVal ** 2
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )
        rsigma = (
            rp["sigma"] * qVal ** 2
            if "sigma" in rglob
            else lp["sigma_%i" % qId]
        )

        out.append(lorentzian(x, amplitude, center, lsigma + rsigma))

    return np.array(out)
Exemple #14
0
def conv_jumpdiff_pvoigt(left, right, params, **kwargs):
    """Convolution between the jump diffusion model and a
    pseudo-Voigt profile.

    """
    # set left to jump_diff component if not so
    if left.func.__name__ == "pvoigt":
        left, right = (right, left)

    lp, rp, x, q, out, lglob, rglob = _getVariables(
        left, right, params, **kwargs
    )

    for qId, qVal in enumerate(q):
        amplitude = (
            lp["amplitude"]
            if "amplitude" in lglob
            else lp["amplitude_%i" % qId]
        )
        amplitude *= (
            rp["amplitude"]
            if "amplitude" in rglob
            else rp["amplitude_%i" % qId]
        )
        center = lp["center_%i" % qId] + rp["center_%i" % qId]
        frac = rp["fraction_%i" % qId]
        lsigma = (
            lp["sigma"] * qVal ** 2 / (1 + lp["sigma"] * qVal ** 2 * lp["tau"])
            if "sigma" in lglob
            else lp["sigma_%i" % qId]
        )
        rsigma = rp["sigma_%i" % qId]
        sigma_v = rsigma / np.sqrt(2 * np.log(2))

        out.append(
            frac * voigt(x, amplitude, center, sigma_v, lsigma)
            + (1 - frac) * lorentzian(x, amplitude, center, lsigma + rsigma)
        )

    return np.array(out)
Exemple #15
0
def plot_fit(out):
    fig, ax = plt.subplots(
        2, 1, sharex=True, figsize=(12, 6), gridspec_kw={"height_ratios": [1, 4]}
    )
    xd = out.userkws[out.model.independent_vars[0]]
    xnew = np.linspace(xd[0], xd[-1], 1000)
    ax[0].plot(xd, out.residual, "k-", ms=3, lw=1, alpha=0.5)
    ax[1].plot(xd, out.data, "b+-", ms=3, lw=1, alpha=0.8)
    ax[1].plot(xnew, out.eval(x=xnew), "k--", lw=1.5)
    for i, p in enumerate(out.peak_pos):
        # print(out.params['p%s_'])
        ax[1].plot(
            xnew,
            lorentzian(
                xnew,
                amplitude=out.params["p%s_amplitude" % i],
                center=out.params["p%s_center" % i],
                sigma=out.params["p%s_sigma" % i],
            ),
            lw=0.5,
        )
    return fig
Exemple #16
0
import matplotlib.pyplot as plt
import numpy as np

from lmfit import Minimizer, Parameters, report_fit
from lmfit.lineshapes import gaussian, lorentzian


def residual(pars, x, data):
    model = (gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g']) +
             lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l']))
    return model - data

np.random.seed(0)
x = np.linspace(0, 20.0, 601)

data = (gaussian(x, 21, 6.1, 1.0) + lorentzian(x, 10, 9.6, 1.3) +
        np.random.normal(scale=0.1, size=x.size))

pfit = Parameters()
# pfit.add(name='amp_g', value=10)
# pfit.add(name='amp_l', value=10)
# pfit.add(name='cen_g', value=5)
# pfit.add(name='peak_split', value=2.5, min=0, max=5, vary=True)
# pfit.add(name='cen_l', expr='peak_split+cen_g')
# pfit.add(name='wid_g', value=1)
# pfit.add(name='wid_l', expr='wid_g')

pfit.add(name='amp_g', value=10)
pfit.add(name='amp_l', value=10)
pfit.add(name='cen_g', value=5)
pfit.add(name='cen_l', value=10)
def test_constraints2():
    """add a user-defined function to symbol table"""
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value,
                      pars['cen_g'].value, pars['wid_g'].value)
        yl = lorentzian(x, pars['amp_l'].value,
                   pars['cen_l'].value, pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model =  yg +  yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data)/sigma


    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) +
            lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23,  size=n) +
            x*0.5)

    pfit = Parameters()
    pfit.add(name='amp_g',  value=10)
    pfit.add(name='cen_g',  value=9)
    pfit.add(name='wid_g',  value=1)

    pfit.add(name='amp_tot',  value=20)
    pfit.add(name='amp_l',  expr='amp_tot - amp_g')
    pfit.add(name='cen_l',  expr='1.5+cen_g')
    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual, pfit,
                      fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data},
                      scale_covar=True)

    def width_func(wpar):
        """ """
        return 2*wpar

    myfit.params._asteval.symtable['wfun'] = width_func

    try:
        myfit.params.add(name='wid_l', expr='wfun(wid_g)')
    except:
        assert(False)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)
    report_fit(result.params)
    pfit= result.params
    fit = residual(result.params, x)
    assert(pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert(pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert(pfit['wid_l'].value == 2 * pfit['wid_g'].value)
Exemple #18
0
    offset = pars['line_off'].value
    model =  yg +  yl + offset + x * slope
    if data is None:
        return model
    if sigma is  None:
        return (model - data)
    return (model - data)/sigma


n = 601
xmin = 0.
xmax = 20.0
x = linspace(xmin, xmax, n)

data = (gaussian(x, 21, 8.1, 1.2) +
        lorentzian(x, 10, 9.6, 2.4) +
        random.normal(scale=0.23,  size=n) +
        x*0.5)


if HASPYLAB:
    pylab.plot(x, data, 'r+')

pfit = [Parameter(name='amp_g',  value=10),
        Parameter(name='cen_g',  value=9),
        Parameter(name='wid_g',  value=1),

        Parameter(name='amp_tot',  value=20),
        Parameter(name='amp_l',  expr='amp_tot - amp_g'),
        Parameter(name='cen_l',  expr='1.5+cen_g'),
        Parameter(name='wid_l',  expr='2*wid_g'),
Exemple #19
0
def mypvoigt(x, amp, center, fwhm, frac):
    sig = fwhm * 0.424660900144
    return ((1 - frac) * gaussian(x, amp, center, sig) +
            frac * lorentzian(x, amp, center, sig))
Exemple #20
0
# Test that FT{Gaussian} = Gaussian, and FT{exponential} = Lorentzian
x = np.arange(-0.1, 0.5, 0.0004)  # energy domain, in meV
# items are (tau, beta, intensities). Assumed that tau unit is picoseconds
trios = [
    (20.0, 2.0,
     gaussian(x,
              amplitude=1.0,
              center=0.0,
              sigma=planck_constant / (np.sqrt(2.0) * 20.0 * np.pi))),
    (
        100.0,
        1.0,
        # sigma below is actually the HWHM
        lorentzian(x,
                   amplitude=1.0,
                   center=0.0,
                   sigma=planck_constant / (2 * np.pi * 100.0)))
]


@pytest.mark.parametrize('tau, beta, y', trios)
def test_lineshapes(tau, beta, y):
    model = StretchedExponentialFTModel()
    params = model.guess(y, x=None)
    # Stray away from optimal parameters
    [
        params[name].set(value=val) for name, val in dict(
            amplitude=3.0, center=0.0002, tau=50.0, beta=1.5).items()
    ]
    r = model.fit(y, params, x=x)
    all_params = 'tau beta amplitude center'.split()
                      pars['amp_g'].value,
                      pars['cen_g'].value,
                      pars['wid_g'].value)
    model += lorentzian(x,
                        pars['amp_l'].value,
                        pars['cen_l'].value,
                        pars['wid_l'].value)
    return (model - data)


n = 601
random.seed(0)
x = linspace(0, 20.0, n)

data = (gaussian(x,   21, 6.1, 1.2) +
        lorentzian(x, 10, 9.6, 1.3) +
        random.normal(scale=0.1,  size=n))

pfit = Parameters()
pfit.add(name='amp_g',  value=10)
pfit.add(name='amp_l',  value=10)
pfit.add(name='cen_g',  value=5)
pfit.add(name='peak_split',  value=2.5, min=0, max=5, vary=True)
pfit.add(name='cen_l',  expr='peak_split+cen_g')
pfit.add(name='wid_g',  value=1)
pfit.add(name='wid_l',  expr='wid_g')

mini = Minimizer(residual, pfit, fcn_args=(x, data))
out  = mini.leastsq()

report_fit(out.params)
def test_constraints(with_plot=True):
    with_plot = with_plot and WITHPLOT

    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value,
                      pars['wid_g'].value)
        yl = lorentzian(x, pars['amp_l'].value, pars['cen_l'].value,
                        pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model = yg + yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma

    n = 201
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23, size=n) + x * 0.5)

    if with_plot:
        pylab.plot(x, data, 'r+')

    pfit = Parameters()
    pfit.add(name='amp_g', value=10)
    pfit.add(name='cen_g', value=9)
    pfit.add(name='wid_g', value=1)

    pfit.add(name='amp_tot', value=20)
    pfit.add(name='amp_l', expr='amp_tot - amp_g')
    pfit.add(name='cen_l', expr='1.5+cen_g')
    pfit.add(name='wid_l', expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual,
                      pfit,
                      fcn_args=(x, ),
                      fcn_kws={
                          'sigma': sigma,
                          'data': data
                      },
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    myfit.leastsq()

    print(' Nfev = ', myfit.nfev)
    print(myfit.chisqr, myfit.redchi, myfit.nfree)

    report_fit(myfit.params, min_correl=0.3)

    fit = residual(myfit.params, x)
    if with_plot:
        pylab.plot(x, fit, 'b-')
    assert (myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value)
    assert (myfit.params['amp_l'].value == myfit.params['amp_tot'].value -
            myfit.params['amp_g'].value)
    assert (myfit.params['wid_l'].value == 2 * myfit.params['wid_g'].value)

    # now, change fit slightly and re-run
    myfit.params['wid_l'].expr = '1.25*wid_g'
    myfit.leastsq()
    report_fit(myfit.params, min_correl=0.4)
    fit2 = residual(myfit.params, x)
    if with_plot:
        pylab.plot(x, fit2, 'k')
        pylab.show()

    assert (myfit.params['cen_l'].value == 1.5 + myfit.params['cen_g'].value)
    assert (myfit.params['amp_l'].value == myfit.params['amp_tot'].value -
            myfit.params['amp_g'].value)
    assert (myfit.params['wid_l'].value == 1.25 * myfit.params['wid_g'].value)
def test_constraints2():
    """add a user-defined function to symbol table"""
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'].value, pars['cen_g'].value,
                      pars['wid_g'].value)
        yl = lorentzian(x, pars['amp_l'].value, pars['cen_l'].value,
                        pars['wid_l'].value)

        slope = pars['line_slope'].value
        offset = pars['line_off'].value
        model = yg + yl + offset + x * slope
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma

    n = 601
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23, size=n) + x * 0.5)

    pfit = [
        Parameter(name='amp_g', value=10),
        Parameter(name='cen_g', value=9),
        Parameter(name='wid_g', value=1),
        Parameter(name='amp_tot', value=20),
        Parameter(name='amp_l', expr='amp_tot - amp_g'),
        Parameter(name='cen_l', expr='1.5+cen_g'),
        Parameter(name='line_slope', value=0.0),
        Parameter(name='line_off', value=0.0)
    ]

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual,
                      pfit,
                      fcn_args=(x, ),
                      fcn_kws={
                          'sigma': sigma,
                          'data': data
                      },
                      scale_covar=True)

    def width_func(wpar):
        """ """
        return 2 * wpar

    myfit.params._asteval.symtable['wfun'] = width_func
    myfit.params.add(name='wid_l', expr='wfun(wid_g)')

    myfit.leastsq()

    print(' Nfev = ', myfit.nfev)
    print(myfit.chisqr, myfit.redchi, myfit.nfree)

    report_fit(myfit.params)
    pfit = myfit.params
    fit = residual(myfit.params, x)
    assert (pfit['cen_l'].value == 1.5 + pfit['cen_g'].value)
    assert (pfit['amp_l'].value == pfit['amp_tot'].value - pfit['amp_g'].value)
    assert (pfit['wid_l'].value == 2 * pfit['wid_g'].value)
Exemple #24
0
def residual(pars, x, data):
    model = (gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g']) +
             lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l']))
    return model - data
Exemple #25
0
    out = mod.fit(yn, pars, x=xs)
    out2 = mod.fit(yn, pars, x=xs, fit_kws={'Dfun': dfunc_gaussian,
                                            'col_deriv': 1})
    print('lmfit without dfunc **************')
    print('number of function calls: ', out.nfev)
    print('params', out.best_values)
    print('lmfit with dfunc *****************')
    print('number of function calls: ', out2.nfev)
    print('params', out2.best_values)
    print('\n \n')
    out2.plot(datafmt='.')

    print('**********************************')
    print('***** Test Lorentzian ************')
    print('**********************************')
    ys = lorentzian(xs, 2.5, 0, 0.5)
    yn = ys + 0.1*np.random.normal(size=len(xs))

    mod = LorentzianModel()
    pars = mod.guess(yn, xs)
    out = mod.fit(yn, pars, x=xs)
    out2 = mod.fit(yn, pars, x=xs, fit_kws={'Dfun': dfunc_lorentzian, 'col_deriv': 1})
    print('lmfit without dfunc **************')
    print('number of function calls: ', out.nfev)
    print('params', out.best_values)
    print('lmfit with dfunc *****************')
    print('number of function calls: ', out2.nfev)
    print('params', out2.best_values)
    print('\n \n')
    out2.plot(datafmt='.')
Exemple #26
0
def teixeira_water(x, amplitude=1.0, center=1.0, tau=1.0, dcf=1.0, q=1.0):
    dq2 = dcf * q * q
    hwhm = hbar * dq2 / (1 + tau * dq2)
    return lorentzian(x, amplitude=amplitude, center=center, sigma=hwhm)
Exemple #27
0
def residual(pars, x, data):
    model = gaussian(x, pars['amp_g'].value, pars['cen_g'].value,
                     pars['wid_g'].value)
    model += lorentzian(x, pars['amp_l'].value, pars['cen_l'].value,
                        pars['wid_l'].value)
    return (model - data)
            tau = max(y) / amplitude  # assumed beta==1.0
        return self.make_params(amplitude=amplitude,
                                center=center,
                                tau=tau,
                                beta=beta)


# Test that FT{Gaussian} = Gaussian, and FT{exponential} = Lorentzian
x = np.arange(-0.1, 0.5, 0.0004)  # energy domain, in meV
# items are (tau, beta, intensities). Assumed that tau unit is picoseconds
trios = [(20.0, 2.0,
          gaussian(x, amplitude=1.0, center=0.0,
                   sigma=planck_constant/(np.sqrt(2.0)*20.0*np.pi))),
         (100.0, 1.0,
          # sigma below is actually the HWHM
          lorentzian(x, amplitude=1.0, center=0.0,
                     sigma=planck_constant / (2 * np.pi * 100.0)))
         ]

@pytest.mark.parametrize('tau, beta, y', trios)
def test_lineshapes(tau, beta, y):
    model = StretchedExponentialFTModel()
    params = model.guess(y, x=None)
    # Stray away from optimal parameters
    [params[name].set(value=val) for name, val in
     dict(amplitude=3.0, center=0.0002, tau=50.0, beta=1.5).items()]
    r = model.fit(y, params, x=x)
    all_params = 'tau beta amplitude center'.split()
    assert_allclose([tau, beta, 1.0, 0.0],
                    [r.params[p].value for p in all_params],
                    rtol=0.1, atol=0.000001)
Exemple #29
0
def test_constraints():
    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model = yg + yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma

    n = 201
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23, size=n) + x * 0.5)

    pfit = Parameters()
    pfit.add(name='amp_g', value=10)
    pfit.add(name='cen_g', value=9)
    pfit.add(name='wid_g', value=1)

    pfit.add(name='amp_tot', value=20)
    pfit.add(name='amp_l', expr='amp_tot - amp_g')
    pfit.add(name='cen_l', expr='1.5+cen_g')
    pfit.add(name='wid_l', expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual,
                      pfit,
                      fcn_args=(x, ),
                      fcn_kws={
                          'sigma': sigma,
                          'data': data
                      },
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print(result.chisqr, result.redchi, result.nfree)

    report_fit(result.params, min_correl=0.3)

    fit = residual(result.params, x)
    assert (result.params['cen_l'].value == 1.5 + result.params['cen_g'].value)
    assert (result.params['amp_l'].value == result.params['amp_tot'].value -
            result.params['amp_g'].value)
    assert (result.params['wid_l'].value == 2 * result.params['wid_g'].value)

    # now, change fit slightly and re-run
    myfit.params['wid_l'].expr = '1.25*wid_g'
    result = myfit.leastsq()
    report_fit(result.params, min_correl=0.4)
    fit2 = residual(result.params, x)

    assert (result.params['cen_l'].value == 1.5 + result.params['cen_g'].value)
    assert (result.params['amp_l'].value == result.params['amp_tot'].value -
            result.params['amp_g'].value)
    assert (result.params['wid_l'].value == 1.25 *
            result.params['wid_g'].value)
Exemple #30
0
def residual(pars, x, data):
    model = (gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g']) +
             lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l']))
    return model - data
def test_constraints(with_plot=True):
    with_plot = with_plot and WITHPLOT

    def residual(pars, x, sigma=None, data=None):
        yg = gaussian(x, pars['amp_g'], pars['cen_g'], pars['wid_g'])
        yl = lorentzian(x, pars['amp_l'], pars['cen_l'], pars['wid_l'])

        model =  yg +  yl + pars['line_off'] + x * pars['line_slope']
        if data is None:
            return model
        if sigma is None:
            return (model - data)
        return (model - data) / sigma


    n = 201
    xmin = 0.
    xmax = 20.0
    x = linspace(xmin, xmax, n)

    data = (gaussian(x, 21, 8.1, 1.2) +
            lorentzian(x, 10, 9.6, 2.4) +
            random.normal(scale=0.23,  size=n) +
            x*0.5)

    if with_plot:
        pylab.plot(x, data, 'r+')

    pfit = Parameters()
    pfit.add(name='amp_g',  value=10)
    pfit.add(name='cen_g',  value=9)
    pfit.add(name='wid_g',  value=1)

    pfit.add(name='amp_tot',  value=20)
    pfit.add(name='amp_l',  expr='amp_tot - amp_g')
    pfit.add(name='cen_l',  expr='1.5+cen_g')
    pfit.add(name='wid_l',  expr='2*wid_g')

    pfit.add(name='line_slope', value=0.0)
    pfit.add(name='line_off', value=0.0)

    sigma = 0.021  # estimate of data error (for all data points)

    myfit = Minimizer(residual, pfit,
                      fcn_args=(x,), fcn_kws={'sigma':sigma, 'data':data},
                      scale_covar=True)

    myfit.prepare_fit()
    init = residual(myfit.params, x)

    result = myfit.leastsq()

    print(' Nfev = ', result.nfev)
    print( result.chisqr, result.redchi, result.nfree)

    report_fit(result.params, min_correl=0.3)

    fit = residual(result.params, x)
    if with_plot:
        pylab.plot(x, fit, 'b-')
    assert(result.params['cen_l'].value == 1.5 + result.params['cen_g'].value)
    assert(result.params['amp_l'].value == result.params['amp_tot'].value - result.params['amp_g'].value)
    assert(result.params['wid_l'].value == 2 * result.params['wid_g'].value)

    # now, change fit slightly and re-run
    myfit.params['wid_l'].expr = '1.25*wid_g'
    result = myfit.leastsq()
    report_fit(result.params, min_correl=0.4)
    fit2 = residual(result.params, x)
    if with_plot:
        pylab.plot(x, fit2, 'k')
        pylab.show()

    assert(result.params['cen_l'].value == 1.5 + result.params['cen_g'].value)
    assert(result.params['amp_l'].value == result.params['amp_tot'].value - result.params['amp_g'].value)
    assert(result.params['wid_l'].value == 1.25 * result.params['wid_g'].value)
Exemple #32
0
def ltz():
    r"""Sample data is a Lorentzian"""
    x = np.arange(-0.1, 0.5, 0.0004)  # energy domain, in meV
    params = dict(amplitude=1.0, center=0.0, sigma=0.025)
    y = lorentzian(x, **params)
    return dict(x=x, y=y, p=params)
Exemple #33
0
def find_grain_diameter(X, Y, min_size, max_size, size_step, return_figure,
                        peaks_params, is_bg_active):
    """
    New parameters are stored in peaks_params. The old ones are still present to provide compatibility with old code.
    :param X:
    :param Y:
    :param min_size:
    :param max_size:
    :param size_step:
    :param center:
    :param gamma_0:
    :param peak_height:
    :param return_figure:
    :param sample_type:
    :param peaks_params: [[center, gamma_0, amplitude, from, to, is_visible, is_lorentz, is fano], ...]
    :return:
    """

    best_d = -1
    best_sigma = -1
    best_center = -1
    best_amplitude = -1
    best_q = 5

    X_ex = X
    max_y = max(Y)
    x_range = (X > 400) * (X < 600)

    lin_mod = LinearModel(prefix="background_", min=0, max=0.5 * max_y)
    pars = lin_mod.guess(Y, x=X)
    final_mod = lin_mod

    for ii in range(0, len(peaks_params)):
        if peaks_params[ii][6] == True:
            mod = LorentzianModel(prefix="l" + str(ii) + '_')
            pars.update(mod.make_params())
            pars['l' + str(ii) + '_center'].set(peaks_params[ii][0],
                                                min=peaks_params[ii][3],
                                                max=peaks_params[ii][4])
            pars['l' + str(ii) + '_sigma'].set(peaks_params[ii][1])
            pars['l' + str(ii) + '_amplitude'].set(peaks_params[ii][2],
                                                   min=0)  #, max=max_y)
        elif peaks_params[ii][7] == True:
            mod = Model(fano_function)
            pars.update(mod.make_params())
            pars['q'].set(
                -4, min=-20, max=0
            )  #q may be negative as well as positive, the most common values for q: [-1,5]
            pars['center'].set(peaks_params[ii][0], vary=True)
            pars['sigma'].set(peaks_params[ii][1], min=0.1, vary=True)
            pars['amplitude'].set(peaks_params[ii][2], min=0)
        else:
            mod = Model(
                total_intensity_fit_func
            )  #total_intensity_fit_func(omega, d, N, center, gamma_0, amplitude)
            pars.update(mod.make_params())
            pars['d'].set((max_size - min_size), min=min_size, max=max_size)
            pars['N'].set(100, vary=False)
            pars['center'].set(peaks_params[ii][0], vary=False)
            pars['sigma'].set(peaks_params[ii][1], vary=False)
            pars['amplitude'].set(peaks_params[ii][2], min=0, max=max_y)

        final_mod = final_mod + mod

###########PLOT & RETURN######################################
    if return_figure:
        my_figure = plt.Figure()

        my_plot = my_figure.add_subplot(111)
        legend_labels = []
        for ax in my_figure.axes:
            ax.set_xlabel(u'\u03C9' + ' [cm^-1]')
            ax.set_ylabel('Intensity [arb.]')

        my_plot.plot(X[x_range], Y[x_range], "ro")
        legend_labels.append('Data')

    out = final_mod.fit(Y[x_range], pars, x=X[x_range])
    if not out.success:
        print("!!!!!!!!!!!!!FIT HAVE FAILED!!!!!!!!!!!")
        legend_labels = ['FIT FAILED!']
        if return_figure:
            my_plot.legend(legend_labels)
            return best_d, best_sigma, best_center, best_amplitude, my_figure
        else:
            return best_d, best_sigma, best_center, best_amplitude
    elif not return_figure:
        if (peaks_params[0][6] == True):
            best_sigma = out.best_values['l' + str(0) + '_sigma']
            best_center = out.best_values['l' + str(0) + '_center']
            best_amplitude = out.best_values['l' + str(0) + '_amplitude']
            return 0, best_sigma, best_center, best_amplitude
        elif (peaks_params[0][7] == True):
            best_sigma = out.best_values['sigma']
            best_center = out.best_values['center']
            best_amplitude = out.best_values['amplitude']
            best_q = out.best_values['q']
            print(best_q)
            return best_q, best_sigma, best_center, best_amplitude
        else:
            best_sigma = out.best_values['sigma']
            best_center = out.best_values['center']
            best_amplitude = out.best_values['amplitude']
            best_d = out.best_values['d']
            print(best_d)
            return best_d, best_sigma, best_center, best_amplitude
    else:
        print(out.fit_report(min_correl=0.5))
        legend_labels.append('Best fit')

        my_plot.plot(X[x_range], out.best_fit, "b-")
        my_plot.plot(
            X[x_range], out.best_values['background_slope'] * X[x_range] +
            out.best_values['background_intercept'], '--')
        legend_labels.append('background')

        for jj in range(0, len(peaks_params)):
            if (peaks_params[jj][6] == True):
                sigma = out.best_values['l' + str(jj) + '_sigma']
                center = out.best_values['l' + str(jj) + '_center']
                amplitude = out.best_values['l' + str(jj) + '_amplitude']
                legend_labels.append('l' + str(jj))
                my_plot.plot(
                    X[x_range],
                    lorentzian(X[x_range],
                               center=center,
                               sigma=sigma,
                               amplitude=amplitude), '--')
            elif (peaks_params[jj][7] == True):
                sigma = out.best_values['sigma']
                center = out.best_values['center']
                amplitude = out.best_values['amplitude']
                q = out.best_values['q']
                legend_labels.append('fano; q=' + str(q))
                my_plot.plot(
                    X[x_range],
                    fano_function(X[x_range], q, center, sigma, amplitude),
                    '--')
            else:
                sigma = out.best_values['sigma']
                center = out.best_values['center']
                amplitude = out.best_values['amplitude']
                d = out.best_values['d']
                N = out.best_values['N']
                legend_labels.append('fc; d=' + str(d))
                my_plot.plot(
                    X[x_range],
                    total_intensity_fit_func(X[x_range], d, N, center, sigma,
                                             amplitude), '--')

        if (peaks_params[0][7] == True):
            my_figure.suptitle(
                "q:{0:.1f}[nm]   omega:{1:.4f}[cm^-1]   sigma:{2:.4f}[cm^-1]    inten:{3:.4}[arb]"
                .format(float(best_q), float(best_center), float(best_sigma),
                        float(best_amplitude)))
        else:
            my_figure.suptitle(
                "d:{0:.1f}[nm]   omega:{1:.4f}[cm^-1]   sigma:{2:.4f}[cm^-1]    inten:{3:.4}[arb]"
                .format(float(best_d), float(best_center), float(best_sigma),
                        float(best_amplitude)))
        my_plot.legend(legend_labels, loc=2)

        return best_d, best_sigma, best_center, best_amplitude, my_figure
    offset = pars['line_off']
    model = yg + yl + offset + x * slope
    if data is None:
        return model
    if sigma is None:
        return (model - data)
    return (model - data) / sigma


n = 601
xmin = 0.
xmax = 20.0
random.seed(0)
x = linspace(xmin, xmax, n)

data = (gaussian(x, 21, 8.1, 1.2) + lorentzian(x, 10, 9.6, 2.4) +
        random.normal(scale=0.23, size=n) + x * 0.5)

if HASPYLAB:
    pylab.plot(x, data, 'r+')

pfit = Parameters()
pfit.add(name='amp_g', value=10)
pfit.add(name='cen_g', value=9)
pfit.add(name='wid_g', value=1)
pfit.add(name='amp_tot', value=20)
pfit.add(name='amp_l', expr='amp_tot - amp_g')
pfit.add(name='cen_l', expr='1.5+cen_g')
pfit.add(name='wid_l', expr='2*wid_g')
pfit.add(name='line_slope', value=0.0)
pfit.add(name='line_off', value=0.0)
    model =  yg +  yl + offset + x * slope
    if data is None:
        return model
    if sigma is  None:
        return (model - data)
    return (model - data)/sigma


n = 601
xmin = 0.
xmax = 20.0
random.seed(0)
x = linspace(xmin, xmax, n)

data = (gaussian(x, 21, 8.1, 1.2) +
        lorentzian(x, 10, 9.6, 2.4) +
        random.normal(scale=0.23,  size=n) +
        x*0.5)


if HASPYLAB:
    pylab.plot(x, data, 'r+')

pfit = [Parameter(name='amp_g',  value=10),
        Parameter(name='cen_g',  value=9),
        Parameter(name='wid_g',  value=1),

        Parameter(name='amp_tot',  value=20),
        Parameter(name='amp_l',  expr='amp_tot - amp_g'),
        Parameter(name='cen_l',  expr='1.5+cen_g'),
        Parameter(name='wid_l',  expr='2*wid_g'),