Exemple #1
0
def fit_two_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
    '''
    
    # Follows
    # http://lmfit.github.io/lmfit-py/builtin_models.html#example-1-fit-peaked-data-to-gaussian-lorentzian-and-voigt-profiles
    # and 
    # http://cars9.uchicago.edu/software/python/lmfit_MinimizerResult/builtin_models.html
    # and 
    # the alpha version of this code
    # Figure out Composit Model
    
    import numpy as np
    # for smoothing the curves
    import scipy.interpolate as interp #import splev 
    
    from lmfit.models import VoigtModel, 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 = 1 # 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 = VoigtModel(prefix = pref1, independent_vars=['x'],nan_policy='raise')
    peak2 = VoigtModel(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 = 4*y_max, min=y_max*.8,max = y_max*9,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)
    
    # 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*9,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, min = 0, max = 5*w_guess,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:
        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
Exemple #2
0
def fit_Voigt_and_step(x_lst,y_lst,x_min_flt,x_max_flt, pre, width_1, width_2, 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
    
    returns result object
    
    '''

    # Restrict the fit
    x_bkp = x_lst
    y_bkp = y_lst
    
    x_lst, y_lst, y_p, ypp = smooth_and_remove_step(x_lst, y_lst, x_min_flt, x_max_flt,True)
    
    '''
    *******************************************************
    Section of bad code that it'd take too long to do right
    *******************************************************
    '''
    step_at = 95
    step_width = 10
    prefp = pre
    prefs = "stp"
    prefc = 'c'    
    w_guess = 3 # sigma
    '''
    *******************************************************
    Section of bad code that it'd take too long to do right
    *******************************************************
    '''
    
    # this is the money
    # defines the model that'll be fit
    peak = VoigtModel(prefix = prefp, independent_vars=['x'],nan_policy='raise')
    step = StepModel(prefix = prefs, independent_vars=['x'],form='logistic')
    const = ConstantModel(prefix = prefc,independent_vars=['x'], nan_policy='raise', form ='logistic')
    
    mod = peak + step + const
    #mod = peak + const
    
    # guess parameters
    x_max = x_lst[np.argmax(y_lst)]
    y_max = y_lst[np.argmax(y_lst)]
    
    # Peak
    # here we set up the peak fitting guess. Then the peak fitter will make a parameter object out of them
    mod.set_param_hint(prefp+'amplitude', value = value_max*y_max, min = .6*value_max_min*y_max,max = 4*value_max_max*y_max, vary=True)
    # mod.set_param_hint(prefp+'center', value = x_max, min = x_max*(1-wiggle_room), max = x_max*(1+wiggle_room),vary=True)
    mod.set_param_hint(prefp+'center', value = x_max,min = x_max*.97, max = x_max*1.03, vary=True)
    
     # Basically FWHM/3.6
    if pre =='one':     # fitting with only one peak
        mod.set_param_hint(prefp+'sigma', value = width_1, min = .25*width_2, max = 2*width_1,vary=True)
    else:               # fitting with two peaks
        mod.set_param_hint(prefp+'sigma', value = width_2, min = 0, max = width_1,vary=True)
    
    # Constant
    top = []
    bottom = []
    for a,b in zip(x_lst,y_lst):
        if a > 135:
            top.append(b)
        elif a < 93:
            bottom.append(b)
    top = np.mean(np.asarray(top))
    bottom = np.mean(np.asarray(bottom))
            
    mod.set_param_hint(prefc+'c', value = bottom, min = -3*bottom, max = 3*bottom,vary=True)
    
    # restrict the fit again
    x_fit = []
    y_fit = []
    for a,b in zip(x_lst,y_lst):
        if 80 < a < 135:
            x_fit.append(a)
            y_fit.append(b)
    top = y_fit[0]
    bottom = y_fit[-1]
    
    # Step
    # Step height
    delta = 2*abs(top - bottom)
    if delta == 0:
        delta = 1
    mod.set_param_hint(prefs+'amplitude', value = delta, min = -3*delta, max = 3*delta, vary=True)
    # Charastic width
    mod.set_param_hint(prefs+'sigma', value = 3,min = 1, max = 3, vary=False)
    # The half way point... 
    mod.set_param_hint(prefs+'center', value = step_at, min = step_at-step_width, max = step_at+step_width, vary = False)
    
    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()
        
        # each component
        for x in result.best_values:
            if prefp in x:      # Get peak
                peak.set_param_hint(x, value = result.best_values[str(x)])
            elif prefs in x:    # Get step
                step.set_param_hint(x, value = result.best_values[str(x)])
        
        # Data - 'background' 
        y_m_background = []
        for a,b in zip(x_lst,y_lst):
            y_m_background.append(b - result.eval(x=a) + peak.eval(x=a,  params=peak.make_params()))
        
        peak_only = [peak.eval(x=yy, params=peak.make_params()) for yy in x_dense]
        #stp_only = [result.best_values['stpamplitude'] + result.best_values['cc']]*len(x_dense)
        # sum of them
        #y_fit = [a+b for a,b in zip(peak_only,stp_only)]
        y_fit = [a+b for a in peak_only]
        
        plt.plot(x_dense,peak_only, 'g', label = 'Peak Only')
        #plt.plot(x_dense,stp_only, 'g--', label = None)
        #plt.plot(x_dense, y_fit, 'g', label = "Fit Result")        
        
        plt.plot(x_lst,y_lst,'bx', label= "Data")
        plt.plot(x_lst,y_m_background,'ko', label= "Data-Background")
        
        plt.title("Fit vs Data")
        plt.xlabel("Inv Cm")
        plt.ylabel("counts")
        plt.legend()
        plt.savefig(place_to_save_str+"Voigt&Step")
        plt.clf()    
    
    return result
