]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TOF/AliTOFSDigitizer.cxx
filter out additional compile defines to fit into rootcints 1024 char limit
[u/mrichter/AliRoot.git] / TOF / AliTOFSDigitizer.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 /* $Id$ */
17
18 //__________________________________________________________//
19 //                                                          //
20 //   This is a TTask that constructs SDigits out of Hits    //
21 //   A Summable Digits is the "sum" of all hits in a pad    //
22 //   Detector response has been simulated via the method    //
23 //   SimulateDetectorResponse                               //
24 //                                                          //
25 //  -- Authors: F. Pierella, A. De Caro                     //
26 //   Use case: see AliTOFhits2sdigits.C macro in the CVS    //
27 //__________________________________________________________//
28
29 #include <TBenchmark.h>
30 #include <TClonesArray.h>
31 #include <TF1.h>
32 #include <TFile.h>
33 #include <TParticle.h>
34 #include <TTree.h>
35 #include <TRandom.h>
36 #include <TROOT.h>
37
38 #include "AliLoader.h"
39 #include "AliLog.h"
40 #include "AliMC.h"
41 #include "AliRunLoader.h"
42 #include "AliRun.h"
43
44 #include "AliTOFGeometry.h"
45 #include "AliTOFHitMap.h"
46 #include "AliTOFhitT0.h"
47 #include "AliTOFhit.h"
48 #include "AliTOFSDigitizer.h"
49 #include "AliTOFSDigit.h"
50 #include "AliTOF.h"
51
52
53 ClassImp(AliTOFSDigitizer)
54
55 //____________________________________________________________________________ 
56 AliTOFSDigitizer::AliTOFSDigitizer():
57   TTask("TOFSDigitizer",""),
58   fEvent1(-1),
59   fEvent2(-1),
60   ftail(0x0),
61   fHeadersFile(""),
62   fRunLoader(0x0),
63   fTOFLoader(0x0),
64   fSelectedSector(-1), 
65   fSelectedPlate(-1),
66   fTimeResolution(0),
67   fpadefficiency(0),
68   fEdgeEffect(-1),
69   fEdgeTails(-1),
70   fHparameter(0),
71   fH2parameter(0),
72   fKparameter(0),
73   fK2parameter(0),
74   fEffCenter(0),
75   fEffBoundary(0),
76   fEff2Boundary(0),
77   fEff3Boundary(0),
78   fAddTRes(0),
79   fResCenter(0),
80   fResBoundary(0),
81   fResSlope(0),
82   fTimeWalkCenter(0),
83   fTimeWalkBoundary(0),
84   fTimeWalkSlope(0),
85   fTimeDelayFlag(-1),
86   fPulseHeightSlope(0),
87   fTimeDelaySlope(0),
88   fMinimumCharge(0),
89   fChargeSmearing(0),
90   fLogChargeSmearing(0),
91   fTimeSmearing(0),
92   fAverageTimeFlag(-1),
93   fAdcBin(0),
94   fAdcMean(0),
95   fAdcRms(0)
96 {
97   // ctor
98 }
99
100 //------------------------------------------------------------------------
101 AliTOFSDigitizer::AliTOFSDigitizer(const AliTOFSDigitizer &source):
102   TTask(source),
103   fEvent1(-1),
104   fEvent2(-1),
105   ftail(0x0),
106   fHeadersFile(""),
107   fRunLoader(0x0),
108   fTOFLoader(0x0),
109   fSelectedSector(-1), 
110   fSelectedPlate(-1),
111   fTimeResolution(0),
112   fpadefficiency(0),
113   fEdgeEffect(-1),
114   fEdgeTails(-1),
115   fHparameter(0),
116   fH2parameter(0),
117   fKparameter(0),
118   fK2parameter(0),
119   fEffCenter(0),
120   fEffBoundary(0),
121   fEff2Boundary(0),
122   fEff3Boundary(0),
123   fAddTRes(0),
124   fResCenter(0),
125   fResBoundary(0),
126   fResSlope(0),
127   fTimeWalkCenter(0),
128   fTimeWalkBoundary(0),
129   fTimeWalkSlope(0),
130   fTimeDelayFlag(-1),
131   fPulseHeightSlope(0),
132   fTimeDelaySlope(0),
133   fMinimumCharge(0),
134   fChargeSmearing(0),
135   fLogChargeSmearing(0),
136   fTimeSmearing(0),
137   fAverageTimeFlag(-1),
138   fAdcBin(0),
139   fAdcMean(0),
140   fAdcRms(0)
141 {
142   // copy constructor
143   //this->fTOFGeometry=source.fTOFGeometry;
144
145 }
146
147 //____________________________________________________________________________ 
148 AliTOFSDigitizer& AliTOFSDigitizer::operator=(const AliTOFSDigitizer &/*source*/)
149 {
150   // ass. op.
151   return *this;
152
153 }
154
155 //____________________________________________________________________________ 
156 AliTOFSDigitizer::AliTOFSDigitizer(const char* HeaderFile, Int_t evNumber1, Int_t nEvents):
157   TTask("TOFSDigitizer",""),
158   fEvent1(-1),
159   fEvent2(-1),
160   ftail(0x0),
161   fHeadersFile(HeaderFile), // input filename (with hits)
162   fRunLoader(0x0),
163   fTOFLoader(0x0),
164   fSelectedSector(-1), // by default we sdigitize all sectors
165   fSelectedPlate(-1),  // by default we sdigitize all plates in all sectors
166   fTimeResolution(0),
167   fpadefficiency(0),
168   fEdgeEffect(-1),
169   fEdgeTails(-1),
170   fHparameter(0),
171   fH2parameter(0),
172   fKparameter(0),
173   fK2parameter(0),
174   fEffCenter(0),
175   fEffBoundary(0),
176   fEff2Boundary(0),
177   fEff3Boundary(0),
178   fAddTRes(0),
179   fResCenter(0),
180   fResBoundary(0),
181   fResSlope(0),
182   fTimeWalkCenter(0),
183   fTimeWalkBoundary(0),
184   fTimeWalkSlope(0),
185   fTimeDelayFlag(-1),
186   fPulseHeightSlope(0),
187   fTimeDelaySlope(0),
188   fMinimumCharge(0),
189   fChargeSmearing(0),
190   fLogChargeSmearing(0),
191   fTimeSmearing(0),
192   fAverageTimeFlag(-1),
193   fAdcBin(0),
194   fAdcMean(0),
195   fAdcRms(0)
196 {
197   //ctor, reading from input file 
198   
199   TFile * file = (TFile*) gROOT->GetFile(fHeadersFile.Data());
200   
201   //File was not opened yet open file and get alirun object
202   if (file == 0) {
203     file   = TFile::Open(fHeadersFile.Data(),"update") ;
204     gAlice = (AliRun *) file->Get("gAlice") ;
205   }
206   
207   // add Task to //root/Tasks folder
208   TString evfoldname = AliConfig::GetDefaultEventFolderName();
209   fRunLoader = AliRunLoader::GetRunLoader(evfoldname);
210   if (!fRunLoader)
211     fRunLoader = AliRunLoader::Open(HeaderFile);//open session and mount on default event folder
212   if (fRunLoader == 0x0)
213     {
214       AliFatal("Event is not loaded. Exiting");
215       return;
216     }
217
218   /*
219   fRunLoader->CdGAFile();
220   TDirectory *savedir=gDirectory;
221   TFile *in=(TFile*)gFile;
222
223    
224 // when fTOFGeometry was needed
225   if (!in->IsOpen()) {
226     AliWarning("Geometry file is not open default TOF geometry will be used");
227     fTOFGeometry = new AliTOFGeometry();
228   }
229   else {
230     in->cd();
231     fTOFGeometry = (AliTOFGeometry*)in->Get("TOFgeometry");
232   }
233   
234   savedir->cd();
235   */
236   if (fRunLoader->TreeE() == 0x0) fRunLoader->LoadHeader();
237   
238   if (evNumber1>=0) fEvent1 = evNumber1;
239   else fEvent1=0;
240   
241   if (nEvents==0) fEvent2 = (Int_t)(fRunLoader->GetNumberOfEvents());
242   else if (nEvents>0) fEvent2 = evNumber1+nEvents;
243   else fEvent2 = 1;
244   
245   if (!(fEvent2>fEvent1)) {
246     AliError(Form("fEvent2 = %d <= fEvent1 = %d", fEvent2, fEvent1));
247     fEvent1 = 0;
248     fEvent2 = 1;
249     AliError(Form("Correction: fEvent2 = %d <= fEvent1 = %d", fEvent2, fEvent1));
250   }
251   
252   // init parameters for sdigitization
253   InitParameters();
254   
255   fTOFLoader = fRunLoader->GetLoader("TOFLoader");
256   if (fTOFLoader == 0x0)
257     {
258       AliFatal("Can not find TOF loader in event. Exiting.");
259       return;
260     }
261   fTOFLoader->PostSDigitizer(this);
262 }
263
264 //____________________________________________________________________________ 
265 AliTOFSDigitizer::~AliTOFSDigitizer()
266 {
267   // dtor
268   fTOFLoader->CleanSDigitizer();
269
270 }
271
272 //____________________________________________________________________________ 
273 void AliTOFSDigitizer::InitParameters()
274 {
275   // set parameters for detector simulation
276   
277   fTimeResolution = 0.080; //0.120; OLD
278   fpadefficiency  = 0.99 ;
279   fEdgeEffect     = 2   ;
280   fEdgeTails      = 0   ;
281   fHparameter     = 0.4 ;
282   fH2parameter    = 0.15;
283   fKparameter     = 0.5 ;
284   fK2parameter    = 0.35;
285   fEffCenter      = fpadefficiency;
286   fEffBoundary    = 0.65;
287   fEff2Boundary   = 0.90;
288   fEff3Boundary   = 0.08;
289   fAddTRes        = 68. ; // \sqrt{2x20^2 + 15^2 + 2x10^2 + 30^2 + 50^2} (p-p)
290   //fAddTRes      = 48. ; // \sqrt{2x20^2 + 15^2 + 2x10^2 + 30^2 + 15^2} (Pb-Pb)
291   // 30^2+20^2+40^2+50^2+50^2+50^2 = 10400 ps^2 (very old value)
292   fResCenter      = 35. ; //50. ; // OLD
293   fResBoundary    = 70. ;
294   fResSlope       = 37. ; //40. ; // OLD
295   fTimeWalkCenter = 0.  ;
296   fTimeWalkBoundary=0.  ;
297   fTimeWalkSlope  = 0.  ;
298   fTimeDelayFlag  = 1   ;
299   fPulseHeightSlope=2.0 ;
300   fTimeDelaySlope =0.060;
301   // was fMinimumCharge = TMath::Exp(fPulseHeightSlope*fKparameter/2.);
302   fMinimumCharge = TMath::Exp(-fPulseHeightSlope*fHparameter);
303   fChargeSmearing=0.0   ;
304   fLogChargeSmearing=0.13;
305   fTimeSmearing   =0.022;
306   fAverageTimeFlag=0    ;
307
308   fAdcBin   = 0.25;    // 1 ADC bin = 0.25 pC (or 0.03 pC)
309   fAdcMean  = 50.;     // ADC distribution mpv value for Landau (in bins)
310                        // it corresponds to a mean value of ~100 bins
311   fAdcRms   = 25.;     // ADC distribution rms value (in bins)
312                        // it corresponds to distribution rms ~50 bins
313 }
314
315 //__________________________________________________________________
316 Double_t TimeWithTail(Double_t* x, Double_t* par)
317 {
318   // sigma - par[0], alpha - par[1], part - par[2]
319   //  at x<part*sigma - gauss
320   //  at x>part*sigma - TMath::Exp(-x/alpha)
321   Float_t xx =x[0];
322   Double_t f;
323   if(xx<par[0]*par[2]) {
324     f = TMath::Exp(-xx*xx/(2*par[0]*par[0]));
325   } else {
326     f = TMath::Exp(-(xx-par[0]*par[2])/par[1]-0.5*par[2]*par[2]);
327   }
328   return f;
329 }
330
331 //____________________________________________________________________________
332 void AliTOFSDigitizer::Exec(Option_t *verboseOption) { 
333   //execute TOF sdigitization
334   if (strstr(verboseOption,"tim") || strstr(verboseOption,"all"))
335     gBenchmark->Start("TOFSDigitizer");
336
337   if (fEdgeTails) ftail = new TF1("tail",TimeWithTail,-2,2,3);
338   
339   Int_t nselectedHits=0;
340   Int_t ntotalsdigits=0;
341   Int_t ntotalupdates=0;
342   Int_t nnoisesdigits=0;
343   Int_t nsignalsdigits=0;
344   Int_t nHitsFromPrim=0;
345   Int_t nHitsFromSec=0;
346   Int_t nlargeTofDiff=0;
347
348   Bool_t thereIsNotASelection=(fSelectedSector==-1) && (fSelectedPlate==-1);
349
350   if (fRunLoader->GetAliRun() == 0x0) fRunLoader->LoadgAlice();
351   gAlice = fRunLoader->GetAliRun();
352
353   fRunLoader->LoadKinematics();
354   
355   AliTOF *tof = (AliTOF *) gAlice->GetDetector("TOF");
356   
357   if (!tof) {
358     AliError("TOF not found");
359     return;
360   }
361   
362   fTOFLoader->LoadHits("read");
363   fTOFLoader->LoadSDigits("recreate");
364   
365   for (Int_t iEvent=fEvent1; iEvent<fEvent2; iEvent++) {
366     //AliInfo(Form("------------------- %s -------------", GetName()));
367     //AliInfo(Form("Sdigitizing event %i", iEvent));
368
369     fRunLoader->GetEvent(iEvent);
370
371     TTree *hitTree = fTOFLoader->TreeH ();
372     if (!hitTree) return;
373
374     if (fTOFLoader->TreeS () == 0) fTOFLoader->MakeTree ("S");
375     
376     //Make branch for digits
377     tof->MakeBranch("S");
378     
379     // recreate TClonesArray fSDigits - for backward compatibility
380     if (tof->SDigits() == 0) {
381       tof->CreateSDigitsArray();
382     } else {
383       tof->RecreateSDigitsArray();
384     }
385
386     tof->SetTreeAddress();
387
388     Int_t version=tof->IsVersion();
389
390     Int_t nselectedHitsinEv=0;
391     Int_t ntotalsdigitsinEv=0;
392     Int_t ntotalupdatesinEv=0;
393     Int_t nnoisesdigitsinEv=0;
394     Int_t nsignalsdigitsinEv=0;
395
396     TParticle *particle;
397     //AliTOFhit *tofHit;
398     TClonesArray *tofHitArray = tof->Hits();
399
400     // create hit map
401     //    AliTOFHitMap *hitMap = new AliTOFHitMap(tof->SDigits(), fTOFGeometry);
402     AliTOFHitMap *hitMap = new AliTOFHitMap(tof->SDigits());
403
404     TBranch * tofHitsBranch = hitTree->GetBranch("TOF");
405
406     Int_t ntracks = static_cast<Int_t>(hitTree->GetEntries());
407     for (Int_t track = 0; track < ntracks; track++)
408     {
409       gAlice->ResetHits();
410       tofHitsBranch->GetEvent(track);
411
412       AliMC *mcApplication = (AliMC*)gAlice->GetMCApp();
413
414       particle = mcApplication->Particle(track);
415       Int_t nhits = tofHitArray->GetEntriesFast();
416       // cleaning all hits of the same track in the same pad volume
417       // it is a rare event, however it happens
418
419       Int_t previousTrack =-1;
420       Int_t previousSector=-1;
421       Int_t previousPlate =-1;
422       Int_t previousStrip =-1;
423       Int_t previousPadX  =-1;
424       Int_t previousPadZ  =-1;
425
426       for (Int_t hit = 0; hit < nhits; hit++) {
427         Int_t    vol[5];       // location for a digit
428         Int_t  digit[2];     // TOF digit variables
429         Int_t tracknum;
430         Float_t dxPad;
431         Float_t dzPad;
432         Float_t geantTime;
433
434         // fp: really sorry for this, it is a temporary trick to have
435         // track length too
436         if (version<6) { //(version!=6 && version!=7)
437           AliTOFhit *tofHit = (AliTOFhit *) tofHitArray->UncheckedAt(hit);
438           tracknum = tofHit->GetTrack();
439           vol[0] = tofHit->GetSector();
440           vol[1] = tofHit->GetPlate();
441           vol[2] = tofHit->GetStrip();
442           vol[3] = tofHit->GetPadx();
443           vol[4] = tofHit->GetPadz();
444           dxPad = tofHit->GetDx();
445           dzPad = tofHit->GetDz();
446           geantTime = tofHit->GetTof(); // unit [s]
447         } else {
448           AliTOFhitT0 *tofHit = (AliTOFhitT0 *) tofHitArray->UncheckedAt(hit);
449           tracknum = tofHit->GetTrack();
450           vol[0] = tofHit->GetSector();
451           vol[1] = tofHit->GetPlate();
452           vol[2] = tofHit->GetStrip();
453           vol[3] = tofHit->GetPadx();
454           vol[4] = tofHit->GetPadz();
455           dxPad = tofHit->GetDx();
456           dzPad = tofHit->GetDz();
457           geantTime = tofHit->GetTof(); // unit [s]
458         }
459         
460         geantTime *= 1.e+09;  // conversion from [s] to [ns]
461         
462         // selection case for sdigitizing only hits in a given plate of a given sector
463         if(thereIsNotASelection || (vol[0]==fSelectedSector && vol[1]==fSelectedPlate)){
464           
465           Bool_t dummy=((tracknum==previousTrack) && (vol[0]==previousSector) && (vol[1]==previousPlate) && (vol[2]==previousStrip));
466           
467           Bool_t isCloneOfThePrevious=dummy && ((vol[3]==previousPadX) && (vol[4]==previousPadZ));
468           
469           Bool_t isNeighOfThePrevious=dummy && ((((vol[3]==previousPadX-1) || (vol[3]==previousPadX+1)) && (vol[4]==previousPadZ)) || ((vol[3]==previousPadX) && ((vol[4]==previousPadZ+1) || (vol[4]==previousPadZ-1))));
470           
471           if(!isCloneOfThePrevious && !isNeighOfThePrevious){
472             // update "previous" values
473             // in fact, we are yet in the future, so the present is past
474             previousTrack=tracknum;
475             previousSector=vol[0];
476             previousPlate=vol[1];
477             previousStrip=vol[2];
478             previousPadX=vol[3];
479             previousPadZ=vol[4];
480             
481             nselectedHits++;
482             nselectedHitsinEv++;
483             if (particle->GetFirstMother() < 0) nHitsFromPrim++; // counts hits due to primary particles
484             
485             Float_t xStrip=AliTOFGeometry::XPad()*(vol[3]+0.5-0.5*AliTOFGeometry::NpadX())+dxPad;
486             Float_t zStrip=AliTOFGeometry::ZPad()*(vol[4]+0.5-0.5*AliTOFGeometry::NpadZ())+dzPad;
487
488             Int_t nActivatedPads = 0, nFiredPads = 0;
489             Bool_t isFired[4] = {kFALSE, kFALSE, kFALSE, kFALSE};
490             Float_t tofAfterSimul[4] = {0., 0., 0., 0.};
491             Float_t qInduced[4] = {0.,0.,0.,0.};
492             Int_t nPlace[4] = {0, 0, 0, 0};
493             Float_t averageTime = 0.;
494             SimulateDetectorResponse(zStrip,xStrip,geantTime,nActivatedPads,nFiredPads,isFired,nPlace,qInduced,tofAfterSimul,averageTime);
495             if(nFiredPads) {
496               for(Int_t indexOfPad=0; indexOfPad<nActivatedPads; indexOfPad++) {
497                 if(isFired[indexOfPad]){ // the pad has fired
498                   Float_t timediff=geantTime-tofAfterSimul[indexOfPad];
499                   
500                   if(timediff>=0.2) nlargeTofDiff++;
501                   
502                   digit[0] = (Int_t) ((tofAfterSimul[indexOfPad]*1.e+03)/AliTOFGeometry::TdcBinWidth()); // TDC bin number (each bin -> 24.4 ps)
503                   
504                   Float_t landauFactor = gRandom->Landau(fAdcMean, fAdcRms); 
505                   digit[1] = (Int_t) (qInduced[indexOfPad] * landauFactor); // ADC bins (each bin -> 0.25 (or 0.03) pC)
506
507                   // recalculate the volume only for neighbouring pads
508                   if(indexOfPad){
509                     (nPlace[indexOfPad]<=AliTOFGeometry::NpadX()) ? vol[4] = 0 : vol[4] = 1;
510                     (nPlace[indexOfPad]<=AliTOFGeometry::NpadX()) ? vol[3] = nPlace[indexOfPad] - 1 : vol[3] = nPlace[indexOfPad] - AliTOFGeometry::NpadX() - 1;
511                   }
512                   // check if two sdigit are on the same pad;
513                   // in that case we sum the two or more sdigits
514                   if (hitMap->TestHit(vol) != kEmpty) {
515                     AliTOFSDigit *sdig = static_cast<AliTOFSDigit*>(hitMap->GetHit(vol));
516                     Int_t tdctime = (Int_t) digit[0];
517                     Int_t adccharge = (Int_t) digit[1];
518                     sdig->Update(AliTOFGeometry::TdcBinWidth(),tdctime,adccharge,tracknum);
519                     ntotalupdatesinEv++;
520                     ntotalupdates++;
521                   } else {
522                     
523                     tof->AddSDigit(tracknum, vol, digit);
524                     
525                     if(indexOfPad){
526                       nnoisesdigits++;
527                       nnoisesdigitsinEv++;
528                     } else {
529                       nsignalsdigits++;
530                       nsignalsdigitsinEv++;
531                     }
532                     ntotalsdigitsinEv++;  
533                     ntotalsdigits++;
534                     hitMap->SetHit(vol);
535                   } // if (hitMap->TestHit(vol) != kEmpty)
536                 } // if(isFired[indexOfPad])
537               } // end loop on nActivatedPads
538             } // if(nFiredPads) i.e. if some pads has fired
539           } // close if(!isCloneOfThePrevious)
540         } // close the selection on sector and plate
541       } // end loop on hits for the current track
542     } // end loop on ntracks
543     
544     delete hitMap;
545     
546     fTOFLoader->TreeS()->Reset();
547     fTOFLoader->TreeS()->Fill();
548     fTOFLoader->WriteSDigits("OVERWRITE");
549     
550     if (tof->SDigits()) tof->ResetSDigits();
551     
552     if (strstr(verboseOption,"all")) {
553       AliInfo("----------------------------------------");
554       AliInfo("       <AliTOFSDigitizer>    ");
555       AliInfo(Form("After sdigitizing %d hits in event %d", nselectedHitsinEv, iEvent));
556       //" (" << nHitsFromPrim << " from primaries and " << nHitsFromSec << " from secondaries) TOF hits, " 
557       AliInfo(Form("%d digits have been created", ntotalsdigitsinEv));
558       AliInfo(Form("(%d due to signals and %d due to border effect)", nsignalsdigitsinEv, nnoisesdigitsinEv));
559       AliInfo(Form("%d total updates of the hit map have been performed in current event", ntotalupdatesinEv));
560       AliInfo("----------------------------------------");
561     }
562
563   } //event loop on events
564
565     fTOFLoader->UnloadSDigits();
566     fTOFLoader->UnloadHits();
567     fRunLoader->UnloadKinematics();
568     //fRunLoader->UnloadgAlice();
569
570   // free used memory
571   if (ftail){
572     delete ftail;
573     ftail = 0;
574   }
575   
576   nHitsFromSec=nselectedHits-nHitsFromPrim;
577   if(strstr(verboseOption,"all")){
578     AliInfo("----------------------------------------");
579     AliInfo("----------------------------------------");
580     AliInfo("-----------SDigitization Summary--------");
581     AliInfo("       <AliTOFSDigitizer>     ");
582     AliInfo(Form("After sdigitizing %d hits", nselectedHits));
583     AliInfo(Form("in %d events", fEvent2-fEvent1));
584 //" (" << nHitsFromPrim << " from primaries and " << nHitsFromSec << " from secondaries) TOF hits, " 
585     AliInfo(Form("%d sdigits have been created", ntotalsdigits));
586     AliInfo(Form("(%d due to signals and " 
587                  "%d due to border effect)", nsignalsdigits, nnoisesdigits));
588     AliInfo(Form("%d total updates of the hit map have been performed", ntotalupdates));
589     AliInfo(Form("in %d cases the time of flight difference is greater than 200 ps", nlargeTofDiff));
590   }
591
592
593   if(strstr(verboseOption,"tim") || strstr(verboseOption,"all")){
594     gBenchmark->Stop("TOFSDigitizer");
595     AliInfo("AliTOFSDigitizer:");
596     AliInfo(Form("   took %f seconds in order to make sdigits " 
597          "%f seconds per event", gBenchmark->GetCpuTime("TOFSDigitizer"), gBenchmark->GetCpuTime("TOFSDigitizer")/(fEvent2-fEvent1)));
598     AliInfo(" +++++++++++++++++++++++++++++++++++++++++++++++++++ ");
599   }
600
601 }
602
603 //__________________________________________________________________
604 void AliTOFSDigitizer::Print(Option_t* /*opt*/)const
605 {
606   AliInfo(Form(" ------------------- %s ------------- ", GetName()));
607 }
608
609 //__________________________________________________________________
610 void AliTOFSDigitizer::SelectSectorAndPlate(Int_t sector, Int_t plate)
611 {
612   //Select sector and plate
613   Bool_t isaWrongSelection=(sector < 0) || (sector >= AliTOFGeometry::NSectors()) || (plate < 0) || (plate >= AliTOFGeometry::NPlates());
614   if(isaWrongSelection){
615     AliError("You have selected an invalid value for sector or plate ");
616     AliError(Form("The correct range for sector is [0,%d]", AliTOFGeometry::NSectors()-1));
617     AliError(Form("The correct range for plate  is [0,%d]",  AliTOFGeometry::NPlates()-1));
618     AliError("By default we continue sdigitizing all hits in all plates of all sectors");
619   } else {
620     fSelectedSector=sector;
621     fSelectedPlate =plate;
622     AliInfo(Form("SDigitizing only hits in plate %d of the sector %d", fSelectedPlate, fSelectedSector));
623   }
624 }
625
626 //__________________________________________________________________
627 void AliTOFSDigitizer::SimulateDetectorResponse(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)
628 {
629   // Description:
630   // Input:  z0, x0 - hit position in the strip system (0,0 - center of the strip), cm
631   //         geantTime - time generated by Geant, ns
632   // Output: nActivatedPads - the number of pads activated by the hit (1 || 2 || 4)
633   //         nFiredPads - the number of pads fired (really activated) by the hit (nFiredPads <= nActivatedPads)
634   //         qInduced[iPad]- charge induced on pad, arb. units
635   //                         this array is initialized at zero by the caller
636   //         tofAfterSimul[iPad] - time calculated with edge effect algorithm, ns
637   //                                   this array is initialized at zero by the caller
638   //         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.
639   //                       The weight is given by the qInduced[iPad]/qCenterPad
640   //                                   this variable is initialized at zero by the caller
641   //         nPlace[iPad] - the number of the pad place, iPad = 0, 1, 2, 3
642   //                                   this variable is initialized at zero by the caller
643   //
644   // Description of used variables:
645   //         eff[iPad] - efficiency of the pad
646   //         res[iPad] - resolution of the pad, ns
647   //         timeWalk[iPad] - time walk of the pad, ns
648   //         timeDelay[iPad] - time delay for neighbouring pad to hited pad, ns
649   //         PadId[iPad] - Pad Identifier
650   //                    E | F    -->   PadId[iPad] = 5 | 6
651   //                    A | B    -->   PadId[iPad] = 1 | 2
652   //                    C | D    -->   PadId[iPad] = 3 | 4
653   //         nTail[iPad] - the tail number, = 1 for tailA, = 2 for tailB
654   //         qCenterPad - charge extimated for each pad, arb. units
655   //         weightsSum - sum of weights extimated for each pad fired, arb. units
656   
657   const Float_t kSigmaForTail[2] = {AliTOFGeometry::SigmaForTail1(),AliTOFGeometry::SigmaForTail2()}; //for tail                                                   
658   Int_t iz = 0, ix = 0;
659   Float_t dX = 0., dZ = 0., x = 0., z = 0.;
660   Float_t h = fHparameter, h2 = fH2parameter, k = fKparameter, k2 = fK2parameter;
661   Float_t effX = 0., effZ = 0., resX = 0., resZ = 0., timeWalkX = 0., timeWalkZ = 0.;
662   Float_t logOfqInd = 0.;
663   Float_t weightsSum = 0.;
664   Int_t nTail[4]  = {0,0,0,0};
665   Int_t padId[4]  = {0,0,0,0};
666   Float_t eff[4]  = {0.,0.,0.,0.};
667   Float_t res[4]  = {0.,0.,0.,0.};
668   //  Float_t qCenterPad = fMinimumCharge * fMinimumCharge;
669   Float_t qCenterPad = 1.;
670   Float_t timeWalk[4]  = {0.,0.,0.,0.};
671   Float_t timeDelay[4] = {0.,0.,0.,0.};
672   
673   nActivatedPads = 0;
674   nFiredPads = 0;
675   
676   (z0 <= 0) ? iz = 0 : iz = 1;
677   dZ = z0 + (0.5 * AliTOFGeometry::NpadZ() - iz - 0.5) * AliTOFGeometry::ZPad(); // hit position in the pad frame, (0,0) - center of the pad
678   z = 0.5 * AliTOFGeometry::ZPad() - TMath::Abs(dZ);                               // variable for eff., res. and timeWalk. functions
679   iz++;                                                                              // z row: 1, ..., AliTOFGeometry::NpadZ = 2
680   ix = (Int_t)((x0 + 0.5 * AliTOFGeometry::NpadX() * AliTOFGeometry::XPad()) / AliTOFGeometry::XPad());
681   dX = x0 + (0.5 * AliTOFGeometry::NpadX() - ix - 0.5) * AliTOFGeometry::XPad(); // hit position in the pad frame, (0,0) - center of the pad
682   x = 0.5 * AliTOFGeometry::XPad() - TMath::Abs(dX);                               // variable for eff., res. and timeWalk. functions;
683   ix++;                                                                              // x row: 1, ..., AliTOFGeometry::NpadX = 48
684   
685   ////// Pad A:
686   nActivatedPads++;
687   nPlace[nActivatedPads-1] = (iz - 1) * AliTOFGeometry::NpadX() + ix;
688   qInduced[nActivatedPads-1] = qCenterPad;
689   padId[nActivatedPads-1] = 1;
690   
691   if (fEdgeEffect == 0) {
692     eff[nActivatedPads-1] = fEffCenter;
693     if (gRandom->Rndm() < eff[nActivatedPads-1]) {
694       nFiredPads = 1;
695       res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + fResCenter * fResCenter); // ns
696       isFired[nActivatedPads-1] = kTRUE;
697       tofTime[nActivatedPads-1] = gRandom->Gaus(geantTime + fTimeWalkCenter, res[0]);
698       averageTime = tofTime[nActivatedPads-1];
699     }
700   } else {
701      
702     if(z < h) {
703       if(z < h2) {
704         effZ = fEffBoundary + (fEff2Boundary - fEffBoundary) * z / h2;
705       } else {
706         effZ = fEff2Boundary + (fEffCenter - fEff2Boundary) * (z - h2) / (h - h2);
707       }
708       resZ = fResBoundary + (fResCenter - fResBoundary) * z / h;
709       timeWalkZ = fTimeWalkBoundary + (fTimeWalkCenter - fTimeWalkBoundary) * z / h;
710       nTail[nActivatedPads-1] = 1;
711     } else {
712       effZ = fEffCenter;
713       resZ = fResCenter;
714       timeWalkZ = fTimeWalkCenter;
715     }
716     
717     if(x < h) {
718       if(x < h2) {
719         effX = fEffBoundary + (fEff2Boundary - fEffBoundary) * x / h2;
720       } else {
721         effX = fEff2Boundary + (fEffCenter - fEff2Boundary) * (x - h2) / (h - h2);
722       }
723       resX = fResBoundary + (fResCenter - fResBoundary) * x / h;
724       timeWalkX = fTimeWalkBoundary + (fTimeWalkCenter - fTimeWalkBoundary) * x / h;
725       nTail[nActivatedPads-1] = 1;
726     } else {
727       effX = fEffCenter;
728       resX = fResCenter;
729       timeWalkX = fTimeWalkCenter;
730     }
731     
732     (effZ<effX) ? eff[nActivatedPads-1] = effZ : eff[nActivatedPads-1] = effX;
733     (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resZ * resZ); // ns
734     (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 *  timeWalkZ : timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
735
736
737     ////// Pad B:
738     if(z < k2) {
739       effZ = fEffBoundary - (fEffBoundary - fEff3Boundary) * (z / k2);
740     } else {
741       effZ = fEff3Boundary * (k - z) / (k - k2);
742     }
743     resZ = fResBoundary + fResSlope * z / k;
744     timeWalkZ = fTimeWalkBoundary + fTimeWalkSlope * z / k;
745     
746     if(z < k && z > 0) {
747       if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
748         nActivatedPads++;
749         nPlace[nActivatedPads-1] = nPlace[0] + (3 - 2 * iz) * AliTOFGeometry::NpadX();
750         eff[nActivatedPads-1] = effZ;
751         res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resZ * resZ); // ns 
752         timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ; // ns
753         nTail[nActivatedPads-1] = 2;
754         if (fTimeDelayFlag) {
755           //      qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
756           //      qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
757           qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * z);
758           logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
759           timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
760         } else {
761           timeDelay[nActivatedPads-1] = 0.;
762         }
763         padId[nActivatedPads-1] = 2;
764       }
765     }
766
767     
768     ////// Pad C, D, E, F:
769     if(x < k2) {
770       effX = fEffBoundary - (fEffBoundary - fEff3Boundary) * (x / k2);
771     } else {
772       effX = fEff3Boundary * (k - x) / (k - k2);
773     }
774     resX = fResBoundary + fResSlope*x/k;
775     timeWalkX = fTimeWalkBoundary + fTimeWalkSlope*x/k;
776     
777     if(x < k && x > 0) {
778       //   C:
779       if(ix > 1 && dX < 0) {
780         nActivatedPads++;
781         nPlace[nActivatedPads-1] = nPlace[0] - 1;
782         eff[nActivatedPads-1] = effX;
783         res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resX * resX); // ns 
784         timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
785         nTail[nActivatedPads-1] = 2;
786         if (fTimeDelayFlag) {
787           //      qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
788           //      qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
789           qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
790           logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
791           timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
792         } else {
793           timeDelay[nActivatedPads-1] = 0.;
794         }
795         padId[nActivatedPads-1] = 3;
796
797         //     D:
798         if(z < k && z > 0) {
799           if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
800             nActivatedPads++;
801             nPlace[nActivatedPads-1] = nPlace[0] + (3 - 2 * iz) * AliTOFGeometry::NpadX() - 1;
802             eff[nActivatedPads-1] = effX * effZ;
803             (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resZ * resZ); // ns
804             (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
805             
806             nTail[nActivatedPads-1] = 2;
807             if (fTimeDelayFlag) {
808               if (TMath::Abs(x) < TMath::Abs(z)) {
809                 //              qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
810                 //              qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
811                 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * z);
812                 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
813               } else {
814                 //              qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
815                 //              qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
816                 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
817                 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
818               }
819               timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
820             } else {
821               timeDelay[nActivatedPads-1] = 0.;
822             }
823             padId[nActivatedPads-1] = 4;
824           }
825         }  // end D
826       }  // end C
827       
828       //   E:
829       if(ix < AliTOFGeometry::NpadX() && dX > 0) {
830         nActivatedPads++;
831         nPlace[nActivatedPads-1] = nPlace[0] + 1;
832         eff[nActivatedPads-1] = effX;
833         res[nActivatedPads-1] = 0.001 * (TMath::Sqrt(fAddTRes*fAddTRes + resX * resX)); // ns
834         timeWalk[nActivatedPads-1] = 0.001 * timeWalkX; // ns
835         nTail[nActivatedPads-1] = 2;
836         if (fTimeDelayFlag) {
837           //      qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
838           //      qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
839           qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
840           logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
841           timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
842         } else {
843           timeDelay[nActivatedPads-1] = 0.;
844         }
845         padId[nActivatedPads-1] = 5;
846
847
848         //     F:
849         if(z < k && z > 0) {
850           if( (iz == 1 && dZ > 0) || (iz == 2 && dZ < 0) ) {
851             nActivatedPads++;
852             nPlace[nActivatedPads - 1] = nPlace[0] + (3 - 2 * iz) * AliTOFGeometry::NpadX() + 1;
853             eff[nActivatedPads - 1] = effX * effZ;
854             (resZ<resX) ? res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resX * resX) : res[nActivatedPads-1] = 0.001 * TMath::Sqrt(fAddTRes*fAddTRes + resZ * resZ); // ns
855             (timeWalkZ<timeWalkX) ? timeWalk[nActivatedPads-1] = 0.001 * timeWalkZ : timeWalk[nActivatedPads-1] = 0.001*timeWalkX; // ns
856             nTail[nActivatedPads-1] = 2;
857             if (fTimeDelayFlag) {
858               if (TMath::Abs(x) < TMath::Abs(z)) {
859                 //              qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * z / 2.);
860                 //              qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * z / 2.);
861                 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * z);
862                 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * z, fLogChargeSmearing);
863               } else {
864                 //              qInduced[0] = fMinimumCharge * TMath::Exp(fPulseHeightSlope * x / 2.);
865                 //              qInduced[nActivatedPads-1] = fMinimumCharge * TMath::Exp(-fPulseHeightSlope * x / 2.);
866                 qInduced[nActivatedPads-1] = TMath::Exp(-fPulseHeightSlope * x);
867                 logOfqInd = gRandom->Gaus(-fPulseHeightSlope * x, fLogChargeSmearing);
868               }
869               timeDelay[nActivatedPads-1] = gRandom->Gaus(-fTimeDelaySlope * logOfqInd, fTimeSmearing);
870             } else {
871               timeDelay[nActivatedPads-1] = 0.;
872             }
873             padId[nActivatedPads-1] = 6;
874           }
875         }  // end F
876       }  // end E
877     } // end if(x < k)
878
879
880     for (Int_t iPad = 0; iPad < nActivatedPads; iPad++) {
881       if (res[iPad] < fTimeResolution) res[iPad] = fTimeResolution;
882       if(gRandom->Rndm() < eff[iPad]) {
883         isFired[iPad] = kTRUE;
884         nFiredPads++;
885         if(fEdgeTails) {
886           if(nTail[iPad] == 0) {
887             tofTime[iPad] = gRandom->Gaus(geantTime + timeWalk[iPad] + timeDelay[iPad], res[iPad]);
888           } else {
889             ftail->SetParameters(res[iPad], 2. * res[iPad], kSigmaForTail[nTail[iPad]-1]);
890             Double_t timeAB = ftail->GetRandom();
891             tofTime[iPad] = geantTime + timeWalk[iPad] + timeDelay[iPad] + timeAB;
892           }
893         } else {
894           tofTime[iPad] = gRandom->Gaus(geantTime + timeWalk[iPad] + timeDelay[iPad], res[iPad]);
895         }
896         if (fAverageTimeFlag) {
897           averageTime += tofTime[iPad] * qInduced[iPad];
898           weightsSum += qInduced[iPad];
899         } else {
900           averageTime += tofTime[iPad];
901           weightsSum += 1.;
902         }
903       }
904     }
905     if (weightsSum!=0) averageTime /= weightsSum;
906   } // end else (fEdgeEffect != 0)
907 }
908
909 //__________________________________________________________________
910 void AliTOFSDigitizer::PrintParameters()const
911 {
912   //
913   // Print parameters used for sdigitization
914   //
915   AliInfo(Form(" ------------------- %s -------------", GetName()));
916   AliInfo(" Parameters used for TOF SDigitization ");
917   //  Printing the parameters
918   
919   AliInfo(Form(" Number of events:                       %i ", (fEvent2-fEvent1)));
920   AliInfo(Form(" from event %i to event %i", fEvent1, (fEvent2-1)));
921   AliInfo(Form(" Time Resolution (ns) %d  Pad Efficiency: %d ", fTimeResolution, fpadefficiency));
922   AliInfo(Form(" Edge Effect option:  %d", fEdgeEffect));
923
924   AliInfo(" Boundary Effect Simulation Parameters ");
925   AliInfo(Form(" Hparameter: %d  H2parameter: %d  Kparameter: %d  K2parameter: %d", fHparameter, fH2parameter, fKparameter, fK2parameter));
926   AliInfo(Form(" Efficiency in the central region of the pad: %d", fEffCenter));
927   AliInfo(Form(" Efficiency at the boundary region of the pad: %d", fEffBoundary));
928   AliInfo(Form(" Efficiency value at H2parameter %d", fEff2Boundary));
929   AliInfo(Form(" Efficiency value at K2parameter %d", fEff3Boundary));
930   AliInfo(Form(" Resolution (ps) in the central region of the pad: %d", fResCenter));
931   AliInfo(Form(" Resolution (ps) at the boundary of the pad      : %d", fResBoundary));
932   AliInfo(Form(" Slope (ps/K) for neighbouring pad               : %d", fResSlope));
933   AliInfo(Form(" Time walk (ps) in the central region of the pad : %d", fTimeWalkCenter));
934   AliInfo(Form(" Time walk (ps) at the boundary of the pad       : %d", fTimeWalkBoundary));
935   AliInfo(Form(" Slope (ps/K) for neighbouring pad               : %d", fTimeWalkSlope));
936   AliInfo(" Pulse Heigth Simulation Parameters ");
937   AliInfo(Form(" Flag for delay due to the PulseHeightEffect  : %d", fTimeDelayFlag));
938   AliInfo(Form(" Pulse Height Slope                           : %d", fPulseHeightSlope));
939   AliInfo(Form(" Time Delay Slope                             : %d", fTimeDelaySlope));
940   AliInfo(Form(" Minimum charge amount which could be induced : %d", fMinimumCharge));
941   AliInfo(Form(" Smearing in charge in (q1/q2) vs x plot      : %d", fChargeSmearing));
942   AliInfo(Form(" Smearing in log of charge ratio              : %d", fLogChargeSmearing));
943   AliInfo(Form(" Smearing in time in time vs log(q1/q2) plot  : %d", fTimeSmearing));
944   AliInfo(Form(" Flag for average time                        : %d", fAverageTimeFlag));
945   AliInfo(Form(" Edge tails option                            : %d", fEdgeTails));
946   
947 }