1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 //_________________________________________________________________________
20 //////////////////////////////////////////////////////////////////////////////
21 // Class performs digitization of Summable digits from simulated data
23 // In addition it performs mixing/embedding of summable digits from different events.
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
31 ////////////////////////////////////////////////////////////////////////////////////
33 //*-- Author: Sahal Yacoob (LBL)
34 // based on : AliEMCALDigitizer
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 //_________________________________________________________________________________
43 // --- ROOT system ---
47 #include <TBenchmark.h>
49 #include <TObjectTable.h>
54 // --- AliRoot header files ---
57 #include "AliRunDigitizer.h"
58 #include "AliRunLoader.h"
59 #include "AliCDBManager.h"
60 #include "AliCDBEntry.h"
61 #include "AliEMCALDigit.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"
73 Double_t HeavisideTheta(Double_t x)
77 if (x > 0.) signal = 1.;
82 Double_t AnalogFastORFunction(Double_t *x, Double_t *par)
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
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));
108 ClassImp(AliEMCALDigitizer)
111 //____________________________________________________________________________
112 AliEMCALDigitizer::AliEMCALDigitizer()
113 : AliDigitizer("",""),
118 fInputFileNames(0x0),
121 fMeanPhotonElectron(0),
125 fTimeResolutionPar0(0),
126 fTimeResolutionPar1(0),
129 fADCchannelECDecal(0),
131 fTimeChannelDecal(0),
133 fEventFolderName(""),
140 fManager = 0 ; // We work in the standalone mode
143 //____________________________________________________________________________
144 AliEMCALDigitizer::AliEMCALDigitizer(TString alirunFileName, TString eventFolderName)
145 : AliDigitizer("EMCAL"+AliConfig::Instance()->GetDigitizerTaskName(), alirunFileName),
146 fDefaultInit(kFALSE),
153 fMeanPhotonElectron(0),
157 fTimeResolutionPar0(0),
158 fTimeResolutionPar1(0),
161 fADCchannelECDecal(0),
163 fTimeChannelDecal(0),
165 fEventFolderName(eventFolderName),
173 fManager = 0 ; // We work in the standalone mode
176 //____________________________________________________________________________
177 AliEMCALDigitizer::AliEMCALDigitizer(const AliEMCALDigitizer & d)
178 : AliDigitizer(d.GetName(),d.GetTitle()),
179 fDefaultInit(d.fDefaultInit),
180 fDigitsInRun(d.fDigitsInRun),
183 fInputFileNames(d.fInputFileNames),
184 fEventNames(d.fEventNames),
185 fDigitThreshold(d.fDigitThreshold),
186 fMeanPhotonElectron(d.fMeanPhotonElectron),
187 fPinNoise(d.fPinNoise),
188 fTimeNoise(d.fTimeNoise),
189 fTimeDelay(d.fTimeDelay),
190 fTimeResolutionPar0(d.fTimeResolutionPar0),
191 fTimeResolutionPar1(d.fTimeResolutionPar1),
192 fADCchannelEC(d.fADCchannelEC),
193 fADCpedestalEC(d.fADCpedestalEC),
194 fADCchannelECDecal(d.fADCchannelECDecal),
195 fTimeChannel(d.fTimeChannel), fTimeChannelDecal(d.fTimeChannelDecal),
197 fEventFolderName(d.fEventFolderName),
198 fFirstEvent(d.fFirstEvent),
199 fLastEvent(d.fLastEvent),
200 fCalibData(d.fCalibData)
205 //____________________________________________________________________________
206 AliEMCALDigitizer::AliEMCALDigitizer(AliRunDigitizer * rd)
207 : AliDigitizer(rd,"EMCAL"+AliConfig::Instance()->GetDigitizerTaskName()),
208 fDefaultInit(kFALSE),
215 fMeanPhotonElectron(0),
219 fTimeResolutionPar0(0.),
220 fTimeResolutionPar1(0.),
223 fADCchannelECDecal(0),
225 fTimeChannelDecal(0),
232 // ctor Init() is called by RunDigitizer
234 fEventFolderName = fManager->GetInputFolderName(0) ;
235 SetTitle(dynamic_cast<AliStream*>(fManager->GetInputStream(0))->GetFileName(0));
239 //____________________________________________________________________________
240 AliEMCALDigitizer::~AliEMCALDigitizer()
243 if (AliRunLoader::Instance()) {
244 AliLoader *emcalLoader=0;
245 if ((emcalLoader = AliRunLoader::Instance()->GetDetectorLoader("EMCAL")))
246 emcalLoader->CleanDigitizer();
249 AliDebug(1," no runloader present");
251 delete [] fInputFileNames ;
252 delete [] fEventNames ;
256 //____________________________________________________________________________
257 void AliEMCALDigitizer::Digitize(Int_t event)
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.
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
271 static int nEMC=0; //max number of digits possible
272 AliRunLoader *rl = AliRunLoader::Instance();
273 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
276 Int_t readEvent = event ;
277 // fManager is data member from AliDigitizer
279 readEvent = dynamic_cast<AliStream*>(fManager->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);
284 TClonesArray * digits = emcalLoader->Digits() ;
285 digits->Delete() ; //correct way to clear array when memory is
286 //allocated by objects stored in array
289 AliEMCALGeometry *geom = 0;
290 if (!rl->GetAliRun()) {
291 AliFatal("Could not get AliRun from runLoader");
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()));
302 digits->Expand(nEMC) ;
304 // get first the sdigitizer from the tasks list (must have same name as the digitizer)
305 if ( !emcalLoader->SDigitizer() )
306 emcalLoader->LoadSDigitizer();
307 AliEMCALSDigitizer * sDigitizer = dynamic_cast<AliEMCALSDigitizer*>(emcalLoader->SDigitizer());
311 Fatal("Digitize", "SDigitizer with name %s %s not found", fEventFolderName.Data(), GetTitle() ) ;
316 //take all the inputs to add together and load the SDigits
317 TObjArray * sdigArray = new TObjArray(fInput) ;
318 sdigArray->AddAt(emcalLoader->SDigits(), 0) ;
320 Int_t embed = kFALSE;
321 for(i = 1 ; i < fInput ; i++){
322 TString tempo(fEventNames[i]) ;
325 AliRunLoader * rl2 = AliRunLoader::GetRunLoader(tempo) ;
328 rl2 = AliRunLoader::Open(fInputFileNames[i], tempo) ;
331 readEvent = dynamic_cast<AliStream*>(fManager->GetInputStream(i))->GetCurrentEventNumber() ;
332 Info("Digitize", "Adding event %d from input stream %d %s %s", readEvent, i, fInputFileNames[i].Data(), tempo.Data()) ;
334 // rl2->LoadDigits();
335 rl2->GetEvent(readEvent);
336 if(rl2->GetDetectorLoader("EMCAL"))
338 AliEMCALLoader *emcalLoader2 = dynamic_cast<AliEMCALLoader*>(rl2->GetDetectorLoader("EMCAL"));
341 //Merge 2 simulated sdigits
342 if(emcalLoader2->SDigits()){
343 TClonesArray* sdigits2 = emcalLoader2->SDigits();
344 sdigArray->AddAt(sdigits2, i) ;
345 // Check if first sdigit is of embedded type, if so, handle the sdigits differently:
346 // do not smear energy of embedded, do not add noise to any sdigits
347 if(sdigits2->GetEntriesFast()>0){
348 //printf("Merged digit type: %d\n",dynamic_cast<AliEMCALDigit*> (sdigits2->At(0))->GetType());
349 AliEMCALDigit * digit2 = dynamic_cast<AliEMCALDigit*> (sdigits2->At(0));
350 if(digit2 && digit2->GetType()==AliEMCALDigit::kEmbedded){
357 else AliFatal("EMCAL Loader of second event not available!");
360 else Fatal("Digitize", "Loader of second input not found");
363 //Find the first tower with signal
364 Int_t nextSig = nEMC + 1 ;
365 TClonesArray * sdigits ;
366 for(i = 0 ; i < fInput ; i++){
367 if(i > 0 && embed) continue;
368 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
370 if (sdigits->GetEntriesFast() ){
371 AliEMCALDigit *sd = dynamic_cast<AliEMCALDigit *>(sdigits->At(0));
373 Int_t curNext = sd->GetId() ;
374 if(curNext < nextSig)
376 AliDebug(1,Form("input %i : #sdigits %i \n",
377 i, sdigits->GetEntriesFast()));
379 }//First entry is not NULL
381 Info("Digitize", "NULL sdigit pointer");
384 }//There is at least one entry
386 Info("Digitize", "NULL sdigits array");
389 }// SDigits array exists
391 Info("Digitizer","Null sdigit pointer");
395 AliDebug(1,Form("FIRST tower with signal %i \n", nextSig));
397 TArrayI index(fInput) ;
398 index.Reset() ; //Set all indexes to zero
400 AliEMCALDigit * digit ;
401 AliEMCALDigit * curSDigit ;
403 //Put Noise contribution, smear time and energy
404 Float_t timeResolution = 0;
405 for(absID = 0; absID < nEMC; absID++){ // Nov 30, 2006 by PAI; was from 1 to nEMC
408 // amplitude set to zero, noise will be added later
409 Float_t noiseTime = 0.;
410 if(!embed) noiseTime = TimeOfNoise(); //No need for embedded events?
411 new((*digits)[absID]) AliEMCALDigit( -1, -1, absID, 0., noiseTime,kFALSE); // absID-1->absID
412 //look if we have to add signal?
413 digit = dynamic_cast<AliEMCALDigit *>(digits->At(absID)); // absID-1->absID
419 // Calculate time as time of the largest digit
420 Float_t time = digit->GetTime() ;
421 Float_t aTime= digit->GetAmplitude() ;
424 Int_t nInputs = fInput;
425 if(embed) nInputs = 1; // In case of embedding, merge later real digits, do not smear energy and time of data
426 for(i = 0; i< nInputs ; i++){ //loop over (possible) merge sources
427 TClonesArray* sdtclarr = dynamic_cast<TClonesArray *>(sdigArray->At(i));
429 Int_t sDigitEntries = sdtclarr->GetEntriesFast();
431 if(sDigitEntries > index[i] )
432 curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ;
436 //May be several digits will contribute from the same input
437 while(curSDigit && (curSDigit->GetId() == absID)){
438 //Shift primary to separate primaries belonging different inputs
439 Int_t primaryoffset ;
441 primaryoffset = fManager->GetMask(i) ;
444 curSDigit->ShiftPrimary(primaryoffset) ;
446 if(curSDigit->GetAmplitude()>aTime) {
447 aTime = curSDigit->GetAmplitude();
448 time = curSDigit->GetTime();
451 *digit = *digit + *curSDigit ; //adds amplitudes of each digit
455 if( sDigitEntries > index[i] )
456 curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ;
461 }// loop over merging sources
464 //Here we convert the summed amplitude to an energy in GeV only for simulation or mixing of simulations
465 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ; // GeV
467 // add fluctuations for photo-electron creation
468 energy *= static_cast<Float_t>(gRandom->Poisson(fMeanPhotonElectron)) / static_cast<Float_t>(fMeanPhotonElectron) ;
470 //calculate and set time
471 digit->SetTime(time) ;
473 //Find next signal module
475 for(i = 0 ; i < nInputs ; i++){
476 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
479 Int_t curNext = nextSig ;
480 if(sdigits->GetEntriesFast() > index[i])
482 AliEMCALDigit * tmpdigit = dynamic_cast<AliEMCALDigit *>(sdigits->At(index[i]));
485 curNext = tmpdigit->GetId() ;
488 if(curNext < nextSig) nextSig = curNext ;
494 // add the noise now, no need for embedded events with real data
496 energy += TMath::Abs(gRandom->Gaus(0., fPinNoise)) ;
500 //Now digitize the energy according to the sDigitizer method,
501 //which merely converts the energy to an integer. Later we will
502 //check that the stored value matches our allowed dynamic ranges
503 digit->SetAmplitude(sDigitizer->Digitize(energy)) ;
505 //Set time resolution with final energy
506 timeResolution = GetTimeResolution(energy);
507 digit->SetTime(gRandom->Gaus(digit->GetTime(),timeResolution) ) ;
508 AliDebug(10,Form(" absID %5i energy %f nextSig %5i\n",
509 absID, energy, nextSig));
511 digit->SetTime(digit->GetTime()+fTimeDelay) ;
513 }// Digit pointer exists
515 Info("Digitizer","Digit pointer is null");
517 } // for(absID = 0; absID < nEMC; absID++)
522 //Embed simulated amplitude (and time?) to real data digits
524 for(Int_t input = 1; input<fInput; input++){
525 TClonesArray *realDigits = dynamic_cast<TClonesArray*> (sdigArray->At(input));
527 AliDebug(1,"No sdigits to merge\n");
530 for(Int_t i2 = 0 ; i2 < realDigits->GetEntriesFast() ; i2++){
531 AliEMCALDigit * digit2 = dynamic_cast<AliEMCALDigit*>( realDigits->At(i2) ) ;
533 digit = dynamic_cast<AliEMCALDigit*>( digits->At(digit2->GetId()) ) ;
536 // Put the embedded cell energy in same units as simulated sdigits -> transform to energy units
537 // and multiply to get a big int.
538 Float_t time2 = digit2->GetTime();
539 Float_t e2 = digit2->GetAmplitude();
540 CalibrateADCTime(e2,time2,digit2->GetId());
541 Float_t amp2 = sDigitizer->Digitize(e2);
543 Float_t e0 = digit ->GetAmplitude();
545 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",
546 digit ->GetId(),digit ->GetAmplitude(), digit ->GetType(), digit->GetTime(),
547 digit2->GetId(),amp2, digit2->GetType(), time2 ));
549 // Sum amplitudes, change digit amplitude
550 digit->SetAmplitude( digit->GetAmplitude() + amp2);
551 // Rough assumption, assign time of the largest of the 2 digits,
552 // data or signal to the final digit.
553 if(amp2 > digit->GetAmplitude()) digit->SetTime(time2);
554 //Mark the new digit as embedded
555 digit->SetType(AliEMCALDigit::kEmbedded);
557 if(digit2->GetAmplitude()>0.01 && e0> 0.01 )
558 AliDebug(1,Form("Embedded digit: Abs ID %d, amp %f, type %d\n",
559 digit->GetId(), digit->GetAmplitude(), digit->GetType()));
566 //JLK is it better to call Clear() here?
567 delete sdigArray ; //We should not delete its contents
569 //remove digits below thresholds
570 // until 10-02-2010 remove digits with energy smaller than fDigitThreshold 3*fPinNoise
571 // now, remove digits with Digitized ADC smaller than fDigitThreshold = 3,
572 // before merge in the same loop real data digits if available
575 for(i = 0 ; i < nEMC ; i++){
576 digit = dynamic_cast<AliEMCALDigit*>( digits->At(i) ) ;
579 //Then get the energy in GeV units.
580 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ;
581 //Then digitize using the calibration constants of the ocdb
582 Float_t ampADC = energy;
583 DigitizeEnergyTime(ampADC, time, digit->GetId()) ;
584 if(ampADC < fDigitThreshold)
585 digits->RemoveAt(i) ;
592 Int_t ndigits = digits->GetEntriesFast() ;
595 //After we have done the summing and digitizing to create the
596 //digits, now we want to calibrate the resulting amplitude to match
597 //the dynamic range of our real data.
598 for (i = 0 ; i < ndigits ; i++) {
599 digit = dynamic_cast<AliEMCALDigit *>( digits->At(i) ) ;
601 digit->SetIndexInList(i) ;
602 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ;
603 time = digit->GetTime();
604 Float_t ampADC = energy;
605 DigitizeEnergyTime(ampADC, time, digit->GetId());
606 digit->SetAmplitude(ampADC) ;
607 digit->SetTime(time);
608 // printf("digit amplitude set at end: i %d, amp %f\n",i,digit->GetAmplitude());
612 }//SDigitizer not null
614 else AliFatal("EMCALLoader is NULL!") ;
618 //_____________________________________________________________________
619 void AliEMCALDigitizer::DigitizeEnergyTime(Float_t & energy, Float_t & time, const Int_t absId)
622 // Returns digitized value of the energy in a cell absId
623 // using the calibration constants stored in the OCDB
624 // or default values if no CalibData object is found.
625 // This effectively converts everything to match the dynamic range
626 // of the real data we will collect
629 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
632 AliFatal("Did not get geometry from EMCALLoader");
642 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
644 Error("DigitizeEnergyTime","Wrong cell id number : absId %i ", absId) ;
645 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
648 fADCpedestalEC = fCalibData->GetADCpedestal (iSupMod,ieta,iphi);
649 fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi);
650 fADCchannelECDecal = fCalibData->GetADCchannelDecal (iSupMod,ieta,iphi);
651 fTimeChannel = fCalibData->GetTimeChannel (iSupMod,ieta,iphi);
652 fTimeChannelDecal = fCalibData->GetTimeChannelDecal(iSupMod,ieta,iphi);
655 //Apply calibration to get ADC counts and partial decalibration as especified in OCDB
656 energy = (energy + fADCpedestalEC)/fADCchannelEC/fADCchannelECDecal ;
657 time += fTimeChannel-fTimeChannelDecal;
659 if(energy > fNADCEC )
663 //_____________________________________________________________________
664 void AliEMCALDigitizer::CalibrateADCTime(Float_t & adc, Float_t & time, const Int_t absId)
666 // Returns the energy in a cell absId with a given adc value
667 // using the calibration constants stored in the OCDB. Time also corrected from parameter in OCDB
668 // Used in case of embedding, transform ADC counts from real event into energy
669 // so that we can add the energy of the simulated sdigits which are in energy
671 // Same as in AliEMCALClusterizer::Calibrate() but here we do not reject channels being marked as hot
672 // or with time out of window
675 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
678 AliFatal("Did not get geometry from EMCALLoader");
688 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
690 Error("CalibrateADCTime","Wrong cell id number : absId %i ", absId) ;
691 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
694 fADCpedestalEC = fCalibData->GetADCpedestal(iSupMod,ieta,iphi);
695 fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi);
696 fTimeChannel = fCalibData->GetTimeChannel(iSupMod,ieta,iphi);
699 adc = adc * fADCchannelEC - fADCpedestalEC;
700 time -= fTimeChannel;
706 //____________________________________________________________________________
707 void AliEMCALDigitizer::Exec(Option_t *option)
709 // Steering method to process digitization for events
710 // in the range from fFirstEvent to fLastEvent.
711 // This range is optionally set by SetEventRange().
712 // if fLastEvent=-1, then process events until the end.
713 // by default fLastEvent = fFirstEvent (process only one event)
715 if (!fInit) { // to prevent overwrite existing file
716 Error( "Exec", "Give a version name different from %s", fEventFolderName.Data() ) ;
720 if (strstr(option,"print")) {
726 if(strstr(option,"tim"))
727 gBenchmark->Start("EMCALDigitizer");
729 AliRunLoader *rl = AliRunLoader::Instance();
730 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
733 AliFatal("Did not get the Loader");
736 // Post Digitizer to the white board
737 emcalLoader->PostDigitizer(this) ;
739 if (fLastEvent == -1) {
740 fLastEvent = rl->GetNumberOfEvents() - 1 ;
743 fLastEvent = fFirstEvent ; // what is this ??
745 nEvents = fLastEvent - fFirstEvent + 1;
748 TClonesArray* digitsTMP = new TClonesArray("AliEMCALDigit", 32*96);
749 TClonesArray* digitsTRG = new TClonesArray("AliEMCALRawDigit", 32*96);
751 rl->LoadSDigits("EMCAL");
752 for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) {
754 rl->GetEvent(ievent);
756 Digitize(ievent) ; //Add prepared SDigits to digits and add the noise
761 //-------------------------------------
764 Digits2FastOR(digitsTMP, digitsTRG);
766 WriteDigits(digitsTRG);
768 (emcalLoader->TreeD())->Fill();
770 emcalLoader->WriteDigits( "OVERWRITE");
771 emcalLoader->WriteDigitizer("OVERWRITE");
775 digitsTRG ->Delete();
776 digitsTMP ->Delete();
778 //-------------------------------------
780 if(strstr(option,"deb"))
782 if(strstr(option,"table")) gObjectTable->Print();
784 //increment the total number of Digits per run
785 fDigitsInRun += emcalLoader->Digits()->GetEntriesFast() ;
788 emcalLoader->CleanDigitizer() ;
792 if(strstr(option,"tim")){
793 gBenchmark->Stop("EMCALDigitizer");
794 AliInfo(Form("Exec: took %f seconds for Digitizing %f seconds per event",
795 gBenchmark->GetCpuTime("EMCALDigitizer"), gBenchmark->GetCpuTime("EMCALDigitizer")/nEvents )) ;
799 //__________________________________________________________________
800 Float_t AliEMCALDigitizer::GetTimeResolution(Float_t energy) const
805 res = TMath::Sqrt(fTimeResolutionPar0 +
806 fTimeResolutionPar1/(energy*energy) );
808 // parametrization above is for ns. Convert to seconds:
812 //____________________________________________________________________________
813 void AliEMCALDigitizer::Digits2FastOR(TClonesArray* digitsTMP, TClonesArray* digitsTRG)
815 // FEE digits afterburner to produce TRG digits
816 // we are only interested in the FEE digit deposited energy
817 // to be converted later into a voltage value
819 // push the FEE digit to its associated FastOR (numbered from 0:95)
820 // TRU is in charge of summing module digits
822 AliRunLoader *runLoader = AliRunLoader::Instance();
824 AliRun* run = runLoader->GetAliRun();
826 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(runLoader->GetDetectorLoader("EMCAL"));
828 AliFatal("Did not get the Loader");
831 AliEMCAL* emcal = dynamic_cast<AliEMCAL*>(run->GetDetector("EMCAL"));
833 AliEMCALGeometry* geom = emcal->GetGeometry();
835 // build FOR from simulated digits
836 // and xfer to the corresponding TRU input (mapping)
838 TClonesArray* digits = emcalLoader->Digits();
840 TIter NextDigit(digits);
841 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
843 Int_t id = digit->GetId();
846 if (geom && geom->GetFastORIndexFromCellIndex(id , trgid))
848 AliDebug(1,Form("trigger digit id: %d from cell id: %d\n",trgid,id));
850 AliEMCALDigit* d = static_cast<AliEMCALDigit*>(digitsTMP->At(trgid));
854 new((*digitsTMP)[trgid]) AliEMCALDigit(*digit);
855 d = (AliEMCALDigit*)digitsTMP->At(trgid);
865 if (AliDebugLevel()) printf("Number of TRG digits: %d\n",digitsTMP->GetEntriesFast());
868 Int_t *timeSamples = new Int_t[nSamples];
870 NextDigit = TIter(digitsTMP);
871 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
875 Int_t id = digit->GetId();
876 Float_t time = digit->GetTime();
878 Double_t depositedEnergy = 0.;
879 for (Int_t j = 1; j <= digit->GetNprimary(); j++) depositedEnergy += digit->GetDEPrimary(j);
881 if (AliDebugLevel()) printf("Deposited Energy: %f\n", depositedEnergy);
883 // FIXME: Check digit time!
886 DigitalFastOR(time, depositedEnergy, timeSamples, nSamples);
888 for (Int_t j=0;j<nSamples;j++)
890 timeSamples[j] = ((j << 12) & 0xFF000) | (timeSamples[j] & 0xFFF);
893 new((*digitsTRG)[digitsTRG->GetEntriesFast()]) AliEMCALRawDigit(id, timeSamples, nSamples);
898 delete [] timeSamples;
900 else AliFatal("Could not get AliEMCAL");
905 //____________________________________________________________________________
906 void AliEMCALDigitizer::DigitalFastOR( Double_t time, Double_t dE, Int_t timeSamples[], Int_t nSamples )
910 const Int_t reso = 11; // 11-bit resolution ADC
911 const Double_t vFSR = 1; // Full scale input voltage range
912 const Double_t dNe = 125; // signal of the APD per MeV of energy deposit in a tower: 125 photo-e-/MeV @ M=30
913 const Double_t vA = .136e-6; // CSP output range: 0.136uV/e-
914 const Double_t rise = 40e-9; // rise time (10-90%) of the FastOR signal before shaping
916 const Double_t kTimeBinWidth = 25E-9; // sampling frequency (40MHz)
918 Double_t vV = 1000. * dE * dNe * vA; // GeV 2 MeV
920 TF1 signalF("signal", AnalogFastORFunction, 0, nSamples * kTimeBinWidth, 3);
921 signalF.SetParameter( 0, vV );
922 signalF.SetParameter( 1, time ); // FIXME: when does the signal arrive? Might account for cable lengths
923 signalF.SetParameter( 2, rise );
925 for (Int_t iTime=0; iTime<nSamples; iTime++)
927 // FIXME: add noise (probably not simply Gaussian) according to DA measurements
928 // probably plan an access to OCDB
930 timeSamples[iTime] = int((TMath::Power(2, reso) / vFSR) * signalF.Eval(iTime * kTimeBinWidth) + 0.5);
934 //____________________________________________________________________________
935 Bool_t AliEMCALDigitizer::Init()
937 // Makes all memory allocations
939 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
941 if ( emcalLoader == 0 ) {
942 Fatal("Init", "Could not obtain the AliEMCALLoader");
947 fLastEvent = fFirstEvent ;
950 fInput = fManager->GetNinputs() ;
954 fInputFileNames = new TString[fInput] ;
955 fEventNames = new TString[fInput] ;
956 fInputFileNames[0] = GetTitle() ;
957 fEventNames[0] = fEventFolderName.Data() ;
959 for (index = 1 ; index < fInput ; index++) {
960 fInputFileNames[index] = dynamic_cast<AliStream*>(fManager->GetInputStream(index))->GetFileName(0);
961 TString tempo = fManager->GetInputFolderName(index) ;
962 fEventNames[index] = tempo.Remove(tempo.Length()-1) ; // strip of the stream number added bt fManager
965 //to prevent cleaning of this object while GetEvent is called
966 emcalLoader->GetDigitsDataLoader()->GetBaseTaskLoader()->SetDoNotReload(kTRUE);
968 //Calibration instance
969 fCalibData = emcalLoader->CalibData();
973 //____________________________________________________________________________
974 void AliEMCALDigitizer::InitParameters()
976 // Parameter initialization for digitizer
978 // Get the parameters from the OCDB via the loader
979 AliRunLoader *rl = AliRunLoader::Instance();
980 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
981 AliEMCALSimParam * simParam = 0x0;
982 if(emcalLoader) simParam = emcalLoader->SimulationParameters();
985 simParam = AliEMCALSimParam::GetInstance();
986 AliWarning("Simulation Parameters not available in OCDB?");
989 fMeanPhotonElectron = simParam->GetMeanPhotonElectron();//4400; // electrons per GeV
990 fPinNoise = simParam->GetPinNoise();//0.012; // pin noise in GeV from analysis test beam data
991 if (fPinNoise < 0.0001 )
992 Warning("InitParameters", "No noise added\n") ;
993 fTimeNoise = simParam->GetTimeNoise(); // 1.28E-5 s
994 fDigitThreshold = simParam->GetDigitThreshold(); //fPinNoise * 3; // 3 * sigma
995 fTimeResolutionPar0 = simParam->GetTimeResolutionPar0();
996 fTimeResolutionPar1 = simParam->GetTimeResolutionPar1();
997 fTimeDelay = simParam->GetTimeDelay(); //600e-9 ; // 600 ns
999 // These defaults are normally not used.
1000 // Values are read from calibration database instead
1001 fADCchannelEC = 0.0153; // Update 24 Apr 2007: 250./16/1024 - width of one ADC channel in GeV
1002 fADCpedestalEC = 0.0 ; // GeV
1003 fADCchannelECDecal = 1.0; // No decalibration by default
1004 fTimeChannel = 0.0; // No time calibration by default
1005 fTimeChannelDecal = 0.0; // No time decalibration by default
1007 fNADCEC = simParam->GetNADCEC();//(Int_t) TMath::Power(2,16) ; // number of channels in Tower ADC - 65536
1009 AliDebug(2,Form("Mean Photon Electron %d, Noise: APD %f, Time %f; Digit Threshold %d,Time Resolution Par0 %g Par1 %g,NADCEC %d",
1010 fMeanPhotonElectron,fPinNoise,fTimeNoise, fDigitThreshold,fTimeResolutionPar0,fTimeResolutionPar1,fNADCEC));
1014 //__________________________________________________________________
1015 void AliEMCALDigitizer::Print1(Option_t * option)
1016 { // 19-nov-04 - just for convenience
1018 PrintDigits(option);
1021 //__________________________________________________________________
1022 void AliEMCALDigitizer::Print (Option_t * ) const
1024 // Print Digitizer's parameters
1025 printf("Print: \n------------------- %s -------------", GetName() ) ;
1026 if( strcmp(fEventFolderName.Data(), "") != 0 ){
1027 printf(" Writing Digits to branch with title %s\n", fEventFolderName.Data()) ;
1031 nStreams = GetNInputStreams() ;
1038 for (index = 0 ; index < nStreams ; index++) {
1039 TString tempo(fEventNames[index]) ;
1041 if ((rl = AliRunLoader::GetRunLoader(tempo)) == 0)
1042 rl = AliRunLoader::Open(fInputFileNames[index], tempo) ;
1043 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
1045 TString fileName( emcalLoader->GetSDigitsFileName() ) ;
1046 if ( fEventNames[index] != AliConfig::GetDefaultEventFolderName()) // only if not the default folder name
1047 fileName = fileName.ReplaceAll(".root", "") + "_" + fEventNames[index] + ".root" ;
1048 printf ("Adding SDigits from %s %s\n", fInputFileNames[index].Data(), fileName.Data()) ;
1052 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1054 if(emcalLoader) printf("\nWriting digits to %s", emcalLoader->GetDigitsFileName().Data()) ;
1055 else printf("\nNULL LOADER");
1057 printf("\nWith following parameters:\n") ;
1058 printf(" Electronics noise in EMC, APD (fPinNoise) = %f, Time = %f \n", fPinNoise, fTimeNoise) ;
1059 printf(" Threshold in Tower (fDigitThreshold) = %d\n", fDigitThreshold) ;
1060 printf("---------------------------------------------------\n") ;
1063 printf("Print: AliEMCALDigitizer not initialized") ;
1066 //__________________________________________________________________
1067 void AliEMCALDigitizer::PrintDigits(Option_t * option)
1069 //utility method for printing digit information
1071 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1073 TClonesArray * digits = emcalLoader->Digits() ;
1074 TClonesArray * sdigits = emcalLoader->SDigits() ;
1076 printf("\n #Digits: %d : sdigits %d ", digits->GetEntriesFast(), sdigits->GetEntriesFast()) ;
1077 printf("\n event %d", emcalLoader->GetRunLoader()->GetEventNumber());
1079 if(strstr(option,"all")){
1081 AliEMCALDigit * digit;
1082 printf("\nEMC digits (with primaries):\n") ;
1083 printf("\n Id Amplitude Time Index Nprim: Primaries list \n") ;
1085 for (index = 0 ; index < digits->GetEntries() ; index++) {
1086 digit = dynamic_cast<AliEMCALDigit *>(digits->At(index)) ;
1088 printf("\n%6d %8f %6.5e %4d %2d : ",
1089 digit->GetId(), digit->GetAmplitude(), digit->GetTime(), digit->GetIndexInList(), digit->GetNprimary()) ;
1091 for (iprimary=0; iprimary<digit->GetNprimary(); iprimary++) {
1092 printf("%d ",digit->GetPrimary(iprimary+1) ) ;
1099 else printf("NULL LOADER, cannot print\n");
1102 //__________________________________________________________________
1103 Float_t AliEMCALDigitizer::TimeOfNoise(void)
1105 // Calculates the time signal generated by noise
1106 //printf("Time noise %e\n",fTimeNoise);
1107 return gRandom->Rndm() * fTimeNoise;
1110 //__________________________________________________________________
1111 void AliEMCALDigitizer::Unload()
1113 // Unloads the SDigits and Digits
1117 for(i = 1 ; i < fInput ; i++){
1118 TString tempo(fEventNames[i]) ;
1120 if ((rl = AliRunLoader::GetRunLoader(tempo)))
1121 rl->GetDetectorLoader("EMCAL")->UnloadSDigits() ;
1123 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1124 if(emcalLoader)emcalLoader->UnloadDigits() ;
1125 else AliFatal("Did not get the loader");
1128 //_________________________________________________________________________________________
1129 void AliEMCALDigitizer::WriteDigits()
1130 { // Makes TreeD in the output file.
1131 // Check if branch already exists:
1132 // if yes, exit without writing: ROOT TTree does not support overwriting/updating of
1133 // already existing branches.
1134 // else creates branch with Digits, named "EMCAL", title "...",
1135 // and branch "AliEMCALDigitizer", with the same title to keep all the parameters
1136 // and names of files, from which digits are made.
1138 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1141 const TClonesArray * digits = emcalLoader->Digits() ;
1142 TTree * treeD = emcalLoader->TreeD();
1144 emcalLoader->MakeDigitsContainer();
1145 treeD = emcalLoader->TreeD();
1148 // -- create Digits branch
1149 Int_t bufferSize = 32000 ;
1150 TBranch * digitsBranch = 0;
1151 if ((digitsBranch = treeD->GetBranch("EMCAL"))) {
1152 digitsBranch->SetAddress(&digits);
1153 AliWarning("Digits Branch already exists. Not all digits will be visible");
1156 treeD->Branch("EMCAL","TClonesArray",&digits,bufferSize);
1157 //digitsBranch->SetTitle(fEventFolderName);
1161 emcalLoader->WriteDigits("OVERWRITE");
1162 emcalLoader->WriteDigitizer("OVERWRITE");
1168 else AliFatal("Loader not available");
1171 //__________________________________________________________________
1172 void AliEMCALDigitizer::WriteDigits(TClonesArray* digits, const char* branchName)
1173 { // overloaded method
1174 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1177 TTree* treeD = emcalLoader->TreeD();
1180 emcalLoader->MakeDigitsContainer();
1181 treeD = emcalLoader->TreeD();
1184 // -- create Digits branch
1185 Int_t bufferSize = 32000;
1187 if (TBranch* triggerBranch = treeD->GetBranch(branchName))
1189 triggerBranch->SetAddress(&digits);
1193 treeD->Branch(branchName,"TClonesArray",&digits,bufferSize);
1198 else AliFatal("Loader not available");