def create_xrf_line(x, params, linedict, linefunc): funcmodel = Model(linefunc) # start with the function parameters... funcparams = funcmodel.make_params() # # copy the function based parameters from params to funcparams # for key in params: if key in funcparams: funcparams[key].value = params[key].value funcparams[key].min = params[key].min funcparams[key].max = params[key].max funcparams[key].vary = params[key].vary result = np.zeros_like(x) sigma_keys = [s for s in funcparams.keys() if 'sigma' in s] for key, linegroup in linedict.iteritems(): if key in params: for line in linegroup: # update funcparams funcparams["area"].value = params[key].value*\ line.intensity funcparams["center"].value = line.line_energy for ii in sigma_keys: funcparams[ii].value = np.sqrt(params[ii].value**2 + \ (line.line_energy*0.001)) result = result + funcmodel.eval(funcparams, x=x) return result
def lmDDOPhaseFit(xdata, ydata, params, f0_range = 1.2, Q_range = 3): f0= params[0] Q=1/(2*params[2]) x = xdata y = ydata #Define a linear model and a Damped Oscillator Model # ddophase_mod = ExpressionModel('off + m*x- arctan(1/Q * 1/(f0/x - x/f0))-') ddophase_mod = Model(phase) #Initial Pars for Linear Model pars = ddophase_mod.make_params(off=0, m=0, f0=f0, Q=Q) #Add fit parameters, Center, Amplitude, and Sigma pars['f0'].set(min=f0/f0_range, max=f0*f0_range) pars['Q'].set(min=Q/Q_range, max=Q*Q_range) #Create full model. Add linear model and all peaks #Initialize fit init = ddophase_mod.eval(pars, x=x) #Do the fit. The weight exponential can weight the points porportional to the #amplitude of y point. In this way, points on peak can be given more weight. out=ddophase_mod.fit(y, pars,x=x) #Get the fit parameters fittedf0= out.params['f0'].value fittedQ = out.params['Q'].value #Returns the output fit as well as an array of the fit parameters """Returns output fit as will as list of important fitting parameters""" return out, [fittedf0, np.nan, np.nan, fittedQ]
def lmDDOPhaseFit(xdata, ydata, params, f0_range=1.2, Q_range=3): f0 = params[0] Q = 1 / (2 * params[2]) x = xdata y = ydata #Define a linear model and a Damped Oscillator Model # ddophase_mod = ExpressionModel('off + m*x- arctan(1/Q * 1/(f0/x - x/f0))-') ddophase_mod = Model(phase) #Initial Pars for Linear Model pars = ddophase_mod.make_params(off=0, m=0, f0=f0, Q=Q) #Add fit parameters, Center, Amplitude, and Sigma pars['f0'].set(min=f0 / f0_range, max=f0 * f0_range) pars['Q'].set(min=Q / Q_range, max=Q * Q_range) #Create full model. Add linear model and all peaks #Initialize fit init = ddophase_mod.eval(pars, x=x) #Do the fit. The weight exponential can weight the points porportional to the #amplitude of y point. In this way, points on peak can be given more weight. out = ddophase_mod.fit(y, pars, x=x) #Get the fit parameters fittedf0 = out.params['f0'].value fittedQ = out.params['Q'].value #Returns the output fit as well as an array of the fit parameters """Returns output fit as will as list of important fitting parameters""" return out, [fittedf0, np.nan, np.nan, fittedQ]
def FitCurve(func, xdata, ydata): ''' Fit data to a function form ''' fmodel = Model(func) params = fmodel.make_params(Psi_1=1, Psi_2=0, N=640, AAAvgVol=10648) params['N'].vary = False params['AAAvgVol'].vary = False results = fmodel.fit(ydata, params, x=xdata) y = fmodel.eval(x=xdata, params=results.params) #parameters_opt, parameter_covariance = curve_fit(func,xdata,ydata) return results, ydata
def simple_echo_fits(): """ Takes the highest point of each echo and fits the echo_as_T2 function to those points. """ xrs, yrs, xr, yr, filename, dat1 = range_to_list() length = len(yrs) max_y = [np.max(yrs[i]) for i in range(length)] max_y_loc = [np.where(yrs[i] == max_y[i])[0][0] for i in range(length)] cents = [xrs[i][max_y_loc[i]] for i in range(length)] heights = max_y # TODO: Find a better value for the uncertainty on y-values. heights = np.array(heights) cents = np.array(cents) maxy = np.max(heights) miny = np.min(heights) decay_pos = np.where(heights == find_nearest(heights, maxy / e))[0][0] decay_pos_time = cents[decay_pos] avg_y_sep = abs(np.mean(np.diff(heights))) efit = Model(echo_as_T2) print(efit, echo_as_T2) param = efit.make_params() param.add('M0', value=maxy, min=maxy * 0.5, max=maxy + (avg_y_sep * 5)) param.add('T2', value=decay_pos_time, min=decay_pos_time * 0.1, max=decay_pos_time * 2.5) if miny != 0: param.add('c', value=miny * 0.3, min=miny * 0.1, max=miny * 2.2) param.add('ph', value=cents[0] * 0.5, min=0, max=cents[0] * 2) param.add('m1', value=0.1) param.add('m', value=1) result_2 = efit.fit(heights, param, t=cents, method='leastsq', weights=np.mean(np.diff(dat1['T'])) / heights) print(result_2.fit_report()) print('\n', result_2.params.pretty_print()) ax = plt.gca() ax.set_xlabel('Time (us)', fontsize=14) ax.set_ylabel('Voltage (V)', fontsize=14) xes = np.linspace(np.min(cents), np.max(cents), 100) y = efit.eval(t=xes, params=result_2.params) plt.plot(xes, y, antialiased=True) plt.plot(cents, heights, 'x', ms=8, color='k') plt.plot(dat1['V'], dat1['T'], lw=2, antialiased=True, color='#4a4a4a', zorder=1) plt.title(filename) plt.xlim(left=0, right=np.max(cents) * 1.1) # plt.ylim(bottom=0, top=result_2.params['M0'].value * 1.1) plt.axhline(result_2.params['M0'].value, color='k', ls='--', alpha=0.7, lw=1, zorder=2) plt.axhline(result_2.params['M0'].value / e, color='k', ls='--', alpha=0.7, lw=1, zorder=2) plt.text(0.9, 0.9, "T_1: {:.4f} us".format(result_2.params['T2'].value), horizontalalignment='center', verticalalignment="center", transform=ax.transAxes, bbox={'pad': 8, 'fc': 'w'}, fontsize=14) plt.tight_layout() plt.tick_params(axis='both', which='major', labelsize=13) fig_manager = plt.get_current_fig_manager() fig_manager.window.showMaximized() plt.show()
def draw_model_fit(self, path, wavelength, flux): """ Generate the gauss model, draw the model results based on x value range and update the table that shows the results parameters""" self.__quadraticDeque.append(1) for i, key in enumerate(self.__quadraticDict.keys()): self.__quadraticDict[key] = self.__quadraticDeque[i] #Obtain the wavelength values on given range wavelengthValues = wavelength[ (wavelength >= self.__quadraticDict['left'][0]) & (wavelength <= self.__quadraticDict['right'][0])] #Obtain de indexes from the initial wavelength array #based on the min a max values of the slice made previously index1 = np.where(wavelength == np.amin(wavelengthValues)) index2 = np.where(wavelength == np.amax(wavelengthValues)) #Obtain the flux values between the indexes obtained previously fluxValues = flux[index1[0][0]:(index2[0][0] + 1)] quadratic_model = Model(quadratic_fitting_function, name='model1') slope = calculate_slope(self.__quadraticDict['left'][0], self.__quadraticDict['left'][1], self.__quadraticDict['right'][0], self.__quadraticDict['right'][1]) inital_y_values = self._generate_initial_quadratic_model( wavelengthValues, calculate_intercept(slope, self.__quadraticDict['left'][0], self.__quadraticDict['left'][1]), slope) params = quadratic_model.make_params(a=calculate_intercept( slope, self.__quadraticDict['left'][0], self.__quadraticDict['left'][1]), b=slope) init = quadratic_model.eval(params, x=wavelengthValues) result = quadratic_model.fit(fluxValues, params, x=wavelengthValues) #Update table of results parameters resultText = "Path: {}".format(path) resultText = resultText + "\n" + \ "Quadratic model: {} + {} * x + {} * x**2".format(str(result.params['a'].value), str(result.params['b'].value), str(result.params['c2'].value)) quadraticFitResultList = [ key + " = " + str(result.params[key].value) for key in result.params ] for resultParams in quadraticFitResultList: resultText = resultText + "\n" + resultParams resultText = resultText + "\n" + "Chi-square" + " = " + str( result.chisqr) return result, resultText, wavelengthValues, fluxValues, inital_y_values, None
class erf_model(): def __init__(self, params0=[1, 1, 1], fixedParams0=[False, False, False]): assert (len(params0) == 3) assert (len(fixedParams0) == 3) self.model = Model(self.erf_curve) self.modelResult = None self.param_names = self.model.param_names self.params = self.model.make_params() for i in range(len(self.param_names)): param_name = self.param_names[i] self.params[param_name].value = params0[i] self.params[param_name].vary = not fixedParams0[i] # t is an array of time points [] def predict(self, t_eval): return self.model.eval(self.params, t=t_eval) # return a matrix with 9 quantiles def predict_with_quantiles(self, t_eval): quantiles = [10, 20, 30, 40, 50, 60, 70, 80, 90] # 9 different quantiles y_pred_lst = self.predict(t_eval) y_pred_quantiles_lst = [] for y_pred in y_pred_lst: y_pred_quantiles = [y_pred for i in range(len(quantiles))] y_pred_quantiles_lst.append(y_pred_quantiles) return y_pred_quantiles_lst # params must have logp, a, b def erf_curve(self, t, logp, a, b): p = 10**logp pred_y = p / 2 * (1 + erf(a * (t - b))) return pred_y # predicts a time window, inclusive def predict_timewindow(self, start, end): t = np.arange(start, end) pred_y = self.predict(t) return pred_y # fits to array of time and deaths def fit(self, T, y): self.modelResult = self.model.fit(y, self.params, t=T) self.params = self.modelResult.params # get cov matrix and errors # errors = np.sqrt(np.diag(pcov)) return self
def prueba(): y2 = [49.0, 49.0, 101.0, 67.0, 65.0, 52.0, 49.0, 49.0, 54.0, 49.0, 48.0, 49.0] y = [i-50 for i in y2] x = linspace(0.0, 11.0, num=12) #variable ind para evento x2 = linspace(0.0, 11.0, num=400) #variable ind para fit gmod = Model(gaussian) #Generar un Modelo Gaussiano peak = max(y) result = gmod.fit(y, x=x, amp=peak, cen=5, wid=1) final = gmod.eval(x=x2, amp=result.best_values['amp'], cen=result.best_values['cen'], wid=result.best_values['wid']) plt.plot(x, y, 'bo') plt.plot(x, result.init_fit, 'k--') #plt.plot(x, result.best_fit, 'r-') plt.plot(x2, final, 'r-') plt.show()
def test_wrapped_model_func(self): x = np.linspace(-1, 1, 51) y = 2.0*x + 3 + 0.0003 * x*x y += np.random.normal(size=len(x), scale=0.025) mod = Model(linear_func) pars = mod.make_params(a=1.5, b=2.5) tmp = mod.eval(pars, x=x) self.assertTrue(tmp.max() > 3) self.assertTrue(tmp.min() > -20) result = mod.fit(y, pars, x=x) self.assertTrue(result.chisqr < 0.05) self.assertTrue(result.aic < -350) self.assertTrue(result.errorbars) self.assertTrue(abs(result.params['a'].value - 2.0) < 0.05) self.assertTrue(abs(result.params['b'].value - 3.0) < 0.41)
def fit_planck(self): T_wien, em_wien = fit_wien(self.lamda, self.I2) bmmodel = Model(planck, independent_vars=['lamda']) params = Parameters() params.add('T', value=T_wien) params.add('em', value=em_wien) self.result = bmmodel.fit(self.I2, params, lamda=self.lamda) # write error report report_fit(self.result) self.result.params.pretty_print() Ifit = bmmodel.eval(self.result.params, lamda=self.lamda) plt.figure() plt.plot(self.lamda * 1e9, self.I2, label='T gradient + absorption') plt.plot(self.lamda * 1e9, Ifit, label='Fitted ' + str(self.result.params.valuesdict()['T']) + ' K') plt.xlabel("wavelegnth (nm)") plt.ylabel("radiance (W/m^3)") plt.legend()
def gauss_fwhm2(x, y): cont_bi = np.sqrt(2 * np.log(2)) xsize = np.size(x) amp = np.amax(y) cen = x[np.argmax(y)] #mean = sum(x * y) / sum(y) wid = fwhm(x, y) #np.sqrt(sum(y * (x - mean) ** 2) / sum(y)) gmodel = Model(Gauss) print('parameter names: {}'.format(gmodel.param_names)) print('independent variables: {}'.format(gmodel.independent_vars)) params = gmodel.make_params(amp=amp, cen=cen, wid=wid, bis=np.amin(y)) results = gmodel.fit(y, params, x=x) print(results.fit_report()) fitx = np.linspace(np.amin(x) * 1.1, np.amax(x) * 1.1, num=np.size(x) * 2) fity = gmodel.eval(params=results.params, x=fitx) dely = results.eval_uncertainty(sigma=3, x=fitx) #3sigma uncertainity fwhm0 = results.params["wid"] * cont_bi return fwhm0, fitx, fity, results, dely
def fit_model_double(function, energy_fit, eqe_fit, bound_dict, p0=None, include_disorder=False, print_report=False ): """ Function to perform curve fit using lmfit This function is used for simultaneous double peak fitting :param function: function to fit against (i.e. gaussian, gaussian_disorder etc.) :param energy_fit: energy values to fit against [list or array] :param eqe_fit: EQE values to fit against [list or array] :param bound_dict: dictionary of boundary values [dict] dict keys: start_ECT, stop_ECT start_lCT, stop_lCT start_fCT, stop_fCT start_Eopt, stop_Eopt start_lopt, stop_lopt start_fopt, stop_fopt start_sig, stop_sig :param p0: list of initial guesses for curve_fit function [list] :param include_disorder: boolean value to specify whether to include disorder [bool] :param print_report: boolean value to specify whether to print fit report [bool] :return: best_vals: list of best fit parameters [list] covar: covariance matrix of fit y_fit: calculated EQE values of the fit [list] r_squared: R^2 of the fit [float] """ if p0 is None: # if no guess is given, initialize with all ones. This is consistent with curve_fit. if include_disorder: p0 = [1, 1, 1, 1, 1, 1, 1] else: p0 = [1, 1, 1, 1, 1, 1] gmodel = Model(function) gmodel.set_param_hint('ECT', min=bound_dict['start_ECT'], max=bound_dict['stop_ECT']) gmodel.set_param_hint('lCT', min=bound_dict['start_lCT'], max=bound_dict['stop_lCT']) gmodel.set_param_hint('fCT', min=bound_dict['start_fCT'], max=bound_dict['stop_fCT']) gmodel.set_param_hint('Eopt', min=bound_dict['start_Eopt'], max=bound_dict['stop_Eopt']) gmodel.set_param_hint('lopt', min=bound_dict['start_lopt'], max=bound_dict['stop_lopt']) gmodel.set_param_hint('fopt', min=bound_dict['start_fopt'], max=bound_dict['stop_fopt']) if include_disorder: gmodel.set_param_hint('sig', min=bound_dict['start_sig'], max=bound_dict['stop_sig']) result = gmodel.fit(eqe_fit, E=energy_fit, fCT=p0[0], lCT=p0[1], ECT=p0[2], fopt=p0[3], lopt=p0[4], Eopt=p0[5], sig=p0[6] ) if print_report: print(result.fit_report()) fCT = float(result.params['fCT'].value) lCT = float(result.params['lCT'].value) ECT = float(result.params['ECT'].value) fopt = float(result.params['fopt'].value) lopt = float(result.params['lopt'].value) Eopt = float(result.params['Eopt'].value) sig = float(result.params['sig'].value) best_vals = [fCT, lCT, ECT, fopt, lopt, Eopt, sig] covar = result.covar if covar is None: covar = np.zeros((7, 7)) y_fit = gmodel.eval(E=np.array(energy_fit), fCT=fCT, lCT=lCT, ECT=ECT, fopt=fopt, lopt=lopt, Eopt=Eopt, sig=sig ) else: result = gmodel.fit(eqe_fit, E=energy_fit, fCT=p0[0], lCT=p0[1], ECT=p0[2], fopt=p0[3], lopt=p0[4], Eopt=p0[5] ) if print_report: print(result.fit_report()) fCT = float(result.params['fCT'].value) lCT = float(result.params['lCT'].value) ECT = float(result.params['ECT'].value) fopt = float(result.params['fopt'].value) lopt = float(result.params['lopt'].value) Eopt = float(result.params['Eopt'].value) best_vals = [fCT, lCT, ECT, fopt, lopt, Eopt] covar = result.covar if covar is None: covar = np.zeros((6, 6)) y_fit = gmodel.eval(E=np.array(energy_fit), fCT=fCT, lCT=lCT, ECT=ECT, fopt=fopt, lopt=lopt, Eopt=Eopt ) r_squared = R_squared(eqe_fit, y_fit) return best_vals, covar, y_fit, r_squared
DA_params = Parameters() with open("dual_annealing_params.json", mode='r') as fname: params = json.load(fname) DA_params.loads(params) path_to_covid_data = "RJ_data.csv" path_to_pop_data = "RJ_populations.csv" DATA = get_data(path_to_pop_data, path_to_covid_data) X0 = DATA[0] time_frame = np.arange(0, 365, 1) kinetic_seasonal_model = Model(SIRD_kinetic_seasonal, independent_vars=['t', 'x0']) no_social_distancing_model = Model(SIRD_kinetic_seasonal_no_SD, independent_vars=['t', 'x0']) DE_pred = kinetic_seasonal_model.eval(DE_params, t=time_frame, x0=X0) BH_pred = kinetic_seasonal_model.eval(BH_params, t=time_frame, x0=X0) DA_pred = kinetic_seasonal_model.eval(DA_params, t=time_frame, x0=X0) print "Differential Evolution:" DE_params.pretty_print() print "gamma0 : %f" % (DE_params["gamma_sum"] * DE_params["gamma_partition"]) print "gamma1 : %f" % (DE_params["gamma_sum"] * (1 - DE_params["gamma_partition"])) print "mu0 : %f" % (DE_params["mu_sum"] * DE_params["mu_partition"]) print "mu1 : %f" % (DE_params["mu_sum"] * (1 - DE_params["mu_partition"])) print "Total Number of Infected DE:\t\t%.1f" % (DE_pred[-1,2] + DE_pred[-1,3]) print "Total Number of Dead DE:\t\t\t%.1f\n" % DE_pred[-1,3] print "Basin Hopping:" BH_params.pretty_print()
x2 = linspace(0.0, 11.0, num=300) #variable ind para fit, 300 asi el eje x esta en 1ns gmod = Model(gaussian) #Generar un Modelo Gaussiano #Iterar el Corpus de datos para realizar un archivo con los features en tuplas #sampled_data = [] with open("C:\Users\Anai\Desktop\Miguel\LAGO\LAGO-AI\src\cosmicfilter\CosmicTrain.txt", "r") as f: with open("OutputClusterReduced.txt", "w") as output: for l in f: data = l.split("-") raw_data = data[0].strip().split(" ") #print(raw_data) y = [int(i)-47 for i in raw_data] peak = max(y) result = gmod.fit(y, x=x, amp=peak, cen=3, wid=1) final = gmod.eval(x=x2, amp=result.best_values['amp'], cen=result.best_values['cen'], wid=result.best_values['wid']) rtime = argmax(final) dummy = str(rtime)+"-"+str(peak) #if dummy not in sampled_data: output.write("["+str(rtime)+","+str(float(peak))+"]\n") #sampled_data.append(str(rtime)+"-"+str(peak)) print("Finished...") #amp_result = result.best_values['amp'] #cen_result = result.best_values['cen'] #wid_result = result.best_values['wid'] #print(result.fit_report()) #print(final)
class XRFAllElementModel(Model): def __init__(self, exptdesc,linedict,xrffunc,comptonfunc, elasticfunc, linetype='element',*args,**kwargs): """ An XRF spectrum model LMFIT offers a range of options for coupling parameters and models but in order to be able to do this it needs to manipulate parameters - in particular string expressions and this leads big slowdowns if you've a large number of models or coupled parameters. To speed up the calculation rather than create the XRF spectrum from a sum of Gaussian Models we create a single model with many parameters. The basic lmfit model works as follows: parse the arguments of the input function. Build a list of param names from these arguments Apply paramhints to these param_names or make parameters from the param names This class will pass a basic line """ # Pass an empty function to model super(XRFAllElementModel, self).__init__(None,*args, **kwargs) # Arguments need to be converted to # a list of elements (the peaks -> translating to peak areas) + the line type arguments # The basic model just assigns # self.func = function # parses the function parameters to # # line model self.funcmodel = Model(xrffunc) self.funcparams_all = self.funcmodel.make_params() self.funcparams_sub = self.funcmodel.make_params() # remove the area and center parameter self.funcparams_all.pop("area",None) self.funcparams_all.pop("center",None) # pileup model self.pileupmodel = Model(linefunc) self.pileupmodel = self.pileupmodel.make_params() # remove the area and center parameter self.funcparams_all.pop("area",None) self.funcparams_all.pop("center",None) # get the function name self.linedict = linedict self.exptdesc = exptdesc self.funcname = linefunc.__name__ self._name = "xrf_model" self.func = self.funcover #self.create_full_parameters(self) def create_full_parameters(self): # remove the area and center parameter # For each element in the linedict add a parameter # which will control the area self.funcparams_all = deepcopy(self.funcparams_sub) self.funcparams_all.pop("area",None) self.funcparams_all.pop("center",None) for key in self.exptdesc["lineshape"]["element"][self.funcname].keys(): if key in self.funcparams_all: self.funcparams_all[key].value = \ self.exptdesc["lineshape"]["element"]\ [self.funcname][key]["value"] self.funcparams_all[key].min = \ self.exptdesc["lineshape"]["element"]\ [self.funcname][key]["min"] self.funcparams_all[key].max = \ self.exptdesc["lineshape"]["element"]\ [self.funcname][key]["max"] self.funcparams_all[key].vary = \ self.exptdesc["lineshape"]["element"]\ [self.funcname][key]["vary"] for key in self.linedict: # if not '+' in key: self.funcparams_all.add(key, **self.exptdesc["lineshape"]["element"][self.funcname]["area"]) def make_params(self): self.create_full_parameters() return self.funcparams_all def funcover(self, params,**kwargs): # # copy the function based parameters from params to funcparams # for key in params: if key in self.funcparams_sub: self.funcparams_sub[key].value = params[key].value self.funcparams_sub[key].min = params[key].min self.funcparams_sub[key].max = params[key].max self.funcparams_sub[key].vary = params[key].vary xrf_sigma_keys = [s for s in self.funcparams_sub if 'sigma' in s] elastic_sigma_keys = [s for s in self.elasticparams if 'sigma' in s] xrf_sigma_keys = [s for s in self.funcparams_sub if 'sigma' in s] first=True # # Do the basic lines XRF and Escape first... # for key,linegroup in self.linedict.iteritems(): if key in params: for line in linegroup: # update funcparams self.funcparams_sub["area"].value = params[key].value*\ line.intensity self.funcparams_sub["center"].value = line.line_energy if isinstance(line,(XrayLine,EscapeLine)): for ii in sigma_keys: self.funcparams_sub[ii].value = np.sqrt(params[ii].value**2 + \ (line.line_energy*0.001)) lineresult =\ self.funcmodel.eval(self.funcparams_sub,**kwargs) if isinstance(line,(ElasticLine)): for ii in elastic_sigma_keys: self.funcparams_sub[ii].value = np.sqrt(params[ii].value**2 + \ (line.line_energy*0.001)) lineresult=\ self.elasticmodel.eval(self.funcparams_sub,**kwargs) if isinstance(line,(ComptonLine)): for ii in elastic_sigma_keys: self.funcparams_sub[ii].value = np.sqrt(params[ii].value**2 + \ (line.line_energy*0.001)) lineresult=\ self.comptonmodel.eval(self.funcparams_sub,**kwargs) if isinstance(line,PileupLine): # full method is to convolute the lines # split the label to determine the individual lines # generate each line... # roll them both to zero # convolve the lineshapes # roll them back to the energy pass if first: result = lineresult first = False else: result += lineresult return result def eval(self, params=None, **kwargs): result= self.funcover(params=params, **kwargs) return result
def process_cam_image(self, data, title_string, draw_plots = False): """process a matrix of camera data""" ret = {} # values in pixels and counts ret['fit_fail'] = True ret['saturated'] = True ret['sigmaX'] = 0 ret['sigmaY'] = 0 ret['peakPosX'] = 0 ret['peakPosY'] = 0 ret['amplitude'] = 0 ret['theta'] = 0 ret['blur_volume'] = 0 ret['blur_peak'] = 0 ret['background'] = 0 if draw_plots: # plot the image fig = plt.figure() ax = plt.matshow(data, fignum=fig.number) ax.axes.xaxis.tick_bottom() plt.title('RAW Camera|' + title_string) plt.colorbar(label='Counts') cameraBits = 12 # bit depth of the camera nCameraValues = 2**cameraBits # and so there are this many unique values a pixel can take on maxCamValue = nCameraValues - 1 # and so the maximum value a pixel can take on is this xRes = data.shape[0] # image x resolution yRes = data.shape[1] # image y resolution nPix = xRes * yRes # number of pixels in camera image # corner method of finding background #cornerDim = 50 #corner = camData[:cornerDim,-cornerDim:] # take corner of the image #background = corner.mean() # histogram method of finding background (better probs) # take a histogram of counts in image and call the bin with the most counts the background bins = np.bincount(data.ravel(),minlength=nCameraValues) # maybe gaussian blur the image first? background = bins.argmax().astype(np.int16) ret['background'] = background #print("Camera background found to be {:} counts.".format(background)) # camData with background offset subtracted away bg0 = data.copy() - background #camMax = camData.max() #camAvg = camData.mean() #print("Camera Maximum:",camMax * photons_per_count,"[photons]") #self.sd['camMax'] = float(camMax * photons_per_count) # global auto-threshold the image (for finding the substrate) blur = data.copy() # copy camera data so we don't mess up the origional blur = cv2.medianBlur(src=blur, ksize=5) # median filter here bg0_blur = blur - background # camData with background offset subtracted away # detect camera saturation saturation_percent_of_max = 5 # any pixel within this percent of max is considered saturated saturation_percent_of_pixels = 1 # if any more than this percent of total pixels in ROI are saturated, then we set the saturated flag for the image sat_thresh = np.int16(round((1-(saturation_percent_of_max / 100)) * maxCamValue)) # any pixel over this value is saturated nSatPix = np.count_nonzero(blur.ravel() >= sat_thresh) # number of saturated pixels cameraSaturated = True if nSatPix < nPix*saturation_percent_of_pixels / 100: cameraSaturated = False ret['saturated'] = False else: print("WARNING: Image saturation detected. >{:}% of pixels are within {:}% of their max value".format(saturation_percent_of_pixels, saturation_percent_of_max)) cantFindSubstrate = True if (not cameraSaturated): ret['blur_peak'] = bg0_blur.max() ret['blur_volume'] = bg0_blur.sum() if self.verbose: print("Median filtered image peak: {:.0f} [counts]".format(ret['blur_peak'])) print("Median filtered image volume: {:.3g} [counts]".format(ret['blur_volume'])) # global auto-threshold the image (for finding the substrate) thresh_copy = data.copy() # copy camera data so we don't mess up the origional thresh_copy = (thresh_copy/nCameraValues*(2**8-1)).round() # re-normalize to be 8 bit thresh_copy = thresh_copy.astype(np.uint8) # information loss here, though only for thresh finding just because the big (k=15 filter makes) cv2 puke for 16bit numbers :-P thresh_blur = cv2.medianBlur(src=thresh_copy, ksize=15) # big filter here tret,thresh = cv2.threshold(thresh_blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) # global auto-threshold nz = cv2.findNonZero(thresh) # thresh --> bool if nz is not None: mar = cv2.minAreaRect(nz) # find our substrate, minimum area rectangle = ((center_x,center_y),(width,height), angle) else: # this gets hit when the camera data is dark mar = ((0,0),(0,0), 0) # caculate the ROI boxScaleFactor = 0.70 # reduce ROI by this factor to prevent substrate edge effects smaller = (mar[0],tuple([x*boxScaleFactor for x in mar[1]]), mar[2]) # scale box width and height box = cv2.boxPoints(smaller).astype(np.int0) # find new ROI corners # show user the new ROI whereIsROI = cv2.drawContours(thresh_blur, [box], 0, 127, 3) if draw_plots: # for the ROI image fig = plt.figure() ax = plt.matshow(whereIsROI, fignum=fig.number, cmap='gray', vmin = 0, vmax = 255) ax.axes.xaxis.tick_bottom() plt.title('Camera ROI|' + title_string) # did we find the substrate? approxSubstrateArea = mar[1][0] * mar[1][1] # compute substrate area substrateAreaFactor = 0.8 if nPix * substrateAreaFactor > approxSubstrateArea: # test if the ROI is huge cantFindSubstrate = False # now we'll crop the blurred camera data ROI = np.full(data.shape, np.NaN) # ROI starts as NaNs TODO: check shape, maybe bg0_blur mask = np.zeros_like(data) # now we'll build up a mask for the ROI TODO: check shape, maybe bg0_blur cv2.drawContours(mask, [box], 0, 255, -1) # fill the ROI box with white in the mask array ROI[mask == 255] = bg0_blur[mask == 255] # now copy the blurred image data from the ROI region into the ROI array else: print("WARNING: Can't find the substrate") # and quit if it's too big if self.fitSpot and (not cantFindSubstrate) and (not cameraSaturated): # let's make some initial guesses for the 2d gaussian fit twoDG_model = Model(analyzer.twoD_Gaussian, independent_vars=['x','y', 'offset']) guesses = twoDG_model.make_params() # the raw image moment calculation forms the basis of our guesses m = cv2.moments(bg0_blur) data_sum = m['m00'] # "center of mass" guesses['yo'].value = m['m10']/data_sum guesses['xo'].value = m['m01']/data_sum #angle = 0.5 * np.arctan(2 * m['mu11'] / (m['mu20'] - m['mu02'])) #guesses['theta'].value = abs(angle - constants.pi/4) - constants.pi/4# lol, wtf, check this against more examples guesses['theta'].value = 0 # can't really get angle guess right guesses['sigma_y'].value = np.sqrt(m['mu20']/m['m00']) guesses['sigma_x'].value = np.sqrt(m['mu02']/m['m00']) # take an average of the points around the peak to find amplitude xc = round(guesses['xo'].value) yc = round(guesses['yo'].value) guesses['amplitude'].value = bg0_blur[xc,yc] # Create x and y grid xv = np.linspace(0, xRes-1, xRes) #TODO: check if yRes needs to be used here yv = np.linspace(0, yRes-1, yRes) #TODO: check if xRes needs to be used here x, y = np.meshgrid(xv, yv, indexing='ij') #x, y = np.meshgrid(xv, yv) # here we fit the camera data to a 2D gaussian model fitFail = True try: fitResult = twoDG_model.fit(ROI, x=x, y=y, offset=0, params=guesses, nan_policy='omit', fit_kws={'maxfev': 500}) if fitResult.success: fitFail = False except: pass if fitFail: print('Camera spot 2D gaussian fit failure \a') else: # do these things when the fit does not fail # the fit parameters in counts and pixels ret['sigmaX'] = fitResult.params['sigma_x'].value ret['sigmaY'] = fitResult.params['sigma_y'].value ret['peakPosX'] = fitResult.params['xo'].value ret['peakPosY'] = fitResult.params['yo'].value ret['amplitude'] = fitResult.params['amplitude'].value ret['theta'] = fitResult.params['theta'].value if self.verbose: totalVolume = 2 * constants.pi * ret['amplitude'] * ret['sigmaX'] * ret['sigmaY'] print("Gaussian spot amplitude seen by camera: {:.0f} [counts]".format(ret['amplitude'])) print("Gaussian spot volume seen by camera: {:.3g} [counts]".format(totalVolume)) print("Gaussian spot sigma X : {:.2f} [pixels]".format(ret['sigmaX'])) print("Gaussian spot sigma Y : {:.2f} [pixels]".format(ret['sigmaY'])) print("Gaussian spot position X : {:.2f} [pixels]".format(ret['peakPosX'])) print("Gaussian spot position Y : {:.2f} [pixels]".format(ret['peakPosY'])) print("Gaussian spot rotation : {:.4f} [radians]".format(ret['theta'])) if draw_plots: theta = fitResult.params['theta'].value amplitude = fitResult.params['amplitude'].value peakPos = (fitResult.params['xo'].value, fitResult.params['yo'].value) sigma = (fitResult.params['sigma_x'].value, fitResult.params['sigma_y'].value) fitSurface2D = twoDG_model.eval(x=x, y=y, offset=0, params=fitResult.params) # let's make some evaluation lines nPoints = 100 nSigmas = 4 # line length, number of sigmas to plot in each direction rA = np.linspace(-nSigmas*sigma[0], nSigmas*sigma[0], nPoints) # radii (in polar coords for line A) AX = rA*np.cos(theta+np.pi/2) + peakPos[0] # x values for line A AY = rA*np.sin(theta+np.pi/2) + peakPos[1] # y values for line A rB = np.linspace(-nSigmas*sigma[1],nSigmas*sigma[1],nPoints) # radii (in polar coords for line B) BX = rB*np.cos(theta) + peakPos[0] # x values for line B BY = rB*np.sin(theta) + peakPos[1] # y values for line B f = interpolate.RectBivariateSpline(xv, yv, data) # linear interpolation for data surface lineAData = f.ev(AX,AY) lineAFit = twoDG_model.eval(x=AX, y=AY, offset=background, params=fitResult.params) lineBData = f.ev(BX,BY) lineBFit = twoDG_model.eval(x=BX, y=BY, offset=background, params=fitResult.params) residuals = lineBData - lineBFit ss_res = np.sum(residuals**2) ss_tot = np.sum((lineBData - np.mean(lineBData)) ** 2) r2 = 1 - (ss_res / ss_tot) fig, axes = plt.subplots(2, 2,figsize=(8, 6), facecolor='w', edgecolor='k') fig.suptitle('Camera|' + self.titleString, fontsize=10) axes[0,0].matshow(data, cmap=plt.cm.copper) axes[0,0].contour(y, x, mask, 3, colors='yellow', alpha=0.2) #thresh #whereIsROI2 = cv2.drawContours(camData, [box], 0, 50, 3) #axes[0,0].matshow(whereIsROI2, cmap=plt.cm.copper) # ax.axes.xaxis.tick_bottom() if len(np.unique(fitSurface2D)) is not 1: # this works around a bug in contour() axes[0,0].contour(y, x, fitSurface2D, 3, colors='gray', alpha=0.5) else: print('Warning: contour() bug avoided') axes[0,0].plot(AY,AX,'r', alpha=0.5) # plot line A axes[0,0].plot(BY,BX,'g', alpha=0.5) # plot line B axes[0,0].set_title("Image Data") axes[0,0].set_ylim([xv.max(), xv.min()]) axes[0,0].set_xlim([yv.min(), yv.max()]) axes[0,0].xaxis.tick_bottom() axes[1,0].plot(rA, lineAData, 'r', label='Data') axes[1,0].plot(rA, lineAFit, 'k', label='Fit') axes[1,0].set_title('Red Line Cut') axes[1,0].set_xlabel('Distance from center of spot [pixels]') axes[1,0].set_ylabel('Magnitude [counts]') axes[1,0].grid(linestyle = '--') handles, labels = axes[1,0].get_legend_handles_labels() axes[1,0].legend(handles, labels) axes[1,1].plot(rB,lineBData,'g',label='Data') axes[1,1].plot(rB,lineBFit,'k',label='Fit') axes[1,1].set_title('Green Line Cut') axes[1,1].set_xlabel('Distance from center of spot [pixels]') axes[1,1].set_ylabel('Magnitude [counts]') axes[1,1].yaxis.set_label_position("right") axes[1,1].grid(linestyle='--') handles, labels = axes[1,1].get_legend_handles_labels() axes[1,1].legend(handles, labels) axes[0,1].axis('off') axes[0,1].set_title('Fit Details') logMessages = io.StringIO() print("Green Line Cut R^2 = {:0.8f}".format(r2), file=logMessages) print("Peak = {:+011.5f} [counts]\n".format(amplitude+background), file=logMessages) print(" ====Fit Parameters====", file=logMessages) print("Amplitude = {:+011.5f} [counts]".format(amplitude), file=logMessages) print("Center X = {:+011.5f} [pixels]".format(peakPos[1]), file=logMessages) print("Center Y = {:+011.5f} [pixels]".format(peakPos[0]), file=logMessages) print("Sigma X = {:+011.5f} [pixels]".format(sigma[1]), file=logMessages) print("Sigma Y = {:+011.5f} [pixels]".format(sigma[0]), file=logMessages) print("Rotation = {:+011.5f} [radians]".format(theta), file=logMessages) print("Baseline = {:+011.5f} [counts]".format(background), file=logMessages) logMessages.seek(0) messages = logMessages.read() axes[0,1].text(0,0,messages, family='monospace') ret['fit_fail'] = fitFail return(ret)
class XRFModel(Model): def __init__(self, exptdesc, linedict, linefunc, *args, **kwargs): """ An XRF spectrum model LMFIT offers a range of options for coupling parameters and models but in order to be able to do this it needs to manipulate parameters - in particular string expressions and this leads big slowdowns if you've a large number of models or coupled parameters. To speed up the calculation rather than create the XRF spectrum from a sum of Gaussian Models we create a single model with many parameters. The basic lmfit model works as follows: parse the arguments of the input function. Build a list of param names from these arguments Apply paramhints to these param_names or make parameters from the param names This class will pass a basic line """ # Pass an empty function to model super(XRFModel, self).__init__(linefunc, prefix="xrf_", independent_vars=['x', 'area', 'center']) self.linedict = linedict self.exptdesc = exptdesc self.func = self.xrffunc self.linefunc = linefunc self.xrfmodel = Model(linefunc) self.set_param_hints_from_dict("element", linefunc.__name__) name = None if name is None and hasattr(self.xrffunc, '__name__'): name = self.func.__name__ self._name = name def set_param_hints_from_dict(self, linetype, linefuncname): """ This sets the default paramter hints for the model on setup """ avail_hints = self.exptdesc["lineshape"][linetype][linefuncname].keys() for key in avail_hints: if key in self._param_root_names: self.set_param_hint(key,expr=None,**self.exptdesc["lineshape"]\ [linetype][linefuncname][key]) # exclude pileups from the parameters for key in self.linedict: if not any(word in key for word in ['+', 'Elastic', 'Compton']): self.set_param_hint(key,expr=None,**self.exptdesc["lineshape"]["element"]\ [self.linefunc.__name__]["area"]) self.set_param_hint("fano",expr=None,**self.exptdesc["xrf_fitting"]["params"]\ ["fano"]) def make_params(self): params = super(XRFModel, self).make_params() # # If the element list is empty return no parameters... # elementlist = [] for key in self.linedict: if any(keyv not in key for keyv in ['+', 'Elastic', 'Compton']): elementlist.append(key) if elementlist: return params else: return Parameters() def xrffunc(self, params, **kwargs): xrf_sigma_keys = [s for s in params if 'sigma' in s] # # common parameters # pileup_factor , fano # first = True x = kwargs.get('x', None) result = np.zeros(len(x)) fano = params["fano"] # # Do the basic lines XRF and Escape first... # for key, linegroup in self.linedict.iteritems(): if key in params: for line in linegroup: area = params[key].value * line.intensity center = line.line_energy # update funcparams #if type(line) == XrayLine or type(line) == EscapeLine: if isinstance(line, (XrayLine, EscapeLine)): for ii in xrf_sigma_keys: params[ii].value = sqrt(params[ii].value**2 + \ (center*fano)) lineresult =\ self.xrfmodel.eval(params=params,area = area, center = center,**kwargs) if first: result = lineresult first = False else: result += lineresult # # generate the pileup lines... # you can convolute the whole line with itself to get the pileup # (basic code is a variation on what's done in pymca..) # # # The problem is largely in the intensity scaling. For a simple # 2-event summation you can just scale it by some factor # but for 3 event pileup the magnitude over the curve # grows rather than diminishes. # # result = result + pileup_factor*self.selfconvolute(result,**kwargs) return result def eval(self, params=None, **kwargs): pardict = self.make_funcargs(params) return self.xrffunc(params, pardict, **kwargs)
def simple_echo_fits2(): """ Takes the highest point of each echo and fits the echo_as_T2 function to those points. """ datafolder = filedialog.askopenfilenames(initialdir="C:\\Users\Josh\IdeaProjects\OpticalPumping", title="Select data for bulk plotting") for filename in datafolder: name_ext = filename.split('/')[-1] name_no_ending = name_ext.split('.csv')[0] dat1 = read_csv("C:\\Users\\Josh\\IdeaProjects\\OpticalPumping\\Rabi_RDAT\\{}".format(name_ext), names=['T', 'V']) backup_datV = np.array(dat1['V']) backup_datT = np.array(dat1['T']) try: dat3 = read_csv("C:\\Users\\Josh\\IdeaProjects\\OpticalPumping\\Sweep_ranges\\{}".format(name_ext), names=['Lower Bound', 'LowerIndex', 'Upper Bound', 'UpperIndex']) except FileNotFoundError: fig1, ax1 = plt.subplots() plt.title('Pick Ranges for Exponential decay fit') Figure1, = ax1.plot(dat1['T'], dat1['V']) Sel3 = RangeTool(dat1['T'], dat1['V'], Figure1, ax1, name_no_ending) fullscreen() plt.show() dat3 = Sel3.return_range() plt.close() xrange = [] yrange = [] xranges = {} yranges = {} x_append = xrange.append y_append = yrange.append for o in range(0, len(dat3)): x_append((dat1['T'][dat3['LowerIndex'][o]:dat3['UpperIndex'][o] + 1]).values) y_append((dat1['V'][dat3['LowerIndex'][o]:dat3['UpperIndex'][o] + 1]).values) for o in range(0, len(xrange)): xranges[o] = xrange[o] yranges[o] = yrange[o] xrs = xranges yrs = yranges length = len(yrs) try: max_y = [np.max(yrs[i]) for i in range(length)] max_y_loc = [np.where(yrs[i] == max_y[i])[0][0] for i in range(length)] cents = [xrs[i][max_y_loc[i]] for i in range(length)] min_y = [np.min(yrs[i]) for i in range(length)] min_y_loc = [np.where(yrs[i] == min_y[i])[0][0] for i in range(length)] min_cents = [xrs[i][min_y_loc[i]] for i in range(length)] heights = max_y heights2 = min_y # TODO: Find a better value for the uncertainty on y-values. heights = np.array(heights) cents = np.array(cents) min_cents = np.array(min_cents) maxy = np.max(heights) miny = np.min(heights) heights2 = np.array(heights2) maxy2 = np.max(heights2) avg_y_sep = abs(np.mean(np.diff(heights))) ys = [((heights2[x] + heights2[x + 1]) / 2 if x < len(heights2) - 1 else heights2[x]) for x in range(len( heights2 - 1))] background_interp = interp1d(x=cents, y=ys, bounds_error=False) dat1['V'] = dat1['V'] - background_interp(dat1['T']) heights = heights - ys maxy = maxy - background_interp(cents[0]) efit = Model(echo_as_T2) param = efit.make_params() decay_pos = np.where(heights == find_nearest(heights, maxy / e))[0][0] decay_pos_time = cents[decay_pos] param.add('M0', value=maxy, min=maxy * 0.9, max=maxy + (avg_y_sep * 1.5)) param.add('T2', value=decay_pos_time, min=decay_pos_time * 0.1, max=decay_pos_time * 6.5) param.add('ph', value=cents[0] * 0.6, min=0, max=cents[0] * 1.3) param.add('c', value=0, min=-5, max=5) result_2 = efit.fit(heights, param, t=cents, method='brute', weights=np.mean(np.diff(dat1['T'])) / heights2) print('\n', name_no_ending) print(result_2.fit_report()) fig3, ax3 = plt.subplots(figsize=(8, 5.5)) ax3.set_xlabel('Time (µs)', fontsize=14) ax3.set_ylabel('Voltage (a.u.)', fontsize=14) xes = np.linspace(np.min(cents), np.max(cents), 100) y = efit.eval(t=xes, params=result_2.params) plt.plot(xes, y, antialiased=True) plt.plot(min_cents, ys - background_interp(min_cents)) # plt.plot(xes, quadratic(xes, result_2.params['m1'].value, result_2.params['m'].value, result_2.params[ # 'c'].value)) plt.plot(cents, heights, 'x', ms=8, color='k') plt.plot(dat1['T'], dat1['V'], lw=2, antialiased=True, color='#4a4a4a', zorder=1) plt.title(filename) plt.xlim(left=0, right=np.max(cents) * 1.1) # plt.ylim(bottom=0, top=result_2.params['M0'].value * 1.1) plt.axhline(result_2.params['M0'].value, color='k', ls='--', alpha=0.7, lw=1, zorder=2) plt.axhline(result_2.params['M0'].value / e, color='k', ls='--', alpha=0.7, lw=1, zorder=2) plt.text(0.9, 0.9, "T_1: {:.4f} us".format(result_2.params['T2'].value), horizontalalignment='center', verticalalignment="center", transform=ax3.transAxes, bbox={'pad': 8, 'fc': 'w'}, fontsize=14) # plt.tight_layout() plt.tick_params(axis='both', which='major', labelsize=13) fullscreen() plt.savefig("C:\\Users\\Josh\\IdeaProjects\\OpticalPumping\\MatplotlibFigures\\ExpDecay_{}.png".format( name_no_ending), dpi=600) plt.show() plt.close() dat1.dropna(axis=0, how='any', inplace=True) sample_rate = round(1 / np.mean(np.diff(dat1['T'])), 11) length = len(dat1['T']) fo = fftpack.fft(dat1['V']) freq4 = [x * 10e6 * sample_rate / length for x in np.array(range(0, length))] fig5, ax5 = plt.subplots(figsize=(8, 5.5)) plt.title('Select region containing peak') figure5, = ax5.plot(freq4[2:100], abs(fo[2:100])) # Sel1 = RangeTool(freq4[2:100], abs(fo[2:100]), figure5, ax5, 'thing') fullscreen() ax5.set_xlabel('Frequency (Hz)', fontsize=14) ax5.set_ylabel('Intensity (a.u.)', fontsize=14) plt.savefig("C:\\Users\\Josh\\IdeaProjects\\OpticalPumping\\MatplotlibFigures\\FourierDecay_{}.png".format( name_no_ending), dpi=600) plt.show() # range2 = Sel1.return_range() bing = np.where(abs(fo[2:100]) == np.max(abs(fo[2:100])))[0][0] print('Maximum frequency: {:.2f}Hz'.format(freq4[2:100][bing])) print('\n \n ') plt.close() except ValueError: print('ValueError in simpleechofits2 at end') continue
#result = gmodel.fit(y, x=x, amp=5, cen=5, wid=1) #print(result.fit_report()) JH = CRDW(i) pos, neg = correlation(i) beta = cointegration(JH) country = Y_growth[i] model = Model(model,independent_vars=['JH','pos', 'neg', 'beta', 'country']) from lmfit import Model model_us = Model(model) model_us.independent_vars model.independent_vars model_us.eval(params, i=7) model_us.fit(7, params) pars = model.make_params(a=3, b=0.5) mod = Model(myfunc) mod.set_param_hint('a', value=1.0) mod.set_param_hint('b', value=0.3, min=0, max=1.0) pars = mod.make_params() range_N=[50] range_T=[50] range_alpha=[2, 5, 10] range_a=[1, 2, 5, 10] range_var_eps=[0.5, 1]
def param(self): RF_mcvine = [] RFE_mcvine = [] RF_intp = [] RFE_intp = [] RF_Fit = [] peak_positionE = [] error = [] R_fit = [] a_fit = [] b_fit = [] s_fit = [] t0_fit = [] A_fit = [] p_fit = [] a0 = 1.6 a1 = 1.5 b0 = 31.9 k = 46. # b_cal = 1 / b0 Ei_array = np.array([15, 60, 100, 200, 600]) a_array = np.array([0.21850, 0.35601, 0.46473, 0.71558, 1.33170]) b_array = np.array([0.03737, 0.03931, 0.04370, 0.09717, 0.19422]) R_array = np.array([0.76500, 0.73662, 0.62021, 0.31510, 0.26689]) t0_array = np.array([0.42578, 0.22595, 0.17405, 0.12609, 0.07622]) A_fixed = 1 s_fixed = 2 a = QApplication([]) mcvine = QFileDialog.getOpenFileNames()[0] # a_cal = interp1d(Ei_array, a_array, fill_value='interpolate', kind='cubic')(self.Ei) # b_cal = interp1d(Ei_array, b_array, fill_value='interpolate', kind='cubic')(self.Ei) # R_cal = interp1d(Ei_array, R_array, fill_value='interpolate', kind='cubic')(self.Ei) # t0_cal = interp1d(Ei_array, t0_array, fill_value='interpolate', kind='cubic')(self.Ei) if self.Ei == 30: a_cal = 0.28175 b_cal = 0.03827 R_cal = 0.78498 t0_cal = 0.30687 if self.Ei == 130: a_cal = 0.528 b_cal = 0.04910 R_cal = 0.51 t0_cal = 0.155 if self.Ei == 300: a_cal = 0.89 b_cal = 0.15 R_cal = 0.28 t0_cal = 0.10 # R_cal = 0.5 # 0.5 for Ei=30, # a_cal = 1. / (a0 + (self.lamda(self.Ei) * a1)) no_Et_Files = len(mcvine) for i in range(no_Et_Files): mcvineSol = mcvine[i] print(mcvineSol) iqe = hh.load(mcvineSol) iqe.I[iqe.I != iqe.I] = 0 ie = iqe.sum('Q') # histogram of DOS ie.I[np.isnan(ie.I)] = 0 ie.I = ie.I / np.sum(ie.I) RF_mcvine.append(ie.I) RFE_mcvine.append(ie.E) peak_position = ie.E[np.where(ie.I == max(ie.I))[0][ 0]] # finding the position of the peak of Eenergy transfer thar are given from mcvine # if self.Ei==30: # if peak_position>20: # s_fixed=8 peak_positionE.append(peak_position) #### interpolation EnerInt = np.arange(min(ie.E), max(ie.E), self.Et_interpolation_space) RF_inpl = interp1d(ie.E, ie.I, fill_value='interpolate', kind='cubic')(EnerInt) RF_inpl[RF_inpl < 0] = 0 RF_intp.append(RF_inpl) RFE_intp.append(EnerInt) ##model fitting taxis = self.t(self.l3, self.Ei, peak_position, EnerInt) mod = Model(self.Count) # RF_inpl = RF_inpl / np.sum(RF_inpl) p_val = np.sum(RF_inpl) # RF_inter.append( RF_inpl(EnerInt )) # t0_cal =1 # # print (t_fixed) # if self.Ei==30: # t_fixed = peak_position # R_cal=np.exp(-81.799/(k*(self.lamda(self.Ei)**2))) # if self.Ei == 130: # R_cal=0.5 print(a_cal, b_cal, R_cal) # if self.Ei == 130: # mod.set_param_hint('R', value=R_cal, min=0.0, max=1.0 ) # mod.set_param_hint('a', value=a_cal, min=0.0) # mod.set_param_hint('b', value=b_cal, min=0.0) # mod.set_param_hint('s', value=s_fixed, min=0.0) # mod.set_param_hint('t0', value=t_fixed, min=0.0) # if self.Ei == 30: # mod.set_param_hint('R', value=R_cal, min=0.0, max=1.0) # mod.set_param_hint('a', value=a_cal, min=0.0) # mod.set_param_hint('b', value=b_cal, min=0.0) # mod.set_param_hint('s', value=s_fixed, min=0.0) # mod.set_param_hint('t0', value=t_fixed, min=0.0, vary=False) # if self.Ei == 30: # mod.set_param_hint('R', value=R_cal, vary=False) # mod.set_param_hint('a', value=a_cal, vary=False) # mod.set_param_hint('b', value=b_cal, vary=False) # mod.set_param_hint('s', value=s_fixed, min=0.0) # mod.set_param_hint('t0', value=t_fixed, min=0.0) # if self.Ei == 300: if i == 0: mod.set_param_hint('R', value=R_cal, min=0.0, max=1.0) mod.set_param_hint('a', value=a_cal) mod.set_param_hint('b', value=b_cal) mod.set_param_hint('s', value=s_fixed, min=0.0) mod.set_param_hint('t0', value=t0_cal, min=0.0) if i > 0: mod.set_param_hint('R', value=R_cal, vary=False) mod.set_param_hint('a', value=a_cal, vary=False) mod.set_param_hint('b', value=b_cal, vary=False) mod.set_param_hint('s', value=s_fixed, min=0.0) mod.set_param_hint('t0', value=t0_cal, min=0.0, vary=False) mod.set_param_hint('p', value=p_val, min=0.0, vary=False) # a.exec_() pars = mod.make_params() result = mod.fit(RF_inpl, pars, tm=taxis, fit_kws={'nan_policy': 'omit'}) RF_Fit.append(result.best_fit) residual = np.sqrt((np.sum( (RF_inpl - result.best_fit)**2)) / len(EnerInt)) error.append(residual) dely = mod.eval(pars, tm=taxis) R_cal0 = R_cal a_cal0 = a_cal b_cal0 = b_cal t0_cal0 = t0_cal R_cal = result.params['R'].value a_cal = result.params['a'].value b_cal = result.params['b'].value t0_cal = result.params['t0'].value R_fit.append(result.params['R'].value) # saving the parameters a_fit.append(result.params['a'].value) # saving the parameters b_fit.append(result.params['b'].value) # saving the parameters s_fit.append(result.params['s'].value) # saving the parameters t0_fit.append(result.params['t0'].value) # saving the parameters p_fit.append(result.params['p'].value) # saving the parameters # print R_fit RF_mcvine = np.reshape(RF_mcvine, (no_Et_Files, -1)) RFE_mcvine = np.reshape(RFE_mcvine, (no_Et_Files, -1)) RF_intp = np.reshape(RF_intp, (no_Et_Files, -1)) RFE_intp = np.reshape(RFE_intp, (no_Et_Files, -1)) RF_Fit = np.reshape(RF_Fit, (no_Et_Files, -1)) np.savetxt( 'Ikeda_Carpenter Parameters for Ei= {}.xlsx'.format(self.Ei), np.c_[peak_positionE, R_fit, a_fit, b_fit, s_fit, t0_fit]) return (RF_mcvine, RFE_mcvine, RF_intp, RFE_intp, RF_Fit, R_fit, a_fit, b_fit, s_fit, t0_fit, p_fit, peak_positionE, error)
def fit_model(function, energy_fit, eqe_fit, p0=None, include_disorder=False ): """ Function to perform curve fit using lmfit This function is used for standard / disorder single peak fits. :param function: function to fit against (i.e. gaussian, gaussian_disorder etc.) :param energy_fit: energy values to fit against [list or array] :param eqe_fit: EQE values to fit against [list or array] :param p0: list of initial guesses for curve_fit function [list] :param include_disorder: boolean value :return: best_vals: list of best fit parameters [list] covar: covariance matrix of fit y_fit: calculated EQE values of the fit [list] r_squared: R^2 of the fit [float] """ if p0 is None: # if no guess is given, initialize with all ones. This is consistent with curve_fit. if include_disorder: p0 = [1, 1, 1, 1] else: p0 = [1, 1, 1] gmodel = Model(function) gmodel.set_param_hint('Ect', min=0, max=1.6) gmodel.set_param_hint('l', min=0, max=0.6) # changed from 0.4 gmodel.set_param_hint('f', min=0, max=0.1) # changed from 0.4 if include_disorder: gmodel.set_param_hint('sig', min=0, max=0.2) result = gmodel.fit(eqe_fit, f=p0[0], l=p0[1], Ect=p0[2], sig=p0[3], E=energy_fit ) f = float(result.params['f'].value) l = float(result.params['l'].value) Ect = float(result.params['Ect'].value) sig = float(result.params['sig'].value) best_vals = [f, l, Ect, sig] covar = result.covar if covar is None: covar = np.zeros((4, 4)) y_fit = gmodel.eval(E=np.array(energy_fit), f=f, l=l, Ect=Ect, sig=sig ) else: result = gmodel.fit(eqe_fit, f=p0[0], l=p0[1], Ect=p0[2], E=energy_fit ) f = float(result.params['f'].value) l = float(result.params['l'].value) Ect = float(result.params['Ect'].value) best_vals = [f, l, Ect] covar = result.covar if covar is None: covar = np.zeros((4, 4)) y_fit = gmodel.eval(E=np.array(energy_fit), f=f, l=l, Ect=Ect ) r_squared = R_squared(eqe_fit, y_fit) return best_vals, covar, y_fit, r_squared
def slit_fit(nu, spec, init_params=None, lineshape='sGaussian', power_factor=1., eval_only=False, save_fit=False, dir_save=None, file_name=None, **kwargs): r"""fitting the experimental slit function with a chosen lineshape .. attention:: It is recommended to always look for initial parameters by using the `eval_only` option to roughly match the shape of the experimental slit function. The built-in initial parameters may not work for all the cases. Parameters ---------- nu : 1d array of floats Spectral positions in [:math:`\mathrm{cm}^{-1}`]. spec : 1d array of floats Experimentally obtained slit function, usually an isolated atomic line from a calibration lamp. init_params : dict, optional Initial fitting parameters for the lineshape. Refer to :mod:`carspy.convol_fcn.asym_Voigt` and :mod:`carspy.convol_fcn.asym_Gaussian` for the required arguments. lineshape : str, optional Type of the lineshape, by default 'sGaussian'. Choose between 'sGaussian' and 'sVoigt'. eval_only : bool, optional If true, returns the evaluation with given initial parameters. save_fit : bool, optional If true, fit results will be saved in a pickle file. dir_save : str, optional If `save_fit` is true, a string to the desired directory for saving. file_name : str, optional If `save_fit` is true, specify the file name without file extension. Other Parameters ---------------- **kwargs: Keyword arguments of the `Model.fit()` method from the module `lmfit`. Returns ------- 1d array If `eval_only` is true, the evaluation result is returned. """ if lineshape == 'sGaussian': slit_func = partial(asym_Gaussian, power_factor=power_factor) elif lineshape == 'sVoigt': slit_func = partial(asym_Voigt, power_factor=power_factor) else: raise ValueError("Please choose between 'sGaussian' and 'sVoigt'") slit_func.__name__ = 'slit_func' fit_model = Model( slit_func, independent_vars='w', ) if init_params is None: init_params = (('w0', 0, True), ('sigma', 2, True, 0.01, 10), ('k', 2, True, 0, 10), ('a_sigma', -0.8, True, -5, 5), ('a_k', 1, True, -5, 5), ('sigma_L_l', 0.1, True, 0.01, 5), ('sigma_L_h', 0.1, True, 0.01, 5), ('offset', 0, True, 0, 1)) params = fit_model.make_params() params.add_many(*init_params) if eval_only: return fit_model.eval(params, w=nu) else: fit_result = fit_model.fit((spec / spec.max())**power_factor, params, w=nu, **kwargs) report_fit(fit_result, show_correl=True, modelpars=params) fit_result.plot() if save_fit and dir_save and file_name: path_write = Path(dir_save) / (file_name + '.pkl') pkl_dump(path_write, fit_result)
def use_lmfit(x_values, y_values, functionlist, title,i, max_y_values): """ Use lmfit. IN : x- and y-values. functionlist (which functions to use) adapted from https://stackoverflow.com/a/49843706/4173718 TODO: Make all graphs in one graph """ a_start, b_start, c_start = 0,0,0 for function in functionlist: #placeholder0.subheader(f"LMFIT - {title} - {function}") # create a Model from the model function if function == "exponential": bmodel = Model(exponential) formula = "a * np.exp(-b * np.exp(-c * x))" elif function == "derivate": bmodel = Model(derivate) formula = "a * b * c * np.exp(b * (-1 * np.exp(-c * x)) - c * x)" elif function == "gaussian": bmodel = Model(gaussian_2) formula = "a * np.exp(-((x - b) ** 2) / c)" else: st.write("Please choose a function") st.stop() # create Parameters, giving initial values #params = bmodel.make_params(a=4711, b=12, c=0.06) params = bmodel.make_params(a=a_start, b=b_start, c=c_start) # IC BEDDEN MAART APRIL # params = bmodel.make_params() params["a"].min = a_start params["b"].min = b_start params["c"].min = c_start # do fit, st.write result result = bmodel.fit(y_values, params, x=x_values) a = round(result.params['a'].value,5) b= round(result.params['b'].value,5) c =round(result.params['c'].value,5) placeholder1.text(result.fit_report()) with _lock: #fig1y = plt.figure() fig1y, ax1 = plt.subplots() ax2 = ax1.twinx() # plot results -- note that `best_fit` is already available ax1.scatter(x_values, y_values, color="#00b3b3", s=2) #ax1.plot(x_values, result.best_fit, "g") res = (f"a: {a} / b: {b} / c: {c}") plt.title(f"{title} / lmfit - {function}\n{formula}\n{res}") t = np.linspace(0.0, TOTAL_DAYS_IN_GRAPH, 10000) # use `result.eval()` to evaluate model given params and x ax1.plot(t, bmodel.eval(result.params, x=t), "r-") ax2.plot (t, derivate_of_derivate(t,a,b,c), color = 'purple') ax2.axhline(linewidth=1, color='purple', alpha=0.5, linestyle="--") #ax1.plot (t, derivate(t,26660.1, 9.01298, 0.032198), color = 'purple') #ax2.plot (t, derivate_of_derivate(t,26660.1, 9.01298, 0.032198), color = 'yellow') #plt.ylim(bottom=0) #ax1.ylim(0, max_y_values*1.1) #ax1.set_ylim(510,1200) #ax2.set_ylim(0,12) ax1.set_xlabel(f"Days from {from_}") ax1.set_ylabel(f"{title} - red") ax2.set_ylabel("delta - purple") #plt.show() filename= (f"{OUTPUT_DIR}lmfit_{title}_{function}_{i}") plt.savefig(filename, dpi=100, bbox_inches="tight") placeholder.pyplot(fig1y) if prepare_for_animation == False: with _lock: fig1z = plt.figure() # plot results -- note that `best_fit` is already available if function == "exponential": plt.plot(t, derivate(t,a,b,c)) function_x = "derivate" formula_x = "a * b * c * np.exp(b * (-1 * np.exp(-c * x)) - c * x)" elif function == "derivate": plt.plot(t, exponential(t, a,b,c)) function_x = "exponential" formula_x = "a * np.exp(-b * np.exp(-c * x))" else: st.error("ERROR") st.stop() plt.title(f"{title} / {function_x}\n{formula_x}\n{res}") t = np.linspace(0.0, TOTAL_DAYS_IN_GRAPH, 10000) # use `result.eval()` to evaluate model given params and x #plt.plot(t, bmodel.eval(result.params, x=t), "r-") plt.ylim(bottom=0) plt.xlabel(f"Days from {from_}") plt.ylabel(title) #plt.show() #filename= (f"{OUTPUT_DIR}lmfit_{title}_{function}_{i}") #plt.savefig(filename, dpi=100, bbox_inches="tight") st.pyplot(fig1z) return filename
def fine_s21_model(freqs_fine, fit_params): #use this after fitting the data to get a prettier model totalmodel = Model(resonator_cable) params = totalmodel.make_params(**fit_params) fine_model = totalmodel.eval(params, f=freqs_fine) return fine_model
class XRFAllElementModel(): def __init__(self, exptdesc, linedict, xrffunc, comptonfunc, elasticfunc, *args, **kwargs): """ An XRF spectrum model LMFIT offers a range of options for coupling parameters and models but in order to be able to do this it needs to manipulate parameters - in particular string expressions and this leads big slowdowns if you've a large number of models or coupled parameters. To speed up the calculation rather than create the XRF spectrum from a sum of Gaussian Models we create a single model with many parameters. The basic lmfit model works as follows: parse the arguments of the input function. Build a list of param names from these arguments Apply paramhints to these param_names or make parameters from the param names This class will pass a basic line """ self.linedict = linedict self.exptdesc = exptdesc # # xrf line model self.xrfmodel = Model(xrffunc, prefix="xrf_", independent_vars=['x', 'area', 'center']) self.set_param_hints_from_dict(self.xrfmodel, "element", xrffunc.__name__) self.xrfparams = self.xrfmodel.make_params() #self.xrfparams.pretty_print() # elastic model self.elasticmodel = Model(elasticfunc, prefix="elastic_", independent_vars=['x', 'area', 'center']) self.set_param_hints_from_dict(self.elasticmodel, "elastic", elasticfunc.__name__) self.elasticparams = self.elasticmodel.make_params() # compton model self.comptonmodel = Model(comptonfunc, prefix="compton_", independent_vars=['x', 'area', 'center']) self.set_param_hints_from_dict(self.comptonmodel, "compton", comptonfunc.__name__) self.comptonparams = self.comptonmodel.make_params() def set_param_hints_from_dict(self, model, linetype, linefuncname): avail_hints = self.exptdesc["lineshape"][linetype][linefuncname].keys() for key in avail_hints: if key in model._param_root_names: model.set_param_hint(key,expr=None,**self.exptdesc["lineshape"]\ [linetype][linefuncname][key]) def make_params(self): # A composite of the parameters.. self.funcparams_all = Parameters() self.funcparams_all.update(self.xrfparams) self.funcparams_all.update(self.comptonparams) self.funcparams_all.update(self.elasticparams) # exclude pileups from the parameters for key in self.linedict: if not '+' in key: if "Elastic" in key: self.funcparams_all.add(key, **self.exptdesc["lineshape"]["elastic"]\ [self.elasticmodel.func.__name__]["area"]) elif "Compton" in key: self.funcparams_all.add(key, **self.exptdesc["lineshape"]["compton"]\ [self.comptonmodel.func.__name__]["area"]) else: self.funcparams_all.add(key, **self.exptdesc["lineshape"]["element"]\ [self.xrfmodel.func.__name__]["area"]) # self.funcparams_all.add("pileup_factor",value=0.05,min=1.0e-5, # max=2.,vary=True) return self.funcparams_all def compositefunc(self, params, **kwargs): xrf_sigma_keys = [s for s in self.xrfparams if 'sigma' in s] elastic_sigma_keys = [s for s in self.elasticparams if 'sigma' in s] compton_sigma_keys = [s for s in self.comptonparams if 'sigma' in s] # # common parameters # pileup_factor , fano # # pileup_factor = params["pileup_factor"].value first = True x = kwargs.get('x', None) result = np.zeros(len(x)) # # Do the basic lines XRF and Escape first... # for key, linegroup in self.linedict.iteritems(): if key in params: for line in linegroup: area = params[key].value * line.intensity center = line.line_energy # update funcparams if isinstance(line, (XrayLine, EscapeLine)): # for ii in xrf_sigma_keys: # params[ii].value = np.sqrt(params[ii].value**2 + \ # (line.line_energy*0.0001)) lineresult =\ self.xrfmodel.eval(params=params,area = area, center = center,**kwargs) if isinstance(line, (ElasticLine)): # for ii in elastic_sigma_keys: # params[ii].value = np.sqrt(params[ii].value**2 + \ # (line.line_energy*0.0001)) lineresult=\ self.elasticmodel.eval(params=params,area = area, center = center,**kwargs) if isinstance(line, (ComptonLine)): # for ii in compton_sigma_keys: # params[ii].value = np.sqrt(params[ii].value**2 + \ # (line.line_energy*0.0001)) lineresult=\ self.comptonmodel.eval(params=params,area = area, center = center,**kwargs) if first: result = lineresult first = False else: result += lineresult # # generate the pileup lines... # you can convolute the whole line with itself to get the pileup # (basic code is a variation on what's done in pymca..) # # # The problem is largely in the intensity scaling. For a simple # 2-event summation you can just scale it by some factor # but for 3 event pileup the magnitude over the curve # grows rather than diminishes. # # result = result + pileup_factor*self.selfconvolute(result,**kwargs) return result def eval(self, params=None, **kwargs): result = self.compositefunc(params=params, **kwargs) return result def selfconvolute(self, spectra, **kwargs): x = kwargs.get('x', None) start_index = int(x[0] / 0.01) pileup_window = np.zeros(3 * len(spectra)) result = np.zeros(len(spectra)) window = spectra spectrum = copy(spectra) for i in range(2): pileup = np.convolve(spectrum, window) pileup = pileup / (window.sum()) pileup_window[start_index:len(pileup) + start_index] += pileup[:] spectrum = copy(pileup_window[0:len(spectra)]) result = result + spectrum return result def residuals(self, params, *args, **kwargs): # Do this to include errors as weights. weights = kwargs.get('weights', None) data = kwargs.get('data', None) x = kwargs.get('x', None) model = self.compositefunc(params, x=x) resids = model - data return resids / weights def fit(self, params, *args, **kwargs): return minimize(self.residuals, params, *args, **kwargs)
cellModelV.set_param_hint('I0', min=0) #fitResult = cellModel.fit(ii, V=vv) #resultParams = fitResult.params #print(fitResult.fit_report()) #print(fitResult.message) fitResult = cellModelV.fit(vv, I=ii, method='nelder') resultParams = fitResult.params print(fitResult.fit_report()) print(fitResult.message) exit(code=0) #resultParams['Rsh'].value = resultParams['Rsh'].value + 1000 #resultParams['Iph'].value = resultParams['Iph'].value - 0.09e-3 #resultParams['n'].value = resultParams['n'].value + 0.2 fig, ax = plt.subplots() fitVals = cellModel.eval(params=resultParams, V=vv) ax.plot(vv, fitVals, label='Fit') ax.plot(vv, ii, '.', label='Data') ax.legend() fig.tight_layout() print("SSE={:}".format(SSE(fitVals, ii))) plt.show() #cellModelInv = Model(cellEqnV) #print(f.name)
#fitResult = cellModel.fit(ii, V=vv) #resultParams = fitResult.params #print(fitResult.fit_report()) #print(fitResult.message) fitResult = cellModelV.fit(vv, I=ii,method='nelder') resultParams = fitResult.params print(fitResult.fit_report()) print(fitResult.message) exit(code=0) #resultParams['Rsh'].value = resultParams['Rsh'].value + 1000 #resultParams['Iph'].value = resultParams['Iph'].value - 0.09e-3 #resultParams['n'].value = resultParams['n'].value + 0.2 fig, ax = plt.subplots() fitVals = cellModel.eval(params=resultParams,V=vv) ax.plot(vv,fitVals,label='Fit') ax.plot(vv,ii,'.',label='Data') ax.legend() fig.tight_layout() print("SSE={:}".format(SSE(fitVals,ii))) plt.show() #cellModelInv = Model(cellEqnV) #print(f.name)
def AdvancedBraggEdgeFitting( myspectrum, myrange, myTOF, est_pos, est_sigma, est_alpha, bool_print, bool_average, bool_linear, bool_transmission ): ## my range should be now the index position of the spectra that I want to study, est_pos is also the index position where the expected peak is #get the part of the spectrum that I want to fit mybragg = myspectrum[myrange[0]:myrange[1]] if (bool_average): mybragg = running_mean(mybragg, 3) t = myTOF[myrange[0]:myrange[1]] est_pos = est_pos - myrange[ 0] # I move the estimated position relative to the studied range, this is an index t0_f = myTOF[ est_pos + myrange[0]] # this is the actual estimated first position in TOF [s] plt.figure() plt.plot(t, mybragg) plt.plot(t0_f, mybragg[est_pos], 'x', markeredgewidth=3, c='orange') plt.title('Bragg edge') plt.xlabel('Wavelenght [Å]') plt.ylabel('Tranmission I/I$_{0}$') # plt.savefig('step1_fitting.pdf') t_before = t[0:est_pos] bragg_before = mybragg[0:est_pos] # t_after= t[est_pos+int(est_pos*0.2):-1] # bragg_after=mybragg[est_pos+int(est_pos*0.2):-1] t_after = t[est_pos + int(est_pos * 0.2):-1] bragg_after = mybragg[est_pos + int(est_pos * 0.2):-1] #first step: estimate the linear or exponential function before and after the Bragg Edge if (bool_linear): [slope_before, interception_before] = np.polyfit(t_before, bragg_before, 1) [slope_after, interception_after] = np.polyfit(t_after, bragg_after, 1) #first guess of paramters a2_f = slope_after a5_f = interception_before a6_f = slope_before a1_f = interception_after plt.figure() plt.plot(t_before, bragg_before, '.g') plt.plot(t_after, bragg_after, '.r') plt.plot(t, mybragg) plt.plot(t, interception_before + slope_before * t, 'g') plt.plot(t, interception_after + slope_after * t, 'r') plt.title('linear fitting before and after the given edge position') gmodel = Model(BraggEdgeLinear) else: [slope_before, interception_before] = np.polyfit(t_before, bragg_before, 1) [slope_after, interception_after] = np.polyfit(t_after, bragg_after, 1) #first guess of paramters a2_f = slope_after a5_f = interception_before a6_f = slope_before a1_f = interception_after exp_model_after = Model(exp_after) params = exp_model_after.make_params(a1=a1_f, a2=a2_f) result_exp_model_after = exp_model_after.fit(bragg_after, params, t=t_after) a1_f = result_exp_model_after.best_values.get('a1') a2_f = result_exp_model_after.best_values.get('a2') exp_model_before = Model(exp_combined) params = exp_model_before.make_params(a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f) params['a1'].vary = False params['a2'].vary = False result_exp_model_before = exp_model_before.fit(bragg_before, params, t=t_before) a5_f = result_exp_model_before.best_values.get('a5') a6_f = result_exp_model_before.best_values.get('a6') gmodel = Model(BraggEdgeExponential) plt.figure() plt.plot(t_before, bragg_before, '.r', label='int point') plt.plot(t_after, bragg_after, '.g', label='int point') plt.plot(t, mybragg) plt.plot(t, interception_before + slope_before * t, '--r', label='firred line before') plt.plot(t, interception_after + slope_after * t, '--g', label='fitted line after') plt.plot(t, exp_after(t, a1_f, a2_f), 'g', label='fitted exp before') plt.plot(t, exp_combined(t, a1_f, a2_f, a5_f, a6_f), 'r', label='fitted exp after') plt.xlabel('Wavelenght [Å]') plt.ylabel('Transmission I/I$_{0}$') plt.title('fitting before and after the given edge position') plt.legend() # plt.savefig('step2_fitting_legend.pdf') # plt.plot(t, BraggEdgeExponential(t,t0_f,est_alpha,est_sigma,a1_f,a2_f,a5_f,a6_f)) sigma_f = est_sigma alpha_f = est_alpha # method='trust_exact' # method='nelder' #not bad # method='differential_evolution' # needs bounds # method='basinhopping' # not bad # method='lmsquare' # this should implement the Levemberq-Marquardt but it says Nelder-Mead method (which should be Amoeba) method = 'least_squares' # default and it implements the Levenberg-Marquardt params = gmodel.make_params(t0=t0_f, sigma=sigma_f, alpha=alpha_f, a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f, bool_trasmission=bool_transmission) print(bool_transmission) first_guess = gmodel.eval(params, t=t) plt.figure() plt.plot(t, mybragg, label='data') plt.plot(t, first_guess, '--b', label='initial model') plt.title('initial BE with given parameters') plt.xlabel('Wavelenght [Å]') plt.ylabel('Transmission I/I$_{0}$') plt.legend() # plt.savefig('step3_fitting_legend.pdf') params['alpha'].vary = False params['sigma'].vary = False params['t0'].vary = False params['a2'].vary = False params['a5'].vary = False params['bool_transmission'].vary = False result1 = gmodel.fit(mybragg, params, t=t, method=method, nan_policy='propagate') # print(result1.fit_report()) a1_f = result1.best_values.get('a1') a6_f = result1.best_values.get('a6') params = gmodel.make_params(t0=t0_f, sigma=sigma_f, alpha=alpha_f, a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f, bool_trasmission=bool_transmission) params['alpha'].vary = False params['sigma'].vary = False params['t0'].vary = False params['a1'].vary = False params['a6'].vary = False params['bool_transmission'].vary = False result2 = gmodel.fit(mybragg, params, t=t, method=method, nan_policy='propagate') a2_f = result2.best_values.get('a2') a5_f = result2.best_values.get('a5') params = gmodel.make_params(t0=t0_f, sigma=sigma_f, alpha=alpha_f, a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f, bool_trasmission=bool_transmission) params['a2'].vary = False params['a5'].vary = False params['a1'].vary = False params['a6'].vary = False params['sigma'].vary = False params['alpha'].vary = False params['bool_transmission'].vary = False params['t0'].min = myTOF[myrange[0]] params['t0'].max = myTOF[myrange[1]] result3 = gmodel.fit(mybragg, params, t=t, method=method, nan_policy='propagate') t0_f = result3.best_values.get('t0') params = gmodel.make_params(t0=t0_f, sigma=sigma_f, alpha=alpha_f, a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f, bool_trasmission=bool_transmission) params['a2'].vary = False params['a5'].vary = False params['a1'].vary = False params['a6'].vary = False params['bool_transmission'].vary = False params['t0'].min = myTOF[myrange[0]] params['t0'].max = myTOF[myrange[1]] params['alpha'].min = 0.0 params['alpha'].max = 1.5 params['sigma'].min = 0.0 params['sigma'].max = 1.5 result4 = gmodel.fit(mybragg, params, t=t, nan_policy='propagate', method=method) sigma_f = result4.best_values.get('sigma') alpha_f = result4.best_values.get('alpha') t0_f = result4.best_values.get('t0') params = gmodel.make_params(t0=t0_f, sigma=sigma_f, alpha=alpha_f, a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f, bool_trasmission=bool_transmission) params['t0'].vary = False params['sigma'].vary = False params['alpha'].vary = False params['bool_transmission'].vary = False result5 = gmodel.fit(mybragg, params, t=t, nan_policy='propagate', method=method) a1_f = result5.best_values.get('a1') a2_f = result5.best_values.get('a2') a5_f = result5.best_values.get('a5') a6_f = result5.best_values.get('a6') params = gmodel.make_params(t0=t0_f, sigma=sigma_f, alpha=alpha_f, a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f, bool_trasmission=bool_transmission) params['a2'].vary = False params['a5'].vary = False params['a1'].vary = False params['a6'].vary = False params['bool_transmission'].vary = False params['t0'].min = myTOF[myrange[0]] params['t0'].max = myTOF[myrange[1]] params['alpha'].min = 0.0 params['alpha'].max = 1.5 params['sigma'].min = 0.0 params['sigma'].max = 1.5 result6 = gmodel.fit(mybragg, params, t=t, nan_policy='propagate', method=method) t0_f = result6.best_values.get('t0') sigma_f = result6.best_values.get('sigma') alpha_f = result6.best_values.get('alpha') params = gmodel.make_params(t0=t0_f, sigma=sigma_f, alpha=alpha_f, a1=a1_f, a2=a2_f, a5=a5_f, a6=a6_f) params['bool_transmission'].vary = False params['t0'].min = myTOF[myrange[0]] params['t0'].max = myTOF[myrange[1]] params['alpha'].min = 0.0 params['alpha'].max = 1.5 params['sigma'].min = 0.0 params['sigma'].max = 1.5 result7 = gmodel.fit(mybragg, params, t=t, nan_policy='propagate', method=method) # print(params) print(result7.fit_report()) print(result7.covar) print('bool value, Boolean for whether error bars were estimated by fit.', result7.errorbars) print(result7.ci_out) # print out the interval confidence # print(result7.conf_interval()) # print(result7.ci_report()) # this crashes sometimes when the MinimizerException: Cannot determine Confidence Intervals without sensible uncertainty estimates t0_f = result7.best_values.get('t0') sigma_f = result7.best_values.get('sigma') alpha_f = result7.best_values.get('alpha') a1_f = result7.best_values.get('a1') a2_f = result7.best_values.get('a2') a5_f = result7.best_values.get('a5') a6_f = result7.best_values.get('a6') # Get the extrema for edge height fitting fitted_data = result7.best_fit pos_extrema = [] ## Attempt n.1 -------- Here I was searching the last 0 value and the first value with 1.0 in the step function, however is it not a robust solution # step_function = B(t,t0_f,alpha_f,sigma_f) # min_pos = find_last(step_function,0.0) # pos_extrema.append(min_pos) # max_pos = find_first(step_function,0.99) # pos_extrema.append(max_pos) if (bool_linear): fit_before = line_before(t, a5_f, a6_f) fit_after = line_after(t, a1_f, a2_f) else: fit_before = exp_combined(t, a1_f, a2_f, a5_f, a6_f) fit_after = exp_after(t, a1_f, a2_f) fit_edge = B(t, t0_f, alpha_f, sigma_f, bool_transmission) plt.figure() plt.plot(t, fit_before, 'o-') plt.plot(t, fit_after, 'o-') plt.plot(t, fitted_data, '.-') index_t0 = find_nearest(t, t0_f) # Attempt n.2 ------This is Florencia's approach: this gives an overestimation in most cases of the edge height # pos_extrema.append(fit_before[index_t0]) # pos_extrema.append(fit_after[index_t0]) # Attempt n.3 ------ This approach is based on the difference between the fit before and after the edge and the fitted data itself. so far, it gives the nicest results on the calibration sample, however the value used as threshold is not general and should probably be adjusted from case to case. So again it is not yet the final solution for i in range(0, len(fitted_data)): # print(i,(fitted_data[i]-fit_before[i])) if (np.abs(fitted_data[i] - fit_before[i]) > 1e-4): pos_extrema.append(i - 1) break for i in range(len(fitted_data) - 1, 0, -1): # here I am moving backwards # print(i,(fitted_data[i]-fit_after[i])) if (np.abs(fitted_data[i] - fit_after[i]) > 1e-3): pos_extrema.append(i) break # # Attempt n.4 -- max and min before and after the estimated edge position, for the calibration sample works fine # range_min = t[0:index_t0] # range_max= t[index_t0:-1] # min_fit = np.min(fitted_data[0:index_t0]) # max_fit = np.max(fitted_data[index_t0:-1]) # pos_min = find_nearest(fitted_data[0:index_t0], min_fit) # pos_max = index_t0+find_nearest(fitted_data[index_t0:-1], max_fit) ## For other attempts have a look in the SENJU branch height = np.abs(mybragg[pos_extrema[0]] - mybragg[pos_extrema[1]]) plt.figure() plt.plot(t, mybragg) # plt.plot(t, result7.init_fit, 'k--') plt.plot(t, result1.best_fit, '--', color='gray', label='intermediate steps') plt.plot(t, result1.init_fit, '--', color='gray') plt.plot(t, result2.best_fit, '--', color='gray') plt.plot(t, result3.best_fit, '--', color='gray') plt.plot(t, result4.best_fit, '--', color='gray') plt.plot(t, result5.best_fit, '--', color='gray') plt.plot(t, result6.best_fit, '--', color='gray') plt.plot(t, result7.best_fit, 'r', linewidth='1.5', label='final fit') plt.legend() plt.xlabel('Wavelenght [Å]') plt.ylabel('Transmission I/I$_{0}$') plt.plot(t0_f, result7.best_fit[index_t0], 'ok') plt.plot(t[pos_extrema[0]], result7.best_fit[pos_extrema[0]], 'ok') plt.plot(t[pos_extrema[1]], result7.best_fit[pos_extrema[1]], 'ok') plt.title('edge fitting and estimated edge position') plt.show() if (bool_print): print('first iteration: ', result1.fit_report()) print('second iteration: ', result2.fit_report()) print('third iteration: ', result3.fit_report()) print('fourth iteration: ', result4.fit_report()) print('fifth iteration: ', result5.fit_report()) print('sixth iteration: ', result6.fit_report()) return { 't0': t0_f, 'sigma': sigma_f, 'alpha': alpha_f, 'a1': a1_f, 'a2': a2_f, 'a5': a5_f, 'a6': a6_f, 'final_result': result7, 'fitted_data': fitted_data, 'pos_extrema': pos_extrema, 'height': height }
def echo_fits(): """ Fits a Gaussian with a linear background to each of the echo peaks, finds the centroid and top of the Gaussian, then fits the echo_as_T2 function to the points given by x=centroid, y=top. """ xrs, yrs, xr, yr, filename, dat1 = range_to_list() cents: List[float] = [] cents_uncert: List[float] = [] heights: List[float] = [] heights_uncert: List[float] = [] for i in range(0, len(xrs)): mdl = GaussianModel(prefix='G_') lne = LinearModel(prefix='L_') params = mdl.guess(yrs[i], x=xrs[i]) params += lne.guess(yrs[i], x=xrs[i]) max_y = np.max(yrs[i]) min_y = np.min(yrs[i]) max_x = np.max(yrs[i]) min_x = np.min(yrs[i]) predicted_slope = (max_y - min_y) / (max_x - min_x) params.add('L_slope', value=predicted_slope, min=predicted_slope * 1.1, max=predicted_slope * 0.9) params.add('L_intercept', value=min_y, min=min_y * 0.9, max=min_y * 1.1) params.add('G_height', value=max_y - min_y, min=(max_y - min_y) * 0.99, max=(max_y - min_y) * 1.05) model = mdl + lne result = model.fit(yrs[i], params, x=xrs[i], method='leastsq') cent: float = result.params['G_center'].value amp: float = result.params['G_height'].value inter: float = result.params['L_intercept'].value grad: float = result.params['L_slope'].value height: float = amp + ((cent * grad) + inter) heights.append(height) cents.append(cent) cents_uncert.append(result.params['G_center'].stderr) partial_amp = 1 partial_grad = cent partial_x = grad partial_inter = 1 amp_term = partial_amp * result.params['G_height'].stderr grad_term = partial_grad * result.params['L_slope'].stderr x_term = partial_x * np.mean(np.diff(xrs[i])) inter_term = partial_inter * result.params['L_intercept'].stderr height_uncert = np.sqrt(amp_term**2 + grad_term**2 + x_term**2 + inter_term**2) heights_uncert.append(height_uncert) heights = np.array(heights) cents = np.array(cents) maxy = np.max(heights) miny = np.min(heights) decay_pos = np.where(heights == find_nearest(heights, maxy / e))[0][0] decay_pos_time = cents[decay_pos] avg_y_sep = abs(np.mean(np.diff(heights))) efit = Model(echo_as_T2) param = efit.make_params() param.add('M0', value=maxy, min=maxy * 0.8, max=maxy + (avg_y_sep * 2)) param.add('T2', value=decay_pos_time, min=decay_pos_time * 0.1, max=decay_pos_time * 1.5) param.add('c', value=miny * 0.3, min=miny * 0.1, max=miny * 1) param.add('ph', value=cents[0] * 0.1, min=0, max=cents[0] * 1) result_2 = efit.fit( heights, param, t=cents, method='leastsq', weights=np.sqrt( np.mean(np.diff(dat1['m']))**2 + np.array(heights_uncert)**2) / heights) print(result_2.fit_report()) print('\n', result_2.params.pretty_print(fmt='e', precision=2)) ax = plt.gca() ax.set_xlabel('Time (s)', fontsize=14) ax.set_ylabel('Magnetization (A/m)', fontsize=14) xes = np.linspace(np.min(cents), np.max(cents), 100) y = efit.eval(t=xes, params=result_2.params) plt.plot(xes, y, antialiased=True) plt.plot(cents, heights, 'x', ms=8, color='k') plt.plot(dat1['t'], dat1['m'], lw=2, antialiased=True, color='#4a4a4a', zorder=1) plt.title(filename) plt.xlim(left=0, right=np.max(cents) * 1.1) plt.ylim(bottom=0, top=result_2.params['M0'].value * 1.3) plt.axhline(result_2.params['M0'].value, color='k', ls='--', alpha=0.7, lw=1, zorder=2) plt.axhline(result_2.params['M0'].value / e, color='k', ls='--', alpha=0.7, lw=1, zorder=2) plt.text(0.9, 0.9, "T_1: {:.4f} s".format(result_2.params['T2'].value), horizontalalignment='center', verticalalignment="center", transform=ax.transAxes, bbox={ 'pad': 8, 'fc': 'w' }, fontsize=14) plt.tight_layout() plt.tick_params(axis='both', which='major', labelsize=13) fig_manager = plt.get_current_fig_manager() fig_manager.window.showMaximized() plt.show()
def galstep(r, mass, a): return (mass / (2 * np.pi)) * (a / (r * (r + a)**3)) gmodel = Model(gaussian) galmodel = Model(galstep) gauss_params = gmodel.make_params(cen=5, amp=200, wid=1) galstep_params = galmodel.make_params(mass=2.3e+10, a=1.5) x = np.linspace(0.1, 10, 201) #y_gauss = gmodel.eval(gauss_params, x=x) #y_galstep = galmodel.eval(galstep_params, r=x) y_gauss = gmodel.eval(x=x, cen=6.5, amp=100, wid=2.0) y_galstep = galmodel.eval(r=x, mass=3.0e+10, a=3.0) result_gauss = gmodel.fit(y_gauss, gauss_params, x=x) result_galstep = galmodel.fit(y_galstep, galstep_params, r=x) print(result_gauss.fit_report()) print(result_galstep.fit_report()) fig, axs = plt.subplots(1, 2) axs[0].plot(x, y_gauss, 'o') axs[0].plot(x, result_gauss.init_fit, 'k--', label='init fit') axs[0].plot(x, result_gauss.best_fit, 'r-', label='best fit') axs[0].legend() axs[1].plot(x, y_galstep, 'o')
def main(): ''' parser = argparse.ArgumentParser(prog='enamelsample', description='Resample image of enamel to standard grid', add_help=True) parser.add_argument('images', type=str, nargs='+', help='Images of enamel 1.') #parser.add_argument('images2', type=str, nargs='+', help='Images of enamel 2.') parser.add_argument('-sp', '--spacing', type=float, default=x_resampling, help='Marker spacing (in pixels).') parser.add_argument('-ex', '--exact', type=float, default=10., help='Exactness of baseline spline.') parser.add_argument('-l', '--order-by-length', action='store_true', help='Order teeth according to length.') parser.add_argument('-s', '--show', action='store_true', help='Show plot.') parser.add_argument('-o', '--output-dir', type=str, default='likelihood min model ', help='Directory in which to store output.') parser.add_argument('-f', '--output', type=str, default='likelihood_min_model.h5', help='Name of mineralization model file to be created.') parser.add_argument('-p', '--partitions', type=int, nargs=2, default=(1,1), help='Number of partitions, and partition to operate on.') if 'python' in sys.argv[0]: offset = 2 else: offset = 1 args = parser.parse_args(sys.argv[offset:]) warnings.simplefilter('ignore') # Load and standardize each tooth image alignedimg = [] Nx, Ny = [], [] age = [] for i,fname in enumerate(args.images): print 'Processing %s ...' % fname img = load_image(fname) # Extract age from filename age.append(float(fname[1:4])) # Generate a spline for each tooth edge x, spl = get_baseline(img, exactness=args.exact) # Place makers along the bottom edge markerPos, markerDeriv = place_markers(x, spl[1], spacing=args.spacing) # Calculate y values of edges y = [] for i in xrange(2): y.append(spl[i](x)) # Calculate perpendicular lines to edges # Height of line is # in markerPos + # DeltaMarker = -np.ones((len(markerDeriv), 2), dtype='f8') DeltaMarker[:,0] = markerDeriv[:] markerPos2 = markerPos + 80. * DeltaMarker # Goal: take our x positions, step along the y positions, and get the # values from the image. # Plot everything # Resample image to standard grid alignedimg.append(get_image_values_2(img, markerPos, DeltaMarker, fname)) ''' # My sheep model data from images, video model_days = np.array([30., 40., 50., 60., 70., 80., 90., 100., 110., 120., 130., 140., 150., 160., 170., 180., 190., 200., 210., 220., 230., 240., 250., 260., 270., 280., 290., 300.]) model_completion = np.array([2.3, 2.3, 2.76, 2.76, 4.6, 9.2, 11.96, 11.96, 13.8, 13.8, 15.64, 16.56, 16.56, 20.7, 20.7, 22.08, 23.46, 23.46, 23.46, 23.46, 23.46, 24.38, 24.84, 24.84, 27.6, 27.6, np.nan, 30.36]) model_initiation = np.array([14.72, 15.64, 16.56, 17.48, 18.4, 24.84, 26.68, 26.68, 28.52, 28.52, 29.44, 30.36, 30.36, 31.28, 31.28, 31.74, 33.12, 33.12, 33.12, 33.12, 33.12, 33.58, 34.04, 34.04, 34.96, 34.96, np.nan, 34.96]) model_min_length = model_initiation - model_completion model_length_percent = model_min_length / 39. model_increase_per_day = np.array([1.104, 0.552, 1.564, 1.932, 0.092, 0., 0.16866667, 0.16866667, 0.16866667, 0.16866667, 0.16866667, 0.16866667, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.10514286, 0.092, 0.15333333, 0.15333333, 0.15333333, 0.138, 0.138, 0.184, 0.276, 0.21466667, 0.21466667, 0.21466667, 0., 0.552, 0.70533333, 0.70533333, 0.70533333, 1.104, 0.598, 0.598, 0., 0.299, 0.299, 0.299, 0.299, 0.1472, 0.1472, 0.1472, 0.1472, 0.1472, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.092, 0.0736, 0.0736, 0.0736, 0.0736, 0.0736, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0.05952941, 0., 0.092, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.05366667, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.04293333, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.03942857, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0.0368, 0., 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.03504762, 0.046, 0.046, 0.0345, 0.0345, 0.0345, 0.0345, 0.0345, 0.0345, 0.0345, 0.0345, 0., 0.046, 0.046, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.036, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.04025, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.046, 0.0644, 0.0644, 0.0644, 0.0644, 0.0644, 0.0644, 0.0644, 0.0644, 0.0644, 0.0644]) for i in xrange(np.size(model_increase_per_day)): if model_increase_per_day[i] > 0.4: model_increase_per_day[i] = 0.40 model_pct_increase_per_day = model_increase_per_day / np.max(model_increase_per_day) # Kierdorf 2013 data kday = np.array([7.5, 21.5, 49.5, 63.3, 73., 154., 168., 185.5, 199., 212.5, 230., 247.5]) kext = np.array([177.6, 168.4, 180., 131.7, 109.9, 40.4, 35.5, 35.0, 33.2, 27.1, 28.0, 29.3]) tooth_days = np.array([1., 9., 11., 19., 21., 30., 31., 31., 38., 42., 54., 56., 56., 58., 61., 66., 68., 73., 78., 84., 88., 92., 97., 100., 101., 101., 104., 105., 124., 127., 140., 140., 157., 167., 173., 174., 179., 202., 222., 235., 238., 251., 259., 274.]) tooth_extension = np.array([9.38, 8.05, 11.32, 9.43, 13.34, 16.19, 13.85, 15.96, 15.32, 14.21, 17.99, 19.32, 19.32, 18.31, 17.53, 18.68, 18.49, 22.08, 23.14, 19.92, 27.97, 24.38, 25.53, 29.07, 27.65, 26.27, 27.55, 24.33, 29.03, 29.07, 30.36, 31.79, 31.37, 31.28, 35.79, 29.81, 31.79, 34.04, 33.21, 34.50, 33.76, 33.40, 36.34, 33.63]) tooth_35p = np.array([2.07, 1.52, 2.39, 2.67, 4.60, 7.04, 4.55, 5.47, 5.47, 4.83, 8.19, 9.98, 9.75, 9.89, 9.29, 10.40, 8.88, 12.88, 14.49, 11.96, 19.04, 17.48, 16.74, 20.61, 18.86, 17.34, 19.92, 14.67, 22.03, 22.91, 24.47, 26.08, 26.13, 25.94, 34.45, 25.35, 26.91, 30.08, 30.68, 33.49, 28.29, 28.34, 35.83, 33.63]) tooth_70p = np.array([np.nan, np.nan, np.nan, np.nan, np.nan, 2.76, np.nan, np.nan, np.nan, np.nan, 3.68, 4.60, 4.69, 5.11, 4.88, 5.75, 4.74, 7.36, 8.97, 5.15, 13.62, 12.33, 11.13, 14.54, 13.25, 10.81, 13.25, 8.69, 15.78, 17.16, 19.27, 20.56, 19.87, 21.48, 30.27, 20.01, 22.17, 24.56, 26.27, 28.11, 23.55, 23.83, 36.34, 29.49]) tooth_mat_length = tooth_extension - tooth_70p / np.percentile(tooth_extension, 95) tooth_70p_days = np.array([30., 54., 56., 56., 58., 61., 66., 68., 73., 78., 84., 88., 92., 97., 100., 101., 101., 104., 105., 124., 127., 140., 140., 157., 167., 173., 174., 179., 202., 222., 235., 238., 251., 259., 274.]) tooth_70p_b = np.array([2.76, 3.68, 4.60, 4.69, 5.11, 4.88, 5.75, 4.74, 7.36, 8.97, 5.15, 13.62, 12.33, 11.13, 14.54, 13.25, 10.81, 13.25, 8.69, 15.78, 17.16, 19.27, 20.56, 19.87, 21.48, 30.27, 20.01, 22.17, 24.56, 26.27, 28.11, 23.55, 23.83, 36.34, 29.49]) p0_var_ext = np.array([30.34, .006102, -10.54]) p0_var_p35 = np.array([23., .008, 13.]) p0_var_p70 = np.array([25., .006, 110.]) days = np.linspace(-50, 350, 401) ext_variables, ext_pcov = curve_fit(est_tooth_extension, tooth_days, tooth_extension, p0_var_ext) p35_variables, p35_pcov = curve_fit(est_tooth_extension, tooth_days, tooth_35p, p0_var_p35) p70_variables, p70_pcov = curve_fit(est_tooth_extension, tooth_70p_days, tooth_70p_b, p0_var_p70) p70_variables2, p70_pcov2 = leastsq(func=curve_residuals, x0=p70_variables, args=(p0_var_p70, tooth_70p_days, tooth_70p_b)) print ext_variables print p35_variables print p70_variables print p70_variables2 extension_erf = est_tooth_extension(days, ext_variables[0], ext_variables[1], ext_variables[2]) p35_erf = est_tooth_extension(days, p35_variables[0], p35_variables[1], p35_variables[2]) p70_erf = est_tooth_extension(days, p70_variables2[0], p70_variables2[1], p70_variables2[2]) diff_extension_erf = np.diff(extension_erf) * 1000 diff_p35_erf = np.diff(p35_erf) * 1000 diff_p70_erf = np.diff(p70_erf) * 1000 ext_zero = ext_variables[1] - ext_variables[2]*spec.erfinv((36. - ext_variables[0])/ext_variables[0]) p35_zero = p35_variables[1] - p35_variables[2]*spec.erfinv((36. - p35_variables[0])/p35_variables[0]) p70_zero = p70_variables2[1] - p70_variables2[2]*spec.erfinv((36. - p70_variables2[0])/p70_variables2[0]) print ext_zero, p35_zero, p70_zero gmod = Model(est_tooth_extension) print gmod.eval(x=tooth_70p_b, amplitude=25., slope=.006, offset=110.) fig = plt.figure() ax = fig.add_subplot(1, 1, 1) ax2 = ax.twinx() ax2.plot(days[1::4], diff_extension_erf[::4], 'b.', label=r'$ \mathrm{extension} \ \Delta $') ax2.plot(days[1::4], diff_p35_erf[::4], 'm.', label=r'$ \mathrm{maturation} \ \Delta $') ax2.plot(days[1::4], diff_p70_erf[::4], 'r.', label=r'$ \mathrm{completion} \ \Delta $') ax2.set_ylim([0,300]) ax2.set_xlim([-60,350]) ax.plot(tooth_days, tooth_extension, marker='o', linestyle='none', color='b', label=r'$ \mathrm{extension}$') ax.plot(tooth_days, tooth_35p, marker='o', linestyle='none', color='m', label=r'$ \mathrm{maturation}$') ax.plot(tooth_days, tooth_70p, marker='o', linestyle='none', color='r', label=r'$ \mathrm{completion}$') ax.plot(days, extension_erf, linestyle='-', color='b', label=r'$ \mathrm{extension,} \ \mathrm{optimized} $') ax.plot(days, p35_erf, linestyle='-', color='m', label=r'$ \mathrm{maturation,} \ \mathrm{optimized} $') ax.plot(days, p70_erf, linestyle='-', color='r', label=r'$ \mathrm{completion,} \ \mathrm{optimized} $') ax.set_ylim([0,40]) ax.set_xlim([-60,350]) plt.title('Enamel secretion and maturation progress over time') ax.set_xlabel('Days after birth') ax.set_ylabel('Progress from cusp tip in mm') ax2.set_ylabel('Secretion or maturation speed in um/day') ax2.legend(loc='lower right', fancybox=True, framealpha=0.8) ax.legend(loc='upper left', fancybox=True, framealpha=0.8) plt.show() ''' ax2 = ax.twinx() ax2.plot(xs, ys, color='g', label='radiograph extension, smooth') ax2.plot(days, increase_per_day, color='y', label='radiograph extension, raw') ax2.plot(kday, kext, color='k', mfc='none', marker='o', linestyle='none', label='histology extension') plt.show() ''' return 0
def ls_fit(self, add_params=None, path_fit=None, show_fit=False, eval_only=False, **kwargs): """ Fitting the experimental CARS spectrum. .. attention:: The least-quare fit module ``lmfit`` is necessary for this method. Please be aware that certain Python versions may not be supported by ``lmfit``. For displaying the fit results ``matplotlib`` will be needed as well. Parameters ---------- add_params : nested tuple, optional List of parameters controlling the fitting process. This option can be used to modify these initial parameters: .. code-block:: python (('temperature', 2000, True, 250, 3000), ('del_Tv', 0, False), ('x_mol', 0.6, x_mol_var, 0.2, 1.5), ('nu_shift', fit_params['nu_shift'], False), ('nu_stretch', fit_params['nu_stretch'], False), ('pump_lw', fit_params['pump_lw'], False), ('param1', fit_params['param1'], False), ('param2', fit_params['param2'], False), ('param3', fit_params['param3'], False), ('param4', fit_params['param4'], False), ('param5', fit_params['param5'], False), ('param6', fit_params['param6'], False)) Each element of the nested tuple has the following element in order: variable_name : str All the arguments of :mod:`carspy.cars_fit.CarsFit.cars_expt_synth` are admissible variables except for the independent variable `nu_expt`. initial_guess : float Initial guess or fixed value set for this variable. variable : bool Determine if the variable is fixed (False) or not (True) during the fit. lower_bound : float Lower boundary for the fitting variable. If not provided, negative infinity will be assumed. upper_bound : float Upper boundary for the fitting variable. If not provide, positive infinity will be assumed. For more details refer to the documentation of ``lmfit.Model``. path_fit : str Path to the `.pkl` file of fitting result created by :mod:`carspy.cars_fit.CarsFit.save_fit`. This allows importing the fitting result of an existing spectrum, such that the inferred values of certain parameters (such as those related to the spectrometer) could be re-used in the next fit. A standard use case for this would be the fitting result of a room-temperature spectrum. This is needed if the `fit` in `fit_mode` of :mod:`carspy.cars_fit.CarsFit` is set to `T_x`. show_fit : bool, optional If True, the fitting results will be reported and plotted. This is done via built-in functions in ``lmfit``. """ # general setup fit_model = Model(self.cars_expt_synth, independent_vars=['nu_expt']) initi_params = [] # different fitting modes if self.fit_mode['fit'] == 'T_x': if path_fit is None: raise ValueError("Please provide path to a .pkl file " "containing the fitting result of a spectrum") if self.fit_mode['chem_eq']: x_mol_var = False else: x_mol_var = True fit_params = pkl_load(path_fit).params initi_params = (('temperature', 2000, True, 250, 3000), ('del_Tv', 0, False), ('x_mol', 0.6, x_mol_var, 0.2, 1.5), ('nu_shift', fit_params['nu_shift'], False), ('nu_stretch', fit_params['nu_stretch'], False), ('pump_lw', fit_params['pump_lw'], False), ('param1', fit_params['param1'], False), ('param2', fit_params['param2'], False), ('param3', fit_params['param3'], False), ('param4', fit_params['param4'], False), ('param5', fit_params['param5'], False), ('param6', fit_params['param6'], False)) if self.fit_mode['fit'] == 'custom': if add_params is None: raise ValueError("Please specify fitting parameters first " "using add_params") params = fit_model.make_params() params.add_many(*initi_params) if add_params is not None: params.add_many(*add_params) if eval_only: return fit_model.eval(params, nu_expt=self.nu) else: self.fit_result = fit_model.fit(np.nan_to_num(self.spec_cars), params, nu_expt=self.nu, **kwargs) if show_fit: report_fit(self.fit_result, show_correl=True, modelpars=params) self.fit_result.plot()
phase = (bfield - popt["bfield_offset"]) * popt["radians_per_tesla"] if config.getboolean("BOTH_BRANCHES"): fig, (ax_p, ax_n) = plt.subplots(2, 1, sharex=True) plot( phase / (2 * np.pi), ic_n / 1e-6, ax=ax_n, xlabel="phase [2π]", ylabel="switching current [μA]", label="data", marker=".", ) if not args.dry_run: best_p, best_n = np.split(result.best_fit, 2) plot(phase / (2 * np.pi), best_n / 1e-6, ax=ax_n, label="fit") init_p, init_n = np.split(model.eval(bfield=bfield, params=params), 2) if args.plot_guess: plot(phase / (2 * np.pi), init_n / 1e-6, ax=ax_n, label="guess") else: fig, ax_p = plt.subplots() if not args.dry_run: best_p = result.best_fit init_p = model.eval(bfield=bfield, params=params) plot( phase / (2 * np.pi), ic_p / 1e-6, ax=ax_p, xlabel="phase [2π]", ylabel="switching current [μA]", label="data", marker=".",