예제 #1
0
def Einzel(x, b, A):
    return ((A*lam)/(math.pi*np.sin(x/L)))**2 * (np.sin((math.pi*b*np.sin(x/L))/lam))**2

def Doppel(x, b, s):
    return 4*(np.cos((math.pi*s*np.sin(x/L))/lam))**2 * ((lam)/(math.pi*b*np.sin(x/L)))**2 * (np.sin((math.pi*b*np.sin(x/L))/lam))**2

print('-------------------------------------------------------------------')
print('Einzelspalt b = 0.075mm')

a1, i1 = np.loadtxt('data1.txt', unpack=True)
i1 = i1 * 10**(-6) - Id
a1 = a1 * 10**(-3)

model = Model(Einzel, independent_vars=['x'])
result = model.fit(i1, x=a1, b=Parameter(value=0.0001), A=Parameter(value=1))

print(result.params)

plt.plot(a1, i1, 'gx', label='Messwerte')
plt.plot(xwerte, Einzel(xwerte, **result.values), 'r-', label='gefittete Kurve')
plt.ylabel('Intensität / A')
plt.xlabel('a / m')
plt.legend(loc="best")
plt.grid()
plt.tight_layout()
plt.savefig('build/plot1.pdf')
plt.close()

print('-------------------------------------------------------------------')
print('Einzelspalt b = 0.15mm')
예제 #2
0
def fit_jd_hist(
    hists: list,
    dt: float,
    D: list,
    fit_D: list,
    F: list,
    fit_F: list,
    sigma: float,
    fit_sigma: bool,
    verbose=False,
):

    """
    Fits jd probability functions to a jd histograms.

    Parameters:
    hist (list): histogram values
    D (list): init values for MSD
    F (list): fractions for D, sum = 1
    sigma (float): localization precision guess
    funcs (dict): dictionary with functions sigma, gamma, center, amplitude

    Returns:
    popt (lmfit.minimizerResult): optimized parameters
    """

    from lmfit import Parameters, Parameter, minimize

    def residual(fit_params, data):
        res = cumulative_error_jd_hist(fit_params, data, len(D))
        return res

    fit_params = Parameters()
    # fit_params.add('sigma', value=sigma, vary=fit_sigma, min=0.)
    fit_params.add("dt", value=dt, vary=False)
    try:
        fit_params.add("max_lag", value=max([h.lag for h in hists]), vary=False)
    except TypeError as e:
        logger.error(
            f"problem with `hists`: expected `list`,\
            got `{type(hists)}`"
        )
        raise e

    for i, (d, f_d, f, f_f) in enumerate(zip(D, fit_D, F, fit_F)):
        fit_params.add(f"D{i}", value=d, vary=f_d, min=0.0)
        fit_params.add(f"F{i}", value=f, min=0.0, max=1.0, vary=f_f)

    f_expr = "1"
    for i, f in enumerate(F[:-1]):
        f_expr += f" - F{i}"

    fit_params[f"F{i+1}"] = Parameter(name=f"F{i+1}", min=0.0, max=1.0, expr=f_expr)

    for i, (s, f_s, min_s, max_s) in enumerate(
        zip(sigma, fit_sigma, (0, sigma[0]), (3 * sigma[0], D[-1]))
    ):
        fit_params.add(f"sigma{i}", value=s, min=min_s, max=max_s, vary=f_s)

    logger.debug("start minimize")

    minimizer_result = minimize(residual, fit_params, args=(hists,))

    if verbose:
        logger.info(f"completed in {minimizer_result.nfev} steps")
        minimizer_result.params.pretty_print()

    return minimizer_result
예제 #3
0
 def parameters(self):
     if self._parameters is None:
         self._parameters = [Parameter(name) 
                             for name in self.module.parameters]
     return self._parameters
예제 #4
0
    def addModel(self, event=None, model=None, is_step=False):
        if model is None and event is not None:
            model = event.GetString()
        if model is None or model.startswith('<'):
            return

        curmodels = ["c%i_" % (i+1) for i in range(1+len(self.fit_components))]
        for comp in self.fit_components:
            if comp in curmodels:
                curmodels.remove(comp)

        prefix = curmodels[0]

        label = "%s(prefix='%s')" % (model, prefix)
        title = "%s: %s" % (prefix[:-1], (model+' '*4)[:5])
        mclass_kws = {'prefix': prefix}
        if is_step:
            form = model.lower()
            if form.startswith('err'): form = 'erf'
            label = "Step(form='%s', prefix='%s')" % (form, prefix)
            title = "%s: Step %s" % (prefix[:-1], form[:3])
            mclass = lm_models.StepModel
            mclass_kws['form'] = form
            minst = mclass(form=form, prefix=prefix)
        else:
            mclass = getattr(lm_models, model+'Model')
            minst = mclass(prefix=prefix)

        panel = GridPanel(self.mod_nb, ncols=1, nrows=1, pad=1, itemstyle=CEN)

        def SLabel(label, size=(75, -1), **kws):
            return  SimpleText(panel, label,
                               size=size, style=wx.ALIGN_LEFT, **kws)
        usebox = Check(panel, default=True, label='Use?', size=(75, -1))
        delbtn = Button(panel, 'Delete Model', size=(120, -1),
                        action=partial(self.onDeleteComponent, prefix=prefix))
        pick2msg = SimpleText(panel, "    ", size=(75, -1))
        pick2btn = Button(panel, 'Pick Data Range', size=(125, -1),
                          action=partial(self.onPick2Points, prefix=prefix))

        # SetTip(mname,  'Label for the model component')
        SetTip(usebox, 'Use this component in fit?')
        SetTip(delbtn, 'Delete this model component')
        SetTip(pick2btn, 'Select X range on Plot to Guess Initial Values')

        panel.Add(HLine(panel, size=(520, 3)), style=wx.ALIGN_CENTER, dcol=6)

        panel.Add(SLabel(label, size=(200, -1), colour='#0000AA'),
                  dcol=3,  newrow=True)
        panel.AddMany((usebox, pick2msg, pick2btn))

        panel.Add(SLabel("Parameter"),   newrow=True)
        panel.AddMany((SLabel("Value"), SLabel("Type"), SLabel("Min"),
                       SLabel("Max"), SLabel("Expression")))

        parwids = OrderedDict()

        parnames = sorted(minst.param_names)

        for a in minst._func_allargs:
            pname = "%s%s" % (prefix, a)
            if (pname not in parnames and
                a in minst.param_hints and
                a not in minst.independent_vars):
                parnames.append(pname)

        for pname in parnames:
            sname = pname[len(prefix):]
            hints = minst.param_hints.get(sname, {})

            par = Parameter(name=pname, value=0, vary=True)
            if 'min' in hints:
                par.min = hints['min']
            if 'max' in hints:
                par.max = hints['max']
            if 'value' in hints:
                par.value = hints['value']
            if 'expr' in hints:
                par.expr = hints['expr']

            pwids = ParameterWidgets(panel, par, name_size=80, expr_size=150,
                                     float_size=70, prefix=prefix,
                                     widgets=('name', 'value',  'minval',
                                              'maxval', 'vary', 'expr'))
            parwids[par.name] = pwids
            panel.Add(pwids.name, newrow=True)
            panel.AddMany((pwids.value, pwids.vary, pwids.minval,
                           pwids.maxval, pwids.expr))

        for sname, hint in minst.param_hints.items():
            pname = "%s%s" % (prefix, sname)
            if 'expr' in hint and pname not in parnames:
                par = Parameter(name=pname, value=0, expr=hint['expr'])

                pwids = ParameterWidgets(panel, par, name_size=80, expr_size=275,
                                         float_size=70, prefix=prefix,
                                         widgets=('name', 'value', 'vary', 'expr'))
                parwids[par.name] = pwids
                panel.Add(pwids.name, newrow=True)
                panel.AddMany((pwids.value, pwids.vary))
                panel.Add(pwids.expr, dcol=3, style=wx.ALIGN_RIGHT)
                pwids.value.Disable()
                pwids.vary.Disable()

        panel.Add(HLine(panel, size=(90,  3)), style=wx.ALIGN_CENTER, newrow=True)
        panel.Add(delbtn, dcol=2)
        panel.Add(HLine(panel, size=(250, 3)), dcol=3, style=wx.ALIGN_CENTER)

        fgroup = Group(prefix=prefix, title=title, mclass=mclass,
                       mclass_kws=mclass_kws, usebox=usebox, panel=panel,
                       parwids=parwids, float_size=65, expr_size=150,
                       pick2_msg=pick2msg)

        self.fit_components[prefix] = fgroup
        panel.pack()

        self.mod_nb.AddPage(panel, title, True)
        sx,sy = self.GetSize()
        self.SetSize((sx, sy+1))
        self.SetSize((sx, sy))
