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