def fit_three_peaks(peak_data,
                    pv_1_cent=3.43,
                    pv_1_min=3.36,
                    pv_1_max=3.44,
                    pv_2_cent=3.52,
                    pv_2_min=3.42,
                    pv_2_max=3.55,
                    pv_3_cent=3.59,
                    pv_3_min=3.54,
                    pv_3_max=3.6,
                    initParams=None):
    """ Pseudo-Voigt fit to the lattice plane peak intensity for three peaks (adjust function to include more).
        Parameters for each peak also require limits and centres to be set in the case of overlapping peaks.
        Return results of the fit as an lmfit class, which contains the fitted parameters (amplitude, fwhm, etc.) 
        and the fit line calculated using the fit parameters and 100x two-theta points.
    """
    ttheta = peak_data[:, 0]
    intensity = peak_data[:, 1]

    PV_1 = PseudoVoigtModel(prefix='pv_1')
    PV_2 = PseudoVoigtModel(prefix='pv_2')
    PV_3 = PseudoVoigtModel(prefix='pv_3')

    model = PV_1 + PV_2 + PV_3 + Model(line)

    if initParams is None:
        # if reflection == '(0002),(110),(10-11)': use starting centres 3.43(min=3.36,max=3.44), 3.54(min=3.42,max=3.55), 3.59(min=3.54,max=3.6)...
        #if reflection == '(20-20),(11-22),(20-21)': use starting centres 6.32(min=6.23,max=6.33), 6.45(min=6.37,max=6.47), 6.54(min=6.46,max=6.56)...
        pars_1 = PV_1.guess(intensity, x=ttheta)
        #note, min and max values are not the same as bounds around the peak, but values that they can go up to!
        pars_1['pv_1center'].set(pv_1_cent, min=pv_1_min, max=pv_1_max)
        #pars_1['pv_1sigma'].set(min=0.001, max=0.1)
        #pars_1['pv_1amplitude'].set(min=0)
        #pars_1['pv_1height'].set(min=10)
        #pars_1['pv_1fwhm'].set(min=0.02, max=0.2)

        pars_2 = PV_2.guess(intensity, x=ttheta)
        pars_2['pv_2center'].set(pv_2_cent, min=pv_2_min, max=pv_2_max)
        #pars_2['pv_2sigma'].set(min=0.001, max=0.1)
        #pars_2['pv_2amplitude'].set(min=0)
        #pars_2['pv_2height'].set(min=10, max = 5000)
        #pars_2['pv_2fwhm'].set(min=0.02, max=0.2)

        pars_3 = PV_3.guess(intensity, x=ttheta)
        pars_3['pv_3center'].set(pv_3_cent, min=pv_3_min, max=pv_3_max)
        #pars_3['pv_3sigma'].set(min=0.001, max=0.1)
        #pars_3['pv_3amplitude'].set(min=1)
        #pars_3['pv_3height'].set(min=10)
        #pars_3['pv_3fwhm'].set(min=0.02, max=0.2)

        pars = pars_1 + pars_2 + pars_3
        pars.add("constBG", 0)

    else:
        pars = initParams
    fit_results = model.fit(intensity, pars, x=ttheta)
    fit_ttheta = np.linspace(ttheta[0], ttheta[-1], 100)
    fit_line = [fit_ttheta, model.eval(fit_results.params, x=fit_ttheta)]
    return fit_results, fit_line
Пример #2
0
def fit_one_Psudo_Voigt(x_lst,y_lst):
    '''
    Fits one Pseudo Voigt returns the 
    results object
    '''
    mod = PseudoVoigtModel(independent_vars=['x'],nan_policy='raise')
    
    x_lst = np.asarray(x_lst)
    y_lst = np.asarray(y_lst)
    # Guess good values computer
    mod.guess(y_lst,x = x_lst)
    
    result = mod.fit(y_lst, x = x_lst)
    
    return result
Пример #3
0
 def guess_params(self, peak):
     """Guesses parameters for a new peak and adds it. See add_peak()."""
     if peak.region is not self._region:
         logger.error("peak with ID {} does not belong to region ID {}"
                      "".format(peak.ID, self._region.ID))
         raise ValueError("Peak does not belong to Region")
     if peak.model_name == "PseudoVoigt":
         model = PseudoVoigtModel(prefix=peak.prefix)
         # model.set_param_hint("fraction", vary=False)
     else:
         raise NotImplementedError("Only PseudoVoigt models supported")
     other_models_cps = [0] * len(self._region.energy)
     for other_peak in self._region.peaks:
         if other_peak == peak:
             continue
         other_models_cps += self.get_peak_cps(other_peak, peak.energy)
     y = self._region.cps - self._region.background - other_models_cps
     params = model.guess(y, x=peak.energy)
     self._params += params
     fwhmname = "{}fwhm".format(peak.prefix)
     sigmaname = "{}sigma".format(peak.prefix)
     ampname = "{}amplitude".format(peak.prefix)
     centername = "{}center".format(peak.prefix)
     params[fwhmname].set(value=params[fwhmname].value, vary=True, min=0)
     params[sigmaname].set(expr="{}/2".format(fwhmname))
     params[ampname].set(min=0)
     params[centername].set(min=0)
     self._single_models[peak.prefix] = model
