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 239 2012-12-12 17:25:09Z cmayer $
22 #include <THashList.h>
23 #include <THnSparse.h>
28 #include "AliEventPoolManager.h"
29 #include "AliAnalysisManager.h"
30 #include "AliAODEvent.h"
31 #include "AliAODMCHeader.h"
32 #include "AliAODMCParticle.h"
33 #include "AliMCEvent.h"
34 #include "AliInputEventHandler.h"
37 #include "AliAnalysisTaskLongRangeCorrelations.h"
40 ClassImp(AliAnalysisTaskLongRangeCorrelations);
41 ClassImp(LRCParticle);
43 AliAnalysisTaskLongRangeCorrelations::AliAnalysisTaskLongRangeCorrelations(const char *name)
44 : AliAnalysisTaskSE(name)
48 , fMixingTracks(50000)
50 , fCentMin(0), fCentMax(20)
51 , fPtMin(0.2), fPtMax(1e10)
52 , fPhiMin(0.), fPhiMax(TMath::TwoPi())
54 , fnBinsCent( 220), fnBinsPt(400), fnBinsPhi(4), fnBinsEta(120)
55 , fxMinCent( -5.0), fxMinPt( 0.0), fxMinPhi( 0.0), fxMinEta(-1.5)
56 , fxMaxCent(105.0), fxMaxPt( 4.0), fxMaxPhi( TMath::TwoPi()), fxMaxEta( 1.5) {
57 DefineInput(0, TChain::Class());
58 DefineOutput(1, TList::Class());
61 AliAnalysisTaskLongRangeCorrelations::~AliAnalysisTaskLongRangeCorrelations() {
62 if (NULL != fOutputList) {
68 void AliAnalysisTaskLongRangeCorrelations::UserCreateOutputObjects() {
69 fOutputList = new THashList;
70 fOutputList->SetOwner(kTRUE);
71 fOutputList->SetName(GetOutputListName());
74 const char* eventStatLabels[] = {
77 "Centrality Selection",
81 const size_t nEventStat(sizeof(eventStatLabels)/sizeof(const char*));
82 TH1* hStats(new TH1D("histEventStats", "histEventStats", nEventStat, -0.5, nEventStat-0.5));
83 for (size_t i(0); i<nEventStat; ++i)
84 hStats->GetXaxis()->SetBinLabel(1+i, eventStatLabels[i]);
85 fOutputList->Add(hStats);
88 fOutputList->Add(new TH1D("histQAVertexZ", ";vertex-z (cm)",
90 fOutputList->Add(new TH3D("histQACentPt", ";charge;centrality V0M(%);p_{T} (GeV/c)",
91 2, -0.5, 1.5, fnBinsCent, fxMinCent, fxMaxCent, fnBinsPt, fxMinPt, fxMaxPt));
92 fOutputList->Add(new TH3D("histQAPhiEta", ";charge;#phi (rad);#eta",
93 2, -0.5, 1.5, 200, 0.0, TMath::TwoPi(), 300, -1.5, 1.5));
95 // N(eta) distributions with different binnings
96 fOutputList->Add(new TH2D("histNEta_300", ";#eta;N", 300, -1.5, 1.5, 1000, 0., 1000.)); // 0.01
97 fOutputList->Add(new TH2D("histNEta_120", ";#eta;N", 120, -1.5, 1.5, 1000, 0., 1000.)); // 0.025
98 fOutputList->Add(new TH2D("histNEta__30", ";#eta;N", 30, -1.5, 1.5, 1000, 0., 1000.)); // 0.1
99 fOutputList->Add(new TH2D("histNEta__15", ";#eta;N", 15, -1.5, 1.5, 1000, 0., 1000.)); // 0.2
102 fOutputList->Add(MakeHistSparsePhiEta("histMoment1PhiEta_1"));
103 fOutputList->Add(MakeHistSparsePhiEta("histMoment1PhiEta_2"));
104 fOutputList->Add(MakeHistSparsePhiEtaPhiEta("histMoment2PhiEtaPhiEta_11"));
105 fOutputList->Add(MakeHistSparsePhiEtaPhiEta("histMoment2PhiEtaPhiEta_12"));
106 fOutputList->Add(MakeHistSparsePhiEtaPhiEta("histMoment2PhiEtaPhiEta_22"));
109 const Int_t N(fOutputList->GetEntries());
110 for (Int_t i(0); i<N; ++i)
111 fOutputList->Add(fOutputList->At(i)->Clone(TString("MC_")
112 + fOutputList->At(i)->GetName()));
117 PostData(1, fOutputList);
120 void AliAnalysisTaskLongRangeCorrelations::UserExec(Option_t* ) {
121 AliAnalysisManager* pManager(AliAnalysisManager::GetAnalysisManager());
122 if (NULL == pManager) return;
124 AliInputEventHandler* pInputHandler(dynamic_cast<AliInputEventHandler*>(pManager->GetInputEventHandler()));
125 if (NULL == pInputHandler) return;
127 AliAODEvent* pAOD(dynamic_cast<AliAODEvent*>(InputEvent()));
128 if (NULL == pAOD) return;
130 AliAODHeader *pAODHeader = pAOD->GetHeader();
131 if (NULL == pAODHeader) return;
133 AliAODMCHeader *pAODMCHeader(dynamic_cast<AliAODMCHeader*>(pAOD->FindListObject(AliAODMCHeader::StdBranchName())));
134 const Bool_t isMC(NULL != pAODMCHeader);
136 TClonesArray *arrayMC(NULL);
138 arrayMC = dynamic_cast<TClonesArray*>(pAOD->GetList()->FindObject(AliAODMCParticle::StdBranchName()));
139 if (NULL == arrayMC) return;
142 // --- event cuts MC ---
144 Fill("MC_histEventStats", 0.); // all events
145 Fill("MC_histEventStats", 1.); // events passing physics selection
146 Fill("MC_histEventStats", 2.); // events passing centrality selection
147 Fill("MC_histQAVertexZ", pAODMCHeader->GetVtxZ());
150 if (TMath::Abs(pAODMCHeader->GetVtxZ()) > fMaxAbsVertexZ) return;
151 Fill("MC_histEventStats", 3.); // events passing vertex selection
154 // --- event cuts data ---
155 Fill("histEventStats", 0.); // all events
157 if (!pInputHandler->IsEventSelected()) return;
158 Fill("histEventStats", 1.); // events passing physics selection
160 const Double_t centrality(pAODHeader->GetCentralityP()->GetCentralityPercentile("V0M"));
161 if (centrality < fCentMin || centrality >= fCentMax) return;
162 Fill("histEventStats", 2.); // events passing centrality selection
165 const Int_t nVertex(pAOD->GetNumberOfVertices());
166 if (0 == nVertex) return;
167 const AliAODVertex* pVertex(pAOD->GetPrimaryVertex());
168 if (NULL == pVertex) return;
169 const Int_t nTracksPrimary(pVertex->GetNContributors());
170 if (nTracksPrimary < 1) return;
172 const Double_t zVertex(pVertex->GetZ());
173 Fill("histQAVertexZ", zVertex);
174 if (TMath::Abs(zVertex) > fMaxAbsVertexZ) return;
176 Fill("histEventStats", 3.); // events passing vertex selection
179 TObjArray* tracksMain(GetAcceptedTracks(pAOD, centrality));
182 AliEventPool* pEventPool(fPoolMgr->GetEventPool(centrality, pAOD->GetPrimaryVertex()->GetZ()));
183 if (NULL == pEventPool)
184 AliFatal(Form("No pool found for centrality = %f, zVtx = %f", centrality, pAOD->GetPrimaryVertex()->GetZ()));
186 // pEventPool->PrintInfo();
187 if (pEventPool->IsReady()
188 || pEventPool->NTracksInPool() > fMixingTracks/10
189 || pEventPool->GetCurrentNEvents() >= 5) {
190 Fill("histEventStats", 4.); // analyzed events
191 const Int_t nMix(pEventPool->GetCurrentNEvents());
192 for (Int_t i(0); i<nMix; ++i) {
193 TObjArray* tracksMixed(pEventPool->GetEvent(i));
194 CalculateMoments("", tracksMain, tracksMixed, 1./nMix);
197 // Update the Event pool
198 pEventPool->UpdatePool(tracksMain);
199 } else { // no mixing
200 Fill("histEventStats", 4.); // analyzed events
201 CalculateMoments("", tracksMain, tracksMain, 1.);
206 TObjArray* tracksMC(GetAcceptedTracks(arrayMC, centrality));
207 Fill("MC_histEventStats", 4.); // analyzed MC events
208 CalculateMoments("MC_", tracksMC, tracksMC, 1.);
213 void AliAnalysisTaskLongRangeCorrelations::Terminate(Option_t* ) {
217 TString AliAnalysisTaskLongRangeCorrelations::GetOutputListName() const {
218 TString listName("listLRC");
219 listName += TString::Format("_%smix", fRunMixing ? "" : "no");
220 listName += TString::Format("_trackFilt%d", fTrackFilter);
221 listName += TString::Format("_cent%.0fT%.0f", fCentMin, fCentMax);
222 listName += TString::Format("_ptMin%.0fMeV", 1e3*fPtMin);
223 listName += TString::Format("_phi%.0fT%.0f", TMath::RadToDeg()*fPhiMin, TMath::RadToDeg()*fPhiMax);
227 void AliAnalysisTaskLongRangeCorrelations::SetupForMixing() {
228 const Int_t trackDepth(fMixingTracks);
229 const Int_t poolsize(1000); // Maximum number of events
231 Double_t centralityBins[] = { // centrality bins
232 // 0.,1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,15.,20.,25.,30.,35.,40.,45.,50.,55.,60.,65.,70.,75.,80.,90.,100.
235 const Int_t nCentralityBins(sizeof(centralityBins)/sizeof(Double_t) - 1);
237 Double_t vertexBins[] = { // Zvtx bins
238 -10., -7., -5., -3., -1., 1., 3., 5., 7., 10.
240 const Int_t nVertexBins(sizeof(vertexBins)/sizeof(Double_t) - 1);
242 fPoolMgr = new AliEventPoolManager(poolsize, trackDepth,
243 nCentralityBins, centralityBins,
244 nVertexBins, vertexBins);
247 THnSparse* AliAnalysisTaskLongRangeCorrelations::MakeHistSparsePhiEta(const char* name) const {
248 const Int_t nBinsM1[] = { fnBinsPhi, fnBinsEta };
249 const Double_t xMinM1[] = { fxMinPhi, fxMinEta };
250 const Double_t xMaxM1[] = { fxMaxPhi, fxMaxEta };
251 const TString title(TString(name)
253 return new THnSparseD(name, title.Data(), 2, nBinsM1, xMinM1, xMaxM1);
255 THnSparse* AliAnalysisTaskLongRangeCorrelations::MakeHistSparsePhiEtaPhiEta(const char* name) const {
256 const Int_t nBinsM2[] = { fnBinsPhi, fnBinsEta, fnBinsPhi, fnBinsEta };
257 const Double_t xMinM2[] = { fxMinPhi, fxMinEta, fxMinPhi, fxMinEta };
258 const Double_t xMaxM2[] = { fxMaxPhi, fxMaxEta, fxMaxPhi, fxMaxEta };
259 const TString title(TString(name)
260 +";#phi_{1};#eta_{1}"
261 +";#phi_{2};#eta_{2};");
262 return new THnSparseD(name, title.Data(), 4, nBinsM2, xMinM2, xMaxM2);
265 TObjArray* AliAnalysisTaskLongRangeCorrelations::GetAcceptedTracks(AliAODEvent* pAOD,
266 Double_t centrality) {
267 TObjArray* tracks= new TObjArray;
268 tracks->SetOwner(kTRUE);
270 const Long64_t N(pAOD->GetNumberOfTracks());
271 AliDebug(5, Form("#tracks= %6lld %f", N, centrality));
272 for (Long64_t i(0); i<N; ++i) {
273 AliAODTrack* pAODTrack(dynamic_cast<AliAODTrack*>(pAOD->GetTrack(i)));
274 if (NULL == pAODTrack) continue;
276 // track filter selection
277 if (!pAODTrack->TestFilterBit(fTrackFilter)) continue;
279 // select only primary tracks
280 if (pAODTrack->GetType() != AliAODTrack::kPrimary) continue;
282 // select only charged tracks
283 if (pAODTrack->Charge() == 0) continue;
285 Fill("histQACentPt", pAODTrack->Charge()>0, centrality, pAODTrack->Pt());
286 Fill("histQAPhiEta", pAODTrack->Charge()>0, pAODTrack->Phi(), pAODTrack->Eta());
287 if (pAODTrack->Phi() < fPhiMin || pAODTrack->Phi() > fPhiMax) continue;
288 if (pAODTrack->Pt() < fPtMin || pAODTrack->Pt() > fPtMax) continue;
290 tracks->Add(new LRCParticle(pAODTrack->Eta(), pAODTrack->Phi()));
295 TObjArray* AliAnalysisTaskLongRangeCorrelations::GetAcceptedTracks(TClonesArray* tracksMC,
296 Double_t centrality) {
297 TObjArray* tracks= new TObjArray;
298 tracks->SetOwner(kTRUE);
300 const Long64_t N(tracksMC->GetEntriesFast());
301 AliDebug(5, Form("#tracks= %6lld %f", N, centrality));
302 for (Long64_t i(0); i<N; ++i) {
303 AliAODMCParticle* pMCTrack(dynamic_cast<AliAODMCParticle*>(tracksMC->At(i)));
304 if (NULL == pMCTrack) continue;
306 // no track filter selection for MC tracks
308 // select only primary tracks
309 if (kFALSE == pMCTrack->IsPhysicalPrimary()) continue;
311 // select only charged tracks
312 if (pMCTrack->Charge() == 0) continue;
314 Fill("MC_histQACentPt", pMCTrack->Charge()>0, centrality, pMCTrack->Pt());
315 Fill("MC_histQAPhiEta", pMCTrack->Charge()>0, pMCTrack->Phi(), pMCTrack->Eta());
317 if (pMCTrack->Phi() < fPhiMin || pMCTrack->Phi() > fPhiMax) continue;
318 if (pMCTrack->Pt() < fPtMin || pMCTrack->Pt() > fPtMax) continue;
320 tracks->Add(new LRCParticle(pMCTrack->Eta(), pMCTrack->Phi()));
325 void AliAnalysisTaskLongRangeCorrelations::CalculateMoments(TString prefix,
329 THnSparse* hN1(dynamic_cast<THnSparse*>(fOutputList->FindObject(prefix+"histMoment1PhiEta_1")));
330 THnSparse* hN2(dynamic_cast<THnSparse*>(fOutputList->FindObject(prefix+"histMoment1PhiEta_2")));
331 if (NULL == hN1) return;
332 if (NULL == hN2) return;
335 THnSparse* hN1ForThisEvent(ComputeNForThisEvent(tracks1, "hN1"));
336 hN1->Add(hN1ForThisEvent, weight);
339 THnSparse* hN2ForThisEvent(ComputeNForThisEvent(tracks2, "hN2"));
340 hN2->Add(hN2ForThisEvent, weight);
342 // n(eta) distributions
343 FillNEtaHist(prefix+"histNEta_300", hN1ForThisEvent, weight);
344 FillNEtaHist(prefix+"histNEta_120", hN1ForThisEvent, weight);
345 FillNEtaHist(prefix+"histNEta__30", hN1ForThisEvent, weight);
346 FillNEtaHist(prefix+"histNEta__15", hN1ForThisEvent, weight);
348 TObjArray* hNs(new TObjArray);
351 hNs->AddAt(hN1ForThisEvent, 0);
352 hNs->AddAt(hN1ForThisEvent, 1);
353 ComputeNXForThisEvent(hNs, prefix+"histMoment2PhiEtaPhiEta_11", weight);
356 hNs->AddAt(hN2ForThisEvent, 1);
357 ComputeNXForThisEvent(hNs, prefix+"histMoment2PhiEtaPhiEta_12", weight);
360 hNs->AddAt(hN2ForThisEvent, 0);
361 ComputeNXForThisEvent(hNs, prefix+"histMoment2PhiEtaPhiEta_22", weight);
365 delete hN1ForThisEvent;
366 delete hN2ForThisEvent;
369 void AliAnalysisTaskLongRangeCorrelations::FillNEtaHist(TString name,
373 TH2* hSum(dynamic_cast<TH2*>(fOutputList->FindObject(name)));
374 if (NULL == hSum) return;
376 TH2* hPerEvent(dynamic_cast<TH2*>(hSum->Clone("hPerEvent")));
377 if (NULL == hPerEvent) return;
381 const Long64_t N(hs->GetNbins());
382 for (Long64_t i(0); i<N; ++i) {
383 Int_t coord[2] = { 0, 0 };
384 const Double_t n(hs->GetBinContent(i, coord));
385 const Double_t eta(hs->GetAxis(1)->GetBinCenter(coord[1]));
386 hPerEvent->Fill(eta, n);
389 // add zero counts for those eta bins with zero tracks
390 TH1* h(hPerEvent->ProjectionX());
391 for (Int_t i(1); i<=h->GetNbinsX(); ++i)
392 hPerEvent->SetBinContent(i,1, Double_t(h->GetBinContent(i) == 0));
394 hSum->Add(hPerEvent, weight);
400 THnSparse* AliAnalysisTaskLongRangeCorrelations::ComputeNForThisEvent(TObjArray* tracks, const char* histName) const {
401 THnSparse* hN(MakeHistSparsePhiEta(histName));
402 const Long64_t nTracks(tracks->GetEntriesFast());
403 for (Long64_t i(0); i<nTracks; ++i) {
404 const LRCParticle* p(dynamic_cast<LRCParticle*>(tracks->At(i)));
405 if (NULL == p) continue;
406 const Double_t x[] = { p->Phi(), p->Eta() };
412 class MultiDimIterator {
414 MultiDimIterator(TObjArray* _fHs)
416 , fN(fHs->GetEntriesFast())
422 for (Long64_t i=0; i<fN; ++i) {
423 THnSparse* hNi(reinterpret_cast<THnSparse*>(fHs->At(i)));
424 fDims[i] = hNi->GetNbins();
429 const Double_t* GetX() const { return &fX.front(); }
430 Double_t GetN() const {
431 return std::accumulate(fNs.begin(), fNs.end(), Double_t(1), std::multiplies<Double_t>());
433 Bool_t end() const { return fj == fN; }
435 MultiDimIterator& operator++() {
440 if (fIdxs[j] < fDims[j]) break;
449 void update(Long64_t j) {
451 THnSparse* hs(reinterpret_cast<THnSparse*>(fHs->At(j)));
452 Int_t coord[] = { 0, 0 };
453 fNs[j] = hs->GetBinContent(fIdxs[j], coord);
454 for (Int_t k(0); k<2; ++k)
455 fX[2*j+k] = hs->GetAxis(k)->GetBinCenter(coord[k]);
458 MultiDimIterator(const MultiDimIterator&);
459 MultiDimIterator& operator=(const MultiDimIterator&);
463 std::vector<Long64_t> fDims;
464 std::vector<Long64_t> fIdxs;
465 std::vector<Double_t> fNs;
466 std::vector<Double_t> fX;
470 void AliAnalysisTaskLongRangeCorrelations::ComputeNXForThisEvent(TObjArray* hNs,
471 const char* histName,
473 if (NULL == fOutputList) return;
475 THnSparse* hs(dynamic_cast<THnSparse*>(fOutputList->FindObject(histName)));
476 if (hs == NULL) return;
478 for (MultiDimIterator mdi(hNs); !mdi.end(); ++mdi)
479 hs->Fill(mdi.GetX(), mdi.GetN()*weight);
482 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, Double_t x) {
483 if (NULL == fOutputList) return;
484 TH1* h = dynamic_cast<TH1*>(fOutputList->FindObject(histName));
485 if (h == NULL) return;
488 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, Double_t x, Double_t y) {
489 if (NULL == fOutputList) return;
490 TH2* h = dynamic_cast<TH2*>(fOutputList->FindObject(histName));
491 if (h == NULL) return;
494 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, Double_t x, Double_t y, Double_t z) {
495 if (NULL == fOutputList) return;
496 TH3* h = dynamic_cast<TH3*>(fOutputList->FindObject(histName));
497 if (h == NULL) return;
500 void AliAnalysisTaskLongRangeCorrelations::Fill(const char* histName, const Double_t* x, Double_t w) {
501 if (NULL == fOutputList) return;
502 THnSparse* h = dynamic_cast<THnSparse*>(fOutputList->FindObject(histName));
503 if (h == NULL) return;