예제 #5
0
def fit_two_lz(x_lst, spectra_lst, first, last):
    '''
    Give it a list x spectra and y spectra
    where to begin the fit and where to end it
    '''
    
    # for gradient
    import numpy as np
    # for smoothing the curves
    import scipy.interpolate as interp #import splev 
    # for non linear fitting
    from lmfit import minimize, Minimizer, Parameters, Parameter, report_fit
    
    # Restrict fitting region
    x_fit = []
    y_fit = []
    for x,y in zip(x_lst,spectra_lst):
        if first <= x and x <= last:
            x_fit.append(x)
            y_fit.append(y)
    
    # The length of the fitting region
    len_fit = len(x_fit)
    '''
    F**K ME THIS IS BAD CODE
    '''
    wiggle_room = .2
    w_guess = 5
    const = y_fit[0]
    ysmooth = interp.interp1d(x_fit, y_fit, kind='cubic')
    # normalize d/dx of smooth spectra
    # yp = list_normalizer(np.gradient(ysmooth(x_lst)).tolist(),1,0)
    yp = np.gradient(ysmooth(x_fit)).tolist()
    # normalize d2/dx2 of smooth spectra
    #ypp = list_normalizer(np.gradient(yp).tolist(),1,0)
    ypp = np.gradient(yp).tolist()
    # we want the peaks of -d2/dx2 
    ypp = [-x for x in ypp]
    '''
    F**K ME THIS IS BAD CODE
    '''
    
    # normalize spectra
    # don't normalize it
    # spectra_lst = list_normalizer(spectra_lst,1,0)
    # interpolate spectra to smooth
    
    
    '''
    Start nailing down parameters 
    '''
    
    max_value = max(ypp)
    max_index = ypp.index(max_value)
    
    max_value = y_fit[max_index]
    peak1_guess = x_fit[max_index]
    
    '''
    First peak is easy to find, now we have two regeims for the rest
    Are the peaks distinguishable, Yes or not
    '''
    params = Parameters()
    '''
    If one wanted to put in something very tricky, like say, 
    fitting a Lorentzian to the LHS of the first peak and subtracting that
    LZ from the spectra, this is where you would do it
    ''' 
    second_index = len_fit - 5
    try: 
        # Find maximum in ypp on the range restricted to what's left of the spectra
        second_value = 0
        for x,y in zip(x_fit,ypp):
            if x > x_fit[max_index]:
                if y > second_value:
                    second_value = y
                    second_index = x_fit.index(x)
                    
    except ValueError:
        second_value = y_fit[max_index - 4]
        print "Value Error in finding second index"
        
    # Nail down the index and value for second peak
    peak2_guess = x_fit[second_index]
    second_value = y_fit[second_index]
    
    # This checks that the centers are *actually* distinguishable
    if not (9 < abs(peak1_guess - peak2_guess) < 11):
        peak2_guess = peak1_guess + 10
    
    '''
    Now we make the parameters dictionary for lmfit
    '''
    params.add('center1',value=peak1_guess,min=peak1_guess-wiggle_room*len_fit,max=peak1_guess+wiggle_room*len_fit, vary=True)
    params.add('center2',value=peak2_guess,min=peak2_guess-wiggle_room*len_fit,max=peak2_guess+wiggle_room*len_fit, vary=True)
    
    params.add('width1', value = w_guess, min = 0, max =5*w_guess, vary=True)
    params.add('width2', value = w_guess, min = 0, max =5*w_guess, vary=True)
    
    params.add('const1', value = const, min = -.1, max = .1, vary=True)
    params.add('const2', value = const, expr='const1',min = -.1, max = .1, vary=False)
    
    # scaling is given by 
    # Height max = scaling*2/(Pi* width)
    s1 = max_value*(2.0/3.14159*(params['width1'])**-1)**-1
    s2 = second_value*(2.0/3.14159*(params['width2'])**-1)**-1
                      
    # Functionally the same as what's above
    params['scaling1'] = Parameter(name='scaling1', value = s1,min = 0, max = 2*s1, vary=True)
    params['scaling2'] = Parameter(name='scaling2', value = s2,min = 0, max = 2*s2, vary=True)
    
    '''
    We have the parameters! 
    Time to do actual fitting
    '''
    
    # Work horse
    minner = Minimizer(DoubleLorentzian, params, fcn_args=(x_fit, y_fit))
    result = minner.minimize(method='least_squares')
    
    return_dict = {}
    
    for x in sorted(result.params):
        return_dict[x] = result.params[x].value
        
    return return_dict