Пример #4
0
def calc_center_pseudoVoigt(vx,vy):
    mod     = PseudoVoigtModel()
    y       = vy
    pars    = mod.guess(y, x=vx)
    out     = mod.fit(y, pars, x=vx)
    center  = out.best_values['center']
    return center
Пример #5
0
def voigt(x, y):

	# Voigt fit to a curve

    x_shifted = x - x.min() # Shifting to 0
    y_shifted = y - y.min() # Shifting to 0    
    mod = PseudoVoigtModel() # Setting model type
    pars = mod.guess(y_shifted, x=x_shifted) # Estimating fit
    out = mod.fit(y_shifted, pars, x=x_shifted) # Fitting fit
    # print(out.fit_report(min_correl=0.25)) # Outputting best fit results
    print("Voigt FWHM = ", out.params['fwhm'].value) # Outputting only FWHM
    out.plot() # Plotting fit
Пример #6
0
def center_psi(file_name):
    #print(file_name)
    psi, vx, vy = read_file(file_name)
    vy = processing_of_data(psi,vx,vy)
    legenda = file_name.split('/')[-1]
    #plt.grid()
    #plt.legend(loc=0)
    #import pdb; pdb.set_trace()
    plt.plot(vx,vy,label=legenda)
    mod = PseudoVoigtModel()
    y=vy
    pars = mod.guess(y, x=vx)
    out  = mod.fit(y, pars, x=vx)
    center =out.best_values['center']
    print('center: {} <--> psi: {}'.format(center,psi))
    return psi, center
Пример #7
0
def test_figure_title_using_title_keyword_argument(peakdata):
    """Test setting figure title using title keyword argument."""
    x, y = peakdata
    pvmodel = PseudoVoigtModel()
    params = pvmodel.guess(y, x=x)
    result = pvmodel.fit(y, params, x=x)

    ax = result.plot_fit(title='test')
    assert ax.axes.get_title() == 'test'

    ax = result.plot_residuals(title='test')
    assert ax.axes.get_title() == 'test'

    fig, _ = result.plot(title='test')
    assert fig.axes[0].get_title() == 'test'
    assert fig.axes[1].get_title() == ''  # no title for fit subplot
Пример #8
0
def test_figure_default_title(peakdata):
    """Test default figure title."""
    x, y = peakdata
    pvmodel = PseudoVoigtModel()
    params = pvmodel.guess(y, x=x)
    result = pvmodel.fit(y, params, x=x)

    ax = result.plot_fit()
    assert ax.axes.get_title() == 'Model(pvoigt)'

    ax = result.plot_residuals()
    assert ax.axes.get_title() == 'Model(pvoigt)'

    fig, _ = result.plot()
    assert fig.axes[0].get_title() == 'Model(pvoigt)'  # default model.name
    assert fig.axes[1].get_title() == ''  # no title for fit subplot
Пример #9
0
def test_priority_setting_figure_title(peakdata):
    """Test for setting figure title: title keyword argument has priority."""
    x, y = peakdata
    pvmodel = PseudoVoigtModel()
    params = pvmodel.guess(y, x=x)
    result = pvmodel.fit(y, params, x=x)

    ax = result.plot_fit(ax_kws={'title': 'ax_kws'}, title='test')
    assert ax.axes.get_title() == 'test'

    ax = result.plot_residuals(ax_kws={'title': 'ax_kws'}, title='test')
    assert ax.axes.get_title() == 'test'

    fig, _ = result.plot(ax_res_kws={'title': 'ax_res_kws'}, title='test')
    assert fig.axes[0].get_title() == 'test'
    assert fig.axes[1].get_title() == ''

    fig, _ = result.plot(ax_fit_kws={'title': 'ax_fit_kws'}, title='test')
    assert fig.axes[0].get_title() == 'test'
    assert fig.axes[1].get_title() == ''
Пример #10
0
def test_figure_title_using_title_to_ax_kws(peakdata):
    """Test setting figure title by supplying ax_{fit,res}_kws."""
    x, y = peakdata
    pvmodel = PseudoVoigtModel()
    params = pvmodel.guess(y, x=x)
    result = pvmodel.fit(y, params, x=x)

    ax = result.plot_fit(ax_kws={'title': 'ax_kws'})
    assert ax.axes.get_title() == 'ax_kws'

    ax = result.plot_residuals(ax_kws={'title': 'ax_kws'})
    assert ax.axes.get_title() == 'ax_kws'

    fig, _ = result.plot(ax_res_kws={'title': 'ax_res_kws'})
    assert fig.axes[0].get_title() == 'ax_res_kws'
    assert fig.axes[1].get_title() == ''

    fig, _ = result.plot(ax_fit_kws={'title': 'ax_fit_kws'})
    assert fig.axes[0].get_title() == 'Model(pvoigt)'  # default model.name
    assert fig.axes[1].get_title() == ''  # no title for fit subplot
