1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 // author: Eulogio Serradilla <eulogio.serradilla@cern.ch>
19 #include <Riostream.h>
28 #include <RooWorkspace.h>
29 #include <RooRealVar.h>
30 #include <RooDataSet.h>
31 #include <RooDataHist.h>
32 #include <RooHistPdf.h>
33 #include <RooMsgService.h>
41 AliLnPt::AliLnPt(const TString& particle, Double_t trigEff, const TString& inputFilename, const TString& outputFilename, const TString& otag, const TString& corrFilename, const TString& corrtag)
45 , fInputFilename(inputFilename)
46 , fOutputFilename(outputFilename)
48 , fCorrFilename(corrFilename)
67 , fPidProc(kMassSquared)
74 TH1::SetDefaultSumw2(); // switch on histogram errors
78 // disable verbose in RooFit
79 RooMsgService::instance().setSilentMode(1);
80 RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
94 // Get the true pt distribution
96 TFile* finput = new TFile(fInputFilename.Data(), "read");
97 if (finput->IsZombie()) exit(1);
99 TFile* foutput = new TFile(fOutputFilename.Data(), "recreate");
100 if (foutput->IsZombie()) exit(1);
105 TString species = fParticle;
106 species.ReplaceAll("Anti","");
108 TH1D* hStats = FindObj<TH1D>(finput, species + "_Stats");
114 hCorrPt = dynamic_cast<TH1D*>( (FindObj<TH1D>(finput, fParticle + "_Gen_PhS_Prim_Pt"))->Clone( Form("%s_Cor_Pt", fParticle.Data())) );
118 fcorr = new TFile(fCorrFilename.Data(),"read");
119 if (fcorr->IsZombie()) exit(1);
121 fdebug = new TFile(Form("debug-%s",fOutputFilename.Data()),"recreate");
122 if (fdebug->IsZombie()) exit(1);
124 fdebug->mkdir(fOutputTag.Data());
126 // pointers to the required histograms
128 TH1D* hOrigPt = FindObj<TH1D>(finput, fParticle + "_PID_Pt");
131 if(fPidProc == kTimeOfFlight) hPidPt = FindObj<TH2D>(finput, fParticle + "_PID_DTime_Pt");
132 else if(fPidProc == kMassSquared) hPidPt = FindObj<TH2D>(finput, fParticle + "_PID_M2_Pt");
133 else if(fPidProc == kMassDifference) hPidPt = FindObj<TH2D>(finput, fParticle + "_PID_DM2_Pt");
137 TH1D* hFracMatPt = FindObj<TH1D>(fcorr, fCorrTag, fParticle + "_Frac_Mat_Pt");
138 TH1D* hFracFdwnPt = FindObj<TH1D>(fcorr, fCorrTag, fParticle + "_Frac_Fdwn_Pt");
139 TF1* fncFracMatPt = FindObj<TF1>(fcorr, fCorrTag, fParticle + "_Frac_Mat_Fit_Pt");
140 TF1* fncFracFdwnPt = FindObj<TF1>(fcorr, fCorrTag, fParticle + "_Frac_Fdwn_Fit_Pt");
144 hFracFdwnPt = FindObj<TH1D>(fcorr, fCorrTag, species + "_Frac_Fdwn_Pt");
145 fncFracFdwnPt = FindObj<TF1>(fcorr, fCorrTag, species + "_Frac_Fdwn_Fit_Pt");
148 TH1D* hEffVtxPt = FindObj<TH1D>(fcorr, fCorrTag, fParticle + "_Eff_Vtx_Pt");
149 TH1D* hEffAccTrkPt = FindObj<TH1D>(fcorr, fCorrTag, fParticle + "_Eff_AccTrk_Pt");
153 fdebug->cd(fOutputTag.Data());
155 TH1D* hPidCorrPt = 0;
158 if(fDebugLevel>1) std::cout << "\t\tpid correction" << std::endl;
160 hPidCorrPt = this->PID(hOrigPt, hPidPt, fPtPid, fPtMax, fParticle + "_PidCorr_Pt");
161 hPidCorrPt->Scale(1./fPidEff);
165 hPidCorrPt = dynamic_cast<TH1D*>(hOrigPt->Clone(Form("%s_PidCorr_Pt", fParticle.Data())));
168 TH1D* hSecCorrPt = 0;
171 if(fDebugLevel>1) std::cout << "\t\tremoval of secondaries" << std::endl;
175 hSecCorrPt = this->Secondaries(hPidCorrPt, fncFracMatPt, fncFracFdwnPt, fParticle + "_SecCorr_Pt");
179 hSecCorrPt = this->Secondaries(hPidCorrPt, hFracMatPt, hFracFdwnPt, fParticle + "_SecCorr_Pt");
184 hSecCorrPt = dynamic_cast<TH1D*>(hPidCorrPt->Clone(Form("%s_SecCorr_Pt", fParticle.Data())));
187 TH1D* hEffCorrPt = 0;
190 if(fDebugLevel>1) std::cout << "\t\tefficiency correction" << std::endl;
194 TH1D* hStatsMC = FindObj<TH1D>(fcorr, fCorrTag, species + "_Stats");
195 fVtxFactor = this->GetVertexCorrection(hStats, hStatsMC);
198 hEffCorrPt = this->Efficiency(hSecCorrPt, hEffVtxPt, hEffAccTrkPt, fParticle + "_EffCorr_Pt");
202 hEffCorrPt = dynamic_cast<TH1D*>(hSecCorrPt->Clone(Form("%s_EffCorr_Pt", fParticle.Data())));
207 hCorrPt = dynamic_cast<TH1D*>(hEffCorrPt->Clone(Form("%s_Corr_Pt", fParticle.Data())));
211 fdebug->cd(fOutputTag.Data());
213 hOrigPt->Write(); // original distribution
227 TH1D* hPt = dynamic_cast<TH1D*>(hCorrPt->Clone(Form("%s_Pt", fParticle.Data())));
228 hPt->SetTitle(fParticle.Data());
232 Int_t lowbin = hPt->GetXaxis()->FindFixBin(fPtMin);
233 Int_t hibin = hPt->GetXaxis()->FindFixBin(fPtMax);
235 for(Int_t i=lowbin; i<hibin; ++i)
237 hPt->SetBinContent(i, hCorrPt->GetBinContent(i));
238 hPt->SetBinError(i, hCorrPt->GetBinError(i));
255 TH1D* hStatsFix = new TH1D(Form("%s_Stats", fParticle.Data()), "Stats", 6, 0, 6);
256 hStatsFix->GetXaxis()->SetBinLabel(1,"Events");
257 hStatsFix->GetXaxis()->SetBinLabel(2,"Trig");
258 hStatsFix->GetXaxis()->SetBinLabel(3,"AnaT");
259 hStatsFix->GetXaxis()->SetBinLabel(4,"Inel");
260 hStatsFix->GetXaxis()->SetBinLabel(5,"Vtx");
261 hStatsFix->GetXaxis()->SetBinLabel(6,"Vz");
262 hStatsFix->SetStats(0);
265 hStatsFix->Fill("Events",hStats->Integral(1,1));
266 hStatsFix->Fill("Trig",hStats->Integral(2,2));
269 hStatsFix->Fill("Ana",hStats->Integral(2,2));
270 hStatsFix->Fill("Inel",hStats->Integral(2,2));
274 Double_t nTrig = hStats->Integral(2,2);
275 Double_t nAna = hStats->Integral(3,3);
276 Double_t nVtx = hStats->Integral(4,4);
277 Double_t nVz = hStats->Integral(5,5);
278 Double_t nAnaT = nTrig; // all triggering events since we have the MC correction
279 Double_t nInel = nTrig/fTrigEff;
283 // Add events without vertex to get the proportional trig. events
284 Double_t nNoVtx = (nAna/nVtx)*(nTrig-nVtx);
285 nAnaT = nAna + nNoVtx;
286 nInel = nAnaT/fTrigEff;
289 hStatsFix->Fill("AnaT",nAnaT);
290 hStatsFix->Fill("Inel",nInel);
291 hStatsFix->Fill("Vtx",nVtx);
292 hStatsFix->Fill("Vz",nVz);
306 Double_t AliLnPt::GetVertexCorrection(const TH1D* hData, const TH1D* hMC) const
309 // vertex correction factor
311 Double_t nAna = hData->Integral(3,3);
312 Double_t nVtx = hData->Integral(4,4);
313 Double_t nAnaMC = hMC->Integral(3,3);
314 Double_t nVtxMC = hMC->Integral(4,4);
316 return (nVtx/nAna)/(nVtxMC/nAnaMC);
319 Double_t AliLnPt::GetM2Width(Double_t pt, Double_t m) const
322 // expected M2 width parameterization from LHC12a5b
324 Double_t c0 = 1.90212e-03;
325 Double_t c1 = 1.29814e-02;
327 TString species = fParticle;
328 species.ReplaceAll("Anti","");
330 if(species == "Deuteron")
335 else if(species == "Triton")
340 else if(species == "He3")
345 else if(species == "Alpha")
351 return c0/(pt*pt) + c1*(pt*pt/(m*m) + 1.);
354 Double_t AliLnPt::GetExpectedDT(Double_t pt, Double_t m) const
357 // estimate of the expected time of flight (ns) for mass hypothesis m
359 Double_t l = 370.; // cm
360 Double_t c = 2.99792458e+1; // cm/ns
362 return (l/c)*TMath::Sqrt(1.+(m/pt)*(m/pt));
365 RooWorkspace* AliLnPt::GetToFModel(Double_t pt, const TString& name) const
368 // model for the time of flight distribution
370 using namespace RooFit;
372 RooWorkspace* w = new RooWorkspace(name.Data());
375 w->factory(Form("AliLnGaussianExpTail::Sd(x[%f,%f], mu[0,-0.06,0.06], sigma[0.120,0.05,0.3], tau[0.1,0.08,0.4])", fBkgMin, fBkgMax));
378 Double_t expTd = this->GetExpectedDT(pt, GetMass("deuteron"));
379 Double_t expDTp = this->GetExpectedDT(pt, GetMass("proton")) - expTd;
380 Double_t expDTk = this->GetExpectedDT(pt, GetMass("kaon")) - expTd;
381 Double_t expDTpi = this->GetExpectedDT(pt, GetMass("pion")) - expTd;
383 w->factory(Form("AliLnGaussianExpTail::ProtonBkg(x, muP[%f,%f-0.2,%f+0.2], widthP[0.120,0.05,0.3], tauP[0.08,0.01,0.2])",expDTp, expDTp, expDTp));
384 w->factory(Form("AliLnGaussianExpTail::KaonBkg(x, muK[%f,%f-0.2,%f+0.2], widthK[0.120,0.05,0.3], tauP[0.08,0.01,0.2])",expDTk, expDTk, expDTk));
385 w->factory(Form("AliLnGaussianExpTail::PionBkg(x, muPi[%f,%f-0.2,%f+0.2], widthPi[0.120,0.05,0.3], tauPi[0.08,0.01,0.2])",expDTpi, expDTpi, expDTpi));
387 w->factory("SUM::Bkg( Npi[0.3,0,1.e+9]*PionBkg, Nk[0.24,0,1.e+9]*KaonBkg, Np[0.47,0,1.e+9]*ProtonBkg, Np[0.47,0,1.e+9]*ProtonBkg)");
389 w->factory("SUM::model( Nd[0,1.e+9]*Sd, Nbkg[0,1.e+9]*Bkg )");
391 w->var("x")->SetTitle("t - <t> (ns)");
396 RooWorkspace* AliLnPt::GetM2Model(Double_t pt, Double_t m, const TString& name, Double_t max) const
399 // mass squared model for deuterons
401 using namespace RooFit;
403 RooWorkspace* w = new RooWorkspace(name.Data());
407 w->factory(Form("Exponential::PionBkg(x[%f,%f],lambdaPi[-0.3,-10.,0.])", fBkgMin, fBkgMax));
408 w->factory("Exponential::KaonBkg(x,lambdaK[-0.4,-10.,0.])");
409 w->factory("Exponential::ProtonBkg(x,lambdaP[-0.5,-10.,0.])");
411 w->factory("SUM::Bkg( Npi[0.3,0.,1.]*PionBkg, Nk[0.24,0.,1.]*KaonBkg, Np[0.47,0.,1.]*ProtonBkg )");
415 Double_t sigma = GetM2Width(pt, m);
416 Double_t mm = (fPidProc == kMassSquared) ? m*m : 0;
420 w->factory(Form("AliLnM2::Sd(x,mu[%f,%f,%f], sigma[%f,%f,%f],tau[0.1,0.05,0.4],p[%f,%f,%f])",mm, mm-0.15, mm+0.1, sigma, 0.1, sigma+0.1, 1.16*pt,pt,1.33*pt));
422 else // neglect non-gaussian tails
424 w->factory(Form("Gaussian::Sd(x, mu[%f,%f,%f], sigma[%f,%f,%f])",mm, mm-0.15, mm+0.1, sigma, 0.1, sigma+0.1));
428 w->factory(Form("SUM::model( Nd[0.,%f]*Sd, Nbkg[0.,%f]*Bkg )", max, max));
430 w->var("x")->SetTitle("#it{m}^{2} (GeV^{2}/c^{4})");
435 void AliLnPt::GetPtFromPid(TH1D* hPt, Double_t ptmin, Double_t ptmax, const TH2D* hPidPt, Double_t pidMin, Double_t pidMax) const
438 // Integrate pid distribution
440 Int_t lowbin = hPt->GetXaxis()->FindFixBin(ptmin);
441 Int_t hibin = hPt->GetXaxis()->FindFixBin(ptmax);
443 for(Int_t i=lowbin; i<hibin; ++i)
445 TH1D* hPid = hPidPt->ProjectionY(Form("%s_PID_%02d",fParticle.Data(),i),i,i);
447 Int_t pidLowBin = hPid->GetXaxis()->FindFixBin(pidMin);
448 Int_t pidHiBin = hPid->GetXaxis()->FindFixBin(pidMax);
451 Double_t n = hPid->IntegralAndError(pidLowBin, pidHiBin, err);
453 hPt->SetBinContent(i, n);
454 hPt->SetBinError(i, err);
460 TH1D* AliLnPt::PID(const TH1D* hPt, const TH2D* hPidPt2, Double_t ptmin, Double_t ptmax, const TString& name)
463 // Remove contamination in the pt distribution
465 TH1D* hPidCorrPt = dynamic_cast<TH1D*>(hPt->Clone(name.Data()));
466 if(hPidCorrPt == 0) return 0;
472 const Int_t kNBin = 2;
474 TH2D* hPidPt = dynamic_cast<TH2D*>(hPidPt2->Clone("_pid_pt_"));
475 hPidPt->Rebin2D(1,kNBin);
477 // integrate around the mean value
479 this->GetPtFromPid(hPidCorrPt, 0, ptmin, hPidPt, fIntMin, fIntMax);
483 using namespace RooFit;
485 Int_t lowbin = hPt->GetXaxis()->FindFixBin(ptmin);
486 Int_t hibin = hPt->GetXaxis()->FindFixBin(ptmax);
488 Double_t m = GetMass(fParticle);
490 for(Int_t i=lowbin; i<hibin; ++i)
492 TH1D* hPid = hPidPt->ProjectionY(Form("%s_PID_%02d",fParticle.Data(),i),i,i);
494 RooWorkspace* w = (fPidProc==kTimeOfFlight) ? GetToFModel( hPt->GetBinCenter(i), Form("%s_M2_%02d",fParticle.Data(),i)) : GetM2Model(hPt->GetBinCenter(i), m, Form("%s_M2_%02d",fParticle.Data(),i),hPid->Integral());
496 RooRealVar* x = w->var("x");
497 RooDataHist data("data", "data to fit", *x, hPid);
501 w->pdf("model")->fitTo(data, Minos(kTRUE), PrintLevel(-1), Verbose(kFALSE), Warnings(kFALSE), PrintEvalErrors(-1) );
503 hPidCorrPt->SetBinContent(i, w->var("Nd")->getVal());
504 hPidCorrPt->SetBinError(i, w->var("Nd")->getError());
516 TH1D* AliLnPt::Secondaries(const TH1D* hPt, const TH1D* hFracMatPt, const TH1D* hFracFdwnPt, const TString& name) const
519 // remove contamination of secondaries using fractions
520 // N_prim = N/(1+fmat+fdwn)
522 TF1* one = new TF1("one","1",0,10);
524 TH1D* xfactor = (TH1D*)hFracMatPt->Clone(Form("%s_1_fmat_fdwn_",fParticle.Data()));
525 if(fFdwnCorr) xfactor->Add(hFracFdwnPt);
528 TH1D* hSecCorPt = (TH1D*)hPt->Clone(name.Data());
530 hSecCorPt->Divide(xfactor);
538 TH1D* AliLnPt::Secondaries(const TH1D* hPt, TF1* fncMatPt, TF1* fncFdwnPt, const TString& name) const
541 // remove contamination of secondaries using a function fitted to the fractions
542 // N_prim = N/(1+fmat+fdwn)
544 TF1* fnc = new TF1("_secondaries_","1 + [0]*exp(-[1]*x)+[2] + [3]*exp(-[4]*x)+[5]", 0, 10);
546 Double_t param[6] = {0};
547 fncMatPt->GetParameters(param);
548 if(fFdwnCorr) fncFdwnPt->GetParameters(¶m[3]);
550 Double_t err[6] = {0};
551 for(Int_t i=0; i<3; ++i) err[i] = fncMatPt->GetParError(i);
552 if(fFdwnCorr) for(Int_t i=3; i<6; ++i) err[i] = fncFdwnPt->GetParError(i);
554 fnc->SetParameters(param);
555 fnc->SetParErrors(err);
557 TH1D* hSecCorPt = (TH1D*)hPt->Clone(name.Data());
558 hSecCorPt->Divide(fnc);
565 TH1D* AliLnPt::Efficiency(const TH1D* hPt, const TH1D* hEffVtxPt, const TH1D* hEffAccTrkPt, const TString& name) const
568 // correct by efficiency
570 TH1D* hEffCorPt = (TH1D*)hPt->Clone(name.Data());
571 hEffCorPt->Divide(hEffAccTrkPt);
575 hEffCorPt->Divide(hEffVtxPt);
576 hEffCorPt->Scale(fVtxFactor);