]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TPCLib/AliHLTTPCConfMapper.cxx
using new TPC offline functions (r27421) to significantly speed up the reconstruction...
[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   fClusterCutZ(-1)
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(fClusterCutZ == -1){
178     if (fHit.size()<fClustersUnused+count) fHit.resize(fClustersUnused+count);
179     assert(fHit.size()>=fClustersUnused+count);
180     for (Int_t i=0;(UInt_t)i<count;i++)
181       { 
182         fHit[i+fClustersUnused].Reset();
183         fHit[i+fClustersUnused].Read(hits[i]);
184       }
185     fClustersUnused += count;
186   }
187   else{
188     //Skipping clusters with high Z. 
189     UInt_t skipped=0;
190     
191     if (fHit.size()<fClustersUnused+count) fHit.resize(fClustersUnused+count);
192     assert(fHit.size()>=fClustersUnused+count);
193     for (Int_t i=0;(UInt_t)i<count;i++)
194       {   
195         if(hits[i].fZ > fClusterCutZ || hits[i].fZ < -1*fClusterCutZ){
196           ++skipped;
197           continue;
198         }
199         fHit[i+fClustersUnused-skipped].Reset();
200         fHit[i+fClustersUnused-skipped].Read(hits[i]);
201       }
202     fClustersUnused += count - skipped;
203     fHit.resize(fClustersUnused);
204   }
205
206   LOG(AliHLTTPCLog::kDebug,"AliHLTTPCConfMapper::ReadHits","#hits")
207     <<AliHLTTPCLog::kDec<<"#hits: "<<count<<" total: "<<fClustersUnused<<ENDLOG;
208   
209   return true;
210 }
211
212 void AliHLTTPCConfMapper::SetPointers()
213 {
214   //Check if there are not enough clusters to make a track in this sector
215   //Can happen in pp events.
216
217   if(fClustersUnused < fMinPoints[fVertexConstraint])
218     return;
219   
220   //Allocate detector volumes
221   if (fVolume==NULL) {
222     LOG(AliHLTTPCLog::kDebug,"AliHLTTPCConfMapper::InitVolumes","Memory")<<AliHLTTPCLog::kDec<<
223       "Allocating "<<fBounds*sizeof(AliHLTTPCConfMapContainer)<<" Bytes to fVolume"<<ENDLOG;
224     fVolume = new AliHLTTPCConfMapContainer[fBounds];
225   }
226
227   if (fRow==NULL) {
228     LOG(AliHLTTPCLog::kDebug,"AliHLTTPCConfMapper::InitVolumes","Memory")<<AliHLTTPCLog::kDec<<
229       "Allocating "<<fNumRowSegmentPlusOne*sizeof(AliHLTTPCConfMapContainer)<<" Bytes to fRow"<<ENDLOG;
230     fRow = new AliHLTTPCConfMapContainer[fNumRowSegmentPlusOne];
231   }
232   
233   memset(fVolume,0,fBounds*sizeof(AliHLTTPCConfMapContainer));
234   memset(fRow,0,fNumRowSegmentPlusOne*sizeof(AliHLTTPCConfMapContainer));
235   
236   Float_t phiSlice = (fPhiMax-fPhiMin)/fNumPhiSegment;
237   Float_t etaSlice = (fEtaMax-fEtaMin)/fNumEtaSegment;
238
239   Int_t volumeIndex;
240   Int_t localcounter=0;
241   assert((int)fHit.size()>=fClustersUnused);
242   for(Int_t j=0; j<fClustersUnused; j++)
243     {
244       AliHLTTPCConfMapPoint *thisHit = &(fHit[j]);
245
246       thisHit->Setup(fVertex);
247       
248       Int_t localrow = thisHit->GetPadRow();
249       
250       if(localrow < fRowMin || localrow > fRowMax)
251         continue;
252
253       //Get indexes:
254       thisHit->SetPhiIndex((Int_t)((thisHit->GetPhi()-fPhiMin)/phiSlice +1));
255       
256       if(thisHit->GetPhiIndex()<1 || thisHit->GetPhiIndex()>fNumPhiSegment)
257         {
258           //cout << "Phiindex: " << thisHit->phiIndex << " " << thisHit->GetPhi() << endl;
259           fPhiHitsOutOfRange++;
260           continue;
261         }
262       
263       thisHit->SetEtaIndex((Int_t)((thisHit->GetEta()-fEtaMin)/etaSlice + 1));
264       if(thisHit->GetEtaIndex()<1 || thisHit->GetEtaIndex()>fNumEtaSegment)
265         {
266           //cout << "Etaindex: " << thisHit->etaIndex << " " << thisHit->GetEta() << endl;
267           fEtaHitsOutOfRange++;
268           continue;
269         }
270       localcounter++;
271       
272       volumeIndex = (localrow-fRowMin)*fNumPhiEtaSegmentPlusOne + 
273                     thisHit->GetPhiIndex()*fNumEtaSegmentPlusOne+thisHit->GetEtaIndex();
274       
275       if(fVolume[volumeIndex].first == NULL)
276         fVolume[volumeIndex].first = (void *)thisHit;
277       else
278         ((AliHLTTPCConfMapPoint *)fVolume[volumeIndex].last)->SetNextVolumeHit(thisHit);
279       fVolume[volumeIndex].last = (void *)thisHit;
280       
281       
282       //set row pointers
283       if(fRow[(localrow-fRowMin)].first == NULL)
284         fRow[(localrow-fRowMin)].first = (void *)thisHit;
285       else
286         ((AliHLTTPCConfMapPoint *)(fRow[(localrow-fRowMin)].last))->SetNextRowHit(thisHit);
287         fRow[(localrow-fRowMin)].last = (void *)thisHit;
288     }
289   
290   // Matthias 2008-03-25
291   // I'm not really sure if this is en error condition. Has to be investigated.
292   // With the ifdef below, the message is only printed if the library was build
293   // in the HLT build system. By that we avoid irritating messages for the
294   // reconstruction included into the Grid tests
295 #ifdef PACKAGE_STRING
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::kDebug,"AliHLTTPCConfMapper::SetPointers","Setup")
303     <<"Setup finished, hits out of range: "<<fEtaHitsOutOfRange+fPhiHitsOutOfRange
304     <<" hits accepted "<<hits_accepted<<ENDLOG;
305 #endif //PACKAGE_STRING
306 }
307
308 void AliHLTTPCConfMapper::MainVertexTrackingA()
309 {
310   //Tracking with vertex constraint.
311
312   if(!fParamSet[(Int_t)kTRUE])
313     {
314       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::MainVertexTracking","Parameters")<<AliHLTTPCLog::kDec<<
315         "Tracking parameters not set!"<<ENDLOG;
316       return;
317     }
318
319   Double_t initCpuTime,cpuTime;
320   initCpuTime = CpuTime();
321
322   SetPointers();
323   SetVertexConstraint(true);
324   cpuTime = CpuTime() - initCpuTime;
325   if(fBench)
326     LOG(AliHLTTPCLog::kBenchmark,"AliHLTTPCConfMapper::MainVertexTrackingA","Timing")
327       <<AliHLTTPCLog::kDec<<"Setup finished in "<<cpuTime*1000<<" ms"<<ENDLOG;
328   
329 }
330
331 void AliHLTTPCConfMapper::MainVertexTrackingB()
332 {
333   //Tracking with vertex constraint.
334
335   if(!fParamSet[(Int_t)kTRUE])
336     {
337       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::MainVertexTracking","Parameters")<<AliHLTTPCLog::kDec<<
338         "Tracking parameters not set!"<<ENDLOG;
339       return;
340     }
341   Double_t initCpuTime,cpuTime;
342   initCpuTime = CpuTime();
343   
344   ClusterLoop();
345  
346   cpuTime = CpuTime() - initCpuTime;
347   if(fBench)
348     LOG(AliHLTTPCLog::kBenchmark,"AliHLTTPCConfMapper::MainVertexTrackingB","Timing")
349       <<AliHLTTPCLog::kDec<<"Main Tracking finished in "<<cpuTime*1000<<" ms"<<ENDLOG;
350 }
351
352 void AliHLTTPCConfMapper::MainVertexTracking()
353 {
354   //Tracking with vertex constraint.
355
356   if(!fParamSet[(Int_t)kTRUE])
357     {
358       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::MainVertexTracking","Parameters")<<AliHLTTPCLog::kDec<<
359         "Tracking parameters not set!"<<ENDLOG;
360       return;
361     }
362
363   Double_t initCpuTime,cpuTime;
364   initCpuTime = CpuTime();
365
366   SetPointers(); 
367
368   SetVertexConstraint(true);
369       
370   ClusterLoop();
371
372   cpuTime = CpuTime() - initCpuTime;
373   if(fBench)
374     LOG(AliHLTTPCLog::kBenchmark,"AliHLTTPCConfMapper::MainVertexTracking","Timing")<<AliHLTTPCLog::kDec<<
375       "Tracking finished in "<<cpuTime*1000<<" ms"<<ENDLOG;
376   
377   return;
378 }
379
380 void AliHLTTPCConfMapper::NonVertexTracking()
381 {
382   //Tracking with no vertex constraint. This should be called after doing MainVertexTracking,
383   //in order to do tracking on the remaining clusters.
384   //The conformal mapping is now done with respect to the first cluster
385   //assosciated with this track.
386   
387   if(!fParamSet[(Int_t)kFALSE])
388     {
389       LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::NonVertexTracking","Parameters")<<AliHLTTPCLog::kDec<<
390         "Tracking parameters not set!"<<ENDLOG;
391       return;
392     }
393   
394   SetVertexConstraint(false);
395   
396   SetPointers(); //To be able to do only nonvertextracking (more testing) 
397   
398   ClusterLoop();
399   LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::NonVertexTracking","ntracks")<<AliHLTTPCLog::kDec<<
400     "Number of nonvertex tracks found: "<<(fNTracks-fMainVertexTracks)<<ENDLOG;
401   return;
402 }
403
404 void AliHLTTPCConfMapper::MainVertexSettings(Int_t trackletlength, Int_t tracklength,
405                                          Int_t rowscopetracklet, Int_t rowscopetrack,
406                                          Double_t maxphi,Double_t maxeta)
407 {
408   //Settings for main vertex tracking. The cuts are:
409   //TrackletLength:      #hits on segment, before trying to build a track
410   //TrackLength:         Minimum hits on a track
411   //RowScopeTracklet:    Row search range for segments
412   //RowScopeTrack:       Row search range for tracks
413   
414   SetTrackletLength(trackletlength,(Bool_t)true);
415   SetRowScopeTracklet(rowscopetracklet, (Bool_t) true);
416   SetRowScopeTrack(rowscopetrack, (Bool_t) true);
417   SetMinPoints(tracklength,(Bool_t)true);
418   fMaxPhi=maxphi;
419   fMaxEta=maxeta;
420   SetParamDone(kTRUE);
421 }
422
423 void AliHLTTPCConfMapper::NonVertexSettings(Int_t trackletlength, Int_t tracklength,
424                                         Int_t rowscopetracklet, Int_t rowscopetrack)
425 {
426   //set parameters for non-vertex tracking
427   SetTrackletLength(trackletlength,(Bool_t)false);
428   SetRowScopeTracklet(rowscopetracklet, (Bool_t)false);
429   SetRowScopeTrack(rowscopetrack, (Bool_t)false);
430   SetMinPoints(tracklength,(Bool_t)false);
431   SetParamDone(kFALSE);
432 }
433
434 void AliHLTTPCConfMapper::SetTrackCuts(Double_t hitChi2Cut, Double_t goodHitChi2, Double_t trackChi2Cut,Int_t maxdist,Bool_t vertexconstraint)
435 {
436   //Settings for tracks. The cuts are:
437   //HitChi2Cut:     Maximum hit chi2
438   //goodHitChi2:    Chi2 to stop look for next hit
439   //trackChi2Cut:   Maximum track chi2
440   //maxdist:        Maximum distance between two clusters when forming segments
441   
442   SetHitChi2Cut(hitChi2Cut,vertexconstraint);
443   SetGoodHitChi2(goodHitChi2,vertexconstraint);
444   SetTrackChi2Cut(trackChi2Cut,vertexconstraint);
445   SetMaxDist(maxdist,vertexconstraint);
446 }
447
448 void AliHLTTPCConfMapper::SetTrackletCuts(Double_t maxangle,Double_t goodDist, Bool_t vc)
449 {
450   //Sets cuts of tracklets. Right now this is only:
451   //maxangle:  Maximum angle when forming segments (if trackletlength > 2)
452  
453   fGoodDist=goodDist;
454   SetMaxAngleTracklet(maxangle, vc);
455 }
456
457 void AliHLTTPCConfMapper::ClusterLoop()
458 {
459   //Loop over hits, starting at outermost padrow, and trying to build segments.
460   
461   //Check if there are not enough clusters to make a track in this sector
462   //Can happen in pp events.
463   if(fClustersUnused < fMinPoints[fVertexConstraint])
464     return;
465   
466   Int_t rowsegm,lastrow = fRowMin + fMinPoints[fVertexConstraint];
467   AliHLTTPCConfMapPoint *hit;
468   
469   //Loop over rows, and try to create tracks from the hits.
470   //Starts at the outermost row, and loops as long as a track can be build, due to length.
471   
472   for(rowsegm = fRowMax; rowsegm >= lastrow; rowsegm--)
473     {
474       if(fRow[(rowsegm-fRowMin)].first && ((AliHLTTPCConfMapPoint*)fRow[(rowsegm-fRowMin)].first)->GetPadRow() < fRowMin + 1)
475         break;
476
477       for(hit = (AliHLTTPCConfMapPoint*)fRow[(rowsegm-fRowMin)].first; hit!=0; hit=hit->GetNextRowHit())
478         {
479           if(hit->GetUsage() == true)
480             continue;
481           else
482             CreateTrack(hit);
483         }
484     }
485   
486   return;
487 }
488
489
490 void AliHLTTPCConfMapper::CreateTrack(AliHLTTPCConfMapPoint *hit)
491 {
492   //Tries to create a track from the initial hit given by ClusterLoop()
493
494   AliHLTTPCConfMapPoint *closesthit = NULL;
495   AliHLTTPCConfMapTrack *track = NULL;
496   
497   Int_t point;
498   Int_t tracks = fNTracks;
499   fNTracks++;
500
501   track = (AliHLTTPCConfMapTrack*)fTrack->NextTrack();
502
503   //reset hit parameters:
504   track->Reset();
505   
506   UInt_t *trackhitnumber = track->GetHitNumbers();
507     
508   //set conformal coordinates if we are looking for non vertex tracks
509   if(!fVertexConstraint) 
510     {
511       hit->SetAllCoord(hit);
512     }
513   
514   //fill fit parameters of initial track:
515   track->UpdateParam(hit); //here the number of hits is incremented.
516   trackhitnumber[track->GetNumberOfPoints()-1] = hit->GetHitNumber();
517   
518   Double_t dx,dy;
519   //create tracklets:
520   
521   for(point=1; point<fTrackletLength[fVertexConstraint]; point++)
522     {
523       if((closesthit = GetNextNeighbor(hit)))
524         {//closest hit exist
525           
526           //   Calculate track length in sz plane
527           dx = ((AliHLTTPCConfMapPoint*)closesthit)->GetX() - ((AliHLTTPCConfMapPoint*)hit)->GetX();
528           dy = ((AliHLTTPCConfMapPoint*)closesthit)->GetY() - ((AliHLTTPCConfMapPoint*)hit)->GetY();
529           //track->fLength += (Double_t)sqrt ( dx * dx + dy * dy ) ;
530           Double_t length = track->GetLength()+(Double_t)sqrt ( dx * dx + dy * dy );
531           track->SetLength(length);
532
533           //closesthit->SetS(track->fLength);
534           closesthit->SetS(track->GetLength());
535
536           //update fit parameters
537           track->UpdateParam(closesthit);
538           trackhitnumber[track->GetNumberOfPoints()-1] = closesthit->GetHitNumber();
539         
540           hit = closesthit;
541         }
542       else
543         {
544           //closest hit does not exist:
545           track->DeleteCandidate();
546           fTrack->RemoveLast();
547           fNTracks--;
548           point = fTrackletLength[fVertexConstraint];
549         }
550     }
551   
552   //tracklet is long enough to be extended to a track
553   if(track->GetNumberOfPoints() == fTrackletLength[fVertexConstraint])
554     {
555       
556       track->SetProperties(true);
557             
558       if(TrackletAngle(track) > fMaxAngleTracklet[fVertexConstraint])
559         {//proof if the first points seem to be a beginning of a track
560           track->SetProperties(false);
561           track->DeleteCandidate();
562           fTrack->RemoveLast();
563           fNTracks--;
564         }
565       
566       else//good tracklet ->proceed, follow the trackfit
567         {
568           tracks++;
569                                   
570           //define variables to keep the total chi:
571           Double_t xyChi2 = track->GetChiSq1();
572           Double_t szChi2 = track->GetChiSq2();
573           
574           for(point = fTrackletLength[fVertexConstraint]; point <= fNumRowSegment; point++)
575             {
576               track->SetChiSq1(fHitChi2Cut[fVertexConstraint]);
577               closesthit = GetNextNeighbor((AliHLTTPCConfMapPoint*)track->GetLastHit(),track);
578               
579               if(closesthit)
580                 {
581                   //keep total chi:
582                   Double_t lxyChi2 = track->GetChiSq1()-track->GetChiSq2();
583                   xyChi2 += lxyChi2;
584                   closesthit->SetXYChi2(lxyChi2);
585                                   
586                   //update track length:
587                   track->SetLength(closesthit->GetS());
588                   szChi2 += track->GetChiSq2();
589                   closesthit->SetSZChi2(track->GetChiSq2());
590                   
591                   track->UpdateParam(closesthit);
592                   trackhitnumber[track->GetNumberOfPoints()-1] = closesthit->GetHitNumber();
593                   
594                   //add closest hit to track
595                   closesthit->SetUsage(true);
596                   closesthit->SetTrackNumber(tracks-1);
597                   
598                 }//closesthit
599               
600               else
601                 {
602                   //closest hit does not exist
603                   point = fNumRowSegment; //continue with next hit in segment
604                 }//else
605               
606             }//create tracks
607           
608           //store track chi2:
609           track->SetChiSq1(xyChi2);
610           track->SetChiSq2(szChi2);
611           Double_t normalizedchi2 = (track->GetChiSq1()+track->GetChiSq2())/track->GetNumberOfPoints();
612           
613           //remove tracks with not enough points already now
614           if(track->GetNumberOfPoints() < fMinPoints[fVertexConstraint] || normalizedchi2 > fTrackChi2Cut[fVertexConstraint])
615             {
616               track->SetProperties(false);
617               fNTracks--;
618               track->DeleteCandidate();
619               fTrack->RemoveLast();
620               tracks--;
621             }
622           
623           else
624             {
625               fClustersUnused -= track->GetNumberOfPoints();
626               track->ComesFromMainVertex(fVertexConstraint);
627               //mark track as main vertex track or not
628               track->SetSector(2); //only needed for testing purposes.
629               track->SetRowRange(fRowMin,fRowMax);
630
631               if(fVertexConstraint) 
632                 fMainVertexTracks++;
633             }
634      
635         }//good tracklet
636       
637     }
638   
639   return;
640 }
641
642 AliHLTTPCConfMapPoint *AliHLTTPCConfMapper::GetNextNeighbor(AliHLTTPCConfMapPoint *starthit,
643                                           AliHLTTPCConfMapTrack *track)
644 {
645   //When forming segments: Finds closest hit to input hit
646   //When forming tracks: Find closest hit to track fit.
647   
648   Double_t dist,closestdist = fMaxDist[fVertexConstraint];
649   
650   AliHLTTPCConfMapPoint *hit = NULL;
651   AliHLTTPCConfMapPoint *closesthit = NULL;
652     
653   Int_t subrowsegm;
654   Int_t subphisegm;
655   Int_t subetasegm;
656   Int_t volumeIndex;
657   Int_t testhit;
658
659   Int_t maxrow = starthit->GetPadRow()-1;
660   Int_t minrow;
661
662   if(track) //finding hit close to trackfit
663     {
664       minrow = starthit->GetPadRow()-fRowScopeTrack[fVertexConstraint];
665     }
666   else
667     {
668       minrow = starthit->GetPadRow()-fRowScopeTracklet[fVertexConstraint];
669     }
670
671   //make a smart loop
672   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};
673   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};
674   
675   if(minrow < fRowMin)
676     minrow = fRowMin;
677   if(maxrow < fRowMin)
678     return 0;  //reached the last padrow under consideration
679
680   else
681     {
682       //loop over sub rows
683       for(subrowsegm=maxrow; subrowsegm>=minrow; subrowsegm--)
684         {
685           //loop over subsegments, in the order defined above.
686           for(Int_t i=0; i<9; i++)  
687             {
688               subphisegm = starthit->GetPhiIndex() + loopphi[i];
689               
690               if(subphisegm < 0 || subphisegm >= fNumPhiSegment)
691                 continue;
692               /*
693                 if(subphisegm<0)
694                 subphisegm += fNumPhiSegment;
695                 
696                 else if(subphisegm >=fNumPhiSegment)
697                 subphisegm -= fNumPhiSegment;
698               */
699               //loop over sub eta segments
700               
701               subetasegm = starthit->GetEtaIndex() + loopeta[i];
702               
703               if(subetasegm < 0 || subetasegm >=fNumEtaSegment)
704                 continue;//segment exceeds bounds->skip it
705               
706               //loop over hits in this sub segment:
707               volumeIndex=(subrowsegm-fRowMin)*fNumPhiEtaSegmentPlusOne +
708                 subphisegm*fNumEtaSegmentPlusOne + subetasegm;
709               
710               if(volumeIndex<0)
711                 {//debugging
712                   LOG(AliHLTTPCLog::kError,"AliHLTTPCConfMapper::GetNextNeighbor","Memory")<<AliHLTTPCLog::kDec<<
713                     "VolumeIndex error "<<volumeIndex<<ENDLOG;
714                 }
715               
716               assert(fVolume!=NULL);
717               for(hit = (AliHLTTPCConfMapPoint*)fVolume[volumeIndex].first;
718                   hit!=0; hit = hit->GetNextVolumeHit())
719                 {
720                   
721                   if(!hit->GetUsage())
722                     {//hit was not used before
723                       
724                       //set conformal mapping if looking for nonvertex tracks:
725                       if(!fVertexConstraint)
726                         {
727                           hit->SetAllCoord(starthit);
728                         }
729                      
730                       if(track)//track search - look for nearest neighbor to extrapolated track
731                         {
732                           if (fVertexConstraint) {   
733                             if(!VerifyRange(starthit,hit))
734                               continue;
735                           }
736                           testhit = EvaluateHit(starthit,hit,track);
737                           
738                           if(testhit == 0)//chi2 not good enough, keep looking
739                             continue;
740                           else if(testhit==2)//chi2 good enough, return it
741                             return hit;
742                           else
743                             closesthit = hit;//chi2 acceptable, but keep looking
744                           
745                         }//track search
746                       
747                       else //tracklet search, look for nearest neighbor
748                         {
749                           
750                           if((dist=CalcDistance(starthit,hit)) < closestdist)
751                             {
752                               if (fVertexConstraint) {   
753                                 if(!VerifyRange(starthit,hit))
754                                   continue;
755                               }
756                               closestdist = dist;
757                               closesthit = hit;
758                          
759                               //if this hit is good enough, return it:
760                               if(closestdist < fGoodDist)
761                                 return closesthit;
762                             }
763                           else
764                             continue;//sub hit was farther away than a hit before
765                           
766                         }//tracklet search
767                       
768                     }//hit not used before
769                   
770                   else continue; //sub hit was used before
771                   
772                 }//loop over hits in sub segment
773                       
774             }//loop over sub segments
775                   
776         }//loop over subrows
777       
778     }//else
779
780   //closest hit found:
781   if(closesthit)// && closestdist < mMaxDist)
782     return closesthit;
783   else
784     return 0;
785 }
786
787 Int_t AliHLTTPCConfMapper::EvaluateHit(AliHLTTPCConfMapPoint *starthit,AliHLTTPCConfMapPoint *hit,AliHLTTPCConfMapTrack *track) 
788 {
789   //Check if space point gives a fit with acceptable chi2.
790   
791   Double_t temp,dxy,lchi2,dx,dy,slocal,dsz,lszChi2;
792   temp = (track->GetA2Xy()*hit->GetXprime()-hit->GetYprime()+track->GetA1Xy());
793   dxy = temp*temp/(track->GetA2Xy()*track->GetA2Xy() + 1.);
794   
795   //Calculate chi2
796   lchi2 = (dxy*hit->GetXYWeight());
797   
798   if(lchi2 > track->GetChiSq1())//chi2 was worse than before.
799     return 0;
800     
801   //calculate s and the distance hit-line
802   dx = starthit->GetX()-hit->GetX();
803   dy = starthit->GetY()-hit->GetY();
804   //slocal = track->fLength+sqrt(dx*dx+dy*dy);
805   slocal = track->GetLength()+sqrt(dx*dx+dy*dy);
806   
807   temp = (track->GetA2Sz()*slocal-hit->GetZ()+track->GetA1Sz());
808   dsz = temp*temp/(track->GetA2Sz()*track->GetA2Sz()+1);
809   
810   //calculate chi2
811   lszChi2 = dsz*hit->GetZWeight();
812   lchi2 += lszChi2;
813   
814     
815   //check whether chi2 is better than previous one:
816   if(lchi2 < track->GetChiSq1())
817     {
818       track->SetChiSq1(lchi2);
819       track->SetChiSq2(lszChi2);
820     
821       hit->SetS(slocal);
822   
823       //if chi2 good enough, stop here:
824       if(lchi2 < fGoodHitChi2[fVertexConstraint]) 
825         return 2;
826       
827       return 1;
828     }
829   
830   return 0;
831   
832 }
833
834 Double_t AliHLTTPCConfMapper::CalcDistance(const AliHLTTPCConfMapPoint *hit1,const AliHLTTPCConfMapPoint *hit2) const
835 {
836   //Return distance between two clusters, defined by Pablo
837   
838   Double_t phidiff = fabs( hit1->GetPhi() - hit2->GetPhi() );
839   if (phidiff > AliHLTTPCTransform::Pi()) phidiff = AliHLTTPCTransform::TwoPi() - phidiff;
840   
841   return AliHLTTPCTransform::ToDeg()*fabs((Float_t)((hit1->GetPadRow() - hit2->GetPadRow()) * 
842          (phidiff + fabs( hit1->GetEta() - hit2->GetEta()))));
843 }
844
845 Bool_t AliHLTTPCConfMapper::VerifyRange(const AliHLTTPCConfMapPoint *hit1,const AliHLTTPCConfMapPoint *hit2) const
846 {
847   //Check if the hit are within reasonable range in phi and eta
848   Double_t dphi,deta;//maxphi=0.1,maxeta=0.1;
849   dphi = fabs(hit1->GetPhi() - hit2->GetPhi());
850   if(dphi > AliHLTTPCTransform::Pi()) dphi = fabs(AliHLTTPCTransform::TwoPi() - dphi);
851   if(dphi > fMaxPhi) return false;
852   
853   deta = fabs(hit1->GetEta() - hit2->GetEta());
854   if(deta > fMaxEta) return false;
855
856   return true;
857
858 }
859
860 Double_t AliHLTTPCConfMapper::TrackletAngle(AliHLTTPCConfMapTrack *track,Int_t n) const
861 {
862   // Returns the angle 'between' the last three points (started at point number n) on this track.
863   
864   if(n > track->GetNumberOfPoints())
865     n = track->GetNumberOfPoints();
866   
867   if(n<3)
868     return 0;
869   
870   Double_t x1[2]={0,0};
871   Double_t x2[2]={0,0};
872   Double_t x3[2]={0,0};
873   Double_t angle1,angle2;
874   Int_t counter=0;
875   for(track->StartLoop(); track->LoopDone(); track->GetNextHit())
876     {
877       AliHLTTPCConfMapPoint *p = (AliHLTTPCConfMapPoint*)track->GetCurrentHit();
878       if( (n-1) == counter)
879         {
880           x1[0] = p->GetX();
881           x1[1] = p->GetY();
882         }
883       else if( (n-2) == counter)
884         {
885           x2[0] = p->GetX();
886           x2[1] = p->GetY();
887         }
888       else if( (n-3) == counter)
889         {
890           x3[0] = p->GetX();
891           x3[1] = p->GetY();
892         }
893       counter++;
894     }
895   
896   angle1 = atan2(x2[1]-x3[1],x2[0]-x3[0]);
897   angle2 = atan2(x1[1]-x2[1],x1[0]-x2[0]);
898   
899   return fabs(angle1-angle2);
900   
901   /*
902     Double_t x1[2];
903   Double_t x2[2];
904   Double_t angle1,angle2;
905   TObjArray *hits = track->GetHits();
906   
907   if (n > track->GetNumberOfPoints()) {
908     n = track->GetNumberOfPoints();
909   }
910
911   if (n<3) 
912     return 0;
913   
914
915   x1[0] = ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetX() - ((AliHLTTPCConfMapPoint *)hits->At(n-3))->GetX();
916   x1[1] = ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetY() - ((AliHLTTPCConfMapPoint *)hits->At(n-3))->GetY();
917
918   x2[0] = ((AliHLTTPCConfMapPoint *)hits->At(n-1))->GetX() - ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetX();
919   x2[1] = ((AliHLTTPCConfMapPoint *)hits->At(n-1))->GetY() - ((AliHLTTPCConfMapPoint *)hits->At(n-2))->GetY();
920   
921   angle1 = atan2(x1[1],x1[0]);
922   angle2 = atan2(x2[1],x1[0]);
923   return fabs(angle1-angle2);
924   */
925 }
926
927 Int_t AliHLTTPCConfMapper::FillTracks()
928 {
929   //Fill track parameters. Which basically means do a fit of helix in real space,
930   //which should be done in order to get nice tracks.
931   
932   Int_t numoftracks = fNTracks;
933   if(fNTracks == 0)
934     {
935       LOG(AliHLTTPCLog::kDebug,"AliHLTTPCConfMapper::FillTracks","fNTracks")<<AliHLTTPCLog::kDec<<
936         "No tracks found!!"<<ENDLOG;
937       return 0;
938     }
939
940   LOG(AliHLTTPCLog::kInformational,"AliHLTTPCConfMapper::FillTracks","fNTracks")<<AliHLTTPCLog::kDec<<
941     "Number of found tracks: "<<fNTracks<<ENDLOG;
942   
943   //  fTrack->Sort();
944   for(Int_t i=0; i<numoftracks; i++)
945     {
946       AliHLTTPCConfMapTrack *track = (AliHLTTPCConfMapTrack*)fTrack->GetTrack(i);
947       track->Fill(fVertex,fMaxDca);
948     }
949   return 1;
950 }
951
952 Double_t AliHLTTPCConfMapper::CpuTime()
953 {
954   //Return the Cputime in seconds.
955  struct timeval tv;
956  gettimeofday( &tv, NULL );
957  return tv.tv_sec+(((Double_t)tv.tv_usec)/1000000.);
958 }