1 // Dihadron correlations task - simple task to read ESD or AOD input,
2 // calculate same- and mixed-event correlations, and fill THnSparse
3 // output. -A. Adare, Apr 2011
10 #include "TProfile2D.h"
11 #include "THnSparse.h"
14 #include "AliAODEvent.h"
15 #include "AliAODInputHandler.h"
16 #include "AliAnalysisManager.h"
17 #include "AliAnalysisTask.h"
18 #include "AliCentrality.h"
19 #include "AliDhcTask_opt.h"
20 #include "AliESDEvent.h"
21 #include "AliESDInputHandler.h"
22 #include "AliESDtrackCuts.h"
23 #include "KiddiePoolClasses.h"
24 #include "AliVParticle.h"
28 //________________________________________________________________________
29 AliDhcTask::AliDhcTask(const char *name)
30 : AliAnalysisTaskSE(name), fVerbosity(0), fEtaMax(1), fZVtxMax(10), fPtMin(0.25), fPtMax(15),
31 fESD(0), fAOD(0), fOutputList(0), fHistPt(0), fHEvt(0), fHTrk(0), fHSs(0), fHMs(0),
32 fIndex(0), fMeanPtTrg(0), fMeanPtAss(0), fMean2PtTrg(0), fMean2PtAss(0),
33 fCentrality(99), fZVertex(99), fEsdTrackCutsTPCOnly(0), fPoolMgr(0)
37 // Define input and output slots here
38 // Input slot #0 works with a TChain
39 DefineInput(0, TChain::Class());
40 // Output slot #0 id reserved by the base class for AOD
41 // Output slot #1 writes into a TH1 container
42 DefineOutput(1, TList::Class());
44 fBranchNames="ESD:AliESDRun.,AliESDHeader.,PrimaryVertex.,SPDVertex.,TPCVertex.,Tracks "
45 "AOD:header,tracks,vertices,";
48 //________________________________________________________________________
49 void AliDhcTask::UserCreateOutputObjects()
52 // Called once (per slave on PROOF!)
54 fOutputList = new TList();
55 fOutputList->SetOwner(1);
57 fEsdTrackCutsTPCOnly = AliESDtrackCuts::GetStandardTPCOnlyTrackCuts();
58 //fEsdTrackCutsTPCOnly->SetMinNClustersTPC(70);
59 fEsdTrackCutsTPCOnly->SetMinNCrossedRowsTPC(70);
60 fEsdTrackCutsTPCOnly->SetMinRatioCrossedRowsOverFindableClustersTPC(0.8);
64 PostData(1, fOutputList);
67 //________________________________________________________________________
68 void AliDhcTask::BookHistos()
72 Int_t nDeta=20, nPtAssc=12, nPtTrig=12, nCent=12, nDphi=36, nZvtx=8;
74 Double_t ptt[] = {0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 15};
75 Double_t pta[] = {0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 15};
76 Double_t cent[] = {0, 1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 60, 90};
77 Double_t zvtx[] = {-10, -6, -4, -2, 0, 2, 4, 6, 10};
80 fHEvt = new TH2F("fHEvt", "Event-level variables; Zvtx; Cent", 30, -15, 15, 101, 0, 101);
81 fOutputList->Add(fHEvt);
83 fHTrk = new TH2F("fHTrk", "Track-level variables",
84 100, 0, TMath::TwoPi(), 100, -fEtaMax, +fEtaMax);
85 fOutputList->Add(fHTrk);
87 // Left over from the tutorial :)
88 fHistPt = new TH1F("fHistPt", "P_{T} distribution", 200, 0., fPtMax);
89 fHistPt->GetXaxis()->SetTitle("P_{T} (GeV/c)");
90 fHistPt->GetYaxis()->SetTitle("dN/dP_{T} (c/GeV)");
91 fHistPt->SetMarkerStyle(kFullCircle);
92 fOutputList->Add(fHistPt);
94 fHPtAss = new TH1F("fHPtAss","PtAssoc;P_{T} (GeV/c) [GeV/c]",nPtAssc,pta);
95 fOutputList->Add(fHPtAss);
96 fHPtTrg = new TH1F("fHPtTrg","PtTrig;P_{T} (GeV/c) [GeV/c]",nPtTrig,ptt);
97 fOutputList->Add(fHPtTrg);
98 fHCent = new TH1F("fHCent","Cent;bins",nCent,cent);
99 fOutputList->Add(fHCent);
100 fHZvtx = new TH1F("fHZvtx","Zvertex;bins",nZvtx,zvtx);
101 fOutputList->Add(fHZvtx);
103 fNbins = nPtTrig*nPtAssc*nCent*nZvtx;
104 fHSs = new TH2*[fNbins];
105 fHMs = new TH2*[fNbins];
107 fIndex = new TFormula("GlobIndex","(t-1)*[0]*[1]*[2]+(z-1)*[0]*[1]+(x-1)*[0]+(y-1)+0*[4]");
108 fIndex->SetParameters(nPtTrig,nPtAssc,nZvtx,nCent);
109 fIndex->SetParNames("NTrigBins","NAssocBins", "NZvertexBins", "NCentBins");
110 //fOutputList->Add(fIndex);
112 fMeanPtTrg = new TProfile2D*[nPtTrig*nPtAssc];
113 fMeanPtAss = new TProfile2D*[nPtTrig*nPtAssc];
114 fMean2PtTrg = new TProfile2D*[nPtTrig*nPtAssc];
115 fMean2PtAss = new TProfile2D*[nPtTrig*nPtAssc];
116 for (Int_t c=1; c<=nCent; ++c) {
117 TString title(Form("cen=%d (%.1f)",c,fHCent->GetBinCenter(c)));
118 fMeanPtTrg[c-1] = new TProfile2D(Form("hMeanPtTrgCen%d",c),title,nPtTrig,ptt,nPtAssc,pta);
119 fMeanPtAss[c-1] = new TProfile2D(Form("hMeanPtAssCen%d",c),title,nPtTrig,ptt,nPtAssc,pta);
120 fMean2PtTrg[c-1] = new TProfile2D(Form("hMean2PtTrgCen%d",c),title,nPtTrig,ptt,nPtAssc,pta);
121 fMean2PtAss[c-1] = new TProfile2D(Form("hMean2PtAssCen%d",c),title,nPtTrig,ptt,nPtAssc,pta);
122 fOutputList->Add(fMeanPtTrg[c-1]);
123 fOutputList->Add(fMeanPtAss[c-1]);
124 fOutputList->Add(fMean2PtTrg[c-1]);
125 fOutputList->Add(fMean2PtAss[c-1]);
129 for (Int_t c=1; c<=nCent; ++c) {
130 for (Int_t z=1; z<=nZvtx; ++z) {
131 for (Int_t t=1; t<=nPtTrig; ++t) {
132 for (Int_t a=1; a<=nPtAssc; ++a) {
139 TString title(Form("cen=%d (%.1f), zVtx=%d (%.1f), trig=%d (%.1f), assc=%d (%.1f)",
140 c,fHCent->GetBinCenter(c), z,fHZvtx->GetBinCenter(z),
141 t,fHPtTrg->GetBinCenter(t),a, fHPtAss->GetBinCenter(a)));
142 fHSs[count] = new TH2F(Form("hS%d",count), Form("Signal %s",title.Data()),
143 nDphi,-0.5*TMath::Pi(),1.5*TMath::Pi(),nDeta,-2*fEtaMax,2*fEtaMax);
144 fHMs[count] = new TH2F(Form("hM%d",count), Form("Signal %s",title.Data()),
145 nDphi,-0.5*TMath::Pi(),1.5*TMath::Pi(),nDeta,-2*fEtaMax,2*fEtaMax);
146 fOutputList->Add(fHSs[count]);
147 fOutputList->Add(fHMs[count]);
149 cout << count << " " << fIndex->Eval(t,a,z,c) << ": " << title << endl;
159 //________________________________________________________________________
160 void AliDhcTask::InitEventMixer()
162 // The effective pool size in events is set by trackDepth, so more
163 // low-mult events are required to maintain the threshold than
164 // high-mult events. Centrality pools are indep. of data histogram
165 // binning, no need to match.
167 Int_t trackDepth = 1000; // # tracks to fill pool
168 Int_t poolsize = 200; // Maximum number of events
171 Int_t nCentBins = 12;
172 Double_t centBins[] = {0,1,2,3,4,5,10,20,30,40,50,60,90.1};
174 //Int_t nCentBins = 1;
175 //Double_t centBins[] = {-1,100.1};
179 Double_t zvtxbin[] = {-10,-6,-4,-2,0,2,4,6,10};
181 fPoolMgr = new KiddiePoolManager();
182 fPoolMgr->SetTargetTrackDepth(trackDepth);
184 fPoolMgr->SetDebug(1);
185 fPoolMgr->InitEventPools(poolsize, nCentBins, centBins, nZvtxBins, zvtxbin);
190 //________________________________________________________________________
191 void AliDhcTask::UserExec(Option_t *)
193 // Main loop, called for each event.
195 static int iEvent = -1; ++iEvent;
198 if (iEvent % 10 == 0)
199 cout << iEvent << endl;
202 Int_t dType = -1; // Will be set to kESD or kAOD.
203 MiniEvent* sTracks = 0; // Vector of selected MiniTracks.
204 Double_t centCL1 = -1;
208 // Get event pointers, check for signs of life
209 fESD = dynamic_cast<AliESDEvent*>(InputEvent());
210 fAOD = dynamic_cast<AliAODEvent*>(InputEvent());
216 AliError("Neither fESD nor fAOD available");
220 // Centrality, vertex, other event variables...
222 if (!VertexOk(fESD)) {
224 AliInfo(Form("Event REJECTED. z = %.1f", fZVertex));
227 const AliESDVertex* vertex = fESD->GetPrimaryVertex();
228 fZVertex = vertex->GetZ();
229 if(fESD->GetCentrality()) {
231 fESD->GetCentrality()->GetCentralityPercentile("V0M");
233 fESD->GetCentrality()->GetCentralityPercentile("CL1");
237 const AliAODVertex* vertex = fAOD->GetPrimaryVertex();
238 fZVertex = vertex->GetZ();
239 if (!VertexOk(fAOD)) {
241 Info("Exec()", "Event REJECTED. z = %.1f", fZVertex);
244 const AliCentrality *aodCent = fAOD->GetHeader()->GetCentralityP();
246 fCentrality = aodCent->GetCentralityPercentile("V0M");
247 centCL1 = aodCent->GetCentralityPercentile("CL1");
251 // Fill Event histogram
252 fHEvt->Fill(fZVertex, fCentrality);
254 if (fCentrality > 90. || fCentrality < 0) {
255 AliInfo(Form("Event REJECTED. fCentrality = %.1f", fCentrality));
259 // Get array of selected tracks
261 sTracks = GetESDTrax();
264 sTracks = GetAODTrax();
267 // Get pool containing tracks from other events like this one
268 KiddiePool* pool = fPoolMgr->GetEventPool(fCentrality, fZVertex);
270 AliWarning(Form("No pool found. Centrality %f, ZVertex %f", fCentrality, fZVertex));
274 if (!pool->IsReady()) {
275 pool->UpdatePool(sTracks);
279 if (pool->IsFirstReady()) {
280 // recover events missed before the pool is ready
281 Int_t nEvs = pool->GetCurrentNEvents();
283 for (Int_t i=0; i<nEvs; ++i) {
284 MiniEvent* evI = pool->GetEvent(i);
285 for (Int_t j=0; j<nEvs; ++j) {
286 MiniEvent* evJ = pool->GetEvent(j);
288 Correlate(*evI, *evJ, kSameEvt);
290 Correlate(*evI, *evJ, kDiffEvt, 1.0);
295 } else { /* standard case: same event, then mix*/
296 Correlate(*sTracks, *sTracks, kSameEvt);
297 Int_t nMix = pool->GetCurrentNEvents();
298 for (Int_t jMix=0; jMix<nMix; ++jMix) {
299 MiniEvent* bgTracks = pool->GetEvent(jMix);
300 Correlate(*sTracks, *bgTracks, kDiffEvt, 1.0);
304 pool->UpdatePool(sTracks);
305 PostData(1, fOutputList);
309 //________________________________________________________________________
310 MiniEvent* AliDhcTask::GetESDTrax() const
312 // Loop twice: 1. Count sel. tracks. 2. Fill vector.
314 const AliESDVertex *vtxSPD = fESD->GetPrimaryVertexSPD();
318 Int_t nTrax = fESD->GetNumberOfTracks();
320 AliInfo(Form("%d tracks in event",nTrax));
324 TObjArray arr(nTrax);
327 for (Int_t i = 0; i < nTrax; ++i) {
328 AliESDtrack* esdtrack = fESD->GetTrack(i);
330 AliError(Form("Couldn't get ESD track %d\n", i));
333 Bool_t trkOK = fEsdTrackCutsTPCOnly->AcceptTrack(esdtrack);
336 Double_t pt = esdtrack->Pt();
337 Bool_t ptOK = pt >= fPtMin && pt < fPtMax;
340 Double_t eta = esdtrack->Eta();
341 if (TMath::Abs(eta) > fEtaMax)
344 // create a tpc only track
345 AliESDtrack *newtrack = AliESDtrackCuts::GetTPCOnlyTrack(fESD,esdtrack->GetID());
348 if (newtrack->Pt()<=0) {
353 AliExternalTrackParam exParam;
354 Bool_t relate = newtrack->RelateToVertexTPC(vtxSPD,fESD->GetMagneticField(),kVeryBig,&exParam);
360 // set the constraint parameters to the track
361 newtrack->Set(exParam.GetX(),exParam.GetAlpha(),exParam.GetParameter(),exParam.GetCovariance());
364 ptOK = pt >= fPtMin && pt < fPtMax;
369 eta = esdtrack->Eta();
370 if (TMath::Abs(eta) > fEtaMax) {
378 MiniEvent* miniEvt = new MiniEvent(0);
379 miniEvt->reserve(nSelTrax);
382 for (Int_t i = 0; i < nSelTrax; ++i) {
383 AliESDtrack* esdtrack = static_cast<AliESDtrack*>(arr.At(i));
385 AliError(Form("Couldn't get ESD track %d\n", i));
388 Double_t pt = esdtrack->Pt();
389 Double_t eta = esdtrack->Eta();
390 Double_t phi = esdtrack->Phi();
391 Int_t sign = esdtrack->Charge() > 0 ? 1 : -1;
392 miniEvt->push_back(MiniTrack(pt, eta, phi, sign));
397 //________________________________________________________________________
398 MiniEvent* AliDhcTask::GetAODTrax() const
400 // Loop twice: 1. Count sel. tracks. 2. Fill vector.
402 Int_t nTrax = fAOD->GetNumberOfTracks();
406 AliInfo(Form("%d tracks in event",nTrax));
409 for (Int_t i = 0; i < nTrax; ++i) {
410 AliAODTrack* aodtrack = fAOD->GetTrack(i);
412 AliError(Form("Couldn't get AOD track %d\n", i));
415 // See $ALICE_ROOT/ANALYSIS/macros/AddTaskESDFilter.C
416 UInt_t tpcOnly = 1 << 7;
417 Bool_t trkOK = aodtrack->TestFilterBit(tpcOnly);
420 Double_t pt = aodtrack->Pt();
421 Bool_t ptOK = pt >= fPtMin && pt < fPtMax;
424 Double_t eta = aodtrack->Eta();
425 if (TMath::Abs(eta) > fEtaMax)
430 MiniEvent* miniEvt = new MiniEvent(0);
431 miniEvt->reserve(nSelTrax);
434 for (Int_t i = 0; i < nTrax; ++i) {
435 AliAODTrack* aodtrack = fAOD->GetTrack(i);
437 AliError(Form("Couldn't get AOD track %d\n", i));
441 // See $ALICE_ROOT/ANALYSIS/macros/AddTaskESDFilter.C
442 UInt_t tpcOnly = 1 << 7;
443 Bool_t trkOK = aodtrack->TestFilterBit(tpcOnly);
446 Double_t pt = aodtrack->Pt();
447 Bool_t ptOK = pt >= fPtMin && pt < fPtMax;
450 Double_t eta = aodtrack->Eta();
451 if (TMath::Abs(eta) > fEtaMax)
454 Double_t phi = aodtrack->Phi();
455 Int_t sign = aodtrack->Charge() > 0 ? 1 : -1;
456 miniEvt->push_back(MiniTrack(pt, eta, phi, sign));
461 //________________________________________________________________________
462 Double_t AliDhcTask::DeltaPhi(Double_t phia, Double_t phib,
463 Double_t rangeMin, Double_t rangeMax) const
465 Double_t dphi = -999;
466 Double_t pi = TMath::Pi();
468 if (phia < 0) phia += 2*pi;
469 else if (phia > 2*pi) phia -= 2*pi;
470 if (phib < 0) phib += 2*pi;
471 else if (phib > 2*pi) phib -= 2*pi;
473 if (dphi < rangeMin) dphi += 2*pi;
474 else if (dphi > rangeMax) dphi -= 2*pi;
479 //________________________________________________________________________
480 Int_t AliDhcTask::Correlate(const MiniEvent &evt1, const MiniEvent &evt2,
481 Int_t pairing, Double_t /*weight*/)
483 // Triggered angular correlations. If pairing is kSameEvt, particles
484 // within evt1 are correlated. If kDiffEvt, correlate triggers from
485 // evt1 with partners from evt2.
487 Int_t cbin = fHCent->FindBin(fCentrality);
488 if (fHCent->IsBinOverflow(cbin) ||
489 fHCent->IsBinUnderflow(cbin))
492 Int_t zbin = fHZvtx->FindBin(fZVertex);
493 if (fHZvtx->IsBinOverflow(zbin) ||
494 fHZvtx->IsBinUnderflow(zbin))
497 Int_t iMax = evt1.size();
498 Int_t jMax = evt2.size();
501 if (pairing == kSameEvt) {
503 fHCent->AddBinContent(cbin);
504 fHZvtx->AddBinContent(zbin);
507 Int_t nZvtx = fHZvtx->GetNbinsX();
508 Int_t nPtTrig = fHPtTrg->GetNbinsX();
509 Int_t nPtAssc = fHPtAss->GetNbinsX();
511 Int_t globIndex = (cbin-1)*nZvtx*nPtTrig*nPtAssc+(zbin-1)*nPtTrig*nPtAssc;
513 for (Int_t i=0; i<iMax; ++i) {
516 const MiniTrack &a(evt1.at(i));
518 Float_t pta = a.Pt();
519 Int_t abin = fHPtTrg->FindBin(pta);
520 if (fHPtTrg->IsBinOverflow(abin) ||
521 fHPtTrg->IsBinUnderflow(abin))
524 if (pairing == kSameEvt) {
526 fHTrk->Fill(a.Phi(),a.Eta());
527 fHPtTrg->AddBinContent(abin);
530 for (Int_t j=0; j<jMax; ++j) {
531 // Associated particles
532 if (pairing == kSameEvt && i==j)
535 const MiniTrack &b(evt2.at(j));
537 Float_t ptb = b.Pt();
541 Int_t bbin = fHPtTrg->FindBin(ptb);
542 if (fHPtAss->IsBinOverflow(bbin) ||
543 fHPtAss->IsBinUnderflow(bbin))
546 Float_t dphi = DeltaPhi(a.Phi(), b.Phi());
547 Float_t deta = a.Eta() - b.Eta();
549 Int_t index = globIndex+(abin-1)*nPtAssc+(bbin-1);
550 hist[index]->Fill(dphi,deta);
552 if (pairing == kSameEvt) {
553 fHPtAss->AddBinContent(bbin);
554 fMeanPtTrg[cbin-1]->Fill(pta,ptb,pta);
555 fMeanPtAss[cbin-1]->Fill(pta,ptb,ptb);
556 fMean2PtTrg[cbin-1]->Fill(pta,ptb,pta*pta);
557 fMean2PtAss[cbin-1]->Fill(pta,ptb,ptb*ptb);
565 //________________________________________________________________________
566 void AliDhcTask::Terminate(Option_t *)
568 // Draw result to the screen
569 // Called once at the end of the query
573 fHCent->SetEntries(fHCent->Integral());
574 fHZvtx->SetEntries(fHZvtx->Integral());
575 fHPtTrg->SetEntries(fHPtTrg->Integral());
576 fHPtAss->SetEntries(fHPtAss->Integral());
578 if (gROOT->IsBatch())
581 fOutputList = dynamic_cast<TList*> (GetOutputData(1));
583 AliError("Output list not available");
587 fHistPt = dynamic_cast<TH1F*> (fOutputList->At(0));
589 AliError("ERROR: fHistPt not available\n");
593 TCanvas *c1 = new TCanvas("AliDhcTask","Pt",10,10,510,510);
594 c1->cd(1)->SetLogy();
595 fHistPt->DrawCopy("E");
598 //________________________________________________________________________
599 Bool_t AliDhcTask::VertexOk(TObject* obj) const
601 // Modified from AliAnalyseLeadingTrackUE::VertexSelection()
603 Int_t nContributors = 0;
604 Double_t zVertex = 999;
607 if (obj->InheritsFrom("AliESDEvent")) {
608 AliESDEvent* esdevt = (AliESDEvent*) obj;
609 const AliESDVertex* vtx = esdevt->GetPrimaryVertex();
612 nContributors = vtx->GetNContributors();
613 zVertex = vtx->GetZ();
614 name = vtx->GetName();
616 else if (obj->InheritsFrom("AliAODEvent")) {
617 AliAODEvent* aodevt = (AliAODEvent*) obj;
618 if (aodevt->GetNumberOfVertices() < 1)
620 const AliAODVertex* vtx = aodevt->GetPrimaryVertex();
621 nContributors = vtx->GetNContributors();
622 zVertex = vtx->GetZ();
623 name = vtx->GetName();
626 // Reject if TPC-only vertex
627 if (name.CompareTo("TPCVertex")==0)
630 // Check # contributors and range...
631 if( nContributors < 1 || TMath::Abs(zVertex) > fZVtxMax ) {