//+ example of sampling a multi-dim distribution using the DistSampler class //NOTE: This tutorial must be run with ACLIC //Author L. Moneta Dec 2010 // function (a 4d gaussian) #include "TMath.h" #include "TF2.h" #include "TStopwatch.h" #include "Math/DistSampler.h" #include "Math/DistSamplerOptions.h" #include "Math/MinimizerOptions.h" #include "Math/Factory.h" #include "TKDTreeBinning.h" #include "TTree.h" #include "TFile.h" #include "TMatrixDSym.h" #include "TVectorD.h" #include "TCanvas.h" #include // Gauss ND function // make a class in order to avoid constructing the // matrices for every call // This however requires that the code must be compiled with ACLIC bool debug = false; struct GausND { TVectorD X; TVectorD Mu; TMatrixDSym CovMat; GausND( int dim ) : X(TVectorD(dim)), Mu(TVectorD(dim)), CovMat(TMatrixDSym(dim) ) {} double operator() (double *x, double *p) { // 4 parameters int dim = X.GetNrows(); int k = 0; for (int i = 0; iSetParameters(par0); double x0[] = {0,0,0,0}; // for debugging if (debug) f->EvalPar(x0,0); debug = false; TString name; for (int i = 0; i < NPAR; ++i ) { if (i < DIM) f->SetParName(i, name.Format("mu_%d",i+1) ); else if (i < 2*DIM) f->SetParName(i, name.Format("sig_%d",i-DIM+1) ); else if (i < 2*DIM) f->SetParName(i, name.Format("sig_%d",i-2*DIM+1) ); } //ROOT::Math::DistSamplerOptions::SetDefaultSampler("Foam"); DistSampler * sampler = Factory::CreateDistSampler(); if (sampler == 0) { Info("multidimSampling","Default sampler %s is not available try with Foam ", ROOT::Math::DistSamplerOptions::DefaultSampler().c_str() ); ROOT::Math::DistSamplerOptions::SetDefaultSampler("Foam"); } sampler = Factory::CreateDistSampler(); if (sampler == 0) { Error("multidimSampling","Foam sampler is not available - exit "); return; } sampler->SetFunction(*f,DIM); sampler->SetRange(xmin,xmax); bool ret = sampler->Init(); std::vector data1(DIM*N); double v[DIM]; TStopwatch w; if (!ret) { Error("Sampler::Init","Error initializing unuran sampler"); return; } // generate the data w.Start(); for (int i = 0; i < N; ++i) { sampler->Sample(v); for (int j = 0; j < DIM; ++j) data1[N*j + i] = v[j]; } w.Stop(); w.Print(); // fill tree with data TFile * file = new TFile("multiDimSampling.root","RECREATE"); double x[DIM]; TTree * t1 = new TTree("t1","Tree from Unuran"); t1->Branch("x",x,"x[4]/D"); for (int i = 0; i < N; ++i) { for (int j = 0; j < DIM; ++j) { x[j] = data1[i+N*j]; } t1->Fill(); } // try to fit the 2d data; // GausND gaus2(2); // TF2 * f2 = new TF2("f2",gaus2,-3,3,-3,3,5,"GausND"); // f2->SetParameters(0,0,1,1,0); // f2->SetParLimits(4,-1,1); // t1->UnbinnedFit("f2","x[0]:x[1]"); // plot the data t1->Draw("x[0]:x[1]:x[2]:x[3]","","candle"); TCanvas * c2 = new TCanvas(); c2->Divide(3,2); int ic=1; c2->cd(ic++); t1->Draw("x[0]:x[1]"); c2->cd(ic++); t1->Draw("x[0]:x[2]"); c2->cd(ic++); t1->Draw("x[0]:x[3]"); c2->cd(ic++); t1->Draw("x[1]:x[2]"); c2->cd(ic++); t1->Draw("x[1]:x[3]"); c2->cd(ic++); t1->Draw("x[2]:x[3]"); t1->Write(); file->Close(); }