5 #include "AliMCParticle.h"
7 #include "AliAnalysisTask.h"
8 #include "AliAnalysisManager.h"
10 #include "AliVEvent.h"
11 #include "AliESDEvent.h"
12 #include "AliAODEvent.h"
13 #include "AliMCEvent.h"
14 #include "AliESDInputHandler.h"
15 #include "AliInputEventHandler.h"
16 #include "AliVTrack.h"
17 #include "AliExternalTrackParam.h"
18 #include "AliVVertex.h"
19 #include "AliAnalysisFilter.h"
20 #include "AliAnalysisUtils.h"
22 #include "AliPIDResponse.h"
23 #include "AliESDv0KineCuts.h"
26 #include "AliAnalysisTaskPIDV0base.h"
29 This class is a base class for all other
30 analysis tasks that use V0's.
31 It provides basics for V0 identification.
32 In addition, some further basic functions are provided.
34 Class written by Benjamin Hess.
35 Contact: bhess@cern.ch
38 ClassImp(AliAnalysisTaskPIDV0base)
40 Double_t AliAnalysisTaskPIDV0base::fgCutGeo = 1.;
41 Double_t AliAnalysisTaskPIDV0base::fgCutNcr = 0.85;
42 Double_t AliAnalysisTaskPIDV0base::fgCutNcl = 0.7;
44 UShort_t AliAnalysisTaskPIDV0base::fgCutPureNcl = 60;
46 //________________________________________________________________________
47 AliAnalysisTaskPIDV0base::AliAnalysisTaskPIDV0base()
66 , fStoreMotherIndex(kFALSE)
69 // default Constructor
71 fRandom = new TRandom3(0); // 0 means random seed
74 // Question: Is this the right place to initialize these functions?
75 // Will it work on proof? i.e. will they be streamed to the workers?
76 // Also one should add getters and setters
77 fPhiCutLow = new TF1("StdPhiCutLow", "0.1/x/x+pi/18.0-0.025", 0, 100);
78 fPhiCutHigh = new TF1("StandardPhiCutHigh", "0.12/x+pi/18.0+0.035", 0, 100);
81 //________________________________________________________________________
82 AliAnalysisTaskPIDV0base::AliAnalysisTaskPIDV0base(const char *name)
83 : AliAnalysisTaskSE(name)
101 , fStoreMotherIndex(kFALSE)
102 , fV0motherIndex(0x0)
106 fRandom = new TRandom3(0); // 0 means random seed
109 // Question: Is this the right place to initialize these functions?
110 // Will it work on proof? i.e. will they be streamed to the workers?
111 // Also one should add getters and setters
112 fPhiCutLow = new TF1("StdPhiCutLow", "0.1/x/x+pi/18.0-0.025", 0, 100);
113 fPhiCutHigh = new TF1("StandardPhiCutHigh", "0.12/x+pi/18.0+0.035", 0, 100);
115 DefineInput (0, TChain::Class());
116 DefineOutput(0, TTree::Class());
120 //________________________________________________________________________
121 AliAnalysisTaskPIDV0base::~AliAnalysisTaskPIDV0base()
144 delete fV0motherIndex;
152 //________________________________________________________________________
153 void AliAnalysisTaskPIDV0base::UserCreateOutputObjects()
159 AliAnalysisManager* man = AliAnalysisManager::GetAnalysisManager();
160 AliInputEventHandler* inputHandler = dynamic_cast<AliInputEventHandler*>(man->GetInputEventHandler());
163 AliFatal("Input handler needed");
169 // PID response object
170 fPIDResponse = inputHandler->GetPIDResponse();
172 AliError("PIDResponse object was not created");
175 fV0KineCuts = new AliESDv0KineCuts;
176 fV0KineCuts->SetGammaCutChi2NDF(5.);
177 // Only accept V0el with prod. radius within 45 cm -> PID will by systematically biased for larger values!
178 Float_t gammaProdVertexRadiusCuts[2] = { 3.0, 45. };
179 fV0KineCuts->SetGammaCutVertexR(&gammaProdVertexRadiusCuts[0]);
181 // Default analysis utils
182 fAnaUtils = new AliAnalysisUtils();
186 //________________________________________________________________________
187 void AliAnalysisTaskPIDV0base::UserExec(Option_t *)
190 // Called for each event
193 //________________________________________________________________________
194 void AliAnalysisTaskPIDV0base::Terminate(const Option_t *)
196 // Called once at the end of the query
200 //_____________________________________________________________________________
201 Double_t AliAnalysisTaskPIDV0base::GetPhiPrime(Double_t phi, Double_t magField, Int_t charge) const
203 // Get phiPrime which is the cut variable to reject high pT tracks near edges
205 if(magField < 0) // for negatve polarity field
206 phi = TMath::TwoPi() - phi;
208 if(charge < 0) // for negatve charge
209 phi = TMath::TwoPi() - phi;
211 phi += TMath::Pi() / 18.0; // to center gap in the middle
212 phi = fmod(phi, TMath::Pi() / 9.0);
217 //______________________________________________________________________________
218 Bool_t AliAnalysisTaskPIDV0base::PhiPrimeCut(Double_t trackPt, Double_t trackPhi, Short_t trackCharge, Double_t magField) const
220 // Apply phi' cut to given track parameters
225 Double_t phiPrime = GetPhiPrime(trackPhi, magField, trackCharge);
227 if (phiPrime < fPhiCutHigh->Eval(trackPt) && phiPrime > fPhiCutLow->Eval(trackPt))
228 return kFALSE; // reject track
234 //______________________________________________________________________________
235 Bool_t AliAnalysisTaskPIDV0base::PhiPrimeCut(const AliVTrack* track, Double_t magField) const
237 return PhiPrimeCut(track->Pt(), track->Phi(), track->Charge(), magField);
241 //______________________________________________________________________________
242 Bool_t AliAnalysisTaskPIDV0base::GetVertexIsOk(AliVEvent* event, Bool_t doVtxZcut) const
244 // Check whether vertex ful-fills quality requirements.
245 // Apply cut on z-position of vertex if doVtxZcut = kTRUE.
247 AliAODEvent* aod = 0x0;
248 AliESDEvent* esd = 0x0;
250 aod = dynamic_cast<AliAODEvent*>(event);
252 esd = dynamic_cast<AliESDEvent*>(event);
255 AliError("Event seems to be neither AOD nor ESD!");
261 const AliVVertex* trkVtx = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertex()) :
262 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertex()));
264 if (!trkVtx || trkVtx->GetNContributors() <= 0)
267 TString vtxTtl = trkVtx->GetTitle();
268 if (!vtxTtl.Contains("VertexerTracks"))
271 Float_t zvtx = trkVtx->GetZ();
272 const AliVVertex* spdVtx = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertexSPD()) :
273 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertexSPD()));
274 if (spdVtx->GetNContributors() <= 0)
277 TString vtxTyp = spdVtx->GetTitle();
278 Double_t cov[6] = {0};
279 spdVtx->GetCovarianceMatrix(cov);
280 Double_t zRes = TMath::Sqrt(cov[5]);
281 if (vtxTyp.Contains("vertexer:Z") && (zRes > 0.25))
284 if (TMath::Abs(spdVtx->GetZ() - trkVtx->GetZ()) > 0.5)
288 if (TMath::Abs(zvtx) > fZvtxCutEvent) //Default: 10 cm
297 const AliVVertex* primaryVertex = (aod ? dynamic_cast<const AliVVertex*>(aod->GetPrimaryVertex()) :
298 dynamic_cast<const AliVVertex*>(esd->GetPrimaryVertexTracks()));
300 if (!primaryVertex || primaryVertex->GetNContributors() <= 0)
304 if (TMath::Abs(primaryVertex->GetZ()) > fZvtxCutEvent) //Default: 10 cm
312 //______________________________________________________________________________
313 Bool_t AliAnalysisTaskPIDV0base::GetIsPileUp(AliVEvent* event, AliAnalysisTaskPIDV0base::PileUpRejectionType pileUpRejectionType) const
315 // Check whether event is a pile-up event according to current AnalysisUtils object.
316 // If rejection type is kPileUpRejectionOff, kFALSE is returned.
317 // In case of errors, the error is displayed and kTRUE is returned.
319 if (pileUpRejectionType == kPileUpRejectionOff)
323 AliError("No event!");
328 AliError("AnalysisUtils object not available!");
332 if (pileUpRejectionType == kPileUpRejectionSPD)
333 return fAnaUtils->IsPileUpSPD(event);
334 else if (pileUpRejectionType == kPileUpRejectionMV)
335 return fAnaUtils->IsPileUpMV(event);
341 //______________________________________________________________________________
342 void AliAnalysisTaskPIDV0base::FillV0PIDlist(AliESDEvent* event)
345 // Fill the PID tag list
348 // If no event forwarded as parameter (default), cast current input event.
349 // Dynamic cast to ESD events (DO NOTHING for AOD events)
351 event = dynamic_cast<AliESDEvent *>(InputEvent());
353 // If this fails, do nothing
355 AliError("Failed to retrieve ESD event. No V0's processed (only works for ESDs by now).");
360 AliError("V0KineCuts not available!");
364 TString beamType(event->GetBeamType());
366 if (beamType.CompareTo("Pb-Pb") == 0 || beamType.CompareTo("A-A") == 0) {
367 fV0KineCuts->SetMode(AliESDv0KineCuts::kPurity, AliESDv0KineCuts::kPbPb);
370 fV0KineCuts->SetMode(AliESDv0KineCuts::kPurity, AliESDv0KineCuts::kPP);
375 fV0KineCuts->SetEvent(event);
377 const Int_t numTracks = event->GetNumberOfTracks();
378 fV0tags = new Char_t[numTracks];
379 for (Int_t i = 0; i < numTracks; i++)
382 if (fStoreMotherIndex) {
383 fV0motherIndex = new Int_t[numTracks];
384 for (Int_t i = 0; i < numTracks; i++)
385 fV0motherIndex[i] = -1;
388 fNumTagsStored = numTracks;
390 // loop over V0 particles
391 for (Int_t iv0 = 0; iv0 < event->GetNumberOfV0s(); iv0++) {
392 AliESDv0* v0 = (AliESDv0*)event->GetV0(iv0);
397 // Reject onFly V0's <-> Only take V0's from offline V0 finder
398 if (v0->GetOnFlyStatus())
401 // Get the particle selection
402 Bool_t foundV0 = kFALSE;
403 Int_t pdgV0 = 0, pdgP = 0, pdgN = 0;
405 foundV0 = fV0KineCuts->ProcessV0(v0, pdgV0, pdgP, pdgN);
409 Int_t iTrackP = v0->GetPindex(); // positive track
410 Int_t iTrackN = v0->GetNindex(); // negative track
413 // Fill the Object arrays
414 // positive particles
416 fV0tags[iTrackP] = 14;
418 else if (pdgP == 211) {
419 fV0tags[iTrackP] = 15;
421 else if(pdgP == 2212) {
422 fV0tags[iTrackP] = 16;
425 if (fStoreMotherIndex)
426 fV0motherIndex[iTrackP] = iv0;
428 // negative particles
430 fV0tags[iTrackN] = -14;
432 else if( pdgN == -211){
433 fV0tags[iTrackN] = -15;
435 else if( pdgN == -2212){
436 fV0tags[iTrackN] = -16;
439 if (fStoreMotherIndex)
440 fV0motherIndex[iTrackN] = iv0;
445 //______________________________________________________________________________
446 void AliAnalysisTaskPIDV0base::ClearV0PIDlist()
449 // Clear the PID tag list
455 delete fV0motherIndex;
462 //______________________________________________________________________________
463 Char_t AliAnalysisTaskPIDV0base::GetV0tag(Int_t trackIndex) const
466 // Get the tag for the corresponding trackIndex. Returns -99 in case of invalid index/tag list.
469 if (trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0tags)
472 return fV0tags[trackIndex];
476 //______________________________________________________________________________
477 Int_t AliAnalysisTaskPIDV0base::GetV0motherIndex(Int_t trackIndex) const
480 // Get the index of the V0 mother for the corresponding trackIndex. Returns -99 in case of invalid index/mother index list.
483 if (!fStoreMotherIndex || trackIndex < 0 || trackIndex >= fNumTagsStored || !fV0motherIndex)
486 return fV0motherIndex[trackIndex];
490 //________________________________________________________________________
491 Bool_t AliAnalysisTaskPIDV0base::TPCCutMIGeo(const AliVTrack* track, const AliVEvent* evt, TTreeStream* streamer)
500 const Short_t sign = track->Charge();
506 track->GetPxPyPz(pxpypz);
508 AliExternalTrackParam* par = new AliExternalTrackParam(xyz, pxpypz, cv, sign);
509 const AliESDtrack dummy;
511 const Double_t magField = evt->GetMagneticField();
512 Double_t varGeom = dummy.GetLengthInActiveZone(par, 3, 236, magField, 0, 0);
513 Double_t varNcr = track->GetTPCClusterInfo(3, 1);
514 Double_t varNcls = track->GetTPCsignalN();
516 const Double_t varEval = 130. - 5. * TMath::Abs(1. / track->Pt());
517 Bool_t cutGeom = varGeom > fgCutGeo * varEval;
518 Bool_t cutNcr = varNcr > fgCutNcr * varEval;
519 Bool_t cutNcls = varNcls > fgCutNcl * varEval;
521 Bool_t kout = cutGeom && cutNcr && cutNcls;
524 Double_t dedx = track->GetTPCsignal();
526 (*streamer)<<"tree"<<
528 "varGeom="<<varGeom<<
530 "varNcls="<<varNcls<<
532 "cutGeom="<<cutGeom<<
534 "cutNcls="<<cutNcls<<
548 //________________________________________________________________________
549 Bool_t AliAnalysisTaskPIDV0base::TPCnclCut(const AliVTrack* track)
552 // TPC Cut on TPCsignalN() only
558 return (track->GetTPCsignalN() >= fgCutPureNcl);