1 //--------------------------------------------------------------------------------
2 // Implementation of the ITS tracker class
3 // It reads AliITSUClusterPix clusters and and fills the ESD with tracks
5 // The algorithm implemented here takes inspiration from UniCA code of FIAS
7 //--------------------------------------------------------------------------------
20 //#include "AliITSUTrackerSAauxVc.h" // Structs and other stuff using Vc library
22 #include "AliESDEvent.h"
23 #include "AliITSUClusterPix.h"
24 #include "AliITSUTrackerSA.h"
25 #include "AliITSUReconstructor.h"
26 #include "AliITSURecoDet.h"
27 #include "AliESDtrack.h"
29 #include <Riostream.h>
35 //#include "AliITSUtrackSA.h" // Some dedicated SA track class ?
37 ClassImp(AliITSUTrackerSA)
39 const Double_t AliITSUTrackerSA::fgkToler = 1e-6;// tolerance for layer on-surface check
40 const Double_t AliITSUTrackerSA::fgkChi2Cut = 600.f;
42 //________________________________________________________________________________
43 AliITSUTrackerSA::AliITSUTrackerSA(AliITSUReconstructor* rec) :
51 fChi2Cut( fgkChi2Cut ),
56 //--------------------------------------------------------------------
57 // This default constructor needs to be provided
58 //--------------------------------------------------------------------
62 //________________________________________________________________________________
63 AliITSUTrackerSA::AliITSUTrackerSA(const AliITSUTrackerSA &t): AliTracker(t),
64 fReconstructor(t.fReconstructor),
67 fUseMatLUT(t.fUseMatLUT),
68 fCurrMass(t.fCurrMass),
76 //--------------------------------------------------------------------
77 // The copy constructor is protected
78 //--------------------------------------------------------------------
81 //________________________________________________________________________________
82 AliITSUTrackerSA::~AliITSUTrackerSA()
89 //_________________________________________________________________________
90 void AliITSUTrackerSA::Init(AliITSUReconstructor* rec)
92 // init with external reconstructor
94 fITS = rec->GetITSInterface();
96 // create material lookup table
97 const int kNTest = 1000;
98 const double kStepsPerCM=5;
99 fMatLUT = new AliITSUMatLUT(fITS->GetRMin(),fITS->GetRMax(),Nint(kStepsPerCM*(fITS->GetRMax()-fITS->GetRMin())));
101 for (int ilr=fITS->GetNLayers();ilr--;) {
102 AliITSURecoLayer* lr = fITS->GetLayer(ilr);
103 if (zmn>Abs(lr->GetZMin())) zmn = Abs(lr->GetZMin());
104 if (zmn>Abs(lr->GetZMax())) zmn = Abs(lr->GetZMax());
106 fMatLUT->FillData(kNTest,-zmn,zmn);
110 //________________________________________________________________________________
111 Int_t AliITSUTrackerSA::Clusters2Tracks(AliESDEvent *event) {
112 //--------------------------------------------------------------------
113 // This is the main tracking function
114 // The clusters must already be loaded
115 //--------------------------------------------------------------------
117 // Possibly, create the track "seeds" (combinatorial)
119 // Possibly, increment the seeds with additional clusters (Kalman)
121 // Possibly, (re)fit the found tracks
124 // - High momentum first;
125 // - Low momentum with vertex constraint;
126 // - Everything else.
129 CellularAutomaton(event);
132 // CellularAutomaton(event);
137 //________________________________________________________________________________
138 Int_t AliITSUTrackerSA::PropagateBack(AliESDEvent * event) {
139 //--------------------------------------------------------------------
140 // Here, we implement the Kalman smoother ?
141 // The clusters must be already loaded
142 //--------------------------------------------------------------------
143 Int_t n=event->GetNumberOfTracks();
146 for (Int_t i=0; i<n; i++) {
147 AliESDtrack *esdTrack=event->GetTrack(i);
149 if ((esdTrack->GetStatus()&AliESDtrack::kITSin)==0) continue;
151 AliITSUTrackCooked track(*esdTrack);
153 track.ResetCovariance(10.);
155 int points[2*AliITSUAux::kMaxLayers];
156 for (UInt_t k=0; k<2*AliITSUAux::kMaxLayers; k++)
158 Int_t nc=track.GetNumberOfClusters();
159 for (Int_t k=0; k<nc; k++) {
160 const int layer = (track.GetClusterIndex(k)&0xf0000000)>>28;
161 const int idx = (track.GetClusterIndex(k)&0x0fffffff);
162 points[layer<<1]=idx;
165 if (RefitTrack(&track,points,40,1)>=0) {
167 CookLabel(&track, 0.); //For comparison only
168 Int_t label=track.GetLabel();
169 if (label>0) ngood++;
171 esdTrack->UpdateTrackParams(&track,AliESDtrack::kITSout);
176 Info("PropagateBack","Back propagated tracks: %d",ntrk);
178 Info("PropagateBack","Good tracks/back propagated: %f",Float_t(ngood)/ntrk);
183 //________________________________________________________________________________
184 Int_t AliITSUTrackerSA::RefitInward(AliESDEvent * event) {
185 //--------------------------------------------------------------------
186 // Some final refit, after the outliers get removed by the smoother ?
187 // The clusters must be loaded
188 //--------------------------------------------------------------------
189 Int_t n=event->GetNumberOfTracks();
192 for (Int_t i=0; i<n; i++) {
193 AliESDtrack *esdTrack=event->GetTrack(i);
195 if ((esdTrack->GetStatus()&AliESDtrack::kITSout)==0) continue;
197 AliITSUTrackCooked track(*esdTrack);
199 track.ResetCovariance(10.);
201 int points[2*AliITSUAux::kMaxLayers];
202 for (UInt_t k=0; k<2*AliITSUAux::kMaxLayers; k++)
204 Int_t nc=track.GetNumberOfClusters();
205 for (Int_t k=0; k<nc; k++) {
206 const int layer = (track.GetClusterIndex(k)&0xf0000000)>>28;
207 const int idx = (track.GetClusterIndex(k)&0x0fffffff);
208 points[layer<<1]=idx;
211 if (RefitTrack(&track,points,1.8,1)>=0) { //2.1,1)>=0) {
213 //if (!track.PropagateTo(1.8, 2.27e-3, 35.28*1.848)) continue;
214 CookLabel(&track, 0.); //For comparison only
215 Int_t label=track.GetLabel();
216 if (label>0) ngood++;
218 //cout << esdTrack->GetStatus() << " ";
219 esdTrack->UpdateTrackParams(&track,AliESDtrack::kITSrefit);
220 //cout << esdTrack->GetStatus() << endl;
225 Info("RefitInward","Refitted tracks: %d",ntrk);
227 Info("RefitInward","Good tracks/refitted: %f",Float_t(ngood)/ntrk);
232 //________________________________________________________________________________
233 Int_t AliITSUTrackerSA::LoadClusters(TTree *cluTree) {
234 //--------------------------------------------------------------------
235 // This function reads the ITSU clusters from the tree,
236 // sort them, distribute over the internal tracker arrays, etc
237 //--------------------------------------------------------------------
238 fITS->LoadClusters(cluTree);
239 fITS->ProcessClusters();
241 for(int iL=0; iL<7; ++iL) {
242 fClustersTC[iL]=*fITS->GetLayerActive(iL)->GetClustersAddress();
243 AliITSURecoLayer* lr = fITS->GetLayerActive(iL) ; // assign the layer which the cluster belongs to
244 for(int iC=0;iC<fClustersTC[iL]->GetEntriesFast();++iC) {
245 const AliITSUClusterPix *cl = (AliITSUClusterPix*)fClustersTC[iL]->At(iC);
247 cl->GetGlobalXYZ(pos);
248 float phi = TMath::PiOver2();
249 if(Abs(pos[0])>1e-9) {
250 phi=TMath::ATan2(pos[1]-GetY(),pos[0]-GetX());
251 if(phi<0.f) phi+=TMath::TwoPi();
252 } else if(pos[1]<0.f) phi *= 3.f ;
253 AliITSURecoSens* sens = lr->GetSensorFromID(cl->GetVolumeId());
254 const float alpha = sens->GetPhiTF();
255 const float cov[3]={cl->GetSigmaZ2(),cl->GetSigmaYZ(),cl->GetSigmaY2()};
257 fLayer[iL].AddPoint(pos,cov,phi,alpha);
258 for ( int i=0 ; i<3; ++i ) {
259 fLayer[iL].Points.back().Label[i] = (cl->GetLabel(i)<0) ? -1 : cl->GetLabel(i);
269 //________________________________________________________________________________
270 void AliITSUTrackerSA::UnloadClusters() {
271 //--------------------------------------------------------------------
272 // This function unloads ITSU clusters from the RAM
273 //--------------------------------------------------------------------
281 //________________________________________________________________________________
282 void AliITSUTrackerSA::CellularAutomaton(AliESDEvent *event) {
284 // Here it's implemented the Cellular Automaton routine
285 // Firstly the level of each doublet is set according to the level of
286 // the neighbour doublets.
287 // Doublet are considered to be neighbour if they share one point and the
288 // phi and theta direction difference of the two is below a cut value.
289 Int_t ntrk=0,ngood=0;
291 for( int iL = 1; iL < 5; ++iL ) {
292 for( size_t iC1 = 0; iC1 < fCells[iL-1].size(); ++iC1 ) {
293 for( size_t iC2 = 0; iC2 < fCells[iL].size(); ++iC2 ) {
294 if( fCells[iL-1][iC1].Points[1]==fCells[iL][iC2].Points[0] &&
295 fCells[iL-1][iC1].Points[2]==fCells[iL][iC2].Points[1] &&
296 fCells[iL-1][iC1].Level >= fCells[iL][iC2].Level - 1 ) {
297 // The implementation of the curvature based matching has to be studied.
298 fCells[iL][iC2].Level = fCells[iL-1][iC1].Level+1;
299 fCells[iL][iC2].Neighbours.push_back(iC1);
305 for (int level = 5; level > 0; --level ) {
307 roads.reserve(100); // should reserve() be based on number of clusters on outermost layer?
308 for (int iCL=4; iCL >= level-1; --iCL ) {
309 for (size_t iCell = 0; iCell < fCells[iCL].size(); ++iCell) {
310 if ( fCells[iCL][iCell].Level != level ) continue;
311 roads.push_back( Road(iCL,iCell) );
312 for( size_t iN=0;iN<fCells[iCL][iCell].Neighbours.size(); ++iN ) {
313 const int currD = iCL - 1;
314 const int neigh = fCells[iCL][iCell].Neighbours[iN];
315 if( iN > 0 ) roads.push_back(roads.back());
316 CandidatesTreeTraversal(roads,neigh,currD);
318 fCells[iCL][iCell].Level = -1;
322 // for(size_t iR=0; iR<roads.size(); ++iR) {
323 // cout << "ROAD " << iR << " | ";
324 // for(int i=0;i<5;++i) {
325 // if(roads[iR][i]<0) continue;
327 // if(roads[iR].Label==-1){
328 // roads[iR].Label = fCells[i][roads[iR][i]].Label;
329 // if(roads[iR].Label==-1) roads[iR].Label--;
331 // if (fCells[i][roads[iR][i]].Label!=roads[iR].Label&&roads[iR].Label>-1) {
332 // roads[iR].Label = -1;
333 // if(fCells[i][roads[iR][i]].Label==-1) roads[iR].Label--;
336 // cout << fCells[i][roads[iR][i]].Label << " ";
339 // cout << " | " << roads[iR].Label << " | " << roads[iR].N << endl;
341 vector<AliITSUTrackCooked> candidates;
342 candidates.reserve(roads.size());
344 for (size_t iR=0; iR<roads.size(); ++iR) {
345 if(roads[iR].N != level) {
349 int points[2*AliITSUAux::kMaxLayers];
350 for(unsigned int i=0;i<2*AliITSUAux::kMaxLayers;++i) points[i] = -1;
351 for(int i=0;i<5;++i) {
352 if(roads[iR].Elements[i]<0) continue;
353 points[( i )<<1]=fLayer[ i ](fCells[i][roads[iR].Elements[i]].Points[0]);
354 points[(i+1)<<1]=fLayer[i+1](fCells[i][roads[iR].Elements[i]].Points[1]);
355 points[(i+2)<<1]=fLayer[i+2](fCells[i][roads[iR].Elements[i]].Points[2]);
358 candidates.push_back(AliITSUTrackCooked());
360 InitTrackParams(candidates.back(),points);
361 const double chi2 = RefitTrack( (AliExternalTrackParam*)&candidates.back(), points, 0. ,-1);
364 // cout << "FAIL: " << chi2 << endl;
365 // for(unsigned int i=0;i<2*AliITSUAux::kMaxLayers;++i)
366 // cout << points[i] << " ";
368 candidates.back().SetChi2( 1e27 );
369 } else candidates.back().SetChi2( chi2 );
370 candidates.back().SetLabel(roads[iR].Label);
374 index.reserve(candidates.size());
375 for ( size_t i = 0; i < candidates.size(); ++i ) index.push_back(i);
376 Comparison<AliITSUTrackCooked> comp(&candidates);
377 sort(index.begin(),index.end(),comp);
379 for ( size_t cand = 0; cand < candidates.size(); ++cand ) {
380 const int ii = index[cand];
382 if ( candidates[ii].GetChi2() < 0. ) continue;
384 // cout << candidates[ii].GetChi2() << " " << candidates[ii].GetNumberOfClusters() << " | " << candidates[ii].GetLabel() << " | ";
385 // for(int i=0;i<candidates[ii].GetNumberOfClusters();++i) {
386 // cout<< GetCluster(candidates[ii].GetClusterIndex(i))->GetLabel(0) << " ";
390 if( candidates[ii].GetChi2()/candidates[ii].GetNumberOfClusters() > fgkChi2Cut ) {
393 bool goodTrack = true;
394 for ( int point = 0; point < candidates[ii].GetNumberOfClusters(); ++point ) {
395 int layer = (candidates[ii].GetClusterIndex(point)&0xf0000000)>>28;
396 int ind = (candidates[ii].GetClusterIndex(point)&0x0fffffff);
398 if( (fLayer[ layer ].Points[ ind ].Used ) ) {
406 for ( int point = 0; point < candidates[ii].GetNumberOfClusters(); ++point ) {
407 int layer = (candidates[ii].GetClusterIndex(point)&0xf0000000)>>28;
408 int ind = (candidates[ii].GetClusterIndex(point)&0x0fffffff);
409 fLayer[ layer ].Points[ ind ].Used = true;
412 AliESDtrack outTrack;
413 CookLabel((AliKalmanTrack*)&candidates[ii],0.f);
415 if(candidates[ii].GetChi2()>0) ngood++;
417 // cout << candidates[ii].GetChi2() << " " << candidates[ii].GetNumberOfClusters() << " | " << candidates[ii].GetLabel() << " | ";
418 // for(int i=0;i<candidates[ii].GetNumberOfClusters();++i) {
419 // cout<< GetCluster(candidates[ii].GetClusterIndex(i))->GetLabel(0) << " ";
423 outTrack.UpdateTrackParams((AliKalmanTrack*)&candidates[ii],AliESDtrack::kITSin);
424 outTrack.SetLabel(candidates[ii].GetLabel());
425 event->AddTrack(&outTrack);
428 Info("Clusters2Tracks","Reconstructed tracks: %d",ntrk);
430 Info("Clusters2Tracks","Good tracks/reconstructed: %f",Float_t(ngood)/ntrk);
434 //________________________________________________________________________________
435 void AliITSUTrackerSA::CellsCreation(const int &cutLevel) {
436 // Make associations between two points on adjacent layers within an azimuthal window.
437 // Under consideration:
438 // - track parameter estimation using the primary vertex position
443 if( cutLevel==0 ) phiCut = fPhiCut;
446 vector<Cell> doublets[6];
447 for( int iL = 0 ; iL < 6 ; ++iL ) {
448 for ( int iC1 = 0 ; iC1 < fLayer[iL].N ; ++iC1 ) {
449 for ( int iC2 = 0; iC2 < fLayer[iL+1].N ; ++iC2 ) {
450 const float dPhi = Abs( fLayer[iL][iC1].Phi - fLayer[iL+1][iC2].Phi );
451 if( dPhi < phiCut || Abs( dPhi - TMath::TwoPi() ) < phiCut) {
452 doublets[iL].push_back(Cell(iC1,iC2));
453 if(Abs(fLayer[iL][iC1].XYZ[0]-fLayer[iL+1][iC2].XYZ[0])<1e-32) {
454 doublets[iL].back().Param[0] = 1e32;
456 doublets[iL].back().Param[0] = (fLayer[iL][iC1].XYZ[1]-fLayer[iL+1][iC2].XYZ[1])/(fLayer[iL][iC1].XYZ[0]-fLayer[iL+1][iC2].XYZ[0]);
458 const float r1 = Sqrt(fLayer[iL][iC1].XYZ[0] * fLayer[iL][iC1].XYZ[0] + fLayer[iL][iC1].XYZ[1] * fLayer[iL][iC1].XYZ[1]);
459 const float r2 = Sqrt(fLayer[iL+1][iC2].XYZ[0] * fLayer[iL+1][iC2].XYZ[0] + fLayer[iL+1][iC2].XYZ[1] * fLayer[iL+1][iC2].XYZ[1]);
460 doublets[iL].back().Param[1] = (fLayer[iL][iC1].XYZ[2]-fLayer[iL+1][iC2].XYZ[2])/(r1-r2);
461 doublets[iL].back().Label=-1;
462 for(int i=0;i<3;++i) {
463 for(int j=0;j<3;++j) {
464 if(fLayer[iL][iC1].Label[i]>-1&&fLayer[iL][iC1].Label[i]==fLayer[iL+1][iC2].Label[j])
465 doublets[iL].back().Label = fLayer[iL][iC1].Label[i];
468 } else if( fLayer[iL+1][iC2].Phi - fLayer[iL][iC1].Phi > phiCut ) break;
475 for( int iL = 5; iL > 0; --iL ) {
476 fCells[iL-1].clear();
477 for ( size_t iD2 = 0; iD2 < doublets[iL].size(); ++iD2 ) {
478 for ( size_t iD1 = 0; iD1 < doublets[iL-1].size(); ++iD1 ) {
479 const int id1 = doublets[iL-1][iD1].Points[1];
480 const int id2 = doublets[iL][iD2].Points[0];
482 const int id3 = doublets[iL][iD2].Points[1];
483 const float r3 = Sqrt( fLayer[iL+1][id3].XYZ[0] * fLayer[iL+1][id3].XYZ[0] + fLayer[iL+1][id3].XYZ[1] * fLayer[iL+1][id3].XYZ[1] );
484 const float r2 = Sqrt( fLayer[iL][id2].XYZ[0] * fLayer[iL][id2].XYZ[0] + fLayer[iL][id2].XYZ[1] * fLayer[iL][id2].XYZ[1] );
485 const float extrZ3 = doublets[iL-1][iD1].Param[1] * ( r3 - r2 ) + fLayer[iL][id2].XYZ[2] ;
486 const int iii = doublets[iL-1][iD1].Points[0];
487 if ( Abs ( extrZ3 - fLayer[iL+1][id3].XYZ[2] ) < fZCut ) {
488 fCells[iL-1].push_back(Cell(doublets[iL-1][iD1].Points[0],id2,id3));
489 fCells[iL-1].back().Param[0] = Curvature(fLayer[iL+1][id3].XYZ[0],fLayer[iL+1][id3].XYZ[1],fLayer[iL][id2].XYZ[0],fLayer[iL][id2].XYZ[1],fLayer[iL-1][iii].XYZ[0],fLayer[iL-1][iii].XYZ[1]);
490 fCells[iL-1].back().Param[1] = doublets[iL][iD2].Param[1];
491 if(doublets[iL-1][iD1].Label==doublets[iL][iD2].Label&&doublets[iL][iD2].Label!=-1)
492 fCells[iL-1].back().Label=doublets[iL][iD2].Label;
494 fCells[iL-1].back().Label=-1;
503 //______________________________________________________________________________
504 Bool_t AliITSUTrackerSA::InitTrackParams(AliITSUTrackCooked &track, int points[])
506 // Set the initial guess on track kinematics for propagation.
507 // Assume at least 3 points available
508 int lrOcc[AliITSUAux::kMaxLayers], nCl=0;
510 // we will need endpoints and middle layer
511 for (int i=fITS->GetNLayersActive()-1; i>=0; i--) {
512 if (points[i<<0x1]>-1) {
514 track.SetClusterIndex(i,points[i<<0x1]);
519 AliError(Form("Cannot estimate momentum of tracks with %d clusters",nCl));
523 const int lr0 = lrOcc[0];
524 const int lr1 = lrOcc[nCl/2];
525 const int lr2 = lrOcc[nCl-1];
527 const SpacePoint& cl0 = fLayer[lr0].Points[ points[lr0<<1] ];
528 const SpacePoint& cl1 = fLayer[lr1].Points[ points[lr1<<1] ];
529 const SpacePoint& cl2 = fLayer[lr2].Points[ points[lr2<<1] ];
530 double cv = Curvature(cl0.XYZ[0],cl0.XYZ[1], cl1.XYZ[0],cl1.XYZ[1], cl2.XYZ[0],cl2.XYZ[1]);
532 double tgl = (cl2.XYZ[2]-cl0.XYZ[2])/TMath::Sqrt((cl2.XYZ[0]-cl0.XYZ[0])*(cl2.XYZ[0]-cl0.XYZ[0])+(cl2.XYZ[1]-cl0.XYZ[1])*(cl2.XYZ[1]-cl0.XYZ[1]));
534 AliITSUClusterPix* clus = (AliITSUClusterPix*)fClustersTC[ lr0 ]->At( points[lr0<<1] );
535 AliITSURecoLayer* lr = fITS->GetLayerActive(lr0);
536 AliITSURecoSens* sens = lr->GetSensorFromID(clus->GetVolumeId());
537 double x = sens->GetXTF() + clus->GetX();
538 double alp = sens->GetPhiTF();
539 // printf("Alp: %f phi: %f\n",alp,phi);
540 double par[5] = {clus->GetY(),clus->GetZ(),0,tgl,cv};
548 track.Set(x,alp,par,cov);
553 //______________________________________________________________________________
554 void AliITSUTrackerSA::CandidatesTreeTraversal(vector<Road> &candidates, const int &iD, const int &doubl) {
556 if ( doubl < 0 ) return;
558 candidates.back().AddElement(doubl,iD);
559 const int currentN = candidates.back().N;
560 for ( size_t iN = 0; iN < fCells[doubl][iD].Neighbours.size(); ++iN ) {
561 const int currD = doubl - 1 ;
562 const int neigh = fCells[doubl][iD].Neighbours[iN];
565 candidates.push_back(static_cast<Road>(candidates.back()));
566 candidates.back().N = currentN;
569 CandidatesTreeTraversal(candidates,neigh,currD);
572 fCells[doubl][iD].Level = -1;
576 //______________________________________________________________________________
577 Double_t AliITSUTrackerSA::RefitTrack(AliExternalTrackParam* trc,
578 Int_t clInfo[2*AliITSUAux::kMaxLayers],
579 Double_t rDest, Int_t stopCond)
581 // refit track till radius rDest.
582 // if stopCond<0 : propagate till last cluster then stop
583 // if stopCond==0: propagate till last cluster then try to go till limiting rDest, don't mind if fail
584 // if stopCond>0 : rDest must be reached
586 // The clList should provide the indices of clusters at corresponding layer (as stored in the layer
587 // TClonesArray, with convention (allowing for up to 2 clusters per layer due to the overlaps):
588 // if there is a cluster on given layer I, then it should be stored at clInfo[2*I-1]
589 // if there is an additional cluster on this layer, it goes to clInfo[2*I]
590 // -1 means no cluster
592 double rCurr = Sqrt(trc->GetX()*trc->GetX() + trc->GetY()*trc->GetY());
593 int dir,lrStart,lrStop;
595 dir = rCurr<rDest ? 1 : -1;
596 lrStart = fITS->FindFirstLayerID(rCurr,dir);
597 lrStop = fITS->FindLastLayerID(rDest,dir); // lr id before which we have to stop
599 if (lrStop<0 || lrStart<0) AliFatal(Form("Failed to find start(%d) or last(%d) layers. "
600 "Track from %.3f to %.3f",lrStart,lrStop,rCurr,rDest));
603 for (int i=2*fITS->GetNLayersActive();i--;) {if (clInfo[i]<0) continue; nCl++;}
605 AliExternalTrackParam tmpTr(*trc);
610 int lrStop1 = lrStop+dir;
611 for (int ilr=lrStart;ilr!=lrStop1;ilr+=dir) {
612 AliITSURecoLayer* lr = fITS->GetLayer(ilr);
613 if ( dir*(rCurr-lr->GetR(dir))>0) continue; // this layer is already passed
614 int ilrA2,ilrA = lr->GetActiveID();
615 // passive layer or active w/o hits will be traversed on the way to next cluster
616 if (!lr->IsActive() || clInfo[ilrA2=(ilrA<<1)]<0) continue;
618 // select the order in which possible 2 clusters (in case of the overlap) will be traversed and fitted
620 if (dir>0) { // clusters are stored in increasing radius order
621 iclLr[nclLr++]=clInfo[ilrA2++];
622 if (clInfo[ilrA2]>=0) iclLr[nclLr++]=clInfo[ilrA2];
625 if ( clInfo[ilrA2+1]>=0 ) iclLr[nclLr++]=clInfo[ilrA2+1];
626 iclLr[nclLr++]=clInfo[ilrA2];
629 Bool_t transportedToLayer = kFALSE;
630 for (int icl=0;icl<nclLr;icl++) {
631 AliITSUClusterPix* clus = (AliITSUClusterPix*)lr->GetCluster(iclLr[icl]);
632 AliITSURecoSens* sens = lr->GetSensorFromID(clus->GetVolumeId());
633 if (!tmpTr.Rotate(sens->GetPhiTF())) return -1;
635 double xClus = sens->GetXTF()+clus->GetX();
636 if (!transportedToLayer) {
637 if (ilr!=lrStart && !TransportToLayerX(&tmpTr,lrStart,ilr,xClus)) return -1; // go to the entrance to the layer
639 transportedToLayer = kTRUE;
642 if (!PropagateSeed(&tmpTr,xClus,fCurrMass)) return -1;
644 Double_t p[2]={clus->GetY(), clus->GetZ()};
645 Double_t cov[3]={clus->GetSigmaY2(), clus->GetSigmaYZ(), clus->GetSigmaZ2()};
646 double chi2cl = tmpTr.GetPredictedChi2(p,cov);
649 if ( !tmpTr.Update(p,cov) ) return -1;
650 if (++nclFit==nCl && stopCond<0) {
652 return chi2; // it was requested to not propagate after last update
657 // All clusters were succesfully fitted. Even if the track does not reach rDest, this is enough to validate it.
658 // Still, try to go as close as possible to rDest.
660 if (lrStart!=lrStop) {
661 if (!TransportToLayer(&tmpTr,lrStart,lrStop)) return (stopCond>0) ? -chi2 : chi2; // rDest was obligatory
662 if (!GoToExitFromLayer(&tmpTr,fITS->GetLayer(lrStop),dir)) return (stopCond>0) ? -chi2 : chi2; // rDest was obligatory
664 // go to the destination radius. Note that here we don't select direction to avoid precision problems
665 if (!tmpTr.GetXatLabR(rDest,rDest,GetBz(),0) || !PropagateSeed(&tmpTr,rDest,fCurrMass, 100, kFALSE)) {
666 return (stopCond>0) ? -chi2 : chi2; // rDest was obligatory
673 //______________________________________________________________________________
674 Bool_t AliITSUTrackerSA::PropagateSeed(AliExternalTrackParam *seed, Double_t xToGo, Double_t mass, Double_t maxStep, Bool_t matCorr)
676 // propagate seed to given x applying material correction if requested
677 const Double_t kEpsilon = 1e-5;
678 Double_t xpos = seed->GetX();
679 Int_t dir = (xpos<xToGo) ? 1:-1;
680 Double_t xyz0[3],xyz1[3];
682 Bool_t updTime = dir>0 && seed->IsStartedTimeIntegral();
683 if (matCorr || updTime) seed->GetXYZ(xyz1); //starting global position
684 while ( (xToGo-xpos)*dir > kEpsilon){
685 Double_t step = dir*TMath::Min(TMath::Abs(xToGo-xpos), maxStep);
686 Double_t x = xpos+step;
687 Double_t bz=GetBz(); // getting the local Bz
688 if (!seed->PropagateTo(x,bz)) return kFALSE;
690 if (matCorr || updTime) {
691 xyz0[0]=xyz1[0]; // global pos at the beginning of step
694 seed->GetXYZ(xyz1); // // global pos at the end of step
698 ds = GetMaterialBudget(xyz0,xyz1,xx0,xrho);
699 if (dir>0) xrho = -xrho; // outward should be negative
700 if (!seed->CorrectForMeanMaterial(xx0,xrho,mass)) return kFALSE;
702 else { // matCorr is not requested but time integral is
703 double d0 = xyz1[0]-xyz0[0];
704 double d1 = xyz1[1]-xyz0[1];
705 double d2 = xyz1[2]-xyz0[2];
706 ds = TMath::Sqrt(d0*d0+d1*d1+d2*d2);
709 if (updTime) seed->AddTimeStep(ds);
716 //_________________________________________________________________________
717 Bool_t AliITSUTrackerSA::TransportToLayer(AliExternalTrackParam* seed, Int_t lFrom, Int_t lTo, Double_t rLim)
719 // transport track from layerFrom to the entrance of layerTo or to rLim (if>0), wathever is closer
721 if (lTo==lFrom) AliFatal(Form("was called with lFrom=%d lTo=%d",lFrom,lTo));
723 int dir = lTo > lFrom ? 1:-1;
724 AliITSURecoLayer* lrFr = fITS->GetLayer(lFrom); // this can be 0 when extrapolation from TPC to ITS is requested
725 Bool_t checkFirst = kTRUE;
726 Bool_t limReached = kFALSE;
729 if (!GoToExitFromLayer(seed,lrFr,dir,checkFirst)) return kFALSE; // go till the end of current layer
732 AliITSURecoLayer* lrTo = fITS->GetLayer( (lFrom+=dir) );
733 if (!lrTo) AliFatal(Form("Layer %d does not exist",lFrom));
735 // go the entrance of the layer, assuming no materials in between
736 double xToGo = lrTo->GetR(-dir);
739 if (rLim<xToGo) {xToGo = rLim; limReached = kTRUE;}
742 if (rLim>xToGo) {xToGo = rLim; limReached = kTRUE;}
745 // double xts = xToGo;
746 if (!seed->GetXatLabR(xToGo,xToGo,GetBz(),dir)) {
747 // printf("FailHere1: %f %f %d\n",xts,xToGo,dir);
748 // seed->Print("etp");
751 if (!PropagateSeed(seed,xToGo,fCurrMass,100, kFALSE )) {
752 //printf("FailHere2: %f %f %d\n",xts,xToGo,dir);
753 //seed->Print("etp");
757 if (limReached) break;
763 //_________________________________________________________________________
764 Bool_t AliITSUTrackerSA::TransportToLayerX(AliExternalTrackParam* seed, Int_t lFrom, Int_t lTo, Double_t xStop)
766 // transport track from layerFrom to the entrance of layerTo but do not pass control parameter X
768 if (lTo==lFrom) AliFatal(Form("was called with lFrom=%d lTo=%d",lFrom,lTo));
770 int dir = lTo > lFrom ? 1:-1;
771 AliITSURecoLayer* lrFr = fITS->GetLayer(lFrom); // this can be 0 when extrapolation from TPC to ITS is requested
772 Bool_t checkFirst = kTRUE;
775 if (!GoToExitFromLayer(seed,lrFr,dir,checkFirst)) return kFALSE; // go till the end of current layer
778 AliITSURecoLayer* lrTo = fITS->GetLayer( (lFrom+=dir) );
779 if (!lrTo) AliFatal(Form("Layer %d does not exist",lFrom));
781 // go the entrance of the layer, assuming no materials in between
782 double xToGo = lrTo->GetR(-dir); // R of the entrance to layer
784 // double xts = xToGo;
785 if (!seed->GetXatLabR(xToGo,xToGo,GetBz(),dir)) {
786 // printf("FailHere1: %f %f %d\n",xts,xToGo,dir);
787 // seed->Print("etp");
790 if ( (dir>0&&xToGo>xStop) || (dir<0&&xToGo<xStop) ) xToGo = xStop;
793 AliDebug(2,Form("go in dir=%d to R=%.4f(X:%.4f)",dir,lrTo->GetR(-dir), xToGo));
795 if (!PropagateSeed(seed,xToGo,fCurrMass,100, kFALSE )) {
796 //printf("FailHere2: %f %f %d\n",xts,xToGo,dir);
797 //seed->Print("etp");
806 //_________________________________________________________________________
807 Bool_t AliITSUTrackerSA::GoToExitFromLayer(AliExternalTrackParam* seed, AliITSURecoLayer* lr, Int_t dir, Bool_t check)
809 // go to the exit from lr in direction dir, applying material corrections in steps specific for this layer
810 // If check is requested, do this only provided the track has not exited the layer already
811 double xToGo = lr->GetR(dir);
812 if (check) { // do we need to track till the surface of the current layer ?
813 double curR2 = seed->GetX()*seed->GetX() + seed->GetY()*seed->GetY(); // current radius
814 if (dir>0) { if (curR2-xToGo*xToGo>-fgkToler) return kTRUE; } // on the surface or outside of the layer
815 else if (dir<0) { if (xToGo*xToGo-curR2>-fgkToler) return kTRUE; } // on the surface or outside of the layer
817 if (!seed->GetXatLabR(xToGo,xToGo,GetBz(),dir)) return kFALSE;
818 // go via layer to its boundary, applying material correction.
819 if (!PropagateSeed(seed,xToGo,fCurrMass, lr->GetMaxStep())) return kFALSE;
825 //_________________________________________________________________________
826 Bool_t AliITSUTrackerSA::GoToEntranceToLayer(AliExternalTrackParam* seed, AliITSURecoLayer* lr, Int_t dir, Bool_t check)
828 // go to the entrance of lr in direction dir, w/o applying material corrections.
829 // If check is requested, do this only provided the track did not reach the layer already
830 double xToGo = lr->GetR(-dir);
831 if (check) { // do we need to track till the surface of the current layer ?
832 double curR2 = seed->GetX()*seed->GetX() + seed->GetY()*seed->GetY(); // current radius
833 if (dir>0) { if (curR2-xToGo*xToGo>-fgkToler) return kTRUE; } // already passed
834 else if (dir<0) { if (xToGo*xToGo-curR2>-fgkToler) return kTRUE; } // already passed
836 if (!seed->GetXatLabR(xToGo,xToGo,GetBz(),dir)) return kFALSE;
837 // go via layer to its boundary, applying material correction.
838 if (!PropagateSeed(seed,xToGo,fCurrMass, 100, kFALSE)) return kFALSE;
843 //____________________________________________________
844 Double_t AliITSUTrackerSA::GetMaterialBudget(const double* pnt0,const double* pnt1, double& x2x0, double& rhol) const
847 if (fUseMatLUT && fMatLUT) {
848 double d = fMatLUT->GetMatBudget(pnt0,pnt1,par);
849 x2x0 = par[AliITSUMatLUT::kParX2X0];
850 rhol = par[AliITSUMatLUT::kParRhoL];
854 MeanMaterialBudget(pnt0,pnt1,par);
856 rhol = par[0]*par[4];
861 //____________________________________________________________________
862 Double_t AliITSUTrackerSA::Curvature(Double_t x1,Double_t y1,Double_t x2,Double_t y2,Double_t x3,Double_t y3) {
864 //calculates the curvature of track
865 Double_t den = (x3-x1)*(y2-y1)-(x2-x1)*(y3-y1);
866 if(den*den<1e-32) return 0.;
867 Double_t a = ((y3-y1)*(x2*x2+y2*y2-x1*x1-y1*y1)-(y2-y1)*(x3*x3+y3*y3-x1*x1-y1*y1))/den;
868 if((y2-y1)*(y2-y1)<1e-32) return 0.;
869 Double_t b = -(x2*x2-x1*x1+y2*y2-y1*y1+a*(x2-x1))/(y2-y1);
870 Double_t c = -x1*x1-y1*y1-a*x1-b*y1;
873 if((a*a+b*b-4*c)<0) return 0.;
874 Double_t rad = TMath::Sqrt(a*a+b*b-4*c)/2.;
875 if(rad*rad<1e-32) return 1e16;
877 if((x1>0 && y1>0 && x1<xc)) rad*=-1;
878 if((x1<0 && y1>0 && x1<xc)) rad*=-1;
879 // if((x1<0 && y1<0 && x1<xc)) rad*=-1;
880 // if((x1>0 && y1<0 && x1<xc)) rad*=-1;