]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TOF/AliTOFtrackerV2.cxx
Coverity fixes.
[u/mrichter/AliRoot.git] / TOF / AliTOFtrackerV2.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 /**************************************************************************
44  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
45  *                                                                        *
46  * Author: The ALICE Off-line Project.                                    *
47  * Contributors are mentioned in the code where appropriate.              *
48  *                                                                        *
49  * Permission to use, copy, modify and distribute this software and its   *
50  * documentation strictly for non-commercial purposes is hereby granted   *
51  * without fee, provided that the above copyright notice appears in all   *
52  * copies and that both the copyright notice and this permission notice   *
53  * appear in the supporting documentation. The authors make no claims     *
54  * about the suitability of this software for any purpose. It is          *
55  * provided "as is" without express or implied warranty.                  *
56  **************************************************************************/
57
58 //--------------------------------------------------------------------//
59 //                                                                    //
60 // AliTOFtrackerV2 Class                                              //
61 // Task: Perform association of the ESD tracks to TOF Clusters        //
62 // and Update ESD track with associated TOF Cluster parameters        //
63 //                                                                    //
64 // -- Authors : S. Arcelli, C. Zampolli (Bologna University and INFN) //
65 // -- Contacts: Annalisa.De.Caro@cern.ch                              //
66 // --         : Chiara.Zampolli@bo.infn.it                            //
67 // --         : Silvia.Arcelli@bo.infn.it                             //
68 //                                                                    //
69 //--------------------------------------------------------------------//
70
71 #include <Rtypes.h>
72 #include <TROOT.h>
73
74 #include <TClonesArray.h>
75 #include <TObjArray.h>
76 #include <TGeoManager.h>
77 #include <TTree.h>
78
79 #include "AliGeomManager.h"
80 #include "AliESDtrack.h"
81 #include "AliESDEvent.h"
82 #include "AliESDpid.h"
83 #include "AliESDTOFcluster.h"
84 #include "AliLog.h"
85 #include "AliTrackPointArray.h"
86 #include "AliCDBManager.h"
87
88 #include "AliTOFRecoParam.h"
89 #include "AliTOFReconstructor.h"
90 #include "AliTOFcluster.h"
91 #include "AliTOFGeometry.h"
92 #include "AliTOFtrackerV2.h"
93 #include "AliTOFtrack.h"
94
95 extern TGeoManager *gGeoManager;
96
97 ClassImp(AliTOFtrackerV2)
98
99 //_____________________________________________________________________________
100 AliTOFtrackerV2::AliTOFtrackerV2():
101   fkRecoParam(0x0),
102   fGeom(0x0),
103   fN(0),
104   fNseeds(0),
105   fNseedsTOF(0),
106   fnunmatch(0),
107   fnmatch(0),
108   fTracks(new TClonesArray("AliTOFtrack")),
109   fSeeds(new TObjArray(100)),
110   fClusters(0x0)
111 {
112   //AliTOFtrackerV2 main Ctor
113
114   // Getting the geometry
115   fGeom = new AliTOFGeometry();
116
117 }
118 //_____________________________________________________________________________
119 AliTOFtrackerV2::~AliTOFtrackerV2() {
120   //
121   // Dtor
122   //
123
124   if(!(AliCDBManager::Instance()->GetCacheFlag())){
125     delete fkRecoParam;
126   }
127   delete fGeom; 
128   if (fTracks){
129     fTracks->Delete();
130     delete fTracks;
131     fTracks=0x0;
132   }
133   if (fSeeds){
134     fSeeds->Delete();
135     delete fSeeds;
136     fSeeds=0x0;
137   }
138
139   if(fClusters){
140     delete[] fClusters;
141     fClusters = NULL;
142   }
143
144 }
145 //_____________________________________________________________________________
146 void AliTOFtrackerV2::GetPidSettings(AliESDpid *esdPID) {
147   // 
148   // Sets TOF resolution from RecoParams
149   //
150   if (fkRecoParam)
151     esdPID->GetTOFResponse().SetTimeResolution(fkRecoParam->GetTimeResolution());
152   else
153     AliWarning("fkRecoParam not yet set; cannot set PID settings");
154
155 //_____________________________________________________________________________
156 Int_t AliTOFtrackerV2::PropagateBack(AliESDEvent * const event) {
157   //
158   // Gets seeds from ESD event and Match with TOF Clusters
159   //
160
161   //Update the matched ESD tracks
162   // needed in case of call of TOF info before of the selection of matching and in case of no clusters available at all
163   if(fN==0)
164     event->SetTOFcluster(1,fClusters); 
165   else
166     event->SetTOFcluster(fN,fClusters);
167
168   if (fN==0) {
169     AliInfo("No TOF recPoints to be matched with reconstructed tracks");
170     return 0;
171   }
172
173   // initialize RecoParam for current event
174   AliDebug(1,"Initializing params for TOF");
175
176   fkRecoParam = AliTOFReconstructor::GetRecoParam();  // instantiate reco param from STEER...
177
178   if (fkRecoParam == 0x0) { 
179     AliFatal("No Reco Param found for TOF!!!");
180   }
181
182   //Initialise some counters
183
184   fNseeds=0;
185   fNseedsTOF=0;
186   fnunmatch=0;
187   fnmatch=0;
188
189   Int_t ntrk=event->GetNumberOfTracks();
190   fNseeds = ntrk;
191
192   //Load ESD tracks into a local Array of ESD Seeds
193   for (Int_t i=0; i<fNseeds; i++)
194     fSeeds->AddLast(event->GetTrack(i));
195
196   //Prepare ESD tracks candidates for TOF Matching
197   CollectESD();
198
199   if (fNseeds==0 || fNseedsTOF==0) {
200     AliInfo("No seeds to try TOF match");
201     return 0;
202   }
203
204   // clusterize before of matching
205   Clusterize();
206
207   //Second Step with Looser Matching Criterion
208   MatchTracks();
209
210   AliInfo(Form("Number of matched tracks = %d",fnmatch));
211
212   for (Int_t i=0; i<ntrk; i++) {
213     AliESDtrack *t=event->GetTrack(i);
214     //t->SetESDEvent(event);
215     AliESDtrack *seed =(AliESDtrack*)fSeeds->At(i);
216
217     if ( (seed->GetStatus()&AliESDtrack::kTOFin)!=0 ) {
218       t->SetStatus(AliESDtrack::kTOFin);
219       if ( (seed->GetStatus()&AliESDtrack::kTOFout)!=0 ) {
220         t->SetStatus(AliESDtrack::kTOFout);
221         //t->SetTOFclusterArray(seed->GetNTOFclusters(),seed->GetTOFclusterArray());
222         t->SortTOFcluster();
223
224         // Make attention, please:
225         //      AliESDtrack::fTOFInfo array does not be stored in the AliESDs.root file
226         //      it is there only for a check during the reconstruction step.
227         Float_t info[10]; seed->GetTOFInfo(info);
228         t->SetTOFInfo(info);
229         AliDebug(3,Form(" distance=%f; residual in the pad reference frame: dX=%f, dZ=%f", info[0],info[1],info[2]));
230
231         /*
232         Double_t alphaA = (Double_t)t->GetAlpha();
233         Double_t xA = (Double_t)t->GetX();
234         Double_t yA = (Double_t)t->GetY();
235         Double_t zA = (Double_t)t->GetZ();
236         Double_t p1A = (Double_t)t->GetSnp();
237         Double_t p2A = (Double_t)t->GetTgl();
238         Double_t p3A = (Double_t)t->GetSigned1Pt();
239         const Double_t *covA = (Double_t*)t->GetCovariance();
240
241         // Check done:
242         //       by calling the AliESDtrack::UpdateTrackParams,
243         //       the current track parameters are changed
244         //       and it could cause refit problems.
245         //       We need to update only the following track parameters:
246         //            the track length and expected times.
247         //       Removed AliESDtrack::UpdateTrackParams call
248         //       Called AliESDtrack::SetIntegratedTimes(...) and
249         //       AliESDtrack::SetIntegratedLength() routines.
250
251         AliTOFtrack *track = new AliTOFtrack(*seed);
252         t->UpdateTrackParams(track,AliESDtrack::kTOFout); // to be checked - AdC
253         delete track;
254         Double_t time[AliPID::kSPECIESC]; t->GetIntegratedTimes(time);
255         Double_t alphaB = (Double_t)t->GetAlpha();
256         Double_t xB = (Double_t)t->GetX();
257         Double_t yB = (Double_t)t->GetY();
258         Double_t zB = (Double_t)t->GetZ();
259         Double_t p1B = (Double_t)t->GetSnp();
260         Double_t p2B = (Double_t)t->GetTgl();
261         Double_t p3B = (Double_t)t->GetSigned1Pt();
262         const Double_t *covB = (Double_t*)t->GetCovariance();
263         AliDebug(2,"Track params -now(before)-:");
264         AliDebug(2,Form("    X: %f(%f), Y: %f(%f), Z: %f(%f) --- alpha: %f(%f)",
265                         xB,xA,
266                         yB,yA,
267                         zB,zA,
268                         alphaB,alphaA));
269         AliDebug(2,Form("    p1: %f(%f), p2: %f(%f), p3: %f(%f)",
270                         p1B,p1A,
271                         p2B,p2A,
272                         p3B,p3A));
273         AliDebug(2,Form("    cov1: %f(%f), cov2: %f(%f), cov3: %f(%f)"
274                         " cov4: %f(%f), cov5: %f(%f), cov6: %f(%f)"
275                         " cov7: %f(%f), cov8: %f(%f), cov9: %f(%f)"
276                         " cov10: %f(%f), cov11: %f(%f), cov12: %f(%f)"
277                         " cov13: %f(%f), cov14: %f(%f), cov15: %f(%f)",
278                         covB[0],covA[0],
279                         covB[1],covA[1],
280                         covB[2],covA[2],
281                         covB[3],covA[3],
282                         covB[4],covA[4],
283                         covB[5],covA[5],
284                         covB[6],covA[6],
285                         covB[7],covA[7],
286                         covB[8],covA[8],
287                         covB[9],covA[9],
288                         covB[10],covA[10],
289                         covB[11],covA[11],
290                         covB[12],covA[12],
291                         covB[13],covA[13],
292                         covB[14],covA[14]
293                         ));
294         */
295         Double_t time[AliPID::kSPECIESC]; t->GetIntegratedTimes(time);
296         AliDebug(2,Form(" TOF params: %6d  %f %f %f %f %f %6d %3d %f",
297                         i,
298                         t->GetTOFsignalRaw(),t->GetTOFsignal(),t->GetTOFsignalToT(),
299                         t->GetTOFsignalDz(),t->GetTOFsignalDx(),t->GetTOFCalChannel(),
300                         t->GetTOFcluster(),t->GetIntegratedLength()));
301         AliDebug(2,Form("  %f %f %f %f %f %f %f %f %f",
302                         time[0], time[1], time[2], time[3], time[4], time[5], time[6], time[7], time[8]));
303       }
304     }
305   }
306   
307   fSeeds->Clear();
308   fTracks->Clear();
309   
310   AliInfo(Form("Number of cluster to be checked = %d",fN));
311   if(fN){
312     Int_t *matchmap = new Int_t[fN];
313     event->SetTOFcluster(fN,fClusters,matchmap);
314     for (Int_t i=0; i<ntrk; i++) { // remapping after TOF matching selection
315       AliESDtrack *t=event->GetTrack(i);
316       t->ReMapTOFcluster(fN,matchmap);
317     }
318
319     delete[] matchmap;
320   }
321   
322   
323
324   return 0;
325   
326 }
327 //_________________________________________________________________________
328 void AliTOFtrackerV2::CollectESD() {
329    //prepare the set of ESD tracks to be matched to clusters in TOF
330
331   Int_t seedsTOF1=0;
332   Int_t seedsTOF3=0;
333   Int_t seedsTOF2=0;
334  
335   TClonesArray &aTOFTrack = *fTracks;
336   for (Int_t i=0; i<fNseeds; i++) {
337
338     AliESDtrack *t =(AliESDtrack*)fSeeds->At(i);
339     if ((t->GetStatus()&AliESDtrack::kTPCout)==0)continue;
340
341     AliTOFtrack *track = new AliTOFtrack(*t); // New
342     Float_t x = (Float_t)track->GetX(); //New
343
344     // TRD 'good' tracks
345     if ( ( (t->GetStatus()&AliESDtrack::kTRDout)!=0 ) ) {
346
347       AliDebug(1,Form(" Before propagation till inner TOF radius, ESDtrackLength=%f, TOFtrackLength=%f",t->GetIntegratedLength(),track->GetIntegratedLength()));
348
349       // TRD 'good' tracks, already propagated at 371 cm
350       if ( x >= AliTOFGeometry::Rmin() ) {
351
352         if ( track->PropagateToInnerTOF() ) {
353
354           AliDebug(1,Form(" TRD propagated track till rho = %fcm."
355                           " And then the track has been propagated till rho = %fcm.",
356                           x, (Float_t)track->GetX()));
357
358           track->SetSeedIndex(i);
359           t->UpdateTrackParams(track,AliESDtrack::kTOFin);
360           new(aTOFTrack[fNseedsTOF]) AliTOFtrack(*track);
361           fNseedsTOF++;
362           seedsTOF1++;
363
364           AliDebug(1,Form(" After propagation till inner TOF radius, ESDtrackLength=%f, TOFtrackLength=%f",t->GetIntegratedLength(),track->GetIntegratedLength()));
365         }
366         delete track;
367
368       }
369       else { // TRD 'good' tracks, propagated rho<371cm
370
371         if  ( track->PropagateToInnerTOF() ) {
372
373           AliDebug(1,Form(" TRD propagated track till rho = %fcm."
374                           " And then the track has been propagated till rho = %fcm.",
375                           x, (Float_t)track->GetX()));
376
377           track->SetSeedIndex(i);
378           t->UpdateTrackParams(track,AliESDtrack::kTOFin);
379           new(aTOFTrack[fNseedsTOF]) AliTOFtrack(*track);
380           fNseedsTOF++;
381           seedsTOF3++;
382
383           AliDebug(1,Form(" After propagation till inner TOF radius, ESDtrackLength=%f, TOFtrackLength=%f",t->GetIntegratedLength(),track->GetIntegratedLength()));
384         }
385         delete track;
386
387       }
388       //delete track;
389     }
390
391     else { // Propagate the rest of TPCbp
392
393       AliDebug(1,Form(" Before propagation till inner TOF radius, ESDtrackLength=%f, TOFtrackLength=%f",t->GetIntegratedLength(),track->GetIntegratedLength()));
394
395       if ( track->PropagateToInnerTOF() ) { 
396
397         AliDebug(1,Form(" TPC propagated track till rho = %fcm."
398                         " And then the track has been propagated till rho = %fcm.",
399                         x, (Float_t)track->GetX()));
400
401         track->SetSeedIndex(i);
402         t->UpdateTrackParams(track,AliESDtrack::kTOFin);
403         new(aTOFTrack[fNseedsTOF]) AliTOFtrack(*track);
404         fNseedsTOF++;
405         seedsTOF2++;
406
407         AliDebug(1,Form(" After propagation till inner TOF radius, ESDtrackLength=%f, TOFtrackLength=%f",t->GetIntegratedLength(),track->GetIntegratedLength()));
408       }
409       delete track;
410     }
411   }
412
413   AliInfo(Form("Number of TOF seeds = %d (kTRDout371 = %d, kTRDoutLess371 = %d, !kTRDout = %d)",fNseedsTOF,seedsTOF1,seedsTOF3,seedsTOF2));
414
415   // Sort according uncertainties on track position 
416   fTracks->Sort();
417
418 }
419
420 //_________________________________________________________________________
421 void AliTOFtrackerV2::MatchTracks() {
422   //
423   //Match ESD tracks to clusters in TOF
424   //
425
426   // Parameters used/regulating the reconstruction
427   static Float_t detDepth=18.;
428   static Float_t padDepth=0.5;
429
430   const Float_t kSpeedOfLight= 2.99792458e-2; // speed of light [cm/ps]
431
432   Float_t dY=AliTOFGeometry::XPad(); 
433   Float_t dZ=AliTOFGeometry::ZPad(); 
434
435   Float_t sensRadius = fkRecoParam->GetSensRadius();
436   Float_t stepSize   = fkRecoParam->GetStepSize();
437   Float_t scaleFact  = fkRecoParam->GetWindowScaleFact();
438   Float_t dyMax=fkRecoParam->GetWindowSizeMaxY(); 
439   Float_t dzMax=fkRecoParam->GetWindowSizeMaxZ();
440   Float_t dCut=10.;//fkRecoParam->GetDistanceCut(); // This is to be loaded by OCDB. It should be 10cm always.
441   Double_t maxChi2=fkRecoParam->GetMaxChi2TRD();
442   Bool_t timeWalkCorr = fkRecoParam->GetTimeWalkCorr();
443   AliDebug(1,"++++++++++++++TOF Reconstruction Parameters:++++++++++++++");
444   AliDebug(1,Form("TOF sens radius: %f",sensRadius));
445   AliDebug(1,Form("TOF step size: %f",stepSize));
446   AliDebug(1,Form("TOF Window scale factor: %f",scaleFact));
447   AliDebug(1,Form("TOF Window max dy: %f",dyMax));
448   AliDebug(1,Form("TOF Window max dz: %f",dzMax));
449   AliDebug(1,Form("TOF distance Cut: %f",dCut));
450   AliDebug(1,Form("TOF Max Chi2: %f",maxChi2));
451   AliDebug(1,Form("Time Walk Correction? : %d",timeWalkCorr));   
452
453   //Match ESD tracks to clusters in TOF
454
455   // Get the number of propagation steps
456   Int_t nSteps=(Int_t)(detDepth/stepSize);
457   AliDebug(1,Form(" Number of steps to be done %d",nSteps));
458
459   AliDebug(1,"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
460
461   //PH Arrays (moved outside of the loop)
462   Float_t * trackPos[4];
463   for (Int_t ii=0; ii<4; ii++) trackPos[ii] = new Float_t[nSteps];
464   Int_t * clind = new Int_t[fN];
465   
466   // Some init
467   const Int_t kNclusterMax = 1000; // related to fN value
468   TGeoHMatrix global[kNclusterMax];
469
470   //The matching loop
471   for (Int_t iseed=0; iseed<fNseedsTOF; iseed++) {
472
473     for (Int_t ii=0; ii<fN; ii++) clind[ii]=-1;
474     for (Int_t ii=0; ii<kNclusterMax; ii++) global[ii] = 0x0;
475     for (Int_t ii=0; ii<4; ii++)
476       for (Int_t jj=0; jj<nSteps; jj++) trackPos[ii][jj]=0.;
477
478     AliTOFtrack *track =(AliTOFtrack*)fTracks->UncheckedAt(iseed);
479     AliESDtrack *t =(AliESDtrack*)fSeeds->At(track->GetSeedIndex());
480     AliTOFtrack *trackTOFin = new AliTOFtrack(*track);
481
482     Double_t timesOr[AliPID::kSPECIESC]; t->GetIntegratedTimes(timesOr); // in ps
483
484     // Determine a window around the track
485     Double_t x,par[5]; 
486     trackTOFin->GetExternalParameters(x,par);
487     Double_t cov[15]; 
488     trackTOFin->GetExternalCovariance(cov);
489
490     if (cov[0]<0. || cov[2]<0.) {
491       AliWarning(Form("Very strange track (%d)! At least one of its covariance matrix diagonal elements is negative!",iseed));
492       delete trackTOFin;
493       continue;
494     }
495
496     Double_t dphi=
497       scaleFact*
498       ((5*TMath::Sqrt(TMath::Abs(cov[0])) + 0.5*dY + 2.5*TMath::Abs(par[2]))/sensRadius); 
499     Double_t dz=
500        scaleFact*
501        (5*TMath::Sqrt(TMath::Abs(cov[2])) + 0.5*dZ + 2.5*TMath::Abs(par[3]));
502
503     Double_t phi=TMath::ATan2(par[0],x) + trackTOFin->GetAlpha();
504     if (phi<-TMath::Pi())phi+=2*TMath::Pi();
505     if (phi>=TMath::Pi())phi-=2*TMath::Pi();
506     Double_t z=par[1];   
507
508     //upper limit on window's size.
509     if (dz> dzMax) dz=dzMax;
510     if (dphi*sensRadius> dyMax) dphi=dyMax/sensRadius;
511
512
513     // find the clusters in the window of the track
514     Int_t nc=0;
515     for (Int_t k=FindClusterIndex(z-dz); k<fN; k++) {
516
517       if (nc>=kNclusterMax) {
518         AliWarning("No more matchable clusters can be stored! Please, increase the corresponding vectors size.");
519         break;
520       }
521
522       AliESDTOFcluster *c=&(fClusters[k]);
523       if (c->GetZ() > z+dz) break;
524       if (!c->GetStatus()) {
525         AliDebug(1,"Cluster in channel declared bad!");
526         continue; // skip bad channels as declared in OCDB
527       }
528
529       Double_t dph=TMath::Abs(c->GetPhi()-phi);
530       if (dph>TMath::Pi()) dph-=2.*TMath::Pi();
531       if (TMath::Abs(dph)>dphi) continue;
532
533       Double_t yc=(c->GetPhi() - trackTOFin->GetAlpha())*c->GetR();
534       Double_t p[2]={yc, c->GetZ()};
535       Double_t cov2[3]= {dY*dY/12., 0., dZ*dZ/12.};
536       if (trackTOFin->AliExternalTrackParam::GetPredictedChi2(p,cov2) > maxChi2)continue;
537
538       clind[nc] = k;      
539       Char_t path[200];
540       Int_t ind[5]; fGeom->GetVolumeIndices(c->GetTOFchannel(),ind);
541       fGeom->GetVolumePath(ind,path);
542       gGeoManager->cd(path);
543       global[nc] = *gGeoManager->GetCurrentMatrix();
544       nc++;
545     }
546
547     if (nc == 0 ) {
548       AliDebug(1,Form("No available clusters for the track number %d",iseed));
549       fnunmatch++;
550       delete trackTOFin;
551       continue;
552     }
553
554     AliDebug(1,Form(" Number of available TOF clusters for the track number %d: %d",iseed,nc));
555
556     //start fine propagation 
557
558     Double_t *times[AliPID::kSPECIESC];
559     for(Int_t isp=0;isp < AliPID::kSPECIESC;isp++){
560       times[isp] = new Double_t[nSteps];
561     }
562
563     Int_t nStepsDone = 0;
564     for( Int_t istep=0; istep<nSteps; istep++){ 
565       
566       // First of all, propagate the track...
567       Float_t xs = AliTOFGeometry::RinTOF()+istep*stepSize;
568       if (!(trackTOFin->PropagateTo(xs))) break;
569
570       //  ...and then, if necessary, rotate the track
571       Double_t ymax = xs*TMath::Tan(0.5*AliTOFGeometry::GetAlpha());
572       Double_t ysect = trackTOFin->GetY();
573       if (ysect > ymax) {
574         if (!(trackTOFin->Rotate(AliTOFGeometry::GetAlpha()))) break;
575       } else if (ysect <-ymax) {
576         if (!(trackTOFin->Rotate(-AliTOFGeometry::GetAlpha()))) break;
577       }
578
579       Double_t mom = trackTOFin->P();
580
581       if(istep == 0){
582         for(Int_t isp=0;isp<AliPID::kSPECIESC;isp++){
583           Double_t mass=AliPID::ParticleMass(isp);
584           Double_t momz = mom*AliPID::ParticleCharge(isp);
585           times[isp][nStepsDone] = stepSize/kSpeedOfLight*TMath::Sqrt(momz*momz+mass*mass)/momz;
586         }
587       }
588       else{
589         for(Int_t isp=0;isp<AliPID::kSPECIESC;isp++){
590           Double_t mass=AliPID::ParticleMass(isp);
591           Double_t momz = mom*AliPID::ParticleCharge(isp);
592           times[isp][nStepsDone] = times[isp][nStepsDone-1] + (trackTOFin->GetIntegratedLength()-trackPos[3][nStepsDone-1])/kSpeedOfLight*TMath::Sqrt(momz*momz+mass*mass)/momz;
593         }
594       }
595
596       // store the running point (Globalrf) - fine propagation     
597
598       Double_t r[3]; trackTOFin->GetXYZ(r);
599       trackPos[0][nStepsDone]= (Float_t) r[0];
600       trackPos[1][nStepsDone]= (Float_t) r[1];
601       trackPos[2][nStepsDone]= (Float_t) r[2];   
602       trackPos[3][nStepsDone]= trackTOFin->GetIntegratedLength();
603
604       nStepsDone++;
605       AliDebug(3,Form(" current step %d (%d) - nStepsDone=%d",istep,nSteps,nStepsDone));
606     }
607
608     if ( nStepsDone == 0 ) {
609       AliDebug(1,Form(" No track points for track number %d",iseed));
610       fnunmatch++;
611       delete trackTOFin;
612       continue;
613     }
614
615     AliDebug(3,Form(" Number of steps done for the track number %d: %d",iseed,nStepsDone));
616
617     Int_t *isClusterMatchable = NULL;
618     if(nc){
619       isClusterMatchable = new Int_t[nc];
620       for (Int_t i=0; i<nc; i++) isClusterMatchable[i] = kFALSE;                
621     }
622
623     Int_t nfound = 0;
624     Bool_t accept = kFALSE;
625     Bool_t isInside = kFALSE;
626     for (Int_t istep=0; istep<nStepsDone; istep++) {
627
628       Bool_t gotInsideCluster = kFALSE;
629       Int_t trackInsideCluster = -1;
630
631       Float_t ctrackPos[3];     
632       ctrackPos[0] = trackPos[0][istep];
633       ctrackPos[1] = trackPos[1][istep];
634       ctrackPos[2] = trackPos[2][istep];
635
636       //now see whether the track matches any of the TOF clusters            
637
638       Float_t dist3d[3]={0.,0.,0.};
639       accept = kFALSE;
640      
641       for (Int_t i=0; i<nc; i++) {
642
643         // ***** NEW *****
644         /* check whether track was inside another cluster
645          * and in case inhibit this cluster.
646          * this will allow to only go on and add track points for
647          * that cluster where the track got inside first */
648         if (gotInsideCluster && trackInsideCluster != i) {
649           AliDebug(3,Form(" A - istep=%d ~ %d %d ~ nfound=%d",istep,trackInsideCluster,i,nfound));
650           continue;
651         }
652         AliDebug(3,Form(" B - istep=%d ~ %d %d ~ nfound=%d",istep,trackInsideCluster,i,nfound));
653
654         /* check whether track is inside this cluster */
655         for (Int_t hh=0; hh<3; hh++) dist3d[hh]=0.;
656         isInside = fGeom->IsInsideThePad((TGeoHMatrix*)(&global[i]),ctrackPos,dist3d);
657
658         // ***** NEW *****
659         /* if track is inside this cluster set flags which will then
660          * inhibit to add track points for the other clusters */
661         if (isInside) {
662           gotInsideCluster = kTRUE;
663           trackInsideCluster = i;
664         }
665
666         Float_t yLoc = dist3d[1];
667         Float_t rLoc = TMath::Sqrt(dist3d[0]*dist3d[0]+dist3d[2]*dist3d[2]);
668         accept = (TMath::Abs(yLoc)<padDepth*0.5 && rLoc<dCut);
669
670         //***** NEW *****
671         /* add point everytime that:
672          * - the track is inside the cluster
673          * - the track got inside the cluster, even when it eventually exited the cluster
674          * - the tracks is within dCut from the cluster
675          */
676         if (accept || isInside || gotInsideCluster) {
677
678           Double_t timesCurrent[AliPID::kSPECIESC];
679           AliDebug(3,Form(" Momentum for track %d -> %f", iseed,t->P()));
680           for (Int_t j=0;j<AliPID::kSPECIESC;j++) {
681             timesCurrent[j] = timesOr[j] + times[j][istep];
682           }
683
684           if (TMath::Abs(dist3d[1])<stepSize && !isClusterMatchable[i]) {
685             isClusterMatchable[i] = kTRUE;
686             fClusters[clind[i]].Update(t->GetID(),dist3d[1],dist3d[0],dist3d[2],trackPos[3][istep],timesCurrent);//x,y,z -> tracking RF
687             t->AddTOFcluster(clind[i]);
688             t->SetStatus(AliESDtrack::kTOFout);
689           }
690           AliDebug(2,Form(" dist3dLoc[0] = %f, dist3dLoc[1] = %f, dist3dLoc[2] = %f ",dist3d[0],dist3d[1],dist3d[2]));
691
692           nfound++;
693
694           AliDebug(3,Form(" C - istep=%d ~ %d %d ~ nfound=%d",istep,trackInsideCluster,i,nfound));
695         
696           // ***** NEW *****
697         }//end if accept
698         
699       } //end for on the clusters
700     } //end for on the steps     
701     if(nc) delete[] isClusterMatchable;
702
703     for(Int_t isp=0;isp < AliPID::kSPECIESC;isp++){
704       delete[] times[isp];
705     }
706
707
708     if (nfound == 0 ) {
709       AliDebug(1,Form(" No matchable track points for the track number %d",iseed));
710       fnunmatch++;
711       delete trackTOFin;
712       continue;
713     }
714
715     AliDebug(1,Form(" Number of track points for the track number %d: %d",iseed,nfound));
716
717     Int_t nMatchedClusters = t->GetNTOFclusters();
718  
719     if (nMatchedClusters==0) {
720       AliDebug(1,Form("Reconstructed track %d doesn't match any TOF cluster", iseed));
721       fnunmatch++;
722       delete trackTOFin;
723       continue;
724     }
725
726     AliDebug(1,Form(" %d - matched (%d)",track->GetSeedIndex()/*iseed*/,nMatchedClusters));
727
728     fnmatch++;
729
730     /*
731     AliTOFcluster cTOF = AliTOFcluster(volIdClus,
732     (Float_t)posClus[0],(Float_t)posClus[1],(Float_t)posClus[2],
733     (Float_t)covClus[0],(Float_t)covClus[1],(Float_t)covClus[2],
734     (Float_t)covClus[3],(Float_t)covClus[4],(Float_t)covClus[5],
735     tofLabels,volIndices,parClu,kTRUE,index[i]);
736
737     // Fill the track residual histograms.
738     FillResiduals(trackTOFin,c,kFALSE);
739     */
740
741     delete trackTOFin;
742
743   } // loop on fSeeds
744
745   for (Int_t ii=0; ii<4; ii++) delete [] trackPos[ii];
746   delete [] clind;
747  
748 }
749 //_________________________________________________________________________
750 Int_t AliTOFtrackerV2::LoadClusters(TTree *cTree) {
751   //--------------------------------------------------------------------
752   //This function loads the TOF clusters
753   //--------------------------------------------------------------------
754
755   TBranch *branch=cTree->GetBranch("TOF");
756   if (!branch) { 
757     AliError("can't get the branch with the TOF clusters !");
758     return 1;
759   }
760
761   static TClonesArray dummy("AliTOFcluster",10000);
762   dummy.Clear();
763   TClonesArray *clusters=&dummy;
764   branch->SetAddress(&clusters);
765
766   cTree->GetEvent(0);
767   fN=clusters->GetEntriesFast();
768   AliInfo(Form("Number of clusters: %d",fN));
769
770   if(fClusters){
771     delete[] fClusters;
772     fClusters = NULL;
773   }
774
775   if(fN)
776     fClusters = new AliESDTOFcluster[fN];
777   else{
778     fClusters = new AliESDTOFcluster[1];
779     fN = 1;
780     return 0;
781   }
782
783   for (Int_t i=0; i<fN; i++) {
784     AliTOFcluster *c=(AliTOFcluster*)clusters->UncheckedAt(i);
785     Int_t ind[5];
786     ind[0]=c->GetDetInd(0);
787     ind[1]=c->GetDetInd(1);
788     ind[2]=c->GetDetInd(2);
789     ind[3]=c->GetDetInd(3);
790     ind[4]=c->GetDetInd(4);
791     Int_t calindex = AliTOFGeometry::GetIndex(ind);
792     Int_t tofLabels[3]={c->GetLabel(0),c->GetLabel(1),c->GetLabel(2)};
793     AliESDTOFcluster esdTOFclus(i,calindex,
794                                 AliTOFGeometry::TdcBinWidth()*c->GetTDC()/*ps*/,
795                                 AliTOFGeometry::TdcBinWidth()*c->GetTDCRAW()/*ps*/,
796                                 AliTOFGeometry::ToTBinWidth()*c->GetToT()*1E-3/*ns*/,
797                                 tofLabels,
798                                 c->GetDeltaBC(),c->GetL0L1Latency(),
799                                 c->GetStatus(),c->GetZ(),c->GetPhi(),c->GetR());
800
801     fClusters[i] = esdTOFclus;
802
803   }
804
805   return 0;
806 }
807 //_________________________________________________________________________
808 void AliTOFtrackerV2::UnloadClusters() {
809   //--------------------------------------------------------------------
810   //This function unloads TOF clusters
811   //--------------------------------------------------------------------
812
813   // don't delete TOF clusters here because they should be written
814 }
815
816 //_________________________________________________________________________
817 Int_t AliTOFtrackerV2::FindClusterIndex(Double_t z) const {
818   //--------------------------------------------------------------------
819   // This function returns the index of the nearest cluster 
820   //--------------------------------------------------------------------
821   if (fN==0) return 0;
822   if (z <= fClusters[0].GetZ()) return 0;
823   if (z > fClusters[fN-1].GetZ()) return fN;
824   Int_t b=0, e=fN-1, m=(b+e)/2;
825   for (; b<e; m=(b+e)/2) {
826     if (z > fClusters[m].GetZ()) b=m+1;
827
828     else e=m; 
829   }
830   return m;
831 }
832
833 //_________________________________________________________________________
834 Bool_t AliTOFtrackerV2::GetTrackPoint(Int_t index, AliTrackPoint& p) const
835 {
836   // Get track space point with index i
837   // Coordinates are in the global system
838   AliESDTOFcluster *cl = &(fClusters[index]);
839   Float_t xyz[3];
840   xyz[0] = cl->GetR()*TMath::Cos(cl->GetPhi());
841   xyz[1] = cl->GetR()*TMath::Sin(cl->GetPhi());
842   xyz[2] = cl->GetZ();
843   Float_t phiangle = (Int_t(cl->GetPhi()*TMath::RadToDeg()/20.)+0.5)*20.*TMath::DegToRad();
844   Float_t sinphi = TMath::Sin(phiangle), cosphi = TMath::Cos(phiangle);
845   Int_t tofChannel=cl->GetTOFchannel();
846   Int_t ind[5]; fGeom->GetVolumeIndices(tofChannel,ind);
847   Float_t tiltangle = AliTOFGeometry::GetAngles(ind[1],ind[2])*TMath::DegToRad();
848   Float_t sinth = TMath::Sin(tiltangle), costh = TMath::Cos(tiltangle);
849   Float_t sigmay2 = AliTOFGeometry::XPad()*AliTOFGeometry::XPad()/12.;
850   Float_t sigmaz2 = AliTOFGeometry::ZPad()*AliTOFGeometry::ZPad()/12.;
851   Float_t cov[6];
852   cov[0] = sinphi*sinphi*sigmay2 + cosphi*cosphi*sinth*sinth*sigmaz2;
853   cov[1] = -sinphi*cosphi*sigmay2 + sinphi*cosphi*sinth*sinth*sigmaz2;
854   cov[2] = -cosphi*sinth*costh*sigmaz2;
855   cov[3] = cosphi*cosphi*sigmay2 + sinphi*sinphi*sinth*sinth*sigmaz2;
856   cov[4] = -sinphi*sinth*costh*sigmaz2;
857   cov[5] = costh*costh*sigmaz2;
858   p.SetXYZ(xyz[0],xyz[1],xyz[2],cov);
859
860   // Detector numbering scheme
861   Int_t nSector = AliTOFGeometry::NSectors();
862   Int_t nPlate  = AliTOFGeometry::NPlates();
863   Int_t nStripA = AliTOFGeometry::NStripA();
864   Int_t nStripB = AliTOFGeometry::NStripB();
865   Int_t nStripC = AliTOFGeometry::NStripC();
866
867   Int_t isector = ind[0];//cl->GetDetInd(0);
868   if (isector >= nSector)
869     AliError(Form("Wrong sector number in TOF (%d) !",isector));
870   Int_t iplate = ind[1];//cl->GetDetInd(1);
871   if (iplate >= nPlate)
872     AliError(Form("Wrong plate number in TOF (%d) !",iplate));
873   Int_t istrip = ind[2];//cl->GetDetInd(2);
874
875   Int_t stripOffset = 0;
876   switch (iplate) {
877   case 0:
878     stripOffset = 0;
879     break;
880   case 1:
881     stripOffset = nStripC;
882     break;
883   case 2:
884     stripOffset = nStripC+nStripB;
885     break;
886   case 3:
887     stripOffset = nStripC+nStripB+nStripA;
888     break;
889   case 4:
890     stripOffset = nStripC+nStripB+nStripA+nStripB;
891     break;
892   default:
893     AliError(Form("Wrong plate number in TOF (%d) !",iplate));
894     break;
895   };
896
897   Int_t idet = (2*(nStripC+nStripB)+nStripA)*isector +
898                stripOffset +
899                istrip;
900   UShort_t volid = AliGeomManager::LayerToVolUID(AliGeomManager::kTOF,idet);
901   p.SetVolumeID((UShort_t)volid);
902   return kTRUE;
903 }
904 //_________________________________________________________________________
905
906 void AliTOFtrackerV2::FillClusterArray(TObjArray* arr) const
907 {
908   //
909   // Returns the TOF cluster array
910   //
911
912   if (fN==0)
913     arr = 0x0;
914   else
915     for (Int_t i=0; i<fN; ++i) arr->Add(&(fClusters[i]));
916
917 }
918 //_________________________________________________________________________
919 Float_t AliTOFtrackerV2::CorrectTimeWalk( Float_t dist, Float_t tof) const {
920
921   //dummy, for the moment
922   Float_t tofcorr=0.;
923   if(dist<AliTOFGeometry::ZPad()*0.5){
924     tofcorr=tof;
925     //place here the actual correction
926   }else{
927     tofcorr=tof; 
928   } 
929   return tofcorr;
930 }
931 //_________________________________________________________________________
932 void AliTOFtrackerV2::Clusterize(){
933   Int_t detId[5];
934   for(Int_t i=0; i < fN-1;i++){
935     AliESDTOFcluster *c1=&(fClusters[i]);
936     if(!c1->GetStatus()) continue;
937
938     Int_t chan1 = c1->GetTOFchannel();
939     AliTOFGeometry::GetVolumeIndices(chan1, detId); // Get volume index from channel index
940
941     Int_t ieta = detId[2]/*strip*/*2 + detId[3]/*pad Z*/;
942     if(detId[1]/*module*/ == 0) ieta += 0;
943     else if(detId[1] == 1) ieta += 38;
944     else if(detId[1] == 2) ieta += 76;
945     else if(detId[1] == 3) ieta += 106;
946     else if(detId[1] == 4) ieta += 144;
947     Int_t iphi = detId[0]/*phi sector*/*48 + detId[4]/*pad x*/;
948     
949
950     for(Int_t j=i+1; j < fN;j++){
951       AliESDTOFcluster *c2=&(fClusters[j]);
952       if(!c2->GetStatus()) continue;
953
954       Int_t chan2 = c2->GetTOFchannel();
955
956       // check if the two TOF hits are in the same strip
957       if(chan1/96 != chan2/96) continue;
958
959       AliTOFGeometry::GetVolumeIndices(chan2, detId); // Get volume index from channel index
960       Int_t ieta2 = detId[2]/*strip*/*2 + detId[3]/*pad Z*/;
961       if(detId[1]/*module*/ == 0) ieta2 += 0;
962       else if(detId[1] == 1) ieta2 += 38;
963       else if(detId[1] == 2) ieta2 += 76;
964       else if(detId[1] == 3) ieta2 += 106;
965       else if(detId[1] == 4) ieta2 += 144;
966       Int_t iphi2 = detId[0]/*phi sector*/*48 + detId[4]/*pad x*/;
967       
968       // check if the fired pad are close in space
969       if(TMath::Abs(iphi-iphi2)>1 || TMath::Abs(ieta-ieta2)>1) continue;
970
971       // check if the TOF time are close enough to be merged
972       if(TMath::Abs(c1->GetTime() - c2->GetTime()) > 500/*in ps*/) continue;
973
974       // merge them
975       Int_t label[3] = {c2->GetLabel(0),c2->GetLabel(1),c2->GetLabel(2)};
976       fClusters[i].AddTOFhit(c2->GetClusterIndex(),chan2,c2->GetTime(),c2->GetTimeRaw(),c2->GetTOT(),label,
977                                        c2->GetDeltaBC(),c2->GetL0L1Latency(),1,c2->GetZ(),c2->GetPhi(),c2->GetR());
978       
979       c2->SetStatus(0); // only the merged one should be used
980       j = fN; // cluster "i" merged go to the next one ("i+1")
981     }
982   }
983
984   // second step of clusterization
985   for(Int_t i=0; i < fN-1;i++){
986     AliESDTOFcluster *c1=&(fClusters[i]);
987     if(!c1->GetStatus()) continue;
988
989     Int_t chan1 = c1->GetTOFchannel(0);
990     AliTOFGeometry::GetVolumeIndices(chan1, detId); // Get volume index from channel index
991
992     Int_t ieta = detId[2]/*strip*/*2 + detId[3]/*pad Z*/;
993     if(detId[1]/*module*/ == 0) ieta += 0;
994     else if(detId[1] == 1) ieta += 38;
995     else if(detId[1] == 2) ieta += 76;
996     else if(detId[1] == 3) ieta += 106;
997     else if(detId[1] == 4) ieta += 144;
998     Int_t iphi = detId[0]/*phi sector*/*48 + detId[4]/*pad x*/;
999
1000     Int_t ieta2,iphi2,chan2=chan1;
1001     if(c1->GetNTOFhits() > 1){
1002       chan2 = c1->GetTOFchannel(1);
1003       AliTOFGeometry::GetVolumeIndices(chan2, detId); // Get volume index from channel index
1004
1005       ieta2 = detId[2]/*strip*/*2 + detId[3]/*pad Z*/;
1006       if(detId[1]/*module*/ == 0) ieta2 += 0;
1007       else if(detId[1] == 1) ieta2 += 38;
1008       else if(detId[1] == 2) ieta2 += 76;
1009       else if(detId[1] == 3) ieta2 += 106;
1010       else if(detId[1] == 4) ieta2 += 144;
1011       iphi2 = detId[0]/*phi sector*/*48 + detId[4]/*pad x*/;
1012     }
1013     else{
1014       iphi2=iphi;
1015       ieta2=ieta;
1016     }
1017
1018     for(Int_t j=i+1; j < i;j++){
1019       AliESDTOFcluster *c2=&(fClusters[j]);
1020       if(!c2->GetStatus()) continue;
1021
1022       Int_t chan3 = c2->GetTOFchannel();
1023
1024       // check if the two TOF hits are in the same strip
1025       if(chan1/96 != chan3/96) continue;
1026
1027       AliTOFGeometry::GetVolumeIndices(chan3, detId); // Get volume index from channel index
1028       Int_t ieta3 = detId[2]/*strip*/*2 + detId[3]/*pad Z*/;
1029       if(detId[1]/*module*/ == 0) ieta3 += 0;
1030       else if(detId[1] == 1) ieta3 += 38;
1031       else if(detId[1] == 2) ieta3 += 76;
1032       else if(detId[1] == 3) ieta3 += 106;
1033       else if(detId[1] == 4) ieta3 += 144;
1034       Int_t iphi3 = detId[0]/*phi sector*/*48 + detId[4]/*pad x*/;
1035       
1036       // check if the fired pad are close in space
1037       if((TMath::Abs(iphi-iphi3)>1 && TMath::Abs(iphi2-iphi3)>1) || (TMath::Abs(ieta-ieta3)>1 && TMath::Abs(ieta2-ieta3)>1)) 
1038 continue;
1039       
1040       // check if the TOF time are close enough to be merged
1041       if(TMath::Abs(c1->GetTime() - c2->GetTime()) > 500/*in ps*/) continue;
1042       
1043       // merge them
1044       Int_t label[3] = {c2->GetLabel(0),c2->GetLabel(1),c2->GetLabel(2)};
1045       fClusters[i].AddTOFhit(c2->GetClusterIndex(),chan2,c2->GetTime(),c2->GetTimeRaw(),c2->GetTOT(),label,
1046                                        c2->GetDeltaBC(),c2->GetL0L1Latency(),1,c2->GetZ(),c2->GetPhi(),c2->GetR());
1047
1048       if(c2->GetNTOFhits() > 1){ // in case also the second cluster has two hits
1049         Int_t label2[3] = {c2->GetLabel(0,1),c2->GetLabel(1,1),c2->GetLabel(2,1)};
1050         fClusters[i].AddTOFhit(c2->GetClusterIndex(1),c2->GetTOFchannel(1),c2->GetTime(1),c2->GetTimeRaw(1),
1051                                          c2->GetTOT(1),label2,c2->GetDeltaBC(2),c2->GetL0L1Latency(2),1,c2->GetZ(),
1052                                          c2->GetPhi(),c2->GetR());
1053       }
1054
1055       c1->SetStatus(0); // only the merged one should be used
1056       j = fN; // cluster "i" merged go to the next one ("i+1")
1057     }
1058   }  
1059 }
1060