def ws_correlation_orthoginal_distance_model(data, ref_ws_col='ref', site_ws_col='site', force_through_origin=False): """Calculate the slope and offset between two wind speed columns using orthoganal distance regression. https://docs.scipy.org/doc/scipy-0.18.1/reference/odr.html :Parameters: data: DataFrame DataFrame with wind speed columns ref and site, and direction data dir ref_ws_col: string, default None (primary anemometer assumed) Reference anemometer data to use. Extracted from MetMast.data site_ws_col: string, default None (primary anemometer assumed) Site anemometer data to use. Extracted from MetMast.data force_through_origin: boolean, default False Force the correlation through the origin (offset equal to zero) :Returns: out: DataFrame slope, offset, R2, uncert, points """ data = data.loc[:, [ref_ws_col, site_ws_col]].dropna().astype(np.float) results = return_correlation_results_frame(ref_label=ref_ws_col, site_label=site_ws_col) if not valid_ws_correlation_data(data=data, ref_ws_col=ref_ws_col, site_ws_col=site_ws_col): return results points = data.shape[0] R2 = calculate_R2(data=data, ref_ws_col=ref_ws_col, site_ws_col=site_ws_col) uncert = calculate_IEC_uncertainty(data=data, ref_ws_col=ref_ws_col, site_ws_col=site_ws_col) X = data.loc[:, ref_ws_col].values Y = data.loc[:, site_ws_col].values data_mean = data.mean() slope_estimate_via_ratio = data_mean[site_ws_col] / data_mean[ref_ws_col] realdata = odrpack.RealData(X, Y) if force_through_origin: linear = odrpack.Model(f_without_offset) odr = odrpack.ODR(realdata, linear, beta0=[slope_estimate_via_ratio]) slope = odr.run().beta[0] offset = 0 else: linear = odrpack.Model(f_with_offset) odr = odrpack.ODR(realdata, linear, beta0=[slope_estimate_via_ratio, 0.0]) slope, offset = odr.run().beta[0], odr.run().beta[1] results.loc[pd.IndexSlice[ref_ws_col, site_ws_col], ['slope', 'offset', 'R2', 'uncert', 'points']] = np.array( [slope, offset, R2, uncert, points]) return results
def bilinear_Q_regression(freqs_log, Q_list_log): freqs_log = array(freqs_log) #data = odrpack.RealData(x[12:], y[12:]) data = odrpack.RealData(freqs_log, Q_list_log) #x_range = arange(-0.5, 1.0, step=0.01) # x range bilin_reg = odrpack.Model(bilinear_reg_free) odr = odrpack.ODR(data, bilin_reg, beta0=[0.4, 3.0, 0.3, -0.5]) odr.set_job( fit_type=2) #if set fit_type=2, returns the same as least squares out = odr.run() #print('\nbilinear auto\n') #out.pprint() a = out.beta[0] b = out.beta[1] c = out.beta[2] hx = out.beta[3] # x hinge point log_q_fit = b + a * freqs_log # get y values from bilinear yhinge = b + a * hx idx = freqs_log > hx log_q_fit[idx] = c * (freqs_log[idx] - hx) + yhinge return log_q_fit
def bilinear_regression(x, y): data = odrpack.RealData(x[12:], y[12:]) x_range = np.arange(-0.5, 1.0, step=0.01) # x range bilin_reg = odrpack.Model(bilinear_reg_free) odr = odrpack.ODR(data, bilin_reg, beta0=[0.4, 3.0, 0.3, -0.5]) odr.set_job(fit_type=2) #if set fit_type=2, returns the same as least squares out = odr.run() print('\nbilinear auto\n') out.pprint() a = out.beta[0] b = out.beta[1] c = out.beta[2] hx = out.beta[3] # x hinge point y_range = b + a * x_range # get y values from bilinear yhinge = b + a * hx idx = x_range > hx y_range[idx] = c * (x_range[idx]-hx) + yhinge return y_range, x_range
def gaussian_lsq(x, y, verbose=False, itmax=200, iparams=[]): ''' Performs a gaussian least squares fit to the data, with errors! Uses scipy odrpack, but for least squares.''' def _gauss_fjd(B, x): # Analytical derivative of gaussian with respect to x return 2 * (x - B[0]) * gaussian(B, x) # these derivatives need to be fixed! def _gauss_fjb(B, x): # Analytical derivatives of gaussian with respect to parameters _ret = np.concatenate( (-2 * (x - B[0]) * gaussian(B, x), ((x - B[0])**2 / (2 * B[1]**2) - 1) / B[1] * gaussian(B, x), gaussian(B, x) / B[2], np.ones(x.shape, float))) _ret.shape = (4, ) + x.shape return _ret # Centre data in mean(x) (makes better conditioned matrix) mx = np.mean(x) x2 = x - mx if not any(iparams): # automatic guessing of gaussian's initial parameters (saves # iterations) iparams = np.array([ x2[np.argmax(y)], np.std(y), math.sqrt(2 * math.pi) * np.std(y) * np.max(y), 1. ]) gauss = odr.Model(gaussian, fjacd=_gauss_fjd, fjacb=_gauss_fjb) mydata = odr.Data(x2, y) myodr = odr.ODR(mydata, gauss, beta0=iparams, maxit=itmax) # Set type of fit to least-squares: myodr.set_job(fit_type=2) if verbose == 2: myodr.set_iprint(final=2) fit = myodr.run() # Display results: if verbose: fit.pprint() print('Re-centered Beta: [%f %f %f %f]' % (fit.beta[0] + mx, fit.beta[1], fit.beta[2], fit.beta[3])) itlim = False if fit.stopreason[0] == 'Iteration limit reached': itlim = True print("(WWW) gauss_lsq: Iteration limit reached, result not reliable!") # Results and errors coeff = fit.beta coeff[0] += mx # Recentre in original axis err = fit.sd_beta return coeff, err, itlim
def least(func, x, y, sy=None, beta0=None, ifixb=None): linear = odrpack.Model(func) #mydata = odrpack.Data(x, z[1], wd=1./np.power(z[2],2), we=1./np.power(sy,2)) mydata = odrpack.RealData(x, y, sy=sy) myodr = odrpack.ODR(mydata, linear, beta0=beta0, ifixb=ifixb) myodr.set_job(fit_type=2) myoutput = myodr.run() # myoutput.pprint() return myodr.output
def double_gauss_lsq(x, y, verbose=False, itmax=200, iparams=[]): ''' Performs a double gaussian least squares fit to the data, with errors! Uses scipy odrpack, but for least squares.''' def _dgauss_fjd(B, x): # Analytical derivative of gaussian with respect to x return (B[0] - x) / B[1]**2 * gaussian(np.concatenate((B[:3], [0.])), x) + \ (B[3] - x) / B[4]**2 * gaussian(np.concatenate((B[3:6], [0.])), x) def _dgauss_fjb(B, x): # Analytical derivatives of gaussian with respect to parameters gauss1 = gaussian(np.concatenate((B[:3], [0.])), x) gauss2 = gaussian(np.concatenate((B[3:6], [0.])), x) _ret = np.concatenate( ((x - B[0]) / B[1]**2 * gauss1, ((B[0] - x)**2 - B[1]**2) / B[1]**3 * gauss1, gauss1 / B[2], (x - B[3]) / B[4]**2 * gauss2, ((B[3] - x)**2 - B[4]**2) / B[4]**3 * gauss2, gauss2 / B[5], np.ones(x.shape, float))) _ret.shape = (7, ) + x.shape return _ret # Centre data in mean(x) (makes better conditioned matrix) mx = mean(x) x2 = x - mx if not any(iparams): iparams = array([ x2[np.argmax(y)], np.std(y), np.sqrt(2 * np.pi) * np.std(y) * max(y), x2[np.argmax(y)], np.std(y), np.sqrt(2 * np.pi) * np.std(y) * max(y), 1. ]) dgauss = odr.Model(double_gaussian, fjacd=_dgauss_fjd, fjacb=_dgauss_fjb) mydata = odr.Data(x2, y) myodr = odr.ODR(mydata, dgauss, beta0=iparams, maxit=itmax) # Set type of fit to least-squares: myodr.set_job(fit_type=2) if verbose == 2: myodr.set_iprint(final=2) fit = myodr.run() # Display results: if verbose: fit.pprint() print('Re-centered Beta: [%f %f %f %f %f %f %f]' % (fit.beta[0] + mx, fit.beta[1], fit.beta[2], fit.beta[3] + mx, fit.beta[4], fit.beta[5], fit.beta[6])) itlim = False if fit.stopreason[0] == 'Iteration limit reached': itlim = True print('(WWW) gauss_lsq: Iteration limit reached, result not reliable!') # Results and errors coeff = fit.beta coeff[[0, 3]] += mx # Recentre in original axis err = fit.sd_beta return coeff, err, itlim
def fit(self, num_cuts, truncate=True, withSpreadterm=False): x, y, xaxis, m, s, cnt = CMECostModel.qc(self, num_cuts, truncate) try: popt, pcov = curve_fit(self.model_curve_guess, x, y) except RuntimeError: popt = [1.0] * CMECostModel.num_free_params func = odr.Model(self.model_curve_ODR) odrdata = odr.Data(x, y) odrmodel = odr.ODR(odrdata, func, beta0=popt, maxit=500, ifixx=[0]) o = odrmodel.run() return o, x, y, xaxis, m, s, cnt
def fitScipyODR(xdata, ydata, xerr, yerr, func, pInit): """ Fit a series of data points with ODR (function must be in from f(beta[n], x)) """ model = odrpack.Model(func) data = odrpack.RealData(xdata, ydata, sx=xerr, sy=yerr) odr = odrpack.ODR(data, model, beta0=pInit) out = odr.run() popt = out.beta pcov = out.cov_beta out.pprint() print('Chi square = %f' % out.sum_square) return popt, pcov
def least(func, x, y, sy=None, beta0=[]): linear = odrpack.Model(func) #mydata = odrpack.Data(x, z[1], wd=1./np.power(z[2],2), we=1./np.power(sy,2)) if not sy == None: mydata = odrpack.RealData(x, y, sy=sy) else: mydata = odrpack.RealData(x, y) myodr = odrpack.ODR(mydata, linear, beta0=beta0, maxit=500) myodr.set_job(fit_type=2) myoutput = myodr.run() myoutput.pprint() return myodr.output
def do_odr(f, x, xe, y, ye, estimates): model = odrpack.Model(f) # sx and sy should be the covariances data = odrpack.RealData(x, y, sx=xe, sy=ye) # need to hard-code in estimates for parameters odr = odrpack.ODR(data, model, estimates) output = odr.run() return output
def estimate_spectra(self): from scipy.odr import odrpack as odr def ofunc(pars, x, sp_sens, nu, el): a, b, dkalpha, tele = pars spectra = a * Kalpha_profile(el, nu, dkalpha) + b * ff_profile( nu, tele) spectra /= np.trapz(spectra, nu) spectra = np.tile(spectra, (sp_sens.shape[0], 1)) comp_tr = np.trapz(sp_sens * spectra, nu, axis=-1) return comp_tr def ofunc2(pars, thick, nu, el): spectra = compute_spectra(pars, nu) sp_tr_filters = np.ones(nu.shape) for filt_el, filt_thick in self.filters.iteritems(): sp_tr_filters *= np.exp(-cold_opacity(filt_el, nu=nu) * filt_thick) ip_sens = ip_sensitivity(nu) comp_tr = [] for this_thick in thick: sp_sens = np.exp(-cold_opacity(el, nu=nu)*this_thick)\ * sp_tr_filters * ip_sens * spectra comp_tr.append(np.trapz(sp_sens, nu, axis=0)) return np.array(comp_tr).reshape((1, -1)) #return ((comp_tr - exp_tr)**2).sum() beta0 = [1, 1, 100, 1000] my_data = odr.RealData(self.thick, self.exp_tr, sy=0.05 * np.ones(self.exp_tr.shape)) my_model = odr.Model(ofunc2, extra_args=(self.nu, 'polystyrene')) my_odr = odr.ODR(my_data, my_model, beta0=beta0) my_odr.set_job(fit_type=2) my_odr.set_iprint(final=2, iter=1, iter_step=1) fit = my_odr.run() self.beta = fit.beta #[::-1] self.sdbeta = fit.sd_beta #[::-1] print(ofunc2(self.beta, self.thick, self.nu, 'polystyrene')) print(self.exp_tr) print('\n') print(beta0) print(self.beta)
def fitTrack(trackArray): results = [] x = [] y = [] energy = [] for i in trackArray: x.append(i[0]) y.append(i[1]) energy.append(i[2]) slope, intercept, r_value, p_value, std_err = stats.linregress(x, y) mydata = odrpack.Data(x, y, energy, energy) linear = odrpack.Model(f) myodr = odrpack.ODR(mydata, linear, beta0=[slope, intercept]) myoutput = myodr.run() results.append(myoutput.beta) return results
def nominal_AB(self, K, N, T, explore_mag=10, res_time=100): ''' Estimates matrices A and B Args: K: The controller gain N: number of iterations to be consistent with iterative methods T: Rollout length explore_mag: noise magnitude for excitement res_time: when to reset the dynamics to its initial condition Returns: A_nom, B_nom ''' Lin_gain = LinK(K) Lin_gain.make_sampling_on(explore_mag) if T >= res_time: N = int(np.ceil(N * T / res_time)) T = res_time A_nom = np.zeros((self.n, self.n)) B_nom = np.zeros((self.n, self.m)) # storage matrices states_batch = np.zeros((self.n, N, T)) next_states_batch = np.zeros((self.n, N, T)) actions_batch = np.zeros((self.m, N, T)) # simulate for k in range(N): # Do one rollout to save data for model estimation states, actions, _, next_states = self.dyn.one_rollout(Lin_gain.sample_lin_policy, T) states_batch[:, k, :] = states.T actions_batch[:, k, :] = actions.T next_states_batch[:, k, :] = next_states.T for i in range(self.n): linear = odrpack.Model(linear_func) data = odrpack.RealData( x=np.vstack((states_batch.reshape(self.n, N * T), actions_batch.reshape(self.m, N * T))), y=next_states_batch[i, :, :].reshape(1, N * T)) Myodr = odrpack.ODR(data, linear, np.zeros(self.n + self.m)) out = Myodr.run() tmp = out.beta A_nom[i, :] = tmp[0:self.n] B_nom[i, :] = tmp[self.n:] return A_nom, B_nom
def minThis(vertex, trackArray): sumOfSquares = 0 for i in range(len(trackArray)): x = [] y = [] energy = [] #print trackArray for i in trackArray[i]: x.append(i[0]) y.append(i[1]) energy.append(i[2]) slope, intercept, r_value, p_value, std_err = stats.linregress(x, y) mydata = odrpack.Data(x, y, energy, energy) linear = odrpack.Model(fv, extra_args=vertex) myodr = odrpack.ODR(mydata, linear, beta0=[slope, intercept]) myoutput = myodr.run() sumOfSquares += myoutput.sum_square return sumOfSquares
def fitSingleCrystalBallPeak(self): params = np.array([ self.peak1_paramsEdits[0].value(), self.peak1_paramsEdits[1].value(), self.peak1_paramsEdits[2].value(), self.peak1_paramsEdits[3].value(), 0.9, 4 ]) model = odr.Model(lineshape.Single_Crystalball) odr_data = odr.RealData(self.x_cut, self.y_cut) #, sy = np.sqrt(self.y_cut)) myodr = odr.ODR(odr_data, model, beta0=params) myodr.set_job(fit_type=0) myoutput = myodr.run() self.params = myoutput.beta params_cov = myoutput.cov_beta params_output = [] params_red_chi2 = myoutput.res_var content, error = integrate.quad(lineshape.Single_Crystalball_integrand, self.x_fit[0], self.x_fit[-1], args=tuple(self.params)) params_output.append(content) params_output.append(params_red_chi2) self.params_outputs = np.array(params_output) for i in range(len(self.peak1_paramsEdits)): self.peak1_paramsEdits[i].setValue(self.params[i]) self.peak1_contentEdit.setText(str(self.params_outputs[0])) self.peak1_chi2Edit.setText(str(self.params_outputs[1])) self.plotWidget.plot(clear=True) self.plotWidget.plot(self.x, self.y[:-1], stepMode=True) fitPen = pg.mkPen(color=(204, 0, 0), width=2) self.plotWidget.plot(self.x_fit, lineshape.Single_Crystalball( self.params, self.x_fit), pen=fitPen) self.plotWidget.addItem(self.vLine, ignoreBounds=True) self.plotWidget.addItem(self.hLine, ignoreBounds=True)
def fit2(data,interval,init): interval.sort() nData = data[(data[:,0] > interval[0])&(data[:,0] < interval[1])] x=nData[:,0] y=nData[:,1] sx=None sy=None try: sx = nData[:,2] sy = nData[:,3] except: pass def func(B,x): return (1/B[0]) * x linear = odrpack.Model(func) mydata = odrpack.RealData(x, y, sx=sx, sy=sy) myodr = odrpack.ODR(mydata, linear, beta0=[init]) myoutput = myodr.run() myoutput.pprint() return [myoutput.beta[0],myoutput.sd_beta[0]]
def ODRfit(model, X, Y, p0, verbose=False): if type(p0) != 'numpy.ndarray': try: p0, up0 = unpack_unarray(p0) except TypeError: pass x, ux = unpack_unarray(X) y, uy = unpack_unarray(Y) modello = odrpack.Model(model) data = odrpack.RealData(x, y, sx=ux, sy=uy) engine = odrpack.ODR(data, modello, beta0=p0) output = engine.run() P = unc.correlated_values(output.beta, output.cov_beta) if verbose: output.pprint() return P, output.sum_square
def fit_tls(x: np.ndarray, y: np.ndarray) -> float: """Fit total least squares model to data This function fits a total least squares (also known as orthogonal distance regression) model to 2-dimensional data. The model has the form `y = m * x`, where m is the "slope". (It has an intercept at y==0). See Also: At its core, the function uses scipy's `Orthogonal Distance Regression`_ module .. _Orthogonal Distance Regression: https://docs.scipy.org/doc/scipy/reference/odr.html Args: x: 1-dimensional Numpy array y: 1-dimensional Numpy array of the same size as `x` Returns: The slope of the fitted model """ odr_data = odrpack.RealData(x, y) model = odrpack.Model(lambda beta, x_: beta[0] * x_) odr_container = odrpack.ODR(odr_data, model, beta0=[1.0]) slope = odr_container.run().beta[0] #TODO PLOT SECTOR 0 some pairs (weird results) return slope
def estimate_spatial_resolution(x, y, ofunc=blurred_step_function, beta0=None, verbose=True): """ Estimate the spatial resolution of an X-ray image from a lineout of an edge. It assumes that if the spatial resolution was ideal, that should produce a sharp step. Instead we have a step convolved with a gaussian function. This function then estimates the standard deviation of this gaussian. Parameters ---------- x : ndarray : position in physical units [µm, cm, etc] y : ndarray : signal on the IP ofunc: objective function, here the convolution of a step with a gaussian beta0 : initial estimate of parameters. A good estimate could be for instance, beta0 = [y.mean(), x.mean(), 20, y.mean(), 0] verbose: true Returns ------- tuple: (std, std_err) """ from scipy import odr mmodel = odr.Model(ofunc) mdata = odr.Data(x, y) fit = odr.ODR(mdata, mmodel, beta0, maxit=1000) fit.set_job(fit_type=2) # least squares fit.set_iprint(final=verbose) fit.run() beta = fit.output.beta error = fit.output.sd_beta return beta, error
stdp = np.zeros(saveshape[0:-1]) r2 = np.zeros_like(scales) estimate = np.zeros_like(filt) mag = np.array(mag) def linear(beta, x): f = np.zeros(x.shape) f = beta[0] * x + beta[1] return f # Create model linearfit = odr.Model(linear) # Creates a noise mask that takes only those values greater than noise_lb freqs = np.linspace(-1.0, 1.0, nt) / (2 * TR) noise_mask = np.fft.fftshift(1.0 * (abs(freqs) > noise_lb)) # Estimates standard deviations of magnitude and phase for x in range(mag.shape[0]): temp = mag[x, :, :, :] stdm[x, :, :] = np.std(np.fft.ifft(np.fft.fft(temp) * noise_mask), -1) temp = ph[x, :, :, :] stdp[x, :, :] = np.std(np.fft.ifft(np.fft.fft(temp) * noise_mask), -1) # Reshape variables into a single column mag = np.reshape( mag, (-1, nt)) # Reshapes variable intro 2D matrix of voxels x timepoints
binstrp = delete(binstrp, delidx) stdbin = delete(stdbin, delidx) ''' if mb == 4.25: print(len(mmi[idx])) print(log10(rrup[idx])) print(medbin, binstrp) print(eqname[idx]) crash ''' if len(medbin < 2) and mb != 4.25: # get intercept data = odrpack.RealData(binstrp, medbin) intfit = odrpack.Model(linear_fixed_slope) odr = odrpack.ODR(data, intfit, beta0=[5.0]) #data = odrpack.RealData(10**binstrp, medbin, meta={'mag':mb}) #intfit = odrpack.Model(near_src_trunc_fixed_slope) #odr = odrpack.ODR(data, intfit, beta0=[5.0]) odr.set_job(fit_type=2) #if set fit_type=2, returns the same as leastsq, 0=ODR out = odr.run() intercept = out.beta intercepts.append(intercept[0]) meanmagbin.append(mean(mmi[idx])) meanmws.append(mean(mw[idx])) else: intercepts.append(nan) meanmagbin.append(nan)
def circle_lsq(x, y, up=True, verbose=False, itmax=200, iparams=[]): ''' Method to compute a circle fit, It fits for circle parameters in the form y = B_2 +/- sqrt(B_0^2-(x-B_1)^2), the sign is negative if up is False. IN: x,y (arr) - data to fit n (int) - polinomial order verbose - can be 0,1,2 for different levels of output (False or True are the same as 0 or 1) itmax (int) - optional maximum number of iterations. iparams (arr) - optional initial parameters b0,b1,b2 OUT: coeff - polynomial coefficients, lowest order first err - standard error (1-sigma) on the coefficients --Tiago, 20080120 ''' # circle functions for B=r,x0,y0 def circle_up(B, x): return B[2] + sqrt(B[0]**2 - (x - B[1])**2) def circle_dn(B, x): return B[2] - sqrt(B[0]**2 - (x - B[1])**2) # Derivative of function in respect to x def circle_fjd_up(B, x): return -(x - B[1]) / (sqrt(B[0]**2 - (x - B[1])**2)) def circle_fjd_dn(B, x): return (x - B[1]) / (sqrt(B[0]**2 - (x - B[1])**2)) # Derivative of function in respect to B[i] def circle_fjb_up(B, x): _ret = np.concatenate(( B[0] / (sqrt(B[0]**2 - (x - B[1])**2)), -circle_fjd_up(B, x), np.ones(x.shape, float), )) _ret.shape = (3, ) + x.shape return _ret def circle_fjb_dn(B, x): _ret = np.concatenate(( B[0] / (sqrt(B[0]**2 - (x - B[1])**2)), -circle_fjd_dn(B, x), np.ones(x.shape, float), )) _ret.shape = (3, ) + x.shape return _ret if any(iparams): def circle_est(data): return tuple(iparams) else: def circle_est(data): return (1., 1., 1.) if up: circle_fit = odr.Model(circle_up, fjacd=circle_fjd_up, fjacb=circle_fjb_up, estimate=circle_est) else: circle_fit = odr.Model(circle_dn, fjacd=circle_fjd_dn, fjacb=circle_fjb_dn, estimate=circle_est) mydata = odr.Data(x, y) myodr = odr.ODR(mydata, circle_fit, maxit=itmax) # Set type of fit to least-squares: myodr.set_job(fit_type=2) if verbose == 2: myodr.set_iprint(final=2) fit = myodr.run() # Display results: if verbose: fit.pprint() if fit.stopreason[0] != 'Sum of squares convergence': if verbose: print('(WWW): circle_lsq: fit result not reliable') success = 0 else: success = 1 # Results and errors coeff = fit.beta err = fit.sd_beta return coeff, success, err
def gauss_lsq(x, y, weight_x=1., weight_y=1., verbose=False, itmax=200, iparams=[]): """ Performs a Gaussian least squares fit to the data, with errors! Uses scipy odrpack, but for least squares. Parameters ---------- x : 1D array-like Observed data, independent variable y : 1D array-like Observed data, dependent variable weight_x: array-like, optional Weights for independent variable. This is typically based on the errors, if any. With errors, normal weights should be 1/err**2. If weight is a scalar, the same weight will be used for all points and therefore its value is irrelevant. weight_y: array-like, optional. Weights for independent variable. This is typically based on the errors, if any. With errors, normal weights should be 1/err**2. For Poisson weighing, should be 1/y. verbose: boolean If True, will print out more detailed information about the result. itmax: integer, Optional Maximum number of iterations, default is 200. iparams: list, optional Starting guess of Gaussian parameters. Optional but highly recommended to use realistic values! Returns ------- output: tuple Tuple with containing (coeff, err, itlim), where coeff are the fit resulting coefficients (same order as Gaussian function above), err are the errors on each coefficient, and itlim is the number of iterations. Notes ----- See documentation of scipy.odr.ordpack for more information. """ def _gauss_fjd(B, x): # Analytical derivative of gaussian with respect to x return (B[0] - x) / B[1]**2 * gaussian(np.concatenate( (B[:3], [0.])), x) def _gauss_fjb(B, x): gauss1 = gaussian(np.concatenate((B[:3], [0.])), x) # Analytical derivatives of gaussian with respect to parameters _ret = np.concatenate( ((x - B[0]) / B[1]**2 * gauss1, ((B[0] - x)**2 - B[1]**2) / B[1]**3 * gauss1, gauss1 / B[2], np.ones(x.shape, float))) _ret.shape = (4, ) + x.shape return _ret # Centre data in mean(x) (makes better conditioned matrix) mx = np.mean(x) x2 = x - mx if not any(iparams): iparams = np.array([ x2[np.argmax(y)], np.std(y), np.sqrt(2 * np.pi) * np.std(y) * max(y), 1. ]) gauss = odr.Model(gaussian, fjacd=_gauss_fjd, fjacb=_gauss_fjb) mydata = odr.Data(x2, y, wd=weight_x, we=weight_y) myodr = odr.ODR(mydata, gauss, beta0=iparams, maxit=itmax) # Set type of fit to least-squares: myodr.set_job(fit_type=2) if verbose == 2: myodr.set_iprint(final=2) fit = myodr.run() # Display results: if verbose: fit.pprint() print('Re-centered Beta: [%f %f %f %f]' % (fit.beta[0] + mx, fit.beta[1], fit.beta[2], fit.beta[3])) itlim = False if fit.stopreason[0] == 'Iteration limit reached': itlim = True print('(WWW) gauss_lsq: Iteration limit reached, result not reliable!') # Results and errors coeff = fit.beta coeff[0] += mx # Recentre in original axis err = fit.sd_beta return coeff, err, itlim
idx = mrng > lenhmag ylen = lenc + lengrd1 * lenhmag cinter_len[idx] = 10**(lengrd2 * (mrng[idx]-lenhmag) + ylen) ''' h = plt.semilogy(mrng, cinter_len, 'k-', lw=2.0) hh = [h[0]] # fit lengths savec = [] tabtxt = 'Length\nType,a,SEa,b,sig,Range\n' for i in range(0, len(fmag)): data = odrpack.RealData(array(fmag[i]),log10(array(flen[i]))) grad = grads[0] lin = odrpack.Model(linear_reg_fix_slope) odr = odrpack.ODR(data, lin, beta0=[-2.]) odr.set_job(fit_type=0) #if set fit_type=2, returns the same as leastsq out = odr.run() out.pprint() c = out.beta[0] savec.append(c) regmrng = arange(min(fmag[i]), max(fmag[i])+0.01, 0.01) clen = 10**(c + grad * regmrng) print i h = plt.semilogy(regmrng, clen, '-', color=cs2[i+1], lw=2.0) hh.append(h[0]) tabtxt += ','.join((ftypes[i], str('%0.2f' % c), str('%0.2f' % out.sd_beta[0]), \ str('%0.2f' % grad), str('%0.2f' % sqrt(out.res_var)), \ str('%0.1f' % min(fmag[i]))+'-'+str('%0.1f' % max(fmag[i]))))+'\n'
def peak_fit(xdata, ydata, iparams=[], peaktype='Gauss', maxit=300, background='constant', plot=False, func_out=False, debug=False): """ fit function using odr-pack wrapper in scipy similar to https://github.com/tiagopereira/python_tips/wiki/Scipy%3A-curve-fitting for Gauss, Lorentz or Pseudovoigt-functions Parameters ---------- xdata : array_like x-coordinates of the data to be fitted ydata : array_like y-coordinates of the data which should be fit iparams : list, optional initial paramters, determined automatically if not specified peaktype : {'Gauss', 'Lorentz', 'PseudoVoigt', 'PseudoVoigtAsym', 'PseudoVoigtAsym2'}, optional type of peak to fit maxit : int, optional maximal iteration number of the fit background : {'constant', 'linear'}, optional type of background function plot : bool or str, optional flag to ask for a plot to visually judge the fit. If plot is a string it will be used as figure name, which makes reusing the figures easier. func_out : bool, optional returns the fitted function, which takes the independent variables as only argument (f(x)) Returns ------- params : list the parameters as defined in function `Gauss1d/Lorentz1d/PseudoVoigt1d/ PseudoVoigt1dasym`. In the case of linear background one more parameter is included! sd_params : list For every parameter the corresponding errors are returned. itlim : bool flag to tell if the iteration limit was reached, should be False fitfunc : function, optional the function used in the fit can be returned (see func_out). """ if plot: plot, plt = utilities.import_matplotlib_pyplot('XU.math.peak_fit') gfunc, gfunc_dx, gfunc_dp = _getfit_func(peaktype, background) # determine initial parameters _check_iparams(iparams, peaktype, background) if not any(iparams): iparams = _guess_iparams(xdata, ydata, peaktype, background) if config.VERBOSITY >= config.DEBUG: print("XU.math.peak_fit: iparams: %s" % str(tuple(iparams))) # set up odr fitting peak = odr.Model(gfunc, fjacd=gfunc_dx, fjacb=gfunc_dp) sy = numpy.sqrt(ydata) sy[sy == 0] = 1 mydata = odr.RealData(xdata, ydata, sy=sy) myodr = odr.ODR(mydata, peak, beta0=iparams, maxit=maxit) myodr.set_job(fit_type=2) # use least-square fit fit = myodr.run() if config.VERBOSITY >= config.DEBUG: print('XU.math.peak_fit:') fit.pprint() # prints final message from odrpack fparam = fit.beta etaidx = [] if peaktype in ('PseudoVoigt', 'PseudoVoigtAsym'): if background == 'linear': etaidx = [-2, ] else: etaidx = [-1, ] elif peaktype == 'PseudoVoigtAsym2': etaidx = [5, 6] for e in etaidx: fparam[e] = 0 if fparam[e] < 0 else fparam[e] fparam[e] = 1 if fparam[e] > 1 else fparam[e] itlim = False if fit.stopreason[0] == 'Iteration limit reached': itlim = True if config.VERBOSITY >= config.INFO_LOW: print("XU.math.peak_fit: Iteration limit reached, " "do not trust the result!") if plot: if isinstance(plot, str): plt.figure(plot) else: plt.figure('XU:peak_fit') plt.plot(xdata, ydata, 'ok', label='data', mew=2) if debug: plt.plot(xdata, gfunc(iparams, xdata), '-', color='0.5', label='estimate') plt.plot(xdata, gfunc(fparam, xdata), '-r', label='%s-fit' % peaktype) plt.legend() if func_out: return fparam, fit.sd_beta, itlim, lambda x: gfunc(fparam, x) else: return fparam, fit.sd_beta, itlim
def multPeakFit(x, data, peakpos, peakwidth, dranges=None, peaktype='Gaussian', returnerror=False): """ function to fit multiple Gaussian/Lorentzian peaks with linear background to a set of data Parameters ---------- x : array-like x-coordinate of the data data : array-like data array with same length as `x` peakpos : list initial parameters for the peak positions peakwidth : list initial values for the peak width dranges : list of tuples list of tuples with (min, max) value of the data ranges to use. does not need to have the same number of entries as peakpos peaktype : {'Gaussian', 'Lorentzian'} type of peaks to be used returnerror : bool decides if the fit errors of pos, sigma, and amp are returned (default: False) Returns ------- pos : list peak positions derived by the fit sigma : list peak width derived by the fit amp : list amplitudes of the peaks derived by the fit background : array-like background values at positions `x` if returnerror == True: sd_pos : list standard error of peak positions as returned by scipy.odr.Output sd_sigma : list standard error of the peak width sd_amp : list standard error of the peak amplitude """ warnings.warn("deprecated function -> use the lmfit Python packge instead", DeprecationWarning) if peaktype == 'Gaussian': pfunc = Gauss1d pfunc_derx = Gauss1d_der_x elif peaktype == 'Lorentzian': pfunc = Lorentz1d pfunc_derx = Lorentz1d_der_x else: raise ValueError('wrong value for parameter peaktype was given') def deriv_x(p, x): """ function to calculate the derivative of the signal of multiple peaks and background w.r.t. the x-coordinate Parameters ---------- p : list parameters, for every peak there needs to be position, sigma, amplitude and at the end two values for the linear background function (b0, b1) x : array-like x-coordinate """ derx = numpy.zeros(x.size) # sum up peak functions contributions for i in range(len(p) // 3): ldx = pfunc_derx(x, p[3 * i], p[3 * i + 1], p[3 * i + 2], 0) derx += ldx # background contribution k = p[-2] b = numpy.ones(x.size) * k return derx + b def deriv_p(p, x): """ function to calculate the derivative of the signal of multiple peaks and background w.r.t. the parameters Parameters ---------- p : list parameters, for every peak there needs to be position, sigma, amplitude and at the end two values for the linear background function (b0, b1) x : array-like x-coordinate returns derivative w.r.t. all the parameters with shape (len(p),x.size) """ derp = numpy.empty(0) # peak functions contributions for i in range(len(p) // 3): lp = (p[3 * i], p[3 * i + 1], p[3 * i + 2], 0) if peaktype == 'Gaussian': derp = numpy.append(derp, -2 * (lp[0] - x) * pfunc(x, *lp)) derp = numpy.append( derp, (lp[0] - x) ** 2 / (2 * lp[1] ** 3) * pfunc(x, *lp)) derp = numpy.append(derp, pfunc(x, *lp) / lp[2]) else: # Lorentzian derp = numpy.append(derp, 4 * (x - lp[0]) * lp[2] / lp[1] / (1 + (2 * (x - lp[0]) / lp[1]) ** 2) ** 2) derp = numpy.append(derp, 4 * (lp[0] - x) * lp[2] / lp[1] ** 2 / (1 + (2 * (x - lp[0]) / lp[1]) ** 2) ** 2) derp = numpy.append(derp, 1 / (1 + (2 * (x - p[0]) / p[1]) ** 2)) # background contributions derp = numpy.append(derp, x) derp = numpy.append(derp, numpy.ones(x.size)) # reshape output derp.shape = (len(p),) + x.shape return derp def fsignal(p, x): """ function to calculate the signal of multiple peaks and background Parameters ---------- p : list list of parameters, for every peak there needs to be position, sigma, amplitude and at the end two values for the linear background function (k, d) x : array-like x-coordinate """ f = numpy.zeros(x.size) # sum up peak functions for i in range(len(p) // 3): lf = pfunc(x, p[3 * i], p[3 * i + 1], p[3 * i + 2], 0) f += lf # background k = p[-2] d = p[-1] b = numpy.polyval((k, d), x) return f + b ########################## # create local data set (extract data ranges) if dranges: mask = numpy.array([False] * x.size) for i in range(len(dranges)): lrange = dranges[i] lmask = numpy.logical_and(x > lrange[0], x < lrange[1]) mask = numpy.logical_or(mask, lmask) lx = x[mask] ldata = data[mask] else: lx = x ldata = data # create initial parameter list p = [] # background # exclude +/-2 peakwidth around the peaks bmask = numpy.ones_like(lx, dtype=bool) for pp, pw in zip(peakpos, peakwidth): bmask = numpy.logical_and(bmask, numpy.logical_or(lx < (pp-2*pw), lx > (pp+2*pw))) if numpy.any(bmask): k, d = numpy.polyfit(lx[bmask], ldata[bmask], 1) else: if(config.VERBOSITY >= config.DEBUG): print("XU.math.multPeakFit: no data outside peak regions!") k, d = (0, ldata.min()) # peak parameters for i in range(len(peakpos)): amp = ldata[(lx - peakpos[i]) >= 0][0] - \ numpy.polyval((k, d), lx)[(lx - peakpos[i]) >= 0][0] p += [peakpos[i], peakwidth[i], amp] # background parameters p += [k, d] if(config.VERBOSITY >= config.DEBUG): print("XU.math.multPeakFit: intial parameters") print(p) ########################## # fit with odrpack model = odr.Model(fsignal, fjacd=deriv_x, fjacb=deriv_p) odata = odr.RealData(lx, ldata) my_odr = odr.ODR(odata, model, beta0=p) # fit type 2 for least squares my_odr.set_job(fit_type=2) fit = my_odr.run() if(config.VERBOSITY >= config.DEBUG): print("XU.math.multPeakFit: fitted parameters") print(fit.beta) try: if fit.stopreason[0] not in ['Sum of squares convergence']: print("XU.math.multPeakFit: fit NOT converged (%s)" % fit.stopreason[0]) return Nono, None, None, None except IndexError: print("XU.math.multPeakFit: fit most probably NOT converged (%s)" % str(fit.stopreason)) return None, None, None, None # prepare return values fpos = fit.beta[:-2:3] fwidth = numpy.abs(fit.beta[1:-2:3]) famp = fit.beta[2::3] background = numpy.polyval((fit.beta[-2], fit.beta[-1]), x) if returnerror: sd_pos = fit.sd_beta[:-2:3] sd_width = fit.sd_beta[1:-2:3] sd_amp = fit.sd_beta[2::3] return fpos, fwidth, famp, background, sd_pos, sd_width, sd_amp return fpos, fwidth, famp, background
def fitDoubleCrystalBallPeak(self): params = np.array([ self.peak1_paramsEdits[0].value(), self.peak1_paramsEdits[1].value(), self.peak1_paramsEdits[2].value(), self.peak1_paramsEdits[3].value(), self.peak2_paramsEdits[0].value(), self.peak2_paramsEdits[1].value(), self.peak2_paramsEdits[2].value(), 0.9, 4 ]) model = odr.Model(lineshape.Double_Crystalball) odr_data = odr.RealData(self.x_cut, self.y_cut) #, sy = np.sqrt(self.y_cut)) myodr = odr.ODR(odr_data, model, beta0=params) myodr.set_job(fit_type=0) myoutput = myodr.run() self.params = myoutput.beta params_cov = myoutput.cov_beta params_output = [] params_red_chi2 = myoutput.res_var single_index = [0, 1, 2, 3, 7, 8] params_single = self.params[single_index] double_index = [4, 5, 6, 3, 7, 8] params_double = self.params[double_index] content1, error1 = integrate.quad( lineshape.Single_Crystalball_integrand, self.x_fit[0], self.x_fit[-1], args=tuple(params_single)) content2, error2 = integrate.quad( lineshape.Single_Crystalball_integrand, self.x_fit[0], self.x_fit[-1], args=tuple(params_double)) params_output.append(content1) params_output.append(params_red_chi2) params_output.append(content2) self.params_outputs = np.array(params_output) for i in range(len(self.params)): if i < 4: self.peak1_paramsEdits[i].setValue(self.params[i]) if 3 < i < 7: self.peak2_paramsEdits[i - 4].setValue(self.params[i]) self.peak1_contentEdit.setText(str(self.params_outputs[0])) self.peak1_chi2Edit.setText(str(self.params_outputs[1])) self.peak2_contentEdit.setText(str(self.params_outputs[2])) self.plotWidget.plot(clear=True) histo = pg.PlotCurveItem(self.x, self.y[:-1], stepMode=True) self.plotWidget.addItem(histo) if self.PeaksButton.isChecked() == False: fitPen = pg.mkPen(color=(204, 0, 0), width=2) self.plotWidget.plot(self.x_fit, lineshape.Double_Crystalball( self.params, self.x_fit), pen=fitPen) if self.PeaksButton.isChecked() == True: fitPen = pg.mkPen(color=(204, 0, 0), width=2, style=QtCore.Qt.DashLine) params1 = np.array([ self.peak1_paramsEdits[0].value(), self.peak1_paramsEdits[1].value(), self.peak1_paramsEdits[2].value(), self.peak1_paramsEdits[3].value(), 0.9, 4 ]) params2 = np.array([ self.peak2_paramsEdits[0].value(), self.peak2_paramsEdits[1].value(), self.peak2_paramsEdits[2].value(), self.peak1_paramsEdits[3].value(), 0.9, 4 ]) self.plotWidget.plot(self.x_fit, lineshape.Single_Crystalball( params1, self.x_fit), pen=fitPen) self.plotWidget.plot(self.x_fit, lineshape.Single_Crystalball( params2, self.x_fit), pen=fitPen) self.plotWidget.addItem(self.vLine, ignoreBounds=True) self.plotWidget.addItem(self.hLine, ignoreBounds=True)
################################################################################ ## ## Test orth. regression ## ################################################################################ def f(B, theta1): return B[0] * (np.cos((2*np.pi)/360*theta1))**2 + B[1] x = theta1 y = a1 sx = theta2 sy = a2 linear = odrpack.Model(f) myData = odrpack.RealData(x, y, sx=sx, sy=sy) myOdr = odrpack.ODR(myData, linear , beta0=[1,1]) myOdr.set_job(fit_type=2) #if set fit_type=2, returns the same as leastsq out = myOdr.run() #out.pprint() coeff = out.beta[::-1] err = out.sd_beta[::-1] print(coeff[0], err[0]) print(coeff[1], err[1]) ################################################################################
def quad_lsq(x, y, verbose=False, itmax=200, iparams=[]): ''' Method to compute a parabola fit, more handy as it fits for parabola parameters in the form y = B_0 * (x - B_1)**2 + B_2. This is computationally slower than poly_lsq, so beware of its usage for time consuming operations. IN: x,y (arr) - data to fit n (int) - polinomial order verbose - can be 0,1,2 for different levels of output (False or True are the same as 0 or 1) itmax (int) - optional maximum number of iterations. iparams (arr) - optional initial parameters b0,b1,b2 OUT: coeff - polynomial coefficients, lowest order first err - standard error (1-sigma) on the coefficients --Tiago, 20071115 ''' # Tiago's internal new definition of quadratic def _quadratic(B, x): return B[0] * (x - B[1]) * (x - B[1]) + B[2] def _quad_fjd(B, x): return 2 * B[0] * (x - B[1]) def _quad_fjb(B, x): _ret = np.concatenate(( np.ones(x.shape, float), 2 * B[0] * (B[1] - x), x * x - 2 * B[1] * x + B[1] * B[1], )) _ret.shape = (3, ) + x.shape return _ret if any(iparams): def _quad_est(data): return tuple(iparams) else: def _quad_est(data): return (1., 1., 1.) quadratic = odr.Model(_quadratic, fjacd=_quad_fjd, fjacb=_quad_fjb, estimate=_quad_est) mydata = odr.Data(x, y) myodr = odr.ODR(mydata, quadratic, maxit=itmax) # Set type of fit to least-squares: myodr.set_job(fit_type=2) if verbose == 2: myodr.set_iprint(final=2) fit = myodr.run() # Display results: if verbose: fit.pprint() if fit.stopreason[0] == 'Iteration limit reached': print('(WWW) quad_lsq: iteration limit reached, result not reliable!') # Results and errors coeff = fit.beta err = fit.sd_beta return coeff, err
ax1.errorbar(s, x, 0, 0, color="black", fmt='.', label='Data') def fit_function(w, F0, w0, gamma): #gamma = 0.01515 return F0 / pylab.sqrt((w0**2 - w**2)**2 + 4.0 * (gamma**2) * (w**2)) def fit_function_ODR(pars, w): #pars[2] = 0.01515 return pars[0] / pylab.sqrt((pars[1]**2 - w**2)**2 + 4.0 * (pars[2]**2) * (w**2)) # Run the actual ODR. model = odrpack.Model(fit_function_ODR) data = odrpack.RealData(s, x) odr = odrpack.ODR(data, model, beta0=(53.7, 4.7, 0.064)) out = odr.run() popt, pcov = out.beta, out.cov_beta F0, w0, gamma = popt dF0, dw0, dgamma = numpy.sqrt(pcov.diagonal()) chisq = out.sum_square # !Run the actual ODR. # Run the actual ODR. model = odrpack.Model(fit_function_ODR) data = odrpack.RealData(s, x) odr = odrpack.ODR(data, model, beta0=(F0, w0, gamma)) out = odr.run() popt, pcov = out.beta, out.cov_beta F0, w0, gamma = popt