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