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