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