예제 #6
0
def Ecal_old(detectors,
             motor,
             guessed_energy,
             mode,
             *,
             guessed_amplitude=0.5,
             guessed_sigma=0.004,
             min_step=0.001,
             D='LaB6',
             max_n=3,
             margin=0.5,
             md=None):
    """
    Energy calibration scan


    Parameters
    ----------
    detectors : detectors
    motor : the motor
    guessed_energy : number
        units of keV
    mode : {'peaks', 'dips'}
    guessed_amplitude : number, optional
        detector units, defaults to 1500
    guessed_sigma : number, optional
        in units of degrees, defaults to 0.004
    min_step : number, optional
        step size in degrees, defaults to 0.001
    D : string or array, optional
        Either provide the spacings literally (as an array) or
        give the name of a known spacing ('LaB6' or 'Si')
    max_n : integer, optional
        how many peaks (on one side of 0), default is 3
    margin : number, optional
        how far to scan in two theta beyond the 
        guessed left and right peaks, default 0.5

    Example
    -------
    Execute an energy calibration scan with default steps.

    >>> RE(Ecal(68))
    """
    if mode == 'peaks':
        #motor = tth_cal
        factor = 2
        offset = 0
        sign = 1
    if mode == 'dips':
        #motor = th_cal
        factor = 1
        # theta_hardware = theta_theorhetical + offset
        offset = -35.26  # degrees
        sign = -1
    if isinstance(D, str):
        D = D_SPACINGS[D]
    # Based on the guessed energy, compute where the peaks should be centered
    # in theta. This will be used as an initial guess for peak-fitting.
    guessed_wavelength = 12.398 / guessed_energy  # angtroms

    theta = np.rad2deg(np.arcsin(guessed_wavelength / (2 * D)))
    guessed_centers = factor * theta  # 'factor' puts us in two-theta units if applicable
    _range = max(guessed_centers) + (factor * margin)
    # Scan from positive to negative because that is the direction
    # that the th_cal and tth_cal motors move without backlash.
    start, stop = _range + offset, -_range + offset
    print('guessed_wavelength={} [Angstroms]'.format(guessed_wavelength))
    print('guessed_centers={} [in {}-theta DEGREES]'.format(
        guessed_centers, factor))
    print('will scan from {} to {} in hardware units'.format(start, stop))

    if max_n > 3:
        raise NotImplementedError("I only work for n up to 3.")

    # todo : make a model and sum them
    def peaks(x, c0, wavelength, a1, a2, sigma):
        # x comes from hardware in [theta or two-theta] degrees
        x = np.deg2rad(x / factor - offset)  # radians
        assert np.all(wavelength < 2 * D), \
            "wavelength would result in illegal arg to arcsin"
        cs = np.arcsin(wavelength / (2 * D))
        c1 = cs[0]
        c2 = cs[1]
        #c3 = cs[2]
        # first peak
        result = (
            voigt(x=x, amplitude=sign * a1, center=c0 - c1, sigma=sigma) +
            voigt(x=x, amplitude=sign * a1, center=c0 + c1, sigma=sigma))

        # second peak
        result += (
            voigt(x=x, amplitude=sign * a2, center=c0 - c2, sigma=sigma) +
            voigt(x=x, amplitude=sign * a2, center=c0 + c2, sigma=sigma))

        # third peak
        #result += (voigt(x=x, amplitude=sign*a3, center=c0 - c3, sigma=sigma) +
        #voigt(x=x, amplitude=sign*a3, center=c0 + c3, sigma=sigma))
        return result

    model = Model(peaks) + LinearModel()

    # Fill out initial guess.
    init_guess = {
        'intercept':
        Parameter('intercept', value=0, min=-100, max=100),
        'slope':
        Parameter('slope', value=0, min=-100, max=100),
        'sigma':
        Parameter('sigma', value=np.deg2rad(guessed_sigma)),
        'c0':
        Parameter('c0', value=np.deg2rad(0), min=-0.2, max=0.2),
        'wavelength':
        Parameter('wavelength',
                  guessed_wavelength,
                  min=0.8 * guessed_wavelength,
                  max=1.2 * guessed_wavelength)
    }
    # min=0, max=np.min(2 * D))}
    kwargs = {'min': 0.5 * guessed_amplitude, 'max': 2 * guessed_amplitude}
    for i, center in enumerate(guessed_centers):
        init_guess.update({
            'a%d' % (1 + i):
            Parameter('a%d' % (1 + i), guessed_amplitude, **kwargs)
        })
    print(init_guess)
    lf = LiveFit(model,
                 detectors[0].name, {'x': motor.name},
                 init_guess,
                 update_every=100)

    fig, ax = plt.subplots()  # explitly create figure, axes to use below
    plot = LivePlot(detectors[0].name,
                    motor.name,
                    linestyle='none',
                    marker='o',
                    ax=ax)
    lfp = LiveFitPlot(lf, ax=ax, color='r')
    subs = [lfp, plot]

    #detectors = [det]#[sc]

    # Set up metadata -- based on the sourcecode of bluesky.plans.scan.
    _md = {
        'detectors': [det.name for det in detectors],
        'motors': [motor.name],
        'hints': {},
    }
    _md.update(md or {})
    try:
        dimensions = [(motor.hints['fields'], 'primary')]
    except (AttributeError, KeyError):
        pass
    else:
        _md['hints'].setdefault('dimensions', dimensions)

    initial_steps = np.arange(start, stop, -min_step)
    assert len(initial_steps), "bad start, stop, min_step parameters"
    size = factor * 0.05  # region around each predicted peak location

    @bpp.stage_decorator(list(detectors) + [motor])
    @bpp.run_decorator(md=_md)
    def inner_scan():
        wavelength = guessed_wavelength
        for step in initial_steps:
            yield from bps.one_1d_step(detectors, motor, step)
            x_data = lf.independent_vars_data['x']
            if x_data and lf.result is not None:
                # Have we yet scanned past the third peak?
                wavelength = lf.result.values['wavelength']
                # Convert c's to hardware units here for comparison with x_data.
                c1, c2, c3 = factor * np.rad2deg(
                    np.arcsin(wavelength / (2 * D))) + offset
                if np.min(x_data) < (c1 - 1):
                    # Stop dense scanning.
                    print('Preliminary result:\n', lf.result.values)
                    print('Becoming adaptive to save time....')
                    break
        # left of zero peaks
        c1, c2, c3 = -factor * np.rad2deg(np.arcsin(wavelength /
                                                    (2 * D))) + offset
        neighborhoods = [
            np.arange(c + size, c - size, -min_step) for c in (c1, c2, c3)
        ]
        for neighborhood in neighborhoods:
            for step in neighborhood:
                yield from bps.one_1d_step(detectors, motor, step)

    plan = inner_scan()
    plan = bpp.subs_wrapper(plan, subs)
    plan = bpp.reset_positions_wrapper(plan, [motor])
    ret = (yield from plan)
    print(lf.result.values)
    print('WAVELENGTH: {} [Angstroms]'.format(lf.result.values['wavelength']))
    return ret
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)
예제 #8
0
###############################################################################
# We can review the best-fit `Parameters` by accessing `result.params`:
result.params.pretty_print()

###############################################################################
# More information about the fit is stored in the result, which is an
# ``lmfit.MimimizerResult`` object (see:
# https://lmfit.github.io/lmfit-py/fitting.html#lmfit.minimizer.MinimizerResult)

###############################################################################
# **Specifying Bounds and Holding Parameters Constant**
#
# Above, the ``Model`` class implicitly builds ``Parameter`` objects from
# keyword arguments of ``fit`` that match the argments of ``decay``. You can
# build the ``Parameter`` objects explicity; the following is equivalent.
result = model.fit(data, t=t, N=Parameter(value=10), tau=Parameter(value=1))
report_fit(result.params)

###############################################################################
# By building ``Parameter`` objects explicitly, you can specify bounds
# (``min``, ``max``) and set parameters constant (``vary=False``).
result = model.fit(data,
                   t=t,
                   N=Parameter(value=7, vary=False),
                   tau=Parameter(value=1, min=0))
report_fit(result.params)

###############################################################################
# **Defining Parameters in Advance**
#
# Passing parameters to ``fit`` can become unwieldly. As an alternative, you
예제 #9
0
    Af[i] = math.sqrt(As[i]) / 10
    i += 1
print(Af)

print('---------------------------------------------------------------------')
#Charakteristik
Ux = U[3:12]
Ax = A[3:12]


def Fit(x, m, b):
    return x * m + b


model = Model(Fit, independent_vars=['x'])
result = model.fit(Ax / 10, x=Ux, b=Parameter(value=1), m=Parameter(value=0.1))
print('Steigung =', 0.090864197530844279, '+-', 0.0222)
print('y-Achse =', 503.69013096345441, '+-', 11.4)
Stei = (ufloat(0.090864197530844279, 0.0222) * 100) / 545
print('Steigung in Prozent =', Stei * 100)
print('---------------------------------------------------------------------')

