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