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