1 /*************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: A.Abrahantes, E.Lopez, S.Vallero *
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 //#include <TBranch.h>
16 //#include <TCanvas.h>
23 //#include <TLorentzVector.h>
25 #include <TObjArray.h>
27 //#include <TProfile.h>
28 //#include <TRandom.h>
29 //#include <TSystem.h>
33 #include "AliAnalyseLeadingTrackUE.h"
34 //#include "AliAnalysisTask.h"
36 //#include "AliAnalysisHelperJetTasks.h"
37 //#include "AliAnalysisManager.h"
38 #include "AliAODEvent.h"
39 //#include "AliAODHandler.h"
40 //#include "AliAODJet.h"
41 #include "AliAODMCParticle.h"
42 #include "AliAODTrack.h"
43 #include "AliESDEvent.h"
44 #include "AliESDtrack.h"
45 #include "AliESDtrackCuts.h"
46 //#include "AliGenPythiaEventHeader.h"
47 #include "AliInputEventHandler.h"
48 //#include "AliKFVertex.h"
50 #include "AliMCEvent.h"
51 #include "AliVParticle.h"
53 #include "AliAnalysisManager.h"
54 #include "AliMCEventHandler.h"
58 ////////////////////////////////////////////////
59 //---------------------------------------------
60 // Class for transverse regions analysis
61 //---------------------------------------------
62 ////////////////////////////////////////////////
67 ClassImp(AliAnalyseLeadingTrackUE)
69 //-------------------------------------------------------------------
70 AliAnalyseLeadingTrackUE::AliAnalyseLeadingTrackUE() :
78 fEsdTrackCutsSPD(0x0),
85 //-------------------------------------------------------------------
86 AliAnalyseLeadingTrackUE & AliAnalyseLeadingTrackUE::operator = (const AliAnalyseLeadingTrackUE & /*source*/)
88 // assignment operator
93 //-------------------------------------------------------------------
94 AliAnalyseLeadingTrackUE::~AliAnalyseLeadingTrackUE()
102 //____________________________________________________________________
103 Bool_t AliAnalyseLeadingTrackUE::ApplyCuts(TObject* track)
106 // select track according to set of cuts
107 if (!fEsdTrackCuts->IsSelected(track) )return kFALSE;
108 if (fEsdTrackCutsSPD && fEsdTrackCutsSDD && !fEsdTrackCutsSPD->IsSelected(track) && fEsdTrackCutsSDD->IsSelected(track)) return kFALSE;
114 //____________________________________________________________________
115 void AliAnalyseLeadingTrackUE::DefineESDCuts(Int_t /*filterbit*/){
117 // Reproduces the cuts of the corresponding bit in the ESD->AOD filtering
118 // (see $ALICE_ROOT/ANALYSIS/macros/AddTaskESDFilter.C)
120 if (fFilterBit == 128)
122 fEsdTrackCuts = AliESDtrackCuts::GetStandardTPCOnlyTrackCuts();
123 fEsdTrackCuts->SetMinNClustersTPC(70);
127 fEsdTrackCuts = AliESDtrackCuts::GetStandardITSTPCTrackCuts2010();
128 fEsdTrackCuts->SetClusterRequirementITS(AliESDtrackCuts::kSPD, AliESDtrackCuts::kNone);
130 // Add SPD requirement
131 fEsdTrackCutsSPD = new AliESDtrackCuts("SPD", "Require 1 cluster in SPD");
132 fEsdTrackCutsSPD->SetClusterRequirementITS(AliESDtrackCuts::kSPD,AliESDtrackCuts::kAny);
134 // Add SDD requirement
135 fEsdTrackCutsSDD = new AliESDtrackCuts("SDD", "Require 1 cluster in first layer SDD");
136 fEsdTrackCutsSDD->SetClusterRequirementITS(AliESDtrackCuts::kSDD,AliESDtrackCuts::kFirst);
140 //____________________________________________________________________
141 TObjArray* AliAnalyseLeadingTrackUE::FindLeadingObjects(TObject *obj)
144 // Returns an array of charged particles (or jets) ordered according to their pT.
146 Int_t nTracks = NParticles(obj);
149 if( !nTracks ) return 0;
151 // Define array of AliVParticle objects
152 TObjArray* tracks = new TObjArray(nTracks);
154 // Loop over tracks or jets
155 for (Int_t ipart=0; ipart<nTracks; ++ipart) {
156 AliVParticle* part = ParticleWithCuts( obj, ipart );
158 // Accept leading-tracks in a limited pseudo-rapidity range
159 if( TMath::Abs(part->Eta()) > fTrackEtaCut ) continue;
160 tracks->AddLast( part );
162 // Order tracks by pT
163 QSortTracks( *tracks, 0, tracks->GetEntriesFast() );
165 nTracks = tracks->GetEntriesFast();
166 if( !nTracks ) return 0;
172 //-------------------------------------------------------------------
173 TObjArray* AliAnalyseLeadingTrackUE::GetAcceptedParticles(TObject* obj, TObject* arrayMC, Bool_t onlyprimaries, Int_t particleSpecies, Bool_t useEtaPtCuts)
175 // Returns an array of particles that pass the cuts, if arrayMC is given each reconstructed particle is replaced by its corresponding MC particles, depending on the parameter onlyprimaries only for primaries
176 // particleSpecies: -1 all particles are returned
177 // 0 (pions) 1 (kaons) 2 (protons) 3 (others) particles
179 Int_t nTracks = NParticles(obj);
180 TObjArray* tracks = new TObjArray;
182 // for TPC only tracks
183 if (fFilterBit == 128 && obj->InheritsFrom("AliESDEvent"))
184 tracks->SetOwner(kTRUE);
186 // Loop over tracks or jets
187 for (Int_t ipart=0; ipart<nTracks; ++ipart) {
188 AliVParticle* part = ParticleWithCuts( obj, ipart, onlyprimaries, particleSpecies );
192 if (TMath::Abs(part->Eta()) > fTrackEtaCut || part->Pt() < fTrackPtMin)
195 if (arrayMC && arrayMC->InheritsFrom("TClonesArray") && obj->InheritsFrom("AliAODEvent")) {
196 Int_t label = ((AliAODTrack*)part)->GetLabel();
197 // re-define part as the matched MC particle
198 part = (AliAODMCParticle*)ParticleWithCuts(arrayMC, TMath::Abs(label),onlyprimaries, particleSpecies);
208 //-------------------------------------------------------------------
209 TObjArray* AliAnalyseLeadingTrackUE::GetMinMaxRegion(TList *transv1, TList *transv2)
212 // Returns two lists of particles, one for MIN and one for MAX region
213 Double_t sumpT1 = 0.;
214 Double_t sumpT2 = 0.;
216 Int_t particles1 = transv1->GetEntries();
217 Int_t particles2 = transv2->GetEntries();
219 // Loop on transverse region 1
220 for (Int_t i=0; i<particles1; i++){
221 AliVParticle *part = (AliVParticle*)transv1->At(i);
222 sumpT1 += part->Pt();
225 // Loop on transverse region 2
226 for (Int_t i=0; i<particles2; i++){
227 AliVParticle *part = (AliVParticle*)transv2->At(i);
228 sumpT2 += part->Pt();
231 TObjArray *regionParticles = new TObjArray;
232 if ( sumpT2 >= sumpT1 ){
233 regionParticles->AddLast(transv1); // MIN
234 regionParticles->AddLast(transv2); // MAX
236 regionParticles->AddLast(transv2); // MIN
237 regionParticles->AddLast(transv1); // MAX
240 return regionParticles;
243 //-------------------------------------------------------------------
244 Int_t AliAnalyseLeadingTrackUE::NParticles(TObject* obj)
247 //Returns the number of particles in AliAODMCParticle array or AliAODTracks or AliESDTracks
251 if (obj->InheritsFrom("TClonesArray")){ // MC particles
252 TClonesArray *arrayMC = static_cast<TClonesArray*>(obj);
253 nTracks = arrayMC->GetEntriesFast();
254 }else if (obj->InheritsFrom("TObjArray")){ // list of AliVParticle
255 TObjArray *array = static_cast<TObjArray*>(obj);
256 nTracks = array->GetEntriesFast();
257 }else if (obj->InheritsFrom("AliAODEvent")){ // RECO AOD tracks
258 AliAODEvent *aodEvent = static_cast<AliAODEvent*>(obj);
259 nTracks = aodEvent->GetNTracks();
260 }else if (obj->InheritsFrom("AliESDEvent")){ // RECO ESD tracks
261 AliESDEvent *esdEvent = static_cast<AliESDEvent*>(obj);
262 nTracks = esdEvent->GetNumberOfTracks();
263 }else if (obj->InheritsFrom("AliMCEvent")){ // RECO ESD tracks
264 AliMCEvent *mcEvent = static_cast<AliMCEvent*>(obj);
265 nTracks = mcEvent->GetNumberOfTracks();
267 if (fDebug > 1) AliFatal(" Analysis type not defined !!! ");
275 //-------------------------------------------------------------------
276 AliVParticle* AliAnalyseLeadingTrackUE::ParticleWithCuts(TObject* obj, Int_t ipart, Bool_t onlyprimaries, Int_t particleSpecies)
278 // Returns track or MC particle at position "ipart" if passes selection criteria
279 // particleSpecies: -1 all particles are returned
280 // 0 (pions) 1 (kaons) 2 (protons) 3 (others) particles
281 AliVParticle *part=0;
283 if (obj->InheritsFrom("TClonesArray")){ // AOD-MC PARTICLE
284 TClonesArray *arrayMC = static_cast<TClonesArray*>(obj);
285 part = (AliVParticle*)arrayMC->At( ipart );
287 // eventually only primaries
288 if (onlyprimaries && !( ((AliAODMCParticle*)part)->IsPhysicalPrimary()) )return 0;
289 // eventually only hadrons
291 Int_t pdgCode = ((AliAODMCParticle*)part)->GetPdgCode();
292 Bool_t isHadron = TMath::Abs(pdgCode)==211 || // Pion
293 TMath::Abs(pdgCode)==2212 || // Proton
294 TMath::Abs(pdgCode)==321; // Kaon
295 if (!isHadron) return 0;
297 if (particleSpecies != -1) {
298 // find the primary mother
299 AliVParticle* mother = part;
300 while (!((AliAODMCParticle*)mother)->IsPhysicalPrimary())
302 if (((AliAODMCParticle*)mother)->GetMother() < 0)
308 mother = (AliVParticle*) arrayMC->At(((AliAODMCParticle*)mother)->GetMother());
315 Int_t pdgCode = ((AliAODMCParticle*)mother)->GetPdgCode();
316 if (particleSpecies == 0 && TMath::Abs(pdgCode)!=211)
318 if (particleSpecies == 1 && TMath::Abs(pdgCode)!=321)
320 if (particleSpecies == 2 && TMath::Abs(pdgCode)!=2212)
322 if (particleSpecies == 3 && (TMath::Abs(pdgCode)==211 || TMath::Abs(pdgCode)==321 || TMath::Abs(pdgCode)==2212))
327 // if mother not found, accept particle only in case of particleSpecies == 3. To include it in all or no sample is no solution
328 Printf("WARNING: No mother found for particle %d:", part->GetLabel());
332 // this code prints the details of the mother that is missing in the AOD
333 AliMCEventHandler* fMcHandler = dynamic_cast<AliMCEventHandler*> (AliAnalysisManager::GetAnalysisManager()->GetMCtruthEventHandler());
335 AliMCEvent* fMcEvent = fMcHandler->MCEvent();
337 fMcEvent->Stack()->Particle(fMcEvent->Stack()->Particle(part->GetLabel())->GetMother(0))->Print();
338 fMcEvent->Stack()->Particle(fMcEvent->Stack()->Particle(fMcEvent->Stack()->Particle(part->GetLabel())->GetMother(0))->GetMother(0))->Print();
339 Printf("eta = %f", fMcEvent->Stack()->Particle(fMcEvent->Stack()->Particle(fMcEvent->Stack()->Particle(part->GetLabel())->GetMother(0))->GetMother(0))->Eta());
342 if (particleSpecies != 3)
347 }else if (obj->InheritsFrom("TObjArray")){ // list of AliVParticle
348 TObjArray *array = static_cast<TObjArray*>(obj);
349 part = (AliVParticle*)array->At( ipart );
351 }else if (obj->InheritsFrom("AliMCEvent")){ // MC PARTICLE
352 AliMCEvent* mcEvent = static_cast<AliMCEvent*>(obj);
353 part = mcEvent->GetTrack( ipart );
355 // eventually only primaries
356 if (onlyprimaries && !( mcEvent->IsPhysicalPrimary(ipart)) )return 0;
357 // eventually only hadrons
360 Int_t pdgCode = part->GetPdgCode();
361 Bool_t isHadron = TMath::Abs(pdgCode)==211 || // Pion
362 TMath::Abs(pdgCode)==2212 || // Proton
363 TMath::Abs(pdgCode)==321; // Kaon
364 if (!isHadron) return 0;
368 }else if (obj->InheritsFrom("AliAODEvent")){ // RECO AOD TRACKS
369 AliAODEvent *aodEvent = static_cast<AliAODEvent*>(obj);
370 part = aodEvent->GetTrack(ipart);
371 // track selection cuts
372 if ( !(((AliAODTrack*)part)->TestFilterBit(fFilterBit)) ) return 0;
373 //if ( !(((AliAODTrack*)part)->TestFilterBit(fFilterBit)) && !(((AliAODTrack*)part)->TestFilterBit(32)) ) return 0;
374 // only primary candidates
375 //if ( ((AliAODTrack*)part)->IsPrimaryCandidate() )return 0;
376 // eventually only hadrons
378 Bool_t isHadron = ((AliAODTrack*)part)->GetMostProbablePID()==AliAODTrack::kPion ||
379 ((AliAODTrack*)part)->GetMostProbablePID()==AliAODTrack::kKaon ||
380 ((AliAODTrack*)part)->GetMostProbablePID()==AliAODTrack::kProton;
381 if (!isHadron) return 0;
384 }else if (obj->InheritsFrom("AliESDEvent")){ // RECO ESD TRACKS
385 AliESDEvent *esdEvent = static_cast<AliESDEvent*>(obj);
386 part = esdEvent->GetTrack(ipart);
388 // track selection cuts
390 if (!( ApplyCuts(part)) )
393 if (fFilterBit == 128)
395 // create TPC only tracks constrained to the SPD vertex
397 const AliESDVertex *vtxSPD = esdEvent->GetPrimaryVertexSPD();
399 AliESDtrack* track = AliESDtrackCuts::GetTPCOnlyTrack(esdEvent, ipart);
402 // laser warm up tracks
403 if (track->GetTPCsignal() < 10.)
407 // only constrain tracks above threshold
408 AliExternalTrackParam exParam;
409 // take the B-feild from the ESD, no 3D fieldMap available at this point
410 Bool_t relate = kFALSE;
411 relate = track->RelateToVertex(vtxSPD,esdEvent->GetMagneticField(),kVeryBig,&exParam);
414 // Printf("relating failed");
418 track->Set(exParam.GetX(),exParam.GetAlpha(),exParam.GetParameter(),exParam.GetCovariance());
424 // eventually only hadrons
427 Bool_t isHadron = ((AliAODTrack*)part)->GetMostProbablePID()==AliAODTrack::kPion ||
428 ((AliAODTrack*)part)->GetMostProbablePID()==AliAODTrack::kKaon ||
429 ((AliAODTrack*)part)->GetMostProbablePID()==AliAODTrack::kProton;
430 if (!isHadron) return 0;
434 if (fDebug > 1) AliFatal(" Analysis type not defined !!! ");
439 if (!part->Charge())return 0;
445 //-------------------------------------------------------------------
446 void AliAnalyseLeadingTrackUE::QSortTracks(TObjArray &a, Int_t first, Int_t last)
448 // Sort array of TObjArray of tracks by Pt using a quicksort algorithm.
451 static int i; // "static" to save stack space
454 while (last - first > 1) {
458 while (++i < last && ((AliVParticle*)a[i])->Pt() > ((AliVParticle*)a[first])->Pt() )
460 while (--j > first && ((AliVParticle*)a[j])->Pt() < ((AliVParticle*)a[first])->Pt() )
476 if (j - first < last - (j + 1)) {
477 QSortTracks(a, first, j);
478 first = j + 1; // QSortTracks(j + 1, last);
480 QSortTracks(a, j + 1, last);
481 last = j; // QSortTracks(first, j);
486 //____________________________________________________________________
487 TObjArray* AliAnalyseLeadingTrackUE::SortRegions(const AliVParticle* leading, TObject* obj, TObject* arrayMC, Bool_t onlyprimaries)
490 // Assign particles to towards, away or transverse regions.
491 // Returns a lists of particles for each region.
493 static const Double_t k60rad = 60.*TMath::Pi()/180.;
494 static const Double_t k120rad = 120.*TMath::Pi()/180.;
496 // Define output lists of particles
497 TList *toward = new TList();
498 TList *away = new TList();
499 // Two transverse regions, for the moment those are not yet MIN and MAX!!!
500 // MIN and MAX can be sorted in GetMinMaxRegion function
501 TList *transverse1 = new TList();
502 TList *transverse2 = new TList();
504 TObjArray *regionParticles = new TObjArray;
505 regionParticles->SetOwner(kTRUE);
507 regionParticles->AddLast(toward);
508 regionParticles->AddLast(away);
509 regionParticles->AddLast(transverse1);
510 regionParticles->AddLast(transverse2);
513 return regionParticles;
515 // Switch to vector for leading particle
516 TVector3 leadVect(leading->Px(),leading->Py(),leading->Pz());
518 Int_t nTracks = NParticles(obj);
519 if( !nTracks ) return 0;
521 for (Int_t ipart=0; ipart<nTracks; ++ipart) {
522 AliVParticle* part = ParticleWithCuts(obj, ipart);
524 //Switch to vectors for particles
525 TVector3 partVect(part->Px(), part->Py(), part->Pz());
528 if( TMath::Abs(partVect.Eta()) > fTrackEtaCut ) continue;
529 // transverse regions
530 if (leadVect.DeltaPhi(partVect) < -k60rad && leadVect.DeltaPhi(partVect) > -k120rad )region = -1; //left
531 if (leadVect.DeltaPhi(partVect) > k60rad && leadVect.DeltaPhi(partVect) < k120rad ) region = 1; //right
533 if (TMath::Abs(leadVect.DeltaPhi(partVect)) < k60rad ) region = 2; //forward
534 if (TMath::Abs(leadVect.DeltaPhi(partVect)) > k120rad ) region = -2; //backward
536 // skip leading particle
540 if (!region)continue;
541 if (arrayMC && arrayMC->InheritsFrom("TClonesArray") && obj->InheritsFrom("AliAODEvent")){
542 Int_t label = ((AliAODTrack*)part)->GetLabel();
543 // re-define part as the matched MC particle
544 part = (AliAODMCParticle*)ParticleWithCuts(arrayMC, TMath::Abs(label),onlyprimaries);
546 // skip leading particle
550 if (arrayMC && arrayMC->InheritsFrom("AliMCEvent") && obj->InheritsFrom("AliESDEvent")){
551 Int_t label = ((AliESDtrack*)part)->GetLabel();
552 // look for the matched MC particle (but do not re-define part)
553 if (!ParticleWithCuts(arrayMC, TMath::Abs(label),onlyprimaries)) continue;
556 if ( region == 1 ) transverse1->Add(part);
557 if ( region == -1 ) transverse2->Add(part);
558 if ( region == 2 ) toward->Add(part);
559 if ( region == -2 ) away->Add(part);
561 }//end loop on tracks
563 return regionParticles;
568 //____________________________________________________________________
569 Bool_t AliAnalyseLeadingTrackUE::TriggerSelection(const TObject* obj)
574 // Use AliPhysicsSelection to select good events, works for ESD and AOD
575 if (!(((AliInputEventHandler*)obj)->IsEventSelected()&(AliVEvent::kMB|AliVEvent::kUserDefined)))
581 //____________________________________________________________________
582 Bool_t AliAnalyseLeadingTrackUE::VertexSelection(const TObject* obj, Int_t ntracks, Double_t zed)
585 //Require 1 vertex (no TPC stand-alone) with a minimum number of tracks and z-coordinate in a limited range
587 if (obj->InheritsFrom("AliAODEvent")){
588 Int_t nVertex = ((AliAODEvent*)obj)->GetNumberOfVertices();
590 AliAODVertex* vertex = (AliAODVertex*)((AliAODEvent*)obj)->GetPrimaryVertex();
591 Int_t nTracksPrim = vertex->GetNContributors();
592 Double_t zVertex = vertex->GetZ();
593 if (fDebug > 1)AliInfo(Form(" Vertex in = %f with %d particles by %s data ...",zVertex,nTracksPrim,vertex->GetName()));
594 // Reject TPC only vertex
595 TString name(vertex->GetName());
596 if (name.CompareTo("PrimaryVertex") && name.CompareTo("SPDVertex"))return kFALSE;
598 // Select a quality vertex by number of tracks?
599 if( nTracksPrim < ntracks || TMath::Abs(zVertex) > zed ) {
600 if (fDebug > 1) AliInfo(" Primary-vertex Selection: event REJECTED ...");
603 // TODO remove vertexer Z events with dispersion > 0.02: Doesn't work for AOD at present
604 //if (strcmp(vertex->GetTitle(), "AliVertexerZ") == 0 && vertex->GetDispersion() > 0.02)
606 if (fDebug > 1) AliInfo(" Primary-vertex Selection: event ACCEPTED...");
608 if (fDebug > 1) AliInfo(" Primary-vertex Selection: event REJECTED ...");
613 if (obj->InheritsFrom("AliMCEvent"))
615 if (TMath::Abs(((AliMCEvent*) obj)->GetPrimaryVertex()->GetZ()) > zed)
617 if (fDebug > 1) AliInfo(" Primary-vertex Selection: event (based on MC) REJECTED ...");
622 // ESD case for DCA studies
623 if (obj->InheritsFrom("AliESDEvent")){
624 AliESDVertex* vertex = (AliESDVertex*)((AliESDEvent*)obj)->GetPrimaryVertex();
626 Int_t nTracksPrim = vertex->GetNContributors();
627 Double_t zVertex = vertex->GetZ();
628 if (fDebug > 1)AliInfo(Form(" Vertex in = %f with %d particles by %s data ...",zVertex,nTracksPrim,vertex->GetName()));
629 // Reject SPD or TPC only vertex
630 TString name(vertex->GetName());
631 if (name.CompareTo("PrimaryVertex") && name.CompareTo("SPDVertex"))return kFALSE;
633 // Select a quality vertex by number of tracks?
634 if( nTracksPrim < ntracks || TMath::Abs(zVertex) > zed ) {
635 if (fDebug > 1) AliInfo(" Primary-vertex Selection: event REJECTED ...");
638 // TODO remove vertexer Z events with dispersion > 0.02: Doesn't work for AOD at present
639 //if (strcmp(vertex->GetTitle(), "AliVertexerZ") == 0 && vertex->GetDispersion() > 0.02)
641 if (fDebug > 1) AliInfo(" Primary-vertex Selection: event ACCEPTED...");
643 if (fDebug > 1) AliInfo(" Primary-vertex Selection: event REJECTED ...");