Made it possible to use different cuts for nonvertex tracking
[u/mrichter/AliRoot.git] / HLT / src / AliL3ConfMapper.cxx
1 //$Id$
2
3 // Author: Anders Vestbo <mailto:vestbo@fi.uib.no>
4 //*-- Copyright &copy ASV 
5  
6 #include <iostream.h>
7 #include <time.h>
8 #include <math.h>
9 #include "AliL3ConfMapper.h"
10
11 #include "AliL3Defs.h"
12 #include "AliL3Logging.h"
13 #include "AliL3Transform.h"
14 #include "AliL3Vertex.h"
15 #include "AliL3ConfMapTrack.h"
16 #include "AliL3ConfMapPoint.h"
17 #include "AliL3TrackArray.h"
18
19 //_____________________________________________________________
20 // AliL3ConfMapper
21 //
22 // Conformal mapping base class
23 //
24 ClassImp(AliL3ConfMapper)
25
26 Double_t AliL3ConfMapper::pi=3.14159265358979323846;
27 Double_t AliL3ConfMapper::twopi=2*pi;
28 Double_t AliL3ConfMapper::todeg=180./pi;
29
30 AliL3ConfMapper::AliL3ConfMapper()
31 {
32   //Default constructor
33   fVertex = NULL;
34   fTrack = NULL;
35   fHit = NULL;
36   fVolume = NULL;
37   fRow = NULL;
38   fBench = (Bool_t)true;
39   fParamSet = (Bool_t)false;
40   fVertexConstraint = (Bool_t)true;
41   
42 }
43
44
45 AliL3ConfMapper::~AliL3ConfMapper()
46 {
47   // Destructor.
48
49   if(fVolume) {
50     delete [] fVolume;
51   }
52   if(fRow) {
53     delete [] fRow;
54   }
55   if(fHit) {
56     delete [] fHit;
57   }
58   if(fTrack) {
59     delete fTrack;
60   }
61
62 }
63
64 void AliL3ConfMapper::InitSector(Int_t sector,Int_t *rowrange,Float_t *etarange)
65 {
66   //Initialize tracker for tracking in a given sector.
67   //Resets track and hit arrays.
68   //Here it is also possible to specify a subsector, by defining
69   //rowrange[0]=innermost row;
70   //rowrange[1]=outermostrow;
71   //Finally you can specify etaslices to save time (assuming a good seed from TRD...)
72   
73   if(fHit)
74     {
75       delete [] fHit;
76     }
77   
78   if(fTrack) 
79     {
80       delete fTrack;
81     }
82
83   //Define tracking area:
84   if(rowrange)
85     {
86       fRowMin = rowrange[0];
87       fRowMax = rowrange[1];
88     }
89   else //complete sector
90     {
91       fRowMin = 0;
92       fRowMax = 175;
93     }
94   if(etarange)
95     {
96       fEtaMin = etarange[0];
97       fEtaMax = etarange[1];
98     }
99   else
100     {
101       fEtaMin = 0;
102       fEtaMax = sector < 18 ? 0.9 : -0.9;
103     }
104   
105   //Set the angles to sector 2:
106   fPhiMin = -1.*10/todeg;//fParam->GetAngle(sector) - 10/todeg;
107   fPhiMax = 10/todeg;//fParam->GetAngle(sector) + 10/todeg;
108
109   //rotation angles for sector 2:
110   //cos: 0.766044 sin: 0.642788
111   
112   Int_t max_num_of_tracks = 3000;
113   Int_t max_num_of_hits = 150000;
114
115   fHit = new AliL3ConfMapPoint[max_num_of_hits];
116   fTrack = new AliL3TrackArray("AliL3ConfMapTrack",max_num_of_tracks);
117   
118   nTracks=0;
119   fMainVertexTracks = 0;
120   fClustersUnused = 0;
121   
122   fNumRowSegment = fRowMax - fRowMin; //number of rows to be considered by tracker
123   LOG(AliL3Log::kInformational,"AliL3ConfMapper::InitSector","B-field")
124     <<"Tracker initializing assuming magnetic field of "<<BField<<ENDLOG;
125 }
126
127
128
129 Bool_t AliL3ConfMapper::ReadHits(UInt_t count, AliL3SpacePointData* hits )
130 {
131   Int_t nhit=(Int_t)count; 
132   for (Int_t i=0;i<nhit;i++)
133     fHit[i].ReadHits(&(hits[i]));
134   fClustersUnused += nhit;
135   LOG(AliL3Log::kInformational,"AliL3ConfMapper::ReadHits","#hits")<<AliL3Log::kDec
136   <<"hit_counter: "<<nhit<<" count: "<<count<<ENDLOG;
137
138   return true;
139 }
140
141
142 void AliL3ConfMapper::SetPointers()
143 {
144   //Data organization.
145   //Allocate volumes, set conformal coordinates and pointers.
146   fNumRowSegmentPlusOne = 176;//fNumRowSegment+1;
147   fNumPhiSegmentPlusOne = fNumPhiSegment+1;
148   fNumEtaSegmentPlusOne = fNumEtaSegment+1;
149   fNumPhiEtaSegmentPlusOne = fNumPhiSegmentPlusOne*fNumEtaSegmentPlusOne;
150   fBounds = fNumRowSegmentPlusOne * fNumPhiSegmentPlusOne * fNumEtaSegmentPlusOne;
151   
152   //Allocate volumes:
153   if(fVolume) delete [] fVolume;
154   if(fRow) delete [] fRow;
155   
156   LOG(AliL3Log::kInformational,"AliL3ConfMapper::SetPointers","Memory")<<AliL3Log::kDec<<
157     "Allocating "<<fBounds*sizeof(AliL3ConfMapContainer)<<" Bytes to fVolume"<<ENDLOG;
158   LOG(AliL3Log::kInformational,"AliL3ConfMapper::SetPointers","Memory")<<AliL3Log::kDec<<
159     "Allocating "<<fNumRowSegmentPlusOne*sizeof(AliL3ConfMapContainer)<<" Bytes to fRow"<<ENDLOG;
160   
161   fVolume = new AliL3ConfMapContainer[fBounds];
162   fRow = new AliL3ConfMapContainer[fNumRowSegmentPlusOne];
163
164   //set volumes to zero:
165   memset(fVolume,0,fBounds*sizeof(AliL3ConfMapContainer));
166   memset(fRow,0,fNumRowSegmentPlusOne*sizeof(AliL3ConfMapContainer));
167   
168   Float_t phiSlice = (fPhiMax-fPhiMin)/fNumPhiSegment;
169   Float_t etaSlice = (fEtaMax-fEtaMin)/fNumEtaSegment;
170   
171   Int_t volumeIndex;
172   Int_t local_counter=0;
173   for(Int_t j=0; j<fClustersUnused; j++)
174     {
175       
176       //AliL3ConfMapPoint *thisHit = (AliL3ConfMapPoint*)fHit->At(j);
177       AliL3ConfMapPoint *thisHit = &(fHit[j]);
178
179       thisHit->Setup(fVertex);
180       
181       Int_t localrow = thisHit->GetPadRow();
182       
183       //reset pointers:
184       thisHit->nextVolumeHit=thisHit->nextRowHit=0;
185       
186       if(localrow < fRowMin || localrow > fRowMax)
187         continue;
188       
189
190       //Get indexes:
191       thisHit->phiIndex=(Int_t)((thisHit->GetPhi()-fPhiMin)/phiSlice +1);
192       
193       if(thisHit->phiIndex<1 || thisHit->phiIndex>fNumPhiSegment)
194         {
195           fPhiHitsOutOfRange++;
196           continue;
197         }
198       
199       thisHit->etaIndex=(Int_t)((thisHit->GetEta()-fEtaMin)/etaSlice + 1);
200       if(thisHit->etaIndex<1 || thisHit->etaIndex>fNumEtaSegment)
201         {
202           fEtaHitsOutOfRange++;
203           continue;
204         }
205       local_counter++;
206             
207       //set volume pointers
208       volumeIndex = localrow*fNumPhiEtaSegmentPlusOne+thisHit->phiIndex*fNumEtaSegmentPlusOne+thisHit->etaIndex;
209       if(fVolume[volumeIndex].first == NULL)
210         fVolume[volumeIndex].first = (void *)thisHit;
211       else
212         ((AliL3ConfMapPoint *)fVolume[volumeIndex].last)->nextVolumeHit=thisHit;
213       fVolume[volumeIndex].last = (void *)thisHit;
214       
215       
216       //set row pointers
217       if(fRow[localrow].first == NULL)
218         fRow[localrow].first = (void *)thisHit;
219       else
220         ((AliL3ConfMapPoint *)(fRow[localrow].last))->nextRowHit = thisHit;
221       fRow[localrow].last = (void *)thisHit;
222       
223     }
224   
225   if(fClustersUnused>0 && local_counter==0)
226     LOG(AliL3Log::kError,"AliL3ConfMapper::SetPointers","Parameters")
227       <<AliL3Log::kDec<<"No points passed to track finder, hits out of range: "
228       <<fEtaHitsOutOfRange+fPhiHitsOutOfRange<<ENDLOG;
229   
230 }
231
232 void AliL3ConfMapper::MainVertexTracking_a()
233 {
234   //Tracking with vertex constraint.
235
236   if(!fParamSet)
237     {
238       LOG(AliL3Log::kError,"AliL3ConfMapper::MainVertexTracking","Parameters")<<AliL3Log::kDec<<
239         "Tracking parameters not set!"<<ENDLOG;
240       return;
241     }
242
243   
244   SetPointers();
245   SetVertexConstraint(true);
246 }
247
248 void AliL3ConfMapper::MainVertexTracking_b()
249 {
250   //Tracking with vertex constraint.
251
252   if(!fParamSet)
253     {
254       LOG(AliL3Log::kError,"AliL3ConfMapper::MainVertexTracking","Parameters")<<AliL3Log::kDec<<
255         "Tracking parameters not set!"<<ENDLOG;
256       return;
257     }
258
259   ClusterLoop();
260 }
261
262 void AliL3ConfMapper::MainVertexTracking()
263 {
264   //Tracking with vertex constraint.
265
266   if(!fParamSet)
267     {
268       LOG(AliL3Log::kError,"AliL3ConfMapper::MainVertexTracking","Parameters")<<AliL3Log::kDec<<
269         "Tracking parameters not set!"<<ENDLOG;
270       return;
271     }
272
273   Double_t initCpuTime,cpuTime;
274   initCpuTime = CpuTime();
275   
276   SetPointers();
277   SetVertexConstraint(true);
278       
279   ClusterLoop();
280
281   cpuTime = CpuTime() - initCpuTime;
282   if(fBench)
283     LOG(AliL3Log::kInformational,"AliL3ConfMapper::MainVertexTracking","Timing")<<AliL3Log::kDec<<
284       "Tracking finished in "<<cpuTime*1000<<" ms"<<ENDLOG;
285     
286   return;
287 }
288
289 void AliL3ConfMapper::NonVertexTracking()
290 {
291   //Tracking with no vertex constraint. This should be called after doing MainVertexTracking,
292   //in order to do tracking on the remaining clusters.
293   //The conformal mapping is now done with respect to the first cluster
294   //assosciated with this track.
295
296   SetVertexConstraint(false);
297   ClusterLoop();
298   LOG(AliL3Log::kInformational,"AliL3ConfMapper::NonVertexTracking","ntracks")<<AliL3Log::kDec<<
299     "Number of nonvertex tracks found: "<<(nTracks-fMainVertexTracks)<<ENDLOG;
300   return;
301 }
302
303 void AliL3ConfMapper::MainVertexSettings(Int_t trackletlength, Int_t tracklength,
304                                          Int_t rowscopetracklet, Int_t rowscopetrack,
305                                          Double_t maxphi,Double_t maxeta)
306 {
307   //Settings for main vertex tracking. The cuts are:
308   //TrackletLength:      #hits on segment, before trying to build a track
309   //TrackLength:         Minimum hits on a track
310   //RowScopeTracklet:    Row search range for segments
311   //RowScopeTrack:       Row search range for tracks
312   
313   SetTrackletLength(trackletlength,(Bool_t)true);
314   SetRowScopeTracklet(rowscopetracklet, (Bool_t) true);
315   SetRowScopeTrack(rowscopetrack, (Bool_t) true);
316   SetMinPoints(tracklength,(Bool_t)true);
317   fMaxPhi=maxphi;
318   fMaxEta=maxeta;
319   
320 }
321
322 void AliL3ConfMapper::NonVertexSettings(Int_t trackletlength, Int_t tracklength,
323                                         Int_t rowscopetracklet, Int_t rowscopetrack)
324 {
325   SetTrackletLength(trackletlength,(Bool_t)false);
326   SetRowScopeTracklet(rowscopetracklet, (Bool_t)false);
327   SetRowScopeTrack(rowscopetrack, (Bool_t)false);
328   SetMinPoints(tracklength,(Bool_t)false);
329 }
330
331 void AliL3ConfMapper::SetTrackCuts(Double_t hitChi2Cut, Double_t goodHitChi2, Double_t trackChi2Cut,Int_t maxdist,
332                                    Bool_t vertexconstraint)
333 {
334   //Settings for tracks. The cuts are:
335   //HitChi2Cut:     Maximum hit chi2
336   //goodHitChi2:    Chi2 to stop look for next hit
337   //trackChi2Cut:   Maximum track chi2
338   //maxdist:        Maximum distance between two clusters when forming segments
339   
340   SetHitChi2Cut(hitChi2Cut,vertexconstraint);
341   SetGoodHitChi2(goodHitChi2,vertexconstraint);
342   SetTrackChi2Cut(trackChi2Cut,vertexconstraint);
343   SetMaxDist(maxdist,vertexconstraint);
344 }
345
346 void AliL3ConfMapper::SetTrackletCuts(Double_t maxangle,Double_t goodDist, Bool_t vertex_constraint)
347 {
348   //Sets cuts of tracklets. Right now this is only:
349   //maxangle:  Maximum angle when forming segments (if trackletlength > 2)
350  
351   fGoodDist=goodDist;
352   SetMaxAngleTracklet(maxangle, vertex_constraint);
353 }
354
355 void AliL3ConfMapper::ClusterLoop()
356 {
357   //Loop over hits, starting at outermost padrow, and trying to build segments.
358
359   Int_t row_segm,lastrow = fRowMin + fMinPoints[fVertexConstraint];
360   AliL3ConfMapPoint *hit;
361   
362   //Loop over rows, and try to create tracks from the hits.
363   //Starts at the outermost row, and loops as long as a track can be build, due to length.
364   
365   for(row_segm = fRowMax; row_segm >= lastrow; row_segm--)
366     {
367       if(fRow[row_segm].first && ((AliL3ConfMapPoint*)fRow[row_segm].first)->GetPadRow() < fRowMin + 1)
368         break;
369       for(hit = (AliL3ConfMapPoint*)fRow[row_segm].first; hit!=0; hit=hit->nextRowHit)
370         {
371           if(hit->GetUsage() == true)
372             continue;
373           else
374             CreateTrack(hit);
375         }
376     }
377   
378   return;
379 }
380
381
382 void AliL3ConfMapper::CreateTrack(AliL3ConfMapPoint *hit)
383 {
384   //Tries to create a track from the initial hit given by ClusterLoop()
385
386   AliL3ConfMapPoint *closest_hit = NULL;
387   AliL3ConfMapTrack *track = NULL;
388   
389   Int_t point;
390   Int_t tracks = nTracks;
391   nTracks++;
392
393   track = (AliL3ConfMapTrack*)fTrack->NextTrack();
394
395   //reset hit parameters:
396   track->Reset();
397   
398   UInt_t *trackhitnumber = track->GetHitNumbers();
399     
400   //set conformal coordinates if we are looking for non vertex tracks
401   if(!fVertexConstraint) 
402     {
403       hit->SetAllCoord(hit);
404     }
405   
406   //fill fit parameters of initial track:
407   track->UpdateParam(hit); //here the number of hits is incremented.
408   trackhitnumber[track->GetNumberOfPoints()-1] = hit->GetHitNumber();
409   
410   Double_t dx,dy;
411   //create tracklets:
412   
413   for(point=1; point<fTrackletLength[fVertexConstraint]; point++)
414     {
415       if((closest_hit = GetNextNeighbor(hit)))
416         {//closest hit exist
417           
418           //   Calculate track length in sz plane
419           dx = ((AliL3ConfMapPoint*)closest_hit)->GetX() - ((AliL3ConfMapPoint*)hit)->GetX();
420           dy = ((AliL3ConfMapPoint*)closest_hit)->GetY() - ((AliL3ConfMapPoint*)hit)->GetY();
421           //track->fLength += (Double_t)sqrt ( dx * dx + dy * dy ) ;
422           Double_t length = track->GetLength()+(Double_t)sqrt ( dx * dx + dy * dy );
423           track->SetLength(length);
424
425           //closest_hit->SetS(track->fLength);
426           closest_hit->SetS(track->GetLength());
427
428           //update fit parameters
429           track->UpdateParam(closest_hit);
430           trackhitnumber[track->GetNumberOfPoints()-1] = closest_hit->GetHitNumber();
431         
432           hit = closest_hit;
433         }
434       else
435         {
436           //closest hit does not exist:
437           track->DeleteCandidate();
438           fTrack->RemoveLast();
439           nTracks--;
440           point = fTrackletLength[fVertexConstraint];
441         }
442     }
443   
444   //tracklet is long enough to be extended to a track
445   if(track->GetNumberOfPoints() == fTrackletLength[fVertexConstraint])
446     {
447       
448       track->SetProperties(true);
449             
450       if(TrackletAngle(track) > fMaxAngleTracklet[fVertexConstraint])
451         {//proof if the first points seem to be a beginning of a track
452         
453           track->SetProperties(false);
454           track->DeleteCandidate();
455           fTrack->RemoveLast();
456           nTracks--;
457         }
458       
459       else//good tracklet ->proceed, follow the trackfit
460         {
461           tracks++;
462                                   
463           //define variables to keep the total chi:
464           Double_t xyChi2 = track->fChiSq[0];
465           Double_t szChi2 = track->fChiSq[1];
466           
467           for(point = fTrackletLength[fVertexConstraint]; point <= fNumRowSegment; point++)
468             {
469               track->fChiSq[0] = fHitChi2Cut[fVertexConstraint];
470               closest_hit = GetNextNeighbor((AliL3ConfMapPoint*)track->lastHit,track);
471               
472               if(closest_hit)
473                 {
474                   
475                   //keep total chi:
476                   Double_t lxyChi2 = track->fChiSq[0]-track->fChiSq[1];
477                   xyChi2 += lxyChi2;
478                   closest_hit->xyChi2 = lxyChi2;
479                                   
480                   //update track length:
481                   //track->fLength = closest_hit->GetS();
482                   track->SetLength(closest_hit->GetS());
483                   szChi2 += track->fChiSq[1];
484                   closest_hit->szChi2 = track->fChiSq[1];
485                   
486                   track->UpdateParam(closest_hit);
487                   trackhitnumber[track->GetNumberOfPoints()-1] = closest_hit->GetHitNumber();
488                   
489                   //add closest hit to track
490                   closest_hit->SetUsage(true);
491                   closest_hit->SetTrackNumber(tracks-1);
492                 
493                 }//closest_hit
494             
495               else
496                 {
497                   //closest hit does not exist
498                   point = fNumRowSegment; //continue with next hit in segment
499                 }//else
500               
501             }//create tracks
502           
503           //store track chi2:
504           track->fChiSq[0] = xyChi2;
505           track->fChiSq[1] = szChi2;
506           Double_t normalized_chi2 = (track->fChiSq[0]+track->fChiSq[1])/track->GetNumberOfPoints();
507           
508           //remove tracks with not enough points already now
509           if(track->GetNumberOfPoints() < fMinPoints[fVertexConstraint] || normalized_chi2 > fTrackChi2Cut[fVertexConstraint])
510             {
511               track->SetProperties(false);
512               nTracks--;
513               track->DeleteCandidate();
514               fTrack->RemoveLast();
515               tracks--;
516             }
517           
518           else
519             {
520               fClustersUnused -= track->GetNumberOfPoints();
521               track->ComesFromMainVertex(fVertexConstraint);
522               //mark track as main vertex track or not
523               track->SetSector(2); //only needed for testing purposes.
524               track->SetRowRange(fRowMin,fRowMax);
525
526               if(fVertexConstraint) 
527                 fMainVertexTracks++;
528             }
529      
530         }//good tracklet
531       
532     }
533   
534   return;
535 }
536
537 AliL3ConfMapPoint *AliL3ConfMapper::GetNextNeighbor(AliL3ConfMapPoint *start_hit,
538                                           AliL3ConfMapTrack *track)
539 {
540   //When forming segments: Finds closest hit to input hit
541   //When forming tracks: Find closest hit to track fit.
542   
543   Double_t dist,closest_dist = fMaxDist[fVertexConstraint];
544   
545   AliL3ConfMapPoint *hit = NULL;
546   AliL3ConfMapPoint *closest_hit = NULL;
547     
548   Int_t sub_row_segm;
549   Int_t sub_phi_segm;
550   Int_t sub_eta_segm;
551   Int_t volumeIndex;
552   Int_t test_hit;
553
554   Int_t max_row = start_hit->GetPadRow()-1;
555   Int_t min_row;
556
557   if(track) //finding hit close to trackfit
558     {
559       min_row = start_hit->GetPadRow()-fRowScopeTrack[fVertexConstraint];
560     }
561   else
562     {
563       min_row = start_hit->GetPadRow()-fRowScopeTracklet[fVertexConstraint];
564     }
565
566   //make a smart loop
567   Int_t loop_eta[9] = {0,0,0,-1,-1,-1,1,1,1};
568   Int_t loop_phi[9] = {0,-1,1,0,-1,1,0,-1,1};
569   
570   if(min_row < fRowMin)
571     min_row = fRowMin;
572   if(max_row < fRowMin)
573     return 0;  //reached the last padrow under consideration
574
575   else
576     {
577       //loop over sub rows
578       for(sub_row_segm=max_row; sub_row_segm>=min_row; sub_row_segm--)
579         {
580           //loop over subsegments, in the order defined above.
581           for(Int_t i=0; i<9; i++)  
582             {
583               sub_phi_segm = start_hit->phiIndex + loop_phi[i];
584               
585               if(sub_phi_segm<0)
586                 sub_phi_segm += fNumPhiSegment;
587               
588               else if(sub_phi_segm >=fNumPhiSegment)
589                 sub_phi_segm -= fNumPhiSegment;
590               
591               //loop over sub eta segments
592               
593               sub_eta_segm = start_hit->etaIndex + loop_eta[i];
594               
595               if(sub_eta_segm < 0 || sub_eta_segm >=fNumEtaSegment)
596                 continue;//segment exceeds bounds->skip it
597               
598               //loop over hits in this sub segment:
599               volumeIndex= sub_row_segm*fNumPhiEtaSegmentPlusOne +
600                 sub_phi_segm*fNumEtaSegmentPlusOne + sub_eta_segm;
601               
602               if(volumeIndex<0)
603                 {//debugging
604                   LOG(AliL3Log::kError,"AliL3ConfMapper::GetNextNeighbor","Memory")<<AliL3Log::kDec<<
605                     "VolumeIndex error "<<volumeIndex<<ENDLOG;
606                 }
607               
608               for(hit = (AliL3ConfMapPoint*)fVolume[volumeIndex].first;
609                   hit!=0; hit = hit->nextVolumeHit)
610                 {
611                   
612                   if(!hit->GetUsage())
613                     {//hit was not used before
614                       
615                       //set conformal mapping if looking for nonvertex tracks:
616                       if(!fVertexConstraint)
617                         {
618                           hit->SetAllCoord(start_hit);
619                         }
620                      
621                       if(track)//track search - look for nearest neighbor to extrapolated track
622                         {
623                           if(!VerifyRange(start_hit,hit))
624                             continue;
625                                                   
626                           test_hit = EvaluateHit(start_hit,hit,track);
627                           
628                           if(test_hit == 0)//chi2 not good enough, keep looking
629                             continue;
630                           else if(test_hit==2)//chi2 good enough, return it
631                             return hit;
632                           else
633                             closest_hit = hit;//chi2 acceptable, but keep looking
634                           
635                         }//track search
636                       
637                       else //tracklet search, look for nearest neighbor
638                         {
639                           
640                           if((dist=CalcDistance(start_hit,hit)) < closest_dist)
641                             {
642                               if(!VerifyRange(start_hit,hit))
643                                 continue;
644                               closest_dist = dist;
645                               closest_hit = hit;
646                          
647                               //if this hit is good enough, return it:
648                               if(closest_dist < fGoodDist)
649                                 return closest_hit;
650                             }
651                           else
652                             continue;//sub hit was farther away than a hit before
653                           
654                         }//tracklet search
655                       
656                     }//hit not used before
657                   
658                   else continue; //sub hit was used before
659                   
660                 }//loop over hits in sub segment
661                       
662             }//loop over sub segments
663                   
664         }//loop over subrows
665       
666     }//else
667
668   //closest hit found:
669   if(closest_hit)// && closest_dist < mMaxDist)
670     return closest_hit;
671   else
672     return 0;
673 }
674
675 Int_t AliL3ConfMapper::EvaluateHit(AliL3ConfMapPoint *start_hit,AliL3ConfMapPoint *hit,AliL3ConfMapTrack *track) 
676 {
677   //Check if space point gives a fit with acceptable chi2.
678   
679   Double_t temp,dxy,lchi2,dx,dy,slocal,dsz,lszChi2;
680   temp = (track->a2Xy*hit->GetXprime()-hit->GetYprime()+track->a1Xy);
681   dxy = temp*temp/(track->a2Xy*track->a2Xy + 1.);
682   
683   //Calculate chi2
684   lchi2 = (dxy*hit->GetXYWeight());
685   
686   if(lchi2 > track->fChiSq[0])//chi2 was worse than before.
687     return 0;
688     
689   //calculate s and the distance hit-line
690   dx = start_hit->GetX()-hit->GetX();
691   dy = start_hit->GetY()-hit->GetY();
692   //slocal = track->fLength+sqrt(dx*dx+dy*dy);
693   slocal = track->GetLength()+sqrt(dx*dx+dy*dy);
694   
695   temp = (track->a2Sz*slocal-hit->GetZ()+track->a1Sz);
696   dsz = temp*temp/(track->a2Sz*track->a2Sz+1);
697   
698   //calculate chi2
699   lszChi2 = dsz*hit->GetZWeight();
700   lchi2 += lszChi2;
701   
702     
703   //check whether chi2 is better than previous one:
704   if(lchi2 < track->fChiSq[0])
705     {
706       track->fChiSq[0] = lchi2;
707       track->fChiSq[1] = lszChi2;
708     
709       hit->SetS(slocal);
710   
711       //if chi2 good enough, stop here:
712       if(lchi2 < fGoodHitChi2[fVertexConstraint]) 
713         return 2;
714       
715       return 1;
716     }
717   
718   return 0;
719   
720 }
721
722 Double_t AliL3ConfMapper::CalcDistance(const AliL3ConfMapPoint *hit1,const AliL3ConfMapPoint *hit2) const
723 {
724   //Return distance between two clusters, defined by Pablo
725   
726   Double_t phi_diff = fabs( hit1->GetPhi() - hit2->GetPhi() );
727   if (phi_diff > pi) phi_diff = twopi - phi_diff;
728   
729   return todeg*fabs(hit1->GetPadRow() - hit2->GetPadRow()) * (phi_diff + fabs( hit1->GetEta() - hit2->GetEta() ));
730 }
731
732 Bool_t AliL3ConfMapper::VerifyRange(const AliL3ConfMapPoint *hit1,const AliL3ConfMapPoint *hit2) const
733 {
734   //Check if the hit are within reasonable range in phi and eta
735   Double_t dphi,deta;//maxphi=0.1,maxeta=0.1;
736   dphi = fabs(hit1->GetPhi() - hit2->GetPhi());
737   if(dphi > pi) dphi = fabs(twopi - dphi);
738   if(dphi > fMaxPhi) return false;
739   
740   deta = fabs(hit1->GetEta() - hit2->GetEta());
741   if(deta > fMaxEta) return false;
742
743   return true;
744
745 }
746
747 Double_t AliL3ConfMapper::TrackletAngle(const AliL3ConfMapTrack *track,Int_t n) const
748 {
749   // Returns the angle 'between' the last three points (started at point number n) on this track.
750
751   return 0;
752   /*
753   Double_t x1[2];
754   Double_t x2[2];
755   Double_t angle1,angle2;
756   TObjArray *hits = track->GetHits();
757   
758   if (n > track->GetNumberOfPoints()) {
759     n = track->GetNumberOfPoints();
760   }
761
762   if (n<3) 
763     return 0;
764   
765
766   x1[0] = ((AliL3ConfMapPoint *)hits->At(n-2))->GetX() - ((AliL3ConfMapPoint *)hits->At(n-3))->GetX();
767   x1[1] = ((AliL3ConfMapPoint *)hits->At(n-2))->GetY() - ((AliL3ConfMapPoint *)hits->At(n-3))->GetY();
768
769   x2[0] = ((AliL3ConfMapPoint *)hits->At(n-1))->GetX() - ((AliL3ConfMapPoint *)hits->At(n-2))->GetX();
770   x2[1] = ((AliL3ConfMapPoint *)hits->At(n-1))->GetY() - ((AliL3ConfMapPoint *)hits->At(n-2))->GetY();
771   
772   angle1 = atan2(x1[1],x1[0]);
773   angle2 = atan2(x2[1],x1[0]);
774   return fabs(angle1-angle2);
775   */
776 }
777
778 Int_t AliL3ConfMapper::FillTracks()
779 {
780   //Fill track parameters. Which basically means do a fit of helix in real space,
781   //which should be done in order to get nice tracks.
782   
783   Int_t num_of_tracks = nTracks;
784   LOG(AliL3Log::kInformational,"AliL3ConfMapper::FillTracks","nTracks")<<AliL3Log::kDec<<
785     "Number of found tracks: "<<nTracks<<ENDLOG;
786   
787   if(nTracks == 0)
788     {
789       LOG(AliL3Log::kError,"AliL3ConfMapper::FillTracks","nTracks")<<AliL3Log::kDec<<
790         "No tracks found!!"<<ENDLOG;
791       return 0;
792     }
793   
794   //  fTrack->Sort();
795   for(int i=0; i<num_of_tracks; i++)
796     {
797       AliL3ConfMapTrack *track = (AliL3ConfMapTrack*)fTrack->GetTrack(i);
798       track->Fill(fVertex,fMaxDca);
799     }
800   return 1;
801
802 }
803
804 Double_t AliL3ConfMapper::CpuTime()
805 {
806   //Return the Cputime in seconds.
807
808   return (Double_t)(clock()) / CLOCKS_PER_SEC;
809 }