1 /**************************************************************************
2 * Copyright(c) 1998-2007, 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 **************************************************************************/
18 //-------------------------------------------------------------------------
19 // AOD track implementation of AliVTrack
20 // Author: Markus Oldenburg, CERN
21 // Markus.Oldenburg@cern.ch
22 //-------------------------------------------------------------------------
26 #include "AliExternalTrackParam.h"
27 #include "AliVVertex.h"
28 #include "AliAODTrack.h"
32 //______________________________________________________________________________
33 AliAODTrack::AliAODTrack() :
37 fChi2MatchTrigger(0.),
40 fITSMuonClusterMap(0),
49 fCaloIndex(kEMCALNoMatch),
53 fTrackPhiOnEMCal(-999),
54 fTrackEtaOnEMCal(-999)
56 // default constructor
59 SetPosition((Float_t*)NULL);
60 SetXYAtDCA(-999., -999.);
61 SetPxPyPzAtDCA(-999., -999., -999.);
62 SetPID((Float_t*)NULL);
65 //______________________________________________________________________________
66 AliAODTrack::AliAODTrack(Short_t id,
72 Double_t covMatrix[21],
76 AliAODVertex *prodVertex,
78 Bool_t usedForPrimVtxFit,
84 fChi2perNDF(chi2perNDF),
85 fChi2MatchTrigger(0.),
88 fITSMuonClusterMap(0),
89 fFilterMap(selectInfo),
97 fCaloIndex(kEMCALNoMatch),
100 fProdVertex(prodVertex),
101 fTrackPhiOnEMCal(-999),
102 fTrackEtaOnEMCal(-999)
107 SetPosition(x, isDCA);
108 SetXYAtDCA(-999., -999.);
109 SetPxPyPzAtDCA(-999., -999., -999.);
110 SetUsedForVtxFit(usedForVtxFit);
111 SetUsedForPrimVtxFit(usedForPrimVtxFit);
112 if(covMatrix) SetCovMatrix(covMatrix);
114 SetITSClusterMap(itsClusMap);
117 //______________________________________________________________________________
118 AliAODTrack::AliAODTrack(Short_t id,
124 Float_t covMatrix[21],
128 AliAODVertex *prodVertex,
129 Bool_t usedForVtxFit,
130 Bool_t usedForPrimVtxFit,
133 Float_t chi2perNDF) :
136 fChi2perNDF(chi2perNDF),
137 fChi2MatchTrigger(0.),
140 fITSMuonClusterMap(0),
141 fFilterMap(selectInfo),
149 fCaloIndex(kEMCALNoMatch),
152 fProdVertex(prodVertex),
153 fTrackPhiOnEMCal(-999),
154 fTrackEtaOnEMCal(-999)
159 SetPosition(x, isDCA);
160 SetXYAtDCA(-999., -999.);
161 SetPxPyPzAtDCA(-999., -999., -999.);
162 SetUsedForVtxFit(usedForVtxFit);
163 SetUsedForPrimVtxFit(usedForPrimVtxFit);
164 if(covMatrix) SetCovMatrix(covMatrix);
166 SetITSClusterMap(itsClusMap);
169 //______________________________________________________________________________
170 AliAODTrack::~AliAODTrack()
178 //______________________________________________________________________________
179 AliAODTrack::AliAODTrack(const AliAODTrack& trk) :
181 fRAtAbsorberEnd(trk.fRAtAbsorberEnd),
182 fChi2perNDF(trk.fChi2perNDF),
183 fChi2MatchTrigger(trk.fChi2MatchTrigger),
186 fITSMuonClusterMap(trk.fITSMuonClusterMap),
187 fFilterMap(trk.fFilterMap),
188 fTPCFitMap(trk.fTPCFitMap),
189 fTPCClusterMap(trk.fTPCClusterMap),
190 fTPCSharedMap(trk.fTPCSharedMap),
191 fTPCnclsF(trk.fTPCnclsF),
193 fCharge(trk.fCharge),
195 fCaloIndex(trk.fCaloIndex),
198 fProdVertex(trk.fProdVertex),
199 fTrackPhiOnEMCal(trk.fTrackPhiOnEMCal),
200 fTrackEtaOnEMCal(trk.fTrackEtaOnEMCal)
205 trk.GetPosition(fPosition);
206 SetXYAtDCA(trk.XAtDCA(), trk.YAtDCA());
207 SetPxPyPzAtDCA(trk.PxAtDCA(), trk.PyAtDCA(), trk.PzAtDCA());
208 SetUsedForVtxFit(trk.GetUsedForVtxFit());
209 SetUsedForPrimVtxFit(trk.GetUsedForPrimVtxFit());
210 if(trk.fCovMatrix) fCovMatrix=new AliAODRedCov<6>(*trk.fCovMatrix);
211 if(trk.fDetPid) fDetPid=new AliAODPid(*trk.fDetPid);
215 //______________________________________________________________________________
216 AliAODTrack& AliAODTrack::operator=(const AliAODTrack& trk)
218 // Assignment operator
221 AliVTrack::operator=(trk);
224 trk.GetPosition(fPosition);
225 SetXYAtDCA(trk.XAtDCA(), trk.YAtDCA());
226 SetPxPyPzAtDCA(trk.PxAtDCA(), trk.PyAtDCA(), trk.PzAtDCA());
227 fRAtAbsorberEnd = trk.fRAtAbsorberEnd;
228 fChi2perNDF = trk.fChi2perNDF;
229 fChi2MatchTrigger = trk.fChi2MatchTrigger;
233 fITSMuonClusterMap = trk.fITSMuonClusterMap;
234 fFilterMap = trk.fFilterMap;
235 fTPCFitMap = trk.fTPCFitMap;
236 fTPCClusterMap = trk.fTPCClusterMap;
237 fTPCSharedMap = trk.fTPCSharedMap;
238 fTPCnclsF = trk.fTPCnclsF;
240 fCharge = trk.fCharge;
242 fCaloIndex = trk.fCaloIndex;
243 fTrackPhiOnEMCal = trk.fTrackPhiOnEMCal;
244 fTrackEtaOnEMCal = trk.fTrackEtaOnEMCal;
247 if(trk.fCovMatrix) fCovMatrix=new AliAODRedCov<6>(*trk.fCovMatrix);
248 else fCovMatrix=NULL;
251 fProdVertex = trk.fProdVertex;
252 SetUsedForVtxFit(trk.GetUsedForVtxFit());
253 SetUsedForPrimVtxFit(trk.GetUsedForPrimVtxFit());
256 if(trk.fDetPid) fDetPid=new AliAODPid(*trk.fDetPid);
265 //______________________________________________________________________________
266 Double_t AliAODTrack::M(AODTrkPID_t pid) const
269 // Masses for nuclei don't exist in the PDG tables, therefore they were put by hand.
274 return 0.000510999; //TDatabasePDG::Instance()->GetParticle(11/*::kElectron*/)->Mass();
278 return 0.1056584; //TDatabasePDG::Instance()->GetParticle(13/*::kMuonMinus*/)->Mass();
282 return 0.13957; //TDatabasePDG::Instance()->GetParticle(211/*::kPiPlus*/)->Mass();
286 return 0.4937; //TDatabasePDG::Instance()->GetParticle(321/*::kKPlus*/)->Mass();
290 return 0.9382720; //TDatabasePDG::Instance()->GetParticle(2212/*::kProton*/)->Mass();
294 return 1.8756; //TDatabasePDG::Instance()->GetParticle(1000010020)->Mass();
298 return 2.8089; //TDatabasePDG::Instance()->GetParticle(1000010030)->Mass();
302 return 2.8084; //TDatabasePDG::Instance()->GetParticle(1000020030)->Mass();
306 return 3.7274; //TDatabasePDG::Instance()->GetParticle(1000020040)->Mass();
318 //______________________________________________________________________________
319 Double_t AliAODTrack::E(AODTrkPID_t pid) const
321 // Returns the energy of the particle of a given pid.
323 if (pid != kUnknown) { // particle was identified
325 return TMath::Sqrt(P()*P() + m*m);
326 } else { // pid unknown
331 //______________________________________________________________________________
332 Double_t AliAODTrack::Y(AODTrkPID_t pid) const
334 // Returns the rapidity of a particle of a given pid.
336 if (pid != kUnknown) { // particle was identified
339 if (e>=0 && e!=pz) { // energy was positive (e.g. not -999.) and not equal to pz
340 return 0.5*TMath::Log((e+pz)/(e-pz));
341 } else { // energy not known or equal to pz
344 } else { // pid unknown
349 //______________________________________________________________________________
350 Double_t AliAODTrack::Y(Double_t m) const
352 // Returns the rapidity of a particle of a given mass.
354 if (m >= 0.) { // mass makes sense
357 if (e>=0 && e!=pz) { // energy was positive (e.g. not -999.) and not equal to pz
358 return 0.5*TMath::Log((e+pz)/(e-pz));
359 } else { // energy not known or equal to pz
362 } else { // pid unknown
367 //______________________________________________________________________________
368 AliAODTrack::AODTrkPID_t AliAODTrack::GetMostProbablePID() const
370 // Returns the most probable PID array element.
373 AODTrkPID_t loc = kUnknown;
375 Bool_t allTheSame = kTRUE;
377 for (Int_t iPID = 0; iPID < nPID; iPID++) {
378 if (fPID[iPID] >= max) {
379 if (fPID[iPID] > max) {
382 loc = (AODTrkPID_t)iPID;
388 return allTheSame ? kUnknown : loc;
391 //______________________________________________________________________________
392 void AliAODTrack::ConvertAliPIDtoAODPID()
394 // Converts AliPID array.
395 // The numbering scheme is the same for electrons, muons, pions, kaons, and protons.
396 // Everything else has to be set to zero.
398 fPID[kDeuteron] = 0.;
408 //______________________________________________________________________________
409 template <class T> void AliAODTrack::SetP(const T *p, const Bool_t cartesian)
415 Double_t pt2 = p[0]*p[0] + p[1]*p[1];
416 Double_t pp = TMath::Sqrt(pt2 + p[2]*p[2]);
418 fMomentum[0] = TMath::Sqrt(pt2); // pt
419 fMomentum[1] = (pt2 != 0.) ? TMath::Pi()+TMath::ATan2(-p[1], -p[0]) : -999; // phi
420 fMomentum[2] = (pp != 0.) ? TMath::ACos(p[2] / pp) : -999.; // theta
422 fMomentum[0] = p[0]; // pt
423 fMomentum[1] = p[1]; // phi
424 fMomentum[2] = p[2]; // theta
427 fMomentum[0] = -999.;
428 fMomentum[1] = -999.;
429 fMomentum[2] = -999.;
433 //______________________________________________________________________________
434 template <class T> void AliAODTrack::SetPosition(const T *x, const Bool_t dca)
447 // don't know any better yet
448 fPosition[0] = -999.;
449 fPosition[1] = -999.;
450 fPosition[2] = -999.;
455 fPosition[0] = -999.;
456 fPosition[1] = -999.;
457 fPosition[2] = -999.;
461 //______________________________________________________________________________
462 void AliAODTrack::SetDCA(Double_t d, Double_t z)
471 //______________________________________________________________________________
472 void AliAODTrack::Print(Option_t* /* option */) const
474 // prints information about AliAODTrack
476 printf("Object name: %s Track type: %s\n", GetName(), GetTitle());
477 printf(" px = %f\n", Px());
478 printf(" py = %f\n", Py());
479 printf(" pz = %f\n", Pz());
480 printf(" pt = %f\n", Pt());
481 printf(" 1/pt = %f\n", OneOverPt());
482 printf(" theta = %f\n", Theta());
483 printf(" phi = %f\n", Phi());
484 printf(" chi2/NDF = %f\n", Chi2perNDF());
485 printf(" charge = %d\n", Charge());
488 //______________________________________________________________________________
489 void AliAODTrack::SetMatchTrigger(Int_t matchTrig)
491 // Set the MUON trigger information
493 case 0: // 0 track does not match trigger
494 fITSMuonClusterMap=fITSMuonClusterMap&0x3fffffff;
496 case 1: // 1 track match but does not pass pt cut
497 fITSMuonClusterMap=(fITSMuonClusterMap&0x3fffffff)|0x40000000;
499 case 2: // 2 track match Low pt cut
500 fITSMuonClusterMap=(fITSMuonClusterMap&0x3fffffff)|0x80000000;
502 case 3: // 3 track match High pt cut
503 fITSMuonClusterMap=fITSMuonClusterMap|0xc0000000;
506 fITSMuonClusterMap=fITSMuonClusterMap&0x3fffffff;
507 AliWarning(Form("unknown case for matchTrig: %d\n",matchTrig));
511 //______________________________________________________________________________
512 Bool_t AliAODTrack::HitsMuonChamber(Int_t MuonChamber, Int_t cathode) const
514 // return kTRUE if the track fires the given tracking or trigger chamber.
515 // If the chamber is a trigger one:
516 // - if cathode = 0 or 1, the track matches the corresponding cathode
517 // - if cathode = -1, the track matches both cathodes
519 if (MuonChamber < 0) return kFALSE;
521 if (MuonChamber < 10) return TESTBIT(GetMUONClusterMap(), MuonChamber);
523 if (MuonChamber < 14) {
525 if (cathode < 0) return TESTBIT(GetHitsPatternInTrigCh(), 13-MuonChamber) &&
526 TESTBIT(GetHitsPatternInTrigCh(), 13-MuonChamber+4);
528 if (cathode < 2) return TESTBIT(GetHitsPatternInTrigCh(), 13-MuonChamber+(1-cathode)*4);
535 //______________________________________________________________________________
536 Bool_t AliAODTrack::MatchTriggerDigits() const
538 // return kTRUE if the track matches a digit on both planes of at least 2 trigger chambers
540 Int_t nMatchedChambers = 0;
541 for (Int_t ich=10; ich<14; ich++) if (HitsMuonChamber(ich)) nMatchedChambers++;
543 return (nMatchedChambers >= 2);
546 //______________________________________________________________________________
547 Bool_t AliAODTrack::PropagateToDCA(const AliVVertex *vtx,
548 Double_t b, Double_t maxd, Double_t dz[2], Double_t covar[3])
550 // compute impact parameters to the vertex vtx and their covariance matrix
551 // b is the Bz, needed to propagate correctly the track to vertex
552 // only the track parameters are update after the propagation (pos and mom),
553 // not the covariance matrix. This is OK for propagation over short distance
554 // inside the beam pipe.
555 // return kFALSE is something went wrong
557 // convert to AliExternalTrackParam
558 AliExternalTrackParam etp; etp.CopyFromVTrack(this);
560 Float_t xstart = etp.GetX();
562 AliError("This method can be used only for propagation inside the beam pipe");
566 if(!etp.PropagateToDCA(vtx,b,maxd,dz,covar)) return kFALSE;
568 // update track position and momentum
573 SetPosition(mom,kFALSE);
579 //______________________________________________________________________________
580 Bool_t AliAODTrack::GetPxPyPz(Double_t p[3]) const
582 //---------------------------------------------------------------------
583 // This function returns the global track momentum components
584 //---------------------------------------------------------------------
585 p[0]=Px(); p[1]=Py(); p[2]=Pz();
590 //_______________________________________________________________________
591 Float_t AliAODTrack::GetTPCClusterInfo(Int_t nNeighbours/*=3*/, Int_t type/*=0*/, Int_t row0, Int_t row1, Int_t bitType ) const
594 // TPC cluster information
595 // type 0: get fraction of found/findable clusters with neighbourhood definition
596 // 1: findable clusters with neighbourhood definition
599 // 0 - all cluster used
600 // 1 - clusters used for the kalman update
601 // definition of findable clusters:
602 // a cluster is defined as findable if there is another cluster
603 // within +- nNeighbours pad rows. The idea is to overcome threshold
604 // effects with a very simple algorithm.
610 Int_t last=-nNeighbours;
611 const TBits & clusterMap = (bitType%2==0) ? fTPCClusterMap : fTPCFitMap;
613 Int_t upperBound=clusterMap.GetNbits();
614 if (upperBound>row1) upperBound=row1;
615 for (Int_t i=row0; i<upperBound; ++i){
616 //look to current row
623 //look to nNeighbours before
624 if ((i-last)<=nNeighbours) {
628 //look to nNeighbours after
629 for (Int_t j=i+1; j<i+1+nNeighbours; ++j){
636 if (type==2) return found;
637 if (type==1) return findable;
642 fraction=(Float_t)found/(Float_t)findable;
647 return 0; // undefined type - default value
651 //______________________________________________________________________________
652 Double_t AliAODTrack::GetTRDslice(Int_t plane, Int_t slice) const {
654 // return TRD Pid information
656 if (!fDetPid) return -1;
657 Double32_t *trdSlices=fDetPid->GetTRDsignal();
658 if (!trdSlices) return -1;
659 if ((plane<0) || (plane>=kTRDnPlanes)) {
663 Int_t ns=fDetPid->GetTRDnSlices()/kTRDnPlanes;
664 if ((slice<-1) || (slice>=ns)) {
668 if(slice>=0) return trdSlices[plane*ns + slice];
670 // return average of the dEdx measurements
671 Double_t q=0.; Double32_t *s = &trdSlices[plane*ns];
672 for (Int_t i=0; i<ns; i++, s++) if((*s)>0.) q+=(*s);
676 //______________________________________________________________________________
677 UChar_t AliAODTrack::GetTRDntrackletsPID() const{
679 // return number of tracklets calculated from the slices
681 if(!fDetPid) return -1;
682 return fDetPid->GetTRDntrackletsPID();
685 //______________________________________________________________________________
686 UChar_t AliAODTrack::GetTRDncls(Int_t layer) const {
688 // return number of TRD clusters
690 if(!fDetPid || layer > 5) return -1;
691 if(layer < 0) return fDetPid->GetTRDncls();
692 else return fDetPid->GetTRDncls(layer);
695 //______________________________________________________________________________
696 Double_t AliAODTrack::GetTRDmomentum(Int_t plane, Double_t */*sp*/) const
698 //Returns momentum estimation
699 // in TRD layer "plane".
701 if (!fDetPid) return -1;
702 const Float_t *trdMomentum=fDetPid->GetTRDmomentum();
707 if ((plane<0) || (plane>=kTRDnPlanes)) {
711 return trdMomentum[plane];
714 //_______________________________________________________________________
715 Int_t AliAODTrack::GetTOFBunchCrossing(Double_t b, Bool_t) const
717 // Returns the number of bunch crossings after trigger (assuming 25ns spacing)
718 const double kSpacing = 25e3; // min interbanch spacing
719 const double kShift = 0;
720 Int_t bcid = kTOFBCNA; // defualt one
721 if (!IsOn(kTOFout) || !IsOn(kESDpid)) return bcid; // no info
723 double tdif = GetTOFsignal();
724 if (IsOn(kTIME)) { // integrated time info is there
725 int pid = (int)GetMostProbablePID();
727 GetIntegratedTimes(ttimes);
730 else { // assume integrated time info from TOF radius and momentum
731 const double kRTOF = 385.;
732 const double kCSpeed = 3.e-2; // cm/ps
734 if (p<0.001) p = 1.0;
736 double path = kRTOF; // mean TOF radius
737 if (TMath::Abs(b)>kAlmost0) { // account for curvature
738 double curv = Pt()/(b*kB2C);
740 double tgl = Pz()/Pt();
741 path = 2./curv*TMath::ASin(kRTOF*curv/2.)*TMath::Sqrt(1.+tgl*tgl);
744 tdif -= path/kCSpeed*TMath::Sqrt(1.+m*m/(p*p));
746 bcid = TMath::Nint((tdif - kShift)/kSpacing);
750 //_____________________________________________________________________________
751 Bool_t AliAODTrack::GetXYZAt(Double_t x, Double_t b, Double_t *r) const
753 //---------------------------------------------------------------------
754 // This function returns the global track position extrapolated to
755 // the radial position "x" (cm) in the magnetic field "b" (kG)
756 //---------------------------------------------------------------------
758 //conversion of track parameter representation is
759 //based on the implementation of AliExternalTrackParam::Set(...)
760 //maybe some of this code can be moved to AliVTrack to avoid code duplication
761 const double kSafe = 1e-5;
763 Double_t radPos2 = fPosition[0]*fPosition[0]+fPosition[1]*fPosition[1];
764 Double_t radMax = 45.; // approximately ITS outer radius
765 if (radPos2 < radMax*radMax) { // inside the ITS
766 alpha = TMath::ATan2(fMomentum[1],fMomentum[0]);
767 } else { // outside the ITS
768 Float_t phiPos = TMath::Pi()+TMath::ATan2(-fPosition[1], -fPosition[0]);
770 TMath::DegToRad()*(20*((((Int_t)(phiPos*TMath::RadToDeg()))/20))+10);
773 Double_t cs=TMath::Cos(alpha), sn=TMath::Sin(alpha);
774 // protection: avoid alpha being too close to 0 or +-pi/2
775 if (TMath::Abs(sn)<kSafe) {
777 cs=TMath::Cos(alpha);
778 sn=TMath::Sin(alpha);
781 alpha -= TMath::Sign(kSafe, alpha);
782 cs=TMath::Cos(alpha);
783 sn=TMath::Sin(alpha);
786 // Get the vertex of origin and the momentum
787 TVector3 ver(fPosition[0],fPosition[1],fPosition[2]);
788 TVector3 mom(fMomentum[0],fMomentum[1],fMomentum[2]);
790 // avoid momenta along axis
791 if (TMath::Abs(mom[0])<kSafe) mom[0] = TMath::Sign(kSafe*TMath::Abs(mom[1]), mom[0]);
792 if (TMath::Abs(mom[1])<kSafe) mom[1] = TMath::Sign(kSafe*TMath::Abs(mom[0]), mom[1]);
794 // Rotate to the local coordinate system
798 Double_t param0 = ver.Y();
799 Double_t param1 = ver.Z();
800 Double_t param2 = TMath::Sin(mom.Phi());
801 Double_t param3 = mom.Pz()/mom.Pt();
802 Double_t param4 = TMath::Sign(1/mom.Pt(),(Double_t)fCharge);
804 //calculate the propagated coordinates
805 //this is based on AliExternalTrackParam::GetXYZAt(Double_t x, Double_t b, Double_t *r)
806 Double_t dx=x-ver.X();
807 if(TMath::Abs(dx)<=kAlmost0) return GetXYZ(r);
810 Double_t f2=f1 + dx*param4*b*kB2C;
812 if (TMath::Abs(f1) >= kAlmost1) return kFALSE;
813 if (TMath::Abs(f2) >= kAlmost1) return kFALSE;
815 Double_t r1=TMath::Sqrt((1.-f1)*(1.+f1)), r2=TMath::Sqrt((1.-f2)*(1.+f2));
817 r[1] = param0 + dx*(f1+f2)/(r1+r2);
818 r[2] = param1 + dx*(r2 + f2*(f1+f2)/(r1+r2))*param3;//Thanks to Andrea & Peter
820 return Local2GlobalPosition(r,alpha);