00001
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;
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
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
00076
00077
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
00108 class MultiGaussRooPdf {
00109
00110 public:
00111
00112
00113 MultiGaussRooPdf(unsigned int n) :
00114 x(n), m(n), s(n), g(n), pdf(n)
00115 {
00116
00117
00118
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
00129
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
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
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");
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
00241 template <class MinType>
00242 int DoFit(TTree * tree, Func & func, bool debug = false, bool = false ) {
00243
00244 ROOT::Fit::UnBinData d;
00245
00246 FillUnBinData(d,tree);
00247
00248
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.);
00254
00255 if (debug)
00256 fitter.Config().MinimizerOptions().SetPrintLevel(3);
00257
00258
00259
00260
00261 fitter.SetFunction(func);
00262
00263
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
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
00320 for (int i = 0; i < N; ++i) {
00321 iniPar[2*i] = 1;
00322 iniPar[2*i+1] = 1;
00323 }
00324
00325
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
00343 wpdf.SetParameters(iniPar);
00344
00345 FitUsingRooFit(tree,pdf, *xvars);
00346
00347
00348
00349 if (N == 1) {
00350 ROOT::Math::WrappedParamFunction<> gausn(&gausnorm,2,iniPar,iniPar+1);
00351 FitUsingNewFitter<TMINUIT>(&tree,gausn);
00352 }
00353
00354
00355
00356 }