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