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