]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TOF/AliTOFReconstructioner.cxx
Correcting split lines
[u/mrichter/AliRoot.git] / TOF / AliTOFReconstructioner.cxx
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
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
60 #include "TTask.h"
61 #include "TBenchmark.h"
62 #include "TTree.h"
63 #include "TSystem.h"
64 #include "TFile.h"
65 #include "TParticle.h"
66 #include <TClonesArray.h>
67 #include "TGeant3.h"
68 #include "TVirtualMC.h"
69 #include <TF1.h>
70 #include <TF2.h>
71 #include "TROOT.h"
72 #include "TFolder.h"
73 #include "TNtuple.h"
74 #include <stdlib.h>
75 #include <Riostream.h>
76 #include <Riostream.h>
77
78 ClassImp(AliTOFReconstructioner)
79
80 //____________________________________________________________________________ 
81   AliTOFReconstructioner::AliTOFReconstructioner():TTask("AliTOFReconstructioner","") 
82 {
83   // default ctor
84   fNevents = 0 ; 
85   foutputfile  = 0; 
86   foutputntuple= 0;
87   fZnoise  = 0;
88   ftail    = 0;
89 }
90            
91 //____________________________________________________________________________ 
92   AliTOFReconstructioner::AliTOFReconstructioner(char* headerFile, Option_t* opt, char *RecFile ):TTask("AliTOFReconstructioner","") 
93 {
94   //
95   // ctor
96   //
97   fNevents = 0 ;     // Number of events to reconstruct, 0 means all evens in current file
98   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
119   CreateNTuple();  
120
121   // add Task to //root/Tasks folder
122   TTask * roottasks = (TTask*)gROOT->GetRootFolder()->FindObject("Tasks") ; 
123   roottasks->Add(this) ; 
124 }
125 //____________________________________________________________________________ 
126 void 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   //
215
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 //____________________________________________________________________________
241 void 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 //__________________________________________________________________
292 Double_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 //____________________________________________________________________________
308 void 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
375     Float_t * toftime = new Float_t[fMaxAllTracks]; 
376     InitArray(toftime, fMaxAllTracks);
377     AliTOFPad* pixelArray = new AliTOFPad[fMaxPixels];
378     Int_t* iTOFpixel        = new Int_t[fMaxAllTracks];
379     InitArray(iTOFpixel   , fMaxAllTracks);
380     Int_t* kTOFhitFirst     = new Int_t[fMaxAllTracks];
381     InitArray(kTOFhitFirst, fMaxAllTracks);
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];
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  
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
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;
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
448   // free used memory for ftail
449   if (ftail)
450     {
451       delete ftail;
452       ftail = 0;
453     }
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 //__________________________________________________________________
471 void 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 //__________________________________________________________________
481 void 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 //__________________________________________________________________
495 void 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 //__________________________________________________________________
581 void AliTOFReconstructioner::IsInsideThePad(TVirtualMC *vmc, Float_t x, Float_t y, Float_t z, Int_t *nGeom, Float_t& zPad, Float_t& xPad) 
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   
622   TGeant3 * g3 = (TGeant3*) vmc;
623
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 //__________________________________________________________________
727 void 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 //__________________________________________________________________
778 void 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 //__________________________________________________________________
1062 void 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 //__________________________________________________________________
1345 Int_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 //__________________________________________________________________
1496 Bool_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
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);
1512   
1513   // pad efficiency parameters
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);
1521
1522   // time walk parameters
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);
1529
1530   // ADC-TDC correlation parameters
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);
1538   
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);
1560
1561   if( dummy0 && dummy1 && dummy2 && dummy3 && dummy4)
1562     return kTRUE ;
1563   else
1564     return kFALSE ;
1565
1566 }
1567 //____________________________________________________________________________ 
1568 void AliTOFReconstructioner::UseHitsFrom(const char * filename)
1569 {
1570   SetTitle(filename) ; 
1571 }
1572
1573 //____________________________________________________________________________ 
1574 void 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 //____________________________________________________________________________ 
1586 void 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 //____________________________________________________________________________
1599 void 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)
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)
1620   Int_t * npixel = new Int_t[AliTOFConstants::fgkmaxtoftree]; // array used by TOFRecon for check on TOF geometry
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
1653   // speed-up the code
1654   treehits->SetBranchStatus("*",0); // switch off all branches
1655   treehits->SetBranchStatus("TOF*",1); // switch on only TOF
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;
1694         /* var used for QA
1695         Float_t tofradius = TMath::Sqrt(x*x+y*y); // radius cilindrical coordinate of the TOF hit
1696         */
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 
1702         /* var used for QA
1703         // (>0 for outgoing particles)
1704         Float_t isGoingOut = (x*pxtof+y*pytof+z*pztof)/TMath::Sqrt(x*x+y*y+z*z);
1705         */
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
1765         IsInsideThePad(gMC,x,y,z,npixel,zPad,xPad);
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){
1783           IsInsideThePad(gMC,x,y,z,npixel,zPad,xPad);
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
1906   delete [] npixel;
1907 }
1908
1909 //____________________________________________________________________________
1910 void 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
1917   Float_t * zLen = new Float_t[AliTOFConstants::fgkNPlates+1];
1918   Float_t * zStrips = new Float_t[AliTOFConstants::fgkNPlates];
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
1996       istrip=(Int_t)((zNoise-zLen[iplate-1])/((zLen[iplate]-zLen[iplate-1])/zStrips[iplate-1])); //the strip number in the plate
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); 
2090   delete [] zLen;
2091   delete [] zStrips;
2092   
2093 }
2094
2095
2096 //____________________________________________________________________________
2097 void 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 /*
2137 void 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
2161   // speed-up the code
2162   treehits->SetBranchStatus("*",0); // switch off all branches
2163   treehits->SetBranchStatus("TPC*",1); // switch on only TPC
2164
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 //____________________________________________________________________________
2314 void 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 //____________________________________________________________________________
2327 void 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 {
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];
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();
2391     /* vars used for QA
2392     Float_t RxTPC=x;
2393     Float_t RyTPC=y;
2394     Float_t RzTPC=z;
2395     */
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();
2402     /* vars used for QA
2403     Float_t pxTPC=px;
2404     Float_t pyTPC=py;
2405     Float_t pzTPC=pz;
2406     */
2407     Float_t p = TMath::Sqrt(px*px+py*py+pz*pz);
2408     /* var used for QA
2409     Float_t pTPC=p;
2410     */
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();
2415     /* var used for QA
2416     Float_t phiTPC=phi*kRaddeg;
2417     */
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);
2430     /* var used for QA
2431     Float_t zTPC=z;
2432     */
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         
2630         IsInsideThePad(gMC,gx,gy,gz,npixel,zPad,xPad);
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 {
2762           Int_t k=0;
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
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]);
3001         if(itest) {
3002
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);   
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;
3050   delete [] ntest;
3051   delete [] testPixel;
3052   delete [] testLength;
3053   delete [] testRho;
3054   delete [] testZ;
3055   delete [] testWeight;
3056 }
3057
3058 //____________________________________________________________________________
3059 void 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 }