-/**************************************************************************
- * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
- * *
- * Author: The ALICE Off-line Project. *
- * Contributors are mentioned in the code where appropriate. *
- * *
- * Permission to use, copy, modify and distribute this software and its *
- * documentation strictly for non-commercial purposes is hereby granted *
- * without fee, provided that the above copyright notice appears in all *
- * copies and that both the copyright notice and this permission notice *
- * appear in the supporting documentation. The authors make no claims *
- * about the suitability of this software for any purpose. It is *
- * provided "as is" without express or implied warranty. *
- **************************************************************************/
-
-//-------------------------------------------------------------------------
-// Class AliRsnEvent
-// -------------------
-// Simple collection of reconstructed tracks
-// selected from an ESD event
-// to be used for analysis.
-// .........................................
-//
-// author: A. Pulvirenti (email: alberto.pulvirenti@ct.infn.it)
-//-------------------------------------------------------------------------
-
-#include <Riostream.h>
-
-#include <TString.h>
-#include <TObjArray.h>
-#include <TClonesArray.h>
-
-#include "AliRsnDaughter.h"
+//
+// *** Class AliRsnEvent ***
+//
+// A container for a collection of AliRsnDaughter objects from an event.
+// Contains also the primary vertex, useful for some cuts.
+// In order to retrieve easily the tracks which have been identified
+// as a specific type and charge, there is an array of indexes which
+// allows to avoid to loop on all tracks and have only the neede ones.
+//
+// authors: A. Pulvirenti (email: alberto.pulvirenti@ct.infn.it)
+// M. Vala (email: martin.vala@cern.ch)
+//
+
+#include <TArrayF.h>
+
+#include "AliLog.h"
+#include "AliVEvent.h"
+#include "AliMCEvent.h"
+#include "AliStack.h"
+#include "AliGenEventHeader.h"
+#include "AliRsnCutPID.h"
+
#include "AliRsnEvent.h"
ClassImp(AliRsnEvent)
-//--------------------------------------------------------------------------------------------------------
-AliRsnEvent::AliRsnEvent() :
- fPVx(0.0),
- fPVy(0.0),
- fPVz(0.0),
- fMultiplicity(-1),
- fPosNoPID(0x0),
- fNegNoPID(0x0)
+//_____________________________________________________________________________
+AliRsnEvent::AliRsnEvent(AliVEvent *ref, AliMCEvent *refMC) :
+ fRef(ref),
+ fRefMC(refMC),
+ fLeading(-1)
{
//
-// Default constructor
+// Default constructor.
//
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) {
- fPos[i] = NULL;
- fNeg[i] = NULL;
- }
}
-//--------------------------------------------------------------------------------------------------------
+
+//_____________________________________________________________________________
AliRsnEvent::AliRsnEvent(const AliRsnEvent &event) :
- TObject((TObject)event),
- fPVx(event.fPVx),
- fPVy(event.fPVy),
- fPVz(event.fPVz),
- fMultiplicity(event.fMultiplicity),
- fPosNoPID(0x0),
- fNegNoPID(0x0)
+ TObject(event),
+ fRef(event.fRef),
+ fRefMC(event.fRefMC),
+ fLeading(event.fLeading)
{
//
// Copy constructor.
-// Creates new instances of all collections to store a copy of all objects.
//
- // clone tracks collections
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) {
- fPos[i] = 0;
- fNeg[i] = 0;
- if (event.fPos[i]) fPos[i] = (TClonesArray*)event.fPos[i]->Clone();
- if (event.fNeg[i]) fNeg[i] = (TClonesArray*)event.fNeg[i]->Clone();
- }
- fPosNoPID = (TClonesArray*)event.fPosNoPID->Clone();
- fNegNoPID = (TClonesArray*)event.fNegNoPID->Clone();
}
-//--------------------------------------------------------------------------------------------------------
-AliRsnEvent& AliRsnEvent::operator=(const AliRsnEvent &event)
+
+//_____________________________________________________________________________
+AliRsnEvent& AliRsnEvent::operator= (const AliRsnEvent & event)
{
//
-// Assignment operator.
-// Creates new instances of all collections to store a copy of all objects.
+// Works in the same way as the copy constructor.
//
- fPVx = event.fPVx;
- fPVy = event.fPVy;
- fPVz = event.fPVz;
- fMultiplicity = event.fMultiplicity;
-
- // clone tracks collections
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) {
- fPos[i] = 0;
- fNeg[i] = 0;
- if (event.fPos[i]) fPos[i] = (TClonesArray*)event.fPos[i]->Clone();
- if (event.fNeg[i]) fNeg[i] = (TClonesArray*)event.fNeg[i]->Clone();
- }
- fPosNoPID = (TClonesArray*)event.fPosNoPID->Clone();
- fNegNoPID = (TClonesArray*)event.fNegNoPID->Clone();
-
- return (*this);
+
+ (TObject)(*this) = (TObject)event;
+ fRef = event.fRef;
+ fRefMC = event.fRefMC;
+ fLeading = event.fLeading;
+
+ return (*this);
}
-//--------------------------------------------------------------------------------------------------------
-void AliRsnEvent::AddTrack(AliRsnDaughter track)
+
+//_____________________________________________________________________________
+AliRsnEvent::~AliRsnEvent()
{
//
-// Stores a track into the correct array
+// Destructor.
//
- // if sign is zero, track is not stored
- Char_t sign = track.GetSign();
- if (!sign) return;
-
- // if PDG code is assigned, track is stored in the corresponding collection
- // otherwise, it is stored in the array of unidentified particles with that sign
- Int_t index, iarray, pdg = track.GetPDG();
- if (pdg != 0) {
- iarray = PDG2Enum(pdg);
- if (iarray < AliPID::kElectron || iarray > AliPID::kProton) return;
- TClonesArray &array = (sign > 0) ? *fPos[iarray] : *fNeg[iarray];
- index = array.GetEntries();
- new(array[index]) AliRsnDaughter(track);
- }
- else {
- TClonesArray &array = (sign > 0) ? *fPosNoPID : *fNegNoPID;
- index = array.GetEntries();
- new(array[index]) AliRsnDaughter(track);
- }
}
-//--------------------------------------------------------------------------------------------------------
-void AliRsnEvent::Clear(Option_t *option)
+
+//_____________________________________________________________________________
+Bool_t AliRsnEvent::SetDaughter(AliRsnDaughter &out, Int_t i, AliRsnDaughter::ERefType type)
{
//
-// Clears list of tracks and references.
-// If the string "DELETE" is specified, the collection classes
-// are also cleared from heap.
+// Using the second and third arguments, retrieves the i-th object in the
+// appropriate sample (tracks or V0s) and sets the firs reference object
+// in order to point to that.
+// If a MonteCarlo information is provided, sets the useful informations from there,
+// and in case of a V0, sets the 'label' data member only when the two daughters
+// of the V0 point to the same mother.
+// Returns kFALSE whenever the operation fails (out of range, NULL references).
//
- // evaluate option
- TString opt(option);
- Bool_t deleteCollections = opt.Contains("DELETE", TString::kIgnoreCase);
-
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) {
- if (fPos[i]) fPos[i]->Delete();
- if (fNeg[i]) fNeg[i]->Delete();
- if (deleteCollections) {
- delete fPos[i];
- delete fNeg[i];
- fPos[i] = 0;
- fNeg[i] = 0;
- }
- }
- if (fPosNoPID) fPosNoPID->Delete();
- if (fNegNoPID) fNegNoPID->Delete();
- if (deleteCollections) {
- delete fPosNoPID;
- delete fNegNoPID;
- fPosNoPID = 0;
- fNegNoPID = 0;
- }
+
+ Int_t label;
+
+ // retrieve reference particle from reference event
+ // if it is found, by defaul track can be used (good)
+ if (type == AliRsnDaughter::kTrack)
+ {
+ if (i >= fRef->GetNumberOfTracks())
+ {
+ out.SetBad();
+ return kFALSE;
+ }
+ AliVTrack *track = (AliVTrack*)fRef->GetTrack(i);
+ label = TMath::Abs(track->GetLabel());
+ if (!track)
+ {
+ out.SetBad();
+ return kFALSE;
+ }
+ else
+ {
+ out.SetRef(track);
+ out.SetLabel(label);
+ if (fRefMC)
+ {
+ if (label < fRefMC->GetNumberOfTracks())
+ {
+ AliMCParticle *part = (AliMCParticle*)fRefMC->GetTrack(label);
+ out.SetRefMC(part);
+ }
+ }
+ out.SetGood();
+ }
+ }
+ else if (type == AliRsnDaughter::kV0)
+ {
+ if (i > fRef->GetNumberOfV0s())
+ {
+ out.SetBad();
+ return kFALSE;
+ }
+ AliESDv0 *esdV = 0x0;
+ AliAODv0 *aodV = 0x0;
+ Int_t lp, ln;
+ AliVTrack *tp = 0x0, *tn = 0x0;
+ if (IsESD()) esdV = GetRefESD()->GetV0(i);
+ if (IsAOD()) aodV = GetRefAOD()->GetV0(i);
+ if (!esdV && !aodV)
+ {
+ out.SetBad();
+ return kFALSE;
+ }
+ else
+ {
+ if (esdV) out.SetRef(esdV); else out.SetRef(aodV);
+ // retrieve the V0 daughters, which must be done differently with ESD and AOD v0s
+ if (esdV)
+ {
+ // get the 2 daughters of the V0
+ AliESDEvent *ev = dynamic_cast<AliESDEvent*>(fRef);
+ tp = ev->GetTrack(esdV->GetPindex());
+ tn = ev->GetTrack(esdV->GetNindex());
+ }
+ else if (aodV)
+ {
+ // get the 2 daughters of the V0
+ AliAODEvent *ev = dynamic_cast<AliAODEvent*>(fRef);
+ tp = ev->GetTrack(aodV->GetPosID());
+ tn = ev->GetTrack(aodV->GetNegID());
+ }
+
+ // now, if we have a MC, use the two track objects
+ // to retrieve the true particle which generated the V0
+ // using their labels; by default they are a false V0 with label -1
+ label = -1;
+ if (tp && tn && fRefMC)
+ {
+ lp = TMath::Abs(tp->GetLabel());
+ ln = TMath::Abs(tn->GetLabel());
+ // if labels are meaningful, retrieve corresponding particles
+ TParticle *pp = fRefMC->Stack()->Particle(lp);
+ TParticle *pn = fRefMC->Stack()->Particle(ln);
+ // if their first mothers are the same, the V0 is true
+ // otherwise no label can be assigned
+ if (pp->GetFirstMother() == pn->GetFirstMother()) label = pp->GetFirstMother();
+ }
+ out.SetLabel(label);
+ out.SetGood();
+ }
+ }
+
+ // finally, in case we have a MC, searches for the mother, in order to store
+ // its PDG code into the output AliRsnDaughter
+ if (fRefMC)
+ {
+ label = out.GetLabel();
+ AliStack *stack = fRefMC->Stack();
+ if (label >= 0 && label < stack->GetNtrack())
+ {
+ TParticle *part = stack->Particle(label);
+ if (part)
+ {
+ Int_t imum = part->GetFirstMother();
+ if (imum >= 0 && imum <= stack->GetNtrack())
+ {
+ TParticle *mum = stack->Particle(imum);
+ if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
+ }
+ }
+ }
+ }
+
+ return kTRUE;
}
-//--------------------------------------------------------------------------------------------------------
-void AliRsnEvent::ComputeMultiplicity()
+
+//_____________________________________________________________________________
+Bool_t AliRsnEvent::SetDaughterMC(AliRsnDaughter &out, Int_t i)
{
//
-// Computes multiplicity.
+// Using the second argument, retrieves the i-th object in the
+// appropriate sample and sets the firs reference object
+// in order to point to that.
+// If a MonteCarlo information is provided, sets the useful informations from there,
+// and in case of a V0, sets the 'label' data member only when the two daughters
+// of the V0 point to the same mother.
+// Returns kFALSE whenever the operation fails (out of range, NULL references).
//
- fMultiplicity = 0;
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) {
- fMultiplicity += (Int_t)fPos[i]->GetEntries();
- fMultiplicity += (Int_t)fNeg[i]->GetEntries();
- }
- if (fPosNoPID) fMultiplicity += fPosNoPID->GetEntries();
- if (fNegNoPID) fMultiplicity += fNegNoPID->GetEntries();
+
+ if (!fRefMC)
+ {
+ out.SetBad();
+ return kFALSE;
+ }
+
+ if (i >= fRefMC->GetNumberOfTracks())
+ {
+ out.SetBad();
+ return kFALSE;
+ }
+
+ AliMCParticle *track = (AliMCParticle*)fRef->GetTrack(i);
+ if (!track)
+ {
+ out.SetBad();
+ return kFALSE;
+ }
+ else
+ {
+ out.SetRef(track);
+ out.SetRefMC(track);
+ out.SetLabel(i);
+ out.SetGood();
+ }
+
+ AliStack *stack = fRefMC->Stack();
+ TParticle *part = track->Particle();
+ if (part)
+ {
+ Int_t imum = part->GetFirstMother();
+ if (imum >= 0 && imum <= stack->GetNtrack())
+ {
+ TParticle *mum = stack->Particle(imum);
+ if (mum) out.SetMotherPDG(TMath::Abs(mum->GetPdgCode()));
+ }
+ }
+
+ return kTRUE;
}
-//--------------------------------------------------------------------------------------------------------
-TClonesArray* AliRsnEvent::GetTracks(Char_t sign, AliPID::EParticleType type)
+
+//_____________________________________________________________________________
+AliRsnDaughter AliRsnEvent::GetDaughter(Int_t i, AliRsnDaughter::ERefType type)
{
//
-// Returns the particle collection specified in argument
+// Return an AliRsnDaughter taken from this event,
+// with all additional data members well set.
//
- Int_t itype = (Int_t)type;
- if (itype >= 0 && itype < AliPID::kSPECIES) {
- if (sign == '+') return fPos[type]; else return fNeg[type];
- }
- else if (type == AliPID::kUnknown) {
- if (sign == '+') return fPosNoPID; else return fNegNoPID;
- }
- else {
- return NULL;
- }
+
+ AliRsnDaughter out;
+ SetDaughter(out, i, type);
+
+ return out;
}
-//--------------------------------------------------------------------------------------------------------
-void AliRsnEvent::Init()
+
+//_____________________________________________________________________________
+AliRsnDaughter AliRsnEvent::GetDaughterMC(Int_t i)
{
//
-// Action 1: define default values for some data members (including pointers).
-// Action 2: if 'ntracks' > 0 allocates memory to store tracks.
+// Return an AliRsnDaughter taken from this event,
+// with all additional data members well set.
//
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) {
- fPos[i] = new TClonesArray("AliRsnDaughter", 0);
- fNeg[i] = new TClonesArray("AliRsnDaughter", 0);
- fPos[i]->BypassStreamer(kFALSE);
- fNeg[i]->BypassStreamer(kFALSE);
- }
- fPosNoPID = new TClonesArray("AliRsnDaughter", 0);
- fNegNoPID = new TClonesArray("AliRsnDaughter", 0);
- fPosNoPID->BypassStreamer(kFALSE);
- fNegNoPID->BypassStreamer(kFALSE);
+
+ AliRsnDaughter out;
+ SetDaughterMC(out, i);
+
+ return out;
}
-//--------------------------------------------------------------------------------------------------------
-Int_t AliRsnEvent::PDG2Enum(Int_t pdgcode)
+
+//_____________________________________________________________________________
+Int_t AliRsnEvent::GetMultiplicity()
{
//
-// Converts a PDG code into the correct slot in the EParticleType enumeration in AliPID
+// Returns event multiplicity
//
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) {
- if (AliPID::ParticleCode((AliPID::EParticleType)i) == TMath::Abs(pdgcode)) {
- return i;
- }
- }
-
- return -1;
+ AliDebug(AliLog::kDebug+2,"<-");
+ if (!fRef) return 0;
+ AliDebug(AliLog::kDebug+2,"->");
+ return fRef->GetNumberOfTracks();
}
-//--------------------------------------------------------------------------------------------------------
-void AliRsnEvent::PrintTracks()
+
+//_____________________________________________________________________________
+Double_t AliRsnEvent::GetVz()
{
//
-// Print data for particles stored in this event
+// Return Z coord of primary vertex
//
- cout << endl;
-
- AliRsnDaughter *track = 0;
-
- Int_t type;
- for (type = 0; type < AliPID::kSPECIES; type++) {
- TObjArrayIter iterPos(fPos[type]);
- cout << "Positive " << AliPID::ParticleName(type) << "s" << endl;
- if (!fPos[type]) cout << "NOT INITIALIZED" << endl;
- while ( (track = (AliRsnDaughter*)iterPos.Next()) ) {
- cout << "Index, Sign, PDG = ";
- cout << track->GetIndex() << " ";
- cout << (Int_t)track->GetSign() << " ";
- cout << track->GetPDG() << endl;
- }
- TObjArrayIter iterNeg(fNeg[type]);
- cout << "Negative " << AliPID::ParticleName(type) << "s" << endl;
- if (!fNeg[type]) cout << "NOT INITIALIZED" << endl;
- while ( (track = (AliRsnDaughter*)iterNeg.Next()) ) {
- cout << "Index, Sign, PDG = ";
- cout << track->GetIndex() << " ";
- cout << (Int_t)track->GetSign() << " ";
- cout << track->GetPDG() << endl;
- }
- }
+
+ AliDebug(AliLog::kDebug+2,"<-");
+ return fRef->GetPrimaryVertex()->GetZ();
+ AliDebug(AliLog::kDebug+2,"->");
+}
+
+//_____________________________________________________________________________
+Int_t AliRsnEvent::SelectLeadingParticle
+(Double_t ptMin, AliRsnCutPID *cutPID)
+{
+//
+// Searches the collection of all particles with given PID type and charge,
+// and returns the one with largest momentum, provided that it is greater than 1st argument.
+// If one specifies AliRsnPID::kUnknown as type or AliRsnDaughter::kNoPID as method,
+// the check is done over all particles irrespectively of their PID.
+// If the sign argument is '+' or '-', the check is done over the particles of that charge,
+// otherwise it is done irrespectively of the charge.
+//
+
+ Int_t i, nTracks = fRef->GetNumberOfTracks();
+ fLeading = -1;
+ AliRsnDaughter leading;
+ leading.SetBad();
+
+ for (i = 0; i < nTracks; i++) {
+ AliRsnDaughter track = GetDaughter(i);
+ if (cutPID) if (!cutPID->IsSelected(&track)) continue;
+ if (track.P().Perp() < ptMin) continue;
+ if (!leading.IsOK() || track.P().Perp() > leading.P().Perp())
+ {
+ fLeading = i;
+ leading = track;
+ }
+ }
+
+ return fLeading;
+}
+
+//_________________________________________________________________________________________________
+Double_t AliRsnEvent::GetAverageMomentum(Int_t &count, AliRsnCutPID *cutPID)
+{
+//
+// Loops on the list of tracks and computes average total momentum.
+//
+
+ Int_t i, nTracks = fRef->GetNumberOfTracks();
+ Double_t pmean = 0.0;
+
+ for (i = 0, count = 0; i < nTracks; i++) {
+ AliRsnDaughter track = GetDaughter(i);
+ if (cutPID) if (!cutPID->IsSelected(&track)) continue;
+ pmean += track.P().Mag();
+ count++;
+ }
+
+ if (count > 0) pmean /= (Double_t)count;
+ else pmean = 0.0;
+
+ return pmean;
+}
+
+//_____________________________________________________________________________
+Bool_t AliRsnEvent::GetAngleDistr
+(Double_t &angleMean, Double_t &angleRMS, AliRsnDaughter leading)
+{
+//
+// Takes the leading particle and computes the mean and RMS
+// of the distribution of directions of all other tracks
+// with respect to the direction of leading particle.
+//
+
+ if (!leading.IsOK()) return kFALSE;
+
+ Int_t i, count, nTracks = fRef->GetNumberOfTracks();
+ Double_t angle, angle2Mean = 0.0;
+
+ angleMean = angle2Mean = 0.0;
+
+ for (i = 0, count = 0; i < nTracks; i++) {
+ AliRsnDaughter trk = GetDaughter(i);
+ if (trk.GetID() == leading.GetID()) continue;
+
+ angle = leading.P().Angle(trk.P().Vect());
+
+ angleMean += angle;
+ angle2Mean += angle * angle;
+ count++;
+ }
+
+ if (!count) return kFALSE;
+
+ angleMean /= (Double_t)count;
+ angle2Mean /= (Double_t)count;
+ angleRMS = TMath::Sqrt(angle2Mean - angleMean * angleMean);
+
+ return kTRUE;
}
-//--------------------------------------------------------------------------------------------------------