def calculate_normalised_xsection(inputs, bin_widths, normalise_to_one=False, covariance_matrix=None, inputMC_covariance_matrix=None): """ Calculates normalised average x-section for each bin: 1/N *1/bin_width sigma_i There are two ways to calculate this 1) N = sum(sigma_i) 2) N = sum(sigma_i/bin_width) The latter one will normalise the total distribution to 1 @param inputs: list of value-error pairs @param bin_widths: bin widths of the inputs """ values = [u.ufloat(i[0], i[1]) for i in inputs] norm_cov_matrix = None norm_corr_matrix = None inputMC_norm_cov_matrix = None if not covariance_matrix is None and not normalise_to_one: values_correlated = u.correlated_values( [v.nominal_value for v in values], covariance_matrix.tolist()) norm = sum(values_correlated) norm_values_correlated = [] # Loop over unfolded number of events with correlated uncertainties # And corresponding bin width # Calculate normalised cross section, with correctly correlated uncertainty for v, width in zip(values_correlated, bin_widths): norm_values_correlated.append(v / width / norm) # Get covariance and correlation matrix for normalised cross section norm_cov_matrix = matrix(u.covariance_matrix(norm_values_correlated)) norm_corr_matrix = matrix(u.correlation_matrix(norm_values_correlated)) result = [(v.nominal_value, v.std_dev) for v in norm_values_correlated] # Get Covariance Matrix for input MC if not inputMC_covariance_matrix is None: inputMC_values_correlated = u.correlated_values( [v.nominal_value for v in values], inputMC_covariance_matrix.tolist()) inputMC_norm = sum(inputMC_values_correlated) inputMC_norm_values_correlated = [] for v, width in zip(inputMC_values_correlated, bin_widths): inputMC_norm_values_correlated.append(v / width / inputMC_norm) inputMC_norm_cov_matrix = matrix( u.covariance_matrix(inputMC_norm_values_correlated)) else: normalisation = 0 if normalise_to_one: normalisation = sum([ value / bin_width for value, bin_width in zip(values, bin_widths) ]) else: normalisation = sum(values) xsections = [(1 / bin_width) * value / normalisation for value, bin_width in zip(values, bin_widths)] result = [(xsection.nominal_value, xsection.std_dev) for xsection in xsections] return result, norm_cov_matrix, norm_corr_matrix, inputMC_norm_cov_matrix
def test_correlated_values(): "Correlated variables." u = uncertainties.ufloat((1, 0.1)) cov = uncertainties.covariance_matrix([u]) # "1" is used instead of u.nominal_value because # u.nominal_value might return a float. The idea is to force # the new variable u2 to be defined through an integer nominal # value: u2, = uncertainties.correlated_values([1], cov) expr = 2 * u2 # Calculations with u2 should be possible, like with u #################### # Covariances between output and input variables: x = ufloat((1, 0.1)) y = ufloat((2, 0.3)) z = -3 * x + y covs = uncertainties.covariance_matrix([x, y, z]) # "Inversion" of the covariance matrix: creation of new # variables: (x_new, y_new, z_new) = uncertainties.correlated_values( [x.nominal_value, y.nominal_value, z.nominal_value], covs, tags=["x", "y", "z"] ) # Even the uncertainties should be correctly reconstructed: assert matrices_close(numpy.array((x, y, z)), numpy.array((x_new, y_new, z_new))) # ... and the covariances too: assert matrices_close(numpy.array(covs), numpy.array(uncertainties.covariance_matrix([x_new, y_new, z_new]))) assert matrices_close(numpy.array([z_new]), numpy.array([-3 * x_new + y_new])) #################### # ... as well as functional relations: u = ufloat((1, 0.05)) v = ufloat((10, 0.1)) sum_value = u + 2 * v # Covariance matrices: cov_matrix = uncertainties.covariance_matrix([u, v, sum_value]) # Correlated variables can be constructed from a covariance matrix, if # NumPy is available: (u2, v2, sum2) = uncertainties.correlated_values([x.nominal_value for x in [u, v, sum_value]], cov_matrix) # matrices_close() is used instead of _numbers_close() because # it compares uncertainties too: assert matrices_close(numpy.array([0]), numpy.array([sum2 - (u2 + 2 * v2)]))
def calculate_xsection(inputs, bin_widths, luminosity, efficiency=1., covariance_matrix=None, inputMC_covariance_matrix=None): ''' BUG: this doesn't work unless the inputs are unfolded! inputs = list of value-error pairs luminosity = integrated luminosity of the measurement ''' abs_cov_matrix = None abs_corr_matrix = None inputMC_abs_cov_matrix = None result = [] add_result = result.append values = [u.ufloat(i[0], i[1]) for i in inputs] if not covariance_matrix is None: values_correlated = u.correlated_values( [v.nominal_value for v in values], covariance_matrix.tolist()) abs_values_correlated = [] # Loop over unfolded number of events with correlated uncertainties # And corresponding bin width # Calculate absolute cross section, with correctly correlated uncertainty for v, width in zip(values_correlated, bin_widths): abs_values_correlated.append(v / width / luminosity / efficiency) # Get covariance and correlation matrix for absolute cross section abs_cov_matrix = matrix(u.covariance_matrix(abs_values_correlated)) abs_corr_matrix = matrix(u.correlation_matrix(abs_values_correlated)) result = [(v.nominal_value, v.std_dev) for v in abs_values_correlated] # Get Covariance Matrix for input MC if not inputMC_covariance_matrix is None: inputMC_values_correlated = u.correlated_values( [v.nominal_value for v in values], inputMC_covariance_matrix.tolist()) inputMC_abs_values_correlated = [] for v, width in zip(inputMC_values_correlated, bin_widths): inputMC_abs_values_correlated.append(v / width / luminosity / efficiency) inputMC_abs_cov_matrix = matrix( u.covariance_matrix(inputMC_abs_values_correlated)) else: for valueAndErrors, binWidth in zip(inputs, bin_widths): value = valueAndErrors[0] error = valueAndErrors[1] xsection = value / (luminosity * efficiency * binWidth) xsection_error = error / (luminosity * efficiency * binWidth) add_result((xsection, xsection_error)) return result, abs_cov_matrix, abs_corr_matrix, inputMC_abs_cov_matrix
def linear_regression_u(x, y, uncert_x=None, uncert_y=None): """ Linear regression with uncertainties in both directions, returning UncertainVariables from the uncertainties package. Parameters ---------- x : array_like x-values y : array_like y-values uncert_x : array_like or None uncertainty of x-values uncert_y : array_like uncertainty of y-values Takes two arrays for x-values and y-values and optional two arrays of uncertainties. The uncertainty arguments are default to None, which is treated as a zero uncertainty in every value. Fits a function y=m*x+c to the values and returns the results for m and c as UncertainVariables from the package uncertainties (considering their correlation), and the chisquared of the fit. It returns a tuple containing: m, c, chisquared If both uncertainties are unequal zero, the calculation can not be performed analytically and the package scipy.odr is used. """ m,sigma_m,c,sigma_c,corr,chisq = linear_regression(x,y,uncert_x, uncert_y) cov = sigma_m * sigma_c * corr cov_mat = [[sigma_m**2, cov],[cov, sigma_c**2]] m2, c2 = uncertainties.correlated_values([m, c], cov_mat) return m2, c2, chisq
def set_parameters(self, pars, cov): """ Sets patameters and their covariance matrix Args: pars: dictionary cov: np.cov """ if len(pars) < len(self.param_names): raise ValueError("Provide all parameters!") if len(cov) < len(self.param_names) or len(cov[0]) < len( self.param_names): raise ValueError("Wrong dimensions of covariance matrix") self.params_C = cov self.params = {} for par_name in self.param_names: self.params[par_name] = pars[par_name] # set uparams once for all if self.param_names is None or self.params is None or self.params_C is None: return None par_values = uncertainties.correlated_values( [self.params[par_name] for par_name in self.param_names], self.params_C) self.uparams = {} for i in range(len(self.param_names)): self.uparams[self.param_names[i]] = par_values[i]
def auswerten(name, d, n, t, z, V_mol, eps, raw): d *= 1e-3 N = unp.uarray(n/t, np.sqrt(n)/t) - N_u if name=="Cu": tools.table((raw[0], raw[1], N), ("D/mm", "n", "(N-N_U)/\per\second"), "build/{}.tex".format(name), "Messdaten von {}.".format(name), "tab:daten{}".format(name), split=2, footer=r"$\Delta t = \SI{60}{s}$")#"(N-N_U)/\per\second" else: tools.table((raw[0], raw[1], raw[2], N), ("D/mm", "n", "\Delta t/s", "(N-N_U)/\per\second"), "build/{}.tex".format(name), "Messdaten von {}.".format(name), "tab:daten{}".format(name), split=2) mu = z * const.N_A / V_mol * 2 * np.pi * (const.e**2 / (4 * np.pi * const.epsilon_0 * const.m_e * const.c**2))**2 * ((1+eps)/eps**2 * ((2 * (1+eps))/(1+2*eps) - 1/eps * np.log(1+2*eps)) + 1/(2*eps) * np.log(1+ 2*eps) - (1+ 3*eps)/(1+2*eps)**2) params, pcov = curve_fit(fit, d, unp.nominal_values(N), sigma=unp.std_devs(N)) params_ = unc.correlated_values(params, pcov) print("{}: N(0) = {}, µ = {}, µ_com = {}".format(name, params_[0], -params_[1], mu)) sd = np.linspace(0, .07, 1000) valuesp = (fit(sd, *(unp.nominal_values(params_) + 10*unp.std_devs(params_)))).astype(float) valuesm = (fit(sd, *(unp.nominal_values(params_) - 10*unp.std_devs(params_)))).astype(float) #plt.xlim(0,7) plt.xlabel(r"$D/\si{mm}$") plt.ylabel(r"$(N-N_U)/\si{\per\second}$") plt.plot(1e3*sd, fit(sd, *params), 'b-', label="Fit") plt.fill_between(1e3*sd, valuesm, valuesp, facecolor='blue', alpha=0.125, edgecolor='none', label=r'$1\sigma$-Umgebung ($\times 10$)') plt.errorbar(1e3*d, unp.nominal_values(N), yerr=unp.std_devs(N), fmt='rx', label="Messdaten") plt.legend(loc='best') plt.yscale('linear') plt.tight_layout(pad=0) plt.savefig("build/{}.pdf".format(name)) plt.yscale('log') plt.savefig("build/{}_log.pdf".format(name)) plt.clf()
def FitModel(self, model, x, y): # Fitting the Model to the Data popt, pcov = curve_fit(model, x, y) params = popt errors = np.sqrt(np.diag(pcov)) ymodel = model(x, *params) DoF = len(x) - len(params) chiSq = round( self.ChiSq(y, ymodel), 1 - int(math.floor(math.log10(abs(self.ChiSq(y, ymodel))))) - 1) rChiSq = round(chiSq / DoF, 1 - int(math.floor(math.log10(abs(chiSq / DoF)))) - 1) a, b = unc.correlated_values(popt, pcov) xp = np.linspace(min(x), max(x), 1000) yp = a * xp + b nom = unp.nominal_values(yp) std = unp.std_devs(yp) # Calculating CI lpb, upb = self.predband(xp, x, y, params, model, conf=0.95) print( 'ChiSquared: {} \n Reduced ChiSquare: {} \n Fitted Parameters: {}, {} \n Parameter Errors: {}, {}' .format(chiSq, rChiSq, *np.round(params, 2), *np.round(errors, 2))) print('---------------------------------') confidence95 = [xp, nom - 1.96 * std, nom + 1.96 * std] confidenceInterval = [xp, lpb, upb] fit = [xp, ymodel, params] return fit, confidence95, confidenceInterval
def plot_lightyield_vs_dose(d, title=''): print(" Calculating D for " + title) plt.figure() y = d['Bi207AveragePE'] yerr = 0.7 # for some reason if I use 0.05*y, the plt.errorbar crashes with the contains N2 condition above...? x = d['Dose (Mrad)'] names = d['TileName'] print(d[[ 'TileName', 'SampleRun', 'Dose (Mrad)', 'Comment', 'DoseRate (rad/h)', 'Bi207AveragePE' ]]) #plt.plot(x, y, linewidth=2.0, linestyle='-', color='black', marker='o', markerfacecolor='r', markersize=5.2) plt.errorbar(x, y, yerr=yerr, linestyle='None', ecolor='k', marker='o', markerfacecolor='black', markersize=5.2, label='Tile') for i in range(0, len(names)): plt.text(x.values[i], y.values[i], names.values[i], fontsize=12, color='g') fitres = optimize.curve_fit(func_nexp, x, y, sigma=yerr, full_output=True, absolute_sigma=True) popt = fitres[0] pcov = fitres[1] # Need to use correlated errors to draw sigma bands a, b = unc.correlated_values(popt, pcov) print('Fit results: \na = {0:.3f} \nb = {1:.3f}'.format(a, b)) redchisq = (fitres[2]['fvec']** 2).sum() / (len(fitres[2]['fvec']) - len(popt)) print("chi2/Ndof = %6.3f" % redchisq) #print len(fitres[2]['fvec']) finex = np.arange(min(x), max(x), 0.2) plt.plot( finex, func_nexp(finex, *popt), 'b-', linewidth=2, label=r'Fit: $y={0:.2f}e^{{-x/{1:.2f}}}$'.format(*popt)) # fit line plt.legend(loc='upper right', frameon=False, framealpha=1, numpoints=1) plt.xscale('log') # make it log scale! plt.xlim([5.e-2, 20.]) plt.title(title) plt.ylabel(r"Bi207 Source [# PE]") plt.xlabel(r"Dose d [Mrad]") plt.grid() plt.savefig("SourcePELightYield_vs_Dose" + title + ".png") return a, b
def get_covariance_matrix(self): ''' Get the covariance matrix from all contributions https://root.cern.ch/doc/master/classTUnfoldDensity.html#a7f9335973b3c520e2a4311d2dd6f5579 ''' import uncertainties as u from numpy import array, matrix, zeros from numpy import sqrt as np_sqrt if self.unfolded_data is not None: # Calculate the covariance from TUnfold covariance = asrootpy( self.unfoldObject.GetEmatrixInput('Covariance')) # Reformat into a numpy matrix zs = list(covariance.z()) cov_matrix = matrix(zs) # Just the unfolded number of events inputs = hist_to_value_error_tuplelist(self.unfolded_data) nominal_values = [i[0] for i in inputs] # # Unfolded number of events in each bin # # With correlation between uncertainties values_correlated = u.correlated_values( nominal_values, cov_matrix.tolist() ) corr_matrix = matrix(u.correlation_matrix(values_correlated) ) return cov_matrix, corr_matrix else: print("Data has not been unfolded. Cannot return unfolding covariance matrix") return
def model_with_uncertainties(self): """Best fit model with uncertainties The parameters on the model will be in units ``keV``, ``cm``, and ``s``. Thus, when evaluating the model energies have to be passed in keV and the resulting flux will be in ``cm-2 s-1 keV-1``. The covariance matrix passed on initialization must also have these units. TODO: This is due to sherpa units, make more flexible TODO: Add to gammapy.spectrum.models This function uses the uncertainties packages as explained here https://pythonhosted.org/uncertainties/user_guide.html#use-of-a-covariance-matrix Examples -------- TODO """ import uncertainties pars = self.model.parameters # convert existing parameters to ufloats values = [pars[_].value for _ in self.covar_axis] ufloats = uncertainties.correlated_values(values, self.covariance) upars = dict(zip(self.covar_axis, ufloats)) # add parameters missing in covariance for name in pars: upars.setdefault(name, pars[name].value) return self.model.__class__(**upars)
def iterated_fit( f, X, Y, p0 = None, df = None, absolute_sigma = False, convergence_condition = DEFAULT_CONVERGENCE_CONDITION, max_iterations = DEFAULT_MAX_ITERATION, ): """ Iterated fit that propagates the errors on the X on the Y to account the x-axis error. If p0 is None is calculated with ucurve_fit without X error. If df is None it is used the numeric derivative from scipy. Not always work. """ if df is None: raise NotImplementedError("Numeric derivatived not implemented yet!") else: @wraps(df) def dmodel(x, *pars): return unumpy.nominal_values(df(x, *pars)) @wraps(f) def model(x, *pars): return unumpy.nominal_values(f(x, *pars)) x, ux = unpack_unarray(X) y, uy = unpack_unarray(Y) # Now we can work with normal numpy functions, without unceraties par, cov = curve_fit(model, x, y, sigma = uy, p0 = p0, absolute_sigma = absolute_sigma) while --max_iterations: dif_y = numpy.sqrt(uy**2 + (dmodel(x, *par) * ux)**2) npar, ncov = curve_fit( model, x, y, sigma = dif_y, p0 = par, absolute_sigma = absolute_sigma ) perror = numpy.abs(npar - par) / npar cerror = numpy.abs(ncov - cov) / ncov if (perror < convergence_condition).all() and (cerror < convergence_condition).all(): break par = npar cov = ncov if max_iterations == 0: raise Warning("iterated_fit termined because max_iterations was reached.") return unc.correlated_values(par, cov)
def get_estimates_from_bootstrap(params, daily_installs, observed_days, conversion_rate, free_trial_conversion, N): model = BGModel(penalizer_coef=0.01) Ts = reduce( lambda x, y: x + y, [[(observed_days - day) / 7] * int(math.floor(installs * conversion_rate * free_trial_conversion)) for day, installs in enumerate(daily_installs)]) Ts = filter(lambda x: x > 0, Ts) gen_data = gen.bgext_model(Ts, params['alpha'], params['beta']) data = comp.compress_bgext_data(gen_data) model.fit(frequency=data["frequency"], T=data["T"], N=data["N"], bootstrap_size=N) exs = [] for i in range(N): a = model.sampled_parameters[i]['alpha'] b = model.sampled_parameters[i]['beta'] cov = model.params_C [a, b] = uncertainties.correlated_values([a, b], cov) Ex = model.wrapped_static_expected_number_of_purchases_up_to_time( a, b, 52) + 1 if not math.isnan(Ex.n) and not math.isinf(Ex.n): print((i, Ex)) exs.append(Ex) return exs, model.expected_number_of_purchases_up_to_time(52) + 1
def model_with_uncertainties(self): """Best fit model with uncertainties The parameters on the model will have the units of the model attribute. The covariance matrix passed on initialization must also have these units. TODO: Add to gammapy.spectrum.models This function uses the uncertainties packages as explained here https://pythonhosted.org/uncertainties/user_guide.html#use-of-a-covariance-matrix Examples -------- TODO """ import uncertainties pars = self.model.parameters # convert existing parameters to ufloats values = [pars[_].value for _ in self.covar_axis] ufloats = uncertainties.correlated_values(values, self.covariance) upars = dict(zip(self.covar_axis, ufloats)) # add parameters missing in covariance for name in pars: upars.setdefault(name, pars[name].value) return self.model.__class__(**upars)
def model_with_uncertainties(self): """Best fit model with uncertainties The parameters on the model will have the units of the model attribute. The covariance matrix passed on initialization must also have these units. TODO: Add to gammapy.spectrum.models This function uses the uncertainties packages as explained here https://pythonhosted.org/uncertainties/user_guide.html#use-of-a-covariance-matrix Examples -------- TODO """ if self.covariance is None: raise ValueError('covariance matrix not set') import uncertainties pars = self.model.parameters # convert existing parameters to ufloats values = [pars[_].value for _ in self.covar_axis] ufloats = uncertainties.correlated_values(values, self.covariance) upars = dict(zip(self.covar_axis, ufloats)) # add parameters missing in covariance for par in pars.parameters: upars.setdefault(par.name, par.value) return self.model.__class__(**upars)
def plot_ratio(xvals, ratio, error, p, plotname, cov=None): result = "{:.2e} t^2 + {:.2e} t + {:.2e}".format(*p) result = result.replace("e-0", "e-") print("Fit result:", result) if plotname: result = re.sub(r"e(\S+?)(\s|$)", r" \\times {10}^{\1} ", result) fig, ax = plt.subplots() ax.errorbar(xvals, ratio, yerr=error, fmt="k.") ax.plot(xvals, np.polyval(p, xvals)) ax.text(0.1, 0.85, "${}$".format(result), transform=ax.transAxes, fontsize=16) if cov is not None and unc is not None: p_unc = unc.correlated_values(p, cov) y = np.polyval(p_unc, xvals) ax.fill_between( xvals, unumpy.nominal_values(y) - unumpy.std_devs(y), unumpy.nominal_values(y) + unumpy.std_devs(y), alpha=0.5, facecolor="b", ) fig.savefig(plotname)
def calc_KMCP(temp=25, sal=35, mode='dickson'): """ K2 of MCP dye. Either calculated using equation 8 of SOP 6b in Dickson, Sabine & Christian (2007, ISBN:1-897176-07-4), or calculated using in-house measurements of Tris-buffered artificial seawater. Parameters ---------- temp : array_like Temperature in Celcius sal : array_like Salinity mode : str 'dickson' or 'tris' Returns ------- array_like : K2 of MCP dye """ if mode == 'tris': p = un.correlated_values( [8.81873900e-12, -5.00996717e-11, 5.95759909e-09], [[5.72672924e-24, -2.56643258e-22, 2.80811298e-21], [-2.56643258e-22, 1.15587639e-20, -1.27159130e-19], [2.80811298e-21, -1.27159130e-19, 1.40773494e-18]]) return np.polyval(p, temp) elif mode == 'dickson': tempK = temp + 273.15 pK = 1245.69 / tempK + 3.8275 + 0.00211 * (35 - sal) return 10**-pK else: raise ValueError('Please specify `mode` as `tris` or `dickson`')
def main(): data = pd.read_csv( 'data/messwerte_2.csv', skiprows=(1, 2, 3, 4, 5), ) data['T'] = data['T'].apply(const.C2K) func = partial(linear, x0=data['t'].mean()) params, cov = curve_fit(func, data['t'], data['T']) a, b = unc.correlated_values(params, cov) print('Rate = {} Kelvin per minute'.format(a)) with open('build/rate.tex', 'w') as f: f.write(r'b = \SI{{{a.n:1.2f} +- {a.s:1.2f}}}{{\kelvin\per\minute}}'.format(a=a)) T_max = 289.95 * u.kelvin relaxation_time = ( (u.boltzmann_constant * T_max**2) / (0.526 * u.eV * a * u.kelvin / u.minute) * np.exp(-0.526 * u.eV / (u.boltzmann_constant * T_max)) ) print(relaxation_time.to(u.second)) t = np.linspace(0, 60, 2) plt.plot(t, func(t, *params), label='Ausgleichsgerade', color='gray') plt.plot(data['t'], data['T'], 'x', ms=3, label='Messwerte') plt.xlabel(r'$t \mathbin{/} \si{\minute}$') plt.ylabel(r'$T \mathbin{/} \si{\kelvin}$') plt.legend(loc='lower right') plt.tight_layout(pad=0) plt.savefig('build/rate.pdf')
def plot_confintervals(ax_obj, optpar, covpar, xarr, fcolor='grey'): """ Plots 3-Sigma Confidence Intervals in Fits of SN Parameters. Args: ax_obj : Axes object on which the confidence interval is to be plotted optpar : Optimised Parameters of the Fit covpar : Covariance Parameters of the Fit xarr : Array of X-Values over which confidence intervals are to be plotted fcolor : Fill color for the confidence intervals Returns: None """ coeff = unc.correlated_values(optpar, covpar) func = ls.legval(xarr, coeff) fit = unp.nominal_values(func) sigma = unp.std_devs(func) fitlow = fit - 3 * sigma fithigh = fit + 3 * sigma ax_obj.plot(xarr, fitlow, ls='-.', c='k', lw=0.7, alpha=0.3, label='_nolegend_') ax_obj.plot(xarr, fithigh, ls='-.', c='k', lw=0.7, alpha=0.3, label='_nolegend_') ax_obj.fill_between(xarr, fitlow, fithigh, facecolor=fcolor, alpha=0.3)
def Plot(x=[], y=[], limx=None, limy=None, xname='', yname='', name='', markername='Wertepaare', marker='rx', linear=True, linecolor='b-', linename='Ausgleichsgerade', xscale=1, yscale=1, save=True, Plot=True): uParams = None if(Plot): dx = abs(x[-1]-x[0]) if(limx==None): xplot = np.linspace((x[0]-0.05*dx)*xscale,(x[-1]+0.05*dx)*xscale,1000) else: xplot = np.linspace(limx[0]*xscale,limx[1]*xscale,1000) if(save): plt.cla() plt.clf() plt.errorbar(noms(x)*xscale, noms(y)*yscale, xerr=stds(x)*xscale, yerr=stds(y)*yscale, fmt=marker, markersize=6, elinewidth=0.5, capsize=2, capthick=0.5, ecolor='g',barsabove=True ,label=markername) if(linear == True): params, covar = curve_fit(Line, noms(x), noms(y)) uParams=uncertainties.correlated_values(params, covar) if(Plot): plt.plot(xplot*xscale, Line(xplot, *params)*yscale, linecolor, label=linename) if(Plot): if(limx==None): plt.xlim((x[0]-0.05*dx)*xscale,(x[-1]+0.05*dx)*xscale) else: plt.xlim(limx[0]*xscale,limx[1]*xscale) if(limy != None): plt.ylim(limy[0]*yscale,limy[1]*yscale) plt.xlabel(xname) plt.ylabel(yname) plt.legend(loc='best') plt.tight_layout(pad=0, h_pad=1.08, w_pad=1.08) if(save): plt.savefig('build/'+name+'.pdf') if(linear): return(uParams)
def integral(): x1 = uc.ufloat( 20 /2 *10**(-3) , 1*10**(-3)) x2 = uc.ufloat( 150/2 *10**(-3) , 1*10**(-3)) L = uc.ufloat( 175 *10**(-3) , 1*10**(-3)) l = uc.ufloat( 150 *10**(-3) , 1*10**(-3)) I = uc.ufloat(10 , 0.1) N = 3600 A = N / (2 *L * (x2-x1)) factor = (x2 * (sqrt( x2**2 + ((L+l)/2)**2)- sqrt( x2**2 + ((L-l)/2)**2) ) \ -x1 * (sqrt( x1**2 + ((L+l)/2)**2)- sqrt( x1**2 + ((L-l)/2)**2) ) \ + (((L+l)/2)**2* log((x2 + sqrt(((L+l)/2)**2 + x2**2))/ (x1 + sqrt(((L+l)/2)**2 + x1**2)) ) \ -((L-l)/(4))**2* log((x2 + sqrt(((L-l)/2)**2 + x2**2))/ (x1 + sqrt(((L-l)/2)**2 + x1**2)) ))) print(factor) print(A * factor) a = np.load(input_dir +"a_3.npy") I = np.load(input_dir + "i_3.npy") I_fit = np.linspace(min(I),max(I),100) S_a = 0.2 S_I = 0.05 weights = a*0 + 1/S_a p, cov= np.polyfit(I,a, 1, full=False, cov=True, w=weights) (p1, p2) = uc.correlated_values([p[0],p[1]], cov) print(p1 / (A*factor)) print(p1/2556/100 *oe *60)
def salt2mu_aberr(x1=None,x1err=None, c=None,cerr=None, mb=None,mberr=None, cov_x1_c=None,cov_x1_x0=None,cov_c_x0=None, alpha=None,beta=None, alphaerr=None,betaerr=None, M=None,x0=None,sigint=None,z=None,peczerr=0.0005): from uncertainties import ufloat, correlated_values, correlated_values_norm alphatmp,betatmp = alpha,beta alpha,beta = ufloat(alpha,alphaerr),ufloat(beta,betaerr) sf = -2.5/(x0*np.log(10.0)) cov_mb_c = cov_c_x0*sf cov_mb_x1 = cov_x1_x0*sf mu_out,muerr_out = np.array([]),np.array([]) for i in range(len(x1)): covmat = np.array([[mberr[i]**2.,cov_mb_x1[i],cov_mb_c[i]], [cov_mb_x1[i],x1err[i]**2.,cov_x1_c[i]], [cov_mb_c[i],cov_x1_c[i],cerr[i]**2.]]) mb_single,x1_single,c_single = correlated_values([mb[i],x1[i],c[i]],covmat) mu = mb_single + x1_single*alpha - beta*c_single + 19.36 if sigint: mu = mu + ufloat(0,sigint) zerr = peczerr*5.0/np.log(10)*(1.0+z[i])/(z[i]*(1.0+z[i]/2.0)) mu = mu + ufloat(0,np.sqrt(zerr**2. + 0.055**2.*z[i]**2.)) mu_out,muerr_out = np.append(mu_out,mu.n),np.append(muerr_out,mu.std_dev) return(mu_out,muerr_out)
def ucurve_fit(model, X, Y, p0=None, absolute_sigma=True, check_finite=True, bounds=(-numpy.inf, +numpy.inf), method=None, jac=None): x, ux = unpack_unarray(X) y, uy = unpack_unarray(Y) p, cov = curve_fit(model, x, y, sigma=uy, p0=p0, absolute_sigma=absolute_sigma, check_finite=check_finite, bounds=bounds, method=method, jac=jac) return unc.correlated_values(p, cov)
def _scp_error_curve_fit(f, x, y, *args, **kwargs): if not 'sigma' in kwargs: kwargs['sigma'] = unp.std_devs(y) if not 'absolute_sigma' in kwargs: kwargs['absolute_sigma'] = True result = scp.optimize.curve_fit(f, unp.nominal_values(x), unp.nominal_values(y), *args, **kwargs) return uc.correlated_values(*result)
def ucurve_fit(f, x, y, **kwargs): if np.any(unp.std_devs(y) == 0): sigma = None else: sigma = unp.std_devs(y) popt, pcov = scipy.optimize.curve_fit(f, x, unp.nominal_values(y), sigma=sigma, **kwargs) return unc.correlated_values(popt, pcov)
def MLS(model, d_model, X, Y, convergence_condition=1e-7, max_iterations=20, p0=None, absolute_sigma=True, 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) # Primo step curve fit par, cov = curve_fit(model, x, y, sigma=uy, p0=p0, absolute_sigma=absolute_sigma) # Procedimento iterato while --max_iterations: dif_y = numpy.sqrt(uy**2 + (d_model(x, *par) * ux)**2) npar, ncov = curve_fit(model, x, y, sigma=dif_y, p0=par, absolute_sigma=absolute_sigma) if verbose: print(npar) print(ncov) perror = numpy.abs(npar - par) / npar cerror = numpy.abs(ncov - cov) / ncov if (perror < convergence_condition).all() and ( cerror < convergence_condition).all(): if verbose: print("MLS Convergence") break par = npar cov = ncov return unc.correlated_values(npar, ncov)
def pH_from_spectrum(wavelength, spectrum, dye='BPB', sigma=None, temp=25., sal=35., **kwargs): pe = un.correlated_values(*unmix_spectra(wavelength, spectrum, dye, sigma)) F = pe[1] / pe[0] dyeK = dyes.K_handler(dye, temp=temp, sal=sal, **kwargs) return pH_from_F(F=F, K=dyeK)
def CdTe_Am(): detector_name = "CdTe" sample_name = "Am" suff = "_" + sample_name + "_" + detector_name npy_file = npy_dir + "spectra" + suff + ".npy" n = np.load(npy_file)[:500] s_n = np.sqrt(n) x = np.arange(len(n)) # only fit p0 = [250000, 250, 25] red = (x > 235) * (x < 270) n_red = n[red] x_red = x[red] s_n_red = s_n[red] fit, cov_fit = curve_fit(gauss, x_red, n_red, p0=p0, sigma=s_n_red) fit = np.abs(fit) fit_corr = uc.correlated_values(fit, cov_fit) s_fit = un.std_devs(fit_corr) # chi square n_d = 4 chi2 = np.sum(((gauss(x_red, *fit) - n_red) / s_n_red) ** 2 ) chi2_test = chi2/n_d fit_r, s_fit_r = err_round(fit, cov_fit) fit_both = np.array([fit_r, s_fit_r]) fit_both = np.reshape(fit_both.T, np.size(fit_both)) As[2], mus[2], sigmas[2] = fit s_As[2], s_mus[2], s_sigmas[2] = un.std_devs(fit_corr) all = np.concatenate((fit_both, [chi2_test]), axis=0) def plot_two_gauss(): fig1, ax1 = plt.subplots(1, 1) if not save_fig: fig1.suptitle("Detector: " + detector_name + "; sample: " + sample_name) plot1, = ax1.plot(x, n, '.', alpha=0.3) # histo plot ax1.errorbar(x, n, yerr=s_n, fmt=',', alpha=0.99, c=plot1.get_color(), errorevery=10) # errors of t are not changed! ax1.plot(x_red, gauss(x_red, *fit)) ax1.set_xlabel("channel") ax1.set_ylabel("counts") textstr = 'Results of fit:\n\ \\begin{eqnarray*}\ A &=& (%.0f \pm %.0f) \\\\ \ \mu &=& (%.1f \pm %.1f) \\\\ \ \sigma&=& (%.1f \pm %.1f) \\\\ \ \chi^2 / n_d &=& %.1f\ \end{eqnarray*}'%tuple(all) ax1.text(0.65, 0.95, textstr, transform=ax1.transAxes, va='top', bbox=props) if show_fig: fig1.show() if save_fig: file_name = "detector" + suff fig1.savefig(fig_dir + file_name + ".pdf") fig1.savefig(fig_dir + file_name + ".png") return 0 plot_two_gauss() return fit, s_fit
def poly_fit(x, y_e, x_range, p0): x_min, x_max = x_range mask = (x > x_min) * (x < x_max) x_fit = x[mask] y_fit = un.nominal_values(y_e[mask]) y_sigma = np.sqrt(un.std_devs(y_e[mask])) coeff, cov = curve_fit(poly, x_fit, y_fit, p0=p0, sigma=y_sigma, absolute_sigma=True) c = uc.correlated_values(coeff, cov) return c
def _fit_odr(datax, datay, function, params=None, yerr=None, xerr=None): model = Model(lambda p, x: function(x, *p)) realdata = RealData(datax, datay, sy=yerr, sx=xerr) odr = ODR(realdata, model, beta0=params) out = odr.run() # This was the old wrong way! Now use correct co. matrix through unc-package! # Note Issues on scipy odr and curve_fit, regarding different definitions/namings of standard deviation or error and covaraince matrix # https://github.com/scipy/scipy/issues/6842 # https://github.com/scipy/scipy/pull/12207 # https://stackoverflow.com/questions/62460399/comparison-of-curve-fit-and-scipy-odr-absolute-sigma return unc.correlated_values(out.beta, out.cov_beta)
def plot_fits(country, df, exp_popt, exp_pcov, log_popt, log_pcov, inflection_p_idx, case): plt.figure(figsize=(10, 5)) firstday = 0 lastday = df[country].dropna().shape[0] xdata = df['Day'][(df['Day'] >= firstday) & (df['Day'] < lastday)] ydata = df[country][(df['Day'] >= firstday) & (df['Day'] < lastday)] x = np.linspace(firstday, lastday + 10, 100) plt.plot(xdata, ydata, 'k.', label='data') plt.plot(x, exponential(x, *exp_popt), 'r-', label="Exponential fit") plt.plot(x, logistic(x, *log_popt), 'b-', label='Logistic fit') ae, be, ce = unc.correlated_values(exp_popt, exp_pcov) py = ae * unp.exp(be * x) + ce nom = unp.nominal_values(py) std = unp.std_devs(py) plt.fill_between(x, nom + 2 * std, nom - 2 * std, facecolor="red", alpha=.2) al, bl, cl, dl, el = unc.correlated_values(log_popt, log_pcov) py = al / (1 + bl * unp.exp(-cl * (x - dl))) + el nom = unp.nominal_values(py) std = unp.std_devs(py) plt.fill_between(x, nom + 2 * std, nom - 2 * std, facecolor="blue", alpha=.2) plt.plot(x[inflection_p_idx], logistic(x, *log_popt)[inflection_p_idx], 'oy', label='inflection point') plt.legend() if case == "confirmed": set_cases_labels() elif case == "deaths": set_deaths_labels() plt.ylim(-ydata.max() / 10., 2 * ydata.max()) plt.title(country, loc='center') plt.show()
def linleastsquares(functions, x_values, y_values): y = unp.nominal_values(y_values) Z = np.linalg.inv(unc.covariance_matrix(y_values)) A = np.column_stack([f(x_values) for f in functions]) invATA = np.linalg.inv(A.T @ Z @ A) params = invATA @ A.T @ Z @ y cov = invATA return unc.correlated_values(params.flat, cov)
def test_ucurve_fit_correlation(): def model(x, a, b): return numpy.sqrt(a * x + b) def umodel(x, a, b): return unumpy.sqrt(a * x + b) x = numpy.array([3., 41., 100.]) ux = x / 100. y = numpy.array([5., 15., 25.]) uy = numpy.array([[0.01, 0.001, 0.01], [0.001, 0.01, 0.02], [0.01, 0.02, 0.05]]) p, cov = curve_fit(model, x, y, sigma=uy) fitted1 = correlated_values(p, cov) X = unarray(x, ux) Y = correlated_values(y, uy) fitted2 = ucurve_fit(umodel, X, Y) assert(str(fitted1[0]) == str(fitted2[0])) assert(str(fitted1[1]) == str(fitted2[1]))
def parabola_fit(points): dims = points[0][0].shape[0] x = np.array([p[0] for p in points]) f = np.array([p[1] for p in points]) A = build_design_matrix(x, f) B = build_design_vector(f)[:, np.newaxis] # make column vector # Compute best-fit parabola coefficients using a singular value # decomposition. U, w, V = np.linalg.svd(A, full_matrices=False) V = V.T # Flip to convention used by Numerical Recipies inv_w = 1.0 / w inv_w[np.abs(w) < 1e-6] = 0.0 # Numpy version of Eq 15.4.17 from Numerical Recipies (C edition) coeffs = np.zeros(A.shape[1]) for i in range(len(coeffs)): coeffs += (np.dot(U[:, i], B[:, 0]) * inv_w[i]) * V[:, i] # Chi2 and probability for best fit and quadratic coefficents chi2_terms = np.dot(A, coeffs[:, np.newaxis]) - B chi2 = (chi2_terms**2).sum() ndf = len(points) - (1 + dims + dims * (dims + 1) / 2) prob = ROOT.TMath.Prob(chi2, ndf) # Covariance is from Eq 15.4.20 covariance = np.dot(V * inv_w**2, V.T) # Pack the coefficients into ufloats ufloat_coeffs = uncertainties.correlated_values(coeffs, covariance.tolist()) # Separate coefficients into a, b, and c a = ufloat_coeffs[0] b = ufloat_coeffs[1:dims + 1] c = np.zeros(shape=(dims, dims), dtype=object) index = dims + 1 for i in range(dims): for j in range(i, dims): c[i, j] = ufloat_coeffs[index] c[j, i] = ufloat_coeffs[index] if j != i: # We combined the redundant off-diagonal parts of c # matrix, but now we have to divide by two to # avoid double counting when c is used later c[i, j] /= 2.0 c[j, i] /= 2.0 index += 1 return a, np.array(b), c, chi2, prob
def parabola_fit(points): dims = points[0][0].shape[0] x = np.array([p[0] for p in points]) f = np.array([p[1] for p in points]) A = build_design_matrix(x, f) B = build_design_vector(f)[:,np.newaxis] # make column vector # Compute best-fit parabola coefficients using a singular value # decomposition. U, w, V = np.linalg.svd(A, full_matrices=False) V = V.T # Flip to convention used by Numerical Recipies inv_w = 1.0/w inv_w[np.abs(w) < 1e-6] = 0.0 # Numpy version of Eq 15.4.17 from Numerical Recipies (C edition) coeffs = np.zeros(A.shape[1]) for i in xrange(len(coeffs)): coeffs += (np.dot(U[:,i], B[:,0]) * inv_w[i]) * V[:,i] # Chi2 and probability for best fit and quadratic coefficents chi2_terms = np.dot(A, coeffs[:,np.newaxis]) - B chi2 = (chi2_terms**2).sum() ndf = len(points) - (1 + dims + dims * (dims + 1) / 2) prob = ROOT.TMath.Prob(chi2, ndf) # Covariance is from Eq 15.4.20 covariance = np.dot(V*inv_w**2, V.T) # Pack the coefficients into ufloats ufloat_coeffs = uncertainties.correlated_values(coeffs, covariance.tolist()) # Separate coefficients into a, b, and c a = ufloat_coeffs[0] b = ufloat_coeffs[1:dims+1] c = np.zeros(shape=(dims,dims), dtype=object) index = dims + 1 for i in xrange(dims): for j in xrange(i, dims): c[i,j] = ufloat_coeffs[index] c[j,i] = ufloat_coeffs[index] if j != i: # We combined the redundant off-diagonal parts of c # matrix, but now we have to divide by two to # avoid double counting when c is used later c[i,j] /= 2.0 c[j,i] /= 2.0 index += 1 return a, np.array(b), c, chi2, prob
def verdet_constant(): a = np.load(input_dir +"a_3.npy") I = np.load(input_dir + "i_3.npy") I_fit = np.linspace(min(I),max(I),100) S_a = 0.2 S_I = 0.05 weights = a*0 + 1/S_a p, cov= np.polyfit(I,a, 1, full=False, cov=True, w=weights) (p1, p2) = uc.correlated_values([p[0],p[1]], cov) print(p1/2556) print(p1/2556/100 *oe *60)
def to_uncertainties(self): """Convert to `uncertainties`_ objects. The `uncertainties`_ package makes it easy to do error propagation on derived quantities. See :ref:`analyse-error`. Returns ------- tuple (length ``n``) of ``uncertainties.core.AffineScalarFunc`` """ from uncertainties import correlated_values return correlated_values(self.mean, self.cov)
def fitSpectrum(self): K = K_handler(self.mode, self.data['temp'], self.sal) p, cov = unmix_spectra(self.data['wv'], self.data['absorption'], self.mode) self.p = un.correlated_values(p, cov) F = self.p[1] / self.p[0] pH = pH_from_F(F, K) self.storeResult(K, F, pH) self.updateFitGraph()
def two_bw_fit(x, y_e, x_range, p0, fit=True): x_min, x_max = x_range mask = (x > x_min) * (x < x_max) x_fit = x[mask] y_fit = un.nominal_values(y_e[mask]) y_sigma = np.sqrt(un.std_devs(y_e[mask])) if fit: coeff, cov = curve_fit(two_breit_wigner, x_fit, y_fit, p0=p0, sigma=y_sigma, absolute_sigma=True) c = uc.correlated_values(coeff, cov) fit_peak = two_breit_wigner(x_fit, *coeff) else: fit_peak = two_breit_wigner(x_fit, *p0) c = un.uarray(p0, [0, 0, 0, 0]) return x_fit, fit_peak, c
def auswerten(param): name, p0 = param I1, U1 = np.genfromtxt('daten/' + name + '1.txt', unpack=True) I2, U2 = np.genfromtxt('daten/' + name + '2.txt', unpack=True) popt1, pcov1 = curve_fit(cauchy, I1, U1, maxfev=10000000, p0=p0) popt2, pcov2 = curve_fit(cauchy, I2, U2, maxfev=10000000, p0=p0) x = np.linspace(0, 950, 1000) plt.xlim(0, 950) plt.xlabel(r'$I/\mathrm{mA}$') plt.ylabel(r'$U_B / \mathrm{mV}$') plt.plot(x, cauchy(x, *popt1), 'C0', label="Fit (mod. Cauchy/Lorentz)") plt.plot(x, cauchy(x, *popt2), 'C1', label="Fit (mod. Cauchy/Lorentz)") plt.plot(I1, U1, 'x', label='Daten 1') plt.plot(I2, U2, 'x', label='Daten 2') plt.legend(loc='best') plt.tight_layout(pad=0) plt.savefig('build/' + name + '.pdf') plt.close() param1 = unc.correlated_values(popt1, pcov1) param2 = unc.correlated_values(popt2, pcov2) return param1[2], param2[2]
def plot_fit(f, c, fit_result, xlimits, ylimits, disregard_correlation=False, color='gray', alpha=0.3, fill_band=True, npoints=100): """Plot the error butterfly. Errors are propagated using the uncertainties module. If disregard_correlation == True, the off-diagonal elements of the covariance matrix are set to 0 before propagating the errors. """ import matplotlib.pylab as plt import uncertainties # Choose equal-log x spacing logxlimits = np.log10(xlimits) logx = np.linspace(logxlimits[0], logxlimits[1], npoints) x = 10**logx popt = fit_result[0] pcov = fit_result[1] if disregard_correlation: pcov = set_off_diagonal_to_zero(pcov) y = f(popt, c, x) # Use uncertainties to compute an error band p_wu = uncertainties.correlated_values(popt, pcov) y_wu = f(p_wu, c, x) y_val = np.empty_like(y_wu) y_err = np.empty_like(y_wu) for i in range(y_wu.size): y_val[i] = y_wu[i].nominal_value y_err[i] = y_wu[i].std_dev # Need to clip values to frame so that no plotting artifacts occur y1 = np.maximum(y - y_err, ylimits[0]) y2 = np.minimum(y + y_err, ylimits[1]) # Plot error band if fill_band == True: plt.fill_between(x, y1, y2, color=color, alpha=alpha) else: plt.plot(x, y1, color=color, alpha=alpha) plt.plot(x, y2, color=color, alpha=alpha) # Plot best-fit spectrum plt.plot(x, y, color=color, alpha=alpha)
def fit_curve(df, country, status, start_date, end_date=None): """ Summary line. Extended description of function. Parameters: arg1 (int): Description of arg1 Returns: int: Description of return value """ # Select the data slc_date = slice(start_date, end_date) y_data = df.loc[(country, status), slc_date].groupby( CTRY_K).sum().values[0] # Generate a dummy x_data x_data = np.arange(0, y_data.shape[0]) # Set initial guesses for the curve fit x0_0 = x_data[np.where(y_data > 0)[0][0]] # Day of the first case a_0 = y_data.max() # Current number of cases b_0 = 0.1 # Arbitrary p0 = [x0_0, a_0, b_0] # Fit the curve popt, pcov = opt.curve_fit(sig, x_data, y_data, p0=p0) # Evaluate the curve fit to calculate the R² y_fit = sig(x_data, *popt) r2 = mt.r2_score(y_data, y_fit) # Estimate the uncertainty of the obtained coefficients x0, a, b, = unc.correlated_values(popt, pcov) # Store the fit information fit = { "r2": r2, "x0": x0, "a": a, "b": b, "coef": popt, "coef_cov": pcov, "y_data": y_data, "x_data": slc_date, } return x0, a, b, fit
def _fit_curvefit(datax, datay, function, params=None, yerr=None, **kwargs): try: pfit, pcov = \ optimize.curve_fit(function, datax, datay, p0=params, sigma=yerr, epsfcn=util.get("epsfcn", kwargs, 0.0001), **kwargs, maxfev=util.get("maxfev", kwargs, 10000)) except RuntimeError as e: debug.msg(str(e)) return params error = [] for i in range(len(pfit)): try: error.append(np.absolute(pcov[i][i])**0.5) except Exception as e: warnings.warn(str(e)) error.append(0.00) return unc.correlated_values(pfit, pcov)
def _ufloats(self): """Return dict of ufloats with covariance.""" from uncertainties import correlated_values values = [_.value for _ in self.parameters] try: # convert existing parameters to ufloats uarray = correlated_values(values, self.covariance) except np.linalg.LinAlgError: raise ValueError("Covariance matrix not set.") upars = {} for par, upar in zip(self.parameters, uarray): upars[par.name] = upar return upars
def plot_fit(f, c, fit_result, xlimits, ylimits, disregard_correlation=False, color='gray', alpha=0.3, fill_band=True, npoints=100): """Plot the error butterfly. Errors are propagated using the uncertainties module. If disregard_correlation == True, the off-diagonal elements of the covariance matrix are set to 0 before propagating the errors. """ import matplotlib.pylab as plt import uncertainties # Choose equal-log x spacing logxlimits = np.log10(xlimits) logx = np.linspace(logxlimits[0], logxlimits[1], npoints) x = 10 ** logx popt = fit_result[0] pcov = fit_result[1] print pcov if disregard_correlation: pcov = set_off_diagonal_to_zero(pcov) print pcov y = f(popt, c, x) # Use uncertainties to compute an error band p_wu = uncertainties.correlated_values(popt, pcov) y_wu = f(p_wu, c, x) y_val = np.empty_like(y_wu) y_err = np.empty_like(y_wu) for i in range(y_wu.size): y_val[i] = y_wu[i].nominal_value y_err[i] = y_wu[i].std_dev # Need to clip values to frame so that no plotting artifacts occur y1 = np.maximum(y - y_err, ylimits[0]) y2 = np.minimum(y + y_err, ylimits[1]) # Plot error band if fill_band == True: plt.fill_between(x, y1, y2, color=color, alpha=alpha) else: plt.plot(x, y1, color=color, alpha=alpha) plt.plot(x, y2, color=color, alpha=alpha) # Plot best-fit spectrum plt.plot(x, y, color=color, alpha=alpha)
def linleastsquares(functionlist, x_values, y_values): y = np.matrix(unp.nominal_values(y_values)).T Z = np.matrix(unc.covariance_matrix(y_values)).I # N rows vor every value, p columns for every function dim = (len(x_values), len(functionlist)) A = np.matrix(np.zeros(dim)) for i, func in enumerate(functionlist): A[:, i] = func(x_values)[:, np.newaxis] invATA = (A.T * Z * A).I params = invATA * A.T * Z * y cov = invATA return (np.array(unc.correlated_values(params.flat, np.array(cov))))
def translate_fit_parameters(popt, pcov, P_detector0_raw, T=300*u.K): """Take the fit parameters and covariances, and converts them to SI values and errors for f_c, k_c, Q. Also makes sure all values are positive.""" pvals = correlated_values(popt, pcov) punits = [u.nm**2 / u.Hz, u.Hz, u.dimensionless, u.nm**2 / u.Hz] scales = [P_detector0_raw, 1, 1, P_detector0_raw] def create_measurement(uncert_val, unit, scale): return (uncert_val.n * unit).plus_minus(uncert_val.s) * scale P_x0, f_c, Q, P_detector = [np.abs( create_measurement(uncert_val, unit, scale) ) for uncert_val, unit, scale in zip(pvals, punits, scales)] k_c = np.abs(calc_k_c(f_c, Q, P_x0, T)) return f_c, k_c, Q, P_detector
def ucurve_fit(f, x, y, **kwargs): ''' Uncertainties wrapper around curve_fit y can be a uarray with uncertainties and the parameters are returned as uncertainties.correlated_values ''' if np.any(unp.std_devs(y) == 0): sigma = None else: sigma = unp.std_devs(y) popt, pcov = scipy.optimize.curve_fit( f, x, unp.nominal_values(y), sigma=sigma, absolute_sigma=True, **kwargs, ) return unc.correlated_values(popt, pcov)
def calibration(detector_name, mu, s_mu): """ does a linear fit fit three points !!! """ def lin_func(x, a, b): return(a*x + b) fit_, cov_fit_ = curve_fit(lin_func, Es, mu, p0=None, sigma=s_mu) fit_corr_ = uc.correlated_values(fit_, cov_fit_) fit_corr = np.array([1 / fit_corr_[0], - fit_corr_[1] / fit_corr_[0]]) fit = un.nominal_values(fit_corr) cov_fit = uc.covariance_matrix(fit_corr) s_fit = un.std_devs(fit_corr) fit_r, s_fit_r = err_round(fit, cov_fit) fit_both = np.array([fit_r, s_fit_r]) fit_both = np.reshape(fit_both.T, np.size(fit_both)) fig1, ax1 = plt.subplots(1, 1) if not save_fig: fig1.suptitle("Calibration: " + detector_name) #plot1, = ax1.plot(mu, Es, '.', alpha=0.9) mu_grid = np.linspace(0, 700, 100) plot_fit, = ax1.plot(mu_grid, lin_func(mu_grid, *fit), alpha=0.5) ax1.errorbar(mu, Es, xerr=s_mu, fmt='.', alpha=0.99, c=plot_fit.get_color()) # errors of t are not changed! ax1.set_xlabel("channel") ax1.set_ylabel("Energy / keV") textstr = 'Results of linear fit for %s'%detector_name + ":\n" textstr += '\\begin{eqnarray*}\ E(\mu)&=& a \mu + E_0 \\\\ \ a &=& (%.4f \pm %.4f)\, \mathrm{keV / ch} \\\\ \ E_0 &=& (%.1f \pm %.1f)\, \mathrm{keV} \\\\ \ \end{eqnarray*}'%tuple(fit_both) ax1.text(0.1, 0.95, textstr, transform=ax1.transAxes, va='top', bbox=props) if show_fig: fig1.show() if save_fig: file_name = "detector_calibration_" + detector_name fig1.savefig(fig_dir + file_name + ".pdf") fig1.savefig(fig_dir + file_name + ".png") return fit_corr[0]
def main(): data = pd.read_csv("build/data_corrected.csv") data["invT"] = 1 / data["T"] data["j"] = data["I_corrected"] / A data["logj"] = np.log(data["j"]) fit_region = data.query("0.00345 < invT < 0.0037") func = partial(linear, x0=fit_region.invT.mean()) params, cov = curve_fit(func, fit_region["invT"], fit_region["logj"]) a, b = unc.correlated_values(params, cov) with open("build/fit_parameters_1.tex", "w") as f: f.write(r"a &= {}".format(SI(a, r"\kelvin"))) f.write(" \\\\ \n ") f.write(r"b &= {}".format(num(b))) with open("build/activation_work_1.tex", "w") as f: f.write("W = ") f.write(SI(-a * const.k, r"\joule")) f.write(" = ") f.write(SI(-a * const.k / const.e, r"\electronvolt")) px = np.linspace(3.335e-3, 3.7e-3, 2) plt.plot(px, func(px, a.n, b.n), label="Ausgleichsgerade") plt.plot(data.invT, data.logj, "+", ms=3, label="Nicht berücksichtigt", color="#949494") plt.plot(fit_region.invT, fit_region.logj, "+", ms=3, label="Fit-Region") plt.legend() plt.xlabel(r"$T^{-1} \mathrel{/} \si{\per\kelvin}$") plt.ylabel(r"$\ln(j \mathrel{/} \si{\pico\ampere})$") plt.xlim(0.0031, 0.0038) # plt.ylim(6, 8.1) plt.tight_layout(pad=0) plt.savefig("build/method1.pdf")
def plot_ratio(xvals, ratio, error, p, plotname, cov=None): result = "{:.2e} t^2 + {:.2e} t + {:.2e}".format(*p) result = result.replace('e-0','e-') print("Fit result:", result) if plotname: result = re.sub(r'e(\S+?)(\s|$)', r' \\times {10}^{\1} ', result) fig, ax = plt.subplots() ax.errorbar(xvals, ratio, yerr=error, fmt='k.') ax.plot(xvals, np.polyval(p, xvals)) ax.text(.1, .85, "${}$".format(result), transform=ax.transAxes, fontsize=16) if cov is not None and unc is not None: p_unc = unc.correlated_values(p, cov) y = np.polyval(p_unc, xvals) ax.fill_between(xvals, unumpy.nominal_values(y)-unumpy.std_devs(y), unumpy.nominal_values(y)+unumpy.std_devs(y), alpha=.5, facecolor='b') fig.savefig(plotname)
header=2, names=['t', 'U'], ) # embed() df['t'] = (df.t - df.ix[df['U'].idxmax()].t) plateau = df.query('t > -0.8e-6 & t < -0.1e-6') u_1 = ufloat(plateau['U'].mean(), plateau['U'].std()) ax_1.axhline(u_1.n, color='#ababab') ax_1.axhline(df['U'].max(), color='#ababab') reflection_factor = (df['U'].max() / u_1) R = - 50 * (1 + reflection_factor)/(1 - reflection_factor) print('resistance is {}'.format(R)) df_fit = df.query('t > 0.4e-6 & t < 3e-6').dropna() popt, pcov = opt.curve_fit(curve, df_fit['t'], df_fit['U'], [1, 1e-6, 1]) a_0, tau, u_0 = correlated_values(popt, pcov) print('tau is {}'.format(tau)) L = tau * (50 + R) print('L is {}'.format(L)) ax_1.plot(df['t']*1e6, df['U'], alpha=0.8, label='Gemessene Spannung') ax_1.plot(df_fit['t']*1e6, curve(df_fit['t'], a_0.n, tau.nominal_value, u_0.n), linewidth=2, label='Fit mit Exponentialfunktion') # ax_1.legend(loc='upper right') ax_1.set_ylabel(r'$U \mathbin{/} \si{\volt}$') ax_1.set_xlim(-2, 6) capacity_tex = '\SI{{{:.0f} \pm {:.0f}}}{{\\micro\\henry}}'.format(L.n * 1e6, L.s* 1e6) with open('build/k1a6_l.tex', 'w') as f: f.write(capacity_tex)
def leastsq(self, scale_covar=True, **kws): """ use Levenberg-Marquardt minimization to perform fit. This assumes that ModelParameters have been stored, and a function to minimize has been properly set up. This wraps scipy.optimize.leastsq, and keyword arguments are passed directly as options to scipy.optimize.leastsq When possible, this calculates the estimated uncertainties and variable correlations from the covariance matrix. writes outputs to many internal attributes, and returns True if fit was successful, False if not. """ # print 'RUNNING LEASTSQ' self.prepare_fit() lskws = dict(full_output=1, xtol=1.0e-7, ftol=1.0e-7, gtol=1.0e-7, maxfev=2000 * (self.nvarys + 1), Dfun=None) lskws.update(self.kws) lskws.update(kws) if lskws["Dfun"] is not None: self.jacfcn = lskws["Dfun"] lskws["Dfun"] = self.__jacobian lsout = scipy_leastsq(self.__residual, self.vars, **lskws) _best, _cov, infodict, errmsg, ier = lsout self.residual = resid = infodict["fvec"] self.ier = ier self.lmdif_message = errmsg self.message = "Fit succeeded." self.success = ier in [1, 2, 3, 4] if ier == 0: self.message = "Invalid Input Parameters." elif ier == 5: self.message = self.err_maxfev % lskws["maxfev"] else: self.message = "Tolerance seems to be too small." self.nfev = infodict["nfev"] self.ndata = len(resid) sum_sqr = (resid ** 2).sum() self.chisqr = sum_sqr self.nfree = self.ndata - self.nvarys self.redchi = sum_sqr / self.nfree # need to map _best values to params, then calculate the # grad for the variable parameters grad = ones_like(_best) vbest = ones_like(_best) for ivar, varname in enumerate(self.var_map): par = self.params[varname] grad[ivar] = par.scale_gradient(_best[ivar]) vbest[ivar] = par.value # modified from JJ Helmus' leastsqbound.py infodict["fjac"] = transpose(transpose(infodict["fjac"]) / take(grad, infodict["ipvt"] - 1)) rvec = dot(triu(transpose(infodict["fjac"])[: self.nvarys, :]), take(eye(self.nvarys), infodict["ipvt"] - 1, 0)) try: cov = inv(dot(transpose(rvec), rvec)) except (LinAlgError, ValueError): cov = None for par in self.params.values(): par.stderr, par.correl = 0, None self.covar = cov if cov is None: self.errorbars = False self.message = "%s. Could not estimate error-bars" else: self.errorbars = True if self.scale_covar: self.covar = cov = cov * sum_sqr / self.nfree for ivar, varname in enumerate(self.var_map): par = self.params[varname] par.stderr = sqrt(cov[ivar, ivar]) par.correl = {} for jvar, varn2 in enumerate(self.var_map): if jvar != ivar: par.correl[varn2] = cov[ivar, jvar] / (par.stderr * sqrt(cov[jvar, jvar])) # set uncertainties on constrained parameters. # Note that first we set all named params to # have values that include uncertainties, then # evaluate all constrained parameters, then set # the values back to the nominal values. if HAS_UNCERT and self.covar is not None: uvars = uncertainties.correlated_values(vbest, self.covar) for v, nam in zip(uvars, self.var_map): self.asteval.symtable[nam] = v for pname, par in self.params.items(): if hasattr(par, "ast"): try: out = self.asteval.run(par.ast) par.stderr = out.std_dev() except: pass for v, nam in zip(uvars, self.var_map): self.asteval.symtable[nam] = v.nominal_value for par in self.params.values(): if hasattr(par, "ast"): delattr(par, "ast") return self.success
labels = ['435.8 nm', '546.1 nm', '577.1 nm', '579.1 nm'] for i, x_range, p0, label in enum(x_ranges, p0s, labels): x_fit, fit_peak, c1 = bw_fit(x, y_e, x_range, p0, fit=True) x0s.append(c1[0]) As.append(c1[2]) lits = [435.8, 546.1, 577.1, 579.1] for i, x0, lit in enum(x0s, lits): print("\cellcolor{LightCyan}$%i$ & $%s$ & $%.1f$ \\\\"%( i+1, uc_str(x0), lit)) # Linear fit on peaks x0 = un.nominal_values(x0s) s_x0 = un.std_devs(x0s) lit_peaks = np.array([435.8, 546.1, 577.1, 579.1]) coeff_lin, cov_lin = curve_fit(linear, lit_peaks, x0, p0=None, sigma=np.sqrt(s_x0), absolute_sigma=True) c_lin = uc.correlated_values(coeff_lin, cov_lin) # Switch to lambda(x0) = lit_peak(x0) d_lin = np.array([1 / c_lin[0], -c_lin[1] / c_lin[0]]) np.save(npy_dir + 'ccd_calibration', d_lin) # Detection probability filename = "ccd_white_pol0" t, avg, x, y0, y_e0 = get_ccd_data(filename) filename = "ccd_white_pol45" t, avg, x, y45, y_e45 = get_ccd_data(filename) filename = "ccd_white_pol90" t, avg, x, y90, y_e90 = get_ccd_data(filename) # Correlation factor: corr0 = y45 / y0 corr90 = y45 / y90 # remove one outlier:
return np.arctan(f * 2 * np.pi * RC) phi_ = a / (1 / f) * 2 * np.pi A_ = U / U0 maketable( (f.astype(int), unp.nominal_values(U), unp.nominal_values(U0), A_, unp.nominal_values(a * 1000), phi_), "build/daten.txt", ) paramsa, pcova = curve_fit(A, f, unp.nominal_values(A_), p0=[1 / 742], sigma=unp.std_devs(A_), absolute_sigma=True) paramsb, pcovb = curve_fit( phi, f, unp.nominal_values(phi_), p0=[1 / 742], sigma=unp.std_devs(phi_), absolute_sigma=True ) paramsa_u = unc.correlated_values(paramsa, pcova) paramsb_u = unc.correlated_values(paramsb, pcovb) maketable([paramsa_u], "build/b1.txt", True) maketable([paramsb_u], "build/b2.txt", True) x = np.linspace(0.2, 10000, 100000) # plt.fill_between(x, A(x, paramsa_u[0].n - paramsa_u[0].s*10), A(x, paramsa_u[0].n + paramsa_u[0].s*10), facecolor='blue', alpha=0.25, edgecolor='none', label=r'$1\sigma$-Umgebung ($\times 10$)') plt.plot(x, A(x, *paramsa), "b-", label="Fit") plt.errorbar(f, unp.nominal_values(A_), yerr=unp.std_devs(A_), fmt="rx", label="Messdaten") plt.xlabel(r"$\nu/\si{\hertz}") plt.ylabel(r"$U/U0$") plt.xlim(4, 11000) plt.legend(loc="best") plt.xscale("log") plt.savefig("build/b1.pdf")
def autobk(energy, mu=None, group=None, rbkg=1, nknots=None, e0=None, edge_step=None, kmin=0, kmax=None, kweight=1, dk=0, win='hanning', k_std=None, chi_std=None, nfft=2048, kstep=0.05, pre_edge_kws=None, nclamp=4, clamp_lo=1, clamp_hi=1, calc_uncertainties=False, _larch=None, **kws): """Use Autobk algorithm to remove XAFS background Parameters: ----------- energy: 1-d array of x-ray energies, in eV, or group mu: 1-d array of mu(E) group: output group (and input group for e0 and edge_step). rbkg: distance (in Ang) for chi(R) above which the signal is ignored. Default = 1. e0: edge energy, in eV. If None, it will be determined. edge_step: edge step. If None, it will be determined. pre_edge_kws: keyword arguments to pass to pre_edge() nknots: number of knots in spline. If None, it will be determined. kmin: minimum k value [0] kmax: maximum k value [full data range]. kweight: k weight for FFT. [1] dk: FFT window window parameter. [0] win: FFT window function name. ['hanning'] nfft: array size to use for FFT [2048] kstep: k step size to use for FFT [0.05] k_std: optional k array for standard chi(k). chi_std: optional chi array for standard chi(k). nclamp: number of energy end-points for clamp [2] clamp_lo: weight of low-energy clamp [1] clamp_hi: weight of high-energy clamp [1] calc_uncertaintites: Flag to calculate uncertainties in mu_0(E) and chi(k) [False] Output arrays are written to the provided group. Follows the 'First Argument Group' convention. """ msg = _larch.writer.write if 'kw' in kws: kweight = kws.pop('kw') if len(kws) > 0: msg('Unrecognized a:rguments for autobk():\n') msg(' %s\n' % (', '.join(kws.keys()))) return energy, mu, group = parse_group_args(energy, members=('energy', 'mu'), defaults=(mu,), group=group, fcn_name='autobk') energy = remove_dups(energy) # if e0 or edge_step are not specified, get them, either from the # passed-in group or from running pre_edge() group = set_xafsGroup(group, _larch=_larch) if edge_step is None and isgroup(group, 'edge_step'): edge_step = group.edge_step if e0 is None and isgroup(group, 'e0'): e0 = group.e0 if e0 is None or edge_step is None: # need to run pre_edge: pre_kws = dict(nnorm=3, nvict=0, pre1=None, pre2=-50., norm1=100., norm2=None) if pre_edge_kws is not None: pre_kws.update(pre_edge_kws) pre_edge(energy, mu, group=group, _larch=_larch, **pre_kws) if e0 is None: e0 = group.e0 if edge_step is None: edge_step = group.edge_step if e0 is None or edge_step is None: msg('autobk() could not determine e0 or edge_step!: trying running pre_edge first\n') return # get array indices for rkbg and e0: irbkg, ie0 ie0 = index_of(energy, e0) rgrid = np.pi/(kstep*nfft) if rbkg < 2*rgrid: rbkg = 2*rgrid irbkg = int(1.01 + rbkg/rgrid) # save ungridded k (kraw) and grided k (kout) # and ftwin (*k-weighting) for FT in residual enpe = energy[ie0:] - e0 kraw = np.sign(enpe)*np.sqrt(ETOK*abs(enpe)) if kmax is None: kmax = max(kraw) else: kmax = max(0, min(max(kraw), kmax)) kout = kstep * np.arange(int(1.01+kmax/kstep), dtype='float64') iemax = min(len(energy), 2+index_of(energy, e0+kmax*kmax/ETOK)) - 1 # interpolate provided chi(k) onto the kout grid if chi_std is not None and k_std is not None: chi_std = np.interp(kout, k_std, chi_std) # pre-load FT window ftwin = kout**kweight * ftwindow(kout, xmin=kmin, xmax=kmax, window=win, dx=dk) # calc k-value and initial guess for y-values of spline params nspl = max(4, min(128, 2*int(rbkg*(kmax-kmin)/np.pi) + 1)) spl_y, spl_k, spl_e = np.zeros(nspl), np.zeros(nspl), np.zeros(nspl) for i in range(nspl): q = kmin + i*(kmax-kmin)/(nspl - 1) ik = index_nearest(kraw, q) i1 = min(len(kraw)-1, ik + 5) i2 = max(0, ik - 5) spl_k[i] = kraw[ik] spl_e[i] = energy[ik+ie0] spl_y[i] = (2*mu[ik+ie0] + mu[i1+ie0] + mu[i2+ie0] ) / 4.0 # get spline represention: knots, coefs, order=3 # coefs will be varied in fit. knots, coefs, order = splrep(spl_k, spl_y) # set fit parameters from initial coefficients params = Group() for i in range(len(coefs)): name = FMT_COEF % i p = Parameter(coefs[i], name=name, vary=i<len(spl_y)) p._getval() setattr(params, name, p) initbkg, initchi = spline_eval(kraw[:iemax-ie0+1], mu[ie0:iemax+1], knots, coefs, order, kout) # do fit fit = Minimizer(__resid, params, _larch=_larch, toler=1.e-4, fcn_kws = dict(ncoefs=len(coefs), chi_std=chi_std, knots=knots, order=order, kraw=kraw[:iemax-ie0+1], mu=mu[ie0:iemax+1], irbkg=irbkg, kout=kout, ftwin=ftwin, kweight=kweight, nfft=nfft, nclamp=nclamp, clamp_lo=clamp_lo, clamp_hi=clamp_hi)) fit.leastsq() # write final results coefs = [getattr(params, FMT_COEF % i) for i in range(len(coefs))] bkg, chi = spline_eval(kraw[:iemax-ie0+1], mu[ie0:iemax+1], knots, coefs, order, kout) obkg = np.copy(mu) obkg[ie0:ie0+len(bkg)] = bkg # outputs to group group = set_xafsGroup(group, _larch=_larch) group.bkg = obkg group.chie = (mu-obkg)/edge_step group.k = kout group.chi = chi/edge_step # now fill in 'autobk_details' group params.init_bkg = np.copy(mu) params.init_bkg[ie0:ie0+len(bkg)] = initbkg params.init_chi = initchi/edge_step params.knots_e = spl_e params.knots_y = np.array([coefs[i] for i in range(nspl)]) params.init_knots_y = spl_y params.nfev = params.fit_details.nfev params.kmin = kmin params.kmax = kmax group.autobk_details = params # uncertainties in mu0 and chi: fairly slow!! if HAS_UNCERTAIN and calc_uncertainties: vbest, vstd = [], [] for n in fit.var_names: par = getattr(params, n) vbest.append(par.value) vstd.append(par.stderr) uvars = uncertainties.correlated_values(vbest, params.covar) # uncertainty in bkg (aka mu0) # note that much of this is working around # limitations in the uncertainty package that make it # 1. take an argument list (not array) # 2. work on returned scalars (but not arrays) # 3. not handle kw args and *args well (so use # of global "index" is important here) nkx = iemax-ie0 + 1 def my_dsplev(*args): coefs = np.array(args) return splev(kraw[:nkx], [knots, coefs, order])[index] fdbkg = uncertainties.wrap(my_dsplev) dmu0 = [fdbkg(*uvars).std_dev() for index in range(len(bkg))] group.delta_bkg = np.zeros(len(mu)) group.delta_bkg[ie0:ie0+len(bkg)] = np.array(dmu0) # uncertainty in chi (see notes above) def my_dchi(*args): coefs = np.array(args) b,chi = spline_eval(kraw[:nkx], mu[ie0:iemax+1], knots, coefs, order, kout) return chi[index] fdchi = uncertainties.wrap(my_dchi) dchi = [fdchi(*uvars).std_dev() for index in range(len(kout))] group.delta_chi = np.array(dchi)/edge_step
save_tab = 1 plt.close('all') fig_dir = '../figures/' tab_dir = '../tables/' tab_name = "b_I" input_dir = "../data/" output_dir = input_dir colors = ['b', 'g', 'r', 'pink'] b, I = csv_to_npy(1) b2, I2 = csv_to_npy(2) # least square fit for b(I) (polyfit of deg = 1) i_max = 8 coeff, cov = np.polyfit(I[:i_max], b[:i_max], deg=1, cov=True) c = uc.correlated_values(coeff, cov) Is = np.linspace(0, 6, 100) f1 = open("coefficients.tex", "w+") var_names = ["p_0", "p_1"] la_coeff(f1, coeff, cov, var_names, additional_digits=2) f1.close() # plot B(I) with error bars fig1, ax1 = plt.subplots(1,1, figsize = (8.09,5)) b_error = 5 # uncertainty on B measurement, taken to be the last significant digit I_error = 0.01 # uncertainty in measuring the current I ax1.fill_between(Is, unv(np.polyval(c, Is)) + usd(np.polyval(c, Is)), unv(np.polyval(c, Is)) - usd(np.polyval(c, Is)), facecolor=colors[0], color=colors[0], alpha=0.2)
def f(a,b,c): return ( b * a ) + c parameters1, pcov = curve_fit(f, a, dx) a_plot = np.linspace(0.02,0.18) plt.xlim(0.02,0.18) plt.plot(a_plot,f(a_plot,*parameters1), 'g-', label='Fit') plt.plot(a,dx, 'rx', label='Messwerte') plt.xlabel(r'$4 x^3 - 12 L x^2 + 9 L^2 x - L^3 / m^3$') plt.ylabel(r'$D(x) / m$') plt.tight_layout() plt.legend(loc='best') plt.savefig('stab1_beidseitig_rechts.pdf') parameters1 = correlated_values(parameters1, pcov) for param1 in parameters1: print(param1) print() print(parameters1) print(pcov) #Ausgabe: #0.01207+/-0.00006 #(4.8+/-0.8)e-05 # #(0.012074401751652291+/-5.565018647514912e-05, 4.8030418172796886e-05+/-8.120504158407705e-06) #[[ 3.09694325e-09 -4.34868178e-10] # [ -4.34868178e-10 6.59425878e-11]] #Elasitzitätsmodul:
def gaussian_sum_moments(F, sigma, x, y, cov_matrix, shift=0.5): """Compute image moments with uncertainties for sum of Gaussians. The moments are computed analytically, the formulae are documented below. Calls ``uncertainties.correlated_values`` to propagate the errors. Parameters ---------- F : array Integral norms of the Gaussian components. sigmas : array Widths of the Gaussian components. x : array x positions of the Gaussian components. y : array y positions of the Gaussian components. cov_matrix : array Covariance matrix of the parameters. The columns have to follow the order: [sigma_1, x_1, y_1, F_1, sigma_2, x_2, y_2, F_2, ..., sigma_N, x_N, y_N, F_N] shift : float (default = 0.5) Depending on where the image values are given, the grid has to be shifted. If the values are given at the center of the pixel shift = 0.5. Returns ------- nominal_values : list List of image moment nominal values: [F_sum, x_sum, y_sum, x_sigma, y_sigma, sqrt(x_sigma * y_sigma)] All values are given in pixel coordinates. std_devs : list List of image moment standard deviations. Examples -------- A simple example for an image consisting of three Gaussians with zero covariance matrix: >>> import numpy as np >>> from gammapy.image.models.gauss import gaussian_sum_moments >>> cov_matrix = np.zeros((12, 12)) >>> F = [100, 200, 300] >>> sigma = [15, 10, 5] >>> x = [100, 120, 70] >>> y = [100, 90, 120] >>> nominal_values, std_devs = gaussian_sum_moments(F, sigma, x, y, cov_matrix) Notes ----- The 0th moment (total flux) is given by: .. math:: F_{\\Sigma} = \\int_{-\\infty}^{\\infty}f_{\\Sigma}(x, y)dx dy = \\sum_i^N F_i The 1st moments (position) are given by: .. math:: x_{\\Sigma} = \\frac{1}{F_{\\Sigma}} \\int_{-\\infty}^{\\infty}x f_{\\Sigma}(x, y)dx dy = \\frac{1}{F_{\\Sigma}}\\sum_i^N x_iF_i y_{\\Sigma} = \\frac{1}{F_{\\Sigma}} \\int_{-\\infty}^{\\infty}y f_{\\Sigma}(x, y)dx dy = \\frac{1}{F_{\\Sigma}}\\sum_i^N y_iF_i The 2nd moments (extension) are given by: .. math:: \\sigma_{\\Sigma_x}^2 = \\frac{1}{F_{\\Sigma}} \\sum_i^N F_i \\cdot (\\sigma_i^2 + x_i^2) - x_{\\Sigma}^2 \\sigma_{\\Sigma_y}^2 = \\frac{1}{F_{\\Sigma}} \\sum_i^N F_i \\cdot (\\sigma_i^2 + y_i^2) - y_{\\Sigma}^2 """ import uncertainties # Check input arrays if len(F) != len(sigma) or len(F) != len(x) or len(F) != len(x): raise Exception("Input arrays have to have the same size") # Order parameter values values = [] for i in range(len(F)): values += [sigma[i], x[i], y[i], F[i]] # Set up parameters with uncertainties parameter_list = uncertainties.correlated_values(values, cov_matrix) # Reorder parameters by splitting into 4-tuples parameters = list(zip(*[iter(parameter_list)] * 4)) def zero_moment(parameters): """0th moment of the sum of Gaussian components.""" F_sum = 0 for component in parameters: F_sum += component[3] return F_sum def first_moment(parameters, F_sum, shift): """1st moment of the sum of Gaussian components.""" x_sum, y_sum = 0, 0 for component in parameters: x_sum += (component[1] + shift) * component[3] y_sum += (component[2] + shift) * component[3] return x_sum / F_sum, y_sum / F_sum def second_moment(parameters, F_sum, x_sum, y_sum, shift): """2nd moment of the sum of Gaussian components.""" var_x_sum, var_y_sum = 0, 0 for p in parameters: var_x_sum += ((p[1] + shift) ** 2 + p[0] ** 2) * p[3] var_y_sum += ((p[2] + shift) ** 2 + p[0] ** 2) * p[3] return var_x_sum / F_sum - x_sum ** 2, var_y_sum / F_sum - y_sum ** 2 # Compute moments F_sum = zero_moment(parameters) x_sum, y_sum = first_moment(parameters, F_sum, shift) var_x_sum, var_y_sum = second_moment(parameters, F_sum, x_sum, y_sum, shift) # Return values and stddevs separately values = [F_sum, x_sum, y_sum, var_x_sum ** 0.5, var_y_sum ** 0.5, (var_x_sum * var_y_sum) ** 0.25] nominal_values = [_.nominal_value for _ in values] std_devs = [float(_.std_dev) for _ in values] return nominal_values, std_devs