def poly_lsq(x, y, n, verbose=False, itmax=200): ''' Performs a polynomial least squares fit to the data, with errors! Uses scipy odrpack, but for least squares. IN: x,y (arrays) - 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 OUT: coeff - polynomial coefficients, lowest order first err - standard error (1-sigma) on the coefficients --Tiago, 20071114 ''' func = models.polynomial(n) mydata = odr.Data(x, y) myodr = odr.ODR(mydata, func, 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) poly_lsq: Iteration limit reached, result not reliable!') # Results and errors coeff = fit.beta err = fit.sd_beta return coeff, err
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 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 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 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 poly_lsq(x, y, n, verbose=False, itmax=200): """ Performs a polynomial least squares fit to the data, with errors! Uses scipy odrpack, but for least squares. Parameters ---------- x, y : 1-D arrays Data to fit. n : int Polynomial order verbose : bool or int, optional 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. Returns ------- coeff : 1-D array Polynomial coefficients, lowest order first. err : 1-D array Standard error (1-sigma) on the coefficients. """ func = models.polynomial(n) mydata = odr.Data(x, y) myodr = odr.ODR(mydata, func, 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) poly_lsq: Iteration limit reached, result not reliable!') # Results and errors coeff = fit.beta err = fit.sd_beta return coeff, err
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
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
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
def circle_lsq(x, y, up=True, verbose=False, itmax=200, iparams=[]): """ Method to compute a (half) 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. Parameters ---------- x, y : 1-D arrays Data to fit. up : bool, optional Whether the half circle is up or down. verbose : bool or int, optional 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 : 1D array, optional Initial parameters B_0, B_1, B_2. Returns ------- coeff : 1-D array Parabola coefficients err : 1-D array Standard error (1-sigma) on the coefficients. """ # 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 quad_lsq(x, y, verbose=False, itmax=200, iparams=[]): """ Fits a parabola to the data, 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. Uses scipy odrpack, but for least squares. Parameters ---------- x, y : 1-D arrays Data to fit. verbose : bool or int, optional 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 : 1D array, optional Initial parameters B_0, B_1, B_2. Returns ------- coeff : 1-D array Parabola coefficients err : 1-D array Standard error (1-sigma) on the coefficients. """ # Internal 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
def fit(func, x, y, default_pars=None, data_range=None, we=None, verbose=False, itmax=200): ''' The meat of the fitting package. See docs of fit.py for more details. Functions available are gaus and expo and more. Error implementation provided via an example by: Tiago, 20071114 Performs a least squares fit to the data, with errors! Uses scipy odrpack, but for least squares. IN: (func, x, y, verbose, itmax) func - A function that accepts input in the form: func(params, x) x,y (arrays) - data to fit default_pars - Optional default parameters to start minimization at. data_range - Fit a subrange of (x,y). Provide a tuple of the form (x_min, x_max). we - Weighting for data points as delivered to ODR. You probably want it the same length as x. 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 OUT: (fit, params, err) fit - xfit,yfit arrays that can immediately plotted to see the results of your fit. xf and yf are defined as: xfit = linspace( min(x), max(x), len(x)*10) yfit = func(xfit) params - the coefficients of your fit in the order the function takes. err - standard error (1-sigma) on the coefficients ''' # If this is a histogram output, correct it for the user. if len(x) == len(y) + 1: x = (x[1:] + x[:-1]) / 2. # Take a slice of data. if data_range: y = y[logical_and(x > data_range[0], x < data_range[1])] x = x[logical_and(x > data_range[0], x < data_range[1])] # http://www.scipy.org/doc/api_docs/SciPy.odr.odrpack.html # see models.py and use ready made models!!!! if default_pars != None: beta0 = array(default_pars) else: beta0 = get_default_params(x, y, func) model_func = models.Model(func) mydata = odr.Data(x, y, we) myodr = odr.ODR(mydata, model_func, maxit=itmax, beta0=beta0) # 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) poly_lsq: Iteration limit reached, result not reliable!') # Results and errors coeff = fit.beta err = fit.sd_beta chi = fit.sum_square # The resulting fit. xfit = linspace(min(x), max(x), len(x) * 10) yfit = func(fit.beta, xfit) return array([xfit, yfit]), coeff, err, chi