示例#1
0
文件: fitter.py 项目: felixfeske/xpl
 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
示例#2
0
文件: fitter.py 项目: felixfeske/xpl
 def add_peak(self, peak):
     """Adds a new Peak to the Model list."""
     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, value=0.2)
         params = model.make_params()
     else:
         raise NotImplementedError("Only PseudoVoigt models supported")
     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
示例#3
0
def fit_two_Psudo_Voigt(x_lst,y_lst,x_min_flt,x_max_flt,print_all_fits_bool,place_to_save_str):
    '''
    x_lst = x axis
    y_lst = spectra to fit
    first = beginning of fitting regions
    last = end of fitting region
    print_all_fits = Bool, do you want to save all plots
    place_to_save = string that is the filename where we're saving the data
    
    This takes the spectra and fits two Lorentzian curves to it. 
    Returns dictionary of fit values 
    Parameters have prefixes "one" for first V, "two" for second V, "c" for constant
    '''
    
    import numpy as np
    # for smoothing the curves
    import scipy.interpolate as interp #import splev 
    
    from lmfit.models import PseudoVoigtModel, ConstantModel
    
    # Restrict the fit
    x_fit = []
    y_fit = []
    
    for x,y in zip(x_lst, y_lst):
        if x_min_flt < x < x_max_flt:
            x_fit.append(float(x))
            y_fit.append(float(y))
    
    x_fit = np.asarray(x_fit)
    y_fit = np.asarray(y_fit)   
    
    # now we find the parameters using the - d^2/dx^2
    ysmooth = interp.interp1d(x_fit, y_fit, kind='cubic')
    # differentiate x 2
    yp = np.gradient(ysmooth(x_fit))
    ypp = np.gradient(yp)
    # we want the peaks of -d2/dx2 
    ypp = np.asarray([-x for x in ypp])
    
    '''
    *******************************************************
    Section of bad code that it'd take too long to do right
    *******************************************************
    '''
    # % of wavelength you want the peak centers to move 
    wiggle_room = .05
    w_guess = 3 # sigma
    pref1 = 'one'
    pref2 = 'two'
    prefo = 'off'
    
    # if the fancy shit doesn't work, this is how far in index
    # we shift the 2nd peak and max over
    doesnt_work_shift = 10
    '''
    *******************************************************
    Section of bad code that it'd take too long to do right
    *******************************************************
    '''
    
    # this is the money
    # defines the model that'll be fit
    peak1 = PseudoVoigtModel(prefix = pref1, independent_vars=['x'],nan_policy='raise')
    peak2 = PseudoVoigtModel(prefix = pref2, independent_vars=['x'],nan_policy='raise')
    offset = ConstantModel(prefix=prefo, independent_vars=['x'],nan_policy='raise')
    
    mod = peak1 + peak2 + offset
    
    # guess parameters
    x_max = x_fit[np.argmax(ypp)]
    y_max = y_fit[np.argmax(ypp)]
    
    # peak #1 
    # here we set up the peak fitting guess. Then the peak fitter will make a parameter object out of them
    mod.set_param_hint(pref1+'amplitude', value = 5*y_max, min=y_max*.8,max = y_max*6,vary=True)
    
    mod.set_param_hint(pref1+'center', value = x_max, min = x_max*(1-wiggle_room), max = x_max*(1+wiggle_room),vary=True)
    
    mod.set_param_hint(pref1+'sigma', value = w_guess, min = 0, max = 5*w_guess,vary=True)
    
    # Set Fraction
    mod.set_param_hint(pref1+'fraction', value = .5, min = 0, max = 1,vary=True)

    # Change gama maybe
    # mod.set_param_hint(pref1+'gamma', value = 1, vary=True)
    
    # peak #2
    x_trunk = []
    y_trunk = []
    ypp_trunk = []
    try:
        for a,b,c in zip(x_fit.tolist(),y_fit.tolist(),ypp.tolist()):
            '''
            BAD CODE MAKE THIS BETTER
            '''
            if x_max + 8 < a < x_max + 12:
                x_trunk.append(a)
                y_trunk.append(b)
                ypp_trunk.append(c)
        x_trunk = np.asarray(x_trunk)
        y_trunk = np.asarray(y_trunk)
        ypp_trunk = np.asarray(ypp_trunk)
        
        x_max_2 = x_trunk[np.argmax(ypp_trunk)]
        y_max_2 = y_trunk[np.argmax(ypp_trunk)]
        
    except ValueError:
        x_max_2 = x_trunk[np.argmax(ypp) + doesnt_work_shift]
        y_max_2 = y_trunk[np.argmax(ypp) + doesnt_work_shift]
        
    # add peak 2 paramaters 
    mod.set_param_hint(pref2+'amplitude', value = 4*y_max_2, min=y_max_2*.8,max = y_max_2*6,vary=True)
    # changed the bounds to be near other peak
    mod.set_param_hint(pref2+'center', value = x_max_2, min = x_max+8, max = x_max+14,vary=True)
    
    mod.set_param_hint(pref2+'sigma', value = w_guess/2, min = 0, max = w_guess ,vary=True)
    #mod.set_param_hint(pref2+'sigma', pref1 + 'sigma' < expr < pref1 + 'sigma')
    
    # Set Fraction
    mod.set_param_hint(pref2+'fraction', value = .5, min = 0, max = 1,vary=True)
    
    # Change gama maybe
    # mod.set_param_hint(pref2+'gamma', value = 1, vary=False)
    
    # constant offest
    mod.set_param_hint(prefo+'c', value = y_fit[-1], min = 0, max = 5*y_fit[-1],vary=False)
    
    # this does the fitting
    # the params = mod.ma... is what initializes the parameters
    result = mod.fit(y_fit, x=x_fit, params = mod.make_params())
    
    # If print all fits ... 
    if print_all_fits_bool:
        x_dense = np.arange(x_min_flt,x_max_flt,(x_max_flt-x_min_flt)/300.0).tolist()
        
        result.plot_fit(xlabel='Inv Cm', ylabel='counts',datafmt = 'xb', numpoints=len(x_fit)*10)
        
        '''
        Here we make paramaters for peak 1 and 2
        '''
        for x in result.best_values:
            if pref1 in x:
                peak1.set_param_hint(x, value = result.best_values[str(x)])
            elif pref2 in x:
                peak2.set_param_hint(x, value = result.best_values[str(x)])
            else:
                peak1.set_param_hint(x, value = result.best_values[str(x)])
                peak2.set_param_hint(x, value = result.best_values[str(x)])
        
        comp = [peak1.eval(x=yy, params=peak1.make_params()) for yy in x_dense]
        plt.plot(x_dense,comp, 'green', label = None)
        
        comp = [peak2.eval(x=yy, params=peak2.make_params()) for yy in x_dense]
        plt.plot(x_dense, comp, 'green', label= None)
        plt.title("Fit vs Data")
        plt.ylim(0, 1.1*np.max(y_fit))
        plt.legend()
        plt.savefig(place_to_save_str)
        plt.clf()
        
    return result.best_values