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