def fit_peak(peak_data, initParams=None):
    """ Pseudo-Voigt fit to the lattice plane peak intensity.
        Return results of the fit as an lmfit class, which contains the fitted parameters (amplitude, fwhm, etc.) 
        and the fit line calculated using the fit parameters and 100x two-theta points.
    """
    ttheta = peak_data[:, 0]
    intensity = peak_data[:, 1]
    pvModel = PseudoVoigtModel()
    model = pvModel + Model(line)
    if initParams is None:
        pars = pvModel.guess(intensity, x=ttheta)
        pars['sigma'].set(min=0.01, max=1)  #sigma is the width?
        pars['amplitude'].set(min=0.05)
        pars.add("constBG", 0)
    else:
        pars = initParams
    fit_results = model.fit(intensity, pars, x=ttheta)
    fit_ttheta = np.linspace(ttheta[0], ttheta[-1], 100)
    fit_line = [fit_ttheta, model.eval(fit_results.params, x=fit_ttheta)]
    return fit_results, fit_line
Пример #12
0
def fit_voigt(xp: XPS_experiment,
              region: str,
              prefix: str = 'v_',
              pars: list = None,
              bounds: list = None,
              ax=None,
              flag_plot: bool = True):
    """General method for fitting voigt model
        Input
        ----------
        xp : class XPS_experiment
            XPS data
        region : str
            core level name
        pars, bounds : list
            initial guess of the fit parameters and bounds. If unspecified, guessed automatically
        Returns
        -----------
        fitv : lmfit.model
            fit result to Voigt model
    """
    from lmfit.models import PseudoVoigtModel, GaussianModel

    x = xp.dfx[region].dropna().energy
    y = xp.dfx[region].dropna().counts

    mod = PseudoVoigtModel(prefix=prefix)
    if pars == None:
        pars = mod.guess(y, x=x)
        pars[prefix + 'sigma'].set(value=1)  # Usually guessed wrong anyway
        pars[prefix + 'fraction'].set(value=0.2, min=0.15, max=0.20)

    fitv = mod.fit(y, pars, x=x)
    xp.fit.update({region: fitv})

    if flag_plot:
        hatchplot_fit(xp, region, fitv, ax=ax, plot_comps=True)
    return fitv
Пример #13
0
def fittingPseudoVoigt(x, y):  #fits a pseudovoigt curve
    mod = PseudoVoigtModel()
    pars = mod.guess(y, x=x)
    out = mod.fit(y, pars, x=x)
    print(out.fit_report(min_correl=0.25))
    return out.best_fit
    'grey': '#7F7F7F',
    'lightgrey': '#BFBFBF'
}

# get point-spread function data
psf = pu.load_muv_point_spread_function()

# set model x and y variables
detector_pixels = np.arange(len(psf))
detector_pixel_edges = np.linspace(0, len(psf) - 1, len(psf) + 1)

# initialize model
model = PseudoVoigtModel()

# use model's built-in initial parameters guessing option
initial_parameters = model.guess(psf, x=detector_pixels)

# fit the model to the point-spread function data
result = model.fit(psf, initial_parameters, x=detector_pixels)
params = result.params
parnames = sorted(params)

# make a figure and axes
fig, axes = plt.subplots(2,
                         1,
                         figsize=(5, 4),
                         sharex=True,
                         gridspec_kw={'height_ratios': [4, 1]},
                         constrained_layout=True)

