#include "TF1.h"
#include "TH1D.h"
#include "TVirtualFitter.h"
#include "TMath.h"
#include <assert.h>
#include <iostream>
#include <cmath>
TF1 * fitFunc;
const int NPAR = 2;
double f(double * x, double * p) {
return p[1]*TMath::Sin( p[0] * x[0] );
}
#ifdef HAVE_OLD_ROOT_VERSION
double df_dPar(double * x, double * p) {
double grad[NPAR];
int ipar = int(p[0] );
assert (ipar >=0 && ipar < NPAR );
assert(fitFunc);
fitFunc->GradientPar(x, grad);
return grad[ipar];
}
double IntegralError(int npar, double * c, double * errPar,
double * covMatrix = 0) {
double err2 = 0;
for (int i = 0; i < npar; ++i) {
if (covMatrix == 0) {
err2 += c[i] * c[i] * errPar[i] * errPar[i];
} else {
double s = 0;
for (int j = 0; j < npar; ++j) {
s += covMatrix[i*npar + j] * c[j];
}
err2 += c[i] * s;
}
}
return TMath::Sqrt(err2);
}
#endif
void ErrorIntegral() {
fitFunc = new TF1("f",f,0,1,NPAR);
TH1D * h1 = new TH1D("h1","h1",50,0,1);
double par[NPAR] = { 3.14, 1.};
fitFunc->SetParameters(par);
h1->FillRandom("f",1000);
fitFunc->SetParameter(0,3.);
h1->Fit(fitFunc);
h1->Draw();
double integral = fitFunc->Integral(0,1);
TVirtualFitter * fitter = TVirtualFitter::GetFitter();
assert(fitter != 0);
double * covMatrix = fitter->GetCovarianceMatrix();
#ifdef HAVE_OLD_ROOT_VERSION
TF1 * deriv_par0 = new TF1("dfdp0",df_dPar,0,1,1);
deriv_par0->SetParameter(0,0);
TF1 * deriv_par1 = new TF1("dfdp1",df_dPar,0,1,1);
deriv_par1->SetParameter(0,1.);
double c[2];
c[0] = deriv_par0->Integral(0,1);
c[1] = deriv_par1->Integral(0,1);
double * epar = fitFunc->GetParErrors();
double sigma_integral_0 = IntegralError(2,c,epar);
double sigma_integral = IntegralError(2,c,epar,covMatrix);
#else
double sigma_integral = fitFunc->IntegralError(0,1);
#endif
std::cout << "Integral = " << integral << " +/- " << sigma_integral
<< std::endl;
double * p = fitFunc->GetParameters();
double ic = p[1]* (1-std::cos(p[0]) )/p[0];
double c0c = p[1] * (std::cos(p[0]) + p[0]*std::sin(p[0]) -1.)/p[0]/p[0];
double c1c = (1-std::cos(p[0]) )/p[0];
double sic = std::sqrt( c0c*c0c * covMatrix[0] + c1c*c1c * covMatrix[3]
+ 2.* c0c*c1c * covMatrix[1]);
if ( std::fabs(sigma_integral-sic) > 1.E-6*sic )
std::cout << " ERROR: test failed : different analytical integral : "
<< ic << " +/- " << sic << std::endl;
}
|
|