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 **************************************************************************/
20 #include "AliTracker.h"
22 #include "AliTRDgeometry.h"
23 #include "AliTRDcluster.h"
24 #include "AliTRDtrack.h"
25 #include "AliTRDcalibDB.h"
26 #include "Cal/AliTRDCalPID.h"
30 ///////////////////////////////////////////////////////////////////////////////
32 // Represents a reconstructed TRD track //
33 // Local TRD Kalman track //
35 ///////////////////////////////////////////////////////////////////////////////
37 //_____________________________________________________________________________
38 AliTRDtrack::AliTRDtrack()
44 ,fClusterOwner(kFALSE)
59 // AliTRDtrack default constructor
62 for (Int_t i = 0; i < kNplane; i++) {
63 for (Int_t j = 0; j < kNslice; j++) {
64 fdEdxPlane[i][j] = 0.0;
70 fTrackletIndex[i] = -1;
72 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
73 fPID[ispec] = 1.0 / AliPID::kSPECIES;
76 for (UInt_t i = 0; i < kMAXCLUSTERSPERTRACK; i++) {
83 for (Int_t i = 0; i < 3; i++) {
89 //_____________________________________________________________________________
90 AliTRDtrack::AliTRDtrack(AliTRDcluster *c, Int_t index
91 , const Double_t p[5], const Double_t cov[15]
92 , Double_t x, Double_t alpha)
98 ,fClusterOwner(kFALSE)
113 // The main AliTRDtrack constructor.
116 Double_t cnv = 1.0 / (GetBz() * kB2C);
118 Double_t pp[5] = { p[0]
124 Double_t c22 = x*x*cov[14] - 2*x*cov[12] + cov[ 5];
125 Double_t c32 = x*cov[13] - cov[ 8];
126 Double_t c20 = x*cov[10] - cov[ 3];
127 Double_t c21 = x*cov[11] - cov[ 4];
128 Double_t c42 = x*cov[14] - cov[12];
130 Double_t cc[15] = { cov[ 0]
133 , cov[ 6], cov[ 7], c32, cov[ 9]
134 , cov[10]*cnv, cov[11]*cnv, c42*cnv, cov[13]*cnv, cov[14]*cnv*cnv };
137 SetNumberOfClusters(1);
141 for (Int_t i = 0; i < kNplane; i++) {
142 for (Int_t j = 0; j < kNslice; j++) {
143 fdEdxPlane[i][j] = 0.0;
145 fTimBinPlane[i] = -1;
149 fTrackletIndex[i] = -1;
151 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
152 fPID[ispec] = 1.0 / AliPID::kSPECIES;
155 Double_t q = TMath::Abs(c->GetQ());
156 Double_t s = GetSnp();
157 Double_t t = GetTgl();
159 q *= TMath::Sqrt((1-s*s)/(1+t*t));
163 for (UInt_t i = 1; i < kMAXCLUSTERSPERTRACK; i++) {
170 for (Int_t i = 0; i < 3;i++) {
176 //_____________________________________________________________________________
177 AliTRDtrack::AliTRDtrack(const AliTRDtrack &t/*, const Bool_t owner*/)
179 ,fSeedLab(t.GetSeedLabel())
182 ,fPIDquality(t.fPIDquality)
183 ,fClusterOwner(kTRUE)
184 ,fPIDmethod(t.fPIDmethod)
185 ,fStopped(t.fStopped)
188 ,fNRotate(t.fNRotate)
190 ,fNExpected(t.fNExpected)
192 ,fNExpectedLast(t.fNExpectedLast)
194 ,fChi2Last(t.fChi2Last)
201 for (Int_t i = 0; i < kNplane; i++) {
202 for (Int_t j = 0; j < kNslice; j++) {
203 fdEdxPlane[i][j] = t.fdEdxPlane[i][j];
205 fTimBinPlane[i] = t.fTimBinPlane[i];
206 fTracklets[i] = t.fTracklets[i];
210 fTrackletIndex[i] = t.fTrackletIndex[i];
213 Int_t n = t.GetNumberOfClusters();
214 SetNumberOfClusters(n);
216 for (Int_t i = 0; i < n; i++) {
217 fIndex[i] = t.fIndex[i];
218 fIndexBackup[i] = t.fIndex[i];
219 fdQdl[i] = t.fdQdl[i];
220 if (fClusterOwner && t.fClusters[i]) {
221 fClusters[i] = new AliTRDcluster(*(t.fClusters[i]));
224 fClusters[i] = t.fClusters[i];
228 for (UInt_t i = n; i < kMAXCLUSTERSPERTRACK; i++) {
235 for (Int_t i = 0; i < 3;i++) {
236 fBudget[i] = t.fBudget[i];
239 for(Int_t ispec = 0; ispec<AliPID::kSPECIES; ispec++) fPID[ispec] = t.fPID[ispec];
242 //_____________________________________________________________________________
243 AliTRDtrack::AliTRDtrack(const AliKalmanTrack &t, Double_t /*alpha*/)
246 ,fdEdx(t.GetPIDsignal())
249 ,fClusterOwner(kFALSE)
264 // Constructor from AliTPCtrack or AliITStrack
267 SetLabel(t.GetLabel());
269 SetMass(t.GetMass());
270 SetNumberOfClusters(0);
272 for (Int_t i = 0; i < kNplane; i++) {
273 for (Int_t j = 0; j < kNslice; j++) {
274 fdEdxPlane[i][j] = 0.0;
276 fTimBinPlane[i] = -1;
280 fTrackletIndex[i] = -1;
282 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
283 fPID[ispec] = 1.0 / AliPID::kSPECIES;
286 for (UInt_t i = 0; i < kMAXCLUSTERSPERTRACK; i++) {
293 for (Int_t i = 0; i < 3; i++) {
299 //_____________________________________________________________________________
300 AliTRDtrack::AliTRDtrack(const AliESDtrack &t)
303 ,fdEdx(t.GetTRDsignal())
306 ,fClusterOwner(kFALSE)
321 // Constructor from AliESDtrack
324 SetLabel(t.GetLabel());
326 SetMass(t.GetMass());
327 SetNumberOfClusters(t.GetTRDclusters(fIndex));
329 Int_t ncl = t.GetTRDclusters(fIndexBackup);
330 for (UInt_t i = ncl; i < kMAXCLUSTERSPERTRACK; i++) {
335 for (Int_t i = 0; i < kNplane; i++) {
336 for (Int_t j = 0; j < kNslice; j++) {
337 fdEdxPlane[i][j] = t.GetTRDslice(i,j);
339 fTimBinPlane[i] = t.GetTRDTimBin(i);
343 fTrackletIndex[i] = -1;
346 const AliExternalTrackParam *par = &t;
347 if (t.GetStatus() & AliESDtrack::kTRDbackup) {
348 par = t.GetOuterParam();
350 AliError("No backup info!");
357 ,par->GetCovariance());
359 for (UInt_t i = 0; i < kMAXCLUSTERSPERTRACK; i++) {
364 for (Int_t i = 0; i < 3; i++) {
367 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
368 fPID[ispec] = t.GetTRDpid(ispec);
371 if ((t.GetStatus() & AliESDtrack::kTIME) == 0) {
377 t.GetIntegratedTimes(times);
378 SetIntegratedTimes(times);
379 SetIntegratedLength(t.GetIntegratedLength());
383 //____________________________________________________________________________
384 AliTRDtrack::~AliTRDtrack()
397 while ((icluster < kMAXCLUSTERSPERTRACK) && fClusters[icluster]) {
398 delete fClusters[icluster];
399 fClusters[icluster] = 0x0;
406 //____________________________________________________________________________
407 Float_t AliTRDtrack::StatusForTOF()
410 // Defines the status of the TOF extrapolation
413 // Definition of res ????
414 Float_t res = (0.2 + 0.8 * (fN / (fNExpected + 5.0)))
415 * (0.4 + 0.6 * fTracklets[5].GetN() / 20.0);
416 res *= (0.25 + 0.8 * 40.0 / (40.0 + fBudget[2]));
421 //_____________________________________________________________________________
422 Int_t AliTRDtrack::Compare(const TObject *o) const
425 // Compares tracks according to their Y2 or curvature
428 AliTRDtrack *t = (AliTRDtrack *) o;
430 Double_t co = TMath::Abs(t->GetC());
431 Double_t c = TMath::Abs(GetC());
444 //_____________________________________________________________________________
445 void AliTRDtrack::CookdEdx(Double_t low, Double_t up)
448 // Calculates the truncated dE/dx within the "low" and "up" cuts.
451 // Array to sort the dEdx values according to amplitude
452 Float_t sorted[kMAXCLUSTERSPERTRACK];
455 // Require at least 10 clusters for a dedx measurement
460 // Can fdQdl be negative ????
461 for (Int_t i = 0; i < fNdedx; i++) {
462 sorted[i] = TMath::Abs(fdQdl[i]);
464 // Sort the dedx values by amplitude
465 Int_t *index = new Int_t[fNdedx];
466 TMath::Sort(fNdedx, sorted, index, kFALSE);
468 // Sum up the truncated charge between lower and upper bounds
469 Int_t nl = Int_t(low * fNdedx);
470 Int_t nu = Int_t( up * fNdedx);
471 for (Int_t i = nl; i <= nu; i++) {
472 fdEdx += sorted[index[i]];
474 fdEdx /= (nu - nl + 1.0);
480 //_____________________________________________________________________________
481 void AliTRDtrack::CookdEdxTimBin(const Int_t/* tid*/)
484 // Set fdEdxPlane and fTimBinPlane and also get the
485 // Time bin for Max. Cluster
488 // Prashant Shukla (shukla@physi.uni-heidelberg.de)
489 // Alexandru Bercuci (A.Bercuci@gsi.de)
492 // Max charge in chamber
493 Double_t maxcharge[kNplane];
494 // Number of clusters attached to track per chamber and slice
495 Int_t nCluster[kNplane][kNslice];
496 // Number of time bins in chamber
497 Int_t ntb = AliTRDcalibDB::Instance()->GetNumberOfTimeBins();
498 Int_t plane; // Plane of current cluster
499 Int_t tb; // Time bin of current cluster
500 Int_t slice; // Current slice
501 AliTRDcluster *cluster = 0x0; // Pointer to current cluster
503 // Reset class and local counters/variables
504 for (Int_t iPlane = 0; iPlane < kNplane; iPlane++) {
505 fTimBinPlane[iPlane] = -1;
506 maxcharge[iPlane] = 0.0;
507 for (Int_t iSlice = 0; iSlice < kNslice; iSlice++) {
508 fdEdxPlane[iPlane][iSlice] = 0.0;
509 nCluster[iPlane][iSlice] = 0;
513 // Start looping over clusters attached to this track
514 for (Int_t iClus = 0; iClus < GetNumberOfClusters(); iClus++) {
516 cluster = fClusters[iClus]; //(AliTRDcluster*)tracker->GetCluster(fIndex[iClus]);
517 if (!cluster) continue;
519 // Read info from current cluster
520 plane = AliTRDgeometry::GetLayer(cluster->GetDetector());
521 if (plane < 0 || plane >= kNplane) {
522 AliError(Form("Wrong plane %d", plane));
526 tb = cluster->GetLocalTimeBin();
527 if ((tb < 0) || (tb >= ntb)) {
528 AliWarning(Form("time bin < 0 or > %d in cluster %d", ntb, iClus));
529 AliInfo(Form("dQ/dl %f", fdQdl[iClus]));
533 slice = tb * kNslice / ntb;
535 fdEdxPlane[plane][slice] += fdQdl[iClus];
536 if (fdQdl[iClus] > maxcharge[plane]) {
537 maxcharge[plane] = fdQdl[iClus];
538 fTimBinPlane[plane] = tb;
541 nCluster[plane][slice]++;
543 } // End of loop over cluster
545 // Normalize fdEdxPlane to number of clusters and set track segments
546 for (Int_t iPlane = 0; iPlane < kNplane; iPlane++) {
547 for (Int_t iSlice = 0; iSlice < kNslice; iSlice++) {
548 if (nCluster[iPlane][iSlice]) {
549 fdEdxPlane[iPlane][iSlice] /= nCluster[iPlane][iSlice];
556 //_____________________________________________________________________________
557 void AliTRDtrack::CookdEdxNN(Float_t *dedx)
560 // This function calcuates the input for the neural networks
561 // which are used for the PID.
564 //number of time bins in chamber
565 Int_t ntb = AliTRDcalibDB::Instance()->GetNumberOfTimeBins();
567 Int_t plane; // plane of current cluster
568 Int_t tb; // time bin of current cluster
569 Int_t slice; // curent slice
570 AliTRDcluster *cluster = 0x0; // pointer to current cluster
571 const Int_t kMLPscale = 16000; // scaling of the MLP input to be smaller than 1
573 // Reset class and local contors/variables
574 for (Int_t iPlane = 0; iPlane < kNplane; iPlane++){
575 for (Int_t iSlice = 0; iSlice < kNMLPslice; iSlice++) {
576 *(dedx + (kNMLPslice * iPlane) + iSlice) = 0.0;
580 // Start looping over clusters attached to this track
581 for (Int_t iClus = 0; iClus < GetNumberOfClusters(); iClus++) {
583 cluster = fClusters[iClus]; //(AliTRDcluster*)tracker->GetCluster(fIndex[iClus]);
588 // Read info from current cluster
589 plane = AliTRDgeometry::GetLayer(cluster->GetDetector());
590 if (plane < 0 || plane >= kNplane) {
591 AliError(Form("Wrong plane %d",plane));
595 tb = cluster->GetLocalTimeBin();
596 if (tb == 0 || tb >= ntb) {
597 AliWarning(Form("time bin 0 or > %d in cluster %d",ntb,iClus));
598 AliInfo(Form("dQ/dl %f",fdQdl[iClus]));
602 slice = tb * kNMLPslice / ntb;
604 *(dedx+(kNMLPslice * plane) + slice) += fdQdl[iClus]/kMLPscale;
606 } // End of loop over cluster
610 //_____________________________________________________________________________
611 void AliTRDtrack::SetTrackSegmentDirMom(const Int_t plane)
614 // Set the momenta for a track segment in a given plane
619 AliError(Form("Trying to access out of range plane (%d)", plane));
623 fSnp[plane] = GetSnp();
624 fTgl[plane] = GetTgl();
627 fMom[plane] = TMath::Sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
631 //_____________________________________________________________________________
632 Float_t AliTRDtrack::GetTrackLengthPlane(Int_t plane) const
635 // Calculate the track length of a track segment in a given plane
639 (plane >= kNplane)) {
643 return (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick())
644 / TMath::Sqrt((1.0 - fSnp[plane]*fSnp[plane])
645 / (1.0 + fTgl[plane]*fTgl[plane]));
649 //_____________________________________________________________________________
650 Bool_t AliTRDtrack::CookPID(Int_t &pidQuality)
653 // This function calculates the PID probabilities based on TRD signals
655 // The method produces probabilities based on the charge
656 // and the position of the maximum time bin in each layer.
657 // The dE/dx information can be used as global charge or 2 to 3
658 // slices. Check AliTRDCalPID and AliTRDCalPIDRefMaker for the actual
662 // Alex Bercuci (A.Bercuci@gsi.de) 2nd May 2007
665 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
667 AliError("No access to calibration data");
671 // Retrieve the CDB container class with the probability distributions
672 const AliTRDCalPID *pd = calibration->GetPIDObject(AliTRDReconstructor::kLQPID);
674 AliError("No access to AliTRDCalPID");
678 // Calculate the input for the NN if fPIDmethod is kNN
679 Float_t ldEdxNN[AliTRDgeometry::kNlayer * kNMLPslice], *dedx = 0x0;
680 if(fPIDmethod == kNN) {
681 CookdEdxNN(&ldEdxNN[0]);
684 // Sets the a priori probabilities
685 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
686 fPID[ispec] = 1.0 / AliPID::kSPECIES;
689 if(AliPID::kSPECIES != 5){
690 AliError("Probabilities array defined only for 5 values. Please modify !!");
695 Float_t length; // track segment length in chamber
697 // Skip tracks which have no TRD signal at all
698 if (fdEdx == 0.) return kFALSE;
700 for (Int_t iPlane = 0; iPlane < AliTRDgeometry::kNlayer; iPlane++) {
702 length = (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick())
703 / TMath::Sqrt((1.0 - fSnp[iPlane]*fSnp[iPlane])
704 / (1.0 + fTgl[iPlane]*fTgl[iPlane]));
707 if((fdEdxPlane[iPlane][0] + fdEdxPlane[iPlane][1] + fdEdxPlane[iPlane][2]) <= 0.
708 || fTimBinPlane[iPlane] == -1.) continue;
710 // this track segment has fulfilled all requierments
713 // Get the probabilities for the different particle species
714 for (Int_t iSpecies = 0; iSpecies < AliPID::kSPECIES; iSpecies++) {
717 dedx = fdEdxPlane[iPlane];
720 dedx = &ldEdxNN[iPlane*kNMLPslice];
723 fPID[iSpecies] *= pd->GetProbability(iSpecies, fMom[iPlane], dedx, length, iPlane);
728 if (pidQuality == 0) {
732 // normalize probabilities
733 Double_t probTotal = 0.0;
734 for (Int_t iSpecies = 0; iSpecies < AliPID::kSPECIES; iSpecies++) {
735 probTotal += fPID[iSpecies];
738 if (probTotal <= 0.0) {
739 AliWarning("The total probability over all species <= 0.");
740 AliWarning("This may be caused by some error in the reference histograms.");
744 for (Int_t iSpecies = 0; iSpecies < AliPID::kSPECIES; iSpecies++) {
745 fPID[iSpecies] /= probTotal;
752 //_____________________________________________________________________________
753 Bool_t AliTRDtrack::PropagateTo(Double_t xk, Double_t xx0, Double_t xrho)
756 // Propagates this track to a reference plane defined by "xk" [cm]
757 // correcting for the mean crossed material.
759 // "xx0" - thickness/rad.length [units of the radiation length]
760 // "xrho" - thickness*density [g/cm^2]
767 Double_t oldX = GetX();
768 Double_t oldY = GetY();
769 Double_t oldZ = GetZ();
771 Double_t bz = GetBz();
773 if (!AliExternalTrackParam::PropagateTo(xk,bz)) {
783 if (IsStartedTimeIntegral()) {
784 Double_t l2 = TMath::Sqrt((x-oldX)*(x-oldX)
786 + (z-oldZ)*(z-oldZ));
787 Double_t crv = GetC();
788 if (TMath::Abs(l2*crv) > 0.0001) {
789 // Make correction for curvature if neccesary
790 l2 = 0.5 * TMath::Sqrt((x-oldX)*(x-oldX)
791 + (y-oldY)*(y-oldY));
792 l2 = 2.0 * TMath::ASin(l2 * crv) / crv;
793 l2 = TMath::Sqrt(l2*l2 + (z-oldZ)*(z-oldZ));
799 if (!AliExternalTrackParam::CorrectForMeanMaterial(xx0,xrho,GetMass())) {
806 Double_t p2 = (1.0 + GetTgl()*GetTgl()) / (GetSigned1Pt()*GetSigned1Pt());
807 Double_t beta2 = p2 / (p2 + GetMass()*GetMass());
808 if ((beta2 < 1.0e-10) ||
809 ((5940.0 * beta2/(1.0 - beta2 + 1.0e-10) - beta2) < 0.0)) {
813 Double_t dE = 0.153e-3 / beta2
814 * (TMath::Log(5940.0 * beta2/(1.0 - beta2 + 1.0e-10)) - beta2)
819 // Suspicious part - think about it ?
820 Double_t kinE = TMath::Sqrt(p2);
821 if (dE > 0.8*kinE) dE = 0.8 * kinE; //
822 if (dE < 0) dE = 0.0; // Not valid region for Bethe bloch
829 Double_t sigmade = 0.07 * TMath::Sqrt(TMath::Abs(dE)); // Energy loss fluctuation
830 Double_t sigmac2 = sigmade*sigmade*fC*fC*(p2+GetMass()*GetMass())/(p2*p2);
832 fCee += fX*fX * sigmac2;
841 //_____________________________________________________________________________
842 Bool_t AliTRDtrack::Update(const AliTRDcluster *c, Double_t chisq
843 , Int_t index, Double_t h01)
846 // Assignes the found cluster <c> to the track and updates
847 // track information.
848 // <chisq> : predicted chi2
850 // <h01> : Tilting factor
853 Double_t p[2] = { c->GetY()
855 Double_t sy2 = c->GetSigmaY2() * 4.0;
856 Double_t sz2 = c->GetSigmaZ2() * 4.0;
857 Double_t cov[3] = { sy2 + h01*h01*sz2
859 , sz2 + h01*h01*sy2 };
861 if (!AliExternalTrackParam::Update(p,cov)) {
865 Int_t n = GetNumberOfClusters();
867 SetNumberOfClusters(n+1);
869 SetChi2(GetChi2()+chisq);
875 //_____________________________________________________________________________
876 Int_t AliTRDtrack::UpdateMI(AliTRDcluster *c, Double_t chisq, Int_t index
877 , Double_t h01, Int_t /*plane*/, Int_t /*tid*/)
880 // Assignes the found cluster <c> to the track and
881 // updates track information
882 // <chisq> : predicted chi2
884 // <h01> : Tilting factor
886 // Difference to Update(AliTRDcluster *c): cluster is added to fClusters
889 Double_t p[2] = { c->GetY()
891 Double_t sy2 = c->GetSigmaY2() * 4.0;
892 Double_t sz2 = c->GetSigmaZ2() * 4.0;
893 Double_t cov[3] = { sy2 + h01*h01*sz2
895 , sz2 + h01*h01*sy2 };
897 if (!AliExternalTrackParam::Update(p,cov)) {
901 AliTracker::FillResiduals(this,p,cov,c->GetVolumeId());
903 // Register cluster to track
904 Int_t n = GetNumberOfClusters();
907 SetNumberOfClusters(n+1);
908 SetChi2(GetChi2() + chisq);
914 //_____________________________________________________________________________
915 Bool_t AliTRDtrack::Update(const AliTRDtracklet &t, Double_t chisq, Int_t index)
918 // Assignes the found tracklet <t> to the track
919 // and updates track information
920 // <chisq> : predicted chi2
924 Double_t h01 = t.GetTilt(); // Is this correct????
925 Double_t p[2] = { t.GetY(), t.GetZ() };
926 Double_t sy2 = t.GetTrackletSigma2(); // Error pad-column
927 Double_t sz2 = 100000.0; // Error pad-row (????)
928 Double_t cov[3] = { sy2 + h01*h01*sz2 // Does this have any sense????
930 , sz2 + h01*h01*sy2 };
931 if (!AliExternalTrackParam::Update(p,cov)) {
935 Int_t n = GetNumberOfClusters();
937 SetNumberOfClusters(n+1);
938 SetChi2(GetChi2()+chisq);
944 //_____________________________________________________________________________
945 Bool_t AliTRDtrack::Rotate(Double_t alpha, Bool_t absolute)
948 // Rotates track parameters in R*phi plane
949 // if absolute rotation alpha is in global system
950 // otherwise alpha rotation is relative to the current rotation angle
960 return AliExternalTrackParam::Rotate(GetAlpha()+alpha);
964 //_____________________________________________________________________________
965 Double_t AliTRDtrack::GetPredictedChi2(const AliTRDcluster *c, Double_t h01) const
968 // Returns the track chi2
971 Double_t p[2] = { c->GetY()
973 Double_t sy2 = c->GetSigmaY2() * 4.0;
974 Double_t sz2 = c->GetSigmaZ2() * 4.0;
975 Double_t cov[3] = { sy2 + h01*h01*sz2
977 , sz2 + h01*h01*sy2 };
979 return AliExternalTrackParam::GetPredictedChi2(p,cov);
983 //_____________________________________________________________________________
984 void AliTRDtrack::MakeBackupTrack()
987 // Creates a backup track
993 fBackupTrack = new AliTRDtrack(*this);
997 //_____________________________________________________________________________
998 Int_t AliTRDtrack::GetProlongation(Double_t xk, Double_t &y, Double_t &z)
1001 // Find a prolongation at given x
1002 // Return 0 if it does not exist
1005 Double_t bz = GetBz();
1007 if (!AliExternalTrackParam::GetYAt(xk,bz,y)) {
1010 if (!AliExternalTrackParam::GetZAt(xk,bz,z)) {
1018 //_____________________________________________________________________________
1019 Int_t AliTRDtrack::PropagateToX(Double_t xr, Double_t step)
1022 // Propagate track to given x position
1023 // Works inside of the 20 degree segmentation
1024 // (local cooordinate frame for TRD , TPC, TOF)
1026 // Material budget from geo manager
1034 const Double_t kAlphac = TMath::Pi()/9.0;
1035 const Double_t kTalphac = TMath::Tan(kAlphac*0.5);
1037 // Critical alpha - cross sector indication
1038 Double_t dir = (GetX() > xr) ? -1.0 : 1.0;
1041 for (Double_t x = GetX()+dir*step; dir*x < dir*xr; x += dir*step) {
1044 GetProlongation(x,y,z);
1045 xyz1[0] = x * TMath::Cos(GetAlpha()) + y * TMath::Sin(GetAlpha());
1046 xyz1[1] = x * TMath::Sin(GetAlpha()) - y * TMath::Cos(GetAlpha());
1049 AliTracker::MeanMaterialBudget(xyz0,xyz1,param);
1051 if ((param[0] > 0) &&
1053 PropagateTo(x,param[1],param[0]*param[4]);
1056 if (GetY() > GetX()*kTalphac) {
1059 if (GetY() < -GetX()*kTalphac) {
1071 //_____________________________________________________________________________
1072 Int_t AliTRDtrack::PropagateToR(Double_t r,Double_t step)
1075 // Propagate track to the radial position
1076 // Rotation always connected to the last track position
1084 Double_t radius = TMath::Sqrt(GetX()*GetX() + GetY()*GetY());
1086 Double_t dir = (radius > r) ? -1.0 : 1.0;
1088 for (Double_t x = radius+dir*step; dir*x < dir*r; x += dir*step) {
1091 Double_t alpha = TMath::ATan2(xyz0[1],xyz0[0]);
1092 Rotate(alpha,kTRUE);
1094 GetProlongation(x,y,z);
1095 xyz1[0] = x * TMath::Cos(alpha) + y * TMath::Sin(alpha);
1096 xyz1[1] = x * TMath::Sin(alpha) - y * TMath::Cos(alpha);
1099 AliTracker::MeanMaterialBudget(xyz0,xyz1,param);
1100 if (param[1] <= 0) {
1101 param[1] = 100000000;
1103 PropagateTo(x,param[1],param[0]*param[4]);
1108 Double_t alpha = TMath::ATan2(xyz0[1],xyz0[0]);
1109 Rotate(alpha,kTRUE);
1111 GetProlongation(r,y,z);
1112 xyz1[0] = r * TMath::Cos(alpha) + y * TMath::Sin(alpha);
1113 xyz1[1] = r * TMath::Sin(alpha) - y * TMath::Cos(alpha);
1116 AliTracker::MeanMaterialBudget(xyz0,xyz1,param);
1118 if (param[1] <= 0) {
1119 param[1] = 100000000;
1121 PropagateTo(r,param[1],param[0]*param[4]);
1127 //_____________________________________________________________________________
1128 Int_t AliTRDtrack::GetSector() const
1131 // Return the current sector
1134 return Int_t(TVector2::Phi_0_2pi(GetAlpha()) / AliTRDgeometry::GetAlpha())
1135 % AliTRDgeometry::kNsector;
1139 //_____________________________________________________________________________
1140 void AliTRDtrack::SetSampledEdx(Float_t q, Int_t i)
1143 // The sampled energy loss
1146 Double_t s = GetSnp();
1147 Double_t t = GetTgl();
1148 q *= TMath::Sqrt((1.0 - s*s) / (1.0 + t*t));
1153 //_____________________________________________________________________________
1154 void AliTRDtrack::SetSampledEdx(Float_t q)
1157 // The sampled energy loss
1160 Double_t s = GetSnp();
1161 Double_t t = GetTgl();
1162 q *= TMath::Sqrt((1.0 - s*s) / (1.0 + t*t));
1168 //_____________________________________________________________________________
1169 Double_t AliTRDtrack::GetBz() const
1172 // Returns Bz component of the magnetic field (kG)
1175 if (AliTracker::UniformField()) {
1176 return AliTracker::GetBz();
1181 return AliTracker::GetBz(r);