xWert = np.linspace(300, 750, 1000)
plt.errorbar(Ux,
             Ax / 10,
             yerr=Af,
             fmt='x',
             ecolor='b',
             label='relevante Messwerte')
plt.plot(U[0:2], A[0:2] / 10, 'gx')
plt.plot(U[13:16], A[13:16] / 10, 'gx')
예제 #10
0
print('-------------------------------------------------------------------')
print('Exponenten des Raumladungsgesetzes')

a = 0.0002176
konst = 4 / 9 * c.epsilon_0 * (2 * c.e / c.m_e)**(0.5) * f1 / a**2
print('m = ', konst)
print('--------------------')


def Raumladungsgesetz(V, x):
    return konst * (V**x)


model = Model(Raumladungsgesetz, independent_vars=['V'])

result1 = model.fit(I1, V=U_1, x=Parameter(value=1.5))
print('I1 = ', result1.params)
print('--------------------')

result2 = model.fit(I2, V=U_1, x=Parameter(value=1.5))
print('I2 = ', result2.params)
print('--------------------')

plt.plot(U_1, I1, 'rx', label='$I_1 = 2.5$ A')
plt.plot(U_1, I2, 'gx', label='$I_2 = 2.4$ A')
plt.plot(U_1, Raumladungsgesetz(U_1, 1.378684), 'r-', label='$I_1 = 2.5$ A')
plt.plot(U_1, Raumladungsgesetz(U_1, 1.344863), 'g-', label='$I_2 = 2.4$ A')
plt.ylabel('I / mA')
plt.xlabel('U / V')
plt.legend(loc="best")
plt.grid()
예제 #11
0
    def run_bragg_peak(self, update_table_ui=False, list_row_to_fit=None):
        gmodel = Model(kropff_bragg_peak_tof,
                       nan_policy='propagate',
                       independent_vars=['lda'])

        lda = self.xaxis_to_fit
        o_gui = GuiUtility(parent=self.parent)

        ldahkl_init = np.float(
            str(self.parent.ui.kropff_bragg_peak_ldahkl_init.text()))
        tau_init = np.float(str(self.parent.kropff_bragg_peak_tau_init.text()))
        sigma_init = np.float(
            self.parent.kropff_bragg_peak_sigma_comboBox.currentText())

        for _row, yaxis in enumerate(self.list_yaxis_to_fit):

            if not list_row_to_fit is None:
                if _row not in list_row_to_fit:
                    continue

            _entry_high = self.parent.fitting_input_dictionary['rois'][_row][
                'fitting']['kropff']['high']
            a0 = np.float(_entry_high['a0'])
            b0 = np.float(_entry_high['b0'])

            _entry_low = self.parent.fitting_input_dictionary['rois'][_row][
                'fitting']['kropff']['low']
            ahkl = np.float(_entry_low['ahkl'])
            bhkl = np.float(_entry_low['bhkl'])

            yaxis = -np.log(yaxis)

            _result = gmodel.fit(yaxis,
                                 lda=lda,
                                 a0=Parameter('a0', value=a0, vary=False),
                                 b0=Parameter('b0', value=b0, vary=False),
                                 ahkl=Parameter('ahkl', value=ahkl,
                                                vary=False),
                                 bhkl=Parameter('bhkl', value=bhkl,
                                                vary=False),
                                 ldahkl=ldahkl_init,
                                 sigma=sigma_init,
                                 tau=tau_init)

            ldahkl = _result.params['ldahkl'].value
            ldahkl_error = _result.params['ldahkl'].stderr
            sigma = _result.params['sigma'].value
            sigma_error = _result.params['sigma'].stderr
            tau = _result.params['tau'].value
            tau_error = _result.params['tau'].stderr

            yaxis_fitted = kropff_bragg_peak_tof(self.xaxis_to_fit, a0, b0,
                                                 ahkl, bhkl, ldahkl, sigma,
                                                 tau)

            result_dict = {
                'ldahkl': ldahkl,
                'ldahkl_error': ldahkl_error,
                'sigma': sigma,
                'sigma_error': sigma_error,
                'tau': tau,
                'tau_error': tau_error,
                'xaxis_to_fit': lda,
                'yaxis_fitted': yaxis_fitted
            }

            self.parent.fitting_input_dictionary['rois'][_row]['fitting'][
                'kropff']['bragg_peak'] = deepcopy(result_dict)

            if update_table_ui:
                o_gui.update_kropff_bragg_edge_table_ui(
                    row=_row,
                    ldahkl=ldahkl,
                    ldahkl_error=ldahkl_error,
                    tau=tau,
                    tau_error=tau_error,
                    sigma=sigma,
                    sigma_error=sigma_error)
예제 #12
0
    def test_sum_of_two_gaussians(self):

        # two user-defined gaussians
        model1 = self.model
        f2 = lambda x, height_, center_, sigma_: gaussian(
            x, height_, center_, sigma_)
        model2 = Model(f2, ['x'])
        values1 = self.true_values()
        values2 = self.true_values()
        values2['sigma'] = 1.5
        values2['height'] = 4
        data = gaussian(x=self.x, **values1)
        data += gaussian(x=self.x, **values2)
        model = self.model + model2
        values2 = {k + '_': v for k, v in values2.items()}
        guess = {
            'sigma': Parameter(value=2, min=0),
            'center': 1,
            'height': 1,
            'sigma_': Parameter(value=1, min=0),
            'center_': 1,
            'height_': 1
        }

        true_values = dict(list(values1.items()) + list(values2.items()))
        result = model.fit(data, x=self.x, **guess)
        assert_results_close(result.values, true_values)

        # 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 = specified_models.Gaussian(['x'])
        model2 = specified_models.Gaussian(['x'], suffix='_')
        model = model1 + model2
        true_values = {
            'center': values1['center'],
            'height': values1['height'],
            'sigma': values1['sigma'],
            'center_': values2['center_'],
            'height_': values2['height_'],
            'sigma_': values2['sigma_']
        }
        guess = {
            'sigma': 2,
            'center': 1,
            'height': 1,
            'sigma_': 1,
            'center_': 1,
            'height_': 1
        }
        result = model.fit(data, x=self.x, **guess)
        assert_results_close(result.values, true_values)

        # without suffix, the names collide and Model should raise
        model1 = specified_models.Gaussian(['x'])
        model2 = specified_models.Gaussian(['x'])
        f = lambda: model1 + model2
        self.assertRaises(NameError, f)
예제 #13
0
#Auslenkung in Grad für Rubidium
R_r = (np.array([343.7, 344.5]) - HM) * (math.pi/180)
tR_r = 2.92

print('------------------------------------------------------------------')
print('Nr. a: Berechnung der Gitterkonstanten g')

Rad_H = np.sin((np.array([331.1, 331.7, 333.2, 334.6, 335.4, 335.6, 341.4, 347.3, 350.5]) - HM) * (math.pi/180))
Lambda = np.array([438.8, 447.1, 471.3, 492.2, 501.6, 504.8, 587.6, 667.8, 706.5]) * 10**(-9)

def Gitter(x, m, b):
    return x/m + b

model = Model(Gitter, independent_vars=['x'])

result = model.fit(Rad_H, x=Lambda, b=Parameter(value=0.1), m=Parameter(value=10**(-6)))
print(result.params)

