//
-// Class AliRsnDaughter
-//
-// Interface to candidate daughters of a resonance (tracks).
-// Points to the source of information, which is generally an AliVParticle-derived object
-// and contains few internal data-members to store "on fly" some important information
-// for the computations required during resonance analysis.
-// ---
-// Since the package revision, this object is not supposed to be stacked in memory
-// but created "on fly" during analysis and used just for computations, as an interface.
-//
-// authors: A. Pulvirenti (alberto.pulvirenti@ct.infn.it)
-// M. Vala (martin.vala@cern.ch)
+// This class works as generic interface to each candidate resonance daughter.
+// Its main purpose is to provide a unique reference which includes all the
+// facilities available in the AliVParticle generic base class, plus all info
+// which could be needed during analysis, which are not in AliVParticle but
+// need to be accessed from ESD or AOD objects, usually in different ways.
+// When MC is available, AliRsnDaughter matches each reconstructed object with
+// its corresponding MC particle.
+//
+// Currently, this interface can point to all kinds of single-particle object
+// which one can have in the reconstructed event: charged tracks, V0s and
+// cascades. It is care of the user to treat each of them in the correct way,
+// regarding cuts, functions to be computed, etc.
+//
+// authors: A. Pulvirenti (alberto.pulvirenti@ct.infn.it)
+// M. Vala (martin.vala@cern.ch)
//
-#include <Riostream.h>
#include <TParticle.h>
+#include <TDatabasePDG.h>
-#include "AliStack.h"
-#include "AliESDtrack.h"
-#include "AliAODEvent.h"
-#include "AliAODVertex.h"
-#include "AliAODTrack.h"
-
-#include "AliRsnPIDDefESD.h"
#include "AliRsnDaughter.h"
ClassImp(AliRsnDaughter)
-AliRsnDaughter::EPIDMethod AliRsnDaughter::fgPIDMethod = AliRsnDaughter::kRealistic;
-
-//_____________________________________________________________________________
-AliRsnDaughter::AliRsnDaughter(AliVParticle *ref, TParticle *refMC) :
- fOK((ref != 0)),
- fKinkIndex(0),
- fParticle(refMC),
- fMotherPDG(0),
- fStatus(0),
- fPairIndex(0),
- fDr(0.0),
- fDz(0.0),
- fReqPID(AliPID::kUnknown),
- fRef(ref)
-{
-//
-// Default constructor.
-//
-}
-
//_____________________________________________________________________________
AliRsnDaughter::AliRsnDaughter(const AliRsnDaughter ©) :
- TObject(copy),
- fOK(copy.fOK),
- fKinkIndex(copy.fKinkIndex),
- fParticle(copy.fParticle),
- fMotherPDG(copy.fMotherPDG),
- fStatus(copy.fStatus),
- fPairIndex(copy.fPairIndex),
- fDr(copy.fDr),
- fDz(copy.fDz),
- fReqPID(copy.fReqPID),
- fRef(copy.fRef)
+ TObject(copy),
+ fOK(copy.fOK),
+ fLabel(copy.fLabel),
+ fMotherPDG(copy.fMotherPDG),
+ fRsnID(copy.fRsnID),
+ fPrec(copy.fPrec),
+ fPsim(copy.fPsim),
+ fRef(copy.fRef),
+ fRefMC(copy.fRefMC),
+ fOwnerEvent(copy.fOwnerEvent)
{
//
// Copy constructor.
-// Pointers are NOT duplicated.
+// Pointers are NOT duplicated, since they don't come from a 'new'
+// statement, but from just referencing something in the data source.
//
}
{
//
// Assignment operator.
+// Pointers are NOT duplicated, since they don't come from a 'new'
+// statement, but from just referencing something in the data source.
//
- (TObject)(*this) = (TObject)copy;
-
- fOK = copy.fOK;
- fKinkIndex = copy.fKinkIndex;
- fParticle = copy.fParticle;
- fMotherPDG = copy.fMotherPDG;
- fStatus = copy.fStatus;
- fPairIndex = copy.fPairIndex;
- fDr = copy.fDr;
- fDz = copy.fDz;
-
- fReqPID = copy.fReqPID;
+ fOK = copy.fOK;
+ fLabel = copy.fLabel;
+ fMotherPDG = copy.fMotherPDG;
+ fRsnID = copy.fRsnID;
+ fPsim = copy.fPsim;
+ fPrec = copy.fPrec;
+ fRef = copy.fRef;
+ fRefMC = copy.fRefMC;
+ fOwnerEvent = copy.fOwnerEvent;
- fRef = copy.fRef;
-
- return (*this);
+ return (*this);
}
//_____________________________________________________________________________
-AliRsnDaughter::~AliRsnDaughter()
-{
-//
-// Destructor.
-// Since pointers do not allocate new objects, nothing is done.
-//
-}
-
-//_____________________________________________________________________________
-void AliRsnDaughter::RotateP
-(Double_t angle, Double_t &x, Double_t &y, Bool_t isDegrees) const
+void AliRsnDaughter::Reset()
{
//
-// Rotate the transverse momentum by an angle (in DEGREES)
-// around Z axis (does not change the Z component).
-// Rotated values are stored in the two arguments passed by reference.
+// Reset this track to meaningless values and to a 'bad' status.
+// After this has been done, this object should not be used
+// for analysis unless initialized properly.
//
- if (isDegrees) angle *= TMath::DegToRad();
-
- Double_t s = TMath::Sin(angle);
- Double_t c = TMath::Cos(angle);
+ fOK = kFALSE;
+ fLabel = -1;
+ fMotherPDG = 0;
+ fRsnID = -1;
+
+ fPsim.SetXYZT(0.0, 0.0, 0.0, 0.0);
+ fPrec.SetXYZT(0.0, 0.0, 0.0, 0.0);
- x = c*Px() - s*Py();
- y = s*Px() + c*Py();
+ fRef = fRefMC = 0x0;
+ fOwnerEvent = 0x0;
}
//_____________________________________________________________________________
-Double_t AliRsnDaughter::AngleTo(AliRsnDaughter d, Bool_t outInDegrees)
+Int_t AliRsnDaughter::GetPDG()
{
//
-// Compute angle between the vector momentum of this
-// and the one of argument.
+// Return the PDG code of the particle from MC ref (if any).
+// If argument is kTRUE, returns its absolute value.
//
- Double_t arg, dot, ptot2 = P2() * d.P2();
-
- if (ptot2 <= 0) {
- return 0.0;
- } else {
- dot = Px()*d.Px() + Py()*d.Py() + Pz()*d.Pz();
- arg = dot / TMath::Sqrt(ptot2);
- if (arg > 1.0) arg = 1.0;
- if (arg < -1.0) arg = -1.0;
- if (outInDegrees) return TMath::ACos(arg) * TMath::RadToDeg();
- else return TMath::ACos(arg);
- }
+ if (Match(fRefMC, AliMCParticle::Class()))
+ return ((AliMCParticle*)fRefMC)->Particle()->GetPdgCode();
+ else if (Match(fRefMC, AliAODMCParticle::Class()))
+ return ((AliAODMCParticle*)fRefMC)->GetPdgCode();
+ else {
+ AliWarning("Cannot retrieve PDG");
+ return 0;
+ }
}
//_____________________________________________________________________________
-Int_t AliRsnDaughter::GetID() const
+Int_t AliRsnDaughter::GetID()
{
//
// Return reference index, using the "GetID" method
// of the possible source object.
+// When this method is unsuccessful (e.g.: V0s), return the label.
//
- AliESDtrack *esd = dynamic_cast<AliESDtrack*>(fRef);
- if (esd) return esd->GetID();
+ // ESD tracks
+ AliESDtrack *esd = Ref2ESDtrack();
+ if (esd) return esd->GetID();
- AliAODTrack *aod = dynamic_cast<AliAODTrack*>(fRef);
- if (aod) return aod->GetID();
+ // AOD tracks
+ AliAODTrack *aod = Ref2AODtrack();
+ if (aod) return aod->GetID();
- return GetLabel();
+ // whatever else
+ return GetLabel();
}
//_____________________________________________________________________________
-AliPID::EParticleType AliRsnDaughter::RealisticPID() const
+Int_t AliRsnDaughter::GetMother()
{
//
-// Return the "realistic" PID of this track,
-// i.e. the particle species to which corresponds the largest PID probability.
+// Return index of the first mother of the MC reference, if any.
+// Otherwise, returns -1 (the same as for primary tracks)
//
- AliPID::EParticleType pid = AliPID::kElectron;
- Double_t prob = fPID[0];
-
- Int_t i;
- for (i = 1; i < AliPID::kSPECIES; i++) {
- if (fPID[i] > prob) {
- prob = fPID[i];
- pid = (AliPID::EParticleType)i;
- }
- }
+ if (!fRefMC) return -1;
- return pid;
+ if (fRefMC->InheritsFrom(AliMCParticle::Class())) {
+ AliMCParticle *mc = (AliMCParticle*)fRefMC;
+ return mc->Particle()->GetFirstMother();
+ } else if (fRefMC->InheritsFrom(AliAODMCParticle::Class())) {
+ AliAODMCParticle *mc = (AliAODMCParticle*)fRefMC;
+ return mc->GetMother();
+ }
+ else
+ return -1;
}
+
+
-//_____________________________________________________________________________
-AliPID::EParticleType AliRsnDaughter::PerfectPID() const
+//______________________________________________________________________________
+void AliRsnDaughter::Print(Option_t *opt) const
{
//
-// Return the "perfect" PID of this track,
-// reading it from the MC information, if available.
+// Override of TObject::Print()
//
- if (!fParticle) return AliPID::kUnknown;
-
- Int_t absPDG = TMath::Abs(fParticle->GetPdgCode());
- switch (absPDG) {
- case 11:
- return AliPID::kElectron;
- case 13:
- return AliPID::kMuon;
- case 211:
- return AliPID::kPion;
- case 321:
- return AliPID::kKaon;
- case 2212:
- return AliPID::kProton;
- default:
- AliDebug(2, Form("PDG code = %d not recognized. Return 'AliPID::kUnknown'", absPDG));
- return AliPID::kUnknown;
- }
+ AliInfo("=== DAUGHTER INFO ======================================================================");
+ AliInfo(Form(" (sim) px,py,pz = %6.2f %6.2f %6.2f", fPsim.X(), fPsim.Y(), fPsim.Z()));
+ AliInfo(Form(" (rec) px,py,pz = %6.2f %6.2f %6.2f", fPrec.X(), fPrec.Y(), fPrec.Z()));
+ AliInfo(Form(" OK, RsnID, Label, MotherPDG = %s, %5d, %5d, %4d", (fOK ? "true " : "false"), fRsnID, fLabel, fMotherPDG));
+ AliInfo("========================================================================================");
}
-//_____________________________________________________________________________
-AliPID::EParticleType AliRsnDaughter::PIDType(Double_t &prob) const
+//______________________________________________________________________________
+const char* AliRsnDaughter::SpeciesName(ESpecies species)
{
//
-// Return the PID type according to the selected method
-// in the argument passed by reference, the probability is stored.
-// It will be realistic for realistic PID and 1 for perfect PID.
-//
-
- AliPID::EParticleType pid = AssignedPID();
-
- prob = 1.0;
- if (fgPIDMethod == kRealistic) prob = fPID[(Int_t)pid];
-
- return pid;
+// Return a string with the short name of the particle
+//
+
+ switch (species) {
+ case kElectron: return "E";
+ case kMuon: return "Mu";
+ case kPion: return "Pi";
+ case kKaon: return "K";
+ case kProton: return "P";
+ case kKaon0: return "K0s";
+ case kLambda: return "Lambda";
+ case kXi: return "Xi";
+ case kOmega: return "Omega";
+ default: return "Undef";
+ }
}
-//_____________________________________________________________________________
-AliPID::EParticleType AliRsnDaughter::AssignedPID() const
+//______________________________________________________________________________
+Int_t AliRsnDaughter::SpeciesPDG(ESpecies species)
{
//
-// Return the PID type according to the selected method
-// in the argument passed by reference, the probability is stored.
-// It will be realistic for realistic PID and 1 for perfect PID.
-//
-
- switch (fgPIDMethod) {
- case kNoPID:
- return AliPID::kUnknown;
- case kPerfect:
- return PerfectPID();
- case kRealistic:
- return RealisticPID();
- default:
- AliWarning("PID method not properly set. Returning realistic PID");
- return RealisticPID();
- }
+// Return the PDG code of a particle species (abs value)
+//
+
+ switch (species) {
+ case kElectron: return 11;
+ case kMuon: return 13;
+ case kPion: return 211;
+ case kKaon: return 321;
+ case kProton: return 2212;
+ case kKaon0: return 310;
+ case kLambda: return 3122;
+ case kXi: return 3312;
+ case kOmega: return 3334;
+ default: return 0;
+ }
}
-//_____________________________________________________________________________
-Bool_t AliRsnDaughter::CombineWithPriors(const Double_t *priors, AliRsnPIDDefESD *pidDef)
+//______________________________________________________________________________
+Double_t AliRsnDaughter::SpeciesMass(ESpecies species)
{
//
-// Combine current PID weights (assumed to be them) with prior probs
+// Return the mass of a particle species
//
- Int_t i;
- Double_t sum = 0.0;
-
- // get PID weights according to definition
- // if the reference is not ESD or the pidDef is null
- // of it is not null but is requires the ESD pid,
- // the standard PID value is used, otherwise
- if (pidDef && GetRefESD()) {
- pidDef->ComputeWeights(GetRefESD(), fPID);
- } else {
- if (fRef->PID())
- for (i = 0; i < AliPID::kSPECIES; i++) fPID[i] = fRef->PID()[i];
- else if (fParticle) {
- // if the PID() returns 0x0, this is a MC particle
- // and we set the weight corresponding to its species to 1
- // and the others to zero
- for (i = 0; i < AliPID::kSPECIES; i++) fPID[i] = 0.0;
- i = (Int_t)AliRsnDaughter::InternalType(TMath::Abs(fParticle->GetPdgCode()));
- fPID[i] = 1.0;
- }
- }
-
- // multiply weights and priors
- for (i = 0; i < AliPID::kSPECIES; i++) {
- fPID[i] *= priors[i];
- sum += fPID[i];
- }
- if (sum <= 0.0) {
- if (sum < 0.0) AliError(Form("Sum of weights = %f < 0", sum));
- return kFALSE;
- }
-
- // normalize
- for (i = 0; i < AliPID::kSPECIES; i++) fPID[i] /= sum;
-
- return kTRUE;
+ TDatabasePDG *db = TDatabasePDG::Instance();
+ TParticlePDG *part = 0x0;
+
+ Int_t pdg = SpeciesPDG(species);
+ if (pdg) {
+ part = db->GetParticle(pdg);
+ return part->Mass();
+ }
+ else
+ return 0.0;
}
-//_____________________________________________________________________________
-void AliRsnDaughter::FindMotherPDG(AliStack *const stack)
+//______________________________________________________________________________
+EPARTYPE AliRsnDaughter::ToAliPID(ESpecies species)
{
//
-// Searches the stack to find the mother and retrieve its PDG code.
+// Convert an enum element from this object
+// into the enumeration of AliPID.
+// If no match are cound 'kUnknown' is returned.
//
- if (!stack || !fParticle) return;
-
- const Int_t mLabel = fParticle->GetFirstMother();
- if (mLabel < 0) {
- fMotherPDG = 0;
- } else {
- TParticle *mum = stack->Particle(mLabel);
- if (mum) fMotherPDG = mum->GetPdgCode();
- else fMotherPDG = 0;
- }
+ switch (species) {
+ case kElectron: return AliPID::kElectron;
+ case kMuon: return AliPID::kMuon;
+ case kPion: return AliPID::kPion;
+ case kKaon: return AliPID::kKaon;
+ case kProton: return AliPID::kProton;
+ case kKaon0: return AliPID::kKaon0;
+ default: return AliPID::kUnknown;
+ }
}
-//_____________________________________________________________________________
-Double_t AliRsnDaughter::GetMCEnergy(Double_t mass)
-{
-//
-// Uses the argument to compute 4-momentum energy
-//
-
- if (!fParticle) return 0.0;
-
- Double_t p2 = fParticle->Px()*fParticle->Px();
- p2 += fParticle->Py()*fParticle->Py();
- p2 += fParticle->Pz()*fParticle->Pz();
-
- return TMath::Sqrt(mass*mass + p2);
-}
-
-//_____________________________________________________________________________
-void AliRsnDaughter::FindKinkIndex(const AliESDtrack *esdTrack)
-{
-//
-// Assign kink index from an ESD track
-//
-
- Int_t i, ik[3];
- for (i = 0; i < 3; i++) ik[i] = esdTrack->GetKinkIndex(i);
-
- if (ik[0] < 0 || ik[1] < 0 || ik[2] < 0) {
- SetKinkMother();
- } else if (ik[0] > 0 || ik[1] > 0 || ik[2] > 0) {
- SetKinkDaughter();
- } else SetNoKink();
-}
-
-//_____________________________________________________________________________
-void AliRsnDaughter::FindKinkIndex(AliAODEvent *const event)
-{
-//
-// Assign kink index from an AOD event
-//
-
- Int_t iv, id, nD, nV = event->GetNumberOfVertices();
- for (iv = 0; iv < nV; iv++) {
- AliAODVertex *v = event->GetVertex(iv);
- AliAODVertex::AODVtx_t type = (AliAODVertex::AODVtx_t)v->GetType();
- if (type != AliAODVertex::kKink) continue;
- AliAODTrack *mother = (AliAODTrack*)v->GetParent();
- if (mother == (AliAODTrack*)fRef) {
- SetKinkMother();
- return;
- } else {
- nD = v->GetNDaughters();
- for (id = 0; id < nD; id++) {
- AliAODTrack *son = (AliAODTrack*)v->GetDaughter(id);
- if (son == (AliAODTrack*)fRef) {
- SetKinkDaughter();
- return;
- }
- }
- }
- }
-
- SetNoKink();
-}
-
-//_____________________________________________________________________________
-void AliRsnDaughter::Reset()
-{
-//
-// Reset this track to meaningless values
-//
-
- fOK = kFALSE;
- fKinkIndex = 0;
- fParticle = 0x0;
- fMotherPDG = 0;
- fStatus = 0;
- fRef = 0x0;
-}
-
-//_____________________________________________________________________________
-void AliRsnDaughter::Print(Option_t * const option) const
-{
-//
-// Prints the values of data members, using the options:
-// - P --> momentum
-// - V --> DCA vertex
-// - C --> electric charge
-// - F --> flags
-// - I --> identification (PID, probability and mass)
-// - W --> PID weights
-// - M --> Montecarlo
-// - L --> index & label
-// - A --> angles
-// - ALL --> All oprions switched on
-//
-// Index and label are printed by default.
-//
-
- TString opt(option);
- opt.ToUpper();
-
- if (opt.Contains("L") || opt.Contains("ALL")) {
- cout << ".......Index : " << GetID() << endl;
- cout << ".......Label : " << GetLabel() << endl;
- }
- if (opt.Contains("P") || opt.Contains("ALL")) {
- cout << ".......Px, Py, Pz, Pt : " << Px() << ' ' << Py() << ' ' << Pz() << ' ' << Pt() << endl;
- }
- if (opt.Contains("A") || opt.Contains("ALL")) {
- cout << ".......Phi, Theta : " << Phi() << ' ' << Theta() << endl;
- }
- if (opt.Contains("V") || opt.Contains("ALL")) {
- cout << ".......Vx, Vy, Vz : " << Xv() << ' ' << Yv() << ' ' << Zv() << endl;
- }
- if (opt.Contains("I") || opt.Contains("ALL")) {
- AliPID::EParticleType type;
- Double_t prob;
- type = PIDType(prob);
- cout << ".......PID & prob : " << AliPID::ParticleName(type) << ' ' << prob << endl;
- }
- if (opt.Contains("C") || opt.Contains("ALL")) {
- cout << ".......Charge : " << Charge() << endl;
- }
- if (opt.Contains("F") || opt.Contains("ALL")) {
- cout << ".......Flags : " << fStatus << endl;
- }
- if (opt.Contains("W") || opt.Contains("ALL")) {
- cout << ".......Weights : ";
- Int_t i;
- for (i = 0; i < AliPID::kSPECIES; i++) cout << fPID[i] << ' ';
- cout << endl;
- }
- if (opt.Contains("M") || opt.Contains("ALL")) {
- if (fParticle) {
- cout << ".......PDG code : " << fParticle->GetPdgCode() << endl;
- cout << ".......Mother (label) : " << fParticle->GetFirstMother() << endl;
- cout << ".......Mother (PDG code): " << fMotherPDG << endl;
- } else {
- cout << ".......MC info not present" << endl;
- }
- }
-}
-
-//_____________________________________________________________________________
-AliPID::EParticleType AliRsnDaughter::InternalType(Int_t pdg)
-{
-//
-// Return the internal enum value corresponding to the PDG
-// code passed as argument, if possible.
-// Otherwise, returns 'AliPID::kSPECIES' by default.
-//
-
- AliPID::EParticleType value;
- Int_t absPDG = TMath::Abs(pdg);
-
- switch (absPDG) {
- case 11:
- value = AliPID::kElectron;
- break;
- case 13:
- value = AliPID::kMuon;
- break;
- case 211:
- value = AliPID::kPion;
- break;
- case 321:
- value = AliPID::kKaon;
- break;
- case 2212:
- value = AliPID::kProton;
- break;
- default:
- value = AliPID::kUnknown;
- }
- return value;
-}
-
-//_____________________________________________________________________________
-const char* AliRsnDaughter::MethodName(EPIDMethod method)
+//______________________________________________________________________________
+AliRsnDaughter::ESpecies AliRsnDaughter::FromAliPID(EPARTYPE pid)
{
//
-// Returns a string with the method name
+// Convert an enum element from AliPID
+// into the enumeration of this object.
+// If no match are cound 'kUnknown' is returned.
//
- switch (method)
- {
- case kNoPID:
- return "No PID";
- case kRealistic:
- return "Realistic";
- case kPerfect:
- return "Perfect";
- default:
- return "Unknown";
- }
+ switch (pid) {
+ case AliPID::kElectron: return kElectron;
+ case AliPID::kMuon: return kMuon;
+ case AliPID::kPion: return kPion;
+ case AliPID::kKaon: return kKaon;
+ case AliPID::kProton: return kProton;
+ case AliPID::kKaon0: return kKaon0;
+ default: return kUnknown;
+ }
}