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