testNdimFit.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 = 10; 
00034 const std::string branchType = "x[10]/D";
00035 const int NPoints = 100000;
00036 
00037 // const int N = 50; 
00038 // const std::string branchType = "x[50]/D";
00039 // const int NPoints = 10000;
00040 
00041 
00042 
00043 double truePar[2*N]; 
00044 double iniPar[2*N]; 
00045 const int nfit = 1;
00046 const int strategy = 0;
00047 
00048 double gausnorm(const double *x, const double *p) { 
00049 
00050    double invsig = 1./p[1]; 
00051    double tmp = (x[0]-p[0]) * invsig; 
00052    const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 );
00053    return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig; 
00054 }
00055 
00056 double gausnormN(const double *x, const double *p) { 
00057    double f = 1; 
00058    for (int i = 0; i < N; ++i) 
00059       f *= gausnorm(x+i,p+2*i);
00060 
00061    return f; 
00062 }
00063 
00064 struct MINUIT2 {
00065    static std::string name() { return "Minuit2"; }
00066    static std::string name2() { return ""; }
00067 };
00068 
00069 // fill fit data structure 
00070 ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) { 
00071 
00072    // fill the unbin data set from a TTree
00073    ROOT::Fit::UnBinData * d = 0; 
00074 
00075    // for the large tree access directly the branches 
00076    d = new ROOT::Fit::UnBinData();
00077 
00078    unsigned int n = tree->GetEntries(); 
00079 #ifdef DEBUG
00080    std::cout << "number of unbin data is " << n << " of dim " << N << std::endl;
00081 #endif
00082    d->Initialize(n,N);
00083    TBranch * bx = tree->GetBranch("x"); 
00084    double vx[N];
00085    bx->SetAddress(vx); 
00086    std::vector<double>  m(N);
00087    for (int unsigned i = 0; i < n; ++i) {
00088      bx->GetEntry(i);
00089      d->Add(vx);
00090      for (int j = 0; j < N; ++j) 
00091        m[j] += vx[j];
00092    }
00093 
00094 #ifdef DEBUG
00095    std::cout << "average values of means :\n"; 
00096    for (int j = 0; j < N; ++j) 
00097      std::cout << m[j]/n << "  ";
00098    std::cout << "\n";
00099 #endif
00100    
00101    delete tree; 
00102    tree = 0; 
00103    return d; 
00104    
00105 }
00106 
00107 
00108 // unbin fit
00109 
00110 typedef ROOT::Math::IParamMultiFunction Func;  
00111 template <class MinType, class T>
00112 int DoUnBinFit(T * tree, Func & func, bool debug = false ) {  
00113 
00114    ROOT::Fit::UnBinData * d  = FillUnBinData(tree );  
00115    // need to have done Tree->Draw() before fit
00116    //FillUnBinData(d,tree);
00117 
00118    //std::cout << "data size type and size  is " << typeid(*d).name() <<  "   " << d->Size() << std::endl;
00119    std::cout << "Fit data size =  " << d->Size() << " dimension = " << d->NDim() << std::endl;
00120 
00121          
00122          
00123    //printData(d);
00124 
00125    // create the fitter 
00126    //std::cout << "Fit parameter 2  " << f.Parameters()[2] << std::endl;
00127 
00128    ROOT::Fit::Fitter fitter; 
00129    fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str());
00130 
00131    if (debug) 
00132       fitter.Config().MinimizerOptions().SetPrintLevel(3);
00133    else 
00134       fitter.Config().MinimizerOptions().SetPrintLevel(0);
00135 
00136    // set tolerance 1 for tree to be same as in TTTreePlayer::UnBinFIt
00137    fitter.Config().MinimizerOptions().SetTolerance(1);
00138 
00139    // set strategy (0 to avoid MnHesse
00140    fitter.Config().MinimizerOptions().SetStrategy(strategy);
00141 
00142 
00143    // create the function
00144 
00145    fitter.SetFunction(func); 
00146    // need to fix param 0 , normalization in the unbinned fits
00147    //fitter.Config().ParSettings(0).Fix();
00148 
00149    bool ret = fitter.Fit(*d);
00150    if (!ret) {
00151       std::cout << " Fit Failed " << std::endl;
00152       return -1; 
00153    }
00154    if (debug) 
00155       fitter.Result().Print(std::cout);    
00156 
00157    // check fit result
00158    double chi2 = 0;
00159    for (int i = 0; i < N; ++i) { 
00160       double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) );
00161       chi2 += d*d; 
00162    }
00163    double prob = ROOT::Math::chisquared_cdf_c(chi2,N);
00164    int iret =  (prob < 1.0E-6) ? -1 : 0;
00165    if (iret != 0) {
00166       std::cout <<"Found difference in fitted values - prob = " << prob << std::endl;
00167       if (!debug) fitter.Result().Print(std::cout);    
00168       for (int i = 0; i < N; ++i) { 
00169          double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) );
00170          std::cout << "par_" << i << " = " << fitter.Result().Value(i) << " true  = " << truePar[i] << " pull = " << d << std::endl;
00171       } 
00172       
00173    }
00174 
00175    delete d; 
00176 
00177    return iret; 
00178 
00179 }
00180 
00181 
00182 template <class MinType>
00183 int DoFit(TTree * tree, Func & func, bool debug = false ) {  
00184    return DoUnBinFit<MinType, TTree>(tree, func, debug); 
00185 }
00186 // template <class MinType>
00187 // int DoFit(TH1 * h1, Func & func, bool debug = false, bool copyData = false ) {  
00188 //    return DoBinFit<MinType, TH1>(h1, func, debug, copyData); 
00189 // }
00190 // template <class MinType>
00191 // int DoFit(TGraph * gr, Func & func, bool debug = false, bool copyData = false ) {  
00192 //    return DoBinFit<MinType, TGraph>(gr, func, debug, copyData); 
00193 // }
00194 
00195 template <class MinType, class FitObj>
00196 int FitUsingNewFitter(FitObj * fitobj, Func & func ) { 
00197 
00198    std::cout << "\n************************************************************\n"; 
00199    std::cout << "\tFit using new Fit::Fitter  " << typeid(*fitobj).name() << std::endl;
00200    std::cout << "\tMinimizer is " << MinType::name() << "  " << MinType::name2() << " func dim = " << func.NDim() << std::endl; 
00201 
00202    int iret = 0; 
00203    TStopwatch w; w.Start(); 
00204 
00205 #ifdef DEBUG
00206    std::cout << "initial Parameters " << iniPar << "  " << *iniPar << "   " <<  *(iniPar+1) << std::endl;
00207    func.SetParameters(iniPar);
00208    iret |= DoFit<MinType>(fitobj,func,true );
00209 
00210 #else
00211    for (int i = 0; i < nfit; ++i) { 
00212       func.SetParameters(iniPar);
00213       iret = DoFit<MinType>(fitobj,func, false);
00214       if (iret != 0) {
00215          std::cout << "Fit failed " << std::endl;
00216          break; 
00217       }
00218    }
00219 #endif
00220    w.Stop(); 
00221    std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl;  
00222    std::cout << "\n************************************************************\n"; 
00223 
00224    return iret; 
00225 }
00226 
00227 
00228 int testNdimFit() { 
00229 
00230 
00231    std::cout << "\n\n************************************************************\n"; 
00232    std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM)  FIT\n";
00233    std::cout << "************************************************************\n"; 
00234 
00235    TTree * t1 = new TTree("t2","a large Tree with gaussian variables");
00236    double  x[N];
00237    Int_t ev;
00238    t1->Branch("x",x,branchType.c_str());
00239    t1->Branch("ev",&ev,"ev/I");
00240 
00241    // generate the true parameters 
00242       for (int j = 0;  j < N; ++j) {          
00243          double mu = double(j)/10.; 
00244          double s  = 1.0 + double(j)/10.;  
00245          truePar[2*j] = mu; 
00246          truePar[2*j+1] = s;
00247       }
00248 
00249    
00250    //fill the tree
00251    TRandom3 r; 
00252    for (Int_t i=0;i<NPoints;i++) {
00253       for (int j = 0;  j < N; ++j) { 
00254          double mu = truePar[2*j]; 
00255          double s  = truePar[2*j+1];  
00256          x[j] = r.Gaus(mu,s);
00257       }
00258 
00259       ev = i;
00260       t1->Fill();
00261       
00262    }
00263    //t1.Draw("x"); // to select fit variable 
00264 
00265 
00266    for (int i = 0; i <N; ++i) {
00267       iniPar[2*i] = 0; 
00268       iniPar[2*i+1] = 1; 
00269    }
00270 
00271    // use simply TF1 wrapper 
00272    //ROOT::Math::WrappedMultiTF1 f2(*f1); 
00273    ROOT::Math::WrappedParamFunction<> f2(&gausnormN,N,2*N,iniPar); 
00274 
00275    int iret = 0; 
00276    iret |= FitUsingNewFitter<MINUIT2>(t1,f2);
00277 
00278    return iret; 
00279 }
00280 
00281 int main() { 
00282   return testNdimFit();
00283 }

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