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