1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 ////////////////////////////////////////////////////////////////////////////////
18 // This class works as generic interface to an event.
19 // Its main purpose is to provide a unique reference which includes all the
20 // facilities available in the AliVEvent generic base class, plus all info
21 // which could be needed during analysis, which are not in AliVEvent but
22 // need to be accessed from ESD or AOD objects, usually in different ways.
23 // When MC is available, it is properly taken into account.
25 // authors: A. Pulvirenti (alberto.pulvirenti@ct.infn.it)
26 // M. Vala (martin.vala@cern.ch)
28 ////////////////////////////////////////////////////////////////////////////////
30 #include <Riostream.h>
34 #include "AliVEvent.h"
35 #include "AliMCEvent.h"
37 #include "AliGenEventHeader.h"
38 #include "AliAODEvent.h"
39 #include "AliRsnCutPID.h"
40 #include "AliESDtrackCuts.h"
42 #include "AliRsnEvent.h"
46 AliRsnEvent* AliRsnEvent::fgRsnEvent1 = 0;
47 AliRsnEvent* AliRsnEvent::fgRsnEvent2 = 0;
49 //_____________________________________________________________________________
50 AliRsnEvent::AliRsnEvent(AliVEvent *ref, AliVEvent *refMC) :
57 // Default constructor.
61 //_____________________________________________________________________________
62 AliRsnEvent::AliRsnEvent(const AliRsnEvent &event) :
66 fLeading(event.fLeading),
67 fLocalID(event.fLocalID)
74 //_____________________________________________________________________________
75 AliRsnEvent& AliRsnEvent::operator= (const AliRsnEvent & event)
78 // Works in the same way as the copy constructor.
81 (TObject)(*this) = (TObject)event;
83 fRefMC = event.fRefMC;
84 fLeading = event.fLeading;
85 fLocalID = event.fLocalID;
90 //_____________________________________________________________________________
91 AliRsnEvent::~AliRsnEvent()
95 // Dereferences global pointer, if needed.
98 //if (gRsnCurrentEvent == this) gRsnCurrentEvent = 0;
99 //if (gRsnMixedEvent == this) gRsnMixedEvent = 0;
102 //_____________________________________________________________________________
103 Bool_t AliRsnEvent::SetDaughter(AliRsnDaughter &out, Int_t i, AliRsnDaughter::ERefType type)
106 // Using the second and third arguments, retrieves the i-th object in the
107 // appropriate sample (tracks or V0s) and sets the first reference object
108 // in order to point to that.
109 // If a MonteCarlo information is provided, sets the useful informations from there,
110 // and in case of a V0, sets the 'label' data member only when the two daughters
111 // of the V0 point to the same mother.
112 // Returns kFALSE whenever the operation fails (out of range, NULL references).
117 if (IsESD() && type == AliRsnDaughter::kTrack) ok = SetDaughterESDtrack (out, i);
118 if (IsAOD() && type == AliRsnDaughter::kTrack) ok = SetDaughterAODtrack (out, i);
119 if (IsESD() && type == AliRsnDaughter::kV0) ok = SetDaughterESDv0 (out, i);
120 if (IsAOD() && type == AliRsnDaughter::kV0) ok = SetDaughterAODv0 (out, i);
121 if (IsESD() && type == AliRsnDaughter::kCascade) ok = SetDaughterESDcascade(out, i);
122 if (IsAOD() && type == AliRsnDaughter::kCascade) ok = SetDaughterAODcascade(out, i);
127 //_____________________________________________________________________________
128 Bool_t AliRsnEvent::SetDaughterAbs(AliRsnDaughter &out, Int_t absIndex)
131 // Sets the first argument daughter using the absolute index, which
132 // runs continuously from tracks, to V0s, to cascades.
133 // In case the conversion to real index fails, the track is flagged as bad.
134 // Additionally, sets the daughter internal 'fRsnID' member to this index.
138 AliRsnDaughter::ERefType type;
140 if (!ConvertAbsoluteIndex(absIndex, index, type)) {
146 SetDaughter(out, index, type);
147 out.SetRsnID(absIndex);
151 //_____________________________________________________________________________
152 Bool_t AliRsnEvent::SetDaughterMC(AliRsnDaughter &out, Int_t label)
155 // Using the second argument, retrieves the i-th object in the
156 // MC sample (if present) and assigns the track using only that,
157 // so that it is considered both as main reference and MC reference.
158 // (used for MC-only analysis).
166 // try to convert into both types
168 AliMCEvent *esd = GetRefMCESD();
169 AliAODEvent *aod = GetRefMCAOD();
173 // if the MC track exists, assign it
174 AliMCParticle *track = (AliMCParticle*)fRef->GetTrack(label);
184 // search for its mother in stack
185 imum = track->GetMother();
186 if (imum >= 0 && imum < esd->Stack()->GetNtrack()) {
187 TParticle *mum = esd->Stack()->Particle(imum);
188 if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
194 // checks that array of MC particles exists
195 TClonesArray *mcArray = (TClonesArray*)aod->GetList()->FindObject(AliAODMCParticle::StdBranchName());
201 // in this case one has to loop over the sample to find the good one
202 TObjArrayIter next(mcArray);
203 AliAODMCParticle *part = 0x0;
204 while ((part = (AliAODMCParticle*)next())) {
205 if (TMath::Abs(part->GetLabel()) == label) {
206 // if the MC track exists, assign it
212 // search for the mother
213 imum = part->GetMother();
214 if (imum >= 0 && imum < mcArray->GetEntriesFast()) {
215 AliAODMCParticle *mum = (AliAODMCParticle*)mcArray->At(imum);
216 if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
227 //_____________________________________________________________________________
228 AliRsnDaughter AliRsnEvent::GetDaughter(Int_t i, AliRsnDaughter::ERefType type)
231 // Returns a daughter set using same criteria as SetDaughter
235 SetDaughter(d, i, type);
239 //_____________________________________________________________________________
240 AliRsnDaughter AliRsnEvent::GetDaughterAbs(Int_t absIndex)
243 // Returns a daughter set using same criteria as SetDaughter
247 SetDaughterAbs(d, absIndex);
251 //_____________________________________________________________________________
252 AliRsnDaughter AliRsnEvent::GetDaughterMC(Int_t i)
255 // Returns a daughter set using same criteria as SetDaughterMC
263 //_____________________________________________________________________________
264 Int_t AliRsnEvent::GetAbsoluteSum()
267 // Utility method that returns the sum of all daughter-like objects:
268 // tracks, V0s and cascades
273 total += fRef->GetNumberOfTracks();
274 total += fRef->GetNumberOfV0s();
275 total += fRef->GetNumberOfCascades();
280 //_____________________________________________________________________________
281 Bool_t AliRsnEvent::ConvertAbsoluteIndex(Int_t index, Int_t &realIndex, AliRsnDaughter::ERefType &type)
284 // Using the phylosophy of the absolute index, which loops over
285 // all tracks, V0s and cascades, returns the result of a check
286 // on it (first argument) based on this criterion:
287 // 1) if the absolute ID is smaller than number of tracks,
288 // return itself and the type 'track'
289 // 2) if the absolute ID is larger than number of tracks, subtract it
290 // and if the result is smaller than number of V0s,
291 // return the corresponding V0 index and type
292 // 3) if the absolute ID is larger than number of tracks + V0s, subtract them
293 // and if the result is smaller than number of cascades,
294 // return the corresponding cascade index and type
295 // The results of this check are stored in the reference arguments, while the outcome of
296 // the function is kTRUE if one of these checks was successful, otherwise it is kFALSE,
297 // meaning that the absolute index reached the end.
300 Int_t nTracks = fRef->GetNumberOfTracks();
301 Int_t nV0s = fRef->GetNumberOfV0s();
302 Int_t nCascades = fRef->GetNumberOfCascades();
304 if (index < nTracks) {
306 type = AliRsnDaughter::kTrack;
308 } else if (index >= nTracks && index < nTracks + nV0s) {
309 realIndex = index - nTracks;
310 type = AliRsnDaughter::kV0;
312 } else if (index >= nTracks + nV0s && index < nTracks + nV0s + nCascades) {
313 realIndex = index - nTracks - nV0s;
314 type = AliRsnDaughter::kCascade;
319 type = AliRsnDaughter::kNoType;
323 //_____________________________________________________________________________
324 Int_t AliRsnEvent::ConvertRealIndex(Int_t index, AliRsnDaughter::ERefType type)
327 // Translates a pair made by index + object type into the corresponding
328 // absolute index, which is set to -1 in case the real index overflows.
331 Int_t nTracks = fRef->GetNumberOfTracks();
332 Int_t nV0s = fRef->GetNumberOfV0s();
333 Int_t nCascades = fRef->GetNumberOfCascades();
336 case AliRsnDaughter::kTrack:
337 if (index >= 0 && index < nTracks)
341 case AliRsnDaughter::kV0:
342 if (index >= 0 && index < nV0s)
343 return nTracks + index;
346 case AliRsnDaughter::kCascade:
347 if (index >= 0 && index < nCascades)
348 return nTracks + nV0s + index;
356 //_____________________________________________________________________________
357 Int_t AliRsnEvent::GetMultiplicity(AliESDtrackCuts *cuts)
360 // Returns event multiplicity as the number of tracks.
361 // If the argument is not NULL, returns instead the
362 // number of tracks passing the cuts hereby defined.
367 AliESDEvent *esd = GetRefESD();
368 if (cuts && esd) return cuts->CountAcceptedTracks(esd);
369 else return fRef->GetNumberOfTracks();
372 //_____________________________________________________________________________
373 Int_t AliRsnEvent::GetMultiplicityMC()
376 // Returns event multiplicity as the number of primary tracks
377 // counted from the MC sample, if present.
380 if (!fRefMC) return 0;
383 return GetRefMCESD()->Stack()->GetNprimary();
385 return GetRefMCAOD()->GetNumberOfTracks();
390 //_____________________________________________________________________________
391 Double_t AliRsnEvent::GetVz()
394 // Return Z coord of primary vertex
397 return fRef->GetPrimaryVertex()->GetZ();
400 //_____________________________________________________________________________
401 Int_t AliRsnEvent::SelectLeadingParticle
402 (Double_t ptMin, AliRsnCutPID *cutPID)
405 // Searches the collection of all particles with given PID type and charge,
406 // and returns the one with largest momentum, provided that it is greater than 1st argument.
407 // If one specifies AliRsnPID::kUnknown as type or AliRsnDaughter::kNoPID as method,
408 // the check is done over all particles irrespectively of their PID.
409 // If the sign argument is '+' or '-', the check is done over the particles of that charge,
410 // otherwise it is done irrespectively of the charge.
413 Int_t i, nTracks = fRef->GetNumberOfTracks();
415 AliRsnDaughter leading;
418 for (i = 0; i < nTracks; i++) {
419 AliRsnDaughter track = GetDaughter(i);
420 if (cutPID) if (!cutPID->IsSelected(&track)) continue;
421 const AliVParticle *ref = track.GetRef();
422 if (ref->Pt() < ptMin) continue;
423 //double pt = track.P().Perp();
424 //Printf("track %d %g", i, pt);
425 if (!leading.IsOK() || ref->Pt() > ptMin) {
434 //_________________________________________________________________________________________________
435 Double_t AliRsnEvent::GetAverageMomentum(Int_t &count, AliRsnCutPID *cutPID)
438 // Loops on the list of tracks and computes average total momentum.
441 Int_t i, nTracks = fRef->GetNumberOfTracks();
442 Double_t pmean = 0.0;
444 for (i = 0, count = 0; i < nTracks; i++) {
445 AliRsnDaughter track = GetDaughter(i);
446 if (cutPID) if (!cutPID->IsSelected(&track)) continue;
447 pmean += track.Prec().Mag();
451 if (count > 0) pmean /= (Double_t)count;
457 //_____________________________________________________________________________
458 Bool_t AliRsnEvent::GetAngleDistr
459 (Double_t &angleMean, Double_t &angleRMS, AliRsnDaughter *ref)
462 // Takes the leading particle and computes the mean and RMS
463 // of the distribution of directions of all other tracks
464 // with respect to the direction of leading particle.
467 AliRsnDaughter leading;
468 if (ref) leading = *ref;
469 else if (fLeading >= 0) SetDaughter(leading, fLeading, AliRsnDaughter::kTrack);
470 if (!leading.IsOK()) return kFALSE;
472 Int_t i, count, nTracks = fRef->GetNumberOfTracks();
473 Double_t angle, angle2Mean = 0.0;
475 angleMean = angle2Mean = 0.0;
477 for (i = 0, count = 0; i < nTracks; i++) {
478 AliRsnDaughter trk = GetDaughter(i);
479 if (trk.GetID() == leading.GetID()) continue;
481 angle = leading.Prec().Angle(trk.Prec().Vect());
484 angle2Mean += angle * angle;
488 if (!count) return kFALSE;
490 angleMean /= (Double_t)count;
491 angle2Mean /= (Double_t)count;
492 angleRMS = TMath::Sqrt(angle2Mean - angleMean * angleMean);
497 //_____________________________________________________________________________
498 Bool_t AliRsnEvent::SetDaughterESDtrack(AliRsnDaughter &out, Int_t i)
501 // Setup the first argument to the track identified by the index.
502 // When available, adds the MC information and references.
504 // Version #1: ESD tracks
507 // check 1: index in good range
508 if (i < 0 || i >= fRef->GetNumberOfTracks()) {
513 // check 2: not NULL object
514 AliVTrack *track = (AliVTrack*)fRef->GetTrack(i);
520 // assign references of reconstructed track
521 Int_t label = TMath::Abs(track->GetLabel());
526 // assign MC info, if available
527 return SetMCInfoESD(out);
530 //_____________________________________________________________________________
531 Bool_t AliRsnEvent::SetDaughterAODtrack(AliRsnDaughter &out, Int_t i)
534 // Setup the first argument to the track identified by the index.
535 // When available, adds the MC information and references.
537 // Version #2: AOD tracks
540 // check 1: index in good range
541 if (i < 0 || i >= fRef->GetNumberOfTracks()) {
546 // check 2: not NULL object
547 AliVTrack *track = (AliVTrack*)fRef->GetTrack(i);
553 // assign references of reconstructed track
554 Int_t label = TMath::Abs(track->GetLabel());
559 // assign MC info, if available
560 return SetMCInfoAOD(out);
563 //_____________________________________________________________________________
564 Bool_t AliRsnEvent::SetDaughterESDv0(AliRsnDaughter &out, Int_t i)
567 // Setup the first argument to the track identified by the index.
568 // When available, adds the MC information and references.
570 // Version #3: ESD v0
573 // check 1: index in good range
574 if (i > fRef->GetNumberOfV0s()) {
579 // check 2: not NULL object
580 AliESDEvent *ev = GetRefESD();
581 AliESDv0 *v0 = ev->GetV0(i);
587 // assign references of reconstructed track
592 // this time, assigning label is not trivial,
593 // it is done only if MC is present and both
594 // daughters come from a true particle
595 AliMCEvent *mc = GetRefMCESD();
596 AliESDtrack *tp = ev->GetTrack(v0->GetPindex());
597 AliESDtrack *tn = ev->GetTrack(v0->GetNindex());
598 if (mc && tp && tn) {
599 Int_t lp = TMath::Abs(tp->GetLabel());
600 Int_t ln = TMath::Abs(tn->GetLabel());
601 TParticle *pp = mc->Stack()->Particle(lp);
602 TParticle *pn = mc->Stack()->Particle(ln);
603 // if their first mothers are the same, the V0 is true
604 // otherwise no label can be assigned
605 if (pp->GetFirstMother() == pn->GetFirstMother() && pp->GetFirstMother() >= 0) out.SetLabel(pp->GetFirstMother());
608 // assign MC info, if available
609 return SetMCInfoESD(out);
612 //_____________________________________________________________________________
613 Bool_t AliRsnEvent::SetDaughterAODv0(AliRsnDaughter &out, Int_t i)
616 // Setup the first argument to the track identified by the index.
617 // When available, adds the MC information and references.
619 // Version #4: AOD v0
622 // check 1: index in good range
623 if (i > fRef->GetNumberOfV0s()) {
628 // check 2: not NULL object
629 AliAODEvent *ev = GetRefAOD();
630 AliAODv0 *v0 = ev->GetV0(i);
636 TClonesArray *mcArray = (TClonesArray*)ev->GetList()->FindObject(AliAODMCParticle::StdBranchName());
642 // assign references of reconstructed track
647 // this time, assigning label is not trivial,
648 // it is done only if MC is present and both
649 // daughters come from a true particle
650 AliAODTrack *tp = ev->GetTrack(v0->GetPosID());
651 AliAODTrack *tn = ev->GetTrack(v0->GetNegID());
652 if (mcArray && tp && tn) {
653 Int_t lp = TMath::Abs(tp->GetLabel());
654 Int_t ln = TMath::Abs(tn->GetLabel());
655 // loop on array to find MC daughters
656 AliAODMCParticle *pp = 0x0, *pn = 0x0;
657 Int_t ipp = -1, ipn = -1;
658 TObjArrayIter next(mcArray);
659 AliAODMCParticle *part = 0x0;
660 while ((part = (AliAODMCParticle*)next())) {
661 if (TMath::Abs(part->GetLabel()) == lp) ipp = mcArray->IndexOf(part);
662 if (TMath::Abs(part->GetLabel()) == ln) ipn = mcArray->IndexOf(part);
664 if (ipp >= 0) pp = (AliAODMCParticle*)mcArray->At(ipp);
665 if (ipn >= 0) pn = (AliAODMCParticle*)mcArray->At(ipn);
666 if (!pp || !pn) return kTRUE;
667 // assign a MC reference and a label only to true V0s
668 if (pp->GetMother() == pn->GetMother() && pp->GetMother() >= 0) out.SetLabel(pp->GetMother());
671 // assign MC info, if available
672 return SetMCInfoAOD(out);
675 //_____________________________________________________________________________
676 Bool_t AliRsnEvent::SetDaughterESDcascade(AliRsnDaughter &, Int_t)
679 // Setup the first argument to the track identified by the index.
680 // When available, adds the MC information and references.
682 // Version #3: ESD cascade
688 //_____________________________________________________________________________
689 Bool_t AliRsnEvent::SetDaughterAODcascade(AliRsnDaughter &, Int_t)
692 // Setup the first argument to the track identified by the index.
693 // When available, adds the MC information and references.
695 // Version #4: AOD cascade
701 //_____________________________________________________________________________
702 Bool_t AliRsnEvent::SetMCInfoESD(AliRsnDaughter &out)
705 // Using the label assigned to the daughter, searches for the MC informations:
710 Int_t label = out.GetLabel();
712 // if no MC reference is available, exit here (successfully)
713 AliMCEvent *mc = GetRefMCESD();
714 if (!mc) return kTRUE;
715 Int_t nMC = mc->GetNumberOfTracks();
717 // debug message for fakes
719 AliDebug(AliLog::kDebug + 1, "Fake object (fake track or false V0)");
723 // assign MC reference, being aware of eventual
724 // overflows in the array (sometimes happened)
726 AliWarning(Form("Stack overflow: track label = %d -- stack maximum = %d", label, nMC));
729 AliMCParticle *mcPart = (AliMCParticle*)mc->GetTrack(label);
731 AliWarning(Form("Stack discontinuity: label %d refers to a NULL object", label));
734 out.SetRefMC(mcPart);
736 // if this is a primary track, exit here (successfully)
737 Int_t imum = mcPart->Particle()->GetFirstMother();
743 // if didn't stop there, search for the mother
745 AliWarning(Form("Stack overflow: track mother label = %d -- stack maximum = %d", label, nMC));
748 AliMCParticle *mcMother = (AliMCParticle*)mc->GetTrack(imum);
750 AliWarning(Form("Stack discontinuity: label mother %d refers to a NULL object", imum));
753 out.SetMotherPDG(TMath::Abs(mcMother->Particle()->GetPdgCode()));
758 //_____________________________________________________________________________
759 Bool_t AliRsnEvent::SetMCInfoAOD(AliRsnDaughter &out)
762 // Using the label assigned to the daughter, searches for the MC informations:
767 Int_t label = out.GetLabel();
769 // debug message for fakes
771 AliDebug(AliLog::kDebug + 1, "Fake object (fake track or false V0)");
775 // if no MC reference is available, exit here (successfully)
776 AliAODEvent *mc = GetRefMCAOD();
777 if (!mc) return kTRUE;
779 // loop on particles using the track label as reference
780 // and then assign also the mother type, if found
781 TClonesArray *mcArray = (TClonesArray*)mc->GetList()->FindObject(AliAODMCParticle::StdBranchName());
782 if (!mcArray) return kFALSE;
783 TObjArrayIter next(mcArray);
784 AliAODMCParticle *part = 0x0;
785 while ((part = (AliAODMCParticle*)next())) {
786 if (TMath::Abs(part->GetLabel()) == label) {
789 Int_t imum = part->GetMother();
790 if (imum >= 0 && imum <= mcArray->GetEntriesFast()) {
791 AliAODMCParticle *mum = (AliAODMCParticle*)mcArray->At(imum);
792 if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
795 AliWarning(Form("Array overflow: track mother label = %d -- stack maximum = %d", imum, mcArray->GetEntriesFast()));
799 // if a MC reference is found, there is no need to go on with the loop