# plot the IUVS data
Пример #15
0
def fit_double_shouldered_voigt(xp: XPS_experiment,
                                region: str,
                                par_g1: list,
                                bound_g1: list,
                                par_g2: list,
                                bound_g2: list,
                                lb: str = None,
                                ax=None,
                                flag_plot: bool = True) -> tuple:

    x = xp.dfx[region].dropna().energy
    y = xp.dfx[region].dropna().counts
    ### Separate two peaks ###
    sepPt = find_separation_point(x, y)
    x1 = x[x < sepPt].values
    x2 = x[x > sepPt].values
    y1 = y[x < sepPt].values
    y2 = y[x > sepPt].values

    ### Set and guess main (voigt) components  ####
    vo1 = PseudoVoigtModel(prefix='v1_')
    pars1 = vo1.guess(y1, x=x1)
    vo2 = PseudoVoigtModel(prefix='v2_')
    pars2 = vo2.guess(y2, x=x2)
    pars1['v1_sigma'].set(value=1)  # Usually guessed wrong anyway
    pars1['v1_fraction'].set(value=0.15, min=0.15, max=0.2)
    pars2['v2_sigma'].set(value=1)  # Usually guessed wrong anyway
    pars2['v2_fraction'].set(value=0.15, min=0.15, max=0.2)

    ### Set gaussian shoulders ###
    gauss1 = GaussianModel(prefix='g1_')
    pars1.update(gauss1.make_params())

    gauss2 = GaussianModel(prefix='g2_')
    pars2.update(gauss2.make_params())
    mod1 = vo1 + gauss1
    mod2 = vo2 + gauss2

    for k, p, b in zip(gauss1.param_names, par_g1, bounds_g1):
        pars1[k].set(value=p, min=b[0], max=b[1])

    for k, p, b in zip(gauss2.param_names, par_g2, bounds_g2):
        pars2[k].set(value=p, min=b[0], max=b[1])

    fitvg1 = mod1.fit(y1, pars1, x=x1)
    fitvg2 = mod2.fit(y2, pars2, x=x2)

    if ax == None: ax = plt.gca()
    col = plot_region(xp, region, lb, ax).get_color()
    comps1 = fitvg1.eval_components(x=x1)
    ax.plot(x1,
            fitvg1.best_fit,
            '-r',
            label='best fit, $\chi^2_N$ = %i' % fitvg1.redchi)
    for compo in comps1:
        colc = ax.plot(
            x1,
            comps1[compo],
            ls='dashdot',
            label='%scenter: %.2f' %
            (compo, fitvg1.best_values[compo + 'center']))[0].get_color()
        ax.fill_between(x1, y1=0, y2=comps1[compo], alpha=0.3, color=colc)

    comps2 = fitvg2.eval_components(x=x2)
    ax.plot(x2,
            fitvg2.best_fit,
            '-',
            label='best fit, $\chi^2_N$ = %i' % fitvg2.redchi)
    for compo in comps2:
        colc = ax.plot(
            x2,
            comps2[compo],
            ls='dashdot',
            label='%scenter: %.2f' %
            (compo, fitvg2.best_values[compo + 'center']))[0].get_color()
        ax.fill_between(x2, y1=0, y2=comps2[compo], alpha=0.3, color=colc)

    ax.legend()
    return fitvg1, fitvg2
Пример #16
0
def fit_double_voigt(xp: XPS_experiment,
                     region: str,
                     pars: list = None,
                     bounds: list = None,
                     sepPt: float = None,
                     frac: float = None,
                     lb: str = None,
                     ax=None,
                     flag_plot: bool = True,
                     plot_comps: bool = False,
                     DEBUG: bool = False):
    """Fitting double voigt model
        Input
        ----------
        xp : class XPS_experiment
            XPS data
        region : str
            core level name
        pars, bounds : list
            initial guess of the fit parameters and bounds. If unspecified, guessed automatically
        sepPt : float
            separation point in energy between the two peaks. If unspecified guessed automatically
        flag_plot, DEBUG : bool
            flags to plot intermediate and final fit results
        Returns
        -----------
        fitv : lmfit.model
            fit result to Voigt model
    """
    from lmfit.models import PseudoVoigtModel

    x = xp.dfx[region].dropna().energy
    y = xp.dfx[region].dropna().counts
    if sepPt == None: sepPt = find_separation_point(x, y)

    x1 = x[x < sepPt].values
    x2 = x[x > sepPt].values
    y1 = y[x < sepPt].values
    y2 = y[x > sepPt].values

    mod1 = PseudoVoigtModel(prefix='v1_')
    mod2 = PseudoVoigtModel(prefix='v2_')
    if pars == None:
        pars1 = mod1.guess(y1, x=x1)
        pars1['v1_sigma'].set(value=1)  # Usually guessed wrong anyway
        pars2 = mod2.guess(y2, x=x2)
        pars2['v2_sigma'].set(value=1)  # Usually guessed wrong anyway

    if frac != None:
        pars1['v1_fraction'].set(value=frac, vary=False)
        pars2['v2_fraction'].set(value=frac, vary=False)

    mod = mod1 + mod2
    pars = mod.make_params()
    pars.update(pars1)
    pars.update(pars2)
    if DEBUG:  # Fit & plot individual components separately
        fit1 = mod1.fit(y1, x=x1, params=pars1)
        fit2 = mod2.fit(y2, x=x2, params=pars2)
        plot_fit_result(xp, region, fit1)
        plot_fit_result(xp, region, fit2)

    fitv = mod.fit(y, pars, x=x)
    xp.fit.update({region: fitv})

    if flag_plot:
        hatchplot_fit(xp, region, fitv, ax=ax, plot_comps=True)
    return fitv