x_Wert = np.linspace(400, 750, 10000) * 10**(-9)
plt.plot(Lambda * 10**(9), Rad_H, 'rx', label='Messwerte')
plt.plot(x_Wert * 10**(9), Gitter(x_Wert, **result.params), 'b-', label='Ausgleichsgerade')
plt.xlabel('$\lambda$ / $10^{-9}$ m')
plt.ylabel('$\sin(\phi)$')
plt.legend(loc="best")
plt.grid()
plt.tight_layout()
plt.savefig('build/Gitterkonstante.pdf')
plt.close()

print('------------------------------------------------------------------')
print('Nr. b: Berechnung der Eichgröße')
예제 #14
0
def fit_decaying_oscillation(y_array, x_array, d=2, freq_init=None, amp_init=None, phase_init=0, y0_init=None):
    """
    Fit y_array with Gaussian decay oscillations.
    """
    def oscillation(t, y0, amplitude, freq, t2, phase):
        return y0 + amplitude * np.exp(-(t/t2)**d) * np.cos(2*pi*freq*t + phase)

    time_scale = x_array[-1] - x_array[0]
    if freq_init is None:
        freq_init = 10.0/time_scale
    if amp_init is None:
        amp_init = y_array[0] - y_array[-1]
    if y0_init is None:
        y0_init = y_array[-1]
    model = lmfit.Model(oscillation, independent_vars=['t'])
    result = model.fit(y_array, t=x_array, y0=y0_init, amplitude=amp_init, freq=freq_init, t2=Parameter(value=time_scale/2, min=0), phase=phase_init)
    return result
예제 #15
0
p_true.add('cen_g', value=8.1)
p_true.add('wid_g', value=1.6)
p_true.add('frac', value=0.37)
p_true.add('line_off', value=-1.023)
p_true.add('line_slope', value=0.62)

data = (pvoigt(x, p_true['amp_g'].value, p_true['cen_g'].value,
               p_true['wid_g'].value, p_true['frac'].value) +
        random.normal(scale=0.23, size=n) + x * p_true['line_slope'].value +
        p_true['line_off'].value)

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

