]> git.uio.no Git - u/mrichter/AliRoot.git/blob - PWGCF/Correlations/DPhi/AliAnalysisTaskPhiCorrelations.cxx
option to skip fast cluster
[u/mrichter/AliRoot.git] / PWGCF / Correlations / DPhi / AliAnalysisTaskPhiCorrelations.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
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  **************************************************************************/
15
16 /* $Id:$ */
17
18 #include <TROOT.h>
19 #include <TChain.h>
20 #include <TFile.h>
21 #include <TList.h>
22 #include <TMath.h>
23 #include <TTree.h>
24 #include <TH2F.h>
25 #include <TH3F.h>
26 #include <TRandom.h>
27
28 #include "AliAnalysisTaskPhiCorrelations.h"
29 #include "AliAnalyseLeadingTrackUE.h"
30 #include "AliUEHistograms.h"
31 #include "AliUEHist.h"
32
33 #include "AliAnalysisManager.h"
34 #include "AliAODHandler.h"
35 #include "AliAODInputHandler.h"
36 #include "AliAODMCParticle.h"
37 #include "AliInputEventHandler.h"
38 #include "AliLog.h"
39 #include "AliMCEventHandler.h"
40 #include "AliVParticle.h"
41 #include "AliCFContainer.h"
42
43 #include "AliESDEvent.h"
44 #include "AliESDInputHandler.h"
45 #include "AliMultiplicity.h"
46 #include "AliCentrality.h"
47 #include "AliStack.h"
48 #include "AliAODMCHeader.h"
49 #include "AliGenCocktailEventHeader.h"
50 #include "AliGenEventHeader.h"
51
52 #include "AliEventPoolManager.h"
53
54 #include "AliESDZDC.h"
55 #include "AliESDtrackCuts.h"
56
57
58 ////////////////////////////////////////////////////////////////////////
59 //
60 // Analysis class for azimuthal correlation studies
61 // Based on the UE task from Sara Vallero and Jan Fiete
62 //
63 // This class needs input AODs.
64 // The output is a list of analysis-specific containers.
65 //
66 // The AOD can be either connected to the InputEventHandler  
67 // for a chain of AOD files 
68 // or 
69 // to the OutputEventHandler
70 // for a chain of ESD files,
71 // in this case the class should be in the train after the jet-finder
72 //
73 //    Authors:
74 //    Jan Fiete Grosse-Oetringhaus
75 // 
76 ////////////////////////////////////////////////////////////////////////
77
78
79 ClassImp( AliAnalysisTaskPhiCorrelations )
80 ClassImp( AliDPhiBasicParticle )
81
82 //____________________________________________________________________
83 AliAnalysisTaskPhiCorrelations:: AliAnalysisTaskPhiCorrelations(const char* name):
84 AliAnalysisTask(name,""),
85 // general configuration
86 fDebug(0),
87 fMode(0),
88 fReduceMemoryFootprint(kFALSE),
89 fFillMixed(kTRUE),
90 fMixingTracks(50000),
91 fCompareCentralities(kFALSE),
92 fTwoTrackEfficiencyStudy(kFALSE),
93 fTwoTrackEfficiencyCut(0),
94 fUseVtxAxis(kFALSE),
95 fCourseCentralityBinning(kFALSE),
96 fSkipTrigger(kFALSE),
97 fInjectedSignals(kFALSE),
98 // pointers to UE classes
99 fAnalyseUE(0x0),
100 fHistos(0x0),
101 fHistosMixed(0),
102 fEfficiencyCorrection(0),
103 fCorrectTriggers(kFALSE),
104 // handlers and events
105 fAOD(0x0),
106 fESD(0x0),
107 fArrayMC(0x0),
108 fInputHandler(0x0),
109 fMcEvent(0x0),
110 fMcHandler(0x0),
111 fPoolMgr(0x0),
112 // histogram settings
113 fListOfHistos(0x0), 
114 // event QA
115 fnTracksVertex(1),  // QA tracks pointing to principal vertex (= 3 default) 
116 fZVertex(7.),
117 fCentralityMethod("V0M"),
118 // track cuts
119 fTrackEtaCut(0.8),
120 fOnlyOneEtaSide(0),
121 fPtMin(0.5),
122 fFilterBit(0xFF),
123 fSelectBit(AliVEvent::kMB|AliVEvent::kUserDefined),
124 fUseChargeHadrons(kFALSE),
125 fSelectCharge(0),
126 fTriggerSelectCharge(0),
127 fTriggerRestrictEta(-1),
128 fEtaOrdering(kFALSE),
129 fCutConversions(kFALSE),
130 fCutResonances(kFALSE),
131 fFillOnlyStep0(kFALSE),
132 fSkipStep6(kFALSE),
133 fRejectCentralityOutliers(kFALSE),
134 fRemoveWeakDecays(kFALSE),
135 fRemoveDuplicates(kFALSE),
136 fSkipFastCluster(kFALSE),
137 fFillpT(kFALSE)
138 {
139   // Default constructor
140   // Define input and output slots here
141   // Input slot #0 works with a TChain
142   DefineInput(0, TChain::Class());
143   // Output slot #0 writes into a TList container
144   DefineOutput(0, TList::Class());
145 }
146
147 AliAnalysisTaskPhiCorrelations::~AliAnalysisTaskPhiCorrelations() 
148
149   // destructor
150   
151   if (fListOfHistos  && !AliAnalysisManager::GetAnalysisManager()->IsProofMode()) 
152     delete fListOfHistos;
153 }
154
155 //____________________________________________________________________
156 void AliAnalysisTaskPhiCorrelations::ConnectInputData(Option_t* /*option*/)
157 {
158   
159   // Connect the input data  
160   if (fDebug > 1) AliInfo("ConnectInputData() ");
161   
162   // Since AODs can either be connected to the InputEventHandler
163   // or to the OutputEventHandler ( the AOD is created by a previus task in the train )
164   // we need to get the pointer to the AODEvent correctly.
165   
166   // Delta AODs are also accepted.
167   
168   TObject* handler = AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler();
169   
170   if( handler && handler->InheritsFrom("AliAODInputHandler") ) 
171   { // input AOD
172     fAOD = ((AliAODInputHandler*)handler)->GetEvent();
173     if (fDebug > 1) AliInfo(" ==== Tracks and Jets from AliAODInputHandler");
174   } 
175   else 
176   {  //output AOD
177     handler = AliAnalysisManager::GetAnalysisManager()->GetOutputEventHandler();
178     if (handler && handler->InheritsFrom("AliAODHandler") ) 
179     {
180       fAOD = ((AliAODHandler*)handler)->GetAOD();
181       if (fDebug > 1) AliInfo(" ==== Tracks and Jets from AliAODHandler");
182     } 
183     else 
184     {  // no AOD
185       AliWarning("I can't get any AOD Event Handler");
186     }
187   }
188   
189   if (handler && handler->InheritsFrom("AliESDInputHandler") ) 
190   { // input ESD
191     // pointer received per event in ::Exec
192     if (fDebug > 1) AliInfo(" ==== Tracks and Jets from AliESDInputHandler");
193   } 
194   
195   // Initialize common pointers
196   Initialize();
197 }
198
199 //____________________________________________________________________
200 void  AliAnalysisTaskPhiCorrelations::CreateOutputObjects()
201 {
202   // Create the output container
203   
204   if (fDebug > 1) AliInfo("CreateOutputObjects()");
205    
206   // Initialize class with main algorithms, event and track selection. 
207   fAnalyseUE = new AliAnalyseLeadingTrackUE();
208   fAnalyseUE->SetParticleSelectionCriteria(fFilterBit, fUseChargeHadrons, fTrackEtaCut, fPtMin);
209   fAnalyseUE->SetDebug(fDebug); 
210   fAnalyseUE->DefineESDCuts(fFilterBit);
211   fAnalyseUE->SetEventSelection(fSelectBit);
212
213   // Initialize output list of containers
214   if (fListOfHistos != NULL){
215         delete fListOfHistos;
216         fListOfHistos = NULL;
217         }
218   if (!fListOfHistos){
219         fListOfHistos = new TList();
220         fListOfHistos->SetOwner(kTRUE); 
221         }
222
223   // Initialize class to handle histograms 
224   TString histType = "4R";
225   if (fUseVtxAxis == 1)
226     histType = "5R";
227   else if (fUseVtxAxis == 2)
228     histType = "6R";
229   if (fCourseCentralityBinning)
230     histType += "C";
231   fHistos = new AliUEHistograms("AliUEHistogramsSame", histType);
232   fHistosMixed = new AliUEHistograms("AliUEHistogramsMixed", histType);
233   
234   fHistos->SetSelectCharge(fSelectCharge);
235   fHistosMixed->SetSelectCharge(fSelectCharge);
236   
237   fHistos->SetSelectTriggerCharge(fTriggerSelectCharge);
238   fHistosMixed->SetSelectTriggerCharge(fTriggerSelectCharge);
239
240   fHistos->SetTriggerRestrictEta(fTriggerRestrictEta);
241   fHistosMixed->SetTriggerRestrictEta(fTriggerRestrictEta);
242   
243   fHistos->SetOnlyOneEtaSide(fOnlyOneEtaSide);
244   fHistosMixed->SetOnlyOneEtaSide(fOnlyOneEtaSide);
245   
246   fHistos->SetEtaOrdering(fEtaOrdering);
247   fHistosMixed->SetEtaOrdering(fEtaOrdering);
248
249   fHistos->SetPairCuts(fCutConversions, fCutResonances);
250   fHistosMixed->SetPairCuts(fCutConversions, fCutResonances);
251   
252   fHistos->SetTrackEtaCut(fTrackEtaCut);
253   fHistosMixed->SetTrackEtaCut(fTrackEtaCut);
254   
255   if (fEfficiencyCorrection)
256   {
257     fHistos->SetEfficiencyCorrection(fEfficiencyCorrection, fCorrectTriggers);
258     fHistosMixed->SetEfficiencyCorrection((THnF*) fEfficiencyCorrection->Clone(), fCorrectTriggers);
259   }
260   
261   // add histograms to list
262   fListOfHistos->Add(fHistos);
263   fListOfHistos->Add(fHistosMixed);
264   
265   fListOfHistos->Add(new TH2F("trackletsVsV0Cent", ";L1 clusters;v0 centrality", 100, -0.5, 9999.5, 101, 0, 101));
266   fListOfHistos->Add(new TH2F("processIDs", ";#Delta#phi;process id", 100, -0.5 * TMath::Pi(), 1.5 * TMath::Pi(), kPNoProcess + 1, -0.5, kPNoProcess + 0.5));
267   fListOfHistos->Add(new TH1F("eventStat", ";;events", 4, -0.5, 3.5));
268   fListOfHistos->Add(new TH2F("mixedDist", ";centrality;tracks;events", 101, 0, 101, 200, 0, fMixingTracks * 1.5));
269   fListOfHistos->Add(new TH1F("pids", ";pdg;tracks", 2001, -1000.5, 1000.5));
270   fListOfHistos->Add(new TH2F("referenceMultiplicity", ";centrality;tracks;events", 101, 0, 101, 200, 0, 200));
271   
272   PostData(0,fListOfHistos);
273   
274   // Add task configuration to output list 
275   AddSettingsTree();
276
277   // event mixing
278   Int_t trackDepth = fMixingTracks; 
279   Int_t poolsize   = 1000;  // Maximum number of events, ignored in the present implemented of AliEventPoolManager
280    
281   Int_t nCentralityBins  = fHistos->GetUEHist(2)->GetEventHist()->GetNBins(1);
282   Double_t* centralityBins = (Double_t*) fHistos->GetUEHist(2)->GetEventHist()->GetAxis(1, 0)->GetXbins()->GetArray();
283   
284   const Int_t kNZvtxBins  = 10+(1+10)*4;
285   // bins for further buffers are shifted by 100 cm
286   Double_t vertexBins[kNZvtxBins+1] = { -10,   -8,  -6,  -4,  -2,   0,   2,   4,   6,   8,  10, 
287                                        90,  92,  94,  96,  98, 100, 102, 104, 106, 108, 110, 
288                                       190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 
289                                       290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 
290                                       390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410 };
291
292   Int_t nZvtxBins  = kNZvtxBins;
293   Double_t* zvtxbin = vertexBins;
294
295   if (fMode == 0 && fHistos->GetUEHist(2)->GetEventHist()->GetNVar() > 2)
296   {
297     nZvtxBins = fHistos->GetUEHist(2)->GetEventHist()->GetNBins(2);
298     zvtxbin = (Double_t*) fHistos->GetUEHist(2)->GetEventHist()->GetAxis(2, 0)->GetXbins()->GetArray();
299   }
300
301   fPoolMgr = new AliEventPoolManager(poolsize, trackDepth, nCentralityBins, centralityBins, nZvtxBins, zvtxbin);
302 }
303
304 //____________________________________________________________________
305 void  AliAnalysisTaskPhiCorrelations::Exec(Option_t */*option*/)
306 {
307   // receive ESD pointer if we are not running AOD analysis
308   if (!fAOD)
309   {
310     AliVEventHandler* handler = AliAnalysisManager::GetAnalysisManager()->GetInputEventHandler();
311     if (handler && handler->InheritsFrom("AliESDInputHandler"))
312       fESD = ((AliESDInputHandler*)handler)->GetEvent();
313   }
314
315   if (fMode)
316   {
317     // correction mode
318     
319     if (fMcHandler)
320       fMcEvent = fMcHandler->MCEvent();
321
322     if (fAOD)
323     {
324       // array of MC particles
325       fArrayMC = dynamic_cast<TClonesArray*>(fAOD->FindListObject(AliAODMCParticle::StdBranchName()));
326       if (!fArrayMC)
327         AliFatal("No array of MC particles found !!!");
328     }
329     
330     AnalyseCorrectionMode();
331   }
332   else AnalyseDataMode();
333 }
334
335 /******************** ANALYSIS METHODS *****************************/
336
337 //____________________________________________________________________
338 void  AliAnalysisTaskPhiCorrelations::AddSettingsTree()
339 {
340   //Write settings to output list
341   TTree *settingsTree   = new TTree("UEAnalysisSettings","Analysis Settings in UE estimation");
342   settingsTree->Branch("fnTracksVertex", &fnTracksVertex,"nTracksVertex/I");
343   settingsTree->Branch("fZVertex", &fZVertex,"ZVertex/D");
344   //settingsTree->Branch("fCentralityMethod", fCentralityMethod.Data(),"CentralityMethod/C");
345   settingsTree->Branch("fTrackEtaCut", &fTrackEtaCut, "TrackEtaCut/D");
346   settingsTree->Branch("fOnlyOneEtaSide", &fOnlyOneEtaSide,"OnlyOneEtaSide/I");
347   settingsTree->Branch("fPtMin", &fPtMin, "PtMin/D");
348   settingsTree->Branch("fFilterBit", &fFilterBit,"FilterBit/I");
349   settingsTree->Branch("fSelectBit", &fSelectBit,"EventSelectionBit/I");
350   settingsTree->Branch("fUseChargeHadrons", &fUseChargeHadrons,"UseChHadrons/O");
351   settingsTree->Branch("fSelectCharge", &fSelectCharge,"SelectCharge/I");
352   settingsTree->Branch("fTriggerSelectCharge", &fTriggerSelectCharge,"TriggerSelectCharge/I");
353   settingsTree->Branch("fTriggerRestrictEta", &fTriggerRestrictEta,"TriggerRestrictEta/D");
354   settingsTree->Branch("fEtaOrdering", &fEtaOrdering,"EtaOrdering/O");
355   settingsTree->Branch("fCutConversions", &fCutConversions,"CutConversions/O");
356   settingsTree->Branch("fCutResonances", &fCutResonances,"CutResonances/O");
357   settingsTree->Branch("fFillpT", &fFillpT,"FillpT/O");
358   settingsTree->Branch("fMixingTracks", &fMixingTracks,"MixingTracks/I");
359   settingsTree->Branch("fSkipTrigger", &fSkipTrigger,"SkipTrigger/O");
360   settingsTree->Branch("fInjectedSignals", &fInjectedSignals,"SkipTrigger/O");
361   settingsTree->Branch("fRejectCentralityOutliers", &fRejectCentralityOutliers,"RejectCentralityOutliers/O");
362   settingsTree->Branch("fRemoveWeakDecays", &fRemoveWeakDecays,"RemoveWeakDecays/O");
363   settingsTree->Branch("fRemoveDuplicates", &fRemoveDuplicates,"RemoveDuplicates/O");
364   settingsTree->Branch("fSkipFastCluster", &fSkipFastCluster,"SkipFastCluster/O");
365   settingsTree->Branch("fCorrectTriggers", &fCorrectTriggers,"CorrectTriggers/O");
366   
367   settingsTree->Fill();
368   fListOfHistos->Add(settingsTree);
369 }  
370
371 //____________________________________________________________________
372 void  AliAnalysisTaskPhiCorrelations::AnalyseCorrectionMode()
373 {
374   // Run the analysis on MC to get the correction maps
375   //
376  
377   if ( fDebug > 3 ) AliInfo( " Processing event in Corrections mode ..." );
378   
379   Double_t centrality = 0;
380   
381   if (fCentralityMethod.Length() > 0)
382   {
383     AliCentrality *centralityObj = 0;
384     if (fAOD)
385       centralityObj = fAOD->GetHeader()->GetCentralityP();
386     else if (fESD)
387       centralityObj = fESD->GetCentrality();
388     
389     if (centralityObj)
390     {
391       centrality = centralityObj->GetCentralityPercentileUnchecked(fCentralityMethod);
392       AliInfo(Form("Centrality is %f", centrality));
393     }
394     else
395     {
396       Printf("WARNING: Centrality object is 0");
397       centrality = -1;
398      }
399   }
400   
401   // Support for ESD and AOD based analysis
402   AliVEvent* inputEvent = fAOD;
403   if (!inputEvent)
404     inputEvent = fESD;
405
406   Float_t bSign = 0;
407   
408   if (inputEvent)
409   {
410     fHistos->SetRunNumber(inputEvent->GetRunNumber());
411     bSign = (inputEvent->GetMagneticField() > 0) ? 1 : -1;
412   }
413     
414   TObject* mc = fArrayMC;
415   if (!mc)
416     mc = fMcEvent;
417   
418   // count all events
419   fHistos->FillEvent(centrality, -1);
420   
421   if (centrality < 0)
422     return;
423
424   // Only consider MC events within the vtx-z region used also as cut on the reconstructed vertex
425   TObject* vertexSupplier = fMcEvent;
426   if (fAOD) // AOD
427     vertexSupplier = fAOD->FindListObject(AliAODMCHeader::StdBranchName());
428     
429   if (!fAnalyseUE->VertexSelection(vertexSupplier, 0, fZVertex)) 
430     return;
431   
432   Float_t zVtx = 0;
433   if (fAOD)
434     zVtx = ((AliAODMCHeader*) vertexSupplier)->GetVtxZ();
435   else
436     zVtx = fMcEvent->GetPrimaryVertex()->GetZ();
437   Float_t weight = 1;
438   if (fFillpT)
439     weight = -1;
440   
441   // For productions with injected signals, figure out above which label to skip particles/tracks
442   Int_t skipParticlesAbove = 0;
443   if (fInjectedSignals)
444   {
445     AliGenEventHeader* eventHeader = 0;
446     Int_t headers = 0;
447
448     if (fMcEvent)
449     {
450       // ESD
451       AliHeader* header = (AliHeader*) fMcEvent->Header();
452       if (!header)
453         AliFatal("fInjectedSignals set but no MC header found");
454         
455       AliGenCocktailEventHeader* cocktailHeader = dynamic_cast<AliGenCocktailEventHeader*> (header->GenEventHeader());
456       if (!cocktailHeader)
457       {
458         header->Dump();
459         AliFatal("fInjectedSignals set but no MC cocktail header found");
460       }
461
462       headers = cocktailHeader->GetHeaders()->GetEntries();
463       eventHeader = dynamic_cast<AliGenEventHeader*> (cocktailHeader->GetHeaders()->First());
464     }
465     else
466     {
467       // AOD
468       AliAODMCHeader* header = (AliAODMCHeader*) fAOD->GetList()->FindObject(AliAODMCHeader::StdBranchName());
469       if (!header)
470         AliFatal("fInjectedSignals set but no MC header found");
471       
472       headers = header->GetNCocktailHeaders();
473       eventHeader = header->GetCocktailHeader(0);
474     }
475     
476     if (!eventHeader)
477     {
478       // We avoid AliFatal here, because the AOD productions sometimes have events where the MC header is missing 
479       // (due to unreadable Kinematics) and we don't want to loose the whole job because of a few events
480       AliError("First event header not found. Skipping this event.");
481       fHistos->FillEvent(centrality, AliUEHist::kCFStepAnaTopology);
482       return;
483     }
484     
485     skipParticlesAbove = eventHeader->NProduced();
486     AliInfo(Form("Injected signals in this event (%d headers). Keeping events of %s. Will skip particles/tracks above %d.", headers, eventHeader->ClassName(), skipParticlesAbove));
487   }
488   
489   // Get MC primaries
490   TObjArray* tmpList = fAnalyseUE->GetAcceptedParticles(mc, 0, kTRUE, -1, kTRUE);
491   if (fInjectedSignals)
492     fAnalyseUE->RemoveInjectedSignals(tmpList, mc, skipParticlesAbove);
493   if (fRemoveWeakDecays)
494     fAnalyseUE->RemoveWeakDecays(tmpList, mc);
495   TObjArray* tracksMC = CloneAndReduceTrackList(tmpList);
496   delete tmpList;
497   
498   /*
499   if (fAOD)
500   {
501     for (Int_t i=0; i<fArrayMC->GetEntriesFast(); i++)
502       ((TH1F*) fListOfHistos->FindObject("pids"))->Fill(((AliAODMCParticle*) fArrayMC->At(i))->PdgCode());
503   }
504   else
505   {
506     for (Int_t i=0; i<fMcEvent->GetNumberOfTracks(); i++)
507       ((TH1F*) fListOfHistos->FindObject("pids"))->Fill(fMcEvent->GetTrack(i)->PdgCode());
508   }
509   */
510   
511   if (fFillOnlyStep0)
512     zVtx = 0;
513   
514   // (MC-true all particles)
515   // STEP 0
516   fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepAll, tracksMC, 0, weight);
517   
518   // mixed event
519   if (fFillMixed)
520   {
521     AliEventPool* pool = fPoolMgr->GetEventPool(centrality, zVtx);
522     //pool->PrintInfo();
523     if (pool->IsReady() || pool->NTracksInPool() > fMixingTracks / 10 || pool->GetCurrentNEvents() >= 5) 
524       for (Int_t jMix=0; jMix<pool->GetCurrentNEvents(); jMix++) 
525         fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepAll, tracksMC, pool->GetEvent(jMix), 1.0 / pool->GetCurrentNEvents(), (jMix == 0));
526     pool->UpdatePool(CloneAndReduceTrackList(tracksMC));
527   }
528   
529 //   Printf("trigger: %d", ((AliInputEventHandler*)fInputHandler)->IsEventSelected());
530   
531   // Trigger selection ************************************************
532   if (!fFillOnlyStep0 && (fSkipTrigger || fAnalyseUE->TriggerSelection(fInputHandler)))
533   {  
534     // (MC-true all particles)
535     // STEP 1
536     if (!fReduceMemoryFootprint)
537       fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepTriggered, tracksMC, 0, weight);
538     else
539       fHistos->FillEvent(centrality, AliUEHist::kCFStepTriggered);
540       
541     if (!inputEvent) {
542       AliFatal("UNEXPECTED: inputEvent is 0. Trigger selection should have failed");
543       return;
544     }
545     
546     // Vertex selection *************************************************
547     if (fAnalyseUE->VertexSelection(inputEvent, fnTracksVertex, fZVertex))
548     {
549       // fill here for tracking efficiency
550       // loop over particle species
551       
552       for (Int_t particleSpecies = 0; particleSpecies < 4; particleSpecies++)
553       {
554         TObjArray* primMCParticles = fAnalyseUE->GetAcceptedParticles(mc, 0x0, kTRUE, particleSpecies, kTRUE);
555         TObjArray* primRecoTracksMatched = fAnalyseUE->GetAcceptedParticles(inputEvent, mc, kTRUE, particleSpecies, kTRUE);
556         TObjArray* allRecoTracksMatched = fAnalyseUE->GetAcceptedParticles(inputEvent, mc, kFALSE, particleSpecies, kTRUE);
557         
558         if (fInjectedSignals)
559         {
560           fAnalyseUE->RemoveInjectedSignals(primMCParticles, mc, skipParticlesAbove);
561           fAnalyseUE->RemoveInjectedSignals(primRecoTracksMatched, mc, skipParticlesAbove);
562           fAnalyseUE->RemoveInjectedSignals(allRecoTracksMatched, mc, skipParticlesAbove);
563         }
564         
565         if (fRemoveWeakDecays)
566         {
567           fAnalyseUE->RemoveWeakDecays(primMCParticles, mc);
568           fAnalyseUE->RemoveWeakDecays(primRecoTracksMatched, mc);
569           fAnalyseUE->RemoveWeakDecays(allRecoTracksMatched, mc);
570         }
571       
572         fHistos->FillTrackingEfficiency(primMCParticles, primRecoTracksMatched, allRecoTracksMatched, 0, particleSpecies, centrality, zVtx);
573         
574 //      Printf("%d --> %d %d %d", particleSpecies, primMCParticles->GetEntries(), primRecoTracksMatched->GetEntries(), allRecoTracksMatched->GetEntries());
575
576         delete primMCParticles;
577         delete primRecoTracksMatched;
578         delete allRecoTracksMatched;
579       }
580       TObjArray* fakeParticles = fAnalyseUE->GetFakeParticles(inputEvent, mc, kFALSE, -1, kTRUE);
581       if (fInjectedSignals)
582       {
583         fAnalyseUE->RemoveInjectedSignals((TObjArray*) fakeParticles->At(0), mc, skipParticlesAbove);
584         fAnalyseUE->RemoveInjectedSignals((TObjArray*) fakeParticles->At(1), mc, skipParticlesAbove);
585       }
586       if (fRemoveWeakDecays)
587       {
588         fAnalyseUE->RemoveWeakDecays((TObjArray*) fakeParticles->At(0), mc);
589         fAnalyseUE->RemoveWeakDecays((TObjArray*) fakeParticles->At(1), mc);
590       }
591       fHistos->FillTrackingEfficiency(0, 0, 0, (TObjArray*) fakeParticles->At(2), -1, centrality, zVtx);
592       fHistos->FillFakePt(fakeParticles, centrality);
593 //       Printf(">>>>> %d %d %d fakes", ((TObjArray*) fakeParticles->At(0))->GetEntriesFast(), ((TObjArray*) fakeParticles->At(1))->GetEntriesFast(), ((TObjArray*) fakeParticles->At(2))->GetEntriesFast());
594       delete fakeParticles;
595     
596       // (MC-true all particles)
597       // STEP 2
598       if (!fReduceMemoryFootprint)
599         fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepVertex, tracksMC, 0, weight);
600       else
601         fHistos->FillEvent(centrality, AliUEHist::kCFStepVertex);
602       
603       // Get MC primaries that match reconstructed track
604       TObjArray* tracksRecoMatchedPrim = fAnalyseUE->GetAcceptedParticles(inputEvent, mc, kTRUE, -1, kTRUE);
605       if (fInjectedSignals)
606         fAnalyseUE->RemoveInjectedSignals(tracksRecoMatchedPrim, mc, skipParticlesAbove);
607       if (fRemoveWeakDecays)
608         fAnalyseUE->RemoveWeakDecays(tracksRecoMatchedPrim, mc);
609       if (fRemoveDuplicates)
610         RemoveDuplicates(tracksRecoMatchedPrim);
611       
612       // (RECO-matched (quantities from MC particle) primary particles)
613       // STEP 4
614       fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepTrackedOnlyPrim, tracksRecoMatchedPrim, 0, weight);
615
616       // mixed event
617       if (fFillMixed)
618       {
619         AliEventPool* pool = fPoolMgr->GetEventPool(centrality, zVtx + 200);
620         //pool->PrintInfo();
621         if (pool->IsReady() || pool->NTracksInPool() > fMixingTracks / 10 || pool->GetCurrentNEvents() >= 5) 
622           for (Int_t jMix=0; jMix<pool->GetCurrentNEvents(); jMix++) 
623             fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepTrackedOnlyPrim, tracksRecoMatchedPrim, pool->GetEvent(jMix), 1.0 / pool->GetCurrentNEvents(), (jMix == 0));
624         pool->UpdatePool(CloneAndReduceTrackList(tracksRecoMatchedPrim));
625       }
626       
627       // Get MC primaries + secondaries that match reconstructed track
628       TObjArray* tracksRecoMatchedAll = fAnalyseUE->GetAcceptedParticles(inputEvent, mc, kFALSE, -1, kTRUE);
629       if (fInjectedSignals)
630         fAnalyseUE->RemoveInjectedSignals(tracksRecoMatchedAll, mc, skipParticlesAbove);
631       if (fRemoveWeakDecays)
632         fAnalyseUE->RemoveWeakDecays(tracksRecoMatchedAll, mc);
633       if (fRemoveDuplicates)
634         RemoveDuplicates(tracksRecoMatchedAll);
635      
636       // (RECO-matched (quantities from MC particle) all particles)
637       // STEP 5
638       fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepTracked, tracksRecoMatchedAll, 0, weight);
639       
640       // mixed event
641       if (fFillMixed)
642       {
643         AliEventPool* pool = fPoolMgr->GetEventPool(centrality, zVtx + 300);
644         //pool->PrintInfo();
645         if (pool->IsReady() || pool->NTracksInPool() > fMixingTracks / 10 || pool->GetCurrentNEvents() >= 5) 
646           for (Int_t jMix=0; jMix<pool->GetCurrentNEvents(); jMix++) 
647             fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepTracked, tracksRecoMatchedAll, pool->GetEvent(jMix), 1.0 / pool->GetCurrentNEvents(), (jMix == 0));
648         pool->UpdatePool(CloneAndReduceTrackList(tracksRecoMatchedAll));
649       }
650       
651       // Get RECO tracks
652       TObjArray* tracks = fAnalyseUE->GetAcceptedParticles(inputEvent, 0, kTRUE, -1, kTRUE);
653       if (fInjectedSignals)
654         fAnalyseUE->RemoveInjectedSignals(tracks, mc, skipParticlesAbove);
655       if (fRemoveWeakDecays)
656         fAnalyseUE->RemoveWeakDecays(tracks, mc);
657      
658       // (RECO all tracks)
659       // STEP 6
660       if (!fSkipStep6)
661         fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepReconstructed, tracks, 0, weight);
662       
663       // two track cut, STEP 8
664       if (fTwoTrackEfficiencyCut > 0)
665         fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepBiasStudy, tracks, 0, weight, kTRUE, kTRUE, bSign, fTwoTrackEfficiencyCut);
666
667       // apply correction efficiency, STEP 10
668       if (fEfficiencyCorrection)
669       {
670         // with or without two track efficiency depending on if fTwoTrackEfficiencyCut is set
671         Bool_t twoTrackCut = (fTwoTrackEfficiencyCut > 0);
672         
673         fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepCorrected, tracks, 0, weight, kTRUE, twoTrackCut, bSign, fTwoTrackEfficiencyCut, kTRUE);
674       }
675
676       // mixed event
677       if (fFillMixed)
678       {
679         AliEventPool* pool2 = fPoolMgr->GetEventPool(centrality, zVtx + 100);
680         //pool2->PrintInfo();
681         if (pool2->IsReady() || pool2->NTracksInPool() > fMixingTracks / 10 || pool2->GetCurrentNEvents() >= 5) 
682         {
683           for (Int_t jMix=0; jMix<pool2->GetCurrentNEvents(); jMix++)
684           {
685             // STEP 6
686             if (!fSkipStep6)
687               fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepReconstructed, tracks, pool2->GetEvent(jMix), 1.0 / pool2->GetCurrentNEvents(), (jMix == 0));
688             
689             // two track cut, STEP 8
690             if (fTwoTrackEfficiencyCut > 0)
691               fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepBiasStudy, tracks, pool2->GetEvent(jMix), 1.0 / pool2->GetCurrentNEvents(), (jMix == 0), kTRUE, bSign, fTwoTrackEfficiencyCut);
692             
693             // apply correction efficiency, STEP 10
694             if (fEfficiencyCorrection)
695             {
696               // with or without two track efficiency depending on if fTwoTrackEfficiencyCut is set
697               Bool_t twoTrackCut = (fTwoTrackEfficiencyCut > 0);
698               
699               fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepCorrected, tracks, pool2->GetEvent(jMix), 1.0 / pool2->GetCurrentNEvents(), (jMix == 0), twoTrackCut, bSign, fTwoTrackEfficiencyCut, kTRUE);
700             }
701           }
702         }
703         pool2->UpdatePool(CloneAndReduceTrackList(tracks));
704       }
705       
706       if (0 && !fReduceMemoryFootprint)
707       {
708         // make list of secondaries (matched with MC)
709         TObjArray* tracksRecoMatchedSecondaries = new TObjArray;
710         for (Int_t i=0; i<tracksRecoMatchedAll->GetEntriesFast(); i++)
711           if (((AliAODMCParticle*)tracksRecoMatchedAll->At(i))->IsPhysicalPrimary() == kFALSE)
712             tracksRecoMatchedSecondaries->Add(tracksRecoMatchedAll->At(i));
713       
714         // Study: Use only secondaries as trigger particles and plot the correlation vs. all particles; store in step 9
715         fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepBiasStudy2, tracksRecoMatchedSecondaries, tracksRecoMatchedAll, weight);
716         
717         // Study: Use only primaries as trigger particles and plot the correlation vs. secondaries; store in step 8
718         fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepBiasStudy, tracksRecoMatchedPrim, tracksRecoMatchedSecondaries, weight);
719       
720         // plot delta phi vs process id of secondaries
721         // trigger particles: primaries in 4 < pT < 10
722         // associated particles: secondaries in 1 < pT < 10
723         
724         for (Int_t i=0; i<tracksRecoMatchedPrim->GetEntriesFast(); i++)
725         {
726           AliVParticle* triggerParticle = (AliVParticle*) tracksRecoMatchedPrim->At(i);
727           
728           if (triggerParticle->Pt() < 4 || triggerParticle->Pt() > 10)
729             continue;
730           
731           for (Int_t j=0; j<tracksRecoMatchedSecondaries->GetEntriesFast(); j++)
732           {
733             AliAODMCParticle* particle = (AliAODMCParticle*) tracksRecoMatchedSecondaries->At(j);
734             
735             if (particle->Pt() < 1 || particle->Pt() > 10)
736               continue;
737             
738             if (particle->Pt() > triggerParticle->Pt())
739               continue;
740               
741             Double_t deltaPhi = triggerParticle->Phi() - particle->Phi();
742             if (deltaPhi > 1.5 * TMath::Pi()) 
743               deltaPhi -= TMath::TwoPi();
744             if (deltaPhi < -0.5 * TMath::Pi())
745               deltaPhi += TMath::TwoPi();
746               
747             Int_t processID = fMcEvent->Stack()->Particle(particle->GetLabel())->GetUniqueID();
748               
749             ((TH2F*) fListOfHistos->FindObject("processIDs"))->Fill(deltaPhi, processID);
750           }
751         }
752         
753         delete tracksRecoMatchedSecondaries;
754       }
755   
756       delete tracksRecoMatchedPrim;
757       delete tracksRecoMatchedAll;
758       delete tracks;
759     }
760   }
761   
762   delete tracksMC;
763 }
764
765 //____________________________________________________________________
766 void  AliAnalysisTaskPhiCorrelations::AnalyseDataMode()
767 {
768
769   // Run the analysis on DATA or MC to get raw distributions
770  
771   if ( fDebug > 3 ) AliInfo( " Processing event in Data mode ..." );
772
773   ((TH1F*) fListOfHistos->FindObject("eventStat"))->Fill(0);
774
775   if (!fInputHandler)
776     return;
777     
778   // skip not selected events here (the AOD is not updated for those)
779   if (!fSkipTrigger && !(fInputHandler->IsEventSelected() & fSelectBit))
780     return;
781   
782   // skip fast cluster events here if requested
783   if (!fSkipFastCluster && (fInputHandler->IsEventSelected() & AliVEvent::kFastOnly))
784     return;
785
786   // Support for ESD and AOD based analysis
787   AliVEvent* inputEvent = fAOD;
788   if (!inputEvent)
789     inputEvent = fESD;
790
791   Double_t centrality = 0;
792   
793   AliCentrality *centralityObj = 0;
794   if (fCentralityMethod.Length() > 0)
795   {
796     if (fCentralityMethod == "ZNA_MANUAL")
797     {
798       Bool_t zna = kFALSE;
799       for(Int_t j = 0; j < 4; ++j) {
800         if (fESD->GetZDCData()->GetZDCTDCData(12,j) != 0) {
801           zna = kTRUE;
802         }
803       }
804
805 //       Printf("%d %f", zna, fZNAtower[0]);
806       if (zna)
807       {
808         // code from Chiara O (23.10.12)
809         const Double_t *fZNAtower = fESD->GetZDCData()->GetZN2TowerEnergy();
810         Float_t znacut[4] = {681., 563., 413., 191.};
811         
812         if(fZNAtower[0]>znacut[0]) centrality = 1;
813         else if(fZNAtower[0]>znacut[1]) centrality = 21;
814         else if(fZNAtower[0]>znacut[2]) centrality = 41;
815         else if(fZNAtower[0]>znacut[3]) centrality = 61;
816         else centrality = 81;
817       }
818       else
819         centrality = -1;
820     }
821     else if (fCentralityMethod == "TRACKS_MANUAL")
822     {
823       // for pp
824       TObjArray* tracks = fAnalyseUE->GetAcceptedParticles(inputEvent, 0, kTRUE, -1, kTRUE);
825       centrality = tracks->GetEntriesFast();
826       if (centrality > 40)
827         centrality = 41;
828 //       Printf("%d %f", tracks->GetEntriesFast(), centrality);
829       delete tracks;
830     }
831     else
832     {
833       if (fAOD)
834         centralityObj = fAOD->GetHeader()->GetCentralityP();
835       else if (fESD)
836         centralityObj = fESD->GetCentrality();
837       
838       if (centralityObj)
839         centrality = centralityObj->GetCentralityPercentile(fCentralityMethod);
840         //centrality = centralityObj->GetCentralityPercentileUnchecked(fCentralityMethod);
841       else
842         centrality = -1;
843
844       if (fAOD)
845       {
846         // remove outliers
847         if (centrality == 0)
848         {
849           if (fAOD->GetVZEROData())
850           {
851             Float_t multV0 = 0;
852             for (Int_t i=0; i<64; i++)
853               multV0 += fAOD->GetVZEROData()->GetMultiplicity(i);
854             if (multV0 < 19500)
855             {
856               centrality = -1;
857               AliInfo("Rejecting event due to too small V0 multiplicity");
858             }
859           }
860         }
861       }
862     }
863     
864     AliInfo(Form("Centrality is %f", centrality));
865   }
866   
867   Float_t bSign = (inputEvent->GetMagneticField() > 0) ? 1 : -1;
868
869   fHistos->SetRunNumber(inputEvent->GetRunNumber());
870   
871   // Fill the "event-counting-container", it is needed to get the number of events remaining after each event-selection cut
872   fHistos->FillEvent(centrality, AliUEHist::kCFStepAll);
873   
874   // Trigger selection ************************************************
875   if (!fSkipTrigger && !fAnalyseUE->TriggerSelection(fInputHandler)) return;
876   
877   // Fill the "event-counting-container", it is needed to get the number of events remaining after each event-selection cut
878   fHistos->FillEvent(centrality, AliUEHist::kCFStepTriggered);
879   
880   // Vertex selection *************************************************
881   if(!fAnalyseUE->VertexSelection(inputEvent, fnTracksVertex, fZVertex)) return;
882   
883   // Fill the "event-counting-container", it is needed to get the number of events remaining after each event-selection cut
884   fHistos->FillEvent(centrality, AliUEHist::kCFStepVertex);
885  
886   // optimization
887   if (centrality < 0 && !fCompareCentralities)
888     return;
889
890   TObjArray* tracks = fAnalyseUE->GetAcceptedParticles(inputEvent, 0, kTRUE, -1, kTRUE);
891   
892   // check for outlier in centrality vs number of tracks (rough constants extracted from correlation histgram)
893   Bool_t reject = kFALSE;
894   if (fRejectCentralityOutliers)
895   {
896     if (centrality > 40 && centrality <= 50 && tracks->GetEntriesFast() > 1160)
897       reject = kTRUE;
898     if (centrality > 50 && centrality <= 60 && tracks->GetEntriesFast() > 650)
899       reject = kTRUE;
900     if (centrality > 60 && centrality <= 70 && tracks->GetEntriesFast() > 370)
901       reject = kTRUE;
902     if (centrality > 70 && centrality <= 80 && tracks->GetEntriesFast() > 220)
903       reject = kTRUE;
904     if (centrality > 80 && centrality <= 90 && tracks->GetEntriesFast() > 130)
905       reject = kTRUE;
906     if (centrality > 90 && tracks->GetEntriesFast() > 75)
907       reject = kTRUE;
908   }
909   
910   if (reject)
911   {
912     AliInfo(Form("Rejecting event due to centrality vs tracks correlation: %f %d", centrality, tracks->GetEntriesFast()));
913     fHistos->FillEvent(centrality, AliUEHist::kCFStepAnaTopology);
914     delete tracks;
915     return;
916   }
917   
918   // reference multiplicity
919   Int_t referenceMultiplicity = -1;
920   if (fESD)
921     referenceMultiplicity = AliESDtrackCuts::GetReferenceMultiplicity(fESD);
922
923   ((TH2F*) fListOfHistos->FindObject("referenceMultiplicity"))->Fill(centrality, referenceMultiplicity);
924   
925   // create a list of reduced objects. This speeds up processing and reduces memory consumption for the event pool
926   TObjArray* tracksClone = CloneAndReduceTrackList(tracks);
927   delete tracks;
928   
929   //Printf("Accepted %d tracks", tracks->GetEntries());
930   
931   const AliVVertex* vertex = inputEvent->GetPrimaryVertex();
932   Double_t zVtx = vertex->GetZ();
933   
934   Float_t weight = 1;
935   if (fFillpT)
936     weight = -1;
937
938   // fill two different centralities (syst study)
939   // the zvtx axis is used to distinguish the results of both centralities: configured centrality in zvtx = 0, SPD in zvtx = 2
940   if (fCompareCentralities)
941     zVtx = 0;
942   
943   // Fill containers at STEP 6 (reconstructed)
944   if (centrality >= 0)
945   {
946     if (!fSkipStep6)
947       fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepReconstructed, tracksClone, 0, weight, kTRUE, kFALSE, 0, 0.02, kTRUE);
948     
949     ((TH1F*) fListOfHistos->FindObject("eventStat"))->Fill(1);
950     
951     if (fTwoTrackEfficiencyCut > 0)
952       fHistos->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepBiasStudy, tracksClone, 0, weight, kTRUE, kTRUE, bSign, fTwoTrackEfficiencyCut, kTRUE);
953   }
954
955   // fill second time with SPD centrality
956   if (fCompareCentralities && centralityObj)
957   {
958     centrality = centralityObj->GetCentralityPercentile("CL1");
959     if (centrality >= 0 && !fSkipStep6)
960       fHistos->FillCorrelations(centrality, 2, AliUEHist::kCFStepReconstructed, tracksClone, 0, weight, kTRUE, kFALSE, 0, 0.02, kTRUE);
961   }
962   
963   if (fFillMixed)
964   {
965     // event mixing
966     
967     // 1. First get an event pool corresponding in mult (cent) and
968     //    zvertex to the current event. Once initialized, the pool
969     //    should contain nMix (reduced) events. This routine does not
970     //    pre-scan the chain. The first several events of every chain
971     //    will be skipped until the needed pools are filled to the
972     //    specified depth. If the pool categories are not too rare, this
973     //    should not be a problem. If they are rare, you could lose
974     //    statistics.
975
976     // 2. Collect the whole pool's content of tracks into one TObjArray
977     //    (bgTracks), which is effectively a single background super-event.
978
979     // 3. The reduced and bgTracks arrays must both be passed into
980     //    FillCorrelations(). Also nMix should be passed in, so a weight
981     //    of 1./nMix can be applied.
982
983     AliEventPool* pool = fPoolMgr->GetEventPool(centrality, zVtx);
984     
985     if (!pool)
986       AliFatal(Form("No pool found for centrality = %f, zVtx = %f", centrality, zVtx));
987     
988     //pool->SetDebug(1);
989      
990     if (pool->IsReady() || pool->NTracksInPool() > fMixingTracks / 10 || pool->GetCurrentNEvents() >= 5) 
991     {
992       
993       Int_t nMix = pool->GetCurrentNEvents();
994 //       cout << "nMix = " << nMix << " tracks in pool = " << pool->NTracksInPool() << endl;
995       
996       ((TH1F*) fListOfHistos->FindObject("eventStat"))->Fill(2);
997       ((TH2F*) fListOfHistos->FindObject("mixedDist"))->Fill(centrality, pool->NTracksInPool());
998       if (pool->IsReady())
999         ((TH1F*) fListOfHistos->FindObject("eventStat"))->Fill(3);
1000     
1001       // Fill mixed-event histos here  
1002       for (Int_t jMix=0; jMix<nMix; jMix++) 
1003       {
1004         TObjArray* bgTracks = pool->GetEvent(jMix);
1005         
1006         if (!fSkipStep6)
1007           fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepReconstructed, tracksClone, bgTracks, 1.0 / nMix, (jMix == 0), kFALSE, 0, 0.02, kTRUE);
1008
1009         if (fTwoTrackEfficiencyCut > 0)
1010           fHistosMixed->FillCorrelations(centrality, zVtx, AliUEHist::kCFStepBiasStudy, tracksClone, bgTracks, 1.0 / nMix, (jMix == 0), kTRUE, bSign, fTwoTrackEfficiencyCut, kTRUE);
1011       }
1012     }
1013     
1014     // ownership is with the pool now
1015     pool->UpdatePool(tracksClone);
1016     //pool->PrintInfo();
1017   }
1018   else
1019     delete tracksClone;
1020 }
1021
1022 TObjArray* AliAnalysisTaskPhiCorrelations::CloneAndReduceTrackList(TObjArray* tracks)
1023 {
1024   // clones a track list by using AliDPhiBasicParticle which uses much less memory (used for event mixing)
1025   
1026   TObjArray* tracksClone = new TObjArray;
1027   tracksClone->SetOwner(kTRUE);
1028   
1029   for (Int_t i=0; i<tracks->GetEntriesFast(); i++)
1030   {
1031     AliVParticle* particle = (AliVParticle*) tracks->At(i);
1032     tracksClone->Add(new AliDPhiBasicParticle(particle->Eta(), particle->Phi(), particle->Pt(), particle->Charge()));
1033   }
1034   
1035   return tracksClone;
1036 }
1037
1038 //____________________________________________________________________
1039 void  AliAnalysisTaskPhiCorrelations::Initialize()
1040 {
1041   // input handler
1042   fInputHandler = (AliInputEventHandler*)
1043          ((AliAnalysisManager::GetAnalysisManager())->GetInputEventHandler());
1044   // MC handler
1045   fMcHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
1046 }
1047
1048 //____________________________________________________________________
1049 void AliAnalysisTaskPhiCorrelations::RemoveDuplicates(TObjArray* tracks)
1050 {
1051   // remove particles with the same label
1052   
1053   Int_t before = tracks->GetEntriesFast();
1054
1055   for (Int_t i=0; i<before; ++i) 
1056   {
1057     AliVParticle* part = (AliVParticle*) tracks->At(i);
1058     
1059     for (Int_t j=i+1; j<before; ++j) 
1060     {
1061       AliVParticle* part2 = (AliVParticle*) tracks->At(j);
1062       
1063       if (part->GetLabel() == part2->GetLabel())
1064       {
1065         Printf("Removing %d with label %d (duplicated in %d)", i, part->GetLabel(), j); part->Dump(); part2->Dump();
1066         TObject* object = tracks->RemoveAt(i);
1067         if (tracks->IsOwner())
1068           delete object;
1069         break;
1070       }
1071     }
1072   }
1073  
1074   tracks->Compress();
1075   
1076   if (before > tracks->GetEntriesFast())
1077     AliInfo(Form("Reduced from %d to %d", before, tracks->GetEntriesFast())); 
1078 }