testUnbinGausFit.cxx

Go to the documentation of this file.
00001 #include "TMath.h"
00002 #include "TSystem.h"
00003 #include "TRandom3.h"
00004 #include "TTree.h"
00005 #include "TROOT.h"
00006 
00007 #include "Fit/UnBinData.h"
00008 #include "Fit/Fitter.h"
00009 
00010 
00011 #include "Math/IParamFunction.h"
00012 #include "Math/WrappedTF1.h"
00013 #include "Math/WrappedMultiTF1.h"
00014 #include "Math/WrappedParamFunction.h"
00015 #include "Math/MultiDimParamFunctionAdapter.h"
00016 
00017 #include "TGraphErrors.h"
00018 
00019 #include "TStyle.h"
00020 
00021 
00022 #include "Math/DistFunc.h"
00023 
00024 #include <string>
00025 #include <iostream>
00026 
00027 #include "TStopwatch.h"
00028 
00029 #define DEBUG
00030 
00031 // test fit with many dimension
00032 
00033 const int N = 1; // 1d fit
00034 const int NGaus = 3; 
00035 const int NPar = 8; // sum of 3 gaussians 
00036 const std::string branchType = "x[1]/D";
00037 
00038 // for 8 core testing use 1M points
00039 const int NPoints = 100000;
00040 double truePar[NPar]; 
00041 double iniPar[NPar]; 
00042 const int nfit = 1;
00043 const int strategy = 0;
00044 
00045 double gausnorm(const double *x, const double *p) { 
00046 
00047    double invsig = 1./std::abs(p[1]); 
00048    double tmp = (x[0]-p[0]) * invsig; 
00049    const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 );
00050    return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; 
00051 }
00052 
00053 double gausSum(const double *x, const double *p) { 
00054 
00055    double f = gausnorm(x,p+2) + 
00056       p[0] *  gausnorm(x,p+4) + 
00057       p[1]  * gausnorm(x,p+6);
00058 
00059    double norm = 1. + p[0] + p[1]; 
00060    return f/norm; 
00061 }
00062 
00063 struct MINUIT2 {
00064    static std::string name() { return "Minuit2"; }
00065    static std::string name2() { return ""; }
00066 };
00067 
00068 // fill fit data structure 
00069 ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) { 
00070 
00071    // fill the unbin data set from a TTree
00072    ROOT::Fit::UnBinData * d = 0; 
00073 
00074    // for the large tree access directly the branches 
00075    d = new ROOT::Fit::UnBinData();
00076 
00077    unsigned int n = tree->GetEntries(); 
00078 #ifdef DEBUG
00079    std::cout << "number of unbin data is " << n << " of dim " << N << std::endl;
00080 #endif
00081    d->Initialize(n,N);
00082    TBranch * bx = tree->GetBranch("x"); 
00083    double vx[N];
00084    bx->SetAddress(vx); 
00085    std::vector<double>  m(N);
00086    for (int unsigned i = 0; i < n; ++i) {
00087      bx->GetEntry(i);
00088      d->Add(vx);
00089      for (int j = 0; j < N; ++j) 
00090        m[j] += vx[j];
00091    }
00092 
00093 #ifdef DEBUG
00094    std::cout << "average values of means :\n"; 
00095    for (int j = 0; j < N; ++j) 
00096      std::cout << m[j]/n << "  ";
00097    std::cout << "\n";
00098 #endif
00099    
00100    return d; 
00101 }
00102 
00103 
00104 // unbin fit
00105 
00106 typedef ROOT::Math::IParamMultiFunction Func;  
00107 template <class MinType, class T>
00108 int DoUnBinFit(T * tree, Func & func, bool debug = false ) {  
00109 
00110    ROOT::Fit::UnBinData * d  = FillUnBinData(tree );  
00111    // need to have done Tree->Draw() before fit
00112    //FillUnBinData(d,tree);
00113 
00114    std::cout << "Filled the fit data " << std::endl;
00115    //printData(d);
00116 
00117 #ifdef DEBUG
00118    std::cout << "data size type and size  is " << typeid(*d).name() <<  "   " << d->Size() << std::endl;
00119 #endif
00120          
00121          
00122 
00123    // create the fitter 
00124    //std::cout << "Fit parameter 2  " << f.Parameters()[2] << std::endl;
00125 
00126    ROOT::Fit::Fitter fitter; 
00127    fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str());
00128 
00129    if (debug) 
00130       fitter.Config().MinimizerOptions().SetPrintLevel(3);
00131    else 
00132       fitter.Config().MinimizerOptions().SetPrintLevel(1);
00133 
00134 
00135    // set tolerance 1 for tree to be same as in TTTreePlayer::UnBinFIt
00136    fitter.Config().MinimizerOptions().SetTolerance(0.01);
00137 
00138    // set strategy (0 to avoid MnHesse
00139    fitter.Config().MinimizerOptions().SetStrategy(strategy);
00140 
00141 
00142    // create the function
00143 
00144    fitter.SetFunction(func); 
00145    // need to set limits to constant term
00146    fitter.Config().ParSettings(0).SetLowerLimit(0.);
00147    fitter.Config().ParSettings(1).SetLowerLimit(0.);
00148 
00149    if (debug) 
00150      std::cout << "do fitting... " << std::endl;
00151 
00152    bool ret = fitter.Fit(*d);
00153    if (!ret) {
00154       std::cout << " Fit Failed " << std::endl;
00155       return -1; 
00156    }
00157    if (debug) 
00158       fitter.Result().Print(std::cout);    
00159 
00160    // check fit result
00161    double chi2 = 0;
00162    //if (fitter.Result().Value(0) <  0.5 ) { 
00163    for (int i = 0; i < NPar; ++i) { 
00164       double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) );
00165       chi2 += d*d; 
00166    }
00167 //}
00168 //    else { 
00169 //      double truePar2[NPar];
00170 //      truePar2[0] = 1.-truePar[0];
00171 //      truePar2[1] = truePar[3];
00172 //      truePar2[2] = truePar[4];
00173 //      truePar2[3] = truePar[1];
00174 //      truePar2[4] = truePar[2];
00175 //      for (int i = 0; i < N; ++i) { 
00176 //        double d = ( truePar2[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) );
00177 //        chi2 += d*d; 
00178 //      }
00179 //    }
00180    double prob = ROOT::Math::chisquared_cdf_c(chi2,NPar);
00181    int iret =  (prob < 1.0E-6) ? -1 : 0;
00182    if (iret != 0) {
00183       std::cout <<"Found difference in fitted values - chi2 = " << chi2 
00184                 << " prob = " << prob << std::endl;
00185       fitter.Result().Print(std::cout);    
00186    }
00187 
00188    delete d; 
00189 
00190    return iret; 
00191 
00192 }
00193 
00194 
00195 template <class MinType>
00196 int DoFit(TTree * tree, Func & func, bool debug = false ) {  
00197    return DoUnBinFit<MinType, TTree>(tree, func, debug); 
00198 }
00199 // template <class MinType>
00200 // int DoFit(TH1 * h1, Func & func, bool debug = false, bool copyData = false ) {  
00201 //    return DoBinFit<MinType, TH1>(h1, func, debug, copyData); 
00202 // }
00203 // template <class MinType>
00204 // int DoFit(TGraph * gr, Func & func, bool debug = false, bool copyData = false ) {  
00205 //    return DoBinFit<MinType, TGraph>(gr, func, debug, copyData); 
00206 // }
00207 
00208 template <class MinType, class FitObj>
00209 int FitUsingNewFitter(FitObj * fitobj, Func & func ) { 
00210 
00211    std::cout << "\n************************************************************\n"; 
00212    std::cout << "\tFit using new Fit::Fitter  " << typeid(*fitobj).name() << std::endl;
00213    std::cout << "\tMinimizer is " << MinType::name() << "  " << MinType::name2() << " func dim = " << func.NDim() << std::endl; 
00214 
00215    int iret = 0; 
00216    TStopwatch w; w.Start(); 
00217 
00218 #ifdef DEBUG
00219    std::cout << "initial Parameters " << iniPar << "  " << *iniPar << "   " <<  *(iniPar+1) << std::endl;
00220    func.SetParameters(iniPar);
00221    iret |= DoFit<MinType>(fitobj,func,true );
00222    if (iret != 0) {
00223      std::cout << "Test  failed " << std::endl;
00224    }
00225 
00226 #else
00227    for (int i = 0; i < nfit; ++i) { 
00228       func.SetParameters(iniPar);
00229       iret = DoFit<MinType>(fitobj,func, false);
00230       if (iret != 0) {
00231          std::cout << "Test failed " << std::endl;
00232          break; 
00233       }
00234    }
00235 #endif
00236    w.Stop(); 
00237    std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl;  
00238    std::cout << "\n************************************************************\n"; 
00239 
00240    return iret; 
00241 }
00242 
00243 
00244 int testNdimFit() { 
00245 
00246 
00247    std::cout << "\n\n************************************************************\n"; 
00248    std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM)  FIT\n";
00249    std::cout << "************************************************************\n"; 
00250 
00251    TTree t1("t2","a large Tree with gaussian variables");
00252    double  x[N];
00253    Int_t ev;
00254    t1.Branch("x",x,branchType.c_str());
00255    t1.Branch("ev",&ev,"ev/I");
00256 
00257    // generate the true parameters 
00258 //       for (int j = 0;  j < NGaus; ++j) {   
00259 //       double a = j+1;
00260 //          double mu = double(j)/NGaus; 
00261 //          double s  = 1.0 + double(j)/NGaus;  
00262 //          truePar[3*j] = a; 
00263 //          truePar[3*j+1] = mu; 
00264 //          truePar[3*j+2] = s;
00265 //       tot += a;
00266 //       }
00267    truePar[0] = 0.2; // % second  gaussian
00268    truePar[1] = 0.05;  // % third gaussian ampl
00269    truePar[2] = 0.;      // mean first gaussian 
00270    truePar[3] = 0.5;    // s1 
00271    truePar[4] = 0.;   // mean secon gauss
00272    truePar[5] = 1; 
00273    truePar[6] = -3;   // mean third gaus
00274    truePar[7] = 10; 
00275 
00276       
00277    
00278    //fill the tree
00279    TRandom3 r; 
00280    double norm = (1+truePar[0] + truePar[1] );
00281    double a = 1./norm; 
00282    double b = truePar[0]/ norm;
00283    double c = truePar[1]/ norm;
00284    assert(a+b+c == 1.);
00285    std::cout << " True amplitude gaussians " << a << "  " << b << "  " << c << std::endl;
00286    for (Int_t i=0;i<NPoints;i++) {
00287       for (int j = 0;  j < N; ++j) { 
00288         if (r.Rndm() < a ) { 
00289           double mu = truePar[2]; 
00290           double s  = truePar[3];  
00291           x[j] = r.Gaus(mu,s);
00292         }
00293         else if (r.Rndm() < b ) { 
00294           double mu = truePar[4]; 
00295           double s  = truePar[5];  
00296           x[j] = r.Gaus(mu,s);
00297         }
00298         else { 
00299           double mu = truePar[6]; 
00300           double s  = truePar[7];  
00301           x[j] = r.Gaus(mu,s);
00302         }
00303       }
00304 
00305       ev = i;
00306       t1.Fill();
00307       
00308    }
00309    //t1.Draw("x"); // to select fit variable 
00310 
00311    iniPar[0] = 0.5; 
00312    iniPar[1] = 0.05; 
00313    for (int i = 0; i <NGaus; ++i) {
00314       iniPar[2*i+2] = 0 ; 
00315       iniPar[2*i+3] = 1. + 4*i;
00316       std::cout << "inipar " << i << " = " << iniPar[2*i+2] << "  " << iniPar[2*i+3] << std::endl;
00317    }
00318 
00319    // use simply TF1 wrapper 
00320    //ROOT::Math::WrappedMultiTF1 f2(*f1); 
00321    ROOT::Math::WrappedParamFunction<> f2(&gausSum,1,NPar,iniPar); 
00322 
00323    int iret = 0; 
00324    iret |= FitUsingNewFitter<MINUIT2>(&t1,f2);
00325 
00326    return iret; 
00327 }
00328 
00329 int main() { 
00330   return testNdimFit();
00331 }

Generated on Tue Jul 5 14:37:14 2011 for ROOT_528-00b_version by  doxygen 1.5.1