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_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