2 /**************************************************************************
3 * Copyright(c) 2012, ALICE Experiment at CERN, All rights reserved. *
5 * Author: The ALICE Off-line Project. *
6 * Contributors are mentioned in the code where appropriate. *
8 * Permission to use, copy, modify and distribute this software and its *
9 * documentation strictly for non-commercial purposes is hereby granted *
10 * without fee, provided that the above copyright notice appears in all *
11 * copies and that both the copyright notice and this permission notice *
12 * appear in the supporting documentation. The authors make no claims *
13 * about the suitability of this software for any purpose. It is *
14 * provided "as is" without express or implied warranty. *
15 **************************************************************************/
16 // $Id: AliAnalysisTaskLongRangeCorrelations.cxx 283 2013-03-26 19:07:58Z cmayer $
23 #include <THashList.h>
24 #include <THnSparse.h>
29 #include "AliEventPoolManager.h"
30 #include "AliAnalysisManager.h"
31 #include "AliAODEvent.h"
32 #include "AliAODMCHeader.h"
33 #include "AliAODMCParticle.h"
34 #include "AliMCEvent.h"
35 #include "AliInputEventHandler.h"
38 #include "AliAnalysisTaskLongRangeCorrelations.h"
41 ClassImp(AliAnalysisTaskLongRangeCorrelations);
42 ClassImp(LRCParticle);
44 AliAnalysisTaskLongRangeCorrelations::AliAnalysisTaskLongRangeCorrelations(const char *name)
45 : AliAnalysisTaskSE(name)
50 , fMixingTracks(50000)
52 , fCentMin(0), fCentMax(20)
53 , fPtMin(0.2), fPtMax(1e10)
54 , fPhiMin(0.), fPhiMax(TMath::TwoPi())
56 , fnBinsCent( 220), fnBinsPt(400), fnBinsPhi(4), fnBinsEta(120)
57 , fxMinCent( -5.0), fxMinPt( 0.0), fxMinPhi( 0.0), fxMinEta(-1.5)
58 , fxMaxCent(105.0), fxMaxPt( 4.0), fxMaxPhi( TMath::TwoPi()), fxMaxEta( 1.5) {
59 DefineInput(0, TChain::Class());
60 DefineOutput(1, TList::Class());
63 AliAnalysisTaskLongRangeCorrelations::~AliAnalysisTaskLongRangeCorrelations() {
64 if (NULL != fOutputList) {
70 void AliAnalysisTaskLongRangeCorrelations::UserCreateOutputObjects() {
71 fOutputList = new THashList;
72 fOutputList->SetOwner(kTRUE);
73 fOutputList->SetName(GetOutputListName());
75 const Double_t vertexBins[] = { // Zvtx bins
76 -10., -7., -5., -3., -1., 1., 3., 5., 7., 10.
78 fVertexZ = new TAxis(sizeof(vertexBins)/sizeof(Double_t)-1, vertexBins);
79 fVertexZ->SetName("VertexZAxis");
80 fOutputList->Add(fVertexZ);
83 const char* eventStatLabels[] = {
86 "Centrality Selection",
90 const size_t nEventStat(sizeof(eventStatLabels)/sizeof(const char*));
91 TH1* hStats(new TH1D("histEventStats", "histEventStats", nEventStat, -0.5, nEventStat-0.5));
92 for (size_t i(0); i<nEventStat; ++i)
93 hStats->GetXaxis()->SetBinLabel(1+i, eventStatLabels[i]);
94 fOutputList->Add(hStats);
97 fOutputList->Add(new TH2D("histQACentrality", ";centrality V0M(%);selected;",
98 fnBinsCent,fxMinCent,fxMaxCent, 2, -0.5, 1.5));
99 fOutputList->Add(new TH2D("histQAVertexZ", ";vertex-z (cm);selected;",
100 800, -40., 40., 2, -0.5, 1.5));
101 fOutputList->Add(new TH1D("histQAMultiplicityBeforeCuts",
102 ";tracks", 10000, 0, 10000));
103 fOutputList->Add(new TH1D("histQAMultiplicityAfterCuts",
104 ";selected tracks", 10000, 0, 10000));
105 fOutputList->Add(new TH3D("histQACentPt", ";charge;centrality V0M(%);p_{T} (GeV/c)",
106 2, -0.5, 1.5, fnBinsCent, fxMinCent, fxMaxCent, fnBinsPt, fxMinPt, fxMaxPt));
107 fOutputList->Add(new TH3D("histQAPhiEta", ";charge;#phi (rad);#eta",
108 2, -0.5, 1.5, 200, 0.0, TMath::TwoPi(), 300, -1.5, 1.5));
110 // N(eta) distributions with different binnings
111 fOutputList->Add(new TH2D("histNEta_300", ";#eta;N", 300, -1.5, 1.5, 1000, 0., 1000.)); // 0.01
112 fOutputList->Add(new TH2D("histNEta_120", ";#eta;N", 120, -1.5, 1.5, 1000, 0., 1000.)); // 0.025
113 fOutputList->Add(new TH2D("histNEta__30", ";#eta;N", 30, -1.5, 1.5, 1000, 0., 1000.)); // 0.1
114 fOutputList->Add(new TH2D("histNEta__15", ";#eta;N", 15, -1.5, 1.5, 1000, 0., 1000.)); // 0.2
117 fOutputList->Add(MakeHistSparsePhiEta("histMoment1PhiEta_1"));
118 fOutputList->Add(MakeHistSparsePhiEta("histMoment1PhiEta_2"));
119 fOutputList->Add(MakeHistSparsePhiEtaPhiEta("histMoment2PhiEtaPhiEta_11"));
120 fOutputList->Add(MakeHistSparsePhiEtaPhiEta("histMoment2PhiEtaPhiEta_12"));
121 fOutputList->Add(MakeHistSparsePhiEtaPhiEta("histMoment2PhiEtaPhiEta_22"));
124 const Int_t N(fOutputList->GetEntries());
125 for (Int_t i(0); i<N; ++i)
126 fOutputList->Add(fOutputList->At(i)->Clone(TString("MC_") + fOutputList->At(i)->GetName()));
131 PostData(1, fOutputList);
134 void AliAnalysisTaskLongRangeCorrelations::UserExec(Option_t* ) {
135 AliAnalysisManager* pManager(AliAnalysisManager::GetAnalysisManager());
136 if (NULL == pManager) return;
138 AliInputEventHandler* pInputHandler(dynamic_cast<AliInputEventHandler*>(pManager->GetInputEventHandler()));
139 if (NULL == pInputHandler) return;
141 AliAODEvent* pAOD(dynamic_cast<AliAODEvent*>(InputEvent()));
142 if (NULL == pAOD) return;
144 AliAODHeader *pAODHeader = pAOD->GetHeader();
145 if (NULL == pAODHeader) return;
147 AliAODMCHeader *pAODMCHeader(dynamic_cast<AliAODMCHeader*>(pAOD->FindListObject(AliAODMCHeader::StdBranchName())));
148 const Bool_t isMC(NULL != pAODMCHeader);
150 TClonesArray *arrayMC(NULL);
152 arrayMC = dynamic_cast<TClonesArray*>(pAOD->GetList()->FindObject(AliAODMCParticle::StdBranchName()));
153 if (NULL == arrayMC) return;
156 // --- event cuts MC ---
158 Fill("MC_histEventStats", 0.); // all events
159 Fill("MC_histEventStats", 1.); // events passing physics selection
160 Fill("MC_histEventStats", 2.); // events passing centrality selection
162 const Bool_t vertexSelected(TMath::Abs(pAODMCHeader->GetVtxZ()) < fMaxAbsVertexZ);
163 Fill("MC_histQAVertexZ", pAODMCHeader->GetVtxZ(), vertexSelected);
164 if (!vertexSelected) return;
165 Fill("MC_histEventStats", 3.); // events passing vertex selection
168 // --- event cuts data ---
169 Fill("histEventStats", 0.); // all events
171 if (!pInputHandler->IsEventSelected()) return;
172 Fill("histEventStats", 1.); // events passing physics selection
174 const Double_t centrality(pAODHeader->GetCentralityP()->GetCentralityPercentile("V0M"));
175 AliDebug(3, Form("centrality=%f", centrality));
176 const Bool_t centralitySelected(centrality > fCentMin && centrality < fCentMax);
177 Fill("histQACentrality", centrality, centralitySelected);
178 if (!centralitySelected) return;
179 Fill("histEventStats", 2.); // events passing centrality selection
182 const Int_t nVertex(pAOD->GetNumberOfVertices());
183 if (0 == nVertex) return;
184 const AliAODVertex* pVertex(pAOD->GetPrimaryVertex());
185 if (NULL == pVertex) return;
186 const Int_t nTracksPrimary(pVertex->GetNContributors());
187 if (nTracksPrimary < 1) return;
189 const Double_t zVertex(pVertex->GetZ());
190 const Bool_t vertexSelected(TMath::Abs(zVertex) < fMaxAbsVertexZ);
191 Fill("histQAVertexZ", zVertex, vertexSelected);
192 if (!vertexSelected) return;
193 Fill("histEventStats", 3.); // events passing vertex selection
196 TObjArray* tracksMain(GetAcceptedTracks(pAOD, centrality));
197 Fill("histQAMultiplicityBeforeCuts", pAOD->GetNumberOfTracks());
198 Fill("histQAMultiplicityAfterCuts", tracksMain->GetEntriesFast());
201 AliEventPool* pEventPool(fPoolMgr->GetEventPool(centrality, pAOD->GetPrimaryVertex()->GetZ()));
202 if (NULL == pEventPool)
203 AliFatal(Form("No pool found for centrality = %f, zVtx = %f", centrality, pAOD->GetPrimaryVertex()->GetZ()));
205 // pEventPool->PrintInfo();
206 if (pEventPool->IsReady()
207 || pEventPool->NTracksInPool() > fMixingTracks/10
208 || pEventPool->GetCurrentNEvents() >= 5) {
209 Fill("histEventStats", 4.); // analyzed events
210 const Int_t nMix(pEventPool->GetCurrentNEvents());
211 for (Int_t i(0); i<nMix; ++i) {
212 TObjArray* tracksMixed(pEventPool->GetEvent(i));
213 CalculateMoments("", tracksMain, tracksMixed, zVertex, 1./nMix);
216 // Update the Event pool
217 pEventPool->UpdatePool(tracksMain);
218 } else { // no mixing
219 Fill("histEventStats", 4.); // analyzed events
220 CalculateMoments("", tracksMain, tracksMain, zVertex, 1.);
225 TObjArray* tracksMC(GetAcceptedTracks(arrayMC, centrality));
226 const Double_t x[2] = {
227 arrayMC->GetEntriesFast(),
228 tracksMC->GetEntriesFast()
230 Fill("MC_histQAMultiplicity", x);
231 Fill("MC_histEventStats", 4.); // analyzed MC events
232 CalculateMoments("MC_", tracksMC, tracksMC, zVertex, 1.);
237 void AliAnalysisTaskLongRangeCorrelations::Terminate(Option_t* ) {
241 TString AliAnalysisTaskLongRangeCorrelations::GetOutputListName() const {
242 TString listName("listLRC");
243 listName += TString::Format("_%smix", fRunMixing ? "" : "no");
244 listName += TString::Format("_trackFilt%d", fTrackFilter);
245 listName += TString::Format("_cent%.0fT%.0f", fCentMin, fCentMax);
246 listName += TString::Format("_ptMin%.0fMeV", 1e3*fPtMin);
247 listName += TString::Format("_phi%.0fT%.0f", TMath::RadToDeg()*fPhiMin, TMath::RadToDeg()*fPhiMax);
251 void AliAnalysisTaskLongRangeCorrelations::SetupForMixing() {
252 const Int_t trackDepth(fMixingTracks);
253 const Int_t poolsize(1000); // Maximum number of events
255 Double_t centralityBins[] = { fCentMin, fCentMax };
256 const Int_t nCentralityBins(sizeof(centralityBins)/sizeof(Double_t) - 1);
258 fPoolMgr = new AliEventPoolManager(poolsize, trackDepth,
259 nCentralityBins, centralityBins,
260 fVertexZ->GetNbins()+1,
261 const_cast<Double_t*>(fVertexZ->GetXbins()->GetArray()));
264 THnSparse* AliAnalysisTaskLongRangeCorrelations::MakeHistSparsePhiEta(const char* name) const {
265 const Int_t nVertexZBins=fVertexZ->GetNbins();
266 const Int_t nBinsM1[] = { fnBinsPhi, fnBinsEta, nVertexZBins };
267 const Double_t xMinM1[] = { fxMinPhi, fxMinEta, 0.5 };
268 const Double_t xMaxM1[] = { fxMaxPhi, fxMaxEta, nVertexZBins+0.5 };
269 const TString title(TString(name)
270 +";#phi;#eta;vertex Z (bin);");
271 return new THnSparseD(name, title.Data(), 3, nBinsM1, xMinM1, xMaxM1);
273 THnSparse* AliAnalysisTaskLongRangeCorrelations::MakeHistSparsePhiEtaPhiEta(const char* name) const {
274 const Int_t nVertexZBins=fVertexZ->GetNbins();
275 const Int_t nBinsM2[] = { fnBinsPhi, fnBinsEta, fnBinsPhi, fnBinsEta, nVertexZBins };
276 const Double_t xMinM2[] = { fxMinPhi, fxMinEta, fxMinPhi, fxMinEta, 0.5 };
277 const Double_t xMaxM2[] = { fxMaxPhi, fxMaxEta, fxMaxPhi, fxMaxEta, nVertexZBins+0.5 };
278 const TString title(TString(name)
279 +";#phi_{1};#eta_{1}"
280 +";#phi_{2};#eta_{2};vertex Z (bin);");
281 return new THnSparseD(name, title.Data(), 5, nBinsM2, xMinM2, xMaxM2);
284 TObjArray* AliAnalysisTaskLongRangeCorrelations::GetAcceptedTracks(AliAODEvent* pAOD,
285 Double_t centrality) {
286 TObjArray* tracks= new TObjArray;
287 tracks->SetOwner(kTRUE);
289 const Long64_t N(pAOD->GetNumberOfTracks());
290 AliDebug(5, Form("#tracks= %6lld %f", N, centrality));
291 for (Long64_t i(0); i<N; ++i) {
292 AliAODTrack* pAODTrack(dynamic_cast<AliAODTrack*>(pAOD->GetTrack(i)));
293 if (NULL == pAODTrack) continue;
295 // track filter selection
296 if (!pAODTrack->TestFilterBit(fTrackFilter)) continue;
298 // select only primary tracks
299 if (pAODTrack->GetType() != AliAODTrack::kPrimary) continue;
301 // select only charged tracks
302 if (pAODTrack->Charge() == 0) continue;
304 Fill("histQACentPt", pAODTrack->Charge()>0, centrality, pAODTrack->Pt());
305 Fill("histQAPhiEta", pAODTrack->Charge()>0, pAODTrack->Phi(), pAODTrack->Eta());
306 if (pAODTrack->Phi() < fPhiMin || pAODTrack->Phi() > fPhiMax) continue;
307 if (pAODTrack->Pt() < fPtMin || pAODTrack->Pt() > fPtMax) continue;
309 tracks->Add(new LRCParticle(pAODTrack->Eta(), pAODTrack->Phi()));
314 TObjArray* AliAnalysisTaskLongRangeCorrelations::GetAcceptedTracks(TClonesArray* tracksMC,
315 Double_t centrality) {
316 // for keeping track of MC labels
317 std::set<Int_t> labelSet;
319 TObjArray* tracks= new TObjArray;
320 tracks->SetOwner(kTRUE);
322 const Long64_t N(tracksMC->GetEntriesFast());
323 AliDebug(5, Form("#tracks= %6lld %f", N, centrality));
324 for (Long64_t i(0); i<N; ++i) {
325 AliAODMCParticle* pMCTrack(dynamic_cast<AliAODMCParticle*>(tracksMC->At(i)));
326 if (NULL == pMCTrack) continue;
328 // no track filter selection for MC tracks
330 if (labelSet.find(pMCTrack->Label()) != labelSet.end()) {
331 Printf("Duplicate Label= %3d", pMCTrack->Label());
334 labelSet.insert(pMCTrack->Label());
336 // select only primary tracks
337 if (kFALSE == pMCTrack->IsPhysicalPrimary()) continue;
339 // select only charged tracks
340 if (pMCTrack->Charge() == 0) continue;
342 Fill("MC_histQACentPt", pMCTrack->Charge()>0, centrality, pMCTrack->Pt());
343 Fill("MC_histQAPhiEta", pMCTrack->Charge()>0, pMCTrack->Phi(), pMCTrack->Eta());
345 if (pMCTrack->Phi() < fPhiMin || pMCTrack->Phi() > fPhiMax) continue;
346 if (pMCTrack->Pt() < fPtMin || pMCTrack->Pt() > fPtMax) continue;
348 tracks->Add(new LRCParticle(pMCTrack->Eta(), pMCTrack->Phi()));
353 void AliAnalysisTaskLongRangeCorrelations::CalculateMoments(TString prefix,
358 THnSparse* hN1(dynamic_cast<THnSparse*>(fOutputList->FindObject(prefix+"histMoment1PhiEta_1")));
359 THnSparse* hN2(dynamic_cast<THnSparse*>(fOutputList->FindObject(prefix+"histMoment1PhiEta_2")));
360 if (NULL == hN1) return;
361 if (NULL == hN2) return;
364 THnSparse* hN1ForThisEvent(ComputeNForThisEvent(tracks1, "hN1", vertexZ));
365 hN1->Add(hN1ForThisEvent, weight);
368 THnSparse* hN2ForThisEvent(ComputeNForThisEvent(tracks2, "hN2", vertexZ));
369 hN2->Add(hN2ForThisEvent, weight);
371 // n(eta) distributions
372 FillNEtaHist(prefix+"histNEta_300", hN1ForThisEvent, weight);
373 FillNEtaHist(prefix+"histNEta_120", hN1ForThisEvent, weight);
374 FillNEtaHist(prefix+"histNEta__30", hN1ForThisEvent, weight);
375 FillNEtaHist(prefix+"histNEta__15", hN1ForThisEvent, weight);
377 TObjArray* hNs(new TObjArray);
380 hNs->AddAt(hN1ForThisEvent, 0);
381 hNs->AddAt(hN1ForThisEvent, 1);
382 ComputeNXForThisEvent(hNs, prefix+"histMoment2PhiEtaPhiEta_11", vertexZ, weight);
385 hNs->AddAt(hN2ForThisEvent, 1);
386 ComputeNXForThisEvent(hNs, prefix+"histMoment2PhiEtaPhiEta_12", vertexZ, weight);
389 hNs->AddAt(hN2ForThisEvent, 0);
390 ComputeNXForThisEvent(hNs, prefix+"histMoment2PhiEtaPhiEta_22", vertexZ, weight);
394 delete hN1ForThisEvent;
395 delete hN2ForThisEvent;
398 void AliAnalysisTaskLongRangeCorrelations::FillNEtaHist(TString name,
402 TH2* hSum(dynamic_cast<TH2*>(fOutputList->FindObject(name)));
403 if (NULL == hSum) return;
405 TH2* hPerEvent(dynamic_cast<TH2*>(hSum->Clone("hPerEvent")));
406 if (NULL == hPerEvent) return;
410 const Long64_t N(hs->GetNbins());
411 for (Long64_t i(0); i<N; ++i) {
412 Int_t coord[2] = { 0, 0 };
413 const Double_t n(hs->GetBinContent(i, coord));
414 const Double_t eta(hs->GetAxis(1)->GetBinCenter(coord[1]));
415 hPerEvent->Fill(eta, n);
418 // add zero counts for those eta bins with zero tracks
419 TH1* h(hPerEvent->ProjectionX());
420 for (Int_t i(1); i<=h->GetNbinsX(); ++i)
421 hPerEvent->SetBinContent(i,1, Double_t(h->GetBinContent(i) == 0));
423 hSum->Add(hPerEvent, weight);
429 THnSparse* AliAnalysisTaskLongRangeCorrelations::ComputeNForThisEvent(TObjArray* tracks,
430 const char* histName,
431 Double_t vertexZ) const {
432 const Double_t vertexZBin(fVertexZ->FindBin(vertexZ));
433 THnSparse* hN(MakeHistSparsePhiEta(histName));
434 const Long64_t nTracks(tracks->GetEntriesFast());
435 for (Long64_t i(0); i<nTracks; ++i) {
436 const LRCParticle* p(dynamic_cast<LRCParticle*>(tracks->At(i)));
437 if (NULL == p) continue;
438 const Double_t x[] = { p->Phi(), p->Eta(), vertexZBin };
444 class MultiDimIterator {
446 MultiDimIterator(TObjArray* _fHs, Double_t vertexZBin)
448 , fN(fHs->GetEntriesFast())
454 for (Long64_t i=0; i<fN; ++i) {
455 THnSparse* hNi(reinterpret_cast<THnSparse*>(fHs->At(i)));
457 AliFatal("NULL == hNi");
458 fDims[i] = hNi->GetNbins();
459 AliDebug(3, Form("%lld %s %lld", i, hNi->GetName(), fDims[i]));
462 fX[2*fN] = vertexZBin;
465 const char* ClassName() const { return "MultiDimIterator"; }
466 const Double_t* GetX() const { return &fX.front(); }
467 Double_t GetN() const { // returns the product of all multiplicities
468 return std::accumulate(fNs.begin(), fNs.end(), Double_t(1), std::multiplies<Double_t>());
470 Bool_t end() const { return fj == fN; }
472 MultiDimIterator& operator++() {
477 if (fIdxs[j] < fDims[j]) break;
486 void update(Long64_t j) {
487 THnSparse* hs(reinterpret_cast<THnSparse*>(fHs->At(j)));
488 Int_t coord[] = { 0, 0 };
489 fNs[j] = hs->GetBinContent(fIdxs[j], coord);
490 for (Int_t k(0); k<2; ++k)
491 fX[2*j+k] = hs->GetAxis(k)->GetBinCenter(coord[k]);
494 MultiDimIterator(const MultiDimIterator&);
495 MultiDimIterator& operator=(const MultiDimIterator&);
497 TObjArray* fHs; // array of THnSparse histograms
498 const Long64_t fN; // number of histograms
499 std::vector<Long64_t> fDims; // number of filled bins for each THnSparse
500 std::vector<Long64_t> fIdxs; // indices
501 std::vector<Double_t> fNs; // number of tracks
502 std::vector<Double_t> fX; // coordinate
503 Long64_t fj; // state
506 void AliAnalysisTaskLongRangeCorrelations::ComputeNXForThisEvent(TObjArray* hNs,
507 const char* histName,
510 if (NULL == fOutputList) return;
512 THnSparse* hs(dynamic_cast<THnSparse*>(fOutputList->FindObject(histName)));
513 if (hs == NULL) return;
515 for (MultiDimIterator mdi(hNs, fVertexZ->FindBin(vertexZ)); !mdi.end(); ++mdi)
516 hs->Fill(mdi.GetX(), mdi.GetN()*weight);
519 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, Double_t x) {
520 if (NULL == fOutputList) return;
521 TH1* h = dynamic_cast<TH1*>(fOutputList->FindObject(histName));
522 if (h == NULL) return;
525 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, Double_t x, Double_t y) {
526 if (NULL == fOutputList) return;
527 TH2* h = dynamic_cast<TH2*>(fOutputList->FindObject(histName));
528 if (h == NULL) return;
531 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, Double_t x, Double_t y, Double_t z) {
532 if (NULL == fOutputList) return;
533 TH3* h = dynamic_cast<TH3*>(fOutputList->FindObject(histName));
534 if (h == NULL) return;
537 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, const Double_t* x, Double_t w) {
538 if (NULL == fOutputList) return;
539 THnSparse* h = dynamic_cast<THnSparse*>(fOutputList->FindObject(histName));
540 if (h == NULL) return;