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 **************************************************************************/
18 #include <Riostream.h>
23 #include "AliTracker.h"
24 #include "AliESDtrack.h"
26 #include "AliTRDgeometry.h"
27 #include "AliTRDcluster.h"
28 #include "AliTRDtrack.h"
29 #include "AliTRDtracklet.h"
31 // A. Bercuci - used for PID calculations
32 #include "AliTRDcalibDB.h"
33 #include "Cal/AliTRDCalPID.h"
37 ///////////////////////////////////////////////////////////////////////////////
39 // Represents a reconstructed TRD track //
40 // Local TRD Kalman track //
42 ///////////////////////////////////////////////////////////////////////////////
44 //_____________________________________________________________________________
45 AliTRDtrack::AliTRDtrack()
50 ,fClusterOwner(kFALSE)
64 // AliTRDtrack default constructor
67 for (Int_t i = 0; i < kNplane; i++) {
68 for (Int_t j = 0; j < kNslice; j++) {
69 fdEdxPlane[i][j] = 0.0;
77 for (UInt_t i = 0; i < kMAXCLUSTERSPERTRACK; i++) {
84 for (Int_t i = 0; i < 3; i++) {
90 //_____________________________________________________________________________
91 AliTRDtrack::AliTRDtrack(AliTRDcluster *c, Int_t index
92 , const Double_t p[5], const Double_t cov[15]
93 , Double_t x, Double_t alpha)
98 ,fClusterOwner(kFALSE)
112 // The main AliTRDtrack constructor.
115 Double_t cnv = 1.0 / (GetBz() * kB2C);
117 Double_t pp[5] = { p[0]
123 Double_t c22 = x*x*cov[14] - 2*x*cov[12] + cov[ 5];
124 Double_t c32 = x*cov[13] - cov[ 8];
125 Double_t c20 = x*cov[10] - cov[ 3];
126 Double_t c21 = x*cov[11] - cov[ 4];
127 Double_t c42 = x*cov[14] - cov[12];
129 Double_t cc[15] = { cov[ 0]
132 , cov[ 6], cov[ 7], c32, cov[ 9]
133 , cov[10]*cnv, cov[11]*cnv, c42*cnv, cov[13]*cnv, cov[14]*cnv*cnv };
136 SetNumberOfClusters(1);
140 for (Int_t i = 0; i < kNplane; i++) {
141 for (Int_t j = 0; j < kNslice; j++) {
142 fdEdxPlane[i][j] = 0.0;
144 fTimBinPlane[i] = -1;
150 Double_t q = TMath::Abs(c->GetQ());
151 Double_t s = GetSnp();
152 Double_t t = GetTgl();
154 q *= TMath::Sqrt((1-s*s)/(1+t*t));
158 for (UInt_t i = 1; i < kMAXCLUSTERSPERTRACK; i++) {
165 for (Int_t i = 0; i < 3;i++) {
171 //_____________________________________________________________________________
172 AliTRDtrack::AliTRDtrack(const AliTRDtrack &t/*, const Bool_t owner*/)
174 ,fSeedLab(t.GetSeedLabel())
177 ,fClusterOwner(kTRUE)
178 ,fStopped(t.fStopped)
181 ,fNRotate(t.fNRotate)
183 ,fNExpected(t.fNExpected)
185 ,fNExpectedLast(t.fNExpectedLast)
187 ,fChi2Last(t.fChi2Last)
194 for (Int_t i = 0; i < kNplane; i++) {
195 for (Int_t j = 0; j < kNslice; j++) {
196 fdEdxPlane[i][j] = t.fdEdxPlane[i][j];
198 fTimBinPlane[i] = t.fTimBinPlane[i];
199 fTracklets[i] = t.fTracklets[i];
205 Int_t n = t.GetNumberOfClusters();
206 SetNumberOfClusters(n);
208 for (Int_t i = 0; i < n; i++) {
209 fIndex[i] = t.fIndex[i];
210 fIndexBackup[i] = t.fIndex[i];
211 fdQdl[i] = t.fdQdl[i];
212 if (fClusterOwner && t.fClusters[i]) {
213 fClusters[i] = new AliTRDcluster(*(t.fClusters[i]));
216 fClusters[i] = t.fClusters[i];
220 for (UInt_t i = n; i < kMAXCLUSTERSPERTRACK; i++) {
227 for (Int_t i = 0; i < 3;i++) {
228 fBudget[i] = t.fBudget[i];
233 //_____________________________________________________________________________
234 AliTRDtrack::AliTRDtrack(const AliKalmanTrack &t, Double_t /*alpha*/)
237 ,fdEdx(t.GetPIDsignal())
239 ,fClusterOwner(kFALSE)
253 // Constructor from AliTPCtrack or AliITStrack
256 SetLabel(t.GetLabel());
258 SetMass(t.GetMass());
259 SetNumberOfClusters(0);
261 for (Int_t i = 0; i < kNplane; i++) {
262 for (Int_t j = 0; j < kNslice; j++) {
263 fdEdxPlane[i][j] = 0.0;
265 fTimBinPlane[i] = -1;
271 for (UInt_t i = 0; i < kMAXCLUSTERSPERTRACK; i++) {
278 for (Int_t i = 0; i < 3; i++) {
284 //_____________________________________________________________________________
285 AliTRDtrack::AliTRDtrack(const AliESDtrack &t)
288 ,fdEdx(t.GetTRDsignal())
290 ,fClusterOwner(kFALSE)
304 // Constructor from AliESDtrack
307 SetLabel(t.GetLabel());
309 SetMass(t.GetMass());
310 SetNumberOfClusters(t.GetTRDclusters(fIndex));
312 Int_t ncl = t.GetTRDclusters(fIndexBackup);
313 for (UInt_t i = ncl; i < kMAXCLUSTERSPERTRACK; i++) {
318 for (Int_t i = 0; i < kNplane; i++) {
319 for (Int_t j = 0; j < kNslice; j++) {
320 fdEdxPlane[i][j] = t.GetTRDsignals(i,j);
322 fTimBinPlane[i] = t.GetTRDTimBin(i);
328 const AliExternalTrackParam *par = &t;
329 if (t.GetStatus() & AliESDtrack::kTRDbackup) {
330 par = t.GetOuterParam();
332 AliError("No backup info!");
336 Set(par->GetX(),par->GetAlpha(),par->GetParameter(),par->GetCovariance());
338 for (UInt_t i = 0; i < kMAXCLUSTERSPERTRACK; i++) {
343 for (Int_t i = 0; i < 3; i++) {
347 if ((t.GetStatus() & AliESDtrack::kTIME) == 0) {
353 t.GetIntegratedTimes(times);
354 SetIntegratedTimes(times);
355 SetIntegratedLength(t.GetIntegratedLength());
359 //____________________________________________________________________________
360 AliTRDtrack::~AliTRDtrack()
372 while ((icluster < kMAXCLUSTERSPERTRACK) && fClusters[icluster]) {
373 delete fClusters[icluster];
374 fClusters[icluster] = 0x0;
381 //____________________________________________________________________________
382 Float_t AliTRDtrack::StatusForTOF()
385 // Defines the status of the TOF extrapolation
388 // Definition of res ????
389 Float_t res = (0.2 + 0.8 * (fN / (fNExpected + 5.0)))
390 * (0.4 + 0.6 * fTracklets[5].GetN() / 20.0);
391 res *= (0.25 + 0.8 * 40.0 / (40.0 + fBudget[2]));
394 // This part of the function is never reached ????
395 // What defines these parameters ????
397 //if (GetNumberOfClusters() < 20) return 0;
399 // (fChi2/(Float_t(fN)) < 3)) return 3; // Gold
400 //if ((fNLast > 30) &&
401 // (fChi2Last/(Float_t(fNLast)) < 3)) return 3; // Gold
402 //if ((fNLast > 20) &&
403 // (fChi2Last/(Float_t(fNLast)) < 2)) return 3; // Gold
404 //if ((fNLast/(fNExpectedLast+3.0) > 0.8) &&
405 // (fChi2Last/Float_t(fNLast) < 5) &&
406 // (fNLast > 20)) return 2; // Silver
407 //if ((fNLast > 5) &&
408 // (((fNLast+1.0)/(fNExpectedLast+1.0)) > 0.8) &&
409 // (fChi2Last/(fNLast-5.0) < 6)) return 1;
415 //_____________________________________________________________________________
416 Int_t AliTRDtrack::Compare(const TObject *o) const
419 // Compares tracks according to their Y2 or curvature
422 AliTRDtrack *t = (AliTRDtrack *) o;
424 Double_t co = TMath::Abs(t->GetC());
425 Double_t c = TMath::Abs(GetC());
437 //_____________________________________________________________________________
438 void AliTRDtrack::CookdEdx(Double_t low, Double_t up)
441 // Calculates the truncated dE/dx within the "low" and "up" cuts.
444 // Array to sort the dEdx values according to amplitude
445 Float_t sorted[kMAXCLUSTERSPERTRACK];
448 // Require at least 10 clusters for a dedx measurement
449 if (fNdedx < 10) return;
451 // Can fdQdl be negative ????
452 for (Int_t i = 0; i < fNdedx; i++) {
453 sorted[i] = TMath::Abs(fdQdl[i]);
455 // Sort the dedx values by amplitude
456 Int_t *index = new Int_t[fNdedx];
457 TMath::Sort(fNdedx, sorted, index, kFALSE);
459 // Sum up the truncated charge between lower and upper bounds
460 Int_t nl = Int_t(low * fNdedx);
461 Int_t nu = Int_t( up * fNdedx);
462 for (Int_t i = nl; i <= nu; i++) {
463 fdEdx += sorted[index[i]];
465 fdEdx /= (nu - nl + 1.0);
471 //_____________________________________________________________________________
472 void AliTRDtrack::CookdEdxTimBin(const Int_t/* tid*/)
475 // Set fdEdxPlane and fTimBinPlane and also get the
476 // Time bin for Max. Cluster
479 // Prashant Shukla (shukla@physi.uni-heidelberg.de)
480 // Alexandru Bercuci (A.Bercuci@gsi.de)
483 Double_t maxcharge[AliESDtrack::kNPlane]; // max charge in chamber
484 // Number of clusters attached to track per chamber and slice
485 Int_t nCluster[AliESDtrack::kNPlane][AliESDtrack::kNSlice];
486 // Number of time bins in chamber
487 Int_t ntb = AliTRDcalibDB::Instance()->GetNumberOfTimeBins();
488 Int_t plane; // Plane of current cluster
489 Int_t tb; // Time bin of current cluster
490 Int_t slice; // Current slice
491 AliTRDcluster *cluster = 0x0; // Pointer to current cluster
493 // Reset class and local counters/variables
494 for (Int_t iPlane = 0; iPlane < AliESDtrack::kNPlane; iPlane++) {
495 fTimBinPlane[iPlane] = -1;
496 maxcharge[iPlane] = 0.;
497 for (Int_t iSlice = 0; iSlice < AliESDtrack::kNSlice; iSlice++) {
498 fdEdxPlane[iPlane][iSlice] = 0.;
499 nCluster[iPlane][iSlice] = 0;
503 // Start looping over clusters attached to this track
504 for (Int_t iClus = 0; iClus < GetNumberOfClusters(); iClus++) {
506 cluster = fClusters[iClus]; //(AliTRDcluster*)tracker->GetCluster(fIndex[iClus]);
507 if(!cluster) continue;
509 // Read info from current cluster
510 plane = AliTRDgeometry::GetPlane(cluster->GetDetector());
511 if (plane < 0 || plane >= AliESDtrack::kNPlane) {
512 AliError(Form("Wrong plane %d", plane));
516 tb = cluster->GetLocalTimeBin();
517 if ((tb == 0) || (tb >= ntb)) {
518 AliWarning(Form("time bin 0 or > %d in cluster %d", ntb, iClus));
519 AliInfo(Form("dQ/dl %f", fdQdl[iClus]));
523 slice = tb * AliESDtrack::kNSlice / ntb;
525 fdEdxPlane[plane][slice] += fdQdl[iClus];
526 if (fdQdl[iClus] > maxcharge[plane]) {
527 maxcharge[plane] = fdQdl[iClus];
528 fTimBinPlane[plane] = tb;
531 nCluster[plane][slice]++;
533 } // End of loop over cluster
535 // Normalize fdEdxPlane to number of clusters and set track segments
536 for (Int_t iPlane = 0; iPlane < AliESDtrack::kNPlane; iPlane++) {
537 for (Int_t iSlice = 0; iSlice < AliESDtrack::kNSlice; iSlice++) {
538 if (nCluster[iPlane][iSlice]) {
539 fdEdxPlane[iPlane][iSlice] /= nCluster[iPlane][iSlice];
546 //_____________________________________________________________________________
547 void AliTRDtrack::CookdEdxNN(Float_t *dedx){
549 // This function calcuates the input for the neural networks
550 // which are used for the PID.
552 Int_t ntb = AliTRDcalibDB::Instance()->GetNumberOfTimeBins();//number of time bins in chamber
553 Int_t plane; // plane of current cluster
554 Int_t tb; // time bin of current cluster
555 Int_t slice; // curent slice
556 AliTRDcluster *cluster = 0x0; // pointer to current cluster
557 const Int_t lMLPscale = 16000; // scaling of the MLP input to be smaller than 1
559 // Reset class and local contors/variables
560 for (Int_t iPlane = 0; iPlane < AliESDtrack::kNPlane; iPlane++){
561 for (Int_t iSlice = 0; iSlice < kNMLPslice; iSlice++) {
562 *(dedx + (kNMLPslice * iPlane) + iSlice) = 0.;
566 // start looping over clusters attached to this track
567 for (Int_t iClus = 0; iClus < GetNumberOfClusters(); iClus++) {
568 cluster = fClusters[iClus]; //(AliTRDcluster*)tracker->GetCluster(fIndex[iClus]);
569 if(!cluster) continue;
571 // Read info from current cluster
572 plane = AliTRDgeometry::GetPlane(cluster->GetDetector());
573 if (plane < 0 || plane >= AliESDtrack::kNPlane) {
574 AliError(Form("Wrong plane %d", plane));
578 tb = cluster->GetLocalTimeBin();
579 if(tb == 0 || tb >= ntb){
580 AliWarning(Form("time bin 0 or > %d in cluster %d", ntb, iClus));
581 AliInfo(Form("dQ/dl %f", fdQdl[iClus]));
585 slice = tb * kNMLPslice / ntb;
587 *(dedx+(kNMLPslice * plane) + slice) += fdQdl[iClus]/lMLPscale;
588 } // End of loop over cluster
593 //_____________________________________________________________________________
594 void AliTRDtrack::SetTrackSegmentDirMom(const Int_t plane)
597 // Set the momenta for a track segment in a given plane
602 AliError(Form("Trying to access out of range plane (%d)", plane));
606 fSnp[plane] = GetSnp();
607 fTgl[plane] = GetTgl();
610 fMom[plane] = TMath::Sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
614 //_____________________________________________________________________________
615 Float_t AliTRDtrack::GetTrackLengthPlane(Int_t plane) const
618 // Calculate the track length of a track segment in a given plane
621 if ((plane < 0) || (plane >= kNplane)) return 0.;
623 return (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick())
624 / TMath::Sqrt((1.0 - fSnp[plane]*fSnp[plane])
625 / (1.0 + fTgl[plane]*fTgl[plane]));
629 //_____________________________________________________________________________
630 Bool_t AliTRDtrack::CookPID(Int_t &pidQuality)
633 // This function calculates the PID probabilities based on TRD signals
635 // The method produces probabilities based on the charge
636 // and the position of the maximum time bin in each layer.
637 // The dE/dx information can be used as global charge or 2 to 3
638 // slices. Check AliTRDCalPID and AliTRDCalPIDRefMaker for the actual
642 // Alex Bercuci (A.Bercuci@gsi.de) 2nd May 2007
645 AliTRDcalibDB *calibration = AliTRDcalibDB::Instance();
647 AliError("No access to calibration data");
651 // Retrieve the CDB container class with the probability distributions
652 const AliTRDCalPID *pd = calibration->GetPIDObject(fPIDmethod == kNN ? 0 : 1);
654 AliError("No access to AliTRDCalPID");
658 // Calculate the input for the NN if fPIDmethod is kNN
659 Float_t ldEdxNN[AliTRDCalPID::kNPlane * kNMLPslice], *dedx = 0x0;
660 if(fPIDmethod == kNN) {
661 CookdEdxNN(&ldEdxNN[0]);
664 // Sets the a priori probabilities
665 for(int ispec=0; ispec<AliPID::kSPECIES; ispec++) {
666 fPID[ispec] = 1./AliPID::kSPECIES;
670 if(AliPID::kSPECIES != 5){
671 AliError("Probabilities array defined only for 5 values. Please modify !!");
677 Float_t length; // track segment length in chamber
679 // Skip tracks which have no TRD signal at all
680 if (fdEdx == 0.) return kFALSE;
682 for (Int_t iPlane = 0; iPlane < AliTRDgeometry::kNplan; iPlane++) {
684 length = (AliTRDgeometry::AmThick() + AliTRDgeometry::DrThick())/TMath::Sqrt((1. - fSnp[iPlane]*fSnp[iPlane]) / (1. + fTgl[iPlane]*fTgl[iPlane]));
687 if((fdEdxPlane[iPlane][0] + fdEdxPlane[iPlane][1] + fdEdxPlane[iPlane][2]) <= 0.
688 || fTimBinPlane[iPlane] == -1.) continue;
690 // this track segment has fulfilled all requierments
693 // Get the probabilities for the different particle species
694 for (Int_t iSpecies = 0; iSpecies < AliPID::kSPECIES; iSpecies++) {
697 dedx = fdEdxPlane[iPlane];
700 dedx = &ldEdxNN[iPlane*kNMLPslice];
703 fPID[iSpecies] *= pd->GetProbability(iSpecies, fMom[iPlane], dedx, length, iPlane);
706 if(pidQuality == 0) return kTRUE;
708 // normalize probabilities
709 Double_t probTotal = 0.;
710 for (Int_t iSpecies = 0; iSpecies < AliPID::kSPECIES; iSpecies++) probTotal += fPID[iSpecies];
712 if(probTotal <= 0.) {
713 AliWarning("The total probability over all species <= 0. This may be caused by some error in the reference histograms.");
716 for(Int_t iSpecies = 0; iSpecies < AliPID::kSPECIES; iSpecies++) fPID[iSpecies] /= probTotal;
722 //_____________________________________________________________________________
723 Bool_t AliTRDtrack::PropagateTo(Double_t xk, Double_t xx0, Double_t xrho)
726 // Propagates this track to a reference plane defined by "xk" [cm]
727 // correcting for the mean crossed material.
729 // "xx0" - thickness/rad.length [units of the radiation length]
730 // "xrho" - thickness*density [g/cm^2]
737 Double_t oldX = GetX();
738 Double_t oldY = GetY();
739 Double_t oldZ = GetZ();
741 Double_t bz = GetBz();
743 if (!AliExternalTrackParam::PropagateTo(xk,bz)) {
753 if (IsStartedTimeIntegral()) {
754 Double_t l2 = TMath::Sqrt((x-oldX)*(x-oldX) + (y-oldY)*(y-oldY) + (z-oldZ)*(z-oldZ));
755 Double_t crv = GetC();
756 if (TMath::Abs(l2*crv) > 0.0001) {
757 // Make correction for curvature if neccesary
758 l2 = 0.5 * TMath::Sqrt((x-oldX)*(x-oldX) + (y-oldY)*(y-oldY));
759 l2 = 2.0 * TMath::ASin(l2 * crv) / crv;
760 l2 = TMath::Sqrt(l2*l2 + (z-oldZ)*(z-oldZ));
766 if (!AliExternalTrackParam::CorrectForMeanMaterial(xx0,xrho,GetMass())) {
772 // Energy losses************************
773 Double_t p2 = (1.0 + GetTgl()*GetTgl()) / (GetSigned1Pt()*GetSigned1Pt());
774 Double_t beta2 = p2 / (p2 + GetMass()*GetMass());
775 if (beta2<1.0e-10 || (5940.0 * beta2/(1.0 - beta2 + 1.0e-10) - beta2) < 0.0) {
779 Double_t dE = 0.153e-3 / beta2
780 * (log(5940.0 * beta2/(1.0 - beta2 + 1.0e-10)) - beta2)
785 // Suspicious part - think about it ?
786 Double_t kinE = TMath::Sqrt(p2);
787 if (dE > 0.8*kinE) dE = 0.8 * kinE; //
788 if (dE < 0) dE = 0.0; // Not valid region for Bethe bloch
795 Double_t sigmade = 0.07 * TMath::Sqrt(TMath::Abs(dE)); // Energy loss fluctuation
796 Double_t sigmac2 = sigmade*sigmade*fC*fC*(p2+GetMass()*GetMass())/(p2*p2);
798 fCee += fX*fX * sigmac2;
807 //_____________________________________________________________________________
808 Bool_t AliTRDtrack::Update(const AliTRDcluster *c, Double_t chisq, Int_t index
812 // Assignes found cluster to the track and updates track information
815 Bool_t fNoTilt = kTRUE;
816 if (TMath::Abs(h01) > 0.003) {
820 // Add angular effect to the error contribution - MI
821 Float_t tangent2 = GetSnp()*GetSnp();
822 if (tangent2 < 0.90000) {
823 tangent2 = tangent2 / (1.0 - tangent2);
825 //Float_t errang = tangent2 * 0.04;
827 Double_t p[2] = {c->GetY(), c->GetZ() };
828 //Double_t cov[3] = {c->GetSigmaY2()+errang, 0.0, c->GetSigmaZ2()*100.0 };
829 Double_t sy2 = c->GetSigmaY2() * 4.0;
830 Double_t sz2 = c->GetSigmaZ2() * 4.0;
831 Double_t cov[3] = { sy2 + h01*h01*sz2, h01*(sy2-sz2), sz2 + h01*h01*sy2 };
833 if (!AliExternalTrackParam::Update(p,cov)) {
837 Int_t n = GetNumberOfClusters();
839 SetNumberOfClusters(n+1);
841 SetChi2(GetChi2()+chisq);
847 //_____________________________________________________________________________
848 Int_t AliTRDtrack::UpdateMI(AliTRDcluster *c, Double_t chisq, Int_t index
849 , Double_t h01, Int_t /*plane*/, Int_t tid)
852 // Assignes found cluster to the track and updates track information
855 Bool_t fNoTilt = kTRUE;
856 if (TMath::Abs(h01) > 0.003) {
860 // Add angular effect to the error contribution and make correction - MI
861 Double_t tangent2 = GetSnp()*GetSnp();
862 if (tangent2 < 0.90000){
863 tangent2 = tangent2 / (1.0-tangent2);
865 Double_t tangent = TMath::Sqrt(tangent2);
871 // Is the following still needed ????
874 // Double_t correction = 0*plane;
876 Double_t errang = tangent2*0.04; //
877 Double_t errsys =0.025*0.025*20; //systematic error part
880 if (c->GetNPads()==4) extend=2;
882 //if (c->GetNPads()==5) extend=3;
883 //if (c->GetNPads()==6) extend=3;
884 //if (c->GetQ()<15) return 1;
889 correction = corrector->GetCorrection(plane,c->GetLocalTimeBin(),tangent);
890 if (TMath::Abs(correction)>0){
892 errang = corrector->GetSigma(plane,c->GetLocalTimeBin(),tangent);
894 errang += tangent2*0.04;
899 //Double_t padlength = TMath::Sqrt(c->GetSigmaZ2()*12.);
902 Double_t dy=c->GetY() - GetY(), dz=c->GetZ() - GetZ();
903 printf("%e %e %e %e\n",dy,dz,padlength/2,h01);
907 Double_t p[2] = { c->GetY(), c->GetZ() };
908 //Double_t cov[3]={ (c->GetSigmaY2()+errang+errsys)*extend, 0.0, c->GetSigmaZ2()*10000.0 };
909 Double_t sy2 = c->GetSigmaY2() * 4.0;
910 Double_t sz2 = c->GetSigmaZ2() * 4.0;
911 Double_t cov[3] = { sy2 + h01*h01*sz2, h01*(sy2-sz2), sz2 + h01*h01*sy2 };
913 if (!AliExternalTrackParam::Update(p,cov)) {
917 // Register cluster to track
918 Int_t n = GetNumberOfClusters();
921 SetNumberOfClusters(n+1);
922 SetChi2(GetChi2() + chisq);
928 // //_____________________________________________________________________________
929 // Int_t AliTRDtrack::UpdateMI(const AliTRDtracklet &tracklet)
932 // // Assignes found tracklet to the track and updates track information
934 // // Can this be removed ????
937 // Double_t r00=(tracklet.GetTrackletSigma2()), r01=0., r11= 10000.;
938 // r00+=fCyy; r01+=fCzy; r11+=fCzz;
940 // Double_t det=r00*r11 - r01*r01;
941 // Double_t tmp=r00; r00=r11/det; r11=tmp/det; r01=-r01/det;
944 // Double_t dy=tracklet.GetY() - fY, dz=tracklet.GetZ() - fZ;
947 // Double_t s00 = tracklet.GetTrackletSigma2(); // error pad
948 // Double_t s11 = 100000; // error pad-row
949 // Float_t h01 = tracklet.GetTilt();
951 // // r00 = fCyy + 2*fCzy*h01 + fCzz*h01*h01+s00;
952 // r00 = fCyy + fCzz*h01*h01+s00;
953 // // r01 = fCzy + fCzz*h01;
956 // det = r00*r11 - r01*r01;
958 // tmp=r00; r00=r11/det; r11=tmp/det; r01=-r01/det;
960 // Double_t k00=fCyy*r00+fCzy*r01, k01=fCyy*r01+fCzy*r11;
961 // Double_t k10=fCzy*r00+fCzz*r01, k11=fCzy*r01+fCzz*r11;
962 // Double_t k20=fCey*r00+fCez*r01, k21=fCey*r01+fCez*r11;
963 // Double_t k30=fCty*r00+fCtz*r01, k31=fCty*r01+fCtz*r11;
964 // Double_t k40=fCcy*r00+fCcz*r01, k41=fCcy*r01+fCcz*r11;
967 // // k00=fCyy*r00+fCzy*(r01+h01*r00),k01=fCyy*r01+fCzy*(r11+h01*r01);
968 // // k10=fCzy*r00+fCzz*(r01+h01*r00),k11=fCzy*r01+fCzz*(r11+h01*r01);
969 // // k20=fCey*r00+fCez*(r01+h01*r00),k21=fCey*r01+fCez*(r11+h01*r01);
970 // // k30=fCty*r00+fCtz*(r01+h01*r00),k31=fCty*r01+fCtz*(r11+h01*r01);
971 // // k40=fCcy*r00+fCcz*(r01+h01*r00),k41=fCcy*r01+fCcz*(r11+h01*r01);
973 // //Update measurement
974 // Double_t cur=fC + k40*dy + k41*dz, eta=fE + k20*dy + k21*dz;
975 // // cur=fC + k40*dy + k41*dz; eta=fE + k20*dy + k21*dz;
976 // if (TMath::Abs(cur*fX-eta) >= 0.90000) {
977 // //Int_t n=GetNumberOfClusters();
978 // // if (n>4) cerr<<n<<" AliTRDtrack warning: Filtering failed !\n";
988 // fY += k00*dy + k01*dz;
989 // fZ += k10*dy + k11*dz;
991 // fT += k30*dy + k31*dz;
995 // //Update covariance
998 // Double_t oldyy = fCyy, oldzz = fCzz; //, oldee=fCee, oldcc =fCcc;
999 // Double_t oldzy = fCzy, oldey = fCey, oldty=fCty, oldcy =fCcy;
1000 // Double_t oldez = fCez, oldtz = fCtz, oldcz=fCcz;
1001 // //Double_t oldte = fCte, oldce = fCce;
1002 // //Double_t oldct = fCct;
1004 // fCyy-=k00*oldyy+k01*oldzy;
1005 // fCzy-=k10*oldyy+k11*oldzy;
1006 // fCey-=k20*oldyy+k21*oldzy;
1007 // fCty-=k30*oldyy+k31*oldzy;
1008 // fCcy-=k40*oldyy+k41*oldzy;
1010 // fCzz-=k10*oldzy+k11*oldzz;
1011 // fCez-=k20*oldzy+k21*oldzz;
1012 // fCtz-=k30*oldzy+k31*oldzz;
1013 // fCcz-=k40*oldzy+k41*oldzz;
1015 // fCee-=k20*oldey+k21*oldez;
1016 // fCte-=k30*oldey+k31*oldez;
1017 // fCce-=k40*oldey+k41*oldez;
1019 // fCtt-=k30*oldty+k31*oldtz;
1020 // fCct-=k40*oldty+k41*oldtz;
1023 // fCcc-=k40*oldcy+k41*oldcz;
1026 // //Int_t n=GetNumberOfClusters();
1027 // //fIndex[n]=index;
1028 // //SetNumberOfClusters(n+1);
1030 // //SetChi2(GetChi2()+chisq);
1031 // // cerr<<"in update: fIndex["<<fN<<"] = "<<index<<endl;
1037 //_____________________________________________________________________________
1038 Bool_t AliTRDtrack::Rotate(Double_t alpha, Bool_t absolute)
1041 // Rotates track parameters in R*phi plane
1042 // if absolute rotation alpha is in global system
1043 // otherwise alpha rotation is relative to the current rotation angle
1047 alpha -= GetAlpha();
1053 return AliExternalTrackParam::Rotate(GetAlpha()+alpha);
1057 //_____________________________________________________________________________
1058 Double_t AliTRDtrack::GetPredictedChi2(const AliTRDcluster *c, Double_t h01) const
1061 // Returns the track chi2
1064 Double_t p[2] = { c->GetY(), c->GetZ() };
1065 Double_t sy2 = c->GetSigmaY2() * 4.0;
1066 Double_t sz2 = c->GetSigmaZ2() * 4.0;
1067 Double_t cov[3] = { sy2 + h01*h01*sz2, h01*(sy2-sz2), sz2 + h01*h01*sy2 };
1069 return AliExternalTrackParam::GetPredictedChi2(p,cov);
1072 // Can the following be removed ????
1075 Bool_t fNoTilt = kTRUE;
1076 if(TMath::Abs(h01) > 0.003) fNoTilt = kFALSE;
1078 return (c->GetY() - GetY())*(c->GetY() - GetY())/c->GetSigmaY2();
1082 Double_t chi2, dy, r00, r01, r11;
1086 r00=c->GetSigmaY2();
1090 Double_t padlength = TMath::Sqrt(c->GetSigmaZ2()*12);
1092 r00=c->GetSigmaY2(); r01=0.; r11=c->GetSigmaZ2();
1093 r00+=fCyy; r01+=fCzy; r11+=fCzz;
1095 Double_t det=r00*r11 - r01*r01;
1096 if (TMath::Abs(det) < 1.e-10) {
1097 Int_t n=GetNumberOfClusters();
1098 if (n>4) cerr<<n<<" AliTRDtrack warning: Singular matrix !\n";
1101 Double_t tmp=r00; r00=r11; r11=tmp; r01=-r01;
1102 Double_t dy=c->GetY() - fY, dz=c->GetZ() - fZ;
1103 Double_t tiltdz = dz;
1104 if (TMath::Abs(tiltdz)>padlength/2.) {
1105 tiltdz = TMath::Sign(padlength/2,dz);
1110 chi2 = (dy*r00*dy + 2*r01*dy*dz + dz*r11*dz)/det;
1118 //_____________________________________________________________________________
1119 void AliTRDtrack::MakeBackupTrack()
1122 // Creates a backup track
1126 delete fBackupTrack;
1128 fBackupTrack = new AliTRDtrack(*this);
1132 //_____________________________________________________________________________
1133 Int_t AliTRDtrack::GetProlongation(Double_t xk, Double_t &y, Double_t &z)
1136 // Find a prolongation at given x
1137 // Return 0 if it does not exist
1140 Double_t bz = GetBz();
1142 if (!AliExternalTrackParam::GetYAt(xk,bz,y)) {
1145 if (!AliExternalTrackParam::GetZAt(xk,bz,z)) {
1153 //_____________________________________________________________________________
1154 Int_t AliTRDtrack::PropagateToX(Double_t xr, Double_t step)
1157 // Propagate track to given x position
1158 // Works inside of the 20 degree segmentation
1159 // (local cooordinate frame for TRD , TPC, TOF)
1161 // Material budget from geo manager
1169 const Double_t kAlphac = TMath::Pi()/9.0;
1170 const Double_t kTalphac = TMath::Tan(kAlphac*0.5);
1172 // Critical alpha - cross sector indication
1173 Double_t dir = (GetX() > xr) ? -1.0 : 1.0;
1176 for (Double_t x = GetX()+dir*step; dir*x < dir*xr; x += dir*step) {
1179 GetProlongation(x,y,z);
1180 xyz1[0] = x * TMath::Cos(GetAlpha()) + y * TMath::Sin(GetAlpha());
1181 xyz1[1] = x * TMath::Sin(GetAlpha()) - y * TMath::Cos(GetAlpha());
1184 AliTracker::MeanMaterialBudget(xyz0,xyz1,param);
1186 if ((param[0] > 0) &&
1188 PropagateTo(x,param[1],param[0]*param[4]);
1191 if (GetY() > GetX()*kTalphac) {
1194 if (GetY() < -GetX()*kTalphac) {
1206 //_____________________________________________________________________________
1207 Int_t AliTRDtrack::PropagateToR(Double_t r,Double_t step)
1210 // Propagate track to the radial position
1211 // Rotation always connected to the last track position
1219 Double_t radius = TMath::Sqrt(GetX()*GetX() + GetY()*GetY());
1221 Double_t dir = (radius > r) ? -1.0 : 1.0;
1223 for (Double_t x = radius+dir*step; dir*x < dir*r; x += dir*step) {
1226 Double_t alpha = TMath::ATan2(xyz0[1],xyz0[0]);
1227 Rotate(alpha,kTRUE);
1229 GetProlongation(x,y,z);
1230 xyz1[0] = x * TMath::Cos(alpha) + y * TMath::Sin(alpha);
1231 xyz1[1] = x * TMath::Sin(alpha) - y * TMath::Cos(alpha);
1234 AliTracker::MeanMaterialBudget(xyz0,xyz1,param);
1235 if (param[1] <= 0) {
1236 param[1] = 100000000;
1238 PropagateTo(x,param[1],param[0]*param[4]);
1243 Double_t alpha = TMath::ATan2(xyz0[1],xyz0[0]);
1244 Rotate(alpha,kTRUE);
1246 GetProlongation(r,y,z);
1247 xyz1[0] = r * TMath::Cos(alpha) + y * TMath::Sin(alpha);
1248 xyz1[1] = r * TMath::Sin(alpha) - y * TMath::Cos(alpha);
1251 AliTracker::MeanMaterialBudget(xyz0,xyz1,param);
1253 if (param[1] <= 0) {
1254 param[1] = 100000000;
1256 PropagateTo(r,param[1],param[0]*param[4]);
1262 //_____________________________________________________________________________
1263 Int_t AliTRDtrack::GetSector() const
1266 // Return the current sector
1269 return Int_t(TVector2::Phi_0_2pi(GetAlpha()) / AliTRDgeometry::GetAlpha())
1270 % AliTRDgeometry::kNsect;
1274 //_____________________________________________________________________________
1275 void AliTRDtrack::SetSampledEdx(Float_t q, Int_t i)
1278 // The sampled energy loss
1281 Double_t s = GetSnp();
1282 Double_t t = GetTgl();
1283 q *= TMath::Sqrt((1.0 - s*s) / (1.0 + t*t));
1288 //_____________________________________________________________________________
1289 void AliTRDtrack::SetSampledEdx(Float_t q)
1292 // The sampled energy loss
1295 Double_t s = GetSnp();
1296 Double_t t = GetTgl();
1297 q *= TMath::Sqrt((1.0 - s*s) / (1.0 + t*t));
1303 //_____________________________________________________________________________
1304 Double_t AliTRDtrack::GetBz() const
1307 // Returns Bz component of the magnetic field (kG)
1310 if (AliTracker::UniformField()) {
1311 return AliTracker::GetBz();
1316 return AliTracker::GetBz(r);