testRooFit.cxx

Go to the documentation of this file.
00001 // test fitting using also RooFit and new Fitter
00002 #include <RooAbsPdf.h>
00003 #include <RooRealVar.h>
00004 #include <RooArgSet.h>
00005 #include <RooGaussian.h>
00006 
00007 #include "RooDataSet.h"
00008 #include "RooRealVar.h"
00009 #include "RooGaussian.h"
00010 #include "RooGlobalFunc.h"
00011 #include "RooFitResult.h"
00012 #include "RooProdPdf.h"
00013 
00014 #include <TF1.h> 
00015 #include <TTree.h>
00016 #include <TRandom3.h>
00017 
00018 #include "TStopwatch.h"
00019 
00020 #include "Math/DistFunc.h"
00021 
00022 #include "Fit/UnBinData.h"
00023 #include "Fit/BinData.h"
00024 #include "Fit/Fitter.h"
00025 
00026 
00027 
00028 #include "WrapperRooPdf.h"
00029 
00030 #include <string>
00031 #include <iostream>
00032 #include <vector>
00033 #include <memory>
00034 
00035 #include "MinimizerTypes.h"
00036 
00037 #include "Math/WrappedParamFunction.h"
00038 #include <cmath>
00039 
00040 const int N = 1; // n must be greater than 1
00041 const int nfit = 1; 
00042 const int nEvents = 10000;
00043 double iniPar[2*N];
00044 
00045 
00046 typedef ROOT::Math::IParamMultiFunction Func;  
00047 
00048 void fillTree(TTree & t2) {
00049  
00050 
00051    double  x[N];
00052    Int_t ev;
00053    for (int j = 0; j < N; ++j) { 
00054       std::string xname = "x_" + ROOT::Math::Util::ToString(j);
00055       std::string xname2 = "x_" + ROOT::Math::Util::ToString(j) + "/D";
00056       t2.Branch(xname.c_str(),&x[j],xname2.c_str());
00057    }
00058    t2.Branch("ev",&ev,"ev/I");
00059    //fill the tree
00060    TRandom3 r; 
00061    for (Int_t i=0;i<nEvents;i++) {
00062       for (int j = 0;  j < N; ++j) { 
00063          double mu = double(j)/10.; 
00064          double s  = 1.0 + double(j)/10.;  
00065          x[j] = r.Gaus(mu,s);
00066       }
00067 
00068       ev = i;
00069       t2.Fill();      
00070    }   
00071 }
00072 
00073 void FillUnBinData(ROOT::Fit::UnBinData &d, TTree * tree ) { 
00074 
00075    // fill the unbin data set from a TTree
00076 
00077    // large tree 
00078    unsigned int n = tree->GetEntries(); 
00079    std::cout << "number of unbin data is " << n << " of dim " << N << std::endl;
00080    d.Initialize(n,N);
00081 
00082    double vx[N];
00083    for (int j = 0; j <N; ++j) { 
00084       std::string bname = "x_" + ROOT::Math::Util::ToString(j);
00085       TBranch * bx = tree->GetBranch(bname.c_str()); 
00086       bx->SetAddress(&vx[j]);
00087    }
00088  
00089    std::vector<double>  m(N);
00090    for (int unsigned i = 0; i < n; ++i) {
00091       tree->GetEntry(i);
00092       d.Add(vx);
00093       for (int j = 0; j < N; ++j) 
00094          m[j] += vx[j];
00095    }
00096    std::cout << "average values of means :\n"; 
00097    for (int j = 0; j < N; ++j) 
00098       std::cout << m[j]/n << "  ";
00099    std::cout << "\n";
00100       
00101    return; 
00102 
00103 }
00104 
00105 
00106 
00107 // class describing product of gaussian pdf
00108 class MultiGaussRooPdf { 
00109    
00110  public: 
00111 
00112    // create all pdf 
00113    MultiGaussRooPdf(unsigned int n) : 
00114       x(n), m(n), s(n), g(n), pdf(n) 
00115       { 
00116          //assert(n >= 2);
00117 
00118          // create the gaussians
00119          for (unsigned int j = 0; j < n; ++j) { 
00120             
00121             std::string xname = "x_" + ROOT::Math::Util::ToString(j);
00122             x[j] = new RooRealVar(xname.c_str(),xname.c_str(),-10000,10000) ;
00123             
00124             std::string mname = "m_" + ROOT::Math::Util::ToString(j);
00125             std::string sname = "s_" + ROOT::Math::Util::ToString(j);
00126             
00127             
00128 //             m[j] = new RooRealVar(mname.c_str(),mname.c_str(),iniPar[2*j],-10000,10000) ;  
00129 //             s[j] = new RooRealVar(sname.c_str(),sname.c_str(),iniPar[2*j+1],-10000,10000) ;  
00130             m[j] = new RooRealVar(mname.c_str(),mname.c_str(),iniPar[2*j],-10,10) ;  
00131             s[j] = new RooRealVar(sname.c_str(),sname.c_str(),iniPar[2*j+1],-10,10) ;  
00132             
00133             std::string gname = "g_" + ROOT::Math::Util::ToString(j);
00134             g[j] = new RooGaussian(gname.c_str(),"gauss(x,mean,sigma)",*x[j],*m[j],*s[j]);
00135             
00136             std::string pname = "prod_" + ROOT::Math::Util::ToString(j);
00137             if (j == 1) { 
00138                pdf[1] = new RooProdPdf(pname.c_str(),pname.c_str(),RooArgSet(*g[1],*g[0]) );
00139             }
00140             else if (j > 1) { 
00141                pdf[j] = new RooProdPdf(pname.c_str(),pname.c_str(),RooArgSet(*g[j],*pdf[j-1]) );
00142             }
00143             else if (j == 0) 
00144                pdf[0] = g[0];  
00145          } 
00146 
00147         
00148    }
00149 
00150    RooAbsPdf & getPdf() { return *pdf.back(); }
00151 
00152    std::auto_ptr<RooArgSet>  getVars() { 
00153       std::auto_ptr<RooArgSet> vars(new RooArgSet() );
00154       for (unsigned int i = 0; i < x.size(); ++i) 
00155          vars->add(*x[i]);
00156       return vars;
00157    }
00158 
00159    ~MultiGaussRooPdf() { 
00160       // free
00161       int n = x.size();
00162       for (int j = 0; j < n; ++j) { 
00163          delete x[j]; 
00164          delete m[j]; 
00165          delete s[j]; 
00166          delete g[j];
00167          delete pdf[j]; 
00168       }
00169    }
00170 
00171    private:
00172 
00173       std::vector<RooRealVar *> x;
00174       std::vector<RooRealVar *> m;
00175       std::vector<RooRealVar *> s;
00176 
00177       std::vector<RooAbsPdf *> g;
00178       std::vector<RooAbsPdf *> pdf;
00179    
00180 };
00181 
00182 
00183 //unbinned roo fit (large tree)
00184 int  FitUsingRooFit(TTree & tree, RooAbsPdf & pdf, RooArgSet & xvars) { 
00185 
00186    int iret = 0; 
00187    std::cout << "\n************************************************************\n"; 
00188    std::cout << "\tFit using RooFit (Likelihood Fit) on " << pdf.GetName() << std::endl;
00189 
00190 
00191    
00192    TStopwatch w; 
00193    w.Start(); 
00194 
00195    for (int i = 0; i < nfit; ++i) { 
00196 
00197       RooDataSet data("unbindata","unbin dataset with x",&tree,xvars) ;       
00198 
00199          
00200      
00201 #ifdef DEBUG
00202       int level = 3; 
00203       std::cout << "num entries = " << data.numEntries() << std::endl;
00204       bool save = true; 
00205       (pdf[N-1]->getVariables())->Print("v"); // print the parameters 
00206       std::cout << "\n\nDo the fit now \n\n"; 
00207 #else 
00208       int level = 1; 
00209       bool save = false; 
00210 #endif
00211 
00212 #ifndef _WIN32 // until a bug 30762 is fixed
00213       RooFitResult * result = pdf.fitTo(data, RooFit::Minos(0), RooFit::Hesse(0) , RooFit::PrintLevel(level), RooFit::Save(save) );
00214 #else
00215       RooFitResult * result = pdf.fitTo(data );
00216 #endif
00217 
00218 #ifdef DEBUG
00219       assert(result != 0); 
00220       std::cout << " Roofit status " << result->status() << std::endl; 
00221       result->Print();
00222 #endif
00223       iret |= (result == 0);
00224 
00225    }
00226 
00227    w.Stop(); 
00228 
00229    RooArgSet * params = pdf.getParameters(xvars); 
00230    params->Print("v");
00231    delete params; 
00232 
00233 
00234    std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl;  
00235    std::cout << "\n************************************************************\n"; 
00236    return iret; 
00237 }
00238 
00239 
00240 // unbin fit
00241 template <class MinType>
00242 int DoFit(TTree * tree, Func & func, bool debug = false, bool = false ) {  
00243 
00244    ROOT::Fit::UnBinData d; 
00245    // need to have done Tree->Draw() before fit
00246    FillUnBinData(d,tree);
00247 
00248    //std::cout << "Fit parameter 2  " << f.Parameters()[2] << std::endl;
00249 
00250    ROOT::Fit::Fitter fitter; 
00251    fitter.Config().MinimizerOptions().SetPrintLevel(2);
00252    fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str());
00253    fitter.Config().MinimizerOptions().SetTolerance(1.); // to be consistent with RooFit
00254 
00255    if (debug) 
00256       fitter.Config().MinimizerOptions().SetPrintLevel(3);
00257 
00258 
00259    // create the function
00260 
00261    fitter.SetFunction(func); 
00262    // need to fix param 0 , normalization in the unbinned fits
00263    //fitter.Config().ParSettings(0).Fix();
00264 
00265    bool ret = fitter.Fit(d);
00266    if (!ret) {
00267       std::cout << " Fit Failed " << std::endl;
00268       return -1; 
00269    }
00270    if (debug) 
00271       fitter.Result().Print(std::cout);    
00272    return 0; 
00273 
00274 }
00275 
00276 template <class MinType, class FitObj>
00277 int FitUsingNewFitter(FitObj * fitobj, Func & func, bool useGrad=false) { 
00278 
00279    std::cout << "\n************************************************************\n"; 
00280    std::cout << "\tFit using new Fit::Fitter\n";
00281    std::cout << "\tMinimizer is " << MinType::name() << "  " << MinType::name2() << std::endl; 
00282 
00283    int iret = 0; 
00284    TStopwatch w; w.Start(); 
00285 
00286 #ifdef DEBUG
00287    func.SetParameters(iniPar);
00288    iret |= DoFit<MinType>(fitobj,func,true, useGrad);
00289 
00290 #else
00291    for (int i = 0; i < nfit; ++i) { 
00292       func.SetParameters(iniPar);
00293       iret = DoFit<MinType>(fitobj,func, false, useGrad);
00294       if (iret != 0) break; 
00295    }
00296 #endif
00297    w.Stop(); 
00298    std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl;  
00299    std::cout << "\n************************************************************\n"; 
00300 
00301    return iret; 
00302 }
00303 
00304 double gausnorm(const double *x, const double *p) { 
00305    //return p[0]*TMath::Gaus(x[0],p[1],p[2]);
00306    double invsig = 1./p[1]; 
00307    double tmp = (x[0]-p[0]) * invsig; 
00308    const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 );
00309    return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; 
00310 }
00311 
00312 
00313 
00314 int main() { 
00315 
00316    TTree tree("t","a large Tree with many gaussian variables");
00317    fillTree(tree);
00318 
00319    // set initial parameters 
00320    for (int i = 0; i < N; ++i) { 
00321       iniPar[2*i] = 1;  
00322       iniPar[2*i+1] = 1;  
00323    }
00324 
00325    // start counting t he time
00326    MultiGaussRooPdf multipdf(N);
00327    RooAbsPdf & pdf = multipdf.getPdf();
00328 
00329    std::auto_ptr<RooArgSet> xvars = multipdf.getVars();   
00330 
00331    WrapperRooPdf  wpdf( &pdf, *xvars ); 
00332 
00333 
00334    std::cout << "ndim " << wpdf.NDim() << std::endl;
00335    std::cout << "npar " << wpdf.NPar() << std::endl;
00336    for (unsigned int i = 0; i < wpdf.NPar(); ++i) 
00337       std::cout << " par " << i << " is " <<  wpdf.ParameterName(i) << " value " << wpdf.Parameters()[i] << std::endl;
00338 
00339 
00340    FitUsingNewFitter<TMINUIT>(&tree,wpdf);
00341 
00342    // reset pdf original values 
00343    wpdf.SetParameters(iniPar);
00344    
00345    FitUsingRooFit(tree,pdf, *xvars);
00346 
00347    // in case of N = 1 do also a simple gauss fit
00348    // using TF1 gausN
00349    if (N == 1) { 
00350       ROOT::Math::WrappedParamFunction<> gausn(&gausnorm,2,iniPar,iniPar+1);       
00351       FitUsingNewFitter<TMINUIT>(&tree,gausn);
00352    }
00353 
00354 
00355 
00356 }

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