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