def fit_one_Voigt(x_lst,y_lst, pre): ''' Fits one Pseudo Voigt returns the results object ''' x_lst = np.asarray(x_lst) y_lst = np.asarray(y_lst) mod = VoigtModel(prefix = pre, independent_vars=['x'],nan_policy='raise') # here we set up the peak fitting guess. Then the peak fitter will make a parameter object out of them mod.set_param_hint(pre+'amplitude', value = 4 * np.max(y_lst), min = 3*np.max(y_lst), max = 7*np.max(y_lst), 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(pre+'center', value = x_lst[np.argmax(y_lst)], vary=True) # Basically FWHM/3.6 w_guess = 2 mod.set_param_hint(pre+'sigma', value = w_guess, min = 0, max = 5*w_guess,vary=True) result = mod.fit(y_lst, x = x_lst, params = mod.make_params()) return result
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
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
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