2 // **************************************************************************
3 // This file is property of and copyright by the ALICE ITSU Project *
4 // ALICE Experiment at CERN, All rights reserved. *
6 // Primary Author: Maximiliano Puccio <maximiliano.puccio@cern.ch> *
7 // for the ITS Upgrade project *
9 // Permission to use, copy, modify and distribute this software and its *
10 // documentation strictly for non-commercial purposes is hereby granted *
11 // without fee, provided that the above copyright notice appears in all *
12 // copies and that both the copyright notice and this permission notice *
13 // appear in the supporting documentation. The authors make no claims *
14 // about the suitability of this software for any purpose. It is *
15 // provided "as is" without express or implied warranty. *
17 //***************************************************************************
19 #include "AliITSUCATracker.h"
28 #include <Riostream.h>
30 #include "AliESDEvent.h"
31 #include "AliESDtrack.h"
34 #include "AliITSUAux.h"
35 #include "AliITSUClusterPix.h"
36 #include "AliITSURecoDet.h"
37 #include "AliITSUReconstructor.h"
38 #include "AliITSUTrackCooked.h"
48 ClassImp(AliITSUCATracker)
51 // tolerance for layer on-surface check
52 const Double_t AliITSUCATracker::fgkChi2Cut = 600.f;
53 const int AliITSUCATracker::fgkNumberOfIterations = 2;
54 const float AliITSUCATracker::fgkR[7] = {2.33959,3.14076,3.91924,19.6213,24.5597,34.388,39.3329};
56 const float kmaxDCAxy[5] = {0.05f,0.04f,0.05f,0.2f,0.4f};
57 const float kmaxDCAz[5] = {0.2f,0.4f,0.5f,0.6f,3.f};
58 const float kmaxDN[4] = {0.002f,0.009f,0.002f,0.005f};
59 const float kmaxDP[4] = {0.008f,0.0025f,0.003f,0.0035f};
60 const float kmaxDZ[6] = {0.1f,0.1f,0.3f,0.3f,0.3f,0.3f};
61 const float kDoublTanL = 0.025;
62 const float kDoublPhi = 0.14;
64 const float kmaxDCAxy1[5] = /*{1.f,0.5,0.5,1.7,3.};/*/{1.f,0.4f,0.4f,1.5f,3.f};
65 const float kmaxDCAz1[5] = /*{2.f,0.8,0.8,3.,5.};/*/{1.f,0.4f,0.4f,1.5f,3.f};
66 const float kmaxDN1[4] = /*{0.006f,0.0045f,0.01f,0.04f};/*/{0.005f,0.0035f,0.009f,0.03f};
67 const float kmaxDP1[4] = /*{0.04f,0.01f,0.012f,0.014f};/*/{0.02f,0.005f,0.006f,0.007f};
68 const float kmaxDZ1[6] = /*{1.5f,1.5f,2.f,2.f,2.f,2.f};/*/{1.f,1.f,1.5f,1.5f,1.5f,1.5f};
69 const float kDoublTanL1 = /*0.12f;/*/0.05f;
70 const float kDoublPhi1 = /*0.4f;/*/0.2f;
72 //__________________________________________________________________________________________________
73 static inline float invsqrt(float _x)
76 // The function calculates fast inverse sqrt. Google for 0x5f3759df.
77 // Credits to ALICE HLT Project
80 union { float f; int i; } x = { _x };
81 const float xhalf = 0.5f * x.f;
82 x.i = 0x5f3759df - ( x.i >> 1 );
83 x.f = x.f * ( 1.5f - xhalf * x.f * x.f );
87 //__________________________________________________________________________________________________
88 static inline float Curvature(float x1, float y1, float x2, float y2, float x3, float y3)
91 // Initial approximation of the track curvature
93 // return - 2.f * ((x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1))
94 // * invsqrt(((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) *
95 // ((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3)) *
96 // ((x3 - x1) * (x3 - x1) + (y3 - y1) * (y3 - y1)));
98 //calculates the curvature of track
99 float den = (x3 - x1) * (y2 - y1) - (x2 - x1) * (y3 - y1);
100 if(den * den < 1e-32) return 0.f;
101 float a = ((y3-y1)*(x2*x2+y2*y2-x1*x1-y1*y1)-(y2-y1)*(x3*x3+y3*y3-x1*x1-y1*y1))/den;
102 if((y2 - y1) * (y2 - y1) < 1e-32) return 0.f;
103 float b = -(x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1 + a * (x2 - x1)) / (y2 - y1);
104 float c = -x1 * x1 - y1 * y1 - a * x1 - b * y1;
107 if((a * a + b * b - 4 * c) < 0) return 0.f;
108 float rad = TMath::Sqrt(a * a + b * b - 4 * c) / 2.f;
109 if(rad * rad < 1e-32) return 1e16;
111 if((x1 > 0.f && y1 > 0.f && x1 < xc)) rad *= -1.f;
112 if((x1 < 0.f && y1 > 0.f && x1 < xc)) rad *= -1.f;
113 // if((x1<0 && y1<0 && x1<xc)) rad*=-1;
114 // if((x1>0 && y1<0 && x1<xc)) rad*=-1;
120 //__________________________________________________________________________________________________
121 static inline float TanLambda(float x1, float y1, float x2, float y2, float z1, float z2)
124 // Initial approximation of the tangent of the track dip angle
126 return (z1 - z2) * invsqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
129 //__________________________________________________________________________________________________
130 //static inline float XCenterOfCurvature(float x1, float y1, float x2, float y2, float x3, float y3)
133 // // Initial approximation of the x-coordinate of the center of curvature
136 // const float k1 = (y2 - y1) / (x2 - x1), k2 = (y3 - y2) / (x3 - x2);
137 // return TMath::Abs(k2 - k1) > kAlmost0 ?
138 // 0.5f * (k1 * k2 * (y1 - y3) + k2 * (x1 + x2) - k1 * (x2 + x3)) / (k2 - k1) : 1e12f;
141 //__________________________________________________________________________________________________
142 static inline bool CompareAngles(float alpha, float beta, float tolerance)
144 const float delta = TMath::Abs(alpha - beta);
145 return (delta < tolerance || TMath::Abs(delta - TMath::TwoPi()) < tolerance);
148 //__________________________________________________________________________________________________
149 AliITSUCATracker::AliITSUCATracker(AliITSUReconstructor* rec) : AliITSUTrackerGlo(rec)
159 ,fChi2Cut(fgkChi2Cut)
174 // This default constructor needs to be provided
175 for (int i = 0; i < 4; ++i)
177 fCandidates[i] = new TClonesArray("AliITSUTrackCooked",100000);
181 for (int i = 0; i < 6; ++i)
183 fGDZ[i] = new TH1F(Form("DGZ%i",i),Form("DZ%i;#Deltaz;Entries",i),500,0.f,5.f);
184 fGDXY[i] = new TH1F(Form("DGPhi%i",i),Form("#Delta#Phi%i;#DeltaPhi;Entries",i),500,0.f,TMath::TwoPi());
185 fFDZ[i] = new TH1F(Form("DFZ%i",i),Form("DZ%i;#Deltaz;Entries",i),500,0.f,5.f);
186 fFDXY[i] = new TH1F(Form("DFPhi%i",i),Form("#Delta#Phi%i;#Delta#Phi;Entries",i),500,0.f,TMath::TwoPi());
188 for (int i = 0; i < 5; ++i)
190 fGDCAZ[i] = new TH1F(Form("DCAGZ%i",i),Form("DCAZ%i;#Deltaz;Entries",i),500,0.f,5.f);
191 fGDCAXY[i] = new TH1F(Form("DCAGXY%i",i),Form("DCAXY%i;#Deltar;Entries",i),500,0.f,5.f);
192 fFDCAZ[i] = new TH1F(Form("DCAFZ%i",i),Form("DCAZ%i;#Deltaz;Entries",i),500,0.f,5.f);
193 fFDCAXY[i] = new TH1F(Form("DCAFXY%i",i),Form("DCAXY%i;#Deltar;Entries",i),500,0.f,5.f);
195 for(int i = 0; i < 4; ++i)
197 fGoodCombChi2[i] = new TH1F(Form("goodcombchi2%i",i),Form("%i;#chi^{2};Entries",i),2000,0,0.1);
198 fFakeCombChi2[i] = new TH1F(Form("fakecombchi2%i",i),Form("%i;#chi^{2};Entries",i),2000,0,0.1);
199 fGoodCombN[i] = new TH1F(Form("goodcombn%i",i),Form("%i;#Deltan;Entries",i),300,0.f,0.03f);
200 fFakeCombN[i] = new TH1F(Form("fakecombn%i",i),Form("%i;#Deltan;Entries",i),300,0.f,0.03f);
202 fGoodCombChi2[4] = new TH1F("goodcomb4",";#chi^{2};Entries",200,0,500);
203 fFakeCombChi2[4] = new TH1F("fakecomb4",";#chi^{2};Entries",200,0,500);
204 fTan = new TH1F("tan","tan",2500,0,0.5);
205 fTanF = new TH1F("tanF","tanF",2500,0,0.5);
206 fPhi = new TH1F("phi","phi",2500,0,TMath::Pi());
207 fPhiF = new TH1F("phi","phiF",2500,0,TMath::Pi());
208 fNEntries = new TH1F("nentries","nentries",2001,-0.5,2000.5);
212 //__________________________________________________________________________________________________
213 AliITSUCATracker::~AliITSUCATracker()
216 for (int i = 0; i < 4; ++i)
219 delete fCandidates[i];
222 // // Just cut and paste from the constructor
223 // for (int i = 0; i < 6; ++i)
230 // for (int i = 0; i < 5; ++i)
233 // delete fGDCAXY[i];
235 // delete fFDCAXY[i];
237 // for(int i = 0; i < 4; ++i)
239 // delete fGoodCombChi2[i];
240 // delete fFakeCombChi2[i];
241 // delete fGoodCombN[i];
242 // delete fFakeCombN[i];
244 // delete fGoodCombChi2[4];
245 // delete fFakeCombChi2[4];
254 //__________________________________________________________________________________________________
255 bool AliITSUCATracker::CellParams(int l, ClsInfo_t* c1, ClsInfo_t* c2, ClsInfo_t* c3,
256 float &curv, float n[3])
258 // Calculation of cell params and filtering using a DCA cut wrt beam line position.
259 // The hit are mapped on a paraboloid space: there a circle is described as plane.
260 // The parameter n of the cells is the normal vector to the plane describing the circle in the
264 const float mHit0[3] = {c1->x, c1->y, c1->r * c1->r};
265 const float mHit1[3] = {c2->x, c2->y, c2->r * c2->r};
266 const float mHit2[3] = {c3->x, c3->y, c3->r * c3->r};
267 // Computing the deltas
268 const float mD10[3] = {mHit1[0] - mHit0[0],mHit1[1] - mHit0[1],mHit1[2] - mHit0[2]};
269 const float mD20[3] = {mHit2[0] - mHit0[0],mHit2[1] - mHit0[1],mHit2[2] - mHit0[2]};
270 // External product of the deltas -> n
271 n[0] = (mD10[1] * mD20[2]) - (mD10[2] * mD20[1]);
272 n[1] = (mD10[2] * mD20[0]) - (mD10[0] * mD20[2]);
273 n[2] = (mD10[0] * mD20[1]) - (mD10[1] * mD20[0]);
275 const float norm = TMath::Sqrt((n[0] * n[0]) + (n[1] * n[1]) + (n[2] * n[2]));
276 if (norm < 1e-20f || fabs(n[2]) < 1e-20f)
281 // Center of the circle
282 const float c[2] = {-0.5f * n[0] / n[2], -0.5f * n[1] / n[2]};
284 const float k = - n[0] * mHit1[0] - n[1] * mHit1[1] - n[2] * mHit1[2];
285 // Radius of the circle
286 curv = TMath::Sqrt((1.f - n[2] * n[2] - 4.f * k * n[2]) / (4.f * n[2] * n[2]));
287 // Distance of closest approach to the beam line
288 const float dca = fabs(curv - sqrt(c[0] * c[0] + c[1] * c[1]));
290 if (dca > fCDCAxy[l]) {
295 fGDCAXY[l]->Fill(dca);
297 fFDCAXY[l]->Fill(dca);
305 //__________________________________________________________________________________________________
306 void AliITSUCATracker::CellsTreeTraversal(vector<AliITSUCARoad> &roads,
307 const int &iD, const int &doubl)
310 // Each cells contains a list of neighbours. Each neighbour has presumably other neighbours.
311 // This chain of neighbours is, as a matter of fact, a tree and this function goes recursively
312 // through it. This function implements a depth first tree browsing.
315 if (doubl < 0) return;
317 // [1] add current cell to current cell
318 roads.back().AddElement(doubl,iD);
319 // We want the right number of elements in the roads also in the case of multiple neighbours
320 const int currentN = roads.back().N;
322 // [2] loop on the neighbours of the current cell
323 for (size_t iN = 0; iN < fCells[doubl][iD].NumberOfNeighbours(); ++iN)
325 const int currD = doubl - 1;
326 const int neigh = fCells[doubl][iD](iN);
328 // [3] for each neighbour one road
331 roads.push_back(roads.back());
332 roads.back().N = currentN;
334 // [4] play this game again until the end of the road
335 CellsTreeTraversal(roads,neigh,currD);
338 fCells[doubl][iD].SetLevel(0u); // Level = -1
341 //__________________________________________________________________________________________________
342 Int_t AliITSUCATracker::Clusters2Tracks(AliESDEvent *event)
344 // This is the main tracking function
345 // The clusters must already be loaded
348 AliITSUTrackerGlo::Clusters2Tracks(event);
349 for (int iL = 0; iL < 7; ++iL) {
350 for (int iC = 0; iC < fLayer[iL].GetNClusters(); ++iC)
351 if (fLayer[iL].GetClusterUnSorted(iC)->IsClusterUsed())
352 fUsedClusters[iL][iC] = true;
356 int ntrk = 0, ngood = 0;
357 for (int iteration = 0; iteration < fgkNumberOfIterations; ++iteration)
360 fCandidates[0]->Clear();
361 fCandidates[1]->Clear();
362 fCandidates[2]->Clear();
363 fCandidates[3]->Clear();
365 MakeCells(iteration);
366 FindTracksCA(iteration);
368 for (int iL = 3; iL >= 0; --iL)
370 const int nCand = fCandidates[iL]->GetEntries();
374 for (int iC = 0; iC < nCand; ++iC)
376 AliITSUTrackCooked *tr = (AliITSUTrackCooked*)fCandidates[iL]->At(iC);
377 chi2[iC] = tr->GetChi2();//(RefitTrack(tr,clInfo,0.,-1));
382 TMath::Sort(nCand,chi2,index,false);
384 for (int iUC = 0; iUC < nCand; ++iUC)
386 const int iC = index[iUC];
392 AliITSUTrackCooked *tr = (AliITSUTrackCooked*)fCandidates[iL]->At(iC);
394 bool sharingCluster = false;
395 for (int k = 0; k < tr->GetNumberOfClusters(); ++k)
397 const int layer = (tr->GetClusterIndex(k) & 0xf0000000) >> 28;
398 const int idx = (tr->GetClusterIndex(k) & 0x0fffffff);
399 if (fUsedClusters[layer][idx])
401 sharingCluster = true;
409 for (int k = 0; k < tr->GetNumberOfClusters(); ++k)
411 const int layer = (tr->GetClusterIndex(k) & 0xf0000000) >> 28;
412 const int idx = (tr->GetClusterIndex(k) & 0x0fffffff);
413 fUsedClusters[layer][idx] = true;
416 AliESDtrack outTrack;
419 if(tr->GetLabel() >= 0)
423 fGoodCombChi2[4]->Fill(chi2[iC] / (4 + iL));
427 fFakeCombChi2[4]->Fill(chi2[iC] / (4 + iL));
431 outTrack.UpdateTrackParams(tr,AliESDtrack::kITSin);
432 outTrack.SetLabel(tr->GetLabel());
433 event->AddTrack(&outTrack);
437 Info("Clusters2Tracks","Reconstructed tracks: %d",ntrk);
439 Info("Clusters2Tracks","Good tracks/reconstructed: %f",Float_t(ngood)/ntrk);
444 //__________________________________________________________________________________________________
445 void AliITSUCATracker::FindTracksCA(int iteration)
447 // Main pattern recognition routine. It has 4 steps (planning to split in different methods)
448 // 1. Tracklet finding (using vertex position)
449 // 2. Tracklet association, cells building
450 // 3. Handshake between neighbour cells
451 // 4. Candidates ("roads") finding and fitting
453 // Road finding and fitting. The routine starts from cells with level 5 since they are the head
454 // of a full road (candidate with 7 points). Minimum level is 2, so candidates at the end have
455 // at least 4 points.
456 const int itLevelLimit[3] = {4, 4, 1};
457 for (int level = 5; level > itLevelLimit[iteration]; --level) {
458 vector<AliITSUCARoad> roads;
459 // Road finding. For each cell at level $(level) a loop on their neighbours to start building
461 for (int iCL = 4; iCL >= level - 1; --iCL) {
462 for (size_t iCell = 0; iCell < fCells[iCL].size(); ++iCell) {
463 if (fCells[iCL][iCell].GetLevel() != level)
467 // [1] Add current cell to road
468 roads.push_back(AliITSUCARoad(iCL,iCell));
469 // [2] Loop on current cell neighbours
470 for(size_t iN = 0; iN < fCells[iCL][iCell].NumberOfNeighbours(); ++iN) {
471 const int currD = iCL - 1;
472 const int neigh = fCells[iCL][iCell](iN);
473 // [3] if more than one neighbour => more than one road, one road for each neighbour
476 roads.push_back(AliITSUCARoad(iCL,iCell));
478 // [4] Essentially the neighbour became the current cell and then go to [1]
479 CellsTreeTraversal(roads,neigh,currD);
481 fCells[iCL][iCell].SetLevel(0u); // Level = -1
486 for (size_t iR = 0; iR < roads.size(); ++iR)
488 if (roads[iR].N != level)
490 AliITSUTrackCooked tr;
491 int first = -1,last = -1;
492 ClsInfo_t *cl0 = 0x0,*cl1 = 0x0,*cl2 = 0x0;
493 for(int i = 0; i < 5; ++i)
495 if (roads[iR][i] < 0)
500 cl0 = fLayer[i][fCells[i][roads[iR][i]].x()];
501 tr.SetClusterIndex(i,fLayer[i][fCells[i][roads[iR][i]].x()]->index);
502 tr.SetClusterIndex(i + 1,fLayer[i + 1][fCells[i][roads[iR][i]].y()]->index);
505 tr.SetClusterIndex(i + 2,fLayer[i + 2][fCells[i][roads[iR][i]].z()]->index);
508 AliITSUClusterPix* c = fLayer[last + 2].GetClusterSorted(fCells[last][roads[iR][last]].z());
509 cl2 = fLayer[last + 2][fCells[last][roads[iR][last]].z()];
510 first = (last + first) / 2;
511 cl1 = fLayer[first + 1][fCells[first][roads[iR][first]].y()];
512 // Init track parameters
513 double cv = Curvature(cl0->x,cl0->y,cl1->x,cl1->y,cl2->x,cl2->y);
514 double tgl = TanLambda(cl0->x,cl0->y,cl2->x,cl2->y,cl0->z,cl2->z);
516 AliITSUCATrackingStation::ITSDetInfo_t det = fLayer[last + 2].GetDetInfo(cl2->detid);
517 double x = det.xTF + c->GetX(); // I'd like to avoit using AliITSUClusterPix...
518 double alp = det.phiTF;
519 double par[5] = {c->GetY(),c->GetZ(),0,tgl,cv};
527 tr.Set(x,alp,par,cov);
528 AliITSUTrackCooked tt(tr);
530 if (RefitAt(2.1, &tt, &tr))
531 new((*fCandidates[level - 2])[fCandidates[level - 2]->GetEntriesFast()]) AliITSUTrackCooked(tt);
536 //__________________________________________________________________________________________________
537 inline AliCluster* AliITSUCATracker::GetCluster(Int_t index) const
539 const Int_t l=(index & 0xf0000000) >> 28;
540 const Int_t c=(index & 0x0fffffff);
541 return (AliCluster*)fLayer[l].GetClusterUnSorted(c) ;
544 //__________________________________________________________________________________________________
545 Double_t AliITSUCATracker::GetMaterialBudget(const double* pnt0,const double* pnt1, double& x2x0,
549 if (fUseMatLUT && fMatLUT) {
550 double d = fMatLUT->GetMatBudget(pnt0,pnt1,par);
551 x2x0 = par[AliITSUMatLUT::kParX2X0];
552 rhol = par[AliITSUMatLUT::kParRhoL];
556 MeanMaterialBudget(pnt0,pnt1,par);
558 rhol = par[0]*par[4];
563 //__________________________________________________________________________________________________
564 Int_t AliITSUCATracker::LoadClusters(TTree *cluTree)
566 // This function reads the ITSU clusters from the tree,
567 // sort them, distribute over the internal tracker arrays, etc
569 AliITSUTrackerGlo::LoadClusters(cluTree); // === fITS->LoadClusters(cluTree);
570 if (fSAonly) fITS->ProcessClusters();
572 // I consider a single vertex event for the moment.
573 //TODO: pile-up (trivial here), fast reco of primary vertices (not so trivial)
574 double vertex[3] = {GetX(),GetY(),GetZ()};
575 for (int iL = 0; iL < 7; ++iL) {
576 fLayer[iL].Init(fITS->GetLayerActive(iL),fITS->GetGeom());
577 AliVertex v(vertex,1,1);
578 fLayer[iL].SortClusters(&v);
579 fUsedClusters[iL].resize(fLayer[iL].GetNClusters(),false);
584 //__________________________________________________________________________________________________
585 void AliITSUCATracker::MakeCells(int iteration)
588 unsigned int numberOfGoodDoublets = 0, totalNumberOfDoublets = 0;
589 unsigned int numberOfGoodCells = 0, totalNumberOfCells = 0;
590 unsigned int cellsCombiningSuccesses = 0, cellsWrongCombinations = 0;
594 if (iteration >= 1) {
598 for (int i = 0; i < 5; ++i)
600 for (int i = 0; i < 6; ++i)
601 fDoublets[i].clear();
604 // Trick to speed up the navigation of the doublets array. The lookup table is build like:
606 // where n is the index inside fDoublets[l+1] of the first doublets that uses the point
609 for (int iL = 0; iL < 6; ++iL) {
611 dLUT[iL].resize(fLayer[iL + 1].GetNClusters(),-1);
613 for (int iC = 0; iC < fLayer[iL].GetNClusters(); ++iC) {
614 ClsInfo_t* cls = fLayer[iL].GetClusterInfo(iC);
615 if (fUsedClusters[iL][cls->index]) {
618 const float tanL = (cls->z - GetZ()) / cls->r;
619 const float extz = tanL * (fgkR[iL + 1] - cls->r) + cls->z;
620 const int nClust = fLayer[iL + 1].SelectClusters(extz - 2 * fCZ, extz + 2 * fCZ,
621 cls->phi - fCPhi, cls->phi + fCPhi);
624 for (int iC2 = 0; iC2 < nClust; ++iC2) {
625 const int iD2 = fLayer[iL + 1].GetNextClusterInfoID();
626 ClsInfo_t* cls2 = fLayer[iL + 1].GetClusterInfo(iD2);
627 if (fUsedClusters[iL + 1][cls2->index]) {
630 const float dz = tanL * (cls2->r - cls->r) + cls->z - cls2->z;
631 if (TMath::Abs(dz) < fCDZ[iL] && CompareAngles(cls->phi, cls2->phi, fCPhi)) {
632 if (first && iL > 0) {
633 dLUT[iL - 1][iC] = fDoublets[iL].size();
636 const float dTanL = (cls->z - cls2->z) / (cls->r - cls2->r);
637 const float phi = TMath::ATan2(cls->y - cls2->y, cls->x - cls2->x);
638 fDoublets[iL].push_back(Doublets(iC,iD2,dTanL,phi));
640 if (fLayer[iL].GetClusterSorted(iC)->GetLabel(0) ==
641 fLayer[iL + 1].GetClusterSorted(iD2)->GetLabel(0) &&
642 fLayer[iL].GetClusterSorted(iC)->GetLabel(0) > 0) {
643 numberOfGoodDoublets++;
645 fGDXY[iL]->Fill(fabs(cls->phi - cls2->phi));
648 fFDXY[iL]->Fill(fabs(cls->phi - cls2->phi));
650 totalNumberOfDoublets++;
654 fLayer[iL + 1].ResetFoundIterator();
658 // Trick to speed up the navigation of the cells array. The lookup table is build like:
660 // where n is the index inside fCells[l+1] of the first cells that uses the doublet
663 for (int iD = 0; iD < 5; ++iD)
666 tLUT[iD].resize(fDoublets[iD + 1].size(),0);
668 for (size_t iD0 = 0; iD0 < fDoublets[iD].size(); ++iD0)
670 const int idx = fDoublets[iD][iD0].y;
672 if (dLUT[iD][idx] == -1) continue;
673 for (size_t iD1 = dLUT[iD][idx]; idx == fDoublets[iD + 1][iD1].x;++iD1)
675 if (TMath::Abs(fDoublets[iD][iD0].tanL - fDoublets[iD + 1][iD1].tanL) < fCDTanL &&
676 TMath::Abs(fDoublets[iD][iD0].phi - fDoublets[iD + 1][iD1].phi) < fCDPhi) {
677 const float tan = 0.5f * (fDoublets[iD][iD0].tanL + fDoublets[iD + 1][iD1].tanL);
678 const float extz = -tan * fLayer[iD][fDoublets[iD][iD0].x]->r +
679 fLayer[iD][fDoublets[iD][iD0].x]->z;
680 if (fabs(extz - GetZ()) < fCDCAz[iD]) {
682 fGood = (fLayer[iD].GetClusterSorted(fDoublets[iD][iD0].x)->GetLabel(0) ==
683 fLayer[iD + 1].GetClusterSorted(fDoublets[iD][iD0].y)->GetLabel(0) &&
684 fLayer[iD].GetClusterSorted(fDoublets[iD][iD0].x)->GetLabel(0) ==
685 fLayer[iD + 2].GetClusterSorted(fDoublets[iD + 1][iD1].y)->GetLabel(0) &&
686 fLayer[iD].GetClusterSorted(fDoublets[iD][iD0].x)->GetLabel(0) > 0);
689 if (CellParams(iD,fLayer[iD][fDoublets[iD][iD0].x],fLayer[iD + 1][fDoublets[iD][iD0].y],
690 fLayer[iD + 2][fDoublets[iD + 1][iD1].y],curv,n)) {
691 if (first && iD > 0) {
692 tLUT[iD - 1][iD0] = fCells[iD].size();
695 fCells[iD].push_back(AliITSUCACell(fDoublets[iD][iD0].x,fDoublets[iD][iD0].y,
696 fDoublets[iD + 1][iD1].y,iD0,iD1,curv,n));
699 fTan->Fill(TMath::Abs(fDoublets[iD][iD0].tanL - fDoublets[iD + 1][iD1].tanL));
700 fPhi->Fill(TMath::Abs(fDoublets[iD][iD0].phi - fDoublets[iD + 1][iD1].phi));
701 fGDCAZ[iD]->Fill(fabs(extz-GetZ()));
704 fTanF->Fill(TMath::Abs(fDoublets[iD][iD0].tanL - fDoublets[iD + 1][iD1].tanL));
705 fPhiF->Fill(TMath::Abs(fDoublets[iD][iD0].phi - fDoublets[iD + 1][iD1].phi));
706 fFDCAZ[iD]->Fill(fabs(extz - GetZ()));
708 totalNumberOfCells++;
717 // Adjacent cells: cells that share 2 points. In the following code adjacent cells are combined.
718 // If they meet some requirements (~ same curvature, ~ same n) the innermost cell id is added
719 // to the list of neighbours of the outermost cell. When the cell is added to the neighbours of
720 // the outermost cell the "level" of the latter is set to the level of the innermost one + 1.
721 // ( only if $(level of the innermost) + 1 > $(level of the outermost) )
722 for (int iD = 0; iD < 4; ++iD) {
723 for (size_t c0 = 0; c0 < fCells[iD].size(); ++c0) {
724 const int idx = fCells[iD][c0].d1();
725 for (size_t c1 = tLUT[iD][idx]; idx == fCells[iD + 1][c1].d0(); ++c1) {
727 fGood = (fLayer[iD].GetClusterSorted(fCells[iD][c0].x())->GetLabel(0) ==
728 fLayer[iD + 1].GetClusterSorted(fCells[iD][c0].y())->GetLabel(0) &&
729 fLayer[iD + 1].GetClusterSorted(fCells[iD][c0].y())->GetLabel(0) ==
730 fLayer[iD + 2].GetClusterSorted(fCells[iD][c0].z())->GetLabel(0) &&
731 fLayer[iD + 2].GetClusterSorted(fCells[iD][c0].z())->GetLabel(0) ==
732 fLayer[iD + 3].GetClusterSorted(fCells[iD + 1][c1].z())->GetLabel(0) &&
733 fLayer[iD].GetClusterSorted(fCells[iD][c0].x())->GetLabel(0) > 0);
735 float *n0 = fCells[iD][c0].GetN();
736 float *n1 = fCells[iD + 1][c1].GetN();
737 const float dn2 = ((n0[0] - n1[0]) * (n0[0] - n1[0]) + (n0[1] - n1[1]) * (n0[1] - n1[1]) +
738 (n0[2] - n1[2]) * (n0[2] - n1[2]));
739 const float dp = fabs(fCells[iD][c0].GetCurvature() - fCells[iD + 1][c1].GetCurvature());
740 if (dn2 < fCDN[iD] && dp < fCDP[iD]) {
742 assert(fCells[iD + 1][c1].Combine(fCells[iD][c0], c0));
744 fGoodCombChi2[iD]->Fill(dp);
745 fGoodCombN[iD]->Fill(dn2);
746 cellsCombiningSuccesses++;
748 fFakeCombChi2[iD]->Fill(dp);
749 fFakeCombN[iD]->Fill(dn2);
750 cellsWrongCombinations++;
753 fCells[iD + 1][c1].Combine(fCells[iD][c0], c0);
760 Info("MakeCells","Good doublets: %d",numberOfGoodDoublets);
761 Info("MakeCells","Number of doublets: %d",totalNumberOfDoublets);
762 Info("MakeCells","Good cells: %d",numberOfGoodCells);
763 Info("MakeCells","Number of cells: %d",totalNumberOfCells);
764 Info("MakeCells","Cells combining successes: %d",cellsCombiningSuccesses);
765 Info("MakeCells","Cells wrong combinations: %d",cellsWrongCombinations);
769 //__________________________________________________________________________________________________
770 Int_t AliITSUCATracker::PropagateBack(AliESDEvent * event)
773 Int_t n=event->GetNumberOfTracks();
776 for (Int_t i=0; i<n; i++) {
777 AliESDtrack *esdTrack=event->GetTrack(i);
779 if ((esdTrack->GetStatus()&AliESDtrack::kITSin)==0) continue;
780 if (esdTrack->IsOn(AliESDtrack::kTPCin)) continue; //skip a TPC+ITS track
782 AliITSUTrackCooked track(*esdTrack);
783 AliITSUTrackCooked temp(*esdTrack);
785 temp.ResetCovariance(10.);
786 temp.ResetClusters();
788 if (RefitAt(40., &temp, &track)) {
790 CookLabel(&temp, 0.); //For comparison only
791 Int_t label = temp.GetLabel();
792 if (label > 0) ngood++;
794 esdTrack->UpdateTrackParams(&temp,AliESDtrack::kITSout);
799 Info("PropagateBack","Back propagated tracks: %d",ntrk);
801 Info("PropagateBack","Good tracks/back propagated: %f",Float_t(ngood)/ntrk);
803 if (!fSAonly) return AliITSUTrackerGlo::PropagateBack(event);
807 //__________________________________________________________________________________________________
808 Bool_t AliITSUCATracker::RefitAt(Double_t xx, AliITSUTrackCooked *t, const AliITSUTrackCooked *c)
810 // This function refits the track "t" at the position "x" using
811 // the clusters from "c"
813 const int nLayers = 7;
814 Int_t index[nLayers];
816 for (k = 0; k < nLayers; k++) index[k] = -1;
817 Int_t nc = c->GetNumberOfClusters();
818 for (k = 0; k < nc; k++) {
819 Int_t idx = c->GetClusterIndex(k), nl = (idx&0xf0000000)>>28;
823 Int_t from, to, step;
824 if (xx > t->GetX()) {
834 for (Int_t i = from; i != to; i += step) {
835 Int_t idx = index[i];
837 const AliCluster *cl = GetCluster(idx);
839 cl->GetXAlphaRefPlane(xr, ar);
840 if (!t->Propagate(Double_t(ar), Double_t(xr), GetBz())) {
843 Double_t chi2 = t->GetPredictedChi2(cl);
845 t->Update(cl, chi2, idx);
847 Double_t r = fgkR[i];
849 if (!t->GetPhiZat(r,phi,z)) {
852 if (!t->Propagate(phi, r, GetBz())) {
856 Double_t xx0 = (i > 2) ? 0.008 : 0.003; // Rough layer thickness
857 Double_t x0 = 9.36; // Radiation length of Si [cm]
858 Double_t rho = 2.33; // Density of Si [g/cm^3]
859 Double_t mass = t->GetMass();
860 t->CorrectForMeanMaterial(xx0, - step * xx0 * x0 * rho, mass, kTRUE);
863 if (!t->PropagateTo(xx,0.,0.)) return kFALSE;
867 //__________________________________________________________________________________________________
868 Int_t AliITSUCATracker::RefitInward(AliESDEvent * event)
870 // Some final refit, after the outliers get removed by the smoother ?
871 // The clusters must be loaded
873 Int_t n = event->GetNumberOfTracks();
876 for (Int_t i = 0; i < n; i++) {
877 AliESDtrack *esdTrack = event->GetTrack(i);
879 if ((esdTrack->GetStatus() & AliESDtrack::kITSout) == 0) continue;
880 if (esdTrack->IsOn(AliESDtrack::kTPCin)) continue; //skip a TPC+ITS track
881 AliITSUTrackCooked track(*esdTrack);
882 AliITSUTrackCooked temp(*esdTrack);
884 temp.ResetCovariance(10.);
885 temp.ResetClusters();
887 if (!RefitAt(2.1, &temp, &track)) continue;
888 //Cross the beam pipe
889 if (!temp.PropagateTo(1.8, 2.27e-3, 35.28 * 1.848)) continue;
891 CookLabel(&temp, 0.); //For comparison only
892 Int_t label = temp.GetLabel();
893 if (label > 0) ngood++;
895 esdTrack->UpdateTrackParams(&temp,AliESDtrack::kITSrefit);
899 Info("RefitInward","Refitted tracks: %d",ntrk);
901 Info("RefitInward","Good tracks/refitted: %f",Float_t(ngood)/ntrk);
903 if (!fSAonly) return AliITSUTrackerGlo::RefitInward(event);
907 //__________________________________________________________________________________________________
908 void AliITSUCATracker::SetCuts(int it)
913 fCDTanL = kDoublTanL;
916 for (int i = 0; i < 5; ++i) {
917 fCDCAxy[i] = kmaxDCAxy[i];
918 fCDCAz[i] = kmaxDCAz[i];
920 for (int i = 0; i < 4; ++i) {
924 for (int i = 0; i < 6; ++i) {
930 fCPhi = 3.f * fPhiCut;
931 fCDTanL = kDoublTanL1;
934 for (int i = 0; i < 5; ++i) {
935 fCDCAxy[i] = kmaxDCAxy1[i];
936 fCDCAz[i] = kmaxDCAz1[i];
938 for (int i = 0; i < 4; ++i) {
939 fCDN[i] = kmaxDN1[i];
940 fCDP[i] = kmaxDP1[i];
942 for (int i = 0; i < 6; ++i) {
943 fCDZ[i] = kmaxDZ1[i];
950 //__________________________________________________________________________________________________
951 void AliITSUCATracker::UnloadClusters()
953 // This function unloads ITSU clusters from the memory
954 for (int i = 0;i < 7;++i) {
956 fUsedClusters[i].clear();
958 for (int i = 0; i < 6; ++i) {
959 fDoublets[i].clear();
961 for (int i = 0; i < 5; ++i) {
964 for (int i = 0; i < 4; ++i)
966 fCandidates[i]->Clear("C");
968 AliITSUTrackerGlo::UnloadClusters();
972 //__________________________________________________________________________________________________
973 void AliITSUCATracker::ResetHistos()
975 for (int i = 0; i < 6; ++i) {
981 for (int i = 0; i < 5; ++i) {
982 fGoodCombChi2[i]->Reset();
983 fFakeCombChi2[i]->Reset();
989 for (int i = 0; i < 4; ++i) {
990 fGoodCombN[i]->Reset();
991 fFakeCombN[i]->Reset();