ErrorIntegral.C

Go to the documentation of this file.
00001 // Estimate the error in the integral of a fitted function 
00002 // taking into account the errors in the parameters resulting from the fit. 
00003 // The error is estimated also using the correlations values obtained from 
00004 // the fit
00005 //
00006 // run the macro doing: 
00007 //  .x ErrorIntegral.C
00008 // Author: Lorenzo Moneta
00009 
00010 #include "TF1.h"
00011 #include "TH1D.h"
00012 #include "TVirtualFitter.h"
00013 #include "TMath.h"
00014 #include <assert.h>
00015 #include <iostream>
00016 #include <cmath>
00017 
00018 //#define HAVE_OLD_ROOT_VERSION
00019 
00020 TF1 * fitFunc;  // fit function pointer 
00021 
00022 const int NPAR = 2; // number of function parameters;
00023 
00024 //____________________________________________________________________
00025 double f(double * x, double * p) { 
00026    // function used to fit the data
00027    return p[1]*TMath::Sin( p[0] * x[0] ); 
00028 }
00029 
00030 // when TF1::IntegralError was not available 
00031 
00032 #ifdef HAVE_OLD_ROOT_VERSION
00033 //____________________________________________________________________
00034 double df_dPar(double * x, double * p) { 
00035    // derivative of the function w.r..t parameters
00036    // use calculated derivatives from TF1::GradientPar
00037 
00038    double grad[NPAR]; 
00039    // p is used to specify for which parameter the derivative is computed 
00040    int ipar = int(p[0] ); 
00041    assert (ipar >=0 && ipar < NPAR );
00042 
00043    assert(fitFunc);
00044    fitFunc->GradientPar(x, grad);
00045 
00046    return grad[ipar]; 
00047 }
00048 
00049 //____________________________________________________________________
00050 double IntegralError(int npar, double * c, double * errPar, 
00051    double * covMatrix = 0) {   
00052 // calculate the error on the integral given the parameter error and 
00053 // the integrals of the gradient functions c[] 
00054 
00055    double err2 = 0; 
00056    for (int i = 0; i < npar; ++i) { 
00057       if (covMatrix == 0) { // assume error are uncorrelated
00058          err2 += c[i] * c[i] * errPar[i] * errPar[i]; 
00059       } else {
00060          double s = 0; 
00061          for (int j = 0; j < npar; ++j) {
00062             s += covMatrix[i*npar + j] * c[j]; 
00063          }
00064          err2 += c[i] * s; 
00065       }
00066    }
00067 
00068    return TMath::Sqrt(err2);
00069 }
00070 #endif
00071 
00072 //____________________________________________________________________
00073 void ErrorIntegral() { 
00074    fitFunc = new TF1("f",f,0,1,NPAR); 
00075    TH1D * h1     = new TH1D("h1","h1",50,0,1); 
00076 
00077    double  par[NPAR] = { 3.14, 1.}; 
00078    fitFunc->SetParameters(par);
00079 
00080    h1->FillRandom("f",1000); // fill histogram sampling fitFunc
00081    fitFunc->SetParameter(0,3.);  // vary a little the parameters
00082    h1->Fit(fitFunc);             // fit the histogram 
00083 
00084    h1->Draw();
00085 
00086    // calculate the integral 
00087    double integral = fitFunc->Integral(0,1);
00088 
00089    TVirtualFitter * fitter = TVirtualFitter::GetFitter();
00090    assert(fitter != 0);
00091    double * covMatrix = fitter->GetCovarianceMatrix(); 
00092 
00093 #ifdef HAVE_OLD_ROOT_VERSION
00094 
00095    // calculate now the error (needs the derivatives of the function 
00096    // w..r.t the parameters)
00097    TF1 * deriv_par0 = new TF1("dfdp0",df_dPar,0,1,1);
00098    deriv_par0->SetParameter(0,0);
00099 
00100    TF1 * deriv_par1 = new TF1("dfdp1",df_dPar,0,1,1);
00101    deriv_par1->SetParameter(0,1.);
00102 
00103    double c[2]; 
00104 
00105    c[0] = deriv_par0->Integral(0,1); 
00106    c[1] = deriv_par1->Integral(0,1); 
00107 
00108    double * epar = fitFunc->GetParErrors();
00109 
00110    // without correlations
00111    double sigma_integral_0 = IntegralError(2,c,epar);
00112 
00113 
00114 
00115    // with correlations
00116    double sigma_integral = IntegralError(2,c,epar,covMatrix);
00117 
00118 #else 
00119    
00120    // using new function in TF1 (from 12/6/2007) 
00121    double sigma_integral = fitFunc->IntegralError(0,1);
00122 
00123 #endif
00124 
00125    std::cout << "Integral = " << integral << " +/- " << sigma_integral 
00126              << std::endl;
00127 
00128    // estimated integral  and error analytically
00129 
00130    double * p = fitFunc->GetParameters();
00131    double ic  = p[1]* (1-std::cos(p[0]) )/p[0];
00132    double c0c = p[1] * (std::cos(p[0]) + p[0]*std::sin(p[0]) -1.)/p[0]/p[0];
00133    double c1c = (1-std::cos(p[0]) )/p[0];
00134 
00135    // estimated error with correlations
00136    double sic = std::sqrt( c0c*c0c * covMatrix[0] + c1c*c1c * covMatrix[3] 
00137       + 2.* c0c*c1c * covMatrix[1]); 
00138 
00139    if ( std::fabs(sigma_integral-sic) > 1.E-6*sic ) 
00140       std::cout << " ERROR: test failed : different analytical  integral : " 
00141                 << ic << " +/- " << sic << std::endl;
00142 }

Generated on Tue Jul 5 15:44:06 2011 for ROOT_528-00b_version by  doxygen 1.5.1