]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCConfMapper.cxx
- made package indepentend of src
[u/mrichter/AliRoot.git] / HLT / TPCLib / AliHLTTPCConfMapper.cxx
1 // @(#) $Id$
2
3 /** \class AliHLTTPCConfMapper
4 <pre>
5 //_____________________________________________________________
6 // AliHLTTPCConfMapper
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 "AliHLTTPCRootTypes.h"
18 #include "AliHLTTPCSpacePointData.h"
19 #include "AliHLTTPCLogging.h" 
20 #include "AliHLTTPCVertex.h"
21 #include "AliHLTTPCConfMapTrack.h"
22 #include "AliHLTTPCConfMapPoint.h"
23 #include "AliHLTTPCTrackArray.h"
24 #include "AliHLTTPCTransform.h"
25 #include "AliHLTTPCConfMapper.h"
26
27 #if __GNUC__ >= 3
28 using namespace std;
29 #endif
30
31 ClassImp(AliHLTTPCConfMapper)
32
33 AliHLTTPCConfMapper::AliHLTTPCConfMapper()
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 AliHLTTPCConfMapper::~AliHLTTPCConfMapper()
49 {
50   // Destructor.
51   if(fVolume) {
52     delete [] fVolume;
53   }
54   if(fRow) {
55     delete [] fRow;
56   }
57   if(fHit) {
58     delete [] fHit;
59   }
60   if(fTrack) {
61     delete fTrack;
62   }
63 }
64  
65 void AliHLTTPCConfMapper::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 = AliHLTTPCTransform::GetNRows();//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(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::InitVolumes","Memory")<<AliHLTTPCLog::kDec<<
83     "Allocating "<<fBounds*sizeof(AliHLTTPCConfMapContainer)<<" Bytes to fVolume"<<ENDLOG;
84   LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::InitVolumes","Memory")<<AliHLTTPCLog::kDec<<
85     "Allocating "<<fNumRowSegmentPlusOne*sizeof(AliHLTTPCConfMapContainer)<<" Bytes to fRow"<<ENDLOG;
86   
87   fVolume = new AliHLTTPCConfMapContainer[fBounds];
88   fRow = new AliHLTTPCConfMapContainer[fNumRowSegmentPlusOne];
89   
90   memset(fVolume,0,fBounds*sizeof(AliHLTTPCConfMapContainer));
91   memset(fRow,0,fNumRowSegmentPlusOne*sizeof(AliHLTTPCConfMapContainer));
92   
93   Int_t maxnumoftracks = 2000;
94   Int_t maxnumofhits = 120000;
95   
96   if(fHit)
97     delete [] fHit;
98   if(fTrack)
99     delete fTrack;
100     
101   fHit = new AliHLTTPCConfMapPoint[maxnumofhits];
102   fTrack = new AliHLTTPCTrackArray("AliHLTTPCConfMapTrack",maxnumoftracks);
103 }
104
105 void AliHLTTPCConfMapper::InitSector(Int_t sector,Int_t *rowrange,Float_t *etarange)
106 { //sector means slice here
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 = AliHLTTPCTransform::GetNRows() - 1;
124     }
125   if(etarange)
126     {
127       fEtaMin = etarange[0];
128       fEtaMax = sector < 18 ? etarange[1] : -etarange[1];
129     }
130   else
131     {
132       fEtaMin = 0;
133       fEtaMax = sector < 18 ? 0.9 : -0.9;
134     }
135   
136   //Set the angles to sector 2:
137   fPhiMin = -10*AliHLTTPCTransform::ToRad();//fParam->GetAngle(sector) - 10/todeg;
138   fPhiMax =  10*AliHLTTPCTransform::ToRad();//fParam->GetAngle(sector) + 10/todeg;
139
140   fNTracks=0;
141   fMainVertexTracks = 0;
142   fClustersUnused = 0;
143   fEtaHitsOutOfRange=0;
144   fPhiHitsOutOfRange=0;
145   
146   fNumRowSegment = fRowMax - fRowMin; //number of rows to be considered by tracker
147   LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::InitSector","B-field")
148     <<"Tracker initializing with a magnetic field of "<<AliHLTTPCTransform::GetBField()<<ENDLOG;
149   
150   fTrack->Reset();
151 }
152
153 Bool_t AliHLTTPCConfMapper::ReadHits(UInt_t count, AliHLTTPCSpacePointData* hits )
154 {
155   //read hits
156   Int_t nhit=(Int_t)count; 
157   for (Int_t i=0;i<nhit;i++)
158     {   
159       fHit[i+fClustersUnused].Reset();
160       fHit[i+fClustersUnused].ReadHits(&(hits[i]));
161     }
162   fClustersUnused += nhit;
163
164   LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::ReadHits","#hits")
165     <<AliHLTTPCLog::kDec<<"hit_counter: "<<nhit<<" count: "<<count<<ENDLOG;
166   
167   return true;
168 }
169
170 void AliHLTTPCConfMapper::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(AliHLTTPCConfMapContainer));
180   memset(fRow,0,fNumRowSegmentPlusOne*sizeof(AliHLTTPCConfMapContainer));
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       //AliHLTTPCConfMapPoint *thisHit = (AliHLTTPCConfMapPoint*)fHit->At(j);
190       AliHLTTPCConfMapPoint *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         ((AliHLTTPCConfMapPoint *)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         ((AliHLTTPCConfMapPoint *)(fRow[(localrow-fRowMin)].last))->SetNextRowHit(thisHit);
233         fRow[(localrow-fRowMin)].last = (void *)thisHit;
234     }
235   
236   if(fClustersUnused>0 && localcounter==0)
237     LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::SetPointers","Parameters")
238       <<AliHLTTPCLog::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(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::SetPointers","Setup")
243     <<"Setup finished, hits out of range: "<<fEtaHitsOutOfRange+fPhiHitsOutOfRange
244     <<" hits accepted "<<hits_accepted<<ENDLOG;
245 }
246
247 void AliHLTTPCConfMapper::MainVertexTracking_a()
248 {
249   //Tracking with vertex constraint.
250
251   if(!fParamSet[(Int_t)kTRUE])
252     {
253       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::MainVertexTracking","Parameters")<<AliHLTTPCLog::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(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::MainVertexTracking_a","Timing")
266       <<AliHLTTPCLog::kDec<<"Setup finished in "<<cpuTime*1000<<" ms"<<ENDLOG;
267   
268 }
269
270 void AliHLTTPCConfMapper::MainVertexTracking_b()
271 {
272   //Tracking with vertex constraint.
273
274   if(!fParamSet[(Int_t)kTRUE])
275     {
276       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::MainVertexTracking","Parameters")<<AliHLTTPCLog::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(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::MainVertexTracking_b","Timing")
288       <<AliHLTTPCLog::kDec<<"Main Tracking finished in "<<cpuTime*1000<<" ms"<<ENDLOG;
289 }
290
291 void AliHLTTPCConfMapper::MainVertexTracking()
292 {
293   //Tracking with vertex constraint.
294
295   if(!fParamSet[(Int_t)kTRUE])
296     {
297       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::MainVertexTracking","Parameters")<<AliHLTTPCLog::kDec<<
298         "Tracking parameters not set!"<<ENDLOG;
299       return;
300     }
301
302   Double_t initCpuTime,cpuTime;
303   initCpuTime = CpuTime();
304 // END ################################################# MODIFIY JMT
305 #if 0
306   SetPointers(); // moved to Component
307 #endif
308 // END ################################################# MODIFIY JMT
309   SetVertexConstraint(true);
310       
311   ClusterLoop();
312
313   cpuTime = CpuTime() - initCpuTime;
314   if(fBench)
315     LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::MainVertexTracking","Timing")<<AliHLTTPCLog::kDec<<
316       "Tracking finished in "<<cpuTime*1000<<" ms"<<ENDLOG;
317   
318   return;
319 }
320
321 void AliHLTTPCConfMapper::NonVertexTracking()
322 {
323   //Tracking with no vertex constraint. This should be called after doing MainVertexTracking,
324   //in order to do tracking on the remaining clusters.
325   //The conformal mapping is now done with respect to the first cluster
326   //assosciated with this track.
327   
328   if(!fParamSet[(Int_t)kFALSE])
329     {
330       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::NonVertexTracking","Parameters")<<AliHLTTPCLog::kDec<<
331         "Tracking parameters not set!"<<ENDLOG;
332       return;
333     }
334   
335   SetVertexConstraint(false);
336   ClusterLoop();
337   LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::NonVertexTracking","ntracks")<<AliHLTTPCLog::kDec<<
338     "Number of nonvertex tracks found: "<<(fNTracks-fMainVertexTracks)<<ENDLOG;
339   return;
340 }
341
342 void AliHLTTPCConfMapper::MainVertexSettings(Int_t trackletlength, Int_t tracklength,
343                                          Int_t rowscopetracklet, Int_t rowscopetrack,
344                                          Double_t maxphi,Double_t maxeta)
345 {
346   //Settings for main vertex tracking. The cuts are:
347   //TrackletLength:      #hits on segment, before trying to build a track
348   //TrackLength:         Minimum hits on a track
349   //RowScopeTracklet:    Row search range for segments
350   //RowScopeTrack:       Row search range for tracks
351   
352   SetTrackletLength(trackletlength,(Bool_t)true);
353   SetRowScopeTracklet(rowscopetracklet, (Bool_t) true);
354   SetRowScopeTrack(rowscopetrack, (Bool_t) true);
355   SetMinPoints(tracklength,(Bool_t)true);
356   fMaxPhi=maxphi;
357   fMaxEta=maxeta;
358   SetParamDone(kTRUE);
359 }
360
361 void AliHLTTPCConfMapper::NonVertexSettings(Int_t trackletlength, Int_t tracklength,
362                                         Int_t rowscopetracklet, Int_t rowscopetrack)
363 {
364   //set parameters for non-vertex tracking
365   SetTrackletLength(trackletlength,(Bool_t)false);
366   SetRowScopeTracklet(rowscopetracklet, (Bool_t)false);
367   SetRowScopeTrack(rowscopetrack, (Bool_t)false);
368   SetMinPoints(tracklength,(Bool_t)false);
369   SetParamDone(kFALSE);
370 }
371
372 void AliHLTTPCConfMapper::SetTrackCuts(Double_t hitChi2Cut, Double_t goodHitChi2, Double_t trackChi2Cut,Int_t maxdist,Bool_t vertexconstraint)
373 {
374   //Settings for tracks. The cuts are:
375   //HitChi2Cut:     Maximum hit chi2
376   //goodHitChi2:    Chi2 to stop look for next hit
377   //trackChi2Cut:   Maximum track chi2
378   //maxdist:        Maximum distance between two clusters when forming segments
379   
380   SetHitChi2Cut(hitChi2Cut,vertexconstraint);
381   SetGoodHitChi2(goodHitChi2,vertexconstraint);
382   SetTrackChi2Cut(trackChi2Cut,vertexconstraint);
383   SetMaxDist(maxdist,vertexconstraint);
384 }
385
386 void AliHLTTPCConfMapper::SetTrackletCuts(Double_t maxangle,Double_t goodDist, Bool_t vc)
387 {
388   //Sets cuts of tracklets. Right now this is only:
389   //maxangle:  Maximum angle when forming segments (if trackletlength > 2)
390  
391   fGoodDist=goodDist;
392   SetMaxAngleTracklet(maxangle, vc);
393 }
394
395 void AliHLTTPCConfMapper::ClusterLoop()
396 {
397   //Loop over hits, starting at outermost padrow, and trying to build segments.
398   
399   //Check if there are not enough clusters to make a track in this sector
400   //Can happen in pp events.
401   if(fClustersUnused < fMinPoints[fVertexConstraint])
402     return;
403   
404   Int_t rowsegm,lastrow = fRowMin + fMinPoints[fVertexConstraint];
405   AliHLTTPCConfMapPoint *hit;
406   
407   //Loop over rows, and try to create tracks from the hits.
408   //Starts at the outermost row, and loops as long as a track can be build, due to length.
409   
410   for(rowsegm = fRowMax; rowsegm >= lastrow; rowsegm--)
411     {
412       if(fRow[(rowsegm-fRowMin)].first && ((AliHLTTPCConfMapPoint*)fRow[(rowsegm-fRowMin)].first)->GetPadRow() < fRowMin + 1)
413         break;
414
415       for(hit = (AliHLTTPCConfMapPoint*)fRow[(rowsegm-fRowMin)].first; hit!=0; hit=hit->GetNextRowHit())
416         {
417           if(hit->GetUsage() == true)
418             continue;
419           else
420             CreateTrack(hit);
421         }
422     }
423   
424   return;
425 }
426
427
428 void AliHLTTPCConfMapper::CreateTrack(AliHLTTPCConfMapPoint *hit)
429 {
430   //Tries to create a track from the initial hit given by ClusterLoop()
431
432   AliHLTTPCConfMapPoint *closesthit = NULL;
433   AliHLTTPCConfMapTrack *track = NULL;
434   
435   Int_t point;
436   Int_t tracks = fNTracks;
437   fNTracks++;
438
439   track = (AliHLTTPCConfMapTrack*)fTrack->NextTrack();
440
441   //reset hit parameters:
442   track->Reset();
443   
444   UInt_t *trackhitnumber = track->GetHitNumbers();
445     
446   //set conformal coordinates if we are looking for non vertex tracks
447   if(!fVertexConstraint) 
448     {
449       hit->SetAllCoord(hit);
450     }
451   
452   //fill fit parameters of initial track:
453   track->UpdateParam(hit); //here the number of hits is incremented.
454   trackhitnumber[track->GetNumberOfPoints()-1] = hit->GetHitNumber();
455   
456   Double_t dx,dy;
457   //create tracklets:
458   
459   for(point=1; point<fTrackletLength[fVertexConstraint]; point++)
460     {
461       if((closesthit = GetNextNeighbor(hit)))
462         {//closest hit exist
463           
464           //   Calculate track length in sz plane
465           dx = ((AliHLTTPCConfMapPoint*)closesthit)->GetX() - ((AliHLTTPCConfMapPoint*)hit)->GetX();
466           dy = ((AliHLTTPCConfMapPoint*)closesthit)->GetY() - ((AliHLTTPCConfMapPoint*)hit)->GetY();
467           //track->fLength += (Double_t)sqrt ( dx * dx + dy * dy ) ;
468           Double_t length = track->GetLength()+(Double_t)sqrt ( dx * dx + dy * dy );
469           track->SetLength(length);
470
471           //closesthit->SetS(track->fLength);
472           closesthit->SetS(track->GetLength());
473
474           //update fit parameters
475           track->UpdateParam(closesthit);
476           trackhitnumber[track->GetNumberOfPoints()-1] = closesthit->GetHitNumber();
477         
478           hit = closesthit;
479         }
480       else
481         {
482           //closest hit does not exist:
483           track->DeleteCandidate();
484           fTrack->RemoveLast();
485           fNTracks--;
486           point = fTrackletLength[fVertexConstraint];
487         }
488     }
489   
490   //tracklet is long enough to be extended to a track
491   if(track->GetNumberOfPoints() == fTrackletLength[fVertexConstraint])
492     {
493       
494       track->SetProperties(true);
495             
496       if(TrackletAngle(track) > fMaxAngleTracklet[fVertexConstraint])
497         {//proof if the first points seem to be a beginning of a track
498           track->SetProperties(false);
499           track->DeleteCandidate();
500           fTrack->RemoveLast();
501           fNTracks--;
502         }
503       
504       else//good tracklet ->proceed, follow the trackfit
505         {
506           tracks++;
507                                   
508           //define variables to keep the total chi:
509           Double_t xyChi2 = track->GetChiSq1();
510           Double_t szChi2 = track->GetChiSq2();
511           
512           for(point = fTrackletLength[fVertexConstraint]; point <= fNumRowSegment; point++)
513             {
514               track->SetChiSq1(fHitChi2Cut[fVertexConstraint]);
515               closesthit = GetNextNeighbor((AliHLTTPCConfMapPoint*)track->GetLastHit(),track);
516               
517               if(closesthit)
518                 {
519                   //keep total chi:
520                   Double_t lxyChi2 = track->GetChiSq1()-track->GetChiSq2();
521                   xyChi2 += lxyChi2;
522                   closesthit->SetXYChi2(lxyChi2);
523                                   
524                   //update track length:
525                   track->SetLength(closesthit->GetS());
526                   szChi2 += track->GetChiSq2();
527                   closesthit->SetSZChi2(track->GetChiSq2());
528                   
529                   track->UpdateParam(closesthit);
530                   trackhitnumber[track->GetNumberOfPoints()-1] = closesthit->GetHitNumber();
531                   
532                   //add closest hit to track
533                   closesthit->SetUsage(true);
534                   closesthit->SetTrackNumber(tracks-1);
535                   
536                 }//closesthit
537               
538               else
539                 {
540                   //closest hit does not exist
541                   point = fNumRowSegment; //continue with next hit in segment
542                 }//else
543               
544             }//create tracks
545           
546           //store track chi2:
547           track->SetChiSq1(xyChi2);
548           track->SetChiSq2(szChi2);
549           Double_t normalizedchi2 = (track->GetChiSq1()+track->GetChiSq2())/track->GetNumberOfPoints();
550           
551           //remove tracks with not enough points already now
552           if(track->GetNumberOfPoints() < fMinPoints[fVertexConstraint] || normalizedchi2 > fTrackChi2Cut[fVertexConstraint])
553             {
554               track->SetProperties(false);
555               fNTracks--;
556               track->DeleteCandidate();
557               fTrack->RemoveLast();
558               tracks--;
559             }
560           
561           else
562             {
563               fClustersUnused -= track->GetNumberOfPoints();
564               track->ComesFromMainVertex(fVertexConstraint);
565               //mark track as main vertex track or not
566               track->SetSector(2); //only needed for testing purposes.
567               track->SetRowRange(fRowMin,fRowMax);
568
569               if(fVertexConstraint) 
570                 fMainVertexTracks++;
571             }
572      
573         }//good tracklet
574       
575     }
576   
577   return;
578 }
579
580 AliHLTTPCConfMapPoint *AliHLTTPCConfMapper::GetNextNeighbor(AliHLTTPCConfMapPoint *starthit,
581                                           AliHLTTPCConfMapTrack *track)
582 {
583   //When forming segments: Finds closest hit to input hit
584   //When forming tracks: Find closest hit to track fit.
585   
586   Double_t dist,closestdist = fMaxDist[fVertexConstraint];
587   
588   AliHLTTPCConfMapPoint *hit = NULL;
589   AliHLTTPCConfMapPoint *closesthit = NULL;
590     
591   Int_t subrowsegm;
592   Int_t subphisegm;
593   Int_t subetasegm;
594   Int_t volumeIndex;
595   Int_t testhit;
596
597   Int_t maxrow = starthit->GetPadRow()-1;
598   Int_t minrow;
599
600   if(track) //finding hit close to trackfit
601     {
602       minrow = starthit->GetPadRow()-fRowScopeTrack[fVertexConstraint];
603     }
604   else
605     {
606       minrow = starthit->GetPadRow()-fRowScopeTracklet[fVertexConstraint];
607     }
608
609   //make a smart loop
610   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};
611   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};
612   
613   if(minrow < fRowMin)
614     minrow = fRowMin;
615   if(maxrow < fRowMin)
616     return 0;  //reached the last padrow under consideration
617
618   else
619     {
620       //loop over sub rows
621       for(subrowsegm=maxrow; subrowsegm>=minrow; subrowsegm--)
622         {
623           //loop over subsegments, in the order defined above.
624           for(Int_t i=0; i<9; i++)  
625             {
626               subphisegm = starthit->GetPhiIndex() + loopphi[i];
627               
628               if(subphisegm < 0 || subphisegm >= fNumPhiSegment)
629                 continue;
630               /*
631                 if(subphisegm<0)
632                 subphisegm += fNumPhiSegment;
633                 
634                 else if(subphisegm >=fNumPhiSegment)
635                 subphisegm -= fNumPhiSegment;
636               */
637               //loop over sub eta segments
638               
639               subetasegm = starthit->GetEtaIndex() + loopeta[i];
640               
641               if(subetasegm < 0 || subetasegm >=fNumEtaSegment)
642                 continue;//segment exceeds bounds->skip it
643               
644               //loop over hits in this sub segment:
645               volumeIndex=(subrowsegm-fRowMin)*fNumPhiEtaSegmentPlusOne +
646                 subphisegm*fNumEtaSegmentPlusOne + subetasegm;
647               
648               if(volumeIndex<0)
649                 {//debugging
650                   LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::GetNextNeighbor","Memory")<<AliHLTTPCLog::kDec<<
651                     "VolumeIndex error "<<volumeIndex<<ENDLOG;
652                 }
653               
654               for(hit = (AliHLTTPCConfMapPoint*)fVolume[volumeIndex].first;
655                   hit!=0; hit = hit->GetNextVolumeHit())
656                 {
657                   
658                   if(!hit->GetUsage())
659                     {//hit was not used before
660                       
661                       //set conformal mapping if looking for nonvertex tracks:
662                       if(!fVertexConstraint)
663                         {
664                           hit->SetAllCoord(starthit);
665                         }
666                      
667                       if(track)//track search - look for nearest neighbor to extrapolated track
668                         {
669 // BEGINN ############################################## MODIFIY JMT
670 #if 1
671                             if (fVertexConstraint) {   
672                                 if(!VerifyRange(starthit,hit))
673                                     continue;
674                             }
675 #else
676                           if(!VerifyRange(starthit,hit))
677                             continue;
678 #endif
679 // END ################################################# MODIFIY JMT                      
680                           testhit = EvaluateHit(starthit,hit,track);
681                           
682                           if(testhit == 0)//chi2 not good enough, keep looking
683                             continue;
684                           else if(testhit==2)//chi2 good enough, return it
685                             return hit;
686                           else
687                             closesthit = hit;//chi2 acceptable, but keep looking
688                           
689                         }//track search
690                       
691                       else //tracklet search, look for nearest neighbor
692                         {
693                           
694                           if((dist=CalcDistance(starthit,hit)) < closestdist)
695                             {
696 // BEGINN ############################################## MODIFIY JMT
697 #if 1
698                             if (fVertexConstraint) {   
699                                 if(!VerifyRange(starthit,hit))
700                                     continue;
701                             }
702 #else
703                           if(!VerifyRange(starthit,hit))
704                             continue;
705 #endif
706 // END ################################################# MODIFIY JMT    
707                               closestdist = dist;
708                               closesthit = hit;
709                          
710                               //if this hit is good enough, return it:
711                               if(closestdist < fGoodDist)
712                                 return closesthit;
713                             }
714                           else
715                             continue;//sub hit was farther away than a hit before
716                           
717                         }//tracklet search
718                       
719                     }//hit not used before
720                   
721                   else continue; //sub hit was used before
722                   
723                 }//loop over hits in sub segment
724                       
725             }//loop over sub segments
726                   
727         }//loop over subrows
728       
729     }//else
730
731   //closest hit found:
732   if(closesthit)// && closestdist < mMaxDist)
733     return closesthit;
734   else
735     return 0;
736 }
737
738 Int_t AliHLTTPCConfMapper::EvaluateHit(AliHLTTPCConfMapPoint *starthit,AliHLTTPCConfMapPoint *hit,AliHLTTPCConfMapTrack *track) 
739 {
740   //Check if space point gives a fit with acceptable chi2.
741   
742   Double_t temp,dxy,lchi2,dx,dy,slocal,dsz,lszChi2;
743   temp = (track->GetA2Xy()*hit->GetXprime()-hit->GetYprime()+track->GetA1Xy());
744   dxy = temp*temp/(track->GetA2Xy()*track->GetA2Xy() + 1.);
745   
746   //Calculate chi2
747   lchi2 = (dxy*hit->GetXYWeight());
748   
749   if(lchi2 > track->GetChiSq1())//chi2 was worse than before.
750     return 0;
751     
752   //calculate s and the distance hit-line
753   dx = starthit->GetX()-hit->GetX();
754   dy = starthit->GetY()-hit->GetY();
755   //slocal = track->fLength+sqrt(dx*dx+dy*dy);
756   slocal = track->GetLength()+sqrt(dx*dx+dy*dy);
757   
758   temp = (track->GetA2Sz()*slocal-hit->GetZ()+track->GetA1Sz());
759   dsz = temp*temp/(track->GetA2Sz()*track->GetA2Sz()+1);
760   
761   //calculate chi2
762   lszChi2 = dsz*hit->GetZWeight();
763   lchi2 += lszChi2;
764   
765     
766   //check whether chi2 is better than previous one:
767   if(lchi2 < track->GetChiSq1())
768     {
769       track->SetChiSq1(lchi2);
770       track->SetChiSq2(lszChi2);
771     
772       hit->SetS(slocal);
773   
774       //if chi2 good enough, stop here:
775       if(lchi2 < fGoodHitChi2[fVertexConstraint]) 
776         return 2;
777       
778       return 1;
779     }
780   
781   return 0;
782   
783 }
784
785 Double_t AliHLTTPCConfMapper::CalcDistance(const AliHLTTPCConfMapPoint *hit1,const AliHLTTPCConfMapPoint *hit2) const
786 {
787   //Return distance between two clusters, defined by Pablo
788   
789   Double_t phidiff = fabs( hit1->GetPhi() - hit2->GetPhi() );
790   if (phidiff > AliHLTTPCTransform::Pi()) phidiff = AliHLTTPCTransform::TwoPi() - phidiff;
791   
792   return AliHLTTPCTransform::ToDeg()*fabs((Float_t)((hit1->GetPadRow() - hit2->GetPadRow()) * 
793          (phidiff + fabs( hit1->GetEta() - hit2->GetEta()))));
794 }
795
796 Bool_t AliHLTTPCConfMapper::VerifyRange(const AliHLTTPCConfMapPoint *hit1,const AliHLTTPCConfMapPoint *hit2) const
797 {
798   //Check if the hit are within reasonable range in phi and eta
799   Double_t dphi,deta;//maxphi=0.1,maxeta=0.1;
800   dphi = fabs(hit1->GetPhi() - hit2->GetPhi());
801   if(dphi > AliHLTTPCTransform::Pi()) dphi = fabs(AliHLTTPCTransform::TwoPi() - dphi);
802   if(dphi > fMaxPhi) return false;
803   
804   deta = fabs(hit1->GetEta() - hit2->GetEta());
805   if(deta > fMaxEta) return false;
806
807   return true;
808
809 }
810
811 Double_t AliHLTTPCConfMapper::TrackletAngle(AliHLTTPCConfMapTrack *track,Int_t n) const
812 {
813   // Returns the angle 'between' the last three points (started at point number n) on this track.
814   
815   if(n > track->GetNumberOfPoints())
816     n = track->GetNumberOfPoints();
817   
818   if(n<3)
819     return 0;
820   
821   Double_t x1[2];
822   Double_t x2[2];
823   Double_t x3[2];
824   Double_t angle1,angle2;
825   Int_t counter=0;
826   for(track->StartLoop(); track->LoopDone(); track->GetNextHit())
827     {
828       AliHLTTPCConfMapPoint *p = (AliHLTTPCConfMapPoint*)track->GetCurrentHit();
829       if( (n-1) == counter)
830         {
831           x1[0] = p->GetX();
832           x1[1] = p->GetY();
833         }
834       else if( (n-2) == counter)
835         {
836           x2[0] = p->GetX();
837           x2[1] = p->GetY();
838         }
839       else if( (n-3) == counter)
840         {
841           x3[0] = p->GetX();
842           x3[1] = p->GetY();
843         }
844       counter++;
845     }
846   
847   angle1 = atan2(x2[1]-x3[1],x2[0]-x3[0]);
848   angle2 = atan2(x1[1]-x2[1],x1[0]-x2[0]);
849   
850   return fabs(angle1-angle2);
851   
852   /*
853     Double_t x1[2];
854   Double_t x2[2];
855   Double_t angle1,angle2;
856   TObjArray *hits = track->GetHits();
857   
858   if (n > track->GetNumberOfPoints()) {
859     n = track->GetNumberOfPoints();
860   }
861
862   if (n<3) 
863     return 0;
864   
865
866   x1[0] = ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetX() - ((AliHLTTPCConfMapPoint *)hits->At(n-3))->GetX();
867   x1[1] = ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetY() - ((AliHLTTPCConfMapPoint *)hits->At(n-3))->GetY();
868
869   x2[0] = ((AliHLTTPCConfMapPoint *)hits->At(n-1))->GetX() - ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetX();
870   x2[1] = ((AliHLTTPCConfMapPoint *)hits->At(n-1))->GetY() - ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetY();
871   
872   angle1 = atan2(x1[1],x1[0]);
873   angle2 = atan2(x2[1],x1[0]);
874   return fabs(angle1-angle2);
875   */
876 }
877
878 Int_t AliHLTTPCConfMapper::FillTracks()
879 {
880   //Fill track parameters. Which basically means do a fit of helix in real space,
881   //which should be done in order to get nice tracks.
882   
883   Int_t numoftracks = fNTracks;
884   if(fNTracks == 0)
885     {
886       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::FillTracks","fNTracks")<<AliHLTTPCLog::kDec<<
887         "No tracks found!!"<<ENDLOG;
888       return 0;
889     }
890
891   LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::FillTracks","fNTracks")<<AliHLTTPCLog::kDec<<
892     "Number of found tracks: "<<fNTracks<<ENDLOG;
893   
894   //  fTrack->Sort();
895   for(Int_t i=0; i<numoftracks; i++)
896     {
897       AliHLTTPCConfMapTrack *track = (AliHLTTPCConfMapTrack*)fTrack->GetTrack(i);
898       track->Fill(fVertex,fMaxDca);
899     }
900   return 1;
901 }
902
903 Double_t AliHLTTPCConfMapper::CpuTime()
904 {
905   //Return the Cputime in seconds.
906  struct timeval tv;
907  gettimeofday( &tv, NULL );
908  return tv.tv_sec+(((Double_t)tv.tv_usec)/1000000.);
909 }