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