26 int gDefMaxPts = ROOT::Math::IntegratorMultiDimOptions::DefaultNCalls();
38 double IntegralError(TF1 * func, Int_t ndim,
const double * a,
const double * b,
const double * params,
const double * covmat,
double epsilon) {
48 bool onedim = ndim == 1;
49 int npar = func->GetNpar();
51 Error(
"TF1Helper",
"Function has no parameters");
55 std::vector<double> oldParams;
58 oldParams.resize(npar);
59 std::copy(func->GetParameters(), func->GetParameters()+npar, oldParams.begin());
60 func->SetParameters(params);
64 TMatrixDSym covMatrix(npar);
67 TVirtualFitter * vfitter = TVirtualFitter::GetFitter();
68 TBackCompFitter * fitter =
dynamic_cast<TBackCompFitter*
> (vfitter);
70 Error(
"TF1Helper::IntegralError",
"No existing fitter can be used for computing the integral error");
74 if (fitter->GetNumberTotalParameters() != npar) {
75 Error(
"TF1Helper::IntegralError",
"Last used fitter is not compatible with the current TF1");
79 if (
int(fitter->GetFitResult().Errors().size()) != npar) {
80 Warning(
"TF1Helper::INtegralError",
"Last used fitter does no provide parameter errors and a covariance matrix");
85 for (
int i = 0; i < npar; ++i) {
86 if (fitter->GetParameter(i) != func->GetParameter(i) ) {
87 Error(
"TF1Helper::IntegralError",
"Last used Fitter has different parameter values");
93 fitter->GetFitResult().GetCovarianceMatrix(covMatrix);
96 covMatrix.Use(npar,covmat);
104 if (epsilon <= 0) epsilon = 1.e7*ROOT::Math::IntegratorMultiDimOptions::DefaultRelTolerance();
106 double numError2 = 0;
107 for (
int i=0; i < npar; ++i) {
110 double epsrel = TMath::Min(0.1, epsilon / std::abs(func->GetParameter(i)) );
111 double epsabs = epsrel;
117 if (covMatrix(i,i) > 0 ) {
118 TF1 gradFunc(
"gradFunc",TGradientParFunction(i,func),0,0,0);
120 integral = gradFunc.IntegralOneDim(*a,*b,epsrel,epsabs, error);
126 int maxpts = ROOT::Math::IntegratorMultiDimOptions::DefaultNCalls();
127 if (maxpts == gDefMaxPts) maxpts = 10*gDefMaxPts;
128 integral = gradFunc.IntegralMultiple(ndim,a,b,maxpts,epsrel,epsabs,relerr,nfnevl,ifail);
130 error = relerr*std::abs(integral);
138 numError2 += covMatrix(i,i)*covMatrix(i,i) * integral * integral * error * error;
140 double err2 = covMatrix.Similarity(ig);
141 double result = sqrt(err2);
142 double numError = sqrt( numError2/sqrt(err2) );
145 if ( result > epsilon && numError > 2*epsilon*result )
146 Warning(
"TF1Helper::IntegralError",
"numerical error from integration is too large. Integral error = %g +/- %g - eps = %g",result,numError,epsilon);
149 if (!oldParams.empty()) {
150 func->SetParameters(&oldParams.front());
155 return std::sqrt(err2);