pfit = [
    Parameter(name='amp_g', value=10),
    Parameter(name='amp_g', value=10.0),
    Parameter(name='cen_g', value=9),
    Parameter(name='wid_g', value=1),
    Parameter(name='frac', value=0.50),
    Parameter(name='amp_l', expr='amp_g'),
    Parameter(name='cen_l', expr='cen_g'),
    Parameter(name='wid_l', expr='wid_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,
예제 #16
0
    def __init__(self, config):
        
        defaultRkpVary = True
        defaultRkpMin = float("-inf")
        defaultRkpMax = float("inf")
        
        params = Parameters()
        
        equationName = ""
        
        try:
            equationName = config['equation']
            
            if equationName == "density":
                params['c1'] = Parameter('c1', value=(1.0 / config['compounds'][0]['density']), vary=False)
                params['c2'] = Parameter('c2', value=(1.0 / config['compounds'][1]['density']), vary=False)
                params['c3'] = Parameter('c3', value=(1.0 / config['compounds'][2]['density']), vary=False)
            elif equationName == "volume":
                params['c1'] = Parameter('c1', value=config['compounds'][0]['volume'], vary=False)
                params['c2'] = Parameter('c2', value=config['compounds'][1]['volume'], vary=False)
                params['c3'] = Parameter('c3', value=config['compounds'][2]['volume'], vary=False)
            elif equationName == "conductivity":
                params['c1'] = Parameter('c1', value=config['compounds'][0]['conductivity'], vary=False)
                params['c2'] = Parameter('c2', value=config['compounds'][1]['conductivity'], vary=False)
                params['c3'] = Parameter('c3', value=config['compounds'][2]['conductivity'], vary=False)
            else:
                raise ValueError("Unknown equation '{}'".format(config['equation']))
        except KeyError:
            equationName = "density"
            
            print "Equation parameter must be set. Using 'density' equation ..."
            
            params['c1'] = Parameter('c1', value=(1.0 / config['compounds'][0]['density']), vary=False)
            params['c2'] = Parameter('c2', value=(1.0 / config['compounds'][1]['density']), vary=False)
            params['c3'] = Parameter('c3', value=(1.0 / config['compounds'][2]['density']), vary=False)

        rkp12Conf = config['binary']['rkp']['x1-x2']
        
        params['rkp12_1'] = \
                Parameter('rkp12_1', \
                        value=rkp12Conf[0]['value'],
                        vary=(rkp12Conf[0]['vary'] if 'vary' in rkp12Conf[0] else defaultRkpVary), \
                        min=(rkp12Conf[0]['min'] if 'min' in rkp12Conf[0] else defaultRkpMin), \
                        max=(rkp12Conf[0]['max'] if 'max' in rkp12Conf[0] else defaultRkpMax))
        params['rkp12_2'] = \
                Parameter('rkp12_2', \
                        value=rkp12Conf[1]['value'],
                        vary=(rkp12Conf[1]['vary'] if 'vary' in rkp12Conf[1] else defaultRkpVary), \
                        min=(rkp12Conf[1]['min'] if 'min' in rkp12Conf[1] else defaultRkpMin), \
                        max=(rkp12Conf[1]['max'] if 'max' in rkp12Conf[1] else defaultRkpMax))
        params['rkp12_3'] = \
                Parameter('rkp12_3', \
                        value=rkp12Conf[2]['value'],
                        vary=(rkp12Conf[2]['vary'] if 'vary' in rkp12Conf[2] else defaultRkpVary), \
                        min=(rkp12Conf[2]['min'] if 'min' in rkp12Conf[2] else defaultRkpMin), \
                        max=(rkp12Conf[2]['max'] if 'max' in rkp12Conf[2] else defaultRkpMax))

        rkp13Conf = config['binary']['rkp']['x1-x3']
        
        params['rkp13_1'] = \
                Parameter('rkp13_1', \
                        value=rkp13Conf[0]['value'],
                        vary=(rkp13Conf[0]['vary'] if 'vary' in rkp13Conf[0] else defaultRkpVary), \
                        min=(rkp13Conf[0]['min'] if 'min' in rkp13Conf[0] else defaultRkpMin), \
                        max=(rkp13Conf[0]['max'] if 'max' in rkp13Conf[0] else defaultRkpMax))
        params['rkp13_2'] = \
                Parameter('rkp13_2', \
                        value=rkp13Conf[1]['value'],
                        vary=(rkp13Conf[1]['vary'] if 'vary' in rkp13Conf[1] else defaultRkpVary), \
                        min=(rkp13Conf[1]['min'] if 'min' in rkp13Conf[1] else defaultRkpMin), \
                        max=(rkp13Conf[1]['max'] if 'max' in rkp13Conf[1] else defaultRkpMax))
        params['rkp13_3'] = \
                Parameter('rkp13_3', \
                        value=rkp13Conf[2]['value'],
                        vary=(rkp13Conf[2]['vary'] if 'vary' in rkp13Conf[2] else defaultRkpVary), \
                        min=(rkp13Conf[2]['min'] if 'min' in rkp13Conf[2] else defaultRkpMin), \
                        max=(rkp13Conf[2]['max'] if 'max' in rkp13Conf[2] else defaultRkpMax))

        
        rkp23Conf = config['binary']['rkp']['x2-x3']
        
        params['rkp23_1'] = \
                Parameter('rkp23_1', \
                        value=rkp23Conf[0]['value'],
                        vary=(rkp23Conf[0]['vary'] if 'vary' in rkp23Conf[0] else defaultRkpVary), \
                        min=(rkp23Conf[0]['min'] if 'min' in rkp23Conf[0] else defaultRkpMin), \
                        max=(rkp23Conf[0]['max'] if 'max' in rkp23Conf[0] else defaultRkpMax))
        params['rkp23_2'] = \
                Parameter('rkp23_2', \
                        value=rkp23Conf[1]['value'],
                        vary=(rkp23Conf[1]['vary'] if 'vary' in rkp23Conf[1] else defaultRkpVary), \
                        min=(rkp23Conf[1]['min'] if 'min' in rkp23Conf[1] else defaultRkpMin), \
                        max=(rkp23Conf[1]['max'] if 'max' in rkp23Conf[1] else defaultRkpMax))
        params['rkp23_3'] = \
                Parameter('rkp23_3', \
                        value=rkp23Conf[2]['value'],
                        vary=(rkp23Conf[2]['vary'] if 'vary' in rkp23Conf[2] else defaultRkpVary), \
                        min=(rkp23Conf[2]['min'] if 'min' in rkp23Conf[2] else defaultRkpMin), \
                        max=(rkp23Conf[2]['max'] if 'max' in rkp23Conf[2] else defaultRkpMax))

        rkp123Conf = config['ternary']['rkp']
        
        params['rkp123_1'] = \
                Parameter('rkp123_1', \
                        value=rkp123Conf[0]['value'],
                        vary=(rkp123Conf[0]['vary'] if 'vary' in rkp123Conf[0] else defaultRkpVary), \
                        min=(rkp123Conf[0]['min'] if 'min' in rkp123Conf[0] else defaultRkpMin), \
                        max=(rkp123Conf[0]['max'] if 'max' in rkp123Conf[0] else defaultRkpMax))
        params['rkp123_2'] = \
                Parameter('rkp123_2', \
                        value=rkp123Conf[1]['value'],
                        vary=(rkp123Conf[1]['vary'] if 'vary' in rkp123Conf[1] else defaultRkpVary), \
                        min=(rkp123Conf[1]['min'] if 'min' in rkp123Conf[1] else defaultRkpMin), \
                        max=(rkp123Conf[1]['max'] if 'max' in rkp123Conf[1] else defaultRkpMax))
        params['rkp123_3'] = \
                Parameter('rkp123_3', \
                        value=rkp123Conf[2]['value'],
                        vary=(rkp123Conf[2]['vary'] if 'vary' in rkp123Conf[2] else defaultRkpVary), \
                        min=(rkp123Conf[2]['min'] if 'min' in rkp123Conf[2] else defaultRkpMin), \
                        max=(rkp123Conf[2]['max'] if 'max' in rkp123Conf[2] else defaultRkpMax))
        
        # data
        rawdata = np.array(config['data'])
        
        rawdataLength = len(rawdata)
        
        data = np.delete(rawdata, 4, 1)

        exp = np.delete(rawdata, [0, 1, 2, 3], 1).reshape((rawdataLength,))
        
        if equationName == "density":
            for i in range(len(exp)):
                exp[i] = (1.0 / exp[i]) if exp[i] != 0.0 else 0.0
        
        # set properties
        self.equationModel = EquationModel()
        self.params = params
        self.data = data
        self.exp = exp
예제 #17
0
def fit_Ecal_dips_symmetric(xdata,
                            ydata,
                            guessed_sigma=.01,
                            wguess=66.,
                            D="Si",
                            theta_offset=-35.26):
    '''
        This fits for two symmetric peaks.

        Parameters
        ----------
        xdata : the xdata (usually theta)
        ydata : the counts measured
        guessed_sigma: float, optional
            the guessed sigma of the peaks (supplied to initial guess)
        wguess :
                the guessed wavelength
        D : str
            The str identifier for the reference sample (usually just "Si")
        theta_offset :
            The offset in theta of the theta motor
    '''
    # this is a cludge used to pass result around.
    # TODO : remove this when we finally agree on a method on how to scan...
    if isinstance(D, str):
        D = D_SPACINGS[D]

    guessed_wavelength = wguess

    # theta-tth factor
    factor = 1
    offset = theta_offset  # degrees

    # TODO : Make a Model
    #def dips(x, c0, wavelength, a1, a2, sigma):
    def dips(x, c0, wavelength, a1, sigma):
        sign = -1
        # x comes from hardware in [theta or two-theta] degrees
        x = np.deg2rad(x / factor - offset)  # radians
        assert np.all(wavelength < 2 * D), \
            "wavelength would result in illegal arg to arcsin"
        centers = np.arcsin(wavelength / (2 * D))
        # just look at one center for now
        c1 = centers[0]

        result = (
            voigt(x=x, amplitude=sign * a1, center=c0 - c1, sigma=sigma) +
            voigt(x=x, amplitude=sign * a1, center=c0 + c1, sigma=sigma))

        return result

    model = Model(dips) + LinearModel()

    guessed_average = np.max(ydata)
    guessed_amplitude = np.abs(np.min(ydata) - np.mean(ydata))
    # Fill out initial guess.
    init_guess = {
        'intercept':
        Parameter(
            'intercept',
            value=guessed_average,
        ),
        'slope':
        Parameter('slope', value=0, min=-100, max=100, vary=False),
        'sigma':
        Parameter('sigma', value=np.deg2rad(guessed_sigma)),
        'c0':
        Parameter('c0', value=np.deg2rad(0)),
        'wavelength':
        Parameter('wavelength',
                  guessed_wavelength,
                  min=0.8 * guessed_wavelength,
                  max=1.2 * guessed_wavelength),
        'a1':
        Parameter('a1', guessed_amplitude, min=0),
    }
    params = Parameters(init_guess)

    # fit_kwargs = dict(ftol=1)
    fit_kwargs = dict()
    result = model.fit(ydata, x=xdata, params=params, fit_kwargs=fit_kwargs)
    print('WAVELENGTH: {} [Angstroms]'.format(result.values['wavelength']))
    print('CENTER is : {} [deg]'.format(result.values['c0']))

    plt.figure(2)
    plt.clf()
    plt.plot(xdata, ydata, linewidth=0, marker='o', color='b', label="data")
    plt.plot(xdata, result.best_fit, color='r', label="best fit")
    plt.legend()
    return result
def pool_data(files,
              dt,
              minframe=5,
              maxframe=10000,
              rsquared_threshold=0.0,
              fit_option=2,
              display_id=False,
              dataframe=True):
    """This function reads the trajectories in all of the files, computes the T-MSD, performs a fit to evaluate D and alpha.
	
	Parameters
	----------
	files : list of str
	    The list of the TrackMate CSV filenames, containing columns POSITION_X, POSITION_Y and TRACK_ID
	dt : float
	    time step between each position in the trajectories
	minframe, maxframe : int 
	    filter on the minimum / maximum number of frames per retained trajectory. Default set to respectively 5 and 10000.
	rsquared_threshold : float <= 1
	    filter on the minimum value for the coefficient of determination during the fit of the T-MSDs. Default is 0.0.
	fit_option : int or list or str
	    options for the points to consider during the fit of the T-MSD. If int, the fit is performed over the N first points. If list the fit is performed from the first element to the second. str option available: "thirty_percent". Default is 2.
	display_id : bool, optional
	    prints the ID of the tracks as they are being processed. Useful if the analysis is too slow. Default is disabled.
	dataframe : bool, optional
	    returns a DataFrame instead of a numpy array. The diffusion coefficient is directly transformed to its log10 form. Default is enabled.
	    
	Returns
	-------
	df
	    a DataFrame collecting all of the generated data
	DATA
	    a numpy matrix containing the same information
	"""

    #Initial tests:
    if isinstance(files, list) == False:
        print(
            "Please provide a list of TrackMate CSV files, with columns POSITION_X, POSITION_Y and TRACK_ID."
        )
        return
    else:
        print("Parameters for the MSD analysis: dt = ", dt)
        print('Initial filters: minframe = ', minframe, ', maxframe = ',
              maxframe, ', R2 threshold = ', rsquared_threshold)
        print("Fit option: ", fit_option)

    #Parameters for the fit
    minalpha = 0.1
    minD = 1.0E-06
    maxD = 1
    maxalpha = 3

    def msdlog(logt, D, alpha):
        return (alpha * logt + np.log(4 * D))

    msdlog_model = Model(msdlog)
    params = Parameters()
    params['alpha'] = Parameter(name='alpha',
                                value=1.0,
                                min=minalpha,
                                max=maxalpha)
    params['D'] = Parameter(name='D', value=0.1, min=minD, max=maxD)

    #Interpret fit option that does not depend on the tracklength
    if isinstance(fit_option, int):
        nbrpts = fit_option
        n0 = 0

    elif isinstance(fit_option, list):
        nbrpts = fit_option[1]
        n0 = fit_option[0]

    DATA = []  #Initialize the DATA output matrix
    print("Reading filenames in ", str(files), '...')

    for p in range(len(files)):
        filename = files[p]
        print('Analysis for', filename, '...')

        data = pd.read_csv(filename)
        tracklist = data.TRACK_ID.unique()  #list of track IDs in the file
        conserved_tracks = 0
        idxt = 0
        for tid in tracklist:

            if display_id == True:
                print('Track ' + str(idxt) + ' out of ' + str(len(tracklist)))

            trackid = data["TRACK_ID"] == tid
            x = data[trackid]["POSITION_X"].to_numpy(
            )  #x associated to track 'tid'
            y = data[trackid]["POSITION_Y"].to_numpy(
            )  #y associated to track 'tid'
            N = len(x)
            if N <= maxframe and N >= minframe:
                tmsd, timelag = T_MSD(x, y, dt)

                #Interpret fit option
                if fit_option == "thirty_percent":
                    nbrpts = round(0.31 * N)
                    n0 = 0

                result = msdlog_model.fit(
                    [np.log(k) for k in tmsd[n0:nbrpts]],
                    params,
                    logt=[np.log(k) for k in timelag[n0:nbrpts]])
                alpha = result.params['alpha'].value
                D = result.params['D'].value

                N_for_R2 = round(
                    0.6 * len(tmsd))  #evaluate R2 on a third of the MSD length
                y_true = tmsd[:N_for_R2]
                y_pred = [4 * D * ndt**alpha for ndt in timelag[:N_for_R2]]
                rsquare = r2_score(y_true, y_pred)

                c = confinement_ratio(x, y)

                if rsquare > rsquared_threshold:
                    feat = [alpha, D, c, rsquare, N, x, y, tmsd, filename]
                    DATA.append(feat)
                    conserved_tracks += 1
            idxt += 1
        print(conserved_tracks, " tracks were kept out of ", len(trackid),
              '. Done.')

    if dataframe == True:
        print("Generating a DataFrame...")
        df = pd.DataFrame(DATA,
                          columns=[
                              'alpha', 'D', 'c', 'R2', 'N', 'x', 'y', 'MSD',
                              'Filename'
                          ])
        df['D'] = df['D'].map(lambda x: np.log10(x))
        print("End of the program. Returning DataFrame.")
        return (df)
    else:
        print("End of the program. Returning numpy array.")
        return (DATA)
예제 #19
0
def calib_g(df_fc_suews, g_max=33.1, lai_max=5.9, s1=5.56, method='cobyla', prms_init=None, debug=False):
    """Calibrate parameters for modelling surface conductance over vegetated surfaces using `LMFIT <https://lmfit.github.io/lmfit-py/model.html>`.

    Parameters
    ----------
    df_fc_suews : pandas.DataFrame
        DataFrame in `SuPy forcing <https://supy.readthedocs.io/en/latest/data-structure/df_forcing.html>`_ format
    g_max : numeric, optional
        Maximum surface conductance [mm s-1], by default 30
    lai_max : numeric, optional
        Maximum LAI [m2 m-2], by default 6
    s1 : numeric, optional
        Wilting point (WP=s1/g6, indicated as deficit [mm]) related parameter, by default 5.56
    method: str, optional
        Method used in minimisation by `lmfit.minimize`: details refer to its `method<lmfit:minimize>`.
    prms_init: lmfit.Parameters
        Initial parameters for calibration
    debug : bool, optional
        Option to output final calibrated `ModelResult <lmfit:ModelResult>`, by default False

    Returns
    -------
    dict, or `ModelResult <lmfit:ModelResult>` if `debug==True`
        1. dict: {parameter_name -> best_fit_value}
        2. `ModelResult`

        Note:
            Parameters for surface conductance:
            g1 (LAI related), g2 (solar radiation related),
            g3 (humidity related), g4 (humidity related),
            g5 (air temperature related),
            g6 (soil moisture related)

    Note
    ----
    For calibration validity, turbulent fluxes, QH and QE, in `df_fc_suews` should ONLY be observations, i.e., interpolated values should be avoided.
    To do so, please place `np.nan` as missing values for QH and QE.

    """
    list_var_sel = ['qh', 'qe', 'Tair', 'RH', 'pres', 'kdown', 'xsmd', 'lai']
    df_obs = df_fc_suews[list_var_sel].copy().dropna()
    df_obs.pres *= 100
    df_obs.Tair += 273.15

    gs_obs = cal_gs_obs(df_obs.qh, df_obs.qe, df_obs.Tair,
                        df_obs.RH, df_obs.pres)

    def func_fit_g(kd, ta, rh, pa, smd, lai, g1, g2, g3, g4, g5, g6):
        return cal_gs_mod(kd, ta, rh, pa, smd, lai,
                          [g1, g2, g3, g4, g5, g6],
                          g_max, lai_max, s1)

    gmodel = Model(func_fit_g,
                   independent_vars=['lai', 'kd', 'ta', 'rh', 'pa', 'smd'],
                   param_names=['g1', 'g2', 'g3', 'g4', 'g5', 'g6'])
    if prms_init is None:
        print('Preset parameters will be loaded!')
        print('Please use with caution.')
        prms = Parameters()
        prm_g_0 = [3.5, 200.0, 0.13, 0.7, 30.0, 0.05]
        list_g = (Parameter(f'g{i+1}', prm_g_0[i], True, 0, None, None,
                            None) for i in range(6))
        prms.add_many(*list_g)
        # set specific bounds:
        # g3, g4: specific humidity related
        prms['g3'].set(min=0, max=1)
        prms['g4'].set(min=0, max=1)
        # g5: within reasonable temperature ranges
        prms['g5'].set(min=-10, max=55)
        # g6: within sensitive ranges of SMD
        prms['g6'].set(min=.02, max=.1)
    else:
        print('User provided parameters are loaded!')
        prms = prms_init

    # pack into a DataFrame for filtering out nan
    df_fit = pd.concat([gs_obs.rename('gs_obs'), df_obs], axis=1).dropna()

    res_fit = gmodel.fit(
        df_fit.gs_obs,
        kd=df_fit.kdown,
        ta=df_fit.Tair,
        rh=df_fit.RH,
        pa=df_fit.pres,
        smd=df_fit.xsmd,
        lai=df_fit.lai,
        params=prms,
        # useful ones: ['nelder', 'powell', 'cg', 'cobyla', 'bfgs', 'trust-tnc']
        method=method,
        #     nan_policy='omit',
        verbose=True,
    )

    # provide full fitted model if debug == True otherwise only a dict with best fit parameters
    res = res_fit if debug else res_fit.best_values

    return res
예제 #20
0
result.params.pretty_print()

###############################################################################
# More information about the fit is stored in the result, which is an
# ``lmfit.MimimizerResult`` object (see:
# https://lmfit.github.io/lmfit-py/fitting.html#lmfit.minimizer.MinimizerResult)

###############################################################################
# **Specifying Bounds and Holding Parameters Constant**
#
# Above, the ``Model`` class implicitly builds ``Parameter`` objects from
# keyword arguments of ``fit`` that match the arguments of ``decay``. You can
# build the ``Parameter`` objects explicitly; the following is equivalent.
result = model.fit(data,
                   t=t,
                   N=Parameter('N', value=10),
                   tau=Parameter('tau', value=1))
report_fit(result.params)

###############################################################################
# By building ``Parameter`` objects explicitly, you can specify bounds
# (``min``, ``max``) and set parameters constant (``vary=False``).
result = model.fit(data,
                   t=t,
                   N=Parameter('N', value=7, vary=False),
                   tau=Parameter('tau', value=1, min=0))
report_fit(result.params)

###############################################################################
# **Defining Parameters in Advance**
#
예제 #21
0
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 = [
        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'),
        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)

    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)
예제 #22
0
    return (model - data) / sigma


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

data = (gauss(x, 21, 8.1, 1.2) + loren(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'),
    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, ),
예제 #23
0
         "T_i_0": None
     },
     ValueError,
     "was not provided in parameters, but is required.",
 ),
 (
     {
         "T_i_1": None
     },
     ValueError,
     "was not provided in parameters, but is required.",
 ),
 # If speed is not zero, vdir must be set
 (
     {
         "electron_speed_0": Parameter("electron_speed_0", 1e5),
         "electron_vdir": None,
     },
     ValueError,
     "electron_vdir must be set if electron_speeds",
 ),
 (
     {
         "ion_speed_0": Parameter("ion_speed_0", 1e5),
         "ion_vdir": None
     },
     ValueError,
     "ion_vdir must be set if ion_speeds",
 ),
 # Test different input types for ``ions``
 ({
예제 #24
0
파일: _gs.py 프로젝트: LewisB7/SuPy
def calib_g(
    df_fc_suews,
    ser_ra,
    g_max,
    lai_max,
    wp_smd,
    method="cobyla",
    prms_init=None,
    debug=False,
):
    """Calibrate parameters for modelling surface conductance over vegetated surfaces using `LMFIT <https://lmfit.github.io/lmfit-py/model.html>`.

    Parameters
    ----------
    df_fc_suews : pandas.DataFrame
        DataFrame in `SuPy forcing <https://supy.readthedocs.io/en/latest/data-structure/df_forcing.html>`_ format
    ser_ra: pandas.Series
        Series with RA, aerodynamic resistance, [s m-1]
    g_max : numeric
        Maximum surface conductance [mm s-1]
    lai_max : numeric
        Maximum LAI [m2 m-2]
    wp_smd : numeric
        Wilting point indicated as soil moisture deficit [mm]
    method: str, optional
        Method used in minimisation by `lmfit.minimize`: details refer to its `method<lmfit:minimize>`.
    prms_init: lmfit.Parameters, optional
        Initial parameters for calibration
    debug : bool, optional
        Option to output final calibrated `ModelResult <lmfit:ModelResult>`, by default False

    Returns
    -------
    dict, or `ModelResult <lmfit:ModelResult>` if `debug==True`
        1. dict: {parameter_name -> best_fit_value}
        2. `ModelResult`

        Note:
            Parameters for surface conductance:
            g_lai (LAI related), g2 (solar radiation related),
            g_dq_base (humidity related), g_dq_shape (humidity related),
            g_ta (air temperature related),
            g_smd (soil moisture related)

    Note
    ----
    For calibration validity, turbulent fluxes, QH and QE, in `df_fc_suews` should ONLY be observations, i.e., interpolated values should be avoided.
    To do so, please place `np.nan` as missing values for QH and QE.

    """
    from lmfit import Model, Parameter, Parameters

    list_var_sel = ["qh", "qe", "Tair", "RH", "pres", "kdown", "xsmd", "lai"]
    df_obs = df_fc_suews[list_var_sel].copy().dropna()

    # convert to Pa
    df_obs.pres *= 100

    gs_obs = cal_gs_obs(
        df_obs.qh, df_obs.qe, df_obs.Tair, df_obs.RH, df_obs.pres, ser_ra
    )

    def func_fit_g(
        kd, ta, rh, pa, smd, lai, g_lai, g_kd, g_dq_base, g_dq_shape, g_ta, g_smd
    ):
        gs = cal_gs_suews(
            kd,
            ta,
            rh,
            pa,
            smd,
            lai,
            [g_lai, g_kd, g_dq_base, g_dq_shape, g_ta, g_smd],
            g_max,
            lai_max,
            wp_smd,
        )
        return gs

    gmodel = Model(
        func_fit_g,
        independent_vars=["lai", "kd", "ta", "rh", "pa", "smd"],
        param_names=["g_lai", "g_kd", "g_dq_base", "g_dq_shape", "g_ta", "g_smd"],
    )
    if prms_init is None:
        print("Preset parameters will be loaded!")
        print("Please use with caution.")
        prms = Parameters()
        dict_prms_init = {
            "lai": 3.5,
            "kd": 50,
            "q1": 0.1,
            "q2": 0.7,
            "ta": 25,
            "smd": 0.05,
        }
        list_g = (
            Parameter(f"g_{var}", val, True, 0, None, None, None)
            for var, val in dict_prms_init.items()
        )
        prms.add_many(*list_g)
        # set specific bounds:
        # g_lai: LAI related
        prms["g_lai"].set(min=0, max=10)

        prms["g_kd"].set(min=0, max=300)
        # g_dq_base, g_dq_shape: specific humidity related
        prms["g_dq_base"].set(min=0, max=1)
        prms["g_dq_shape"].set(min=0, max=1)
        # g_ta: within reasonable temperature ranges
        prms["g_ta"].set(min=-10, max=55)
        # g_smd: within sensitive ranges of SMD
        prms["g_smd"].set(min=0.02, max=0.1)
    else:
        print("User provided parameters are loaded!")
        prms = prms_init

    # pack into a DataFrame for filtering out nan
    df_fit = pd.concat([gs_obs.rename("gs_obs"), df_obs], axis=1).dropna()

    res_fit = gmodel.fit(
        df_fit.gs_obs,
        kd=df_fit.kdown,
        ta=df_fit.Tair,
        rh=df_fit.RH,
        pa=df_fit.pres,
        smd=df_fit.xsmd,
        lai=df_fit.lai,
        params=prms,
        # useful ones: ['nelder', 'powell', 'cg', 'cobyla', 'bfgs', 'trust-tnc']
        method=method,
        #     nan_policy='omit',
        verbose=True,
    )

    # provide full fitted model if debug == True otherwise only a dict with best fit parameters
    res = res_fit if debug else res_fit.best_values

    return res