]>
Commit | Line | Data |
---|---|---|
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 | ////////////////////////////////////////////////////////////////////////////// | |
21 | // Class performs digitization of Summable digits from simulated data | |
22 | // | |
23 | // In addition it performs mixing/embedding of summable digits from different events. | |
24 | // | |
25 | // For each event 3 branches are created in TreeD: | |
26 | // "EMCAL" - list of digits | |
27 | // "EMCALTRG" - list of trigger digits | |
28 | // "AliEMCALDigitizer" - AliEMCALDigitizer with all parameters used in digitization | |
29 | // | |
30 | // | |
31 | //////////////////////////////////////////////////////////////////////////////////// | |
32 | // | |
33 | //*-- Author: Sahal Yacoob (LBL) | |
34 | // based on : AliEMCALDigitizer | |
35 | // Modif: | |
36 | // August 2002 Yves Schutz: clone PHOS as closely as possible and intoduction | |
37 | // of new IO (a la PHOS) | |
38 | // November 2003 Aleksei Pavlinov : adopted for Shish-Kebab geometry | |
39 | // July 2011 GCB: Digitizer modified to accomodate embedding. | |
40 | // Time calibration added. Decalibration possibility of energy and time added | |
41 | //_________________________________________________________________________________ | |
42 | ||
43 | // --- ROOT system --- | |
44 | #include <TROOT.h> | |
45 | #include <TTree.h> | |
46 | #include <TSystem.h> | |
47 | #include <TBenchmark.h> | |
48 | #include <TBrowser.h> | |
49 | #include <TObjectTable.h> | |
50 | #include <TRandom.h> | |
51 | #include <TF1.h> | |
52 | #include <cassert> | |
53 | ||
54 | // --- AliRoot header files --- | |
55 | #include "AliLog.h" | |
56 | #include "AliRun.h" | |
57 | #include "AliDigitizationInput.h" | |
58 | #include "AliRunLoader.h" | |
59 | #include "AliCDBManager.h" | |
60 | #include "AliCDBEntry.h" | |
61 | #include "AliEMCALDigit.h" | |
62 | #include "AliEMCAL.h" | |
63 | #include "AliEMCALLoader.h" | |
64 | #include "AliEMCALDigitizer.h" | |
65 | #include "AliEMCALSDigitizer.h" | |
66 | #include "AliEMCALGeometry.h" | |
67 | #include "AliEMCALCalibData.h" | |
68 | #include "AliEMCALSimParam.h" | |
69 | #include "AliEMCALRawDigit.h" | |
70 | ||
71 | namespace | |
72 | { | |
73 | Double_t HeavisideTheta(Double_t x) | |
74 | { | |
75 | Double_t signal = 0.; | |
76 | ||
77 | if (x > 0.) signal = 1.; | |
78 | ||
79 | return signal; | |
80 | } | |
81 | ||
82 | Double_t AnalogFastORFunction(Double_t *x, Double_t *par) | |
83 | { | |
84 | Double_t v0 = par[0]; | |
85 | Double_t t0 = par[1]; | |
86 | Double_t tr = par[2]; | |
87 | ||
88 | Double_t R1 = 1000.; | |
89 | Double_t C1 = 33e-12; | |
90 | Double_t R2 = 1800; | |
91 | Double_t C2 = 22e-12; | |
92 | ||
93 | Double_t t = x[0]; | |
94 | ||
95 | return (((0.8*(-((TMath::Power(C1,2)*C2*TMath::Power(TMath::E(),(-t + t0)/(C1*R1))* | |
96 | TMath::Power(R1,2)*R2)/(C1*R1 - C2*R2)) + | |
97 | C1*C2*R1*R2*(1 - (C2*TMath::Power(TMath::E(),(-t + t0)/(C2*R2))*R2)/(-(C1*R1) + C2*R2)))*v0* | |
98 | HeavisideTheta(t - t0))/tr | |
99 | - (0.8*(C1*C2*R1*R2 - | |
100 | (TMath::Power(C1,2)*C2*TMath::Power(TMath::E(),(-1.*t + t0 + 1.25*tr)/(C1*R1))* | |
101 | TMath::Power(R1,2)*R2)/(C1*R1 - C2*R2) + | |
102 | (C1*TMath::Power(C2,2)*TMath::Power(TMath::E(),(-1.*t + t0 + 1.25*tr)/(C2*R2))* | |
103 | R1*TMath::Power(R2,2))/(C1*R1 - C2*R2))*v0* | |
104 | HeavisideTheta(t - t0 - 1.25*tr))/tr)/(C2*R1)); | |
105 | } | |
106 | } | |
107 | ||
108 | ClassImp(AliEMCALDigitizer) | |
109 | ||
110 | ||
111 | //____________________________________________________________________________ | |
112 | AliEMCALDigitizer::AliEMCALDigitizer() | |
113 | : AliDigitizer("",""), | |
114 | fDefaultInit(kTRUE), | |
115 | fDigitsInRun(0), | |
116 | fInit(0), | |
117 | fInput(0), | |
118 | fInputFileNames(0x0), | |
119 | fEventNames(0x0), | |
120 | fDigitThreshold(0), | |
121 | fMeanPhotonElectron(0), | |
122 | fGainFluctuations(0), | |
123 | fPinNoise(0), | |
124 | fTimeNoise(0), | |
125 | fTimeDelay(0), | |
126 | fTimeResolutionPar0(0), | |
127 | fTimeResolutionPar1(0), | |
128 | fADCchannelEC(0), | |
129 | fADCpedestalEC(0), | |
130 | fADCchannelECDecal(0), | |
131 | fTimeChannel(0), | |
132 | fTimeChannelDecal(0), | |
133 | fNADCEC(0), | |
134 | fEventFolderName(""), | |
135 | fFirstEvent(0), | |
136 | fLastEvent(0), | |
137 | fCalibData(0x0), | |
138 | fSDigitizer(0x0) | |
139 | { | |
140 | // ctor | |
141 | InitParameters() ; | |
142 | fDigInput = 0 ; // We work in the standalone mode | |
143 | } | |
144 | ||
145 | //____________________________________________________________________________ | |
146 | AliEMCALDigitizer::AliEMCALDigitizer(TString alirunFileName, TString eventFolderName) | |
147 | : AliDigitizer("EMCALDigitizer", alirunFileName), | |
148 | fDefaultInit(kFALSE), | |
149 | fDigitsInRun(0), | |
150 | fInit(0), | |
151 | fInput(0), | |
152 | fInputFileNames(0), | |
153 | fEventNames(0), | |
154 | fDigitThreshold(0), | |
155 | fMeanPhotonElectron(0), | |
156 | fGainFluctuations(0), | |
157 | fPinNoise(0), | |
158 | fTimeNoise(0), | |
159 | fTimeDelay(0), | |
160 | fTimeResolutionPar0(0), | |
161 | fTimeResolutionPar1(0), | |
162 | fADCchannelEC(0), | |
163 | fADCpedestalEC(0), | |
164 | fADCchannelECDecal(0), | |
165 | fTimeChannel(0), | |
166 | fTimeChannelDecal(0), | |
167 | fNADCEC(0), | |
168 | fEventFolderName(eventFolderName), | |
169 | fFirstEvent(0), | |
170 | fLastEvent(0), | |
171 | fCalibData(0x0), | |
172 | fSDigitizer(0x0) | |
173 | { | |
174 | // ctor | |
175 | InitParameters() ; | |
176 | Init() ; | |
177 | fDigInput = 0 ; // We work in the standalone mode | |
178 | } | |
179 | ||
180 | //____________________________________________________________________________ | |
181 | AliEMCALDigitizer::AliEMCALDigitizer(const AliEMCALDigitizer & d) | |
182 | : AliDigitizer(d.GetName(),d.GetTitle()), | |
183 | fDefaultInit(d.fDefaultInit), | |
184 | fDigitsInRun(d.fDigitsInRun), | |
185 | fInit(d.fInit), | |
186 | fInput(d.fInput), | |
187 | fInputFileNames(d.fInputFileNames), | |
188 | fEventNames(d.fEventNames), | |
189 | fDigitThreshold(d.fDigitThreshold), | |
190 | fMeanPhotonElectron(d.fMeanPhotonElectron), | |
191 | fGainFluctuations(d.fGainFluctuations), | |
192 | fPinNoise(d.fPinNoise), | |
193 | fTimeNoise(d.fTimeNoise), | |
194 | fTimeDelay(d.fTimeDelay), | |
195 | fTimeResolutionPar0(d.fTimeResolutionPar0), | |
196 | fTimeResolutionPar1(d.fTimeResolutionPar1), | |
197 | fADCchannelEC(d.fADCchannelEC), | |
198 | fADCpedestalEC(d.fADCpedestalEC), | |
199 | fADCchannelECDecal(d.fADCchannelECDecal), | |
200 | fTimeChannel(d.fTimeChannel), fTimeChannelDecal(d.fTimeChannelDecal), | |
201 | fNADCEC(d.fNADCEC), | |
202 | fEventFolderName(d.fEventFolderName), | |
203 | fFirstEvent(d.fFirstEvent), | |
204 | fLastEvent(d.fLastEvent), | |
205 | fCalibData(d.fCalibData), | |
206 | fSDigitizer(d.fSDigitizer ? new AliEMCALSDigitizer(*d.fSDigitizer) : 0) | |
207 | { | |
208 | // copyy ctor | |
209 | } | |
210 | ||
211 | //____________________________________________________________________________ | |
212 | AliEMCALDigitizer::AliEMCALDigitizer(AliDigitizationInput * rd) | |
213 | : AliDigitizer(rd,"EMCALDigitizer"), | |
214 | fDefaultInit(kFALSE), | |
215 | fDigitsInRun(0), | |
216 | fInit(0), | |
217 | fInput(0), | |
218 | fInputFileNames(0), | |
219 | fEventNames(0), | |
220 | fDigitThreshold(0), | |
221 | fMeanPhotonElectron(0), | |
222 | fGainFluctuations(0), | |
223 | fPinNoise(0.), | |
224 | fTimeNoise(0.), | |
225 | fTimeDelay(0.), | |
226 | fTimeResolutionPar0(0.), | |
227 | fTimeResolutionPar1(0.), | |
228 | fADCchannelEC(0), | |
229 | fADCpedestalEC(0), | |
230 | fADCchannelECDecal(0), | |
231 | fTimeChannel(0), | |
232 | fTimeChannelDecal(0), | |
233 | fNADCEC(0), | |
234 | fEventFolderName(0), | |
235 | fFirstEvent(0), | |
236 | fLastEvent(0), | |
237 | fCalibData(0x0), | |
238 | fSDigitizer(0x0) | |
239 | { | |
240 | // ctor Init() is called by RunDigitizer | |
241 | fDigInput = rd ; | |
242 | fEventFolderName = fDigInput->GetInputFolderName(0) ; | |
243 | SetTitle(dynamic_cast<AliStream*>(fDigInput->GetInputStream(0))->GetFileName(0)); | |
244 | InitParameters() ; | |
245 | } | |
246 | ||
247 | //____________________________________________________________________________ | |
248 | AliEMCALDigitizer::~AliEMCALDigitizer() | |
249 | { | |
250 | //dtor | |
251 | delete [] fInputFileNames ; | |
252 | delete [] fEventNames ; | |
253 | if (fSDigitizer) delete fSDigitizer; | |
254 | } | |
255 | ||
256 | //____________________________________________________________________________ | |
257 | void AliEMCALDigitizer::Digitize(Int_t event) | |
258 | { | |
259 | ||
260 | // Makes the digitization of the collected summable digits | |
261 | // for this it first creates the array of all EMCAL modules | |
262 | // filled with noise and after that adds contributions from | |
263 | // SDigits. This design helps to avoid scanning over the | |
264 | // list of digits to add contribution of any new SDigit. | |
265 | // | |
266 | // JLK 26-Jun-2008 | |
267 | // Note that SDigit energy info is stored as an amplitude, so we | |
268 | // must call the Calibrate() method of the SDigitizer to convert it | |
269 | // back to an energy in GeV before adding it to the Digit | |
270 | // | |
271 | static int nEMC=0; //max number of digits possible | |
272 | AliRunLoader *rl = AliRunLoader::Instance(); | |
273 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL")); | |
274 | ||
275 | if(emcalLoader){ | |
276 | Int_t readEvent = event ; | |
277 | // fDigInput is data member from AliDigitizer | |
278 | if (fDigInput) | |
279 | readEvent = dynamic_cast<AliStream*>(fDigInput->GetInputStream(0))->GetCurrentEventNumber() ; | |
280 | AliDebug(1,Form("Adding event %d from input stream 0 %s %s", | |
281 | readEvent, GetTitle(), fEventFolderName.Data())) ; | |
282 | rl->GetEvent(readEvent); | |
283 | ||
284 | TClonesArray * digits = emcalLoader->Digits() ; | |
285 | digits->Delete() ; //correct way to clear array when memory is | |
286 | //allocated by objects stored in array | |
287 | ||
288 | // Load Geometry | |
289 | AliEMCALGeometry *geom = 0; | |
290 | if (!rl->GetAliRun()) { | |
291 | AliFatal("Could not get AliRun from runLoader"); | |
292 | } | |
293 | else{ | |
294 | AliEMCAL * emcal = (AliEMCAL*)rl->GetAliRun()->GetDetector("EMCAL"); | |
295 | geom = emcal->GetGeometry(); | |
296 | nEMC = geom->GetNCells(); | |
297 | AliDebug(1,Form("nEMC %i (number cells in EMCAL) | %s \n", nEMC, geom->GetName())); | |
298 | } | |
299 | ||
300 | Int_t absID = -1 ; | |
301 | ||
302 | digits->Expand(nEMC) ; | |
303 | ||
304 | // RS create a digitizer on the fly | |
305 | if (!fSDigitizer) fSDigitizer = new AliEMCALSDigitizer(rl->GetFileName().Data()); | |
306 | fSDigitizer->SetEventRange(0, -1) ; | |
307 | // | |
308 | //take all the inputs to add together and load the SDigits | |
309 | TObjArray * sdigArray = new TObjArray(fInput) ; | |
310 | sdigArray->AddAt(emcalLoader->SDigits(), 0) ; | |
311 | Int_t i ; | |
312 | Int_t embed = kFALSE; | |
313 | for(i = 1 ; i < fInput ; i++){ | |
314 | TString tempo(fEventNames[i]) ; | |
315 | tempo += i ; | |
316 | ||
317 | AliRunLoader * rl2 = AliRunLoader::GetRunLoader(tempo) ; | |
318 | ||
319 | if (rl2==0) | |
320 | rl2 = AliRunLoader::Open(fInputFileNames[i], tempo) ; | |
321 | ||
322 | if (fDigInput) | |
323 | readEvent = dynamic_cast<AliStream*>(fDigInput->GetInputStream(i))->GetCurrentEventNumber() ; | |
324 | Info("Digitize", "Adding event %d from input stream %d %s %s", readEvent, i, fInputFileNames[i].Data(), tempo.Data()) ; | |
325 | rl2->LoadSDigits(); | |
326 | // rl2->LoadDigits(); | |
327 | rl2->GetEvent(readEvent); | |
328 | if(rl2->GetDetectorLoader("EMCAL")) | |
329 | { | |
330 | AliEMCALLoader *emcalLoader2 = dynamic_cast<AliEMCALLoader*>(rl2->GetDetectorLoader("EMCAL")); | |
331 | ||
332 | if(emcalLoader2) { | |
333 | //Merge 2 simulated sdigits | |
334 | if(emcalLoader2->SDigits()){ | |
335 | TClonesArray* sdigits2 = emcalLoader2->SDigits(); | |
336 | sdigArray->AddAt(sdigits2, i) ; | |
337 | // Check if first sdigit is of embedded type, if so, handle the sdigits differently: | |
338 | // do not smear energy of embedded, do not add noise to any sdigits | |
339 | if(sdigits2->GetEntriesFast()>0){ | |
340 | //printf("Merged digit type: %d\n",dynamic_cast<AliEMCALDigit*> (sdigits2->At(0))->GetType()); | |
341 | AliEMCALDigit * digit2 = dynamic_cast<AliEMCALDigit*> (sdigits2->At(0)); | |
342 | if(digit2 && digit2->GetType()==AliEMCALDigit::kEmbedded){ | |
343 | embed = kTRUE; | |
344 | } | |
345 | } | |
346 | } | |
347 | ||
348 | }//loader2 | |
349 | else AliFatal("EMCAL Loader of second event not available!"); | |
350 | ||
351 | } | |
352 | else Fatal("Digitize", "Loader of second input not found"); | |
353 | }// input loop | |
354 | ||
355 | //Find the first tower with signal | |
356 | Int_t nextSig = nEMC + 1 ; | |
357 | TClonesArray * sdigits ; | |
358 | for(i = 0 ; i < fInput ; i++){ | |
359 | if(i > 0 && embed) continue; | |
360 | sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ; | |
361 | if(sdigits){ | |
362 | if (sdigits->GetEntriesFast() ){ | |
363 | AliEMCALDigit *sd = dynamic_cast<AliEMCALDigit *>(sdigits->At(0)); | |
364 | if(sd){ | |
365 | Int_t curNext = sd->GetId() ; | |
366 | if(curNext < nextSig) | |
367 | nextSig = curNext ; | |
368 | AliDebug(1,Form("input %i : #sdigits %i \n", | |
369 | i, sdigits->GetEntriesFast())); | |
370 | ||
371 | }//First entry is not NULL | |
372 | else { | |
373 | Info("Digitize", "NULL sdigit pointer"); | |
374 | continue; | |
375 | } | |
376 | }//There is at least one entry | |
377 | else { | |
378 | Info("Digitize", "NULL sdigits array"); | |
379 | continue; | |
380 | } | |
381 | }// SDigits array exists | |
382 | else { | |
383 | Info("Digitizer","Null sdigit pointer"); | |
384 | continue; | |
385 | } | |
386 | }// input loop | |
387 | AliDebug(1,Form("FIRST tower with signal %i \n", nextSig)); | |
388 | ||
389 | TArrayI index(fInput) ; | |
390 | index.Reset() ; //Set all indexes to zero | |
391 | ||
392 | AliEMCALDigit * digit ; | |
393 | AliEMCALDigit * curSDigit ; | |
394 | ||
395 | //Put Noise contribution, smear time and energy | |
396 | Float_t timeResolution = 0; | |
397 | for(absID = 0; absID < nEMC; absID++){ // Nov 30, 2006 by PAI; was from 1 to nEMC | |
398 | Float_t energy = 0 ; | |
399 | ||
400 | // amplitude set to zero, noise will be added later | |
401 | Float_t noiseTime = 0.; | |
402 | if(!embed) noiseTime = TimeOfNoise(); //No need for embedded events? | |
403 | new((*digits)[absID]) AliEMCALDigit( -1, -1, absID, 0., noiseTime,kFALSE); // absID-1->absID | |
404 | //look if we have to add signal? | |
405 | digit = dynamic_cast<AliEMCALDigit *>(digits->At(absID)); // absID-1->absID | |
406 | ||
407 | if (digit) { | |
408 | ||
409 | if(absID==nextSig){ | |
410 | ||
411 | // Calculate time as time of the largest digit | |
412 | Float_t time = digit->GetTime() ; | |
413 | Float_t aTime= digit->GetAmplitude() ; | |
414 | ||
415 | // loop over input | |
416 | Int_t nInputs = fInput; | |
417 | if(embed) nInputs = 1; // In case of embedding, merge later real digits, do not smear energy and time of data | |
418 | for(i = 0; i< nInputs ; i++){ //loop over (possible) merge sources | |
419 | TClonesArray* sdtclarr = dynamic_cast<TClonesArray *>(sdigArray->At(i)); | |
420 | if(sdtclarr) { | |
421 | Int_t sDigitEntries = sdtclarr->GetEntriesFast(); | |
422 | ||
423 | if(sDigitEntries > index[i] ) | |
424 | curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ; | |
425 | else | |
426 | curSDigit = 0 ; | |
427 | ||
428 | //May be several digits will contribute from the same input | |
429 | while(curSDigit && (curSDigit->GetId() == absID)){ | |
430 | //Shift primary to separate primaries belonging different inputs | |
431 | Int_t primaryoffset ; | |
432 | if(fDigInput) | |
433 | primaryoffset = fDigInput->GetMask(i) ; | |
434 | else | |
435 | primaryoffset = i ; | |
436 | curSDigit->ShiftPrimary(primaryoffset) ; | |
437 | ||
438 | if(curSDigit->GetAmplitude()>aTime) { | |
439 | aTime = curSDigit->GetAmplitude(); | |
440 | time = curSDigit->GetTime(); | |
441 | } | |
442 | ||
443 | *digit = *digit + *curSDigit ; //adds amplitudes of each digit | |
444 | ||
445 | index[i]++ ; | |
446 | ||
447 | if( sDigitEntries > index[i] ) | |
448 | curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ; | |
449 | else | |
450 | curSDigit = 0 ; | |
451 | }// while | |
452 | }// source exists | |
453 | }// loop over merging sources | |
454 | ||
455 | ||
456 | //Here we convert the summed amplitude to an energy in GeV only for simulation or mixing of simulations | |
457 | energy = fSDigitizer->Calibrate(digit->GetAmplitude()) ; // GeV | |
458 | ||
459 | // add fluctuations for photo-electron creation | |
460 | // corrected fluctuations after comparison with beam test, Paraskevi Ganoti (06/11/2011) | |
461 | Float_t fluct = static_cast<Float_t>((energy*fMeanPhotonElectron)/fGainFluctuations); | |
462 | energy *= static_cast<Float_t>(gRandom->Poisson(fluct)) / fluct ; | |
463 | ||
464 | //calculate and set time | |
465 | digit->SetTime(time) ; | |
466 | ||
467 | //Find next signal module | |
468 | nextSig = nEMC + 1 ; | |
469 | for(i = 0 ; i < nInputs ; i++){ | |
470 | sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ; | |
471 | ||
472 | if(sdigits){ | |
473 | Int_t curNext = nextSig ; | |
474 | if(sdigits->GetEntriesFast() > index[i]) | |
475 | { | |
476 | AliEMCALDigit * tmpdigit = dynamic_cast<AliEMCALDigit *>(sdigits->At(index[i])); | |
477 | if(tmpdigit) | |
478 | { | |
479 | curNext = tmpdigit->GetId() ; | |
480 | } | |
481 | } | |
482 | if(curNext < nextSig) nextSig = curNext ; | |
483 | }// sdigits exist | |
484 | } // input loop | |
485 | ||
486 | }//absID==nextSig | |
487 | ||
488 | // add the noise now, no need for embedded events with real data | |
489 | if(!embed) | |
490 | energy += TMath::Abs(gRandom->Gaus(0., fPinNoise)) ; | |
491 | ||
492 | ||
493 | // JLK 26-June-2008 | |
494 | //Now digitize the energy according to the fSDigitizer method, | |
495 | //which merely converts the energy to an integer. Later we will | |
496 | //check that the stored value matches our allowed dynamic ranges | |
497 | digit->SetAmplitude(fSDigitizer->Digitize(energy)) ; | |
498 | ||
499 | //Set time resolution with final energy | |
500 | timeResolution = GetTimeResolution(energy); | |
501 | digit->SetTime(gRandom->Gaus(digit->GetTime(),timeResolution) ) ; | |
502 | AliDebug(10,Form(" absID %5i energy %f nextSig %5i\n", | |
503 | absID, energy, nextSig)); | |
504 | //Add delay to time | |
505 | digit->SetTime(digit->GetTime()+fTimeDelay) ; | |
506 | ||
507 | }// Digit pointer exists | |
508 | else{ | |
509 | Info("Digitizer","Digit pointer is null"); | |
510 | } | |
511 | } // for(absID = 0; absID < nEMC; absID++) | |
512 | ||
513 | //ticks->Delete() ; | |
514 | //delete ticks ; | |
515 | ||
516 | //Embed simulated amplitude (and time?) to real data digits | |
517 | if(embed){ | |
518 | for(Int_t input = 1; input<fInput; input++){ | |
519 | TClonesArray *realDigits = dynamic_cast<TClonesArray*> (sdigArray->At(input)); | |
520 | if(!realDigits){ | |
521 | AliDebug(1,"No sdigits to merge\n"); | |
522 | continue; | |
523 | } | |
524 | for(Int_t i2 = 0 ; i2 < realDigits->GetEntriesFast() ; i2++){ | |
525 | AliEMCALDigit * digit2 = dynamic_cast<AliEMCALDigit*>( realDigits->At(i2) ) ; | |
526 | if(digit2){ | |
527 | digit = dynamic_cast<AliEMCALDigit*>( digits->At(digit2->GetId()) ) ; | |
528 | if(digit){ | |
529 | ||
530 | // Put the embedded cell energy in same units as simulated sdigits -> transform to energy units | |
531 | // and multiply to get a big int. | |
532 | Float_t time2 = digit2->GetTime(); | |
533 | Float_t e2 = digit2->GetAmplitude(); | |
534 | CalibrateADCTime(e2,time2,digit2->GetId()); | |
535 | Float_t amp2 = fSDigitizer->Digitize(e2); | |
536 | ||
537 | Float_t e0 = digit ->GetAmplitude(); | |
538 | if(e0>0.01) | |
539 | AliDebug(1,Form("digit 1: Abs ID %d, amp %f, type %d, time %e; digit2: Abs ID %d, amp %f, type %d, time %e\n", | |
540 | digit ->GetId(),digit ->GetAmplitude(), digit ->GetType(), digit->GetTime(), | |
541 | digit2->GetId(),amp2, digit2->GetType(), time2 )); | |
542 | ||
543 | // Sum amplitudes, change digit amplitude | |
544 | digit->SetAmplitude( digit->GetAmplitude() + amp2); | |
545 | // Rough assumption, assign time of the largest of the 2 digits, | |
546 | // data or signal to the final digit. | |
547 | if(amp2 > digit->GetAmplitude()) digit->SetTime(time2); | |
548 | //Mark the new digit as embedded | |
549 | digit->SetType(AliEMCALDigit::kEmbedded); | |
550 | ||
551 | if(digit2->GetAmplitude()>0.01 && e0> 0.01 ) | |
552 | AliDebug(1,Form("Embedded digit: Abs ID %d, amp %f, type %d\n", | |
553 | digit->GetId(), digit->GetAmplitude(), digit->GetType())); | |
554 | }//digit2 | |
555 | }//digit2 | |
556 | }//loop digit 2 | |
557 | }//input loop | |
558 | }//embed | |
559 | ||
560 | //JLK is it better to call Clear() here? | |
561 | delete sdigArray ; //We should not delete its contents | |
562 | ||
563 | //remove digits below thresholds | |
564 | // until 10-02-2010 remove digits with energy smaller than fDigitThreshold 3*fPinNoise | |
565 | // now, remove digits with Digitized ADC smaller than fDigitThreshold = 3, | |
566 | // before merge in the same loop real data digits if available | |
567 | Float_t energy = 0; | |
568 | Float_t time = 0; | |
569 | for(i = 0 ; i < nEMC ; i++){ | |
570 | digit = dynamic_cast<AliEMCALDigit*>( digits->At(i) ) ; | |
571 | if(digit){ | |
572 | ||
573 | //Then get the energy in GeV units. | |
574 | energy = fSDigitizer->Calibrate(digit->GetAmplitude()) ; | |
575 | //Then digitize using the calibration constants of the ocdb | |
576 | Float_t ampADC = energy; | |
577 | DigitizeEnergyTime(ampADC, time, digit->GetId()) ; | |
578 | if(ampADC < fDigitThreshold) | |
579 | digits->RemoveAt(i) ; | |
580 | ||
581 | }// digit exists | |
582 | } // digit loop | |
583 | ||
584 | digits->Compress() ; | |
585 | ||
586 | Int_t ndigits = digits->GetEntriesFast() ; | |
587 | ||
588 | //JLK 26-June-2008 | |
589 | //After we have done the summing and digitizing to create the | |
590 | //digits, now we want to calibrate the resulting amplitude to match | |
591 | //the dynamic range of our real data. | |
592 | for (i = 0 ; i < ndigits ; i++) { | |
593 | digit = dynamic_cast<AliEMCALDigit *>( digits->At(i) ) ; | |
594 | if(digit){ | |
595 | digit->SetIndexInList(i) ; | |
596 | energy = fSDigitizer->Calibrate(digit->GetAmplitude()) ; | |
597 | time = digit->GetTime(); | |
598 | Float_t ampADC = energy; | |
599 | DigitizeEnergyTime(ampADC, time, digit->GetId()); | |
600 | digit->SetAmplitude(ampADC) ; | |
601 | digit->SetTime(time); | |
602 | // printf("digit amplitude set at end: i %d, amp %f\n",i,digit->GetAmplitude()); | |
603 | }// digit exists | |
604 | }//Digit loop | |
605 | ||
606 | } | |
607 | else AliFatal("EMCALLoader is NULL!") ; | |
608 | ||
609 | } | |
610 | ||
611 | //_____________________________________________________________________ | |
612 | void AliEMCALDigitizer::DigitizeEnergyTime(Float_t & energy, Float_t & time, const Int_t absId) | |
613 | { | |
614 | // JLK 26-June-2008 | |
615 | // Returns digitized value of the energy in a cell absId | |
616 | // using the calibration constants stored in the OCDB | |
617 | // or default values if no CalibData object is found. | |
618 | // This effectively converts everything to match the dynamic range | |
619 | // of the real data we will collect | |
620 | // | |
621 | // Load Geometry | |
622 | const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance(); | |
623 | ||
624 | if (geom==0){ | |
625 | AliFatal("Did not get geometry from EMCALLoader"); | |
626 | return; | |
627 | } | |
628 | ||
629 | Int_t iSupMod = -1; | |
630 | Int_t nModule = -1; | |
631 | Int_t nIphi = -1; | |
632 | Int_t nIeta = -1; | |
633 | Int_t iphi = -1; | |
634 | Int_t ieta = -1; | |
635 | Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ; | |
636 | if(!bCell) | |
637 | Error("DigitizeEnergyTime","Wrong cell id number : absId %i ", absId) ; | |
638 | geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta); | |
639 | ||
640 | if(fCalibData) { | |
641 | fADCpedestalEC = fCalibData->GetADCpedestal (iSupMod,ieta,iphi); | |
642 | fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi); | |
643 | fADCchannelECDecal = fCalibData->GetADCchannelDecal (iSupMod,ieta,iphi); | |
644 | fTimeChannel = fCalibData->GetTimeChannel (iSupMod,ieta,iphi); | |
645 | fTimeChannelDecal = fCalibData->GetTimeChannelDecal(iSupMod,ieta,iphi); | |
646 | } | |
647 | ||
648 | //Apply calibration to get ADC counts and partial decalibration as especified in OCDB | |
649 | energy = (energy + fADCpedestalEC)/fADCchannelEC/fADCchannelECDecal ; | |
650 | time += fTimeChannel-fTimeChannelDecal; | |
651 | ||
652 | if(energy > fNADCEC ) | |
653 | energy = fNADCEC ; | |
654 | } | |
655 | ||
656 | //_____________________________________________________________________ | |
657 | void AliEMCALDigitizer::CalibrateADCTime(Float_t & adc, Float_t & time, const Int_t absId) | |
658 | { | |
659 | // Returns the energy in a cell absId with a given adc value | |
660 | // using the calibration constants stored in the OCDB. Time also corrected from parameter in OCDB | |
661 | // Used in case of embedding, transform ADC counts from real event into energy | |
662 | // so that we can add the energy of the simulated sdigits which are in energy | |
663 | // units. | |
664 | // Same as in AliEMCALClusterizer::Calibrate() but here we do not reject channels being marked as hot | |
665 | // or with time out of window | |
666 | ||
667 | // Load Geometry | |
668 | const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance(); | |
669 | ||
670 | if (!geom){ | |
671 | AliFatal("Did not get geometry from EMCALLoader"); | |
672 | return; | |
673 | } | |
674 | ||
675 | Int_t iSupMod = -1; | |
676 | Int_t nModule = -1; | |
677 | Int_t nIphi = -1; | |
678 | Int_t nIeta = -1; | |
679 | Int_t iphi = -1; | |
680 | Int_t ieta = -1; | |
681 | Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ; | |
682 | if(!bCell) | |
683 | Error("CalibrateADCTime","Wrong cell id number : absId %i ", absId) ; | |
684 | geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta); | |
685 | ||
686 | if(fCalibData) { | |
687 | fADCpedestalEC = fCalibData->GetADCpedestal(iSupMod,ieta,iphi); | |
688 | fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi); | |
689 | fTimeChannel = fCalibData->GetTimeChannel(iSupMod,ieta,iphi); | |
690 | } | |
691 | ||
692 | adc = adc * fADCchannelEC - fADCpedestalEC; | |
693 | time -= fTimeChannel; | |
694 | ||
695 | ||
696 | } | |
697 | ||
698 | ||
699 | //____________________________________________________________________________ | |
700 | void AliEMCALDigitizer::Digitize(Option_t *option) | |
701 | { | |
702 | // Steering method to process digitization for events | |
703 | // in the range from fFirstEvent to fLastEvent. | |
704 | // This range is optionally set by SetEventRange(). | |
705 | // if fLastEvent=-1, then process events until the end. | |
706 | // by default fLastEvent = fFirstEvent (process only one event) | |
707 | ||
708 | if (!fInit) { // to prevent overwrite existing file | |
709 | Error( "Digitize", "Give a version name different from %s", fEventFolderName.Data() ) ; | |
710 | return ; | |
711 | } | |
712 | ||
713 | if (strstr(option,"print")) { | |
714 | ||
715 | Print(); | |
716 | return ; | |
717 | } | |
718 | ||
719 | if(strstr(option,"tim")) | |
720 | gBenchmark->Start("EMCALDigitizer"); | |
721 | ||
722 | AliRunLoader *rl = AliRunLoader::Instance(); | |
723 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL")); | |
724 | Int_t nEvents = 0; | |
725 | if(!emcalLoader){ | |
726 | AliFatal("Did not get the Loader"); | |
727 | } | |
728 | else{ | |
729 | ||
730 | if (fLastEvent == -1) { | |
731 | fLastEvent = rl->GetNumberOfEvents() - 1 ; | |
732 | } | |
733 | else if (fDigInput) | |
734 | fLastEvent = fFirstEvent ; // what is this ?? | |
735 | ||
736 | nEvents = fLastEvent - fFirstEvent + 1; | |
737 | Int_t ievent = -1; | |
738 | ||
739 | TClonesArray* digitsTMP = new TClonesArray("AliEMCALDigit", 32*96); | |
740 | TClonesArray* digitsTRG = new TClonesArray("AliEMCALRawDigit", 32*96); | |
741 | ||
742 | rl->LoadSDigits("EMCAL"); | |
743 | for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) { | |
744 | ||
745 | rl->GetEvent(ievent); | |
746 | ||
747 | Digitize(ievent) ; //Add prepared SDigits to digits and add the noise | |
748 | ||
749 | WriteDigits() ; | |
750 | ||
751 | //Trigger Digits | |
752 | //------------------------------------- | |
753 | ||
754 | ||
755 | Digits2FastOR(digitsTMP, digitsTRG); | |
756 | ||
757 | WriteDigits(digitsTRG); | |
758 | ||
759 | (emcalLoader->TreeD())->Fill(); | |
760 | ||
761 | emcalLoader->WriteDigits( "OVERWRITE"); | |
762 | ||
763 | Unload(); | |
764 | ||
765 | digitsTRG ->Delete(); | |
766 | digitsTMP ->Delete(); | |
767 | ||
768 | //------------------------------------- | |
769 | ||
770 | if(strstr(option,"deb")) | |
771 | PrintDigits(option); | |
772 | if(strstr(option,"table")) gObjectTable->Print(); | |
773 | ||
774 | //increment the total number of Digits per run | |
775 | fDigitsInRun += emcalLoader->Digits()->GetEntriesFast() ; | |
776 | }//loop | |
777 | ||
778 | }//loader exists | |
779 | ||
780 | if(strstr(option,"tim")){ | |
781 | gBenchmark->Stop("EMCALDigitizer"); | |
782 | Float_t cputime = gBenchmark->GetCpuTime("EMCALDigitizer"); | |
783 | Float_t avcputime = cputime; | |
784 | if(nEvents==0) avcputime = 0 ; | |
785 | AliInfo(Form("Digitize: took %f seconds for Digitizing %f seconds per event", cputime, avcputime)) ; | |
786 | } | |
787 | } | |
788 | ||
789 | //__________________________________________________________________ | |
790 | Float_t AliEMCALDigitizer::GetTimeResolution(Float_t energy) const | |
791 | { | |
792 | // From F. Blanco | |
793 | Float_t res = -1; | |
794 | if (energy > 0) { | |
795 | res = TMath::Sqrt(fTimeResolutionPar0 + | |
796 | fTimeResolutionPar1/(energy*energy) ); | |
797 | } | |
798 | // parametrization above is for ns. Convert to seconds: | |
799 | return res*1e-9; | |
800 | } | |
801 | ||
802 | //____________________________________________________________________________ | |
803 | void AliEMCALDigitizer::Digits2FastOR(TClonesArray* digitsTMP, TClonesArray* digitsTRG) | |
804 | { | |
805 | // FEE digits afterburner to produce TRG digits | |
806 | // we are only interested in the FEE digit deposited energy | |
807 | // to be converted later into a voltage value | |
808 | ||
809 | // push the FEE digit to its associated FastOR (numbered from 0:95) | |
810 | // TRU is in charge of summing module digits | |
811 | ||
812 | AliRunLoader *runLoader = AliRunLoader::Instance(); | |
813 | ||
814 | AliRun* run = runLoader->GetAliRun(); | |
815 | ||
816 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(runLoader->GetDetectorLoader("EMCAL")); | |
817 | if(!emcalLoader){ | |
818 | AliFatal("Did not get the Loader"); | |
819 | } | |
820 | else { | |
821 | AliEMCAL* emcal = dynamic_cast<AliEMCAL*>(run->GetDetector("EMCAL")); | |
822 | if(emcal){ | |
823 | AliEMCALGeometry* geom = emcal->GetGeometry(); | |
824 | ||
825 | // build FOR from simulated digits | |
826 | // and xfer to the corresponding TRU input (mapping) | |
827 | ||
828 | TClonesArray* digits = emcalLoader->Digits(); | |
829 | ||
830 | TIter NextDigit(digits); | |
831 | while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit()) | |
832 | { | |
833 | Int_t id = digit->GetId(); | |
834 | ||
835 | Int_t trgid; | |
836 | if (geom && geom->GetFastORIndexFromCellIndex(id , trgid)) | |
837 | { | |
838 | AliDebug(1,Form("trigger digit id: %d from cell id: %d\n",trgid,id)); | |
839 | ||
840 | AliEMCALDigit* d = static_cast<AliEMCALDigit*>(digitsTMP->At(trgid)); | |
841 | ||
842 | if (!d) | |
843 | { | |
844 | new((*digitsTMP)[trgid]) AliEMCALDigit(*digit); | |
845 | d = (AliEMCALDigit*)digitsTMP->At(trgid); | |
846 | d->SetId(trgid); | |
847 | } | |
848 | else | |
849 | { | |
850 | *d = *d + *digit; | |
851 | } | |
852 | } | |
853 | } | |
854 | ||
855 | if (AliDebugLevel()) printf("Number of TRG digits: %d\n",digitsTMP->GetEntriesFast()); | |
856 | ||
857 | Int_t nSamples = 32; | |
858 | Int_t *timeSamples = new Int_t[nSamples]; | |
859 | ||
860 | NextDigit = TIter(digitsTMP); | |
861 | while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit()) | |
862 | { | |
863 | if (digit) | |
864 | { | |
865 | Int_t id = digit->GetId(); | |
866 | Float_t time = 50.e-9; | |
867 | ||
868 | Double_t depositedEnergy = 0.; | |
869 | for (Int_t j = 1; j <= digit->GetNprimary(); j++) depositedEnergy += digit->GetDEPrimary(j); | |
870 | ||
871 | if (AliDebugLevel()) printf("Deposited Energy: %f\n", depositedEnergy); | |
872 | ||
873 | // FIXME: Check digit time! | |
874 | if (depositedEnergy) | |
875 | { | |
876 | DigitalFastOR(time, depositedEnergy, timeSamples, nSamples); | |
877 | ||
878 | for (Int_t j=0;j<nSamples;j++) | |
879 | { | |
880 | timeSamples[j] = ((j << 12) & 0xFF000) | (timeSamples[j] & 0xFFF); | |
881 | } | |
882 | ||
883 | new((*digitsTRG)[digitsTRG->GetEntriesFast()]) AliEMCALRawDigit(id, timeSamples, nSamples); | |
884 | } | |
885 | } | |
886 | } | |
887 | ||
888 | delete [] timeSamples; | |
889 | }// AliEMCAL exists | |
890 | else AliFatal("Could not get AliEMCAL"); | |
891 | }// loader exists | |
892 | ||
893 | } | |
894 | ||
895 | //____________________________________________________________________________ | |
896 | void AliEMCALDigitizer::DigitalFastOR( Double_t time, Double_t dE, Int_t timeSamples[], Int_t nSamples ) | |
897 | { | |
898 | // parameters: | |
899 | // id: 0..95 | |
900 | const Int_t reso = 11; // 11-bit resolution ADC | |
901 | const Double_t vFSR = 1; // Full scale input voltage range | |
902 | const Double_t dNe = 125; // signal of the APD per MeV of energy deposit in a tower: 125 photo-e-/MeV @ M=30 | |
903 | const Double_t vA = .136e-6; // CSP output range: 0.136uV/e- | |
904 | const Double_t rise = 40e-9; // rise time (10-90%) of the FastOR signal before shaping | |
905 | ||
906 | const Double_t kTimeBinWidth = 25E-9; // sampling frequency (40MHz) | |
907 | ||
908 | Double_t vV = 1000. * dE * dNe * vA; // GeV 2 MeV | |
909 | ||
910 | TF1 signalF("signal", AnalogFastORFunction, 0, nSamples * kTimeBinWidth, 3); | |
911 | signalF.SetParameter( 0, vV ); | |
912 | signalF.SetParameter( 1, time ); // FIXME: when does the signal arrive? Might account for cable lengths | |
913 | signalF.SetParameter( 2, rise ); | |
914 | ||
915 | for (Int_t iTime=0; iTime<nSamples; iTime++) | |
916 | { | |
917 | // FIXME: add noise (probably not simply Gaussian) according to DA measurements | |
918 | // probably plan an access to OCDB | |
919 | ||
920 | timeSamples[iTime] = int((TMath::Power(2, reso) / vFSR) * signalF.Eval(iTime * kTimeBinWidth) + 0.5); | |
921 | } | |
922 | } | |
923 | ||
924 | //____________________________________________________________________________ | |
925 | Bool_t AliEMCALDigitizer::Init() | |
926 | { | |
927 | // Makes all memory allocations | |
928 | fInit = kTRUE ; | |
929 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL")); | |
930 | ||
931 | if ( emcalLoader == 0 ) { | |
932 | Fatal("Init", "Could not obtain the AliEMCALLoader"); | |
933 | return kFALSE; | |
934 | } | |
935 | ||
936 | fFirstEvent = 0 ; | |
937 | fLastEvent = fFirstEvent ; | |
938 | ||
939 | if(fDigInput) | |
940 | fInput = fDigInput->GetNinputs() ; | |
941 | else | |
942 | fInput = 1 ; | |
943 | ||
944 | fInputFileNames = new TString[fInput] ; | |
945 | fEventNames = new TString[fInput] ; | |
946 | fInputFileNames[0] = GetTitle() ; | |
947 | fEventNames[0] = fEventFolderName.Data() ; | |
948 | Int_t index ; | |
949 | for (index = 1 ; index < fInput ; index++) { | |
950 | fInputFileNames[index] = dynamic_cast<AliStream*>(fDigInput->GetInputStream(index))->GetFileName(0); | |
951 | TString tempo = fDigInput->GetInputFolderName(index) ; | |
952 | fEventNames[index] = tempo.Remove(tempo.Length()-1) ; // strip of the stream number added bt fDigInput | |
953 | } | |
954 | ||
955 | //Calibration instance | |
956 | fCalibData = emcalLoader->CalibData(); | |
957 | return fInit ; | |
958 | } | |
959 | ||
960 | //____________________________________________________________________________ | |
961 | void AliEMCALDigitizer::InitParameters() | |
962 | { | |
963 | // Parameter initialization for digitizer | |
964 | ||
965 | // Get the parameters from the OCDB via the loader | |
966 | AliRunLoader *rl = AliRunLoader::Instance(); | |
967 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL")); | |
968 | AliEMCALSimParam * simParam = 0x0; | |
969 | if(emcalLoader) simParam = emcalLoader->SimulationParameters(); | |
970 | ||
971 | if(!simParam){ | |
972 | simParam = AliEMCALSimParam::GetInstance(); | |
973 | AliWarning("Simulation Parameters not available in OCDB?"); | |
974 | } | |
975 | ||
976 | fMeanPhotonElectron = simParam->GetMeanPhotonElectron() ; // 4400; // electrons per GeV | |
977 | fGainFluctuations = simParam->GetGainFluctuations() ; // 15.0; | |
978 | ||
979 | fPinNoise = simParam->GetPinNoise();//0.012; // pin noise in GeV from analysis test beam data | |
980 | if (fPinNoise < 0.0001 ) | |
981 | Warning("InitParameters", "No noise added\n") ; | |
982 | fTimeNoise = simParam->GetTimeNoise(); // 1.28E-5 s | |
983 | fDigitThreshold = simParam->GetDigitThreshold(); //fPinNoise * 3; // 3 * sigma | |
984 | fTimeResolutionPar0 = simParam->GetTimeResolutionPar0(); | |
985 | fTimeResolutionPar1 = simParam->GetTimeResolutionPar1(); | |
986 | fTimeDelay = simParam->GetTimeDelay(); //600e-9 ; // 600 ns | |
987 | ||
988 | // These defaults are normally not used. | |
989 | // Values are read from calibration database instead | |
990 | fADCchannelEC = 0.0153; // Update 24 Apr 2007: 250./16/1024 - width of one ADC channel in GeV | |
991 | fADCpedestalEC = 0.0 ; // GeV | |
992 | fADCchannelECDecal = 1.0; // No decalibration by default | |
993 | fTimeChannel = 0.0; // No time calibration by default | |
994 | fTimeChannelDecal = 0.0; // No time decalibration by default | |
995 | ||
996 | fNADCEC = simParam->GetNADCEC();//(Int_t) TMath::Power(2,16) ; // number of channels in Tower ADC - 65536 | |
997 | ||
998 | AliDebug(2,Form("Mean Photon Electron %d, Gain Fluct. %2.1f; Noise: APD %f, Time %f; Digit Threshold %d,Time Resolution Par0 %g Par1 %g,NADCEC %d", | |
999 | fMeanPhotonElectron, fGainFluctuations, fPinNoise,fTimeNoise, fDigitThreshold,fTimeResolutionPar0,fTimeResolutionPar1,fNADCEC)); | |
1000 | ||
1001 | } | |
1002 | ||
1003 | //__________________________________________________________________ | |
1004 | void AliEMCALDigitizer::Print1(Option_t * option) | |
1005 | { // 19-nov-04 - just for convenience | |
1006 | Print(); | |
1007 | PrintDigits(option); | |
1008 | } | |
1009 | ||
1010 | //__________________________________________________________________ | |
1011 | void AliEMCALDigitizer::Print (Option_t * ) const | |
1012 | { | |
1013 | // Print Digitizer's parameters | |
1014 | printf("Print: \n------------------- %s -------------", GetName() ) ; | |
1015 | if( strcmp(fEventFolderName.Data(), "") != 0 ){ | |
1016 | printf(" Writing Digits to branch with title %s\n", fEventFolderName.Data()) ; | |
1017 | ||
1018 | Int_t nStreams ; | |
1019 | if (fDigInput) | |
1020 | nStreams = GetNInputStreams() ; | |
1021 | else | |
1022 | nStreams = fInput ; | |
1023 | ||
1024 | AliRunLoader *rl=0; | |
1025 | ||
1026 | Int_t index = 0 ; | |
1027 | for (index = 0 ; index < nStreams ; index++) { | |
1028 | TString tempo(fEventNames[index]) ; | |
1029 | tempo += index ; | |
1030 | if ((rl = AliRunLoader::GetRunLoader(tempo)) == 0) | |
1031 | rl = AliRunLoader::Open(fInputFileNames[index], tempo) ; | |
1032 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL")); | |
1033 | if(emcalLoader){ | |
1034 | TString fileName( emcalLoader->GetSDigitsFileName() ) ; | |
1035 | if ( fEventNames[index] != AliConfig::GetDefaultEventFolderName()) // only if not the default folder name | |
1036 | fileName = fileName.ReplaceAll(".root", "") + "_" + fEventNames[index] + ".root" ; | |
1037 | printf ("Adding SDigits from %s %s\n", fInputFileNames[index].Data(), fileName.Data()) ; | |
1038 | }//loader | |
1039 | } | |
1040 | ||
1041 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL")); | |
1042 | ||
1043 | if(emcalLoader) printf("\nWriting digits to %s", emcalLoader->GetDigitsFileName().Data()) ; | |
1044 | else printf("\nNULL LOADER"); | |
1045 | ||
1046 | printf("\nWith following parameters:\n") ; | |
1047 | printf(" Electronics noise in EMC, APD (fPinNoise) = %f, Time = %f \n", fPinNoise, fTimeNoise) ; | |
1048 | printf(" Threshold in Tower (fDigitThreshold) = %d\n", fDigitThreshold) ; | |
1049 | printf("---------------------------------------------------\n") ; | |
1050 | } | |
1051 | else | |
1052 | printf("Print: AliEMCALDigitizer not initialized") ; | |
1053 | } | |
1054 | ||
1055 | //__________________________________________________________________ | |
1056 | void AliEMCALDigitizer::PrintDigits(Option_t * option) | |
1057 | { | |
1058 | //utility method for printing digit information | |
1059 | ||
1060 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL")); | |
1061 | if(emcalLoader){ | |
1062 | TClonesArray * digits = emcalLoader->Digits() ; | |
1063 | TClonesArray * sdigits = emcalLoader->SDigits() ; | |
1064 | ||
1065 | printf("\n #Digits: %d : sdigits %d ", digits->GetEntriesFast(), sdigits->GetEntriesFast()) ; | |
1066 | printf("\n event %d", emcalLoader->GetRunLoader()->GetEventNumber()); | |
1067 | ||
1068 | if(strstr(option,"all")){ | |
1069 | //loop over digits | |
1070 | AliEMCALDigit * digit; | |
1071 | printf("\nEMC digits (with primaries):\n") ; | |
1072 | printf("\n Id Amplitude Time Index Nprim: Primaries list \n") ; | |
1073 | Int_t index ; | |
1074 | for (index = 0 ; index < digits->GetEntries() ; index++) { | |
1075 | digit = dynamic_cast<AliEMCALDigit *>(digits->At(index)) ; | |
1076 | if(digit){ | |
1077 | printf("\n%6d %8f %6.5e %4d %2d : ", | |
1078 | digit->GetId(), digit->GetAmplitude(), digit->GetTime(), digit->GetIndexInList(), digit->GetNprimary()) ; | |
1079 | Int_t iprimary; | |
1080 | for (iprimary=0; iprimary<digit->GetNprimary(); iprimary++) { | |
1081 | printf("%d ",digit->GetPrimary(iprimary+1) ) ; | |
1082 | } | |
1083 | }// digit exists | |
1084 | }// loop | |
1085 | } | |
1086 | printf("\n"); | |
1087 | }// loader exists | |
1088 | else printf("NULL LOADER, cannot print\n"); | |
1089 | } | |
1090 | ||
1091 | //__________________________________________________________________ | |
1092 | Float_t AliEMCALDigitizer::TimeOfNoise(void) | |
1093 | { | |
1094 | // Calculates the time signal generated by noise | |
1095 | //printf("Time noise %e\n",fTimeNoise); | |
1096 | return gRandom->Rndm() * fTimeNoise; | |
1097 | } | |
1098 | ||
1099 | //__________________________________________________________________ | |
1100 | void AliEMCALDigitizer::Unload() | |
1101 | { | |
1102 | // Unloads the SDigits and Digits | |
1103 | AliRunLoader *rl=0; | |
1104 | ||
1105 | Int_t i ; | |
1106 | for(i = 1 ; i < fInput ; i++){ | |
1107 | TString tempo(fEventNames[i]) ; | |
1108 | tempo += i; | |
1109 | if ((rl = AliRunLoader::GetRunLoader(tempo))) | |
1110 | rl->GetDetectorLoader("EMCAL")->UnloadSDigits() ; | |
1111 | } | |
1112 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL")); | |
1113 | if(emcalLoader)emcalLoader->UnloadDigits() ; | |
1114 | else AliFatal("Did not get the loader"); | |
1115 | } | |
1116 | ||
1117 | //_________________________________________________________________________________________ | |
1118 | void AliEMCALDigitizer::WriteDigits() | |
1119 | { // Makes TreeD in the output file. | |
1120 | // Check if branch already exists: | |
1121 | // if yes, exit without writing: ROOT TTree does not support overwriting/updating of | |
1122 | // already existing branches. | |
1123 | // else creates branch with Digits, named "EMCAL", title "...", | |
1124 | // and branch "AliEMCALDigitizer", with the same title to keep all the parameters | |
1125 | // and names of files, from which digits are made. | |
1126 | ||
1127 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL")); | |
1128 | ||
1129 | if(emcalLoader){ | |
1130 | const TClonesArray * digits = emcalLoader->Digits() ; | |
1131 | TTree * treeD = emcalLoader->TreeD(); | |
1132 | if ( !treeD ) { | |
1133 | emcalLoader->MakeDigitsContainer(); | |
1134 | treeD = emcalLoader->TreeD(); | |
1135 | } | |
1136 | ||
1137 | // -- create Digits branch | |
1138 | Int_t bufferSize = 32000 ; | |
1139 | TBranch * digitsBranch = 0; | |
1140 | if ((digitsBranch = treeD->GetBranch("EMCAL"))) { | |
1141 | digitsBranch->SetAddress(&digits); | |
1142 | AliWarning("Digits Branch already exists. Not all digits will be visible"); | |
1143 | } | |
1144 | else | |
1145 | treeD->Branch("EMCAL","TClonesArray",&digits,bufferSize); | |
1146 | //digitsBranch->SetTitle(fEventFolderName); | |
1147 | ||
1148 | // treeD->Fill() ; | |
1149 | /* | |
1150 | emcalLoader->WriteDigits("OVERWRITE"); | |
1151 | emcalLoader->WriteDigitizer("OVERWRITE"); | |
1152 | ||
1153 | Unload() ; | |
1154 | */ | |
1155 | ||
1156 | }// loader exists | |
1157 | else AliFatal("Loader not available"); | |
1158 | } | |
1159 | ||
1160 | //__________________________________________________________________ | |
1161 | void AliEMCALDigitizer::WriteDigits(TClonesArray* digits, const char* branchName) | |
1162 | { // overloaded method | |
1163 | AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL")); | |
1164 | if(emcalLoader){ | |
1165 | ||
1166 | TTree* treeD = emcalLoader->TreeD(); | |
1167 | if (!treeD) | |
1168 | { | |
1169 | emcalLoader->MakeDigitsContainer(); | |
1170 | treeD = emcalLoader->TreeD(); | |
1171 | } | |
1172 | ||
1173 | // -- create Digits branch | |
1174 | Int_t bufferSize = 32000; | |
1175 | ||
1176 | if (TBranch* triggerBranch = treeD->GetBranch(branchName)) | |
1177 | { | |
1178 | triggerBranch->SetAddress(&digits); | |
1179 | } | |
1180 | else | |
1181 | { | |
1182 | treeD->Branch(branchName,"TClonesArray",&digits,bufferSize); | |
1183 | } | |
1184 | ||
1185 | // treeD->Fill(); | |
1186 | }// loader exists | |
1187 | else AliFatal("Loader not available"); | |
1188 | } | |
1189 |