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