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 "AliESDtrackCuts.h"
39 #include "AliESDUtils.h"
40 #include "AliAODVertex.h"
41 #include "AliMultiplicity.h"
42 #include "AliRsnCutPID.h"
43 #include "AliRsnEvent.h"
47 //_____________________________________________________________________________
48 AliRsnEvent::AliRsnEvent(AliVEvent *ref, AliVEvent *refMC) :
56 // Default constructor.
60 //_____________________________________________________________________________
61 AliRsnEvent::AliRsnEvent(const AliRsnEvent &event) :
65 fLeading(event.fLeading),
66 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;
91 //_____________________________________________________________________________
92 AliRsnEvent::~AliRsnEvent()
96 // Dereferences global pointer, if needed.
99 //if (gRsnCurrentEvent == this) gRsnCurrentEvent = 0;
100 //if (gRsnMixedEvent == this) gRsnMixedEvent = 0;
103 //_____________________________________________________________________________
104 Bool_t AliRsnEvent::SetDaughter(AliRsnDaughter &out, Int_t i, AliRsnDaughter::ERefType type)
107 // Using the second and third arguments, retrieves the i-th object in the
108 // appropriate sample (tracks or V0s) and sets the first reference object
109 // in order to point to that.
110 // If a MonteCarlo information is provided, sets the useful informations from there,
111 // and in case of a V0, sets the 'label' data member only when the two daughters
112 // of the V0 point to the same mother.
113 // Returns kFALSE whenever the operation fails (out of range, NULL references).
119 out.SetOwnerEvent(this);
121 if (IsESD() && type == AliRsnDaughter::kTrack) ok = SetDaughterESDtrack (out, i);
122 if (IsAOD() && type == AliRsnDaughter::kTrack) ok = SetDaughterAODtrack (out, i);
123 if (IsESD() && type == AliRsnDaughter::kV0) ok = SetDaughterESDv0 (out, i);
124 if (IsAOD() && type == AliRsnDaughter::kV0) ok = SetDaughterAODv0 (out, i);
125 if (IsESD() && type == AliRsnDaughter::kCascade) ok = SetDaughterESDcascade(out, i);
126 if (IsAOD() && type == AliRsnDaughter::kCascade) ok = SetDaughterAODcascade(out, i);
131 //_____________________________________________________________________________
132 Bool_t AliRsnEvent::SetDaughterAbs(AliRsnDaughter &out, Int_t absIndex)
135 // Sets the first argument daughter using the absolute index, which
136 // runs continuously from tracks, to V0s, to cascades.
137 // In case the conversion to real index fails, the track is flagged as bad.
138 // Additionally, sets the daughter internal 'fRsnID' member to this index.
142 AliRsnDaughter::ERefType type;
144 out.SetRsnID(absIndex);
146 if (ConvertAbsoluteIndex(absIndex, index, type)) {
147 return SetDaughter(out, index, type);
155 //_____________________________________________________________________________
156 Bool_t AliRsnEvent::SetDaughterMC(AliRsnDaughter &out, Int_t label)
159 // Using the second argument, retrieves the i-th object in the
160 // MC sample (if present) and assigns the track using only that,
161 // so that it is considered both as main reference and MC reference.
162 // (used for MC-only analysis).
170 // try to convert into both types
172 AliMCEvent *esd = GetRefMCESD();
173 AliAODEvent *aod = GetRefMCAOD();
177 // if the MC track exists, assign it
178 AliMCParticle *track = (AliMCParticle*)fRef->GetTrack(label);
188 // search for its mother in stack
189 imum = track->GetMother();
190 if (imum >= 0 && imum < esd->Stack()->GetNtrack()) {
191 TParticle *mum = esd->Stack()->Particle(imum);
192 if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
198 // checks that array of MC particles exists
199 TClonesArray *mcArray = (TClonesArray*)aod->GetList()->FindObject(AliAODMCParticle::StdBranchName());
205 // in this case one has to loop over the sample to find the good one
206 TObjArrayIter next(mcArray);
207 AliAODMCParticle *part = 0x0;
208 while ((part = (AliAODMCParticle*)next())) {
209 if (TMath::Abs(part->GetLabel()) == label) {
210 // if the MC track exists, assign it
216 // search for the mother
217 imum = part->GetMother();
218 if (imum >= 0 && imum < mcArray->GetEntriesFast()) {
219 AliAODMCParticle *mum = (AliAODMCParticle*)mcArray->At(imum);
220 if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
228 out.SetOwnerEvent(this);
233 //_____________________________________________________________________________
234 AliRsnDaughter AliRsnEvent::GetDaughter(Int_t i, AliRsnDaughter::ERefType type)
237 // Returns a daughter set using same criteria as SetDaughter
241 SetDaughter(d, i, type);
245 //_____________________________________________________________________________
246 AliRsnDaughter AliRsnEvent::GetDaughterAbs(Int_t absIndex)
249 // Returns a daughter set using same criteria as SetDaughter
253 SetDaughterAbs(d, absIndex);
257 //_____________________________________________________________________________
258 AliRsnDaughter AliRsnEvent::GetDaughterMC(Int_t i)
261 // Returns a daughter set using same criteria as SetDaughterMC
269 //_____________________________________________________________________________
270 Bool_t AliRsnEvent::ConvertAbsoluteIndex(Int_t index, Int_t &realIndex, AliRsnDaughter::ERefType &type)
273 // Using the phylosophy of the absolute index, which loops over
274 // all tracks, V0s and cascades, returns the result of a check
275 // on it (first argument) based on this criterion:
276 // 1) if the absolute ID is smaller than number of tracks,
277 // return itself and the type 'track'
278 // 2) if the absolute ID is larger than number of tracks, subtract it
279 // and if the result is smaller than number of V0s,
280 // return the corresponding V0 index and type
281 // 3) if the absolute ID is larger than number of tracks + V0s, subtract them
282 // and if the result is smaller than number of cascades,
283 // return the corresponding cascade index and type
284 // The results of this check are stored in the reference arguments, while the outcome of
285 // the function is kTRUE if one of these checks was successful, otherwise it is kFALSE,
286 // meaning that the absolute index reached the end.
289 Int_t nTracks = fRef->GetNumberOfTracks();
290 Int_t nV0s = fRef->GetNumberOfV0s();
291 Int_t nCascades = fRef->GetNumberOfCascades();
293 if (index < nTracks) {
295 type = AliRsnDaughter::kTrack;
297 } else if (index >= nTracks && index < nTracks + nV0s) {
298 realIndex = index - nTracks;
299 type = AliRsnDaughter::kV0;
301 } else if (index >= nTracks + nV0s && index < nTracks + nV0s + nCascades) {
302 realIndex = index - nTracks - nV0s;
303 type = AliRsnDaughter::kCascade;
308 type = AliRsnDaughter::kNoType;
312 //_____________________________________________________________________________
313 Int_t AliRsnEvent::ConvertRealIndex(Int_t index, AliRsnDaughter::ERefType type)
316 // Translates a pair made by index + object type into the corresponding
317 // absolute index, which is set to -1 in case the real index overflows.
320 Int_t nTracks = fRef->GetNumberOfTracks();
321 Int_t nV0s = fRef->GetNumberOfV0s();
322 Int_t nCascades = fRef->GetNumberOfCascades();
325 case AliRsnDaughter::kTrack:
326 if (index >= 0 && index < nTracks)
330 case AliRsnDaughter::kV0:
331 if (index >= 0 && index < nV0s)
332 return nTracks + index;
335 case AliRsnDaughter::kCascade:
336 if (index >= 0 && index < nCascades)
337 return nTracks + nV0s + index;
345 //_____________________________________________________________________________
346 Int_t AliRsnEvent::GetMultiplicityFromESDCuts()
349 // Returns event multiplicity as the number of
350 // tracks passing the standard quality cuts.
353 if (!fRef) return -1;
355 AliESDEvent *esd = GetRefESD();
357 return AliESDtrackCuts::GetReferenceMultiplicity(esd, kTRUE);
359 AliWarning("Invoked multicplicity estimation from AliESDtrackCuts with null ESD");
364 //_____________________________________________________________________________
365 Float_t AliRsnEvent::GetMultiplicityFromSPD()
368 // Returns event multiplicity computed from SPD.
371 if (!fRef) return -1.0;
373 AliESDEvent *esd = GetRefESD();
375 const AliMultiplicity *mult = esd->GetMultiplicity();
376 Float_t nClusters[6] = {0.0,0.0,0.0,0.0,0.0,0.0};
377 for(Int_t ilay = 0; ilay < 6; ilay++) nClusters[ilay] = (Float_t)mult->GetNumberOfITSClusters(ilay);
378 return AliESDUtils::GetCorrSPD2(nClusters[1], GetVz());
381 AliWarning("Cannot compute SPD multiplicity without a well initialized ESD event");
386 //_____________________________________________________________________________
387 Int_t AliRsnEvent::SelectLeadingParticle
388 (Double_t ptMin, AliRsnCutPID *cutPID)
391 // Searches the collection of all particles with given PID type and charge,
392 // and returns the one with largest momentum, provided that it is greater than 1st argument.
393 // If one specifies AliRsnPID::kUnknown as type or AliRsnDaughter::kNoPID as method,
394 // the check is done over all particles irrespectively of their PID.
395 // If the sign argument is '+' or '-', the check is done over the particles of that charge,
396 // otherwise it is done irrespectively of the charge.
399 Int_t i, nTracks = fRef->GetNumberOfTracks();
401 AliRsnDaughter leading;
404 for (i = 0; i < nTracks; i++) {
405 AliRsnDaughter track = GetDaughter(i);
406 if (cutPID) if (!cutPID->IsSelected(&track)) continue;
407 const AliVParticle *ref = track.GetRef();
408 if (ref->Pt() < ptMin) continue;
409 //double pt = track.P().Perp();
410 //Printf("track %d %g", i, pt);
411 if (!leading.IsOK() || ref->Pt() > ptMin) {
420 //_________________________________________________________________________________________________
421 Double_t AliRsnEvent::GetAverageMomentum(Int_t &count, AliRsnCutPID *cutPID)
424 // Loops on the list of tracks and computes average total momentum.
427 Int_t i, nTracks = fRef->GetNumberOfTracks();
428 Double_t pmean = 0.0;
430 for (i = 0, count = 0; i < nTracks; i++) {
431 AliRsnDaughter track = GetDaughter(i);
432 if (cutPID) if (!cutPID->IsSelected(&track)) continue;
433 pmean += track.Prec().Mag();
437 if (count > 0) pmean /= (Double_t)count;
443 //_____________________________________________________________________________
444 Bool_t AliRsnEvent::GetAngleDistr
445 (Double_t &angleMean, Double_t &angleRMS, AliRsnDaughter *leading)
448 // Takes the leading particle and computes the mean and RMS
449 // of the distribution of directions of all other tracks
450 // with respect to the direction of leading particle.
453 if (!leading) return kFALSE;
454 if (!leading->IsOK()) return kFALSE;
456 Int_t i, count, nTracks = fRef->GetNumberOfTracks();
457 Double_t angle, angle2Mean = 0.0;
459 angleMean = angle2Mean = 0.0;
461 for (i = 0, count = 0; i < nTracks; i++) {
462 AliRsnDaughter trk = GetDaughter(i);
463 if (trk.GetID() == leading->GetID()) continue;
465 angle = leading->Prec().Angle(trk.Prec().Vect());
468 angle2Mean += angle * angle;
472 if (!count) return kFALSE;
474 angleMean /= (Double_t)count;
475 angle2Mean /= (Double_t)count;
476 angleRMS = TMath::Sqrt(angle2Mean - angleMean * angleMean);
481 //_____________________________________________________________________________
482 Bool_t AliRsnEvent::SetDaughterESDtrack(AliRsnDaughter &out, Int_t i)
485 // Setup the first argument to the track identified by the index.
486 // When available, adds the MC information and references.
488 // Version #1: ESD tracks
491 // check 1: index in good range
492 if (i < 0 || i >= fRef->GetNumberOfTracks()) {
497 // check 2: not NULL object
498 AliVTrack *track = (AliVTrack*)fRef->GetTrack(i);
504 // assign references of reconstructed track
505 Int_t label = TMath::Abs(track->GetLabel());
510 // assign MC info, if available
511 return SetMCInfoESD(out);
514 //_____________________________________________________________________________
515 Bool_t AliRsnEvent::SetDaughterAODtrack(AliRsnDaughter &out, Int_t i)
518 // Setup the first argument to the track identified by the index.
519 // When available, adds the MC information and references.
521 // Version #2: AOD tracks
524 // check 1: index in good range
525 if (i < 0 || i >= fRef->GetNumberOfTracks()) {
530 // check 2: not NULL object
531 AliVTrack *track = (AliVTrack*)fRef->GetTrack(i);
537 // assign references of reconstructed track
538 Int_t label = TMath::Abs(track->GetLabel());
543 // assign MC info, if available
544 return SetMCInfoAOD(out);
547 //_____________________________________________________________________________
548 Bool_t AliRsnEvent::SetDaughterESDv0(AliRsnDaughter &out, Int_t i)
551 // Setup the first argument to the track identified by the index.
552 // When available, adds the MC information and references.
554 // Version #3: ESD v0
557 // check 1: index in good range
558 if (i > fRef->GetNumberOfV0s()) {
563 // check 2: not NULL object
564 AliESDEvent *ev = GetRefESD();
565 AliESDv0 *v0 = ev->GetV0(i);
571 // assign references of reconstructed track
576 // this time, assigning label is not trivial,
577 // it is done only if MC is present and both
578 // daughters come from a true particle
579 AliMCEvent *mc = GetRefMCESD();
580 AliESDtrack *tp = ev->GetTrack(v0->GetPindex());
581 AliESDtrack *tn = ev->GetTrack(v0->GetNindex());
582 if (mc && tp && tn) {
583 Int_t lp = TMath::Abs(tp->GetLabel());
584 Int_t ln = TMath::Abs(tn->GetLabel());
585 TParticle *pp = mc->Stack()->Particle(lp);
586 TParticle *pn = mc->Stack()->Particle(ln);
587 // if their first mothers are the same, the V0 is true
588 // otherwise no label can be assigned
589 if (pp->GetFirstMother() == pn->GetFirstMother() && pp->GetFirstMother() >= 0) out.SetLabel(pp->GetFirstMother());
592 // assign MC info, if available
593 return SetMCInfoESD(out);
596 //_____________________________________________________________________________
597 Bool_t AliRsnEvent::SetDaughterAODv0(AliRsnDaughter &out, Int_t i)
600 // Setup the first argument to the track identified by the index.
601 // When available, adds the MC information and references.
603 // Version #4: AOD v0
606 // check 1: index in good range
607 if (i > fRef->GetNumberOfV0s()) {
612 // check 2: not NULL object
613 AliAODEvent *ev = GetRefAOD();
614 AliAODv0 *v0 = ev->GetV0(i);
620 TClonesArray *mcArray = (TClonesArray*)ev->GetList()->FindObject(AliAODMCParticle::StdBranchName());
626 // assign references of reconstructed track
631 // retrieve the owner vertex and its daughters
632 AliAODTrack *tp = (AliAODTrack*)v0->GetDaughter(0);
633 AliAODTrack *tn = (AliAODTrack*)v0->GetDaughter(1);
634 if (mcArray && tp && tn) {
635 Int_t lp = TMath::Abs(tp->GetLabel());
636 Int_t ln = TMath::Abs(tn->GetLabel());
637 // loop on array to find MC daughters
638 AliAODMCParticle *pp = 0x0, *pn = 0x0;
639 TObjArrayIter next(mcArray);
640 AliAODMCParticle *part = 0x0;
641 while ((part = (AliAODMCParticle*)next())) {
642 if (TMath::Abs(part->GetLabel()) == lp) pp = part;
643 if (TMath::Abs(part->GetLabel()) == ln) pn = part;
645 // assign a MC reference and a label only to true V0s
647 if (pp->GetMother() == pn->GetMother() && pp->GetMother() >= 0) out.SetLabel(pp->GetMother());
650 // assign MC info, if available
651 return SetMCInfoAOD(out);
654 //_____________________________________________________________________________
655 Bool_t AliRsnEvent::SetDaughterESDcascade(AliRsnDaughter &out, Int_t i)
658 // Setup the first argument to the track identified by the index.
659 // When available, adds the MC information and references.
661 // Version #3: ESD cascade
664 // check 1: index in good range
665 if (i > fRef->GetNumberOfCascades()) {
670 // check 2: not NULL object
671 AliESDEvent *ev = GetRefESD();
672 AliESDcascade *casc = ev->GetCascade(i);
678 // assign references of reconstructed track
686 //_____________________________________________________________________________
687 Bool_t AliRsnEvent::SetDaughterAODcascade(AliRsnDaughter &out, Int_t i)
690 // Setup the first argument to the track identified by the index.
691 // When available, adds the MC information and references.
693 // Version #4: AOD cascade
696 // check 1: index in good range
697 if (i > fRef->GetNumberOfCascades()) {
702 // check 2: not NULL object
703 AliAODEvent *ev = GetRefAOD();
704 AliAODv0 *casc = ev->GetCascade(i);
710 // assign references of reconstructed track
718 //_____________________________________________________________________________
719 Bool_t AliRsnEvent::SetMCInfoESD(AliRsnDaughter &out)
722 // Using the label assigned to the daughter, searches for the MC informations:
727 Int_t label = out.GetLabel();
729 // if no MC reference is available, exit here (successfully)
730 AliMCEvent *mc = GetRefMCESD();
731 if (!mc) return kTRUE;
732 Int_t nMC = mc->GetNumberOfTracks();
734 // debug message for fakes
736 AliDebug(AliLog::kDebug + 1, "Fake object (fake track or false V0)");
740 // assign MC reference, being aware of eventual
741 // overflows in the array (sometimes happened)
743 AliWarning(Form("Stack overflow: track label = %d -- stack maximum = %d", label, nMC));
746 AliMCParticle *mcPart = (AliMCParticle*)mc->GetTrack(label);
748 AliWarning(Form("Stack discontinuity: label %d refers to a NULL object", label));
751 out.SetRefMC(mcPart);
753 // if this is a primary track, exit here (successfully)
754 Int_t imum = mcPart->Particle()->GetFirstMother();
760 // if didn't stop there, search for the mother
762 AliWarning(Form("Stack overflow: track mother label = %d -- stack maximum = %d", label, nMC));
765 AliMCParticle *mcMother = (AliMCParticle*)mc->GetTrack(imum);
767 AliWarning(Form("Stack discontinuity: label mother %d refers to a NULL object", imum));
770 out.SetMotherPDG(TMath::Abs(mcMother->Particle()->GetPdgCode()));
775 //_____________________________________________________________________________
776 Bool_t AliRsnEvent::SetMCInfoAOD(AliRsnDaughter &out)
779 // Using the label assigned to the daughter, searches for the MC informations:
784 Int_t label = out.GetLabel();
786 // debug message for fakes
788 AliDebug(AliLog::kDebug + 1, "Fake object (fake track or false V0)");
792 // if no MC reference is available, exit here (successfully)
793 AliAODEvent *mc = GetRefMCAOD();
794 if (!mc) return kTRUE;
796 // loop on particles using the track label as reference
797 // and then assign also the mother type, if found
798 TClonesArray *mcArray = (TClonesArray*)mc->GetList()->FindObject(AliAODMCParticle::StdBranchName());
799 if (!mcArray) return kFALSE;
800 TObjArrayIter next(mcArray);
801 AliAODMCParticle *part = 0x0;
802 while ((part = (AliAODMCParticle*)next())) {
803 if (TMath::Abs(part->GetLabel()) == label) {
806 Int_t imum = part->GetMother();
807 if (imum >= 0 && imum <= mcArray->GetEntriesFast()) {
808 AliAODMCParticle *mum = (AliAODMCParticle*)mcArray->At(imum);
809 if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
812 AliWarning(Form("Array overflow: track mother label = %d -- stack maximum = %d", imum, mcArray->GetEntriesFast()));
816 // if a MC reference is found, there is no need to go on with the loop