]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TOF/AliTOFReconstructioner.cxx
Added MAcros: QA macros for sdigits and digits - macro to create digits from sdigits
[u/mrichter/AliRoot.git] / TOF / AliTOFReconstructioner.cxx
CommitLineData
db9ba97f 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// Manager class for TOF reconstruction.
18//
19//
20//-- Authors: Bologna-ITEP-Salerno Group
21//
22// Description: Manager class for TOF reconstruction (derived from TTask)
23// Summary of the main methods:
24// - extraction of the TPC (assumed to be) reconstructed tracks
25// comment: it has to me moved as soon as possible into a separate
26// class AliTOFTrackReader (K. Safarik suggestion)
27// - geometrical propagation of the above tracks till TOF detector
28// - matching of the tracks with the TOF signals
29//
30// Remark: the GEANT3.21 geometry is used during the geometrical propagation
31// of the tracks in order to know the current volume reached by the track.
32//
33//////////////////////////////////////////////////////////////////////////////
34
35
db9ba97f 36#include "AliConst.h"
37#include "AliRun.h"
38#include "AliTOFConstants.h"
39#include "AliTOFHitMap.h"
40#include "AliTOFSDigit.h"
41#include "AliTOFhit.h"
42#include "AliTOFRecHit.h"
43#include "AliTOFPad.h"
44#include "AliTOFTrack.h"
45#include "AliTOF.h"
46#include "AliTOFv1.h"
47#include "AliTOFv2.h"
48#include "AliTOFv2FHoles.h"
49#include "AliTOFv3.h"
50#include "AliTOFv4.h"
51#include "AliTOFv4T0.h"
52#include "AliTOFReconstructioner.h"
53// this line has to be commented till TPC will provide fPx fPy fPz and fL in
54// AliTPChit class or somewhere
55// #include "../TPC/AliTPC.h"
56#include "AliRun.h"
57#include "AliDetector.h"
58#include "AliMC.h"
59
b213b8bd 60#include "TTask.h"
61#include "TBenchmark.h"
62#include "TTree.h"
63#include "TSystem.h"
64#include "TFile.h"
65#include "TParticle.h"
db9ba97f 66#include <TClonesArray.h>
67#include "../TGeant3/TGeant3.h"
db9ba97f 68#include <TF1.h>
69#include <TF2.h>
db9ba97f 70#include "TROOT.h"
71#include "TFolder.h"
72#include "TNtuple.h"
73#include <stdlib.h>
74#include <iostream.h>
75#include <fstream.h>
76
77ClassImp(AliTOFReconstructioner)
78
79//____________________________________________________________________________
80 AliTOFReconstructioner::AliTOFReconstructioner():TTask("AliTOFReconstructioner","")
81{
82 // default ctor
83 fNevents = 0 ;
84 fg3 = 0;
85 foutputfile = 0;
86 foutputntuple= 0;
87 fZnoise = 0;
88 ftail = 0;
89}
90
91//____________________________________________________________________________
92 AliTOFReconstructioner::AliTOFReconstructioner(char* headerFile, Option_t* opt, char *RecFile ):TTask("AliTOFReconstructioner","")
93{
94 //
95 // ctor
96 //
97 fNevents = 0 ; // Number of events to reconstruct, 0 means all evens in current file
98 fg3 = 0;
99 foutputfile = 0;
100 foutputntuple= 0;
101 fZnoise = 0;
102 ftail = 0;
103
104 Init(opt);
105
106 // create output file
107 if (RecFile){
108 foutputfile= new TFile(RecFile,"RECREATE","root file for matching");
109 } else {
110 char outFileName[100];
111 strcpy(outFileName,"match");
112 strcat(outFileName,headerFile);
113 foutputfile= new TFile(outFileName,"RECREATE","root file for matching");
114 }
115
116 // initialize the ALIROOT geometry
117 gAlice->Init();
118 gAlice->Print();
119
120 // set the fg3 pointer to geometry used by IsInsideThePad method
121 fg3 = (TGeant3*) gMC;
122
123 CreateNTuple();
124
125 // add Task to //root/Tasks folder
126 TTask * roottasks = (TTask*)gROOT->GetRootFolder()->FindObject("Tasks") ;
127 roottasks->Add(this) ;
128}
129//____________________________________________________________________________
130void AliTOFReconstructioner::Init(Option_t* opt)
131{
132 // Initialize the AliTOFReconstructioner setting parameters for
133 // reconstruction.
134 // Option values: Pb-Pb for Pb-Pb events
135 // pp for pp events
136
137 // set common parameters
138 fdbg=1;
139 fNevents = 1;
140 fFirstEvent = 1;
141 fLastEvent = 1;
142 fTimeResolution =0.120;
143 fpadefficiency =0.99 ;
144 fEdgeEffect = 2 ;
145 fEdgeTails = 0 ;
146 fHparameter = 0.4 ;
147 fH2parameter = 0.15;
148 fKparameter = 0.5 ;
149 fK2parameter = 0.35;
150 fEffCenter = fpadefficiency;
151 fEffBoundary = 0.65;
152 fEff2Boundary = 0.90;
153 fEff3Boundary = 0.08;
154 fResCenter = 50. ;
155 fResBoundary = 70. ;
156 fResSlope = 40. ;
157 fTimeWalkCenter = 0. ;
158 fTimeWalkBoundary=0. ;
159 fTimeWalkSlope = 0. ;
160 fTimeDelayFlag = 1 ;
161 fPulseHeightSlope=2.0 ;
162 fTimeDelaySlope =0.060;
163 // was fMinimumCharge = TMath::Exp(fPulseHeightSlope*fKparameter/2.);
164 fMinimumCharge = TMath::Exp(-fPulseHeightSlope*fHparameter);
165 fChargeSmearing=0.0 ;
166 fLogChargeSmearing=0.13;
167 fTimeSmearing =0.022;
168 fAverageTimeFlag=0 ;
169 fChargeFactorForMatching=1;
170 fTrackingEfficiency=1.0; // 100% TPC tracking efficiency assumed
171 fSigmavsp = 1. ;
172 fSigmaZ = 0. ;
173 fSigmarphi= 0. ;
174 fSigmap = 0. ;
175 fSigmaPhi = 0. ;
176 fSigmaTheta=0. ;
177 fField = 0.2 ;
178 // fRadLenTPC : 0.2 includes TRD / 0.03 TPC only
179 fRadLenTPC=0.06 ; // last value
180 fCorrectionTRD=0. ;
181 fLastTPCRow=111 ;
182 fRadiusvtxBound=50. ; // expressed in [cm]
183 fStep = 0.1 ; // expressed in [cm] step during propagation of the
184 // track inside TOF volumes
185 fMatchingStyle=2 ;
186 /* previous values default
187 fMaxPixels=70000 ;
188 fMaxAllTracks=70000 ;
189 fMaxTracks=15000 ;
190 */
191 fMaxPixels=165000 ;
192 fMaxAllTracks=500000 ;
193 fMaxTracks=15000 ;
194
195 fMaxTOFHits=35000 ;
196 fPBound =0.0 ; // bending effect: P_t=0.3*z*B*R , z particle charge
197 fNoiseSlope=20. ;
198 // set parameters as specified in opt
199 //pp case
200 if(strstr(opt,"pp")){
201 fMaxTestTracks=500 ;
202 fNoise = 26. ;
203 fNoiseMeanTof= 26.4 ; // to check
204 }
205 //Pb-Pb case
206 if(strstr(opt,"Pb-Pb")){
207 fMaxTestTracks=20 ;
208 fNoise = 9400. ;
209 fNoiseMeanTof= 26.4 ;
210 }
211}
212
213//____________________________________________________________________________
214 AliTOFReconstructioner::~AliTOFReconstructioner()
215{
216 //
217 // dtor
218 //
219 if (fg3)
220 {
221 delete fg3;
222 fg3 = 0;
223 }
224 if (foutputfile)
225 {
226 delete foutputfile;
227 foutputfile = 0;
228 }
229 if (foutputntuple)
230 {
231 delete foutputntuple;
232 foutputntuple = 0;
233 }
234
235 if (fZnoise)
236 {
237 delete fZnoise;
238 fZnoise = 0;
239 }
240
241 if (ftail)
242 {
243 delete ftail;
244 ftail = 0;
245 }
246}
247
248//____________________________________________________________________________
249void AliTOFReconstructioner::CreateNTuple()
250{
251 //
252 // Create a Ntuple where information about reconstructed charged particles
253 // (both primaries and secondaries) are stored
254 // Variables: event ipart imam xvtx yvtx zvtx pxvtx pyvtx pzvtx time leng matc text mext
255 // Meaning:
256 // event - event number (0, 1, ...)
257 // ipart - PDG code of particles
258 // imam - PDG code for the parent
259 // =0 for primary particle
260 // xvtx - x-coordinate of the vertex (cm)
261 // yvtx - y-coordinate of the vertex (cm)
262 // zvtx - z-coordinate of the vertex (cm)
263 // pxvtx - x-coordinate of the momentum in the vertex (GeV)
264 // pyvtx - y-coordinate of the momentum in the vertex (GeV)
265 // pzvtx - z-coordinate of the momentum in the vertex (GeV)
266 // time - time of flight from TOF for given track (ps) - TOF time for the
267 // first TOF hit of the track
268 // leng - track length to the TOF pixel (cm), evaluate as a sum of the
269 // track length from the track vertex to TPC and the average
270 // length of the extrapolated track from TPC to TOF.
271 // for the track without TOF hits leng=-abs(leng)
272 // matc - index of the (TPC track) - (TOF pixel) matching
273 // =0 for tracks which are not tracks for matching, i.e.
274 // there is not hit on the TPC or Rvxt>200 cm
275 // >0 for tracks with positive matching procedure:
276 // =1 or 2 for non-identified tracks:
277 // =1, if the corresponding pixel is not fired,
278 // =2, if the corresponding pixel is also matched to the
279 // other track,
280 // =3 or 4 for identified tracks:
281 // =3, if identified with true time,
282 // =4, if identified with wrong time.
283 // <0 for tracks with negative mathing procedure:
284 // =-1, if track do not reach the pixel plate (curved in the
285 // magnetic field),
286 // =-2, if track is out of z-size of the TOF,
287 // =-3, if track is or into the RICH hole, or into the PHOS hole, or in the space between the plates,
288 // =-4, if track is into the dead space of the TOF.
289 // text - time of fligth from the matching procedure = time of the
290 // pixel corresponding to the track (ps)
291 // =0 for the tracks with matc<=1
292 // mext - mass of the track from the matching procedure
293 // =p*sqrt(900*(text/leng)**2-1), if 900*(text/leng)**2-1>=0
294 // =-p*sqrt(abs(900*(text/leng)**2-1)), if 900*(text/leng)**2-1<0
295
296 foutputntuple= new TNtuple("Ntuple","matching","event:ipart:imam:xvtx:yvtx:zvtx:pxvtx:pyvtx:pzvtx:time:leng:matc:text:mext",2000000); // buffersize set for 25 Pb-Pb events
297}
298
299//__________________________________________________________________
300Double_t TimeWithTailR(Double_t* x, Double_t* par)
301{
302 // sigma - par[0], alpha - par[1], part - par[2]
303 // at x<part*sigma - gauss
304 // at x>part*sigma - TMath::Exp(-x/alpha)
305 Float_t xx =x[0];
306 Double_t f;
307 if(xx<par[0]*par[2]) {
308 f = TMath::Exp(-xx*xx/(2*par[0]*par[0]));
309 } else {
310 f = TMath::Exp(-(xx-par[0]*par[2])/par[1]-0.5*par[2]*par[2]);
311 }
312 return f;
313}
314
315//____________________________________________________________________________
316void AliTOFReconstructioner::Exec(const char* datafile, Option_t *option)
317{
318 //
319 // Performs reconstruction for TOF detector
320 //
321 gBenchmark->Start("TOFReconstruction");
322
323 TFile *file = TFile::Open(datafile);
324
325 // Get AliRun object from file or create it if not on file
326 gAlice = (AliRun*)file->Get("gAlice");
327
328 AliTOF* TOF = (AliTOF *) gAlice->GetDetector ("TOF");
329 AliDetector* TPC = gAlice->GetDetector("TPC");
330
331 if (!TOF) {
332 Error("AliTOFReconstructioner","TOF not found");
333 return;
334 }
335 if (!TPC) {
336 Error("AliTOFReconstructioner","TPC Detector not found");
337 return;
338 }
339
340 if (fEdgeTails) ftail = new TF1("tail",TimeWithTailR,-2,2,3);
341
342 if (fNevents == 0) fNevents = (Int_t) gAlice->TreeE()->GetEntries();
343 // You have to set the number of event with the ad hoc setter
344 // see testrecon.C
345
346 for (Int_t ievent = 0; ievent < fNevents; ievent++) { // start loop on events
347
348 Int_t nparticles=gAlice->GetEvent(ievent);
349 if (nparticles <= 0) return;
350
351 TClonesArray* tofhits=0;
352 TClonesArray* tpchits=0;
353
354 if (TOF) tofhits = TOF->Hits();
355 if (TPC) tpchits = TPC->Hits();
356
357 TTree *TH = gAlice->TreeH();
358 if (!TH) return;
359 Int_t ntracks = (Int_t) (TH->GetEntries()); // primary tracks
360 cout << "number of primary tracked tracks in current event " << ntracks << endl; // number of primary tracked tracks
361 // array declaration and initialization
362 // TOF arrays
363 // Int_t mapPixels[AliTOFConstants::fgkNSectors*AliTOFConstants::fgkNPlates][AliTOFConstants::fgkNStripC][AliTOFConstants::fgkNpadZ*AliTOFConstants::fgkNpadX];
364
365 Int_t *** mapPixels = new Int_t**[AliTOFConstants::fgkNSectors*AliTOFConstants::fgkNPlates];
366 for (Int_t i=0; i<AliTOFConstants::fgkNSectors*AliTOFConstants::fgkNPlates; i++) mapPixels[i] = new Int_t*[AliTOFConstants::fgkNStripC];
367 for (Int_t i=0; i<AliTOFConstants::fgkNSectors*AliTOFConstants::fgkNPlates; i++) {
368 for (Int_t j=0; j<AliTOFConstants::fgkNStripC; j++) {
369 mapPixels[i][j]= new Int_t[AliTOFConstants::fgkNpadZ*AliTOFConstants::fgkNpadX];
370 }
371 }
372
373
374 // initializing the previous array
375 for (Int_t i=0;i<AliTOFConstants::fgkNSectors*AliTOFConstants::fgkNPlates;i++) {
376 for (Int_t j=0;j<AliTOFConstants::fgkNStripC;j++) {
377 for (Int_t l=0;l<AliTOFConstants::fgkNpadZ*AliTOFConstants::fgkNpadX;l++) {
378 mapPixels[i][j][l]=0;
379 }
380 }
381 }
382
a020d84f 383 Float_t * toftime = new Float_t[fMaxAllTracks];
f9a28264 384 InitArray(toftime, fMaxAllTracks);
db9ba97f 385 AliTOFPad* pixelArray = new AliTOFPad[fMaxPixels];
f9a28264 386 Int_t* iTOFpixel = new Int_t[fMaxAllTracks];
387 InitArray(iTOFpixel , fMaxAllTracks);
388 Int_t* kTOFhitFirst = new Int_t[fMaxAllTracks];
389 InitArray(kTOFhitFirst, fMaxAllTracks);
db9ba97f 390 AliTOFRecHit* hitArray = new AliTOFRecHit[fMaxTOFHits];
391 Int_t isHitOnFiredPad=0; // index used to fill hitArray (array used to store informations
392 // about pads that contains an hit)
393 Int_t ntotFiredPads=0; // index used to fill array -> total number of fired pads (at least one time)
394
395 // TPC arrays
396 AliTOFTrack* trackArray = new AliTOFTrack[fMaxTracks];
f9a28264 397 Int_t * iparticle = new Int_t[fMaxAllTracks];
398 InitArray(iparticle,fMaxAllTracks);
399 Int_t * iTrackPt = new Int_t[fMaxTracks];
400 InitArray(iTrackPt, fMaxTracks); // array
401 Float_t * ptTrack = new Float_t[fMaxTracks];
402 InitArray( ptTrack, fMaxTracks); // array for selected track pt
db9ba97f 403 Int_t ntotTPCtracks=0; // total number of selected TPC tracks
404
405
406 // reading TOF hits
407 if(TOF) ReadTOFHits(ntracks, TH, tofhits, mapPixels, kTOFhitFirst, pixelArray, iTOFpixel, toftime, hitArray,isHitOnFiredPad,ntotFiredPads);
408 cout << "isHitOnFiredPad " << isHitOnFiredPad << " for event " << ievent << endl;
409
410 // start debug for adding noise
411 // adding noise
412 Int_t nHitsNoNoise=isHitOnFiredPad;
413
414
415 if(fNoise) AddNoiseFromOuter(option,mapPixels,pixelArray,hitArray,isHitOnFiredPad,ntotFiredPads);
416 cout << "ntotFiredPads after adding noise " << ntotFiredPads << " for event " << ievent << endl;
417 // set the hitArray distance to nearest hit
418 SetMinDistance(hitArray,nHitsNoNoise);
419
420 // these lines has to be commented till TPC will provide fPx fPy fPz
421 // and fL in AliTPChit class
422 // reading TPC hits
423 /*
424 if(TPC) ReadTPCHits(ntracks, TH, tpchits, iTrackPt, iparticle, ptTrack, trackArray,ntotTPCtracks);
425 */
426
427 // geometrical matching
428 if(TOF && TPC) Matching(trackArray,hitArray,mapPixels,pixelArray,kTOFhitFirst,ntotFiredPads,iTrackPt,iTOFpixel,ntotTPCtracks);
429
430 // fill ntuple with reconstructed particles from current event
431 FillNtuple(ntracks,trackArray,hitArray,pixelArray,iTOFpixel,iparticle,toftime,ntotFiredPads,ntotTPCtracks);
432
433
434 // free used memory
f9a28264 435 delete [] toftime;
436 delete [] pixelArray;
437 delete [] iTOFpixel;
438 delete [] kTOFhitFirst;
439 delete [] hitArray;
440 delete [] trackArray;
441 delete [] iparticle;
442 delete [] iTrackPt;
443 delete [] ptTrack;
db9ba97f 444
445 for (Int_t i=0; i<AliTOFConstants::fgkNSectors*AliTOFConstants::fgkNPlates; i++) {
446 for (Int_t j=0; j<AliTOFConstants::fgkNStripC; j++) {
447 delete [] mapPixels[i][j];
448 }
449 }
450 for (Int_t i=0; i<AliTOFConstants::fgkNSectors*AliTOFConstants::fgkNPlates; i++) delete [] mapPixels[i];
451
452 delete [] mapPixels;
453
454 }//event loop
455
5fff655e 456 // free used memory for ftail
457 if (ftail)
458 {
459 delete ftail;
460 ftail = 0;
461 }
db9ba97f 462
463 // writing ntuple on output file
464 foutputfile->cd();
465 //foutputntuple->Write(0,TObject::kOverwrite);
466 foutputntuple->Write();
467 foutputfile->Write();
468 foutputfile->Close();
469
470 gBenchmark->Stop("TOFReconstruction");
471 cout << "AliTOFReconstructioner:" << endl ;
472 cout << " took " << gBenchmark->GetCpuTime("TOFReconstruction") << " seconds in order to make the reconstruction for " << fNevents << " events " << endl;
473 cout << gBenchmark->GetCpuTime("TOFReconstruction")/fNevents << " seconds per event " << endl ;
474 cout << endl ;
475
476}
477
478//__________________________________________________________________
479void AliTOFReconstructioner::SetRecFile(char * file )
480{
481 //
482 // Set the file name for reconstruction output
483 //
484 if(!fRecFile.IsNull())
485 cout << "Changing destination file for TOF reconstruction from " <<(char *)fRecFile.Data() << " to " << file << endl ;
486 fRecFile=file ;
487}
488//__________________________________________________________________
489void AliTOFReconstructioner::Print(Option_t* option)const
490{
491 //
492 // Print reconstruction output file name
493 //
494 cout << "------------------- "<< GetName() << " -------------" << endl ;
495 if(fRecFile.IsNull())
496 cout << " Writing reconstructed particles to file galice.root "<< endl ;
497 else
498 cout << " Writing reconstructed particle to file " << (char*) fRecFile.Data() << endl ;
499
500}
501
502//__________________________________________________________________
503void AliTOFReconstructioner::PrintParameters()const
504{
505 //
506 // Print parameters used for reconstruction
507 //
508 cout << " ------------------- "<< GetName() << " -------------" << endl ;
509 cout << " Parameters used for TOF reconstruction " << endl ;
510 // Printing the parameters
511
512 cout << " Number of events: " << fNevents << endl;
513 cout << " Recostruction from event "<< fFirstEvent << " to event "<< fLastEvent << endl;
514 cout << " TOF geometry parameters " << endl;
515 cout << " Min. radius of the TOF (cm) "<< AliTOFConstants::fgkrmin << endl;
516 cout << " Max. radius of the TOF (cm) "<< AliTOFConstants::fgkrmax << endl;
517 cout << " Number of TOF geom. levels "<< AliTOFConstants::fgkmaxtoftree<< endl;
518 cout << " Number of TOF sectors "<< AliTOFConstants::fgkNSectors << endl;
519 cout << " Number of TOF modules "<< AliTOFConstants::fgkNPlates << endl;
520 cout << " Max. Number of strips in a module "<< AliTOFConstants::fgkNStripC << endl;
521 cout << " Number of pads per strip "<< AliTOFConstants::fgkNpadX*AliTOFConstants::fgkNpadZ << endl;
522 cout << " Number of strips in central module "<< AliTOFConstants::fgkNStripA << endl;
523 cout << " Number of strips in intermediate modules "<< AliTOFConstants::fgkNStripB << endl;
524 cout << " Number of strips in outer modules "<< AliTOFConstants::fgkNStripC << endl;
525 cout << " Number of MRPC in x strip direction "<< AliTOFConstants::fgkNpadX<< endl;
526 cout << " Size of MRPC (cm) along X "<< AliTOFConstants::fgkXPad<< endl;
527 cout << " Number of MRPC in z strip direction "<< AliTOFConstants::fgkNpadZ<<endl;
528 cout << " Size of MRPC (cm) along Z "<< AliTOFConstants::fgkZPad<<endl;
529 cout << " Module Lengths (cm)" << endl;
530 cout << " A Module: "<< AliTOFConstants::fgkzlenA<< " B Modules: "<< AliTOFConstants::fgkzlenB<< " C Modules: "<< AliTOFConstants::fgkzlenC<< endl;
531 cout << " Inner radius of the TOF detector (cm): "<<AliTOFConstants::fgkrmin << endl;
532 cout << " Outer radius of the TOF detector (cm): "<<AliTOFConstants::fgkrmax << endl;
533 cout << " Max. half z-size of TOF (cm) : "<<AliTOFConstants::fgkMaxhZtof << endl;
534 cout << " TOF Pad parameters " << endl;
535 cout << " Time Resolution (ns) "<< fTimeResolution <<" Pad Efficiency: "<< fpadefficiency << endl;
536 cout << " Edge Effect option: "<< fEdgeEffect<< endl;
537
538 cout << " Boundary Effect Simulation Parameters " << endl;
539 cout << " Hparameter: "<< fHparameter<<" H2parameter:"<< fH2parameter <<" Kparameter:"<< fKparameter<<" K2parameter: "<< fK2parameter << endl;
540 cout << " Efficiency in the central region of the pad: "<< fEffCenter << endl;
541 cout << " Efficiency at the boundary region of the pad: "<< fEffBoundary << endl;
542 cout << " Efficiency value at H2parameter "<< fEff2Boundary << endl;
543 cout << " Efficiency value at K2parameter "<< fEff3Boundary << endl;
544 cout << " Resolution (ps) in the central region of the pad: "<< fResCenter << endl;
545 cout << " Resolution (ps) at the boundary of the pad : "<< fResBoundary << endl;
546 cout << " Slope (ps/K) for neighbouring pad : "<< fResSlope <<endl;
547 cout << " Time walk (ps) in the central region of the pad : "<< fTimeWalkCenter << endl;
548 cout << " Time walk (ps) at the boundary of the pad : "<< fTimeWalkBoundary<< endl;
549 cout << " Slope (ps/K) for neighbouring pad : "<< fTimeWalkSlope<<endl;
550 cout << " Pulse Heigth Simulation Parameters " << endl;
551 cout << " Flag for delay due to the PulseHeightEffect: "<< fTimeDelayFlag <<endl;
552 cout << " Pulse Height Slope : "<< fPulseHeightSlope<<endl;
553 cout << " Time Delay Slope : "<< fTimeDelaySlope<<endl;
554 cout << " Minimum charge amount which could be induced : "<< fMinimumCharge<<endl;
555 cout << " Smearing in charge in (q1/q2) vs x plot : "<< fChargeSmearing<<endl;
556 cout << " Smearing in log of charge ratio : "<< fLogChargeSmearing<<endl;
557 cout << " Smearing in time in time vs log(q1/q2) plot : "<< fTimeSmearing<<endl;
558 cout << " Flag for average time : "<< fAverageTimeFlag<<endl;
559 cout << " Charge factor flag for matching : "<< fChargeFactorForMatching<<endl;
560 cout << " Edge tails option : "<< fEdgeTails << endl;
561 cout << " TPC tracking parameters " << endl;
562 cout << " TPC tracking efficiency : "<< fTrackingEfficiency<< endl;
563 cout << " Sigma vs momentum dependency flag : "<< fSigmavsp << endl;
564 cout << " Space uncertainties (cm). sigma(z) (cm): "<< fSigmaZ << " sigma(R(phi)) (cm): "<< fSigmarphi << endl;
565 cout << " Momentum uncertainties. sigma(delta(P)/P): "<< fSigmap <<" sigma(phi) (rad): "<< fSigmaPhi <<" sigma(theta) (rad): "<< fSigmaTheta << endl;
566 cout << " Parameters for additional noise hits " << endl;
567 cout << " Number of noise hits : " << fNoise <<" Slope parameter (ns) in the time distribution: " << fNoiseSlope << endl;
568 cout << " Mean TOF for noise from outer regions (ns)" << fNoiseMeanTof << endl;
569 cout << " Physical parameters " << endl;
570 cout << " Magnetic Field (tesla) : "<< fField <<endl;
571 cout << " Radiation length of the outer wall of TPC: "<< fRadLenTPC << endl;
572 cout << " (TPC tracks)-(TOF pads) matching parameters " << endl;
573 cout << " TRD Correction flag : "<< fCorrectionTRD <<endl;
574 cout << " Number of the last TPC row: "<< fLastTPCRow <<" Vertex radius (cm) for selected tracks: "<<fRadiusvtxBound<<endl;
575 cout << " Max. number of test tracks: "<<fMaxTestTracks << endl;
576 cout << " Space step (cm) : "<< fStep <<endl;
577 cout << " Matching style option : "<< fMatchingStyle <<endl;
578 cout << " Array parameters " << endl;
579 cout << " Max.number of pads involved in the matching procedure: "<< fMaxPixels << endl;
580 cout << " Max.number of TOF hits per event : "<< fMaxTOFHits<< endl;
581 cout << " Max.number of tracks selected for matching : "<< fMaxTracks << endl;
582 cout << " Max.number of all tracks including the neutral ones : "<< fMaxAllTracks<< endl;
583 cout << " Debug Flag : "<< fdbg << endl;
584 cout << " Cut on momentum for selecting tracks : "<< fPBound << endl;
585
586}
587
588//__________________________________________________________________
589void AliTOFReconstructioner::IsInsideThePad(TGeant3 *g3, Float_t x, Float_t y, Float_t z, Int_t *nGeom, Float_t& zPad, Float_t& xPad)
590{
591 // input: x,y,z - coordinates of a hit
592 // output: array nGeom[]
593 // nGeom[0] - the TOF sector number, 1,2,...,18 along azimuthal direction starting from -90 deg.!!!
594 // nGeom[1] - the TOF module number, 1,2,3,4,5=C,B,A,B,C along z-direction
595 // nGeom[2] - the TOF strip number, 1,2,... along z-direction
596 // nGeom[3] - the TOF padz number, 1,2=NPZ across a strip
597 // nGeom[4] - the TOF padx number, 1,2,...,48=NPX along a strip
598 // zPad, xPad - coordinates of the hit in the pad frame
599 // numbering is adopted for the version 3.05 of AliRoot
600 // example:
601 // from Hits: sec,pla,str,padz,padx=4,2,14,2,35
602 // Vol. n.0: ALIC, copy number 1
603 // Vol. n.1: B077, copy number 1
604 // Vol. n.2: B074, copy number 5
605 // Vol. n.3: BTO2, copy number 1
606 // Vol. n.4: FTOB, copy number 2
607 // Vol. n.5: FLTB, copy number 0
608 // Vol. n.6: FSTR, copy number 14
609 // Vol. n.7: FSEN, copy number 0
610 // Vol. n.8: FSEZ, copy number 2
611 // Vol. n.9: FSEX, copy number 35
612 // Vol. n.10: FPAD, copy number 0
613
614
615 Float_t xTOF[3];
616 Int_t sector=0,module=0,strip=0,padz=0,padx=0;
617 Int_t i,numed,nLevel,copyNumber;
618 Gcvolu_t* gcvolu;
619 char name[5];
620 name[4]=0;
621
622 for (i=0; i<AliTOFConstants::fgkmaxtoftree; i++) nGeom[i]=0;
623 zPad=100.;
624 xPad=100.;
625
626 xTOF[0]=x;
627 xTOF[1]=y;
628 xTOF[2]=z;
629
630 g3->Gmedia(xTOF, numed);
631 gcvolu=g3->Gcvolu();
632 nLevel=gcvolu->nlevel;
633 if(fdbg) {
634 for (Int_t i=0; i<nLevel; i++) {
635 strncpy(name,(char*) (&gcvolu->names[i]),4);
636 cout<<"Vol. n."<<i<<": "<<name<<", copy number "<<gcvolu->number[i]<<endl;
637 }
638 }
639 if(nLevel>=2) {
640 // sector type name: B071(1,2,...,10),B074(1,2,3,4,5-PHOS),B075(1,2,3-RICH)
641 strncpy(name,(char*) (&gcvolu->names[2]),4);
642 // volume copy: 1,2,...,10 for B071, 1,2,3,4,5 for B074, 1,2,3 for B075
643 copyNumber=gcvolu->number[2];
644 if(!strcmp(name,"B071")) {
645 if (copyNumber>=6 && copyNumber<=8) {
646 sector=copyNumber+10;
647 } else if (copyNumber>=1 && copyNumber<=5){
648 sector=copyNumber+7;
649 } else {
650 sector=copyNumber-8;
651 }
652 } else if(!strcmp(name,"B075")) {
653 sector=copyNumber+12;
654 } else if(!strcmp(name,"B074")) {
655 if (copyNumber>=1 && copyNumber<=3){
656 sector=copyNumber+4;
657 } else {
658 sector=copyNumber-1;
659 }
660 }
661 }
662 if(sector) {
663 nGeom[0]=sector;
664 if(nLevel>=4) {
665 // we'll use the module value in z-direction:
666 // 1 2 3 4 5
667 // the module order in z-direction: FTOC,FTOB,FTOA,FTOB,FTOC
668 // the module copy: 2 2 0 1 1
669 // module type name: FTOA, FTOB, FTOC
670 strncpy(name,(char*) (&gcvolu->names[4]),4);
671 // module copy:
672 copyNumber=gcvolu->number[4];
673 if(!strcmp(name,"FTOC")) {
674 if (copyNumber==2) {
675 module=1;
676 } else {
677 module=5;
678 }
679 } else if(!strcmp(name,"FTOB")) {
680 if (copyNumber==2) {
681 module=2;
682 } else {
683 module=4;
684 }
685 } else if(!strcmp(name,"FTOA")) {
686 module=3;
687 }
688 }
689 }
690
691 if(module) {
692 nGeom[1]=module;
693 if(nLevel>=6) {
694 // strip type name: FSTR
695 strncpy(name,(char*) (&gcvolu->names[6]),4);
696 // strip copy:
697 copyNumber=gcvolu->number[6];
698 if(!strcmp(name,"FSTR")) strip=copyNumber;
699 }
700 }
701
702 if(strip) {
703 nGeom[2]=strip;
704 if(nLevel>=8) {
705 // padz type name: FSEZ
706 strncpy(name,(char*) (&gcvolu->names[8]),4);
707 // padz copy:
708 copyNumber=gcvolu->number[8];
709 if(!strcmp(name,"FSEZ")) padz=copyNumber;
710 }
711 }
712 if(padz) {
713 nGeom[3]=padz;
714 if(nLevel>=9) {
715 // padx type name: FSEX
716 strncpy(name,(char*) (&gcvolu->names[9]),4);
717 // padx copy:
718 copyNumber=gcvolu->number[9];
719 if(!strcmp(name,"FSEX")) padx=copyNumber;
720 }
721 }
722
723 if(padx) {
724 nGeom[4]=padx;
725 zPad=gcvolu->glx[2]; // check here
726 xPad=gcvolu->glx[0]; // check here
727 }
728
729 // printf(" nGeom[0,1,2,3,4]=%i,%i,%i,%i,%i\n",nGeom[0],nGeom[1],nGeom[2],nGeom[3],nGeom[4]);
730}
731
732//__________________________________________________________________
733void AliTOFReconstructioner::EpMulScatt(Float_t& px, Float_t& py, Float_t& pz, Float_t& p, Float_t& theta)
734{
735 // Momentum p - before mult.scat.
736 // Momentum p2 - after mult.scat.
737 // THE0 - r.m.s. of deviation angle in plane
738 // (see RPP'96: Phys.Rev.D54 (1996) 134)
739
740 Float_t pt,thex,they,tantx,tanty,p2px,p2py,p2pz,costhe,sinthe,cospsi,sinpsi,p2x,p2y,p2z,p2,g;
741
742 pt=TMath::Sqrt(px*px+py*py);
743 // angles for p in the ' frame with Z'along p
744 if(fMatchingStyle==1) {
745 thex=theta*gRandom->Gaus();
746 they=theta*gRandom->Gaus();
747 } else {
748 thex=3*(-theta+2*theta*gRandom->Rndm());
749 they=3*(-theta+2*theta*gRandom->Rndm());
750 }
751 tantx=TMath::Tan(thex);
752 tanty=TMath::Tan(they);
753
754 // p2p - p2 in the ' frame
755 p2pz=p/TMath::Sqrt(1.+tantx*tantx+tanty*tanty);
756 p2py=p2pz*tanty;
757 p2px=p2pz*tantx;
758 // choose X'so that PHI=0 (see Il'in, Pozdnyak Analiticheskaya geometriya, 1968, c.88
759 // for Euler angles PSI, THETA (PHI=0)
760 costhe=pz/p;
761 sinthe=pt/p;
762 cospsi=-py/pt;
763 sinpsi=px/pt;
764 //
765 g=p2py*costhe-p2pz*sinthe;
766 p2x=p2px*cospsi-g*sinpsi;
767 p2y=p2px*sinpsi+g*cospsi;
768 p2z=p2py*sinthe+p2pz*costhe;
769 p2=TMath::Sqrt(p2x*p2x+p2y*p2y+p2z*p2z);
770
771 // Test angle
772 g=(px*p2x+py*p2y+pz*p2z)/(p*p2);
773 if(g>1) g=1;
774 theta=TMath::ACos(g);
775 px=p2x;
776 py=p2y;
777 pz=p2z;
778 p=p2;
779
780}
781
782// std border effect algorithm
783//__________________________________________________________________
784void AliTOFReconstructioner::BorderEffect(Float_t z0, Float_t x0, Float_t geantTime, Int_t& nActivatedPads, Int_t& nFiredPads, Bool_t* isFired, Int_t* nPlace, Float_t* qInduced, Float_t* tofTime, Float_t& averageTime)
785{
786 // Input: z0, x0 - hit position in the strip system (0,0 - center of the strip), cm
787 // geantTime - time generated by Geant, ns
788 // Output: nActivatedPads - the number of pads activated by the hit (1 || 2 || 4)
789 // nFiredPads - the number of pads fired (really activated) by the hit (nFiredPads <= nActivatedPads)
790 // qInduced[iPad]- charge induced on pad, arb. units
791 // this array is initialized at zero by the caller
792 // tofAfterSimul[iPad] - time calculated with edge effect algorithm, ns
793 // this array is initialized at zero by the caller
794 // averageTime - time given by pad hited by the Geant track taking into account the times (weighted) given by the pads fired for edge effect also.
795 // The weight is given by the qInduced[iPad]/qCenterPad
796 // this variable is initialized at zero by the caller
797 // nPlace[iPad] - the number of the pad place, iPad = 0, 1, 2, 3
798 // this variable is initialized at zero by the caller
799 //
800 // Description of used variables:
801 // eff[iPad] - efficiency of the pad
802 // res[iPad] - resolution of the pad, ns
803 // timeWalk[iPad] - time walk of the pad, ns
804 // timeDelay[iPad] - time delay for neighbouring pad to hited pad, ns
805 // PadId[iPad] - Pad Identifier
806 // E | F --> PadId[iPad] = 5 | 6
807 // A | B --> PadId[iPad] = 1 | 2
808 // C | D --> PadId[iPad] = 3 | 4
809 // nTail[iPad] - the tail number, = 1 for tailA, = 2 for tailB
810 // qCenterPad - charge extimated for each pad, arb. units
811 // weightsSum - sum of weights extimated for each pad fired, arb. units
812
813 const Float_t kSigmaForTail[2] = {AliTOFConstants::fgkSigmaForTail1,AliTOFConstants::fgkSigmaForTail2}; //for tail
814 Int_t iz = 0, ix = 0;
815 Float_t dX = 0., dZ = 0., x = 0., z = 0.;
816 Float_t h = fHparameter, h2 = fH2parameter, k = fKparameter, k2 = fK2parameter;
817 Float_t effX = 0., effZ = 0., resX = 0., resZ = 0., timeWalkX = 0., timeWalkZ = 0.;
818 Float_t logOfqInd = 0.;
819 Float_t weightsSum = 0.;
820 Int_t nTail[4] = {0,0,0,0};
821 Int_t padId[4] = {0,0,0,0};
822 Float_t eff[4] = {0.,0.,0.,0.};
823 Float_t res[4] = {0.,0.,0.,0.};
824 // Float_t qCenterPad = fMinimumCharge * fMinimumCharge;
825 Float_t qCenterPad = 1.;
826 Float_t timeWalk[4] = {0.,0.,0.,0.};
827 Float_t timeDelay[4] = {0.,0.,0.,0.};
828
829 nActivatedPads = 0;
830 nFiredPads = 0;
831
832 (z0 <= 0) ? iz = 0 : iz = 1;
833 dZ = z0 + (0.5 * AliTOFConstants::fgkNpadZ - iz - 0.5) * AliTOFConstants::fgkZPad; // hit position in the pad frame, (0,0) - center of the pad
834 z = 0.5 * AliTOFConstants::fgkZPad - TMath::Abs(dZ); // variable for eff., res. and timeWalk. functions
835 iz++; // z row: 1, ..., AliTOFConstants::fgkNpadZ = 2
836 ix = (Int_t)((x0 + 0.5 * AliTOFConstants::fgkNpadX * AliTOFConstants::fgkXPad) / AliTOFConstants::fgkXPad);
837 dX = x0 + (0.5 * AliTOFConstants::fgkNpadX - ix - 0.5) * AliTOFConstants::fgkXPad; // hit position in the pad frame, (0,0) - center of the pad
838 x = 0.5 * AliTOFConstants::fgkXPad - TMath::Abs(dX); // variable for eff., res. and timeWalk. functions;
839 ix++; // x row: 1, ..., AliTOFConstants::fgkNpadX = 48
840
841 ////// Pad A:
842 nActivatedPads++;
843 nPlace[nActivatedPads-1] = (iz - 1) * AliTOFConstants::fgkNpadX + ix;
844 qInduced[nActivatedPads-1] = qCenterPad;
845 padId[nActivatedPads-1] = 1;
846
847 if (fEdgeEffect == 0) {
848 eff[nActivatedPads-1] = fEffCenter;
849 if (gRandom->Rndm() < eff[nActivatedPads-1]) {
850 nFiredPads = 1;
851 res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + fResCenter * fResCenter); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns;
852 isFired[nActivatedPads-1] = kTRUE;
853 tofTime[nActivatedPads-1] = gRandom->Gaus(geantTime + fTimeWalkCenter, res[0]);
854 averageTime = tofTime[nActivatedPads-1];
855 }
856 } else {
857
858 if(z < h) {
859 if(z < h2) {
860 effZ = fEffBoundary + (fEff2Boundary - fEffBoundary) * z / h2;
861 } else {
862 effZ = fEff2Boundary + (fEffCenter - fEff2Boundary) * (z - h2) / (h - h2);
863 }
864 resZ = fResBoundary + (fResCenter - fResBoundary) * z / h;
865 timeWalkZ = fTimeWalkBoundary + (fTimeWalkCenter - fTimeWalkBoundary) * z / h;
866 nTail[nActivatedPads-1] = 1;
867 } else {
868 effZ = fEffCenter;
869 resZ = fResCenter;
870 timeWalkZ = fTimeWalkCenter;
871 }
872
873 if(x < h) {
874 if(x < h2) {
875 effX = fEffBoundary + (fEff2Boundary - fEffBoundary) * x / h2;
876 } else {
877 effX = fEff2Boundary + (fEffCenter - fEff2Boundary) * (x - h2) / (h - h2);
878 }
879 resX = fResBoundary + (fResCenter - fResBoundary) * x / h;
880 timeWalkX = fTimeWalkBoundary + (fTimeWalkCenter - fTimeWalkBoundary) * x / h;
881 nTail[nActivatedPads-1] = 1;
882 } else {
883 effX = fEffCenter;
884 resX = fResCenter;
885 timeWalkX = fTimeWalkCenter;
886 }
887
888 (effZ<effX) ? eff[nActivatedPads-1] = effZ : eff[nActivatedPads-1] = effX;
889 (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
890 (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
891
892
893 ////// Pad B:
894 if(z < k2) {
895 effZ = fEffBoundary - (fEffBoundary - fEff3Boundary) * (z / k2);
896 } else {
897 effZ = fEff3Boundary * (k - z) / (k - k2);
898 }
899 resZ = fResBoundary + fResSlope * z / k;
900 timeWalkZ = fTimeWalkBoundary + fTimeWalkSlope * z / k;
901
902 if(z < k && z > 0) {
903 if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
904 nActivatedPads++;
905 nPlace[nActivatedPads-1] = nPlace[0] + (3 - 2 * iz) * AliTOFConstants::fgkNpadX;
906 eff[nActivatedPads-1] = effZ;
907 res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
908 timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ; // ns
909 nTail[nActivatedPads-1] = 2;
910 if (fTimeDelayFlag) {
911 // qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
912 // qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
913 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * z);
914 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
915 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
916 } else {
917 timeDelay[nActivatedPads-1] = 0.;
918 }
919 padId[nActivatedPads-1] = 2;
920 }
921 }
922
923
924 ////// Pad C, D, E, F:
925 if(x < k2) {
926 effX = fEffBoundary - (fEffBoundary - fEff3Boundary) * (x / k2);
927 } else {
928 effX = fEff3Boundary * (k - x) / (k - k2);
929 }
930 resX = fResBoundary + fResSlope*x/k;
931 timeWalkX = fTimeWalkBoundary + fTimeWalkSlope*x/k;
932
933 if(x < k && x > 0) {
934 // C:
935 if(ix > 1 && dX < 0) {
936 nActivatedPads++;
937 nPlace[nActivatedPads-1] = nPlace[0] - 1;
938 eff[nActivatedPads-1] = effX;
939 res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
940 timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
941 nTail[nActivatedPads-1] = 2;
942 if (fTimeDelayFlag) {
943 // qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
944 // qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
945 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
946 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
947 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
948 } else {
949 timeDelay[nActivatedPads-1] = 0.;
950 }
951 padId[nActivatedPads-1] = 3;
952
953 // D:
954 if(z < k && z > 0) {
955 if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
956 nActivatedPads++;
957 nPlace[nActivatedPads-1] = nPlace[0] + (3 - 2 * iz) * AliTOFConstants::fgkNpadX - 1;
958 eff[nActivatedPads-1] = effX * effZ;
959 (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
960 (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
961
962 nTail[nActivatedPads-1] = 2;
963 if (fTimeDelayFlag) {
964 if (TMath::Abs(x) < TMath::Abs(z)) {
965 // qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
966 // qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
967 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * z);
968 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
969 } else {
970 // qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
971 // qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
972 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
973 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
974 }
975 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
976 } else {
977 timeDelay[nActivatedPads-1] = 0.;
978 }
979 padId[nActivatedPads-1] = 4;
980 }
981 } // end D
982 } // end C
983
984 // E:
985 if(ix < AliTOFConstants::fgkNpadX && dX > 0) {
986 nActivatedPads++;
987 nPlace[nActivatedPads-1] = nPlace[0] + 1;
988 eff[nActivatedPads-1] = effX;
989 res[nActivatedPads-1] = 0.001 * (TMath::Sqrt(10400 + resX * resX)); // ns
990 timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
991 nTail[nActivatedPads-1] = 2;
992 if (fTimeDelayFlag) {
993 // qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
994 // qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
995 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
996 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
997 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
998 } else {
999 timeDelay[nActivatedPads-1] = 0.;
1000 }
1001 padId[nActivatedPads-1] = 5;
1002
1003
1004 // F:
1005 if(z < k && z > 0) {
1006 if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
1007 nActivatedPads++;
1008 nPlace[nActivatedPads - 1] = nPlace[0] + (3 - 2 * iz) * AliTOFConstants::fgkNpadX + 1;
1009 eff[nActivatedPads - 1] = effX * effZ;
1010 (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
1011 (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001*timeWalkX; // ns
1012 nTail[nActivatedPads-1] = 2;
1013 if (fTimeDelayFlag) {
1014 if (TMath::Abs(x) < TMath::Abs(z)) {
1015 // qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
1016 // qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
1017 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * z);
1018 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
1019 } else {
1020 // qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
1021 // qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
1022 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
1023 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
1024 }
1025 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
1026 } else {
1027 timeDelay[nActivatedPads-1] = 0.;
1028 }
1029 padId[nActivatedPads-1] = 6;
1030 }
1031 } // end F
1032 } // end E
1033 } // end if(x < k)
1034
1035
1036 for (Int_t iPad = 0; iPad < nActivatedPads; iPad++) {
1037 if (res[iPad] < fTimeResolution) res[iPad] = fTimeResolution;
1038 if(gRandom->Rndm() < eff[iPad]) {
1039 isFired[iPad] = kTRUE;
1040 nFiredPads++;
1041 if(fEdgeTails) {
1042 if(nTail[iPad] == 0) {
1043 tofTime[iPad] = gRandom->Gaus(geantTime + timeWalk[iPad] + timeDelay[iPad], res[iPad]);
1044 } else {
1045 ftail->SetParameters(res[iPad], 2. * res[iPad], kSigmaForTail[nTail[iPad]-1]);
1046 Double_t timeAB = ftail->GetRandom();
1047 tofTime[iPad] = geantTime + timeWalk[iPad] + timeDelay[iPad] + timeAB;
1048 }
1049 } else {
1050 tofTime[iPad] = gRandom->Gaus(geantTime + timeWalk[iPad] + timeDelay[iPad], res[iPad]);
1051 }
1052 if (fAverageTimeFlag) {
1053 averageTime += tofTime[iPad] * qInduced[iPad];
1054 weightsSum += qInduced[iPad];
1055 } else {
1056 averageTime += tofTime[iPad];
1057 weightsSum += 1.;
1058 }
1059 }
1060 }
1061 if (weightsSum!=0) averageTime /= weightsSum;
1062 } // end else (fEdgeEffect != 0)
1063}
1064
1065
1066/* new algorithm (to be checked)
1067//__________________________________________________________________
1068void AliTOFReconstructioner::BorderEffect(Float_t z0, Float_t x0, Float_t geantTime, Int_t& nActivatedPads, Int_t& nFiredPads, Bool_t* isFired, Int_t* nPlace, Float_t* qInduced, Float_t* tofTime, Float_t& averageTime)
1069{
1070 // Input: z0, x0 - hit position in the strip system (0,0 - center of the strip), cm
1071 // geantTime - time generated by Geant, ns
1072 // Output: nActivatedPads - the number of pads activated by the hit (1 || 2 || 4)
1073 // nFiredPads - the number of pads fired (really activated) by the hit (nFiredPads <= nActivatedPads)
1074 // qInduced[iPad]- charge induced on pad, arb. units
1075 // this array is initialized at zero by the caller
1076 // tofAfterSimul[iPad] - time calculated with edge effect algorithm, ns
1077 // this array is initialized at zero by the caller
1078 // averageTime - time given by pad hited by the Geant track taking into account the times (weighted) given by the pads fired for edge effect also.
1079 // The weight is given by the qInduced[iPad]/qCenterPad
1080 // this variable is initialized at zero by the caller
1081 // nPlace[iPad] - the number of the pad place, iPad = 0, 1, 2, 3
1082 // this variable is initialized at zero by the caller
1083 //
1084 // Description of used variables:
1085 // eff[iPad] - efficiency of the pad
1086 // res[iPad] - resolution of the pad, ns
1087 // timeWalk[iPad] - time walk of the pad, ns
1088 // timeDelay[iPad] - time delay for neighbouring pad to hited pad, ns
1089 // PadId[iPad] - Pad Identifier
1090 // E | F --> PadId[iPad] = 5 | 6
1091 // A | B --> PadId[iPad] = 1 | 2
1092 // C | D --> PadId[iPad] = 3 | 4
1093 // nTail[iPad] - the tail number, = 1 for tailA, = 2 for tailB
1094 // qCenterPad - charge extimated for each pad, arb. units
1095 // weightsSum - sum of weights extimated for each pad fired, arb. units
1096
1097 const Float_t kSigmaForTail[2] = {AliTOFConstants::fgkSigmaForTail1,AliTOFConstants::fgkSigmaForTail2}; //for tail
1098 Int_t iz = 0, ix = 0;
1099 Float_t dX = 0., dZ = 0., x = 0., z = 0.;
1100 Float_t h = fHparameter, h2 = fH2parameter, k = fKparameter, k2 = fK2parameter;
1101 Float_t effX = 0., effZ = 0., resX = 0., resZ = 0., timeWalkX = 0., timeWalkZ = 0.;
1102 Float_t logOfqInd = 0.;
1103 Float_t weightsSum = 0.;
1104 Int_t nTail[4] = {0,0,0,0};
1105 Int_t padId[4] = {0,0,0,0};
1106 Float_t eff[4] = {0.,0.,0.,0.};
1107 Float_t res[4] = {0.,0.,0.,0.};
1108 Float_t qCenterPad = fMinimumCharge * fMinimumCharge;
1109 Float_t timeWalk[4] = {0.,0.,0.,0.};
1110 Float_t timeDelay[4] = {0.,0.,0.,0.};
1111
1112 nActivatedPads = 0;
1113 nFiredPads = 0;
1114
1115 (z0 <= 0) ? iz = 0 : iz = 1;
1116 dZ = z0 + (0.5 * AliTOFConstants::fgkNpadZ - iz - 0.5) * AliTOFConstants::fgkZPad; // hit position in the pad frame, (0,0) - center of the pad
1117 z = 0.5 * AliTOFConstants::fgkZPad - TMath::Abs(dZ); // variable for eff., res. and timeWalk. functions
1118 iz++; // z row: 1, ..., AliTOFConstants::fgkNpadZ = 2
1119 ix = (Int_t)((x0 + 0.5 * AliTOFConstants::fgkNpadX * AliTOFConstants::fgkXPad) / AliTOFConstants::fgkXPad);
1120 dX = x0 + (0.5 * AliTOFConstants::fgkNpadX - ix - 0.5) * AliTOFConstants::fgkXPad; // hit position in the pad frame, (0,0) - center of the pad
1121 x = 0.5 * AliTOFConstants::fgkXPad - TMath::Abs(dX); // variable for eff., res. and timeWalk. functions;
1122 ix++; // x row: 1, ..., AliTOFConstants::fgkNpadX = 48
1123
1124 ////// Pad A:
1125 nActivatedPads++;
1126 nPlace[nActivatedPads-1] = (iz - 1) * AliTOFConstants::fgkNpadX + ix;
1127 qInduced[nActivatedPads-1] = qCenterPad;
1128 padId[nActivatedPads-1] = 1;
1129
1130 if (fEdgeEffect == 0) {
1131 eff[nActivatedPads-1] = fEffCenter;
1132 if (gRandom->Rndm() < eff[nActivatedPads-1]) {
1133 nFiredPads = 1;
1134 res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + fResCenter * fResCenter); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns;
1135 isFired[nActivatedPads-1] = kTRUE;
1136 tofTime[nActivatedPads-1] = gRandom->Gaus(geantTime + fTimeWalkCenter, res[0]);
1137 averageTime = tofTime[nActivatedPads-1];
1138 }
1139 } else {
1140
1141 if(z < h) {
1142 if(z < h2) {
1143 effZ = fEffBoundary + (fEff2Boundary - fEffBoundary) * z / h2;
1144 } else {
1145 effZ = fEff2Boundary + (fEffCenter - fEff2Boundary) * (z - h2) / (h - h2);
1146 }
1147 resZ = fResBoundary + (fResCenter - fResBoundary) * z / h;
1148 timeWalkZ = fTimeWalkBoundary + (fTimeWalkCenter - fTimeWalkBoundary) * z / h;
1149 nTail[nActivatedPads-1] = 1;
1150 } else {
1151 effZ = fEffCenter;
1152 resZ = fResCenter;
1153 timeWalkZ = fTimeWalkCenter;
1154 }
1155
1156 if(x < h) {
1157 if(x < h2) {
1158 effX = fEffBoundary + (fEff2Boundary - fEffBoundary) * x / h2;
1159 } else {
1160 effX = fEff2Boundary + (fEffCenter - fEff2Boundary) * (x - h2) / (h - h2);
1161 }
1162 resX = fResBoundary + (fResCenter - fResBoundary) * x / h;
1163 timeWalkX = fTimeWalkBoundary + (fTimeWalkCenter - fTimeWalkBoundary) * x / h;
1164 nTail[nActivatedPads-1] = 1;
1165 } else {
1166 effX = fEffCenter;
1167 resX = fResCenter;
1168 timeWalkX = fTimeWalkCenter;
1169 }
1170
1171 (effZ<effX) ? eff[nActivatedPads-1] = effZ : eff[nActivatedPads-1] = effX;
1172 (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
1173 (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
1174
1175
1176 ////// Pad B:
1177 if(z < k2) {
1178 effZ = fEffBoundary - (fEffBoundary - fEff3Boundary) * (z / k2);
1179 } else {
1180 effZ = fEff3Boundary * (k - z) / (k - k2);
1181 }
1182 resZ = fResBoundary + fResSlope * z / k;
1183 timeWalkZ = fTimeWalkBoundary + fTimeWalkSlope * z / k;
1184
1185 if(z < k && z > 0) {
1186 if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
1187 nActivatedPads++;
1188 nPlace[nActivatedPads-1] = nPlace[0] + (3 - 2 * iz) * AliTOFConstants::fgkNpadX;
1189 eff[nActivatedPads-1] = effZ;
1190 res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
1191 timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ; // ns
1192 nTail[nActivatedPads-1] = 2;
1193 if (fTimeDelayFlag) {
1194 qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
1195 qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
1196 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
1197 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
1198 } else {
1199 timeDelay[nActivatedPads-1] = 0.;
1200 }
1201 padId[nActivatedPads-1] = 2;
1202 }
1203 }
1204
1205
1206 ////// Pad C, D, E, F:
1207 if(x < k2) {
1208 effX = fEffBoundary - (fEffBoundary - fEff3Boundary) * (x / k2);
1209 } else {
1210 effX = fEff3Boundary * (k - x) / (k - k2);
1211 }
1212 resX = fResBoundary + fResSlope*x/k;
1213 timeWalkX = fTimeWalkBoundary + fTimeWalkSlope*x/k;
1214
1215 if(x < k && x > 0) {
1216 // C:
1217 if(ix > 1 && dX < 0) {
1218 nActivatedPads++;
1219 nPlace[nActivatedPads-1] = nPlace[0] - 1;
1220 eff[nActivatedPads-1] = effX;
1221 res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
1222 timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
1223 nTail[nActivatedPads-1] = 2;
1224 if (fTimeDelayFlag) {
1225 qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
1226 qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
1227 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
1228 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
1229 } else {
1230 timeDelay[nActivatedPads-1] = 0.;
1231 }
1232 padId[nActivatedPads-1] = 3;
1233
1234 // D:
1235 if(z < k && z > 0) {
1236 if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
1237 nActivatedPads++;
1238 nPlace[nActivatedPads-1] = nPlace[0] + (3 - 2 * iz) * AliTOFConstants::fgkNpadX - 1;
1239 eff[nActivatedPads-1] = effX * effZ;
1240 (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
1241 (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
1242
1243 nTail[nActivatedPads-1] = 2;
1244 if (fTimeDelayFlag) {
1245 if (TMath::Abs(x) < TMath::Abs(z)) {
1246 qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
1247 qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
1248 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
1249 } else {
1250 qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
1251 qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
1252 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
1253 }
1254 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
1255 } else {
1256 timeDelay[nActivatedPads-1] = 0.;
1257 }
1258 padId[nActivatedPads-1] = 4;
1259 }
1260 } // end D
1261 } // end C
1262
1263 // E:
1264 if(ix < AliTOFConstants::fgkNpadX && dX > 0) {
1265 nActivatedPads++;
1266 nPlace[nActivatedPads-1] = nPlace[0] + 1;
1267 eff[nActivatedPads-1] = effX;
1268 res[nActivatedPads-1] = 0.001 * (TMath::Sqrt(10400 + resX * resX)); // ns
1269 timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
1270 nTail[nActivatedPads-1] = 2;
1271 if (fTimeDelayFlag) {
1272 qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
1273 qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
1274 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
1275 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
1276 } else {
1277 timeDelay[nActivatedPads-1] = 0.;
1278 }
1279 padId[nActivatedPads-1] = 5;
1280
1281
1282 // F:
1283 if(z < k && z > 0) {
1284 if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
1285 nActivatedPads++;
1286 nPlace[nActivatedPads - 1] = nPlace[0] + (3 - 2 * iz) * AliTOFConstants::fgkNpadX + 1;
1287 eff[nActivatedPads - 1] = effX * effZ;
1288 (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(10400 + resZ * resZ); // 10400=30^2+20^2+40^2+50^2+50^2+50^2 ns
1289 (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001*timeWalkX; // ns
1290 nTail[nActivatedPads-1] = 2;
1291 if (fTimeDelayFlag) {
1292 if (TMath::Abs(x) < TMath::Abs(z)) {
1293 qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
1294 qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
1295 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
1296 } else {
1297 qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
1298 qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
1299 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
1300 }
1301 timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
1302 } else {
1303 timeDelay[nActivatedPads-1] = 0.;
1304 }
1305 padId[nActivatedPads-1] = 6;
1306 }
1307 } // end F
1308 } // end E
1309 } // end if(x < k)
1310
1311
1312 for (Int_t iPad = 0; iPad < nActivatedPads; iPad++) {
1313 if (res[iPad] < fTimeResolution) res[iPad] = fTimeResolution;
1314 if(gRandom->Rndm() < eff[iPad]) {
1315 isFired[iPad] = kTRUE;
1316 nFiredPads++;
1317 if(fEdgeTails) {
1318 if(nTail[iPad] == 0) {
1319 tofTime[iPad] = gRandom->Gaus(geantTime + timeWalk[iPad] + timeDelay[iPad], res[iPad]);
1320 } else {
1321 ftail->SetParameters(res[iPad], 2. * res[iPad], kSigmaForTail[nTail[iPad]-1]);
1322 Double_t timeAB = ftail->GetRandom();
1323 tofTime[iPad] = geantTime + timeWalk[iPad] + timeDelay[iPad] + timeAB;
1324 }
1325 } else {
1326 tofTime[iPad] = gRandom->Gaus(geantTime + timeWalk[iPad] + timeDelay[iPad], res[iPad]);
1327 }
1328 if (fAverageTimeFlag) {
1329 averageTime += tofTime[iPad] * qInduced[iPad];
1330 weightsSum += qInduced[iPad];
1331 } else {
1332 averageTime += tofTime[iPad];
1333 weightsSum += 1.;
1334 }
1335 }
1336 }
1337 if (weightsSum!=0) averageTime /= weightsSum;
1338
1339 } // end else (fEdgeEffect != 0)
1340
1341 //cout << "timedelay " << timeDelay[0] << endl;
1342 //cout << "timedelay " << timeDelay[1] << endl;
1343 //cout << "timedelay " << timeDelay[2] << endl;
1344 //cout << "timedelay " << timeDelay[3] << endl;
1345
1346}
1347*/
1348
1349
1350//__________________________________________________________________
1351Int_t AliTOFReconstructioner::PDGtoGeantCode(Int_t pdgcode)
1352{
1353 //
1354 // Gives the GEANT code from KF code of LUND JETSET
1355 //
1356 Int_t geantCode=0; // default value
1357 switch (pdgcode) {
1358 case 22:
1359 geantCode=1; // GAMMA
1360 break ;
1361 case -11:
1362 geantCode=2; // E+
1363 break ;
1364 case 11:
1365 geantCode=3; // E-
1366 break ;
1367 case 12:
1368 geantCode=4; // NUE
1369 break ;
1370 case 14:
1371 geantCode=4; // NUMU
1372 break ;
1373 case -13:
1374 geantCode=5; // MU+
1375 break ;
1376 case 13:
1377 geantCode=6; // MU-
1378 break ;
1379 case 111:
1380 geantCode=7; // PI0
1381 break ;
1382 case 211:
1383 geantCode=8; // PI+
1384 break ;
1385 case -211:
1386 geantCode=9; // PI-
1387 break ;
1388 case 130:
1389 geantCode=10; // K_L0
1390 break ;
1391 case 321:
1392 geantCode=11; // K+
1393 break ;
1394 case -321:
1395 geantCode=12; // K-
1396 break ;
1397 case 2112:
1398 geantCode=13; // N0
1399 break ;
1400 case 2212:
1401 geantCode=14; // P+
1402 break ;
1403 case -2212:
1404 geantCode=15; // P~-
1405 break ;
1406 case 310:
1407 geantCode=16; // K_S0
1408 break ;
1409 case 221:
1410 geantCode=17; // ETA
1411 break ;
1412 case 3122:
1413 geantCode=18; // LAMBDA0
1414 break ;
1415 case 3222:
1416 geantCode=19; // SIGMA+
1417 break ;
1418 case 3212:
1419 geantCode=20; // SIGMA0
1420 break ;
1421 case 3112:
1422 geantCode=21; // SIGMA-
1423 break ;
1424 case 3322:
1425 geantCode=22; // XI0
1426 break ;
1427 case 3312:
1428 geantCode=23; // XI-
1429 break ;
1430 case 3334:
1431 geantCode=24; // OMEGA-
1432 break ;
1433 case -2112:
1434 geantCode=25; // N~0
1435 break ;
1436 case -3122:
1437 geantCode=26; // LAMBDA~0
1438 break ;
1439 case -3112:
1440 geantCode=27; // SIGMA~+
1441 break ;
1442 case -3212:
1443 geantCode=28; // SIGMA~0
1444 break ;
1445 case -3222:
1446 geantCode=29; // SIGMA~-
1447 break ;
1448 case -3322:
1449 geantCode=30; // XI~0
1450 break ;
1451 case -3312:
1452 geantCode=31; // XI~+
1453 break ;
1454 case -3334:
1455 geantCode=32; // OMEGA~+
1456 break ;
1457 case 223:
1458 geantCode=33; // OMEGA(782)
1459 break ;
1460 case 333:
1461 geantCode=34; // PHI(1020)
1462 break ;
1463 case 411:
1464 geantCode=35; // D+
1465 break ;
1466 case -411:
1467 geantCode=36; // D-
1468 break ;
1469 case 421:
1470 geantCode=37; // D0
1471 break ;
1472 case -421:
1473 geantCode=38; // D~0
1474 break ;
1475 case 431:
1476 geantCode=39; // D_S+
1477 break ;
1478 case -431:
1479 geantCode=40; // D_S~-
1480 break ;
1481 case 4122:
1482 geantCode=41; // LAMBDA_C+
1483 break ;
1484 case 213:
1485 geantCode=42; // RHP(770)+
1486 break ;
1487 case -213:
1488 geantCode=43; // RHO(770)-
1489 break ;
1490 case 113:
1491 geantCode=44; // RHO(770)0
1492 break ;
1493 default:
1494 geantCode=45;
1495 break;
1496 }
1497
1498 return geantCode;
1499}
1500
1501//__________________________________________________________________
1502Bool_t AliTOFReconstructioner::operator==( AliTOFReconstructioner const & tofrec)const
1503{
1504 // Equal operator.
1505 // Reconstructioners are equal if their parameters are equal
1506
1507 // split the member variables in analogous categories
1508
1509 // time resolution and edge effect parameters
1510 Bool_t dummy0=(fTimeResolution==tofrec.fTimeResolution)&&(fpadefficiency==tofrec.fpadefficiency)&&(fEdgeEffect==tofrec.fEdgeEffect)&&(fEdgeTails==tofrec.fEdgeTails)&&(fHparameter==tofrec.fHparameter)&&(fH2parameter==tofrec.fH2parameter)&&(fKparameter==tofrec.fKparameter)&&(fK2parameter==tofrec.fK2parameter);
1511
1512 // pad efficiency parameters
1513 Bool_t dummy1=(fEffCenter==tofrec.fEffCenter)&&(fEffBoundary==tofrec.fEffBoundary)&&(fEff2Boundary==tofrec.fEff2Boundary)&&(fEff3Boundary==tofrec.fEff3Boundary)&&(fResCenter==tofrec.fResCenter)&&(fResBoundary==tofrec.fResBoundary)&&(fResSlope==tofrec.fResSlope);
1514
1515 // time walk parameters
1516 Bool_t dummy2=(fTimeWalkCenter==tofrec.fTimeWalkCenter)&&(fTimeWalkBoundary==tofrec.fTimeWalkBoundary)&&(fTimeWalkSlope==tofrec.fTimeWalkSlope)&&(fTimeDelayFlag==tofrec.fTimeDelayFlag)&&(fPulseHeightSlope==tofrec.fPulseHeightSlope)&&(fTimeDelaySlope==tofrec.fTimeDelaySlope);
1517
1518 // ADC-TDC correlation parameters
1519 Bool_t dummy3=(fMinimumCharge==tofrec.fMinimumCharge)&&(fChargeSmearing==tofrec.fChargeSmearing )&&(fLogChargeSmearing==tofrec.fLogChargeSmearing )&&(fTimeSmearing==tofrec.fTimeSmearing )&&(fAverageTimeFlag==tofrec.fAverageTimeFlag)&&(fChargeFactorForMatching==tofrec.fChargeFactorForMatching)&&(fMatchingStyle==tofrec.fMatchingStyle);
1520
1521 Bool_t dummy4=(fTrackingEfficiency==tofrec.fTrackingEfficiency)&&(fSigmavsp==tofrec.fSigmavsp)&&(fSigmaZ==tofrec.fSigmaZ)&&(fSigmarphi==tofrec.fSigmarphi)&&(fSigmap==tofrec.fSigmap)&&(fSigmaPhi==tofrec.fSigmaPhi)&&(fSigmaTheta==tofrec.fSigmaTheta)&&(fNoise==tofrec.fNoise)&&(fNoiseSlope==tofrec.fNoiseSlope)&&(fField==tofrec.fField)&&(fRadLenTPC==tofrec.fRadLenTPC)&&(fCorrectionTRD==tofrec.fCorrectionTRD)&&(fLastTPCRow==tofrec.fLastTPCRow)&&(fRadiusvtxBound==tofrec.fRadiusvtxBound)&&(fMaxTestTracks==tofrec.fMaxTestTracks)&&(fStep==tofrec.fStep)&&(fMaxPixels==tofrec.fMaxPixels)&&(fMaxAllTracks==tofrec.fMaxAllTracks)&&(fMaxTracks==tofrec.fMaxTracks)&&(fMaxTOFHits==tofrec.fMaxTOFHits)&&(fPBound==tofrec.fPBound);
1522
1523 if( dummy0 && dummy1 && dummy2 && dummy3 && dummy4)
1524 return kTRUE ;
1525 else
1526 return kFALSE ;
1527
1528}
1529//____________________________________________________________________________
1530void AliTOFReconstructioner::UseHitsFrom(const char * filename)
1531{
1532 SetTitle(filename) ;
1533}
1534
1535//____________________________________________________________________________
1536void AliTOFReconstructioner::InitArray(Float_t array[], Int_t nlocations)
1537{
1538 //
1539 // Initialize the array of Float_t
1540 //
1541 for (Int_t i = 0; i < nlocations; i++) {
1542 array[i]=0.;
1543 } // end loop
1544
1545}
1546
1547//____________________________________________________________________________
1548void AliTOFReconstructioner::InitArray(Int_t array[], Int_t nlocations)
1549{
1550 //
1551 // Initialize the array of Int_t
1552 //
1553 for (Int_t i = 0; i < nlocations; i++) {
1554 array[i]=0;
1555 } // end loop
1556
1557}
1558
1559
1560//____________________________________________________________________________
1561void AliTOFReconstructioner::ReadTOFHits(Int_t ntracks, TTree* treehits, TClonesArray* tofhits, Int_t ***MapPixels, Int_t* kTOFhitFirst, AliTOFPad* pixelArray , Int_t* iTOFpixel, Float_t* toftime, AliTOFRecHit* hitArray, Int_t& isHitOnFiredPad, Int_t& ipixel)
1562{
1563 //
1564 // Read TOF hits for the current event and fill arrays
1565 //
1566 // Start loop on primary tracks in the hits containers
1567 //
1568 // Noise meaning in ReadTOFHits: we use the word 'noise' in the
1569 // following cases
1570 // - signals produced by secondary particles
1571 // - signals produced by the next hits (out of the first) of a given track
1572 // (both primary and secondary)
1573 // - signals produced by edge effect
1574
1575
1576 TParticle *particle;
1577 Int_t nHitOutofTofVolumes; // number of hits out of TOF GEANT volumes (it happens in very
1578 // few cases)
f9a28264 1579 Int_t * npixel = new Int_t[AliTOFConstants::fgkmaxtoftree]; // array used by TOFRecon for check on TOF geometry
db9ba97f 1580 Int_t npions=0; // number of pions for the current event
1581 Int_t nkaons=0; // number of kaons for the current event
1582 Int_t nprotons=0; // number of protons for the current event
1583 Int_t nelectrons=0;// number of electrons for the current event
1584 Int_t nmuons=0; // number of muons for the current event
1585 Float_t tofpos[3]; // TOF hit position and GEANT time
1586 Float_t zPad,xPad;
1587 Int_t nbytes = 0;
1588 Int_t ipart, nhits=0, nHitsFromPrimaries=0;
1589 Int_t ntotalTOFhits=0; // total number of TOF hits for the current event
1590 Int_t ipartLast=-1; // last track identifier
1591 Int_t iFirstHit; // flag to check if the current hit is the first hit on TOF for the
1592 // current track
1593 Int_t iNoiseHit=0; // flag used to tag noise hits (the noise meaning is reported in the
1594 // header of the ReadTOFHits method)
1595 Int_t nhitWithoutNoise;// number of hits not due to noise
1596 Int_t inoise=0,inoise2=0;
1597 Int_t nMultipleSignOnSamePad=0; // number of cases where a pad is fired more than one time
1598 Int_t nPixEdge=0; // additional pads fired due to edge effect in ReadTOFHits (local var)
1599 // array used for counting different types of primary particles
1600 Int_t particleTypeGEANT[50]={0,4,4,0,5,5,0,3,3,0,
1601 2,2,0,1,1,0,0,0,0,0,
1602 0,0,0,0,0,0,0,0,0,0,
1603 0,0,0,0,0,0,0,0,0,0,
1604 0,0,0,0,0,0,0,0,0,0};
1605 Int_t particleType,particleInTOFtype[6][3];
1606 for (Int_t i=0;i<6;i++) {
1607 for (Int_t j=0;j<3;j++) {
1608 particleInTOFtype[i][j]=0;
1609 }
1610 }
1611
5fff655e 1612 // speed-up the code
1613 treehits->SetBranchStatus("*",0); // switch off all branches
1614 treehits->SetBranchStatus("TOF*",1); // switch on only TOF
db9ba97f 1615
1616 for (Int_t track=0; track<ntracks;track++) { // starting loop on primary tracks for the current event
1617
1618 gAlice->ResetHits();
1619 nbytes += treehits->GetEvent(track);
1620 nhits = tofhits->GetEntriesFast();
1621
1622 ntotalTOFhits+=nhits;
1623
1624 // Start loop on hits connected to the current primary tracked particle
1625 // (including hits produced by secondary particles generaterd by the
1626 // current ptimary tracked particle)
1627 for (Int_t hit=0;hit<nhits;hit++) {
1628 AliTOFhit* tofHit = (AliTOFhit*)tofhits->UncheckedAt(hit);
1629 ipart = tofHit->GetTrack();
1630 if(ipart>=fMaxAllTracks) break;
1631 Float_t geantTime= tofHit->GetTof(); // it is given in [s]
1632 particle = (TParticle*)gAlice->Particle(ipart);
1633
1634 Int_t pdgCode=particle->GetPdgCode();
1635 // Only high momentum tracks (see fPBound value)
1636 // momentum components at vertex
1637 Float_t pxvtx = particle->Px();
1638 Float_t pyvtx = particle->Py();
1639 Float_t pzvtx = particle->Pz();
1640 Float_t pvtx = TMath::Sqrt(pxvtx*pxvtx+pyvtx*pyvtx+pzvtx*pzvtx);
1641 if(pvtx>fPBound) {
1642
1643 if(particle->GetFirstMother() < 0) nHitsFromPrimaries++; // count primaries
1644
1645 // x and y coordinates of the particle production vertex
1646 Float_t vx = particle->Vx();
1647 Float_t vy = particle->Vy();
1648 Float_t vr = TMath::Sqrt(vx*vx+vy*vy); // cylindrical radius of the particle production vertex
1649
1650 Float_t x = tofHit->X(); tofpos[0]=x;
1651 Float_t y = tofHit->Y(); tofpos[1]=y;
1652 Float_t z = tofHit->Z(); tofpos[2]=z;
b213b8bd 1653 /* var used for QA
db9ba97f 1654 Float_t tofradius = TMath::Sqrt(x*x+y*y); // radius cilindrical coordinate of the TOF hit
b213b8bd 1655 */
db9ba97f 1656 // momentum components (cosine) when striking the TOF
1657 Float_t pxtof = tofHit->GetPx();
1658 Float_t pytof = tofHit->GetPy();
1659 Float_t pztof = tofHit->GetPz();
1660 // scalar product indicating the direction of the particle when striking the TOF
b213b8bd 1661 /* var used for QA
db9ba97f 1662 // (>0 for outgoing particles)
1663 Float_t isGoingOut = (x*pxtof+y*pytof+z*pztof)/TMath::Sqrt(x*x+y*y+z*z);
b213b8bd 1664 */
db9ba97f 1665 Float_t momtof = tofHit->GetMom();
1666 // now momentum components when striking the TOF
1667 pxtof *= momtof;
1668 pytof *= momtof;
1669 pztof *= momtof;
1670 particleType=particleTypeGEANT[PDGtoGeantCode(pdgCode)-1];
1671 if(particleType) {
1672 particleInTOFtype[5][2]++;
1673 particleInTOFtype[particleType-1][2]++;
1674 }
1675 iFirstHit=0;
1676 // without noise hits
1677
1678 if(ipart!=ipartLast) {
1679 iFirstHit=1;
1680 toftime[ipart]=geantTime; //time [s]
1681 // tofMom[ipart]=momtof;
1682 ipartLast=ipart;
1683 if(particle->GetFirstMother() < 0) {
1684 Int_t abspdgCode=TMath::Abs(pdgCode);
1685 switch (abspdgCode) {
1686 case 211:
1687 npions++;
1688 break ;
1689 case 321:
1690 nkaons++;
1691 break ;
1692 case 2212:
1693 nprotons++;
1694 break ;
1695 case 11:
1696 nelectrons++;
1697 break ;
1698 case 13:
1699 nmuons++;
1700 break ;
1701 }
1702 }
1703 if(vr>fRadiusvtxBound) {
1704 if(particleType) {
1705 particleInTOFtype[5][1]++;
1706 particleInTOFtype[particleType-1][1]++;
1707 }
1708 inoise++;
1709 inoise2++;
1710 } else {
1711 if(particleType) {
1712 particleInTOFtype[5][0]++;
1713 particleInTOFtype[particleType-1][0]++;
1714 }
1715 }
1716 } else {
1717 inoise++;
1718 if(particleType) {
1719 particleInTOFtype[5][1]++;
1720 particleInTOFtype[particleType-1][1]++;
1721 }
1722 } //end if(ipart!=ipartLast)
1723
1724 IsInsideThePad(fg3,x,y,z,npixel,zPad,xPad);
1725
1726 Int_t sec = tofHit->GetSector();
1727 Int_t pla = tofHit->GetPlate();
1728 Int_t str = tofHit->GetStrip();
1729 if(sec!=npixel[0] || pla!=npixel[1] || str!=npixel[2]){// check on volume
1730 cout << "sector" << sec << " npixel[0] " << npixel[0] << endl;
1731 cout << "plate " << pla << " npixel[1] " << npixel[1] << endl;
1732 cout << "strip " << str << " npixel[2] " << npixel[2] << endl;
1733 } // close check on volume
1734
1735 Int_t padz = tofHit->GetPadz();
1736 Int_t padx = tofHit->GetPadx();
1737 Float_t Zpad = tofHit->GetDz();
1738 Float_t Xpad = tofHit->GetDx();
1739
1740
1741 if (npixel[4]==0){
1742 IsInsideThePad(fg3,x,y,z,npixel,zPad,xPad);
1743 if (npixel[4]==0){
1744 nHitOutofTofVolumes++;
1745 }
1746 } else {
1747 Float_t zStrip=AliTOFConstants::fgkZPad*(padz-0.5-0.5*AliTOFConstants::fgkNpadZ)+Zpad;
1748 if(padz!=npixel[3]) printf(" : Zpad=%f, padz=%i, npixel[3]=%i, zStrip=%f\n",Zpad,padz,npixel[3],zStrip);
1749 Float_t xStrip=AliTOFConstants::fgkXPad*(padx-0.5-0.5*AliTOFConstants::fgkNpadX)+Xpad;
1750
1751 Int_t nPlace[4]={0,0,0,0};
1752 nPlace[0]=(padz-1)*AliTOFConstants::fgkNpadX+padx;
1753
1754 Int_t nActivatedPads=0;
1755 Int_t nFiredPads=0;
1756 Bool_t isFired[4]={kFALSE,kFALSE,kFALSE,kFALSE};
1757 Float_t tofAfterSimul[4]={0.,0.,0.,0.};
1758 Float_t qInduced[4]={0.,0.,0.,0.};
1759 Float_t averageTime=0.;
1760
1761
1762 BorderEffect(zStrip,xStrip,geantTime*1.0e+09,nActivatedPads,nFiredPads,isFired,nPlace,qInduced,tofAfterSimul,averageTime); // simulate edge effect
1763
1764
1765 if(nFiredPads) {
1766 for(Int_t indexOfPad=0; indexOfPad<nActivatedPads; indexOfPad++) {
1767 if(isFired[indexOfPad]){// the pad has fired
1768 if(indexOfPad==0) {// the hit belongs to a fired pad
1769 isHitOnFiredPad++;
1770 hitArray[isHitOnFiredPad-1].SetHit(ipart,pdgCode,tofpos,momtof,vr,iFirstHit);
1771 iNoiseHit=0;
1772
1773 if(vr>fRadiusvtxBound || iFirstHit==0) iNoiseHit=1;
1774
1775 hitArray[isHitOnFiredPad-1].SetNoise(iNoiseHit);
1776 if(iFirstHit) kTOFhitFirst[ipart]=isHitOnFiredPad;
1777
1778 }// close - the hit belongs to a fired pad
1779
1780 Int_t iMapFirstIndex=AliTOFConstants::fgkNSectors*(npixel[1]-1)+npixel[0]-1;
1781 Int_t iMapValue=MapPixels[iMapFirstIndex][npixel[2]-1][nPlace[indexOfPad]-1];
1782
1783 if(iMapValue==0) {
1784 ipixel++;
1785 if(indexOfPad) {
1786 iNoiseHit=1;
1787 nPixEdge++;
1788 } else {
1789 iTOFpixel[ipart]=ipixel;
1790 }
1791
1792 if(ipixel>fMaxPixels){ // check on the total number of activated pads
1793 cout << "ipixel=" << ipixel << " > fMaxPixels=" << fMaxPixels << endl;
1794 return;
1795 } // close check on the number of activated pads
1796
1797 MapPixels[iMapFirstIndex][npixel[2]-1][nPlace[indexOfPad]-1]=ipixel;
1798 pixelArray[ipixel-1].SetGeom(npixel[0],npixel[1],npixel[2],nPlace[indexOfPad]);
1799 pixelArray[ipixel-1].SetTrack(ipart);
1800 if(iNoiseHit) {
1801 pixelArray[ipixel-1].AddState(1);
1802 } else {
1803 if(tofAfterSimul[indexOfPad]<0) cout << "Time of Flight after detector simulation is negative" << endl;
1804 pixelArray[ipixel-1].AddState(10);
1805 }
1806
1807 pixelArray[ipixel-1].SetTofChargeHit(tofAfterSimul[indexOfPad],qInduced[indexOfPad],geantTime*1.0e+09,isHitOnFiredPad);
1808 } else { //else if(iMapValue==0)
1809 if(indexOfPad==0) iTOFpixel[ipart]=iMapValue;
1810 nMultipleSignOnSamePad++;
1811
1812 if(tofAfterSimul[indexOfPad] < pixelArray[iMapValue-1].GetRealTime() ) {
1813 pixelArray[iMapValue-1].SetTrack(ipart);
1814 // if(indexOfPad==0) pixelArray[iMapValue-1].SetTrack(ipart);
1815 if(indexOfPad) iNoiseHit=1;
1816 if(iNoiseHit) {
1817 pixelArray[iMapValue-1].AddState(1);
1818 } else {
1819 pixelArray[iMapValue-1].AddState(10);
1820 }
1821 pixelArray[iMapValue-1].SetRealTime(tofAfterSimul[indexOfPad]);
1822 pixelArray[iMapValue-1].SetGeantTime(geantTime*1.0e+09);
1823 pixelArray[iMapValue-1].SetHit(isHitOnFiredPad);
1824 } // close if(tofAfterSimul[indexOfPad] < pixelArray[iMapValue-1].GetTime() )
1825 } //end of Pixel filling
1826 } // close if(isFired[indexOfPad])
1827 } //end loop on activated pads indexOfPad
1828 } // close if(nFiredPads)
1829 } //end of hit with npixel[3]!=0
1830 } //high momentum tracks
1831 } //end on TOF hits
1832 } //end on primary tracks
1833
1834
1835 if(fdbg) {
1836 cout << ntotalTOFhits << " - total number of TOF hits " << nHitsFromPrimaries << " - primary " << endl;
1837 cout << inoise << " - noise hits, " << inoise2<< " - first crossing of a track with Rvtx>" << fRadiusvtxBound << endl;
1838 // cout << inoise << " - noise hits (" << 100.*inoise/ihit << " %), " << inoise2
1839 //<< " - first crossing of a track with Rvtx>" << RVTXBOUND << endl;
1840 nhitWithoutNoise=isHitOnFiredPad;
1841
1842 cout << ipixel << " fired pixels (" << nMultipleSignOnSamePad << " multiple fired pads, " << endl;
1843 //j << " fired by noise, " << j1 << " noise+track)" << endl;
1844 printf(" %i additional pads are fired due to edge effect\n",nPixEdge);
1845 cout << npions << " primary pions reached TOF" << endl;
1846 cout << nkaons << " primary kaons reached TOF" << endl;
1847 cout << nprotons << " primary protons reached TOF" << endl;
1848 cout << nelectrons<<" primary electrons reached TOF" << endl;
1849 cout << nmuons << " primary muons reached TOF" << endl;
1850 cout << "number of TOF hits for different species: 1-p, 2-K, 3-pi, 4-e, 5-mu, 6-all" << endl;
1851 cout << " first number - track hits, second - noise ones, third - all" << endl;
1852 for (Int_t i=0;i<6;i++) cout << i+1 << " " << particleInTOFtype[i][0] << " " << particleInTOFtype[i][1] << " " << particleInTOFtype[i][2] << endl;
1853
1854 Int_t primaryReachedTOF[6];
1855 primaryReachedTOF[0]=npions;
1856 primaryReachedTOF[1]=nkaons;
1857 primaryReachedTOF[2]=nprotons;
1858 primaryReachedTOF[3]=nelectrons;
1859 primaryReachedTOF[4]=nmuons;
1860 primaryReachedTOF[5]=npions+nkaons+nprotons+nelectrons+nmuons;
1861
1862 cout << " Reading TOF hits done" << endl;
1863 }
1864
f9a28264 1865 delete [] npixel;
db9ba97f 1866}
1867
1868//____________________________________________________________________________
1869void AliTOFReconstructioner::AddNoiseFromOuter(Option_t *option, Int_t ***MapPixels, AliTOFPad* pixelArray , AliTOFRecHit* hitArray, Int_t& isHitOnFiredPad, Int_t& ipixel)
1870{
1871 //
1872 // Add noise hits from outer regions (forward and backward) according
1873 // to parameterized fZNoise distribution (to be used with events
1874 // generated in the barrel region)
1875
f9a28264 1876 Float_t * zLen = new Float_t[AliTOFConstants::fgkNPlates+1];
1877 Float_t * zStrips = new Float_t[AliTOFConstants::fgkNPlates];
db9ba97f 1878 zStrips[0]=(Float_t) (AliTOFConstants::fgkNStripC);
1879 zStrips[1]=(Float_t) (AliTOFConstants::fgkNStripB);
1880 zStrips[2]=(Float_t) (AliTOFConstants::fgkNStripA);
1881 zStrips[3]=(Float_t) (AliTOFConstants::fgkNStripB);
1882 zStrips[4]=(Float_t) (AliTOFConstants::fgkNStripC);
1883
1884 zLen[5]=AliTOFConstants::fgkzlenA*0.5+AliTOFConstants::fgkzlenB+AliTOFConstants::fgkzlenC;
1885 zLen[4]=zLen[5]-AliTOFConstants::fgkzlenC;
1886 zLen[3]=zLen[4]-AliTOFConstants::fgkzlenB;
1887 zLen[2]=zLen[3]-AliTOFConstants::fgkzlenA;
1888 zLen[1]=zLen[2]-AliTOFConstants::fgkzlenB;
1889 zLen[0]=zLen[1]-AliTOFConstants::fgkzlenC;
1890
1891
1892 Int_t isector; // random sector number
1893 Int_t iplate; // random plate number
1894 Int_t istrip; // random strip number in the plate
1895 Int_t ipadAlongX; // random pad number along x direction
1896 Int_t ipadAlongZ; // random pad number along z direction
1897 Int_t ipad;
1898 Int_t nPixEdge=0; // additional pads fired due to edge effect when adding noise from outer
1899 // regions
1900
1901 // x -> time of flight given in ns
1902 TF1 *noiseTof = new TF1("noiseTof","exp(-x/20)",0,100);
1903
1904 if(strstr(option,"pp")){
1905 fZnoise = new TF1("fZnoise","257.8-0.178*x-0.000457*x*x",-AliTOFConstants::fgkMaxhZtof,AliTOFConstants::fgkMaxhZtof);
1906 }
1907 if(strstr(option,"Pb-Pb")){
1908 fZnoise = new TF1("fZnoise","182.2-0.09179*x-0.0001931*x*x",-AliTOFConstants::fgkMaxhZtof,AliTOFConstants::fgkMaxhZtof);
1909 }
1910
1911 if(fNoise) {
1912 if(fdbg) cout << " Start adding additional noise hits from outer regions" << endl;
1913
1914 for(Int_t i=0;i<fNoise;i++) {
1915
1916 isector=(Int_t) (AliTOFConstants::fgkNSectors*gRandom->Rndm())+1; //the sector number
1917 // non-flat z-distribution of additional hits
1918 Float_t zNoise=fZnoise->GetRandom();
1919
1920 // holes for PHOS and HMPID
1921 if(((AliTOF *) gAlice->GetDetector("TOF"))->IsVersion()==2) {
1922 // to be checked the holes case
1923 if(isector>12 && isector<16) { // sectors 13,14,15 - RICH
1924 do {
1925 iplate=(Int_t) (AliTOFConstants::fgkNPlates*gRandom->Rndm())+1;
1926 } while (iplate==2 || iplate==3 || iplate==4);
1927 // } else if(isector>11 && isector<17) { // sectors 12,13,14,15,16 - PHOS
1928 } else if(isector>2 && isector<8) { // sectors 3,4,5,6,7 - PHOS
1929 do {
1930 iplate=(Int_t) (AliTOFConstants::fgkNPlates*gRandom->Rndm())+1;
1931 } while (iplate==3);
1932 } else {
1933 iplate=(Int_t) (AliTOFConstants::fgkNPlates*gRandom->Rndm())+1;
1934 }
1935 } else {
1936 iplate=0;
1937 do {
1938 iplate++;
1939 } while(zNoise>zLen[iplate]);
1940 }
1941 // end of holes
1942
1943 if(iplate<1 || iplate>5) {
1944 printf(" iplate<1 or iplate>5, iplate=%i\n",iplate);
1945 return;
1946 }
1947
1948 Float_t nStripes=0;
1949 if(iplate>1) {
1950 for (Int_t i=0;i<iplate-1;i++) {
1951 nStripes += zStrips[i];
1952 }
1953 }
1954
b213b8bd 1955 istrip=(Int_t)((zNoise-zLen[iplate-1])/((zLen[iplate]-zLen[iplate-1])/zStrips[iplate-1])); //the strip number in the plate
db9ba97f 1956 istrip++;
1957
1958 ipadAlongX = (Int_t)(AliTOFConstants::fgkNpadX*gRandom->Rndm())+1;
1959 ipadAlongZ = (Int_t)(AliTOFConstants::fgkNpadZ*gRandom->Rndm())+1;
1960 ipad=(Int_t)(ipadAlongZ-1)*AliTOFConstants::fgkNpadX+ipadAlongX; //the pad number
1961
1962 Float_t xStrip=(ipadAlongX-1)*AliTOFConstants::fgkXPad+AliTOFConstants::fgkXPad*gRandom->Rndm()-0.5*AliTOFConstants::fgkNpadX*AliTOFConstants::fgkXPad;//x-coor.in the strip frame
1963 Float_t zStrip=(ipadAlongZ-1)*AliTOFConstants::fgkZPad+AliTOFConstants::fgkZPad*gRandom->Rndm()-0.5*AliTOFConstants::fgkNpadZ*AliTOFConstants::fgkZPad;//z-coor.in the strip frame
1964
1965 Int_t nPlace[4]={0,0,0,0};
1966 nPlace[0]=ipad;
1967
1968 Int_t nActivatedPads=0;
1969 Int_t nFiredPads=0;
1970 Bool_t isFired[4]={kFALSE,kFALSE,kFALSE,kFALSE};
1971 Float_t tofAfterSimul[4]={0.,0.,0.,0.};
1972 Float_t qInduced[4]={0.,0.,0.,0.};
1973 Float_t averageTime=0.;
1974 Float_t toffornoise=10.+noiseTof->GetRandom(); // 10 ns offset + parameterization [ns]
1975
1976 BorderEffect(zStrip,xStrip,toffornoise,nActivatedPads,nFiredPads,isFired,nPlace,qInduced,tofAfterSimul,averageTime); // simulate edge effect
1977
1978 if(nFiredPads) {
1979 for(Int_t indexOfPad=0; indexOfPad<nActivatedPads; indexOfPad++) {
1980 if(isFired[indexOfPad]){// the pad has fired
1981
1982 if(indexOfPad==0) {// the hit belongs to a fired pad
1983 isHitOnFiredPad++;
1984 hitArray[isHitOnFiredPad-1].SetX(0.);
1985 hitArray[isHitOnFiredPad-1].SetY(0.);
1986 hitArray[isHitOnFiredPad-1].SetZ(zNoise);
1987 hitArray[isHitOnFiredPad-1].SetNoise(1);
1988 } // close if(indexOfPad==0)
1989
1990 ipad = nPlace[indexOfPad];
1991
1992 Int_t iMapValue=MapPixels[AliTOFConstants::fgkNSectors*(iplate-1)+isector-1][istrip-1][ipad-1];
1993
1994 if(iMapValue==0) {
1995 ipixel++;
1996 if(indexOfPad) nPixEdge++;
1997 MapPixels[AliTOFConstants::fgkNSectors*(iplate-1)+isector-1][istrip-1][ipad-1]=ipixel;
1998 pixelArray[ipixel-1].SetGeom(isector,iplate,istrip,ipad);
1999 pixelArray[ipixel-1].AddState(1);
2000 pixelArray[ipixel-1].SetRealTime(tofAfterSimul[indexOfPad]);
2001 pixelArray[ipixel-1].SetHit(isHitOnFiredPad);
2002 } else if( tofAfterSimul[indexOfPad] < pixelArray[iMapValue-1].GetRealTime() ) {
2003 pixelArray[iMapValue-1].SetTrack(-1);
2004 pixelArray[iMapValue-1].AddState(1);
2005 pixelArray[iMapValue-1].SetRealTime(tofAfterSimul[indexOfPad]);
2006 pixelArray[iMapValue-1].SetHit(isHitOnFiredPad);
2007 } //end of if(iMapValue==0)
2008
2009 }// close if(isFired[indexOfPad])
2010 } //end loop on activated pads indexOfPad
2011 } // close if(nFiredPads)
2012 } //end of NOISE cycle
2013 }
2014
2015 // free used memory
2016 if (fZnoise)
2017 {
2018 delete fZnoise;
2019 fZnoise = 0;
2020 }
2021
2022 if (noiseTof)
2023 {
2024 delete noiseTof;
2025 noiseTof = 0;
2026 }
2027
2028 Int_t nNoiseSignals=0;
2029 Int_t nAll=0;
2030 for(Int_t idummy=1; idummy<ipixel+1; idummy++) {
2031 if(hitArray[pixelArray[idummy-1].GetHit()-1].GetNoise()==1) {
2032 nNoiseSignals++;
2033 if(pixelArray[idummy-1].GetState()>10) nAll++;
2034 }
2035 }
2036
2037 if(fdbg) {
2038 cout << " after adding " << fNoise << " noise hits: " << ipixel << " fired pixels (" << nNoiseSignals << " fired by noise, " << nAll << " noise+track)" << endl;
2039 printf(" %i additional pixels are fired by noise due to edge effect\n",nPixEdge);
2040 cout << " End of adding additional noise hits from outer regions" << endl;
2041 }
2042
2043 Float_t occupancy;
2044 // numberOfPads for AliTOFV4 (Full coverage)
2045 // - to be upgraded checking the used TOF version -
2046 Float_t numberOfPads=AliTOFConstants::fgkPadXSector*AliTOFConstants::fgkNSectors;
2047 occupancy=100.*ipixel/numberOfPads; // percentage of fired pads
2048 printf(" Overall TOF occupancy (percentage of fired pads after adding noise) = %f\n",occupancy);
f9a28264 2049 delete [] zLen;
2050 delete [] zStrips;
db9ba97f 2051
2052}
2053
2054
2055//____________________________________________________________________________
2056void AliTOFReconstructioner::SetMinDistance(AliTOFRecHit* hitArray, Int_t ilastEntry)
2057{
2058 //
2059 // Set the distance to the nearest hit for hitArray
2060 // ilastEntry is the index of the last entry of hitArray
2061
2062 // starting the setting for the distance to the nearest TOFhit (cm)
2063 for(Int_t i=0; i<ilastEntry; i++) {
2064
2065 if(hitArray[i].GetFirst()==1 && hitArray[i].GetNoise()==0) { // select the first hit of the track
2066 // hits are not due to noise
2067 Float_t minDistance=10000.,squareDistance; // current values of the (square) distance
2068 Int_t jAtMin=0; // index of the hit nearest to the i-th hit
2069 Float_t xhit=hitArray[i].X(); // x coordinate for i-th hit
2070 Float_t yhit=hitArray[i].Y(); // y coordinate for i-th hit
2071 Float_t zhit=hitArray[i].Z(); // z coordinate for i-th hit
2072 // was for(Int_t j=0; j<isHitOnFiredPad; j++) {
2073 for(Int_t j=0; j<ilastEntry; j++) {
2074 if(i!=j) {
2075 squareDistance=(hitArray[j].X()-xhit)*(hitArray[j].X()-xhit)+
2076 (hitArray[j].Y()-yhit)*(hitArray[j].Y()-yhit)+
2077 (hitArray[j].Z()-zhit)*(hitArray[j].Z()-zhit);
2078 if(squareDistance<minDistance) {
2079 minDistance=squareDistance;
2080 jAtMin=j;
2081 }
2082 }
2083 }
2084 minDistance=TMath::Sqrt(minDistance);
2085 hitArray[i].SetRmin(minDistance);
2086 if(minDistance==0.) printf(" Rmin=0, i=%i, j=%i, x=%f,y=%f,z=%f\n",i,jAtMin,xhit,yhit,zhit);// it cannot happen
2087 }
2088 }
2089
2090}
2091
2092// these lines has to be commented till TPC will provide fPx fPy fPz
2093// and fL in AliTPChit class
2094//____________________________________________________________________________
2095/*
2096void AliTOFReconstructioner::ReadTPCHits(Int_t ntracks, TTree* treehits, TClonesArray* tpchits, Int_t* iTrackPt, Int_t* iparticle, Float_t* ptTrack, AliTOFTrack* trackArray, Int_t& itrack)
2097{
2098 //
2099 // Read TPC hits for the current event
2100 //
2101 TParticle *particle=0;
2102 Int_t npions=0; // number of pions for the current event
2103 Int_t nkaons=0; // number of kaons for the current event
2104 Int_t nprotons=0; // number of protons for the current event
2105 Int_t nelectrons=0;// number of electrons for the current event
2106 Int_t nmuons=0; // number of muons for the current event
2107 Int_t ntotalTPChits=0; // total number of TPC hits for the current event
2108 Int_t idummy=-1; // dummy var used to count double hit TPC cases
2109 Int_t nTpcDoubleHitsLastRow=0; // number of double TPC hits in the last pad row
2110 Int_t nTpcHitsLastRow=0; // number of TPC hits in the last pad row
2111 Float_t trdpos[2]={0.,0.};
2112 Float_t pos[3]; // TPC hit position
2113 Float_t mom[3]; // momentum components in the last TPC row
2114 Float_t pt=0., tpclen; // pt: transverse momentum in the last TPC row
2115 Int_t nbytes = 0;
2116 Int_t ipart=0, nhits=0, iprim=0;
2117
2118 itrack=0; // itrack: total number of selected TPC tracks
2119
5fff655e 2120 // speed-up the code
2121 treehits->SetBranchStatus("*",0); // switch off all branches
2122 treehits->SetBranchStatus("TPC*",1); // switch on only TPC
2123
db9ba97f 2124 for (Int_t track=0; track<ntracks;track++) {
2125 gAlice->ResetHits();
2126 nbytes += treehits->GetEvent(track);
2127
2128
2129 nhits = tpchits->GetEntriesFast();
2130
2131 for (Int_t hit=0;hit<nhits;hit++) {
2132 ntotalTPChits++;
2133 AliTPChit* tpcHit = (AliTPChit*)tpchits->UncheckedAt(hit);
2134 Int_t row = tpcHit->fPadRow;
2135 ipart = tpcHit->GetTrack();
2136 if(ipart>=fMaxAllTracks) break;
2137 particle = (TParticle*)gAlice->Particle(ipart);
2138 Int_t pdgCode=particle->GetPdgCode();
2139 // only high momentum tracks
2140 // momentum components at production vertex
2141 Float_t pxvtx = particle->Px();
2142 Float_t pyvtx = particle->Py();
2143 Float_t pzvtx = particle->Pz();
2144 Float_t pvtx = TMath::Sqrt(pxvtx*pxvtx+pyvtx*pyvtx+pzvtx*pzvtx);
2145 if(pvtx>fPBound && row == fLastTPCRow) {
2146 Float_t vx = particle->Vx();
2147 Float_t vy = particle->Vy();
2148 Float_t vr = TMath::Sqrt(vx*vx+vy*vy);
2149 Float_t x = tpcHit->X();
2150 Float_t y = tpcHit->Y();
2151 Float_t z = tpcHit->Z();
2152 pos[0]=x; pos[1]=y; pos[2]=z;
2153
2154 Float_t pxtpc = tpcHit->fPx;
2155 Float_t pytpc = tpcHit->fPy;
2156 Float_t pztpc = tpcHit->fPz;
2157 mom[0]=pxtpc; mom[1]=pytpc; mom[2]=pztpc;
2158 Float_t momtpc = TMath::Sqrt(pxtpc*pxtpc+pytpc*pytpc+pztpc*pztpc);
2159
2160 if(x*pxtpc+y*pytpc>0) { // only tracks going out of TPC
2161
2162 Float_t isoutgoing = x*pxtpc+y*pytpc+z*pztpc;
2163 isoutgoing /= (momtpc*TMath::Sqrt(x*x+y*y+z*z));
2164 tpclen = tpcHit->fL;
2165
2166
2167 if(ipart!=idummy) {
2168 if(particle->GetFirstMother() < 0) {
2169 Int_t abspdgCode=TMath::Abs(pdgCode);
2170 switch (abspdgCode) {
2171 case 211:
2172 npions++;
2173 break ;
2174 case 321:
2175 nkaons++;
2176 break ;
2177 case 2212:
2178 nprotons++;
2179 break ;
2180 case 11:
2181 nelectrons++;
2182 break ;
2183 case 13:
2184 nmuons++;
2185 break ;
2186 }
2187 } // close if(particle->GetFirstMother() < 0)
2188 } // close if(ipart!=idummy)
2189
2190 if(gRandom->Rndm()<fTrackingEfficiency && vr<fRadiusvtxBound && ipart!=idummy) {
2191
2192 itrack++;
2193 if(particle->GetFirstMother() < 0) iprim++;
2194
2195 if(itrack>fMaxTracks) {
2196 cout << "itrack=" << itrack << " > MAXTRACKS=" << fMaxTracks << endl;
2197 return;
2198 } // close if(itrack>fMaxTracks)
2199
2200
2201 iparticle[ipart]=itrack;
2202
2203 trackArray[itrack-1].SetTrack(ipart,pvtx,pdgCode,tpclen,pos,mom,trdpos);
2204
2205 pt=TMath::Sqrt(pxtpc*pxtpc+pytpc*pytpc); // pt: transverse momentum at TPC
2206 // Filling iTrackPt[MAXTRACKS] by itrack ordering on Pt
2207 if(itrack==1) {
2208 iTrackPt[itrack-1]=itrack;
2209 ptTrack[itrack-1]=pt;
2210 } else {
2211 for (Int_t i=0; i<itrack-1; i++) {
2212 if(pt>ptTrack[i]) {
2213 for(Int_t j=i; j<itrack-1; j++) {
2214 Int_t k=itrack-1+i-j;
2215 iTrackPt[k]= iTrackPt[k-1];
2216 ptTrack[k] = ptTrack[k-1];
2217 }
2218 iTrackPt[i]=itrack;
2219 ptTrack[i]=pt;
2220 break;
2221 }
2222 if(i==itrack-2) {
2223 iTrackPt[itrack-1]=itrack;
2224 ptTrack[itrack-1]=pt;
2225 }
2226 }
2227 }
2228
2229 } //end of itrack
2230 if(vr>fRadiusvtxBound) nTpcHitsLastRow++;
2231 if(ipart==idummy) nTpcDoubleHitsLastRow++;
2232 idummy=ipart;
2233 } // close if(x*px+y*py>0)
2234 } // close if(pvtx>fPBound && row == fLastTPCRow)
2235 } //end of hits
2236 } // close loop on tracks
2237
2238
2239 if(fdbg) {
2240 cout << ntotalTPChits << " TPC hits in the last TPC row " << fLastTPCRow << endl;
2241 cout << " " << nTpcHitsLastRow << " - hits with Rvtx>fRadiusvtxBound=" << fRadiusvtxBound << endl;
2242 cout << " " << nTpcDoubleHitsLastRow << " double TPC hits" << endl;
2243 cout << itrack << " - extracted TPC tracks " << iprim << " - primary" << endl;
2244 cout << npions << " primary pions reached TPC" << endl;
2245 cout << nkaons << " primary kaons reached TPC" << endl;
2246 cout << nprotons << " primary protons reached TPC" << endl;
2247 cout << nelectrons<< " primary electrons reached TPC" << endl;
2248 cout << nmuons << " primary muons reached TPC" << endl;
2249 } // if(fdbg)
2250
2251 Int_t primaryInTPC[6]={0,0,0,0,0,0};
2252 primaryInTPC[0]=npions;
2253 primaryInTPC[1]=nkaons;
2254 primaryInTPC[2]=nprotons;
2255 primaryInTPC[3]=nelectrons;
2256 primaryInTPC[4]=nmuons;
2257 primaryInTPC[5]=npions+nkaons+nprotons+nelectrons+nmuons;
2258
2259 if(fdbg) {
2260 printf(" contents of iTrackPt[MAXTRACKS],PtTrack[MAXTRACKS]\n");
2261 for (Int_t i=0; i<itrack; i++) {
2262 printf(" %i : iTrackPt=%i, PtTrack=%f\n",i+1,iTrackPt[i],ptTrack[i]);
2263 }
2264 printf(" Check ordered transverse momentum array\n");
2265 for (Int_t i=itrack-1; i>=0; i--) {
2266 printf(" %i : iTrackPt=%i, PtTrack=%f\n",i+1,iTrackPt[i],ptTrack[i]);
2267 }
2268 }// if(fdbg)
2269
2270}
2271*/
2272//____________________________________________________________________________
2273void cylcor(Float_t& x, Float_t& y) {
2274 Float_t rho,phi;
2275
2276 rho=TMath::Sqrt(x*x+y*y);
2277 phi=0.;
2278 if(TMath::Abs(x)>0. || TMath::Abs(y)>0.) phi=TMath::ATan2(y,x);
2279 if(phi<0.) phi=phi+2.*TMath::Pi();
2280 x=rho;
2281 y=phi;
2282
2283}
2284
2285//____________________________________________________________________________
2286void AliTOFReconstructioner::Matching(AliTOFTrack* trackArray, AliTOFRecHit* hitArray, Int_t ***mapPixels, AliTOFPad* pixelArray, Int_t* kTOFhitFirst, Int_t& ipixel, Int_t* iTrackPt, Int_t* iTOFpixel, Int_t ntotTpcTracks)
2287{
f9a28264 2288 Int_t TestTracks,iTestTrack,itest,wPixel=0,itestc;
2289 Int_t * ntest = new Int_t[fMaxTestTracks];
2290 Int_t * testPixel = new Int_t[fMaxTestTracks];
2291 Float_t wLength=0.,wRho=0.,wZ=0.;
2292 Float_t * testLength = new Float_t[fMaxTestTracks];
2293 Float_t * testRho = new Float_t[fMaxTestTracks];
2294 Float_t * testZ = new Float_t[fMaxTestTracks];
2295 Float_t weight;
2296 Float_t * testWeight = new Float_t[fMaxTestTracks];
db9ba97f 2297 Float_t rotationFactor,phi0,coslam,sinlam,helixRadius,xHelixCenter,yHelixCenter,zHelixCenter,helixFactor;
2298 Int_t npixel[5],iMapValue,iwork1,iwork2,iwork3,iwork4,ihit=0;
2299 Int_t charge[48]={ 0, 1,-1, 0, 1,-1, 0, 1,-1, 0,
2300 1,-1, 0, 1,-1, 0, 0, 0, 1, 0,
2301 -1, 0,-1,-1, 0, 0,-1, 0, 1, 0,
2302 1, 1, 0, 0, 1,-1, 0, 0, 1,-1,
2303 1, 1,-1, 0, 1, 1, 2, 0};
2304 Float_t theta0,gpx,gpy,gpz,gp,gpt,gtheta,gx,gy,gz,gr,gxLast,gyLast,gzLast,chargeField;
2305 Float_t sumOfTheta=0.,weightTestTracksOutTof[4];
2306 Float_t s,ds,xRespectToHelixCenter,yRespectToHelixCenter,deltaRadius,fp,xp,yp,grho;
2307 Float_t mass,energy,g;
2308 Int_t itrack=0,itr,particleCharge,istep,iplate=0,iPadAlongX=0;
2309 Int_t itra,t34=0,t32=0,t44=0,t43=0,t42=0;
2310 Int_t wstate=0,m2state=0,wPix;
2311 Int_t idelR=0,idelR1=0,idelR2=0,iRmin=0,iRmin1=0,iRmin2=0;
2312 Float_t massArray[50] = {0.0,0.00051,0.00051,0.0,0.1057,0.1057,0.135,0.1396,0.1396,0.4977,
2313 0.4936,0.4936,0.9396,0.9383,0.9383,0.4977,0.5488,1.1156,1.1894,1.1926,1.1926,
2314 1.3149,1.3213,1.6724,0.9396,1.1156,1.1894,1.1926,1.1974,1.3149,
2315 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
2316 Float_t delR;
2317 Float_t radius,area,normR,normS,cosAngl;
2318 Int_t iPlateFirst,iTestGmax=0;
2319 Int_t fstate,iPrintM1=0,iPrintM2=0;
2320 Float_t gxExtrap=0.,gyExtrap=0.,gzExtrap=0.;
2321 Float_t avSigZ=0,avSigRPHI=0,avSigP=0,avSigPHI=0,avSigTHETA=0;
2322
2323 Float_t gxW,gyW,gzW;
2324 Float_t length0;
2325 Float_t snr=0;
2326 Int_t indexOfTestTrack;
2327 Float_t zPad,xPad;
2328 Int_t istate=0,imax=0,match,iMaxTestTracksOutTof=0,matchw;
2329 Float_t w,wmax=0.,inverseOfParticleSpeed,w2,smat[9],largestWeightTracksOutTof,sw;
2330 Float_t sumWeightTracksOutTof,sGeomWeigth;
2331 Int_t imatched;
2332 Int_t m10=0,m20=0,m22=0,m23=0;
2333 Int_t PRINT=0;
2334 TParticle *particle;
2335
2336 Float_t time=0.;
2337 itr=ntotTpcTracks;
2338 printf(" itr=%i\n",itr);
2339 for (itra=1; itra<itr+1; itra++) {
2340
2341 Int_t itrack=iTrackPt[itra-1];
2342 if(itrack==0) printf(" iTrackPt[itra-1]=0 for itra=%i\n",itra);
2343 Int_t ipart=trackArray[itrack-1].GetTrack();
2344 Float_t pvtx=trackArray[itrack-1].GetP();
2345 Int_t pdgCode=trackArray[itrack-1].GetPdgCode();
2346 Float_t tpclength=trackArray[itrack-1].GetlTPC();
2347 Float_t x=trackArray[itrack-1].GetRxTPC();
2348 Float_t y=trackArray[itrack-1].GetRyTPC();
2349 Float_t z=trackArray[itrack-1].GetRzTPC();
b213b8bd 2350 /* vars used for QA
db9ba97f 2351 Float_t RxTPC=x;
2352 Float_t RyTPC=y;
2353 Float_t RzTPC=z;
b213b8bd 2354 */
db9ba97f 2355 Float_t Wx=x;
2356 Float_t Wy=y;
2357 Float_t Wz=z;
2358 Float_t px=trackArray[itrack-1].GetPxTPC();
2359 Float_t py=trackArray[itrack-1].GetPyTPC();
2360 Float_t pz=trackArray[itrack-1].GetPzTPC();
b213b8bd 2361 /* vars used for QA
db9ba97f 2362 Float_t pxTPC=px;
2363 Float_t pyTPC=py;
2364 Float_t pzTPC=pz;
b213b8bd 2365 */
db9ba97f 2366 Float_t p = TMath::Sqrt(px*px+py*py+pz*pz);
b213b8bd 2367 /* var used for QA
db9ba97f 2368 Float_t pTPC=p;
b213b8bd 2369 */
db9ba97f 2370 Float_t rho = TMath::Sqrt(x*x+y*y);
2371 Float_t phi=0.;
2372 if(TMath::Abs(x)>0. || TMath::Abs(y)>0.) phi=TMath::ATan2(y,x);
2373 if(phi<0.) phi=phi+2.*TMath::Pi();
b213b8bd 2374 /* var used for QA
db9ba97f 2375 Float_t phiTPC=phi*kRaddeg;
b213b8bd 2376 */
db9ba97f 2377 if(fSigmavsp) {
2378 if(p==0) printf(" p=%f in g=0.022/p\n",p);
2379 g=0.022/p;
2380 avSigRPHI += g; // (cm)
2381 if(rho==0) printf(" rho=%f in phi += g*gRandom->Gaus()/rho\n",rho);
2382 phi += g*gRandom->Gaus()/rho;
2383 } else {
2384 if(rho==0) printf(" rho=%f in phi += (SIGMARPHI*gRandom->Gaus()/rho\n",rho);
2385 phi += (fSigmarphi*gRandom->Gaus()/rho);
2386 }
2387 x=rho*TMath::Cos(phi);
2388 y=rho*TMath::Sin(phi);
b213b8bd 2389 /* var used for QA
db9ba97f 2390 Float_t zTPC=z;
b213b8bd 2391 */
db9ba97f 2392 if(fSigmavsp) {
2393 if(p==0) printf(" p=%f in g=0.0275/p\n",p);
2394 g=0.0275/p;
2395 avSigZ += g; // (cm)
2396 z += g*gRandom->Gaus();
2397 } else {
2398 z += fSigmaZ*gRandom->Gaus();
2399 }
2400
2401 // smearing on TPC momentum
2402
2403 {
2404 Float_t pmom,phi,theta,arg;
2405
2406 pmom=TMath::Sqrt(px*px+py*py+pz*pz);
2407 phi=0.;
2408 if(TMath::Abs(px)>0. || TMath::Abs(py)>0.) phi=TMath::ATan2(py,px);
2409 if(phi<0.) phi=phi+2*TMath::Pi();
2410 arg=1.;
2411 if(pmom>0.) arg=pz/pmom;
2412 theta=0.;
2413 if(TMath::Abs(arg)<=1.) theta=TMath::ACos(arg);
2414
2415 if(fSigmavsp) {
2416 if(pmom<=0) printf(" pmom=%f in g = TMath::Abs(TMath::Log(pmom)/TMath::Log(10)+0.5)/0.7\n",pmom);
2417 g = TMath::Abs(TMath::Log(pmom)/TMath::Log(10)+0.5)/0.7;
2418 g = 0.01*(g*g*g+1.5)*1.24;
2419 avSigP += g;
2420 pmom *= (1+g*gRandom->Gaus());
2421
2422 if(p<10) {
2423 if(pmom<=0) printf(" pmom=%f in g = 1-TMath::Log(pmom)/TMath::Log(10)\n",pmom);
2424 g = 1-TMath::Log(pmom)/TMath::Log(10);
2425 g = 0.001*(g*g*g+0.3)*0.65; // (radian)
2426 } else {
2427 g = 0.001*0.3*0.65;
2428 }
2429 avSigPHI += g;
2430 phi += g*gRandom->Gaus();
2431 avSigTHETA += g;
2432 theta += g*gRandom->Gaus();
2433
2434 } else {
2435 pmom *= (1+fSigmap*gRandom->Gaus());
2436 phi += fSigmaPhi*gRandom->Gaus();
2437 theta += fSigmaTheta*gRandom->Gaus();
2438 }
2439 gxW=px;
2440 gyW=py;
2441 gzW=pz;
2442
2443 px=pmom*TMath::Sin(theta)*TMath::Cos(phi);
2444 py=pmom*TMath::Sin(theta)*TMath::Sin(phi);
2445 pz=pmom*TMath::Cos(theta);
2446
2447
2448 if(x*px+y*py<=0) {
2449 x=Wx;
2450 y=Wy;
2451 z=Wz;
2452 px=gxW;
2453 py=gyW;
2454 pz=gzW;
2455 }// if(x*px+y*py<=0)
2456 }
2457
2458 p = TMath::Sqrt(px*px+py*py+pz*pz);
2459
2460 particleCharge=charge[PDGtoGeantCode(pdgCode)-1];
2461 mass=massArray[PDGtoGeantCode(pdgCode)-1];
2462 mass=massArray[8-1]; //we take pion mass for all tracks
2463 // mass=massArray[14-1]; //here we take proton mass for all tracks
2464 energy=TMath::Sqrt(p*p+mass*mass);
2465 chargeField=particleCharge*fField;
2466
2467 g=fRadLenTPC/( (x*px+y*py)/(rho*p) );
2468
2469 if(g<=0) printf(" error, g<=0: g=%f, itra=%i, x,y,px,py=%f, %f, %f, %f\n",g,itra,x,y,px,py);
2470
2471 theta0=13.6*0.001*TMath::Sqrt(g)*(1.+0.038*TMath::Log(g))*energy/(p*p);
2472
2473
2474 // start Loop on test tracks
2475 sumOfTheta=0.;
2476 for(Int_t i=0;i<4;i++) {
2477 weightTestTracksOutTof[i]=0.;
2478 }
2479
2480 itest=0;
2481 for(Int_t i=0;i<fMaxTestTracks;i++) {
2482 ntest[i]=0;
2483 testPixel[i]=0;
2484 testLength[i]=0.;
2485 testRho[i]=0.;
2486 testZ[i]=0.;
2487 testWeight[i]=0.;
2488 }
2489
2490 iPlateFirst=0;
2491 TestTracks=0;
2492 iTestTrack=0;
2493 iTestGmax=0;
2494
2495 length0=0;
2496
2497 for (indexOfTestTrack=0; indexOfTestTrack<fMaxTestTracks; indexOfTestTrack++) {
2498
2499 iTestTrack++;
2500 gpx=px;
2501 gpy=py;
2502 gpz=pz;
2503 gp=p;
2504 if(indexOfTestTrack) {
2505 gtheta=theta0;
2506 EpMulScatt(gpx,gpy,gpz,gp,gtheta);
2507
2508 } else {
2509 gtheta=0;
2510 }
2511
2512 weight=TMath::Exp(-gtheta*gtheta/(2*theta0*theta0));
2513 sumOfTheta += gtheta;
2514
2515 // ==========================================================
2516 // Calculate crossing of the track in magnetic field with cylidrical surface
2517 // of radius RTOFINNER
2518 // chargeField = qB, where q is a charge of a particle in units of e,
2519 // B is magnetic field in tesla
2520 // see 3.3.1.1. in the book "Data analysis techniques for
2521 // high-energy physics experiments", edited by M.Regler
2522 // in Russian: "Metody analiza dannykh v fizicheskom eksperimente"
2523 // Moskva, "Mir", 1993. ctr.306
2524
2525 // Initial constants
2526 rotationFactor=1.;
2527 if(chargeField<0.) rotationFactor=-1.;
2528 rotationFactor=-rotationFactor;
2529 gpt=gpx;
2530 phi0=gpy;
2531 cylcor(gpt,phi0);
2532 phi0 -= rotationFactor*TMath::Pi()*0.5;
2533 // phi0 -= h*PID2;
2534 coslam=gpt/gp;
2535 sinlam=gpz/gp;
2536 // helixRadius=100.*gpt/TMath::Abs(0.299792458*chargeField);
2537 helixRadius=100.*gpt/TMath::Abs(AliTOFConstants::fgkSpeedOfLight*chargeField);
2538 xHelixCenter=x-helixRadius*TMath::Cos(phi0);
2539 yHelixCenter=y-helixRadius*TMath::Sin(phi0);
2540 zHelixCenter=z;
2541 helixFactor=rotationFactor*coslam/helixRadius;
2542
2543 // Solves the equation f(s)=r(s)-RTOFINNER=0 by the Newton's method:
2544 // snew=s-f/f'
2545 istep=0;
2546 s=AliTOFConstants::fgkrmin-TMath::Sqrt(x*x+y*y);;
2547 do {
2548 istep++;
2549 xRespectToHelixCenter=helixRadius*TMath::Cos(phi0+s*helixFactor);
2550 yRespectToHelixCenter=helixRadius*TMath::Sin(phi0+s*helixFactor);
2551 gx=xHelixCenter+xRespectToHelixCenter;
2552 gy=yHelixCenter+yRespectToHelixCenter;
2553 gr=TMath::Sqrt(gx*gx+gy*gy);
2554 deltaRadius=gr-AliTOFConstants::fgkrmin;
2555 xp=-helixFactor*yRespectToHelixCenter;
2556 yp= helixFactor*xRespectToHelixCenter;
2557 fp=(gx*xp+gy*yp)/gr;
2558 ds=deltaRadius/fp;
2559 s -= ds;
2560 if(istep==20) {
2561 istep=0;
2562 break;
2563 }
2564 } while (TMath::Abs(ds)>0.01);
2565
2566
2567 if(istep==0) goto end;
2568
2569 // Steps along the circle till a pad
2570 wPixel=0;
2571 wLength=0.;
2572 iplate=0;
2573 iPadAlongX=0;
2574 grho=0.;
2575 ds=fStep;
2576 gxLast=xHelixCenter+helixRadius*TMath::Cos(phi0+s*helixFactor);
2577 gyLast=yHelixCenter+helixRadius*TMath::Sin(phi0+s*helixFactor);
2578 gzLast=zHelixCenter+s*sinlam;
2579
2580
2581 do {
2582 istep++;
2583 s += ds;
2584 gx=xHelixCenter+helixRadius*TMath::Cos(phi0+s*helixFactor);
2585 gy=yHelixCenter+helixRadius*TMath::Sin(phi0+s*helixFactor);
2586 gz=zHelixCenter+s*sinlam;
2587 rho=TMath::Sqrt(gx*gx+gy*gy);
2588
2589 IsInsideThePad(fg3,gx,gy,gz,npixel,zPad,xPad);
2590
2591 iplate += npixel[1];
2592 iPadAlongX += npixel[4];
2593
2594 if(indexOfTestTrack==0 && iplate && iPlateFirst==0) {
2595 iPlateFirst=1;
2596 length0=s;
2597
2598 radius=s*3*theta0;
2599 area=TMath::Pi()*radius*radius;
2600 normR=TMath::Sqrt(gx*gx+gy*gy);
2601 normS=TMath::Sqrt((gx-gxLast)*(gx-gxLast)+
2602 (gy-gyLast)*(gy-gyLast)+
2603 (gz-gzLast)*(gz-gzLast));
2604
2605 cosAngl=(gx*(gx-gxLast)+gy*(gy-gyLast))/(normR*normS);
2606 if(cosAngl<0) printf(" cosAngl<0: gx=%f,gy=%f, gxLast=%f,gyLast=%f,gzLast=%f\n",gx,gy,gxLast,gyLast,gzLast);
2607
2608 area /= cosAngl;
2609 TestTracks=(Int_t) (2*area/(AliTOFConstants::fgkXPad * AliTOFConstants::fgkZPad));
2610
2611 if(TestTracks<12) TestTracks=12;
2612
2613 // Angles of entering into the TOF plate
2614
2615 Int_t iZ=0;
2616 if(TMath::Abs(gz)>300) {
2617 iZ=4;
2618 } else if(TMath::Abs(gz)>200) {
2619 iZ=3;
2620 } else if(TMath::Abs(gz)>100) {
2621 iZ=2;
2622 } else if(TMath::Abs(gz)>0) {
2623 iZ=1;
2624 }
2625
2626
2627 } // end of if(indexOfTestTrack==0 && iplate && iPlateFirst==0)
2628
2629
2630 if(npixel[4]>0) {
2631
2632 iwork1=npixel[0];
2633 iwork2=npixel[1];
2634 iwork3=npixel[2];
2635 // iwork4=npixel[3];
2636 iwork4=(npixel[3]-1)*AliTOFConstants::fgkNpadX+npixel[4];
2637
2638 Int_t ifirstindex=AliTOFConstants::fgkNSectors*(npixel[1]-1)+npixel[0];
2639 iMapValue=mapPixels[ifirstindex-1][iwork3-1][iwork4-1];
2640 if(iMapValue==0) {
2641 ipixel++;
2642 if(ipixel>fMaxPixels) {
2643 cout << "ipixel=" << ipixel << " > MAXPIXELS=" << fMaxPixels << endl;
2644 break;
2645 }
2646 mapPixels[ifirstindex-1][iwork3-1][iwork4-1]=ipixel;
2647 pixelArray[ipixel-1].SetGeom(iwork1,iwork2,iwork3,iwork4);
2648 iMapValue=ipixel;
2649 }
2650
2651 wPixel=iMapValue;
2652 wLength=tpclength+s;
2653 wRho=rho;
2654 wZ=gz;
2655
2656 ihit=kTOFhitFirst[ipart];
2657
2658 if(ihit) {
2659 if(indexOfTestTrack==0) {
2660 {
2661 idelR++;
2662 delR=TMath::Sqrt((gx-hitArray[ihit-1].X())*(gx-hitArray[ihit-1].X())+
2663 (gy-hitArray[ihit-1].Y())*(gy-hitArray[ihit-1].Y())+
2664 (gz-hitArray[ihit-1].Z())*(gz-hitArray[ihit-1].Z()));
2665
2666 }
2667
2668 if(delR>hitArray[ihit-1].GetRmin()) iRmin++;
2669 gxExtrap=gx;
2670 gyExtrap=gy;
2671 gzExtrap=gz;
2672 } else {
2673 delR=TMath::Sqrt((gx-gxExtrap)*(gx-gxExtrap)+
2674 (gy-gyExtrap)*(gy-gyExtrap)+
2675 (gz-gzExtrap)*(gz-gzExtrap));
2676 }
2677 } //end of if(ihit)
2678
2679 break;
2680
2681 } //end of npixel[4]
2682
2683 if(rho<grho) {
2684 istep=0;
2685 break;
2686 }
2687 grho=rho;
2688
2689 gxLast=gx;
2690 gyLast=gy;
2691 gzLast=gz;
2692
2693 } while(rho<AliTOFConstants::fgkrmax); //end of do
2694
2695
2696 if(istep>0) {
2697 if(iplate) {
2698 if(iPadAlongX==0) {
2699 istep=-3; // holes in TOF
2700 }
2701 } else {
2702 if(TMath::Abs(gz)<AliTOFConstants::fgkMaxhZtof) {
2703 // if(TMath::Abs(gz)<MAXZTOF2) {
2704 istep=-2; // PHOS and RICH holes or holes in between TOF plates
2705 } else {
2706 istep=-1; // out of TOF on z-size
2707 }
2708 }
2709 }
2710
2711 if(iPadAlongX>0) {
2712 if(itest==0) {
2713 itest=1;
2714 ntest[itest-1]=1;
2715 testPixel[itest-1]=wPixel;
2716 testLength[itest-1]=wLength;
2717 testRho[itest-1]=wRho;
2718 testZ[itest-1]=wZ;
2719 testWeight[itest-1]=weight;
2720 } else {
2721 Int_t k;
2722 for(Int_t i=0;i<itest;i++) {
2723 k=0;
2724 if(testPixel[i]==wPixel) {
2725 k=1;
2726 ntest[i]++;
2727 testLength[i] += wLength;
2728 testRho[i] += wRho;
2729 testZ[i] += wZ;
2730 testWeight[i] += weight;
2731 break;
2732 }
2733 } //end for i
2734 if(k==0) {
2735 itest++;
2736 ntest[itest-1]=1;
2737 testPixel[itest-1]=wPixel;
2738 testLength[itest-1]=wLength;
2739 testRho[itest-1]=wRho;
2740 testZ[itest-1]=wZ;
2741 testWeight[itest-1]=weight;
2742 }
2743 }
2744 }
2745
2746 end: ;
2747 // Statistics
2748 if(fMatchingStyle==1) {
2749 if(istep>-4 && istep<1) weightTestTracksOutTof[-istep] ++;
2750 } else {
2751 if(istep>-4 && istep<1) weightTestTracksOutTof[-istep] += weight;
2752 }
2753
2754 if(fMatchingStyle==2) {
2755 if(indexOfTestTrack==0 && istep==0) break;
2756 if(indexOfTestTrack+1==TestTracks) break;
2757 }
2758
2759 } //end of indexOfTestTrack
2760
2761 snr += (Float_t) (indexOfTestTrack+1);
2762
2763 // Search for the "hole" with the largest weigth
2764 largestWeightTracksOutTof=0.;
2765 sumWeightTracksOutTof=0.;
2766 for(Int_t i=0;i<4;i++) {
2767 w=weightTestTracksOutTof[i];
2768 sumWeightTracksOutTof += w;
2769 if(w>largestWeightTracksOutTof) {
2770 largestWeightTracksOutTof=w;
2771 iMaxTestTracksOutTof=i;
2772 }
2773 }
2774
2775 itestc=itest;
2776 if(itest>0) {
2777 for(Int_t i=0;i<itest;i++) {
2778 testLength[i] /= ntest[i];
2779 testRho[i] /= ntest[i];
2780 testZ[i] /= ntest[i];
2781 }
2782 // Search for the pixel with the largest weigth
2783 wmax=0.;
2784 wstate=0;
2785 sw=0;
2786 sGeomWeigth=0;
2787 for(Int_t i=0;i<itest;i++) {
2788 istate=pixelArray[testPixel[i]-1].GetState();
2789 fstate=0;
2790 if(istate>0) {
2791 fstate=1;
2792 wstate++;
2793 }
2794 if(fMatchingStyle==1) {
2795 sGeomWeigth += ntest[i];
2796 w=(fpadefficiency*fstate+(1.-fpadefficiency)*(1-fstate))*ntest[i];
2797 if(pixelArray[testPixel[i]-1].GetTrackMatched()>0) w *= 0.1;
2798 } else {
2799 sGeomWeigth += testWeight[i];
2800 w=(fpadefficiency*fstate+(1.-fpadefficiency)*(1-fstate))*testWeight[i];
2801 if(pixelArray[testPixel[i]-1].GetTrackMatched()>0) w *= 0.1;
2802 }
2803
2804 // weighting according to the Pulse Height (we use the square of weight)
2805 // if (fChargeFactorForMatching) w *= (pixelArray[testPixel[i]-1].GetCharge())*(pixelArray[testPixel[i]-1].GetCharge());
2806 if (fChargeFactorForMatching && fstate==1) w *= (pixelArray[testPixel[i]-1].GetCharge())*(pixelArray[testPixel[i]-1].GetCharge());
2807
2808 if(w>wmax) {
2809 wmax=w;
2810 imax=i;
2811 }
2812 sw += w;
2813 }
2814 wPixel=testPixel[imax];
2815 wLength=testLength[imax];
2816 istate=pixelArray[wPixel-1].GetState();
2817
2818 //Choose the TOF dead space
2819 // if(istate==0 && largestWeightTracksOutTof>wmax) {
2820 // if(istate==0 && largestWeightTracksOutTof>=sw) {
2821 if(istate==0 && sumWeightTracksOutTof>sGeomWeigth) {
2822 itestc=itest;
2823 itest=0;
2824 }
2825 }
2826
2827 if(itest>0) {
2828
2829 // Set for MyTrack: Pixel
2830 trackArray[itrack-1].SetPixel(wPixel);
2831
2832 istate=pixelArray[wPixel-1].GetState();
2833
2834 if(istate) {
2835
2836 // Set for MyTrack: Pixel, Length, TOF, MassTOF
2837 //fp
2838 //time=pixelArray[wPixel-1].GetTime();
2839 time=pixelArray[wPixel-1].GetRealTime();
2840 trackArray[itrack-1].SetLength(wLength);
2841 trackArray[itrack-1].SetTof(time);
2842
2843 inverseOfParticleSpeed=time/wLength;
2844 //w=900.*inverseOfParticleSpeed*inverseOfParticleSpeed-1.;
2845 w=(100.*AliTOFConstants::fgkSpeedOfLight)*(100.*AliTOFConstants::fgkSpeedOfLight)*inverseOfParticleSpeed*inverseOfParticleSpeed-1.;
2846 w2=pvtx*pvtx;
2847 Float_t squareMass=w2*w;
2848 mass=TMath::Sqrt(TMath::Abs(squareMass));
2849 if(w<0.) mass=-mass;
2850
2851 trackArray[itrack-1].SetMassTOF(mass);
2852
2853 // Set for MyTrack: Matching
2854 match=4;
2855 // if(ipart==pixelArray[wPixel-1].GetTrack()) match=3;
2856 if( (ipart==pixelArray[wPixel-1].GetTrack()) && hitArray[pixelArray[wPixel-1].GetHit()-1].GetNoise()==0)match=3;
2857 imatched=pixelArray[wPixel-1].GetTrackMatched();
2858 // Set for TOFPixel the number of matched track
2859 pixelArray[wPixel-1].SetTrackMatched(itrack);
2860
2861 if(imatched>0) {
2862 matchw=trackArray[imatched-1].GetMatching();
2863 if(match==3 && matchw==4) t34++;
2864 if(match==3 && matchw==2) t32++;
2865 if(match==4 && matchw==4) t44++;
2866 if(match==4 && matchw==3) t43++;
2867 if(match==4 && matchw==2) t42++;
2868 if(iTOFpixel[ipart]==0 || iTOFpixel[trackArray[imatched-1].GetTrack()]==0) {
2869 m20++;
2870 } else if(iTOFpixel[ipart]==iTOFpixel[trackArray[imatched-1].GetTrack()]) {
2871 m22++;
2872 } else {
2873 m23++;
2874 wPix=iTOFpixel[ipart];
2875 if(PRINT && iPrintM1==10 && iPrintM2<10) {
2876 if(iPrintM2==0) {
2877 printf("*** test print for tracks matched with the pixel for with we had matched track\n");
2878 }
2879 iPrintM2++;
2880 printf(" m=2: ipart=%i, pdgCode=%i, p=%f, theta0=%f, %i Pixel(LP=%i,SP=%i,P=%i) \n",
2881 ipart,pdgCode,p,theta0,wPix,
2882 pixelArray[wPix-1].GetSector(),pixelArray[wPix-1].GetPlate(),pixelArray[wPix-1].GetPixel());
2883 printf(" mat=%i, %i Pixel(LP=%i,SP=%i,P=%i), Test(n=%i,i=%i,w=%f,z=%f), wst=%i \n",
2884 match,wPixel,
2885 pixelArray[wPixel-1].GetSector(),pixelArray[wPixel-1].GetPlate(),pixelArray[wPixel-1].GetPixel(),
2886 itest,imax,wmax,testZ[imax],wstate);
2887 Int_t fstat,istat;
2888 for(Int_t i=0;i<itest;i++) {
2889 wPix=testPixel[i];
2890 istat=pixelArray[wPix-1].GetState();
2891 fstat=0;
2892 if(istat>0) fstat=1;
2893 w=(fpadefficiency*fstat+(1.-fpadefficiency)*(1-fstat))*ntest[i];
2894 if(istat>0)
2895 printf(" %i: %i Pixel(LP=%i,SP=%i,P=%i), istat=%i, ntest=%i, w=%f\n",i+1,
2896 wPix,pixelArray[wPix-1].GetSector(),pixelArray[wPix-1].GetPlate(),pixelArray[wPix-1].GetPixel(),
2897 istat,ntest[i],w);
2898 }
2899 printf(" mat=%i, %i Pixel \n",matchw,trackArray[imatched-1].GetPad());
2900 }
2901 }
2902 if(wstate>1) m2state++;
2903 smat[matchw+4]--;
2904 match=2;
2905 trackArray[imatched-1].SetMatching(match);
2906 smat[match+4]++;
2907
2908 } // if(imatched>0)
2909
2910 } else { //else if(istate)
2911
2912 match=1;
2913 if(iTOFpixel[ipart]==0) m10++;
2914 if(PRINT && iPrintM1<10) {
2915 Int_t wPix;
2916 wPix=iTOFpixel[ipart];
2917 if(wPix) {
2918 if(iPrintM1==0) {
2919 printf("*** test print for tracks fired a pixel but matched with non-fired pixel\n");
2920 }
2921 iPrintM1++;
2922 printf(" m=1: itra=%i,ipart=%i, pdgCode=%i, p=%f, theta0=%f, %i Pixel(LP=%i,SP=%i,P=%i) \n",
2923 itra,ipart,pdgCode,p,theta0,wPix,
2924 pixelArray[wPix-1].GetSector(),pixelArray[wPix-1].GetPlate(),pixelArray[wPix-1].GetPixel());
2925 printf(" mat=%i, %i Pixel(LP=%i,SP=%i,P=%i), Test(n=%i,i=%i,w=%f,z=%f), wst=%i \n",
2926 match,wPixel,
2927 pixelArray[wPixel-1].GetSector(),pixelArray[wPixel-1].GetPlate(),pixelArray[wPixel-1].GetPixel(),
2928 itest,imax,wmax,testZ[imax],wstate);
2929
2930 }
2931 } //end if(PRINT && iPrintM1<10)
2932
2933 } //end if(istate)
2934
2935 } else {
2936 match=-1-iMaxTestTracksOutTof;
2937
2938 } //end itest
2939
2940 trackArray[itrack-1].SetMatching(match);
2941 // if(iTestGmax==1) hMTT->Fill(match);
2942 smat[match+4]++;
2943
2944 sumOfTheta /= iTestTrack;
2945
2946 itest=itestc;
2947
2948 //Test
2949 if(PRINT) {
2950 if(iTOFpixel[ipart] && match!=3) {
2951 particle = (TParticle*)gAlice->Particle(ipart); //for V3.05
2952
2953 printf(" ipixel=%i (Sector=%i, Plate=%i, Strip=%i, Pixel=%i), fired by %i track\n",iTOFpixel[ipart],pixelArray[iTOFpixel[ipart]-1].GetSector(),pixelArray[iTOFpixel[ipart]-1].GetPlate(),pixelArray[iTOFpixel[ipart]-1].GetStrip(),pixelArray[iTOFpixel[ipart]-1].GetPixel(),pixelArray[iTOFpixel[ipart]-1].GetTrack());
2954 printf(" indexOfTestTrack=%i itest=%i weightTestTracksOutTof[4]=%f weightTestTracksOutTof[2]=%f weightTestTracksOutTof[1]=%f weightTestTracksOutTof[0]=%f\n",indexOfTestTrack,itest,weightTestTracksOutTof[3],weightTestTracksOutTof[2],weightTestTracksOutTof[1],weightTestTracksOutTof[0]);
2955 if(itest) {
2956
2957 printf(" take ipixel=%i (Sector=%i, Plate=%i, Strip=%i, Pixel=%i), (fired by %i track), match=%i\n",wPixel,pixelArray[wPixel-1].GetSector(),pixelArray[wPixel-1].GetPlate(),pixelArray[wPixel-1].GetStrip(),pixelArray[wPixel-1].GetPixel(),pixelArray[wPixel-1].GetTrack(),match);
2958 }
2959 }
2960 }
2961 if(PRINT && itra<10 ) {
2962
2963 if(itest) {
2964 cout << " number of pixels with test tracks=" << itest << endl;
2965 for(Int_t i=0;i<itest;i++) {
2966 cout << " " << i+1 << " tr.=" << ntest[i] << " w=" << testWeight[i] << " pix.= " << testPixel[i] << " (" <<
2967 pixelArray[testPixel[i]-1].GetSector() << " " << " " << pixelArray[testPixel[i]-1].GetPlate() << " " <<
2968 pixelArray[testPixel[i]-1].GetPixel() << " )" << " l= " << testLength[i] << " sig=" <<
2969 theta0*(testLength[i]-tpclength) << " rho= " << testRho[i] << " z= " << testZ[i] << endl;
2970 }
2971 cout << " pixel=" << wPixel << " state=" << istate << " l=" << wLength << " TOF=" << time << " m=" << mass << " match=" << match << endl;
2972 if(istate>0) cout << " fired by track " << pixelArray[wPixel-1].GetTrack() << endl;
2973 }
2974 }
2975 } //end of track
2976
2977
2978 if(itr) {
2979 printf(" %f probe tracks per 1 real track\n",snr/itr);
2980 itrack=itr;
2981 }
2982
2983
2984 cout << ipixel << " - total number of TOF pixels after matching" << endl;
2985 w=iRmin;
2986 if(idelR!=0) {
2987 w /= idelR;
2988 printf(" %i tracks with delR, %f of them have delR>Rmin \n",idelR,w);
2989 }
2990 w=iRmin1;
2991 if(idelR1!=0) {
2992 w /= idelR1;
2993 printf(" %i tracks with delR1 (|z|<175), %f of them have delR>Rmin \n",idelR1,w);
2994 }
2995 w=iRmin2;
2996 if(idelR2!=0) {
2997 w /= idelR2;
2998 printf(" %i tracks with delR2 (|z|>175), %f of them have delR>Rmin \n",idelR2,w);
2999 }
3000
3001 cout << " ******************** End of matching **********" << endl;
f9a28264 3002 delete [] ntest;
3003 delete [] testPixel;
3004 delete [] testLength;
3005 delete [] testRho;
3006 delete [] testZ;
3007 delete [] testWeight;
db9ba97f 3008}
3009
3010//____________________________________________________________________________
3011void AliTOFReconstructioner::FillNtuple(Int_t ntracks, AliTOFTrack* trackArray, AliTOFRecHit* hitArray, AliTOFPad* pixelArray, Int_t* iTOFpixel, Int_t* iparticle, Float_t* toftime, Int_t& ipixelLastEntry, Int_t itrack){
3012
3013 // itrack : total number of TPC selected tracks
3014 // for the caller is ntotTPCtracks
3015
3016 cout << " ******************** Start of searching non-matched fired pixels **********" << endl;
3017 const Int_t charge[48]={ 0, 1,-1, 0, 1,-1, 0, 1,-1, 0,
3018 1,-1, 0, 1,-1, 0, 0, 0, 1, 0,
3019 -1, 0,-1,-1, 0, 0,-1, 0, 1, 0,
3020 1, 1, 0, 0, 1,-1, 0, 0, 1,-1,
3021 1, 1,-1, 0, 1, 1, 2, 0};
3022
3023 Int_t macthm1=0;
3024 Int_t macthm2=0;
3025 Int_t macthm3=0;
3026 Int_t macthm4=0;
3027 Int_t macth0=0;
3028 Int_t macth1=0;
3029 Int_t macth2=0;
3030 Int_t macth3=0;
3031 Int_t macth4=0;
3032
3033
3034 Float_t smat[9],smat0[9],smat1[9];
3035 for(Int_t i=0;i<9;i++) {
3036 smat[i]=0.;
3037 smat0[i]=0.;
3038 smat1[i]=0.;
3039 }
3040
3041 Int_t nFiredPixelsNotMatchedWithTracks=0;
3042 Int_t istate;
3043 for (Int_t i=0; i<ipixelLastEntry; i++) {
3044 istate=pixelArray[i].GetState();
3045 if(istate==0) break;
3046 if(pixelArray[i].GetTrackMatched()==-1) nFiredPixelsNotMatchedWithTracks++;
3047 }
3048 printf(" %i fired pixels have not matched tracks\n",nFiredPixelsNotMatchedWithTracks);
3049 cout << " ******************** End of searching non-matched fired pixels **********" << endl;
3050
3051 Int_t nTPCHitMissing=0;
3052 for(Int_t i=0; i<ipixelLastEntry; i++) {
3053 if(pixelArray[i].GetHit()>0) {
3054 if(hitArray[pixelArray[i].GetHit()-1].GetNoise()==0) {
3055 if(iparticle[pixelArray[i].GetTrack()]==0) nTPCHitMissing++;
3056 }
3057 }
3058 }
3059 printf(" %i pixels fired by track hit without a hit on the last layer of TPC\n",nTPCHitMissing);
3060
3061
3062 Int_t icharge=0; // total number of charged particles
3063 Int_t iprim=0; // number of primaries
3064 Int_t ipions=0; // number of primary pions
3065 Int_t ikaons=0; // number of primary kaons
3066 Int_t iprotons=0; // number of primary protons
3067 Int_t ielectrons=0;// number of primary electrons
3068 Int_t imuons=0; // number of primary muons
3069 Float_t particleTypeArray[6][5][2];
3070
3071 for (Int_t index1=0;index1<6;index1++) {
3072 for (Int_t index2=0;index2<5;index2++) {
3073 for (Int_t index3=0;index3<2;index3++) {
3074 particleTypeArray[index1][index2][index3]=0.;
3075 }
3076 }
3077 }
3078
3079 Int_t nTOFhitsWithNoTPCTracks=0; // to be moved later when used
3080
3081 /*
3082 TObjArray *Particles = gAlice->Particles();
3083 Int_t numberOfParticles=Particles->GetEntries();
3084 cout << "numberOfParticles " << numberOfParticles << endl;
3085 // fpdbg
3086 if(numberOfParticles>fMaxAllTracks) numberOfParticles=fMaxAllTracks;
3087 */
3088
3089 for (Int_t i=0; i<ntracks; i++) { // starting loop on all primaries charged particles for current event)
3090
3091 /*
3092 cout << "particle " << i << endl;
3093 cout << "total " << numberOfParticles << endl;
3094 */
3095 TParticle *part = (TParticle *) gAlice->Particle(i);
3096 if(charge[PDGtoGeantCode(part->GetPdgCode())-1]) {
3097 icharge++;
3098 /*
3099 cout << "charged particles " << icharge << endl;
3100 */
3101 Int_t particleType=0;
3102 Int_t absPdgCode = TMath::Abs(part->GetPdgCode());
3103 switch (absPdgCode) {
3104 case 211:
3105 particleType=3;
3106 break ;
3107 case 321:
3108 particleType=2;
3109 break ;
3110 case 2212:
3111 particleType=1;
3112 break ;
3113 case 11:
3114 particleType=4;
3115 break ;
3116 case 13:
3117 particleType=5;
3118 break ;
3119 }
3120
3121 if(part->GetFirstMother() < 0) {
3122 iprim++;
3123 switch (particleType) {
3124 case 1:
3125 iprotons++;
3126 break ;
3127 case 2:
3128 ikaons++;
3129 break ;
3130 case 3:
3131 ipions++;
3132 break ;
3133 case 4:
3134 ielectrons++;
3135 break ;
3136 case 5:
3137 imuons++;
3138 break ;
3139 }
3140 }
3141
3142 Int_t match=0;
3143 Float_t wLength=-1.;
3144 Float_t time=-1.;
3145 Float_t mass=-1.;
3146
3147 Int_t itr=iparticle[i]; // get the track number for the current charged particle
3148
3149 if(iTOFpixel[i]>0 && itr==0) nTOFhitsWithNoTPCTracks++;
3150
3151 if(itr) {
3152 match=trackArray[itr-1].GetMatching();
3153 //cout << "match " << match << endl;
3154 wLength=trackArray[itr-1].GetLength();
3155 //cout << "wLength " << wLength << endl;
3156 time=trackArray[itr-1].GetTof();
3157 mass=trackArray[itr-1].GetMassTOF();
3158 //cout << "mext " << mass << endl;
3159 // if(PRINT && (i>789 && i<800) ) cout << i << " track: l=" << wLength << " TOF=" << time << " m=" << mass << " match=" << match << endl;
3160 if(iTOFpixel[i]==0) {
3161 smat0[match+4]++;
3162 wLength=-wLength;
3163 }
3164 }
3165 Int_t ikparen=part->GetFirstMother();
3166 Int_t imam;
3167 if(ikparen<0) {
3168 imam=0;
3169 } else {
3170 imam=part->GetPdgCode();
3171 }
3172
3173 Int_t evnumber=gAlice->GetEvNumber();
3174 if(match==-1) macthm1++;
3175 if(match==-2) macthm2++;
3176 if(match==-3) macthm3++;
3177 if(match==-4) macthm4++;
3178 if(match==0) macth0++;
3179 if(match==1) macth1++;
3180 if(match==2) macth2++;
3181 if(match==3) macth3++;
3182 if(match==4) macth4++;
3183 foutputntuple->Fill(evnumber,part->GetPdgCode(),imam,part->Vx(),part->Vy(),part->Vz(),part->Px(),part->Py(),part->Pz(),toftime[i],wLength,match,time,mass);
3184
3185
3186
3187 // -----------------------------------------------------------
3188 // Filling 2 dimensional Histograms true time vs matched time
3189 // Filling 1 dimensional Histogram true time - matched time
3190 //
3191 // time = time associated to the matched pad [ns]
3192 // it could be the average time of the cluster fired
3193 //
3194 // toftime[i] = real time (including pulse height delays) [s]
3195 //
3196 //
3197 // if (time>=0) {
3198 // if (imam==0) TimeTrueMatched->Fill(time, toftime[i]*1E+09);
3199 // if (imam==0) DeltaTrueTimeMatched->Fill(time-toftime[i]*1E+09);
3200 // }
3201 //
3202 //---------------------------------------------------------------
3203
3204 if(match==-4 || match>0) {
3205 Int_t matchW;
3206 matchW=match;
3207 if(match==-4) matchW=1;
3208 if(particleType) {
3209 particleTypeArray[particleType-1][matchW-1][1]++;
3210 particleTypeArray[5][matchW-1][1]++;
3211 particleTypeArray[particleType-1][4][1]++;
3212 particleTypeArray[5][4][1]++;
3213 if(part->GetFirstMother() < 0) {
3214 particleTypeArray[particleType-1][matchW-1][0]++;
3215 particleTypeArray[5][matchW-1][0]++;
3216 particleTypeArray[particleType-1][4][0]++;
3217 particleTypeArray[5][4][0]++;
3218
3219 // fill histos for QA
3220 //if(particleType==3 && matchW==3) hPiWithTrueTime->Fill(sqrt((part->Px())*(part->Px())+(part->Py())*(part->Py())+(part->Pz())*(part->Pz())));
3221 //if(particleType==2 && matchW==3) hKWithTrueTime->Fill(sqrt((part->Px())*(part->Px())+(part->Py())*(part->Py())+(part->Pz())*(part->Pz())));
3222 //if(particleType==1 && matchW==3) hPWithTrueTime->Fill(sqrt((part->Px())*(part->Px())+(part->Py())*(part->Py())+(part->Pz())*(part->Pz())));
3223 //
3224
3225 } // close if(part->GetFirstMother() < 0)
3226 } // close if(particleType)
3227 } // close if(match==-4 || match>0)
3228 } // close if(charge[PDGtoGeantCode(part->GetPdgCode())-1])
3229 } // close for (Int_t i=0; i<ntracks; i++) {
3230
3231 cout << " macthm1 " << macthm1 << endl;
3232 cout << " macthm2 " << macthm2 << endl;
3233 cout << " macthm3 " << macthm3 << endl;
3234 cout << " macthm4 " << macthm4 << endl;
3235 cout << " macth0 " << macth0 << endl;
3236 cout << " macth1 " << macth1 << endl;
3237 cout << " macth2 " << macth2 << endl;
3238 cout << " macth3 " << macth3 << endl;
3239 cout << " macth4 " << macth4 << endl;
3240
3241
3242 printf(" %i TOF hits have not TPC track\n",nTOFhitsWithNoTPCTracks);
3243 Int_t imatch=0;
3244 for(Int_t i=0;i<9;i++) {
3245 if(itrack) cout << " " << smat[i]*100./itrack << " % of them (="<<smat[i]<<") have match=" << i-4 << " " << smat0[i] << " have not TOF hits" << endl;
3246 if(i==0 || i>4) imatch += (Int_t) (smat[i]);
3247
3248 // cout << " " << smat[i]*100./itrack << " % of them (="<<smat[i]<<") have match=" << i-4 << " " << smat0[i] << " have not TOF hits" << " " << smat1[i] << " have (r.p)<0 for first hit" << endl;
3249 }
3250
3251 if(fdbg){
3252 /*
3253 cout << " nparticles = " << numberOfParticles << " charged = " << icharge << " prim.=" << iprim << endl;
3254 */
3255 cout << " nparticles = " << ntracks << " charged = " << icharge << " prim.=" << iprim << endl;
3256 cout << ipions << " - primary pions" << endl;
3257 cout << ikaons << " - primary kaons" << endl;
3258 cout << iprotons << " - primary protons" << endl;
3259 cout << ielectrons << " - primary electrons" << endl;
3260 cout << imuons << " - primary muons reached TPC" << endl;
3261 cout << " ********** " << imatch << " TPC tracks are matched with TOF pixels (incl.match=-4) **********" << endl;
3262 }
3263
3264 /*
3265 Float_t PrimaryInBarrel[6],Acceptance[6];
3266 PrimaryInBarrel[0]=ipions;
3267 PrimaryInBarrel[1]=ikaons;
3268 PrimaryInBarrel[2]=iprotons;
3269 PrimaryInBarrel[3]=ielectrons;
3270 PrimaryInBarrel[4]=imuons;
3271 PrimaryInBarrel[5]=ipions+ikaons+iprotons+ielectrons+imuons;
3272
3273 // cout << " TPC acceptance for the primary species: 1-p, 2-K, 3-pi, 4-e, 5-mu, 6-all" << endl;
3274 for(Int_t i=0; i<6; i++) {
3275 Acceptance[i]=0.;
3276 if(PrimaryInBarrel[i]) Acceptance[i]=100.*PrimaryReachedTPC[i]/PrimaryInBarrel[i];
3277 //hTPCacceptance[i]->Fill(Acceptance[i]);
3278 // printf(" species: %i %f\n",i+1,Acceptance[i]);
3279 }
3280
3281 // cout << " TOF acceptance for the primary species: 1-p, 2-K, 3-pi, 4-e, 5-mu, 6-all" << endl;
3282 for(Int_t i=0; i<6; i++) {
3283 Acceptance[i]=0.;
3284 if(PrimaryInBarrel[i]) Acceptance[i]=100.*PrimaryReachedTOF[i]/PrimaryInBarrel[i];
3285 //hTOFacceptance[i]->Fill(Acceptance[i]);
3286 // printf(" species: %i %f\n",i+1,Acceptance[i]);
3287 }
3288
3289 for (Int_t index1=0;index1<6;index1++) {
3290 for (Int_t index2=0;index2<4;index2++) {
3291 for (Int_t index3=0;index3<2;index3++) {
3292 if(particleTypeArray[index1][4][index3]) particleTypeArray[index1][index2][index3]=
3293 100.*particleTypeArray[index1][index2][index3]/particleTypeArray[index1][4][index3];
3294 }
3295 }
3296 }
3297
3298 cout << "species: 1-p, 2-K, 3-pi, 4-e, 5-mu, 6-all" << endl;
3299 cout << " matched pixels(%): 1-unfired 2-double 3-true 4-wrong 5-total number of tracks" << endl;
3300
3301 cout << " primary tracks:" << endl;
3302 for (Int_t i=0;i<6;i++) {
3303 cout << i+1 << " " << particleTypeArray[i][0][0] << " " << particleTypeArray[i][1][0] << " " << particleTypeArray[i][2][0] << " " << particleTypeArray[i][3][0] << " " << particleTypeArray[i][4][0] << endl;
3304 }
3305
3306 // cout<<" contam.for all prim.(%)="<<100*particleTypeArray[5][3][0]/(particleTypeArray[5][3][0]+particleTypeArray[5][2][0])<<endl;
3307
3308 cout << " all tracks:" << endl;
3309 for (Int_t i=0;i<6;i++) {
3310 cout << i+1 << " " << particleTypeArray[i][0][1] << " " << particleTypeArray[i][1][1] << " " << particleTypeArray[i][2][1] << " " << particleTypeArray[i][3][1] << " " << particleTypeArray[i][4][1] << endl;
3311 }
3312
3313 // cout<<" contam.for all (%)="<<100*particleTypeArray[5][3][1]/(particleTypeArray[5][3][1]+particleTypeArray[5][2][1])<<endl;
3314 // printf(" t34=%i, t32=%i, t44=%i, t43=%i, t42=%i\n",t34,t32,t44,t43,t42);
3315 // printf(" m10=%f, m20=%f, m22=%f, m23=%f, m2state=%i\n",m10,m20,m22,m23,m2state);
3316 */
3317}