Exemple #3
0
def fit_Voigt_and_step(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
    
    '''
    import numpy as np
    # for smoothing the curves
    import scipy.interpolate as interp #import splev 
    
    from lmfit.models import VoigtModel, StepModel, ConstantModel
    from lmfit import CompositeModel
    
    # 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
    *******************************************************
    '''
    step_at = 100
    step_width = 3
    prefp = "one"
    prefs = "stp"
    prefc = 'c'    
    w_guess = 3 # sigma
    '''
    *******************************************************
    Section of bad code that it'd take too long to do right
    *******************************************************
    '''
    
    # this is the money
    # defines the model that'll be fit
    peak = VoigtModel(prefix = prefp, independent_vars=['x'],nan_policy='raise')
    step = StepModel(prefix = prefs, independent_vars=['x'], nan_policy='raise')
    const = ConstantModel(prefix = prefc,independent_vars=['x'], nan_policy='raise', form ='logistic')
    
    mod = peak + step + const
    
    # guess parameters
    x_max = x_fit[np.argmax(y_fit)]
    y_max = y_fit[np.argmax(y_fit)]
    
    # Peak
    # here we set up the peak fitting guess. Then the peak fitter will make a parameter object out of them
    mod.set_param_hint(prefp+'amplitude', value = 4*y_max, min = y_max,max = 30*y_max, vary=True)
    # mod.set_param_hint(prefp+'center', value = x_max, min = x_max*(1-wiggle_room), max = x_max*(1+wiggle_room),vary=True)
    mod.set_param_hint(prefp+'center', value = x_max, vary=True)
    # Basically FWHM/3.6
    mod.set_param_hint(prefp+'sigma', value = w_guess, min = 0, max = 5*w_guess,vary=True)
    
    # Step
    # Step height
    delta = abs(y_fit[-1]-y_fit[0])
    mod.set_param_hint(prefs+'amplitude', value = delta, min = delta*.9, max = delta*1.1, vary=True)
    # Charastic width
    mod.set_param_hint(prefs+'sigma', value = 2,min = 1, max = 3, vary=True)
    # The half way point... 
    mod.set_param_hint(prefs+'center', value = step_at, min = step_at-step_width, max = step_at+step_width, vary = True)
    
    # Constant
    mod.set_param_hint(prefc+'c', value = y_fit[-1], min = 0, max = 2*y_fit[0],vary=True)    
    
    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)
        
        for x in result.best_values:
            if prefp in x:      # Get peak
                peak.set_param_hint(x, value = result.best_values[str(x)])
            elif prefs in x:    # Get step
                step.set_param_hint(x, value = result.best_values[str(x)])
        
        comp = [result.best_values['cc'] + peak.eval(x=yy, params=peak.make_params()) for yy in x_dense]
        plt.plot(x_dense,comp, 'green', label = None)
        
        comp = [result.best_values['stpamplitude'] + result.best_values['cc']]*len(x_dense)
        plt.plot(x_dense, comp, 'green', label= None)
        
        # comp = [result.best_values['cc'] + step.eval(x=yy, params=step.make_params()) for yy in x_dense]
        # plt.plot(x_dense, comp, 'green', label= None)
        
        plt.title("Fit vs Data")
        plt.legend()
        plt.savefig(place_to_save_str)
        plt.clf()    
    
    return result.best_values