def fit_powerlaw_covariance(xdata, ydata, yerr = None, should_plot=True, debug=False): ''' Implements http://www.scipy.org/Cookbook/FittingData We actually compute the standard deviation for each x-value, and use this when computing the fit. ''' assert not (ydata.ndim == 1 and yerr is None), 'Use another function or provide yerr, this function requires the standard deviation' if ydata.ndim == 2: # Y data 2-dim, compute the standard errors, along the second dimension yerr = np.std(ydata, axis=1) ydata = np.mean(ydata, axis=1) logx = np.log(xdata.astype('float')) logy = np.log(ydata) logyerr = yerr/ydata # define our (line) fitting function fitfunc = lambda p, x: p[0] + p[1] * x errfunc = lambda p, x, y, err: (y - fitfunc(p, x)) / err # Initial parameters pinit = np.array([1.0, -1.0]) out = spopt.leastsq(errfunc, pinit, args=(logx, logy, logyerr), full_output=1) pfinal = out[0] covar = out[1] index = pfinal[1] amp = np.exp(pfinal[0]) if debug: indexErr = np.sqrt( covar[0][0] ) ampErr = np.sqrt( covar[1][1] ) * amp print pfinal print 'Ampli = %5.2f +/- %5.2f' % (amp, ampErr) print 'Index = %5.2f +/- %5.2f' % (index, indexErr) ########## # Plotting data ########## if should_plot: plot_powerlaw_fit(xdata, ydata, amp, index, yerr=yerr) return np.array([index, amp])
def fit_powerlaw(xdata, ydata, should_plot=False, debug=False): ''' Fit a power law to the provided data. y = a x**p Actually fit to the mean of the provided data, if multiple columns given (axis 1) Look for next function in order to fit a powerlaw while taking std dev into account. returns (power p, amplitude a) ''' ########## # Fitting the data -- Least Squares Method ########## # Power-law fitting is best done by first converting # to a linear equation and then fitting to a straight line. # # y = a * x^b # log(y) = log(a) + b*log(x) # if ydata.ndim == 1: # We have a 1D array, need a flat 2D array... ydata = ydata[:, np.newaxis] if xdata.ndim == 1: # We need to tile the x values appropriately, to fit the size of y # (just because leastsq is not funny) xdata = np.tile(xdata, (ydata.shape[1], 1)).T logx = np.log(xdata.astype('float')) logy = np.log(ydata) if np.any(np.isnan(logy)): # Something went wrong, just stop here... return np.array([np.nan, np.nan]) # define our (line) fitting function fitfunc = lambda p, x: p[0] + p[1] * x errfunc = lambda p, x, y: np.mean(y - fitfunc(p, x), axis=1) # Initial parameters pinit = np.array([1.0, -1.0]) out = spopt.leastsq(errfunc, pinit, args=(logx, logy), full_output=1) # out = spopt.fmin(errfunc_mse, pinit, args=(logx, logy)) pfinal = out[0] index = pfinal[1] amp = np.exp(pfinal[0]) if debug: print pfinal print 'Ampli = %5.2f' % amp print 'Index = %5.2f' % index ########## # Plotting data ########## if should_plot: plot_powerlaw_fit(xdata, ydata, amp, index) return np.array([index, amp])