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 if(dynamic_cast<AliEMCALDigit*> (sdigits2->At(0))->GetType()==AliEMCALDigit::kEmbedded){
356 else AliFatal("EMCAL Loader of second event not available!");
359 else Fatal("Digitize", "Loader of second input not found");
362 //Find the first tower with signal
363 Int_t nextSig = nEMC + 1 ;
364 TClonesArray * sdigits ;
365 for(i = 0 ; i < fInput ; i++){
366 if(i > 0 && embed) continue;
367 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
369 if (sdigits->GetEntriesFast() ){
370 AliEMCALDigit *sd = dynamic_cast<AliEMCALDigit *>(sdigits->At(0));
372 Int_t curNext = sd->GetId() ;
373 if(curNext < nextSig)
375 AliDebug(1,Form("input %i : #sdigits %i \n",
376 i, sdigits->GetEntriesFast()));
378 }//First entry is not NULL
380 Info("Digitize", "NULL sdigit pointer");
383 }//There is at least one entry
385 Info("Digitize", "NULL sdigits array");
388 }// SDigits array exists
390 Info("Digitizer","Null sdigit pointer");
394 AliDebug(1,Form("FIRST tower with signal %i \n", nextSig));
396 TArrayI index(fInput) ;
397 index.Reset() ; //Set all indexes to zero
399 AliEMCALDigit * digit ;
400 AliEMCALDigit * curSDigit ;
402 //Put Noise contribution, smear time and energy
403 Float_t timeResolution = 0;
404 for(absID = 0; absID < nEMC; absID++){ // Nov 30, 2006 by PAI; was from 1 to nEMC
407 // amplitude set to zero, noise will be added later
408 Float_t noiseTime = 0.;
409 if(!embed) noiseTime = TimeOfNoise(); //No need for embedded events?
410 new((*digits)[absID]) AliEMCALDigit( -1, -1, absID, 0., noiseTime,kFALSE); // absID-1->absID
411 //look if we have to add signal?
412 digit = dynamic_cast<AliEMCALDigit *>(digits->At(absID)); // absID-1->absID
418 // Calculate time as time of the largest digit
419 Float_t time = digit->GetTime() ;
420 Float_t aTime= digit->GetAmplitude() ;
423 Int_t nInputs = fInput;
424 if(embed) nInputs = 1; // In case of embedding, merge later real digits, do not smear energy and time of data
425 for(i = 0; i< nInputs ; i++){ //loop over (possible) merge sources
426 TClonesArray* sdtclarr = dynamic_cast<TClonesArray *>(sdigArray->At(i));
428 Int_t sDigitEntries = sdtclarr->GetEntriesFast();
430 if(sDigitEntries > index[i] )
431 curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ;
435 //May be several digits will contribute from the same input
436 while(curSDigit && (curSDigit->GetId() == absID)){
437 //Shift primary to separate primaries belonging different inputs
438 Int_t primaryoffset ;
440 primaryoffset = fManager->GetMask(i) ;
443 curSDigit->ShiftPrimary(primaryoffset) ;
445 if(curSDigit->GetAmplitude()>aTime) {
446 aTime = curSDigit->GetAmplitude();
447 time = curSDigit->GetTime();
450 *digit = *digit + *curSDigit ; //adds amplitudes of each digit
454 if( sDigitEntries > index[i] )
455 curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ;
460 }// loop over merging sources
463 //Here we convert the summed amplitude to an energy in GeV only for simulation or mixing of simulations
464 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ; // GeV
466 // add fluctuations for photo-electron creation
467 energy *= static_cast<Float_t>(gRandom->Poisson(fMeanPhotonElectron)) / static_cast<Float_t>(fMeanPhotonElectron) ;
469 //calculate and set time
470 digit->SetTime(time) ;
472 //Find next signal module
474 for(i = 0 ; i < nInputs ; i++){
475 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
478 Int_t curNext = nextSig ;
479 if(sdigits->GetEntriesFast() > index[i])
481 AliEMCALDigit * tmpdigit = dynamic_cast<AliEMCALDigit *>(sdigits->At(index[i]));
484 curNext = tmpdigit->GetId() ;
487 if(curNext < nextSig) nextSig = curNext ;
493 // add the noise now, no need for embedded events with real data
495 energy += TMath::Abs(gRandom->Gaus(0., fPinNoise)) ;
499 //Now digitize the energy according to the sDigitizer method,
500 //which merely converts the energy to an integer. Later we will
501 //check that the stored value matches our allowed dynamic ranges
502 digit->SetAmplitude(sDigitizer->Digitize(energy)) ;
504 //Set time resolution with final energy
505 timeResolution = GetTimeResolution(energy);
506 digit->SetTime(gRandom->Gaus(digit->GetTime(),timeResolution) ) ;
507 AliDebug(10,Form(" absID %5i energy %f nextSig %5i\n",
508 absID, energy, nextSig));
510 digit->SetTime(digit->GetTime()+fTimeDelay) ;
512 }// Digit pointer exists
514 Info("Digitizer","Digit pointer is null");
516 } // for(absID = 0; absID < nEMC; absID++)
521 //Embed simulated amplitude (and time?) to real data digits
523 for(Int_t input = 1; input<fInput; input++){
524 TClonesArray *realDigits = dynamic_cast<TClonesArray*> (sdigArray->At(input));
526 AliDebug(1,"No sdigits to merge\n");
529 for(Int_t i2 = 0 ; i2 < realDigits->GetEntriesFast() ; i2++){
530 AliEMCALDigit * digit2 = dynamic_cast<AliEMCALDigit*>( realDigits->At(i2) ) ;
532 digit = dynamic_cast<AliEMCALDigit*>( digits->At(digit2->GetId()) ) ;
535 // Put the embedded cell energy in same units as simulated sdigits -> transform to energy units
536 // and multiply to get a big int.
537 Float_t time2 = digit2->GetTime();
538 Float_t e2 = digit2->GetAmplitude();
539 CalibrateADCTime(e2,time2,digit2->GetId());
540 Float_t amp2 = sDigitizer->Digitize(e2);
542 Float_t e0 = digit ->GetAmplitude();
544 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",
545 digit ->GetId(),digit ->GetAmplitude(), digit ->GetType(), digit->GetTime(),
546 digit2->GetId(),amp2, digit2->GetType(), time2 ));
548 // Sum amplitudes, change digit amplitude
549 digit->SetAmplitude( digit->GetAmplitude() + amp2);
550 // Rough assumption, assign time of the largest of the 2 digits,
551 // data or signal to the final digit.
552 if(amp2 > digit->GetAmplitude()) digit->SetTime(time2);
553 //Mark the new digit as embedded
554 digit->SetType(AliEMCALDigit::kEmbedded);
556 if(digit2->GetAmplitude()>0.01 && e0> 0.01 )
557 AliDebug(1,Form("Embedded digit: Abs ID %d, amp %f, type %d\n",
558 digit->GetId(), digit->GetAmplitude(), digit->GetType()));
565 //JLK is it better to call Clear() here?
566 delete sdigArray ; //We should not delete its contents
568 //remove digits below thresholds
569 // until 10-02-2010 remove digits with energy smaller than fDigitThreshold 3*fPinNoise
570 // now, remove digits with Digitized ADC smaller than fDigitThreshold = 3,
571 // before merge in the same loop real data digits if available
574 for(i = 0 ; i < nEMC ; i++){
575 digit = dynamic_cast<AliEMCALDigit*>( digits->At(i) ) ;
578 //Then get the energy in GeV units.
579 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ;
580 //Then digitize using the calibration constants of the ocdb
581 Float_t ampADC = energy;
582 DigitizeEnergyTime(ampADC, time, digit->GetId()) ;
583 if(ampADC < fDigitThreshold)
584 digits->RemoveAt(i) ;
591 Int_t ndigits = digits->GetEntriesFast() ;
594 //After we have done the summing and digitizing to create the
595 //digits, now we want to calibrate the resulting amplitude to match
596 //the dynamic range of our real data.
597 for (i = 0 ; i < ndigits ; i++) {
598 digit = dynamic_cast<AliEMCALDigit *>( digits->At(i) ) ;
600 digit->SetIndexInList(i) ;
601 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ;
602 time = digit->GetTime();
603 Float_t ampADC = energy;
604 DigitizeEnergyTime(ampADC, time, digit->GetId());
605 digit->SetAmplitude(ampADC) ;
606 digit->SetTime(time);
607 // printf("digit amplitude set at end: i %d, amp %f\n",i,digit->GetAmplitude());
611 }//SDigitizer not null
613 else AliFatal("EMCALLoader is NULL!") ;
617 //_____________________________________________________________________
618 void AliEMCALDigitizer::DigitizeEnergyTime(Float_t & energy, Float_t & time, const Int_t absId)
621 // Returns digitized value of the energy in a cell absId
622 // using the calibration constants stored in the OCDB
623 // or default values if no CalibData object is found.
624 // This effectively converts everything to match the dynamic range
625 // of the real data we will collect
628 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
631 AliFatal("Did not get geometry from EMCALLoader");
641 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
643 Error("DigitizeEnergyTime","Wrong cell id number : absId %i ", absId) ;
644 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
647 fADCpedestalEC = fCalibData->GetADCpedestal (iSupMod,ieta,iphi);
648 fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi);
649 fADCchannelECDecal = fCalibData->GetADCchannelDecal (iSupMod,ieta,iphi);
650 fTimeChannel = fCalibData->GetTimeChannel (iSupMod,ieta,iphi);
651 fTimeChannelDecal = fCalibData->GetTimeChannelDecal(iSupMod,ieta,iphi);
654 //Apply calibration to get ADC counts and partial decalibration as especified in OCDB
655 energy = (energy + fADCpedestalEC)/fADCchannelEC/fADCchannelECDecal ;
656 time += fTimeChannel-fTimeChannelDecal;
658 if(energy > fNADCEC )
662 //_____________________________________________________________________
663 void AliEMCALDigitizer::CalibrateADCTime(Float_t & adc, Float_t & time, const Int_t absId)
665 // Returns the energy in a cell absId with a given adc value
666 // using the calibration constants stored in the OCDB. Time also corrected from parameter in OCDB
667 // Used in case of embedding, transform ADC counts from real event into energy
668 // so that we can add the energy of the simulated sdigits which are in energy
670 // Same as in AliEMCALClusterizer::Calibrate() but here we do not reject channels being marked as hot
671 // or with time out of window
674 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
677 AliFatal("Did not get geometry from EMCALLoader");
687 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
689 Error("CalibrateADCTime","Wrong cell id number : absId %i ", absId) ;
690 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
693 fADCpedestalEC = fCalibData->GetADCpedestal(iSupMod,ieta,iphi);
694 fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi);
695 fTimeChannel = fCalibData->GetTimeChannel(iSupMod,ieta,iphi);
698 adc = adc * fADCchannelEC - fADCpedestalEC;
699 time -= fTimeChannel;
705 //____________________________________________________________________________
706 void AliEMCALDigitizer::Exec(Option_t *option)
708 // Steering method to process digitization for events
709 // in the range from fFirstEvent to fLastEvent.
710 // This range is optionally set by SetEventRange().
711 // if fLastEvent=-1, then process events until the end.
712 // by default fLastEvent = fFirstEvent (process only one event)
714 if (!fInit) { // to prevent overwrite existing file
715 Error( "Exec", "Give a version name different from %s", fEventFolderName.Data() ) ;
719 if (strstr(option,"print")) {
725 if(strstr(option,"tim"))
726 gBenchmark->Start("EMCALDigitizer");
728 AliRunLoader *rl = AliRunLoader::Instance();
729 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
732 AliFatal("Did not get the Loader");
735 // Post Digitizer to the white board
736 emcalLoader->PostDigitizer(this) ;
738 if (fLastEvent == -1) {
739 fLastEvent = rl->GetNumberOfEvents() - 1 ;
742 fLastEvent = fFirstEvent ; // what is this ??
744 nEvents = fLastEvent - fFirstEvent + 1;
747 TClonesArray* digitsTMP = new TClonesArray("AliEMCALDigit", 32*96);
748 TClonesArray* digitsTRG = new TClonesArray("AliEMCALRawDigit", 32*96);
750 rl->LoadSDigits("EMCAL");
751 for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) {
753 rl->GetEvent(ievent);
755 Digitize(ievent) ; //Add prepared SDigits to digits and add the noise
760 //-------------------------------------
763 Digits2FastOR(digitsTMP, digitsTRG);
765 WriteDigits(digitsTRG);
767 (emcalLoader->TreeD())->Fill();
769 emcalLoader->WriteDigits( "OVERWRITE");
770 emcalLoader->WriteDigitizer("OVERWRITE");
774 digitsTRG ->Delete();
775 digitsTMP ->Delete();
777 //-------------------------------------
779 if(strstr(option,"deb"))
781 if(strstr(option,"table")) gObjectTable->Print();
783 //increment the total number of Digits per run
784 fDigitsInRun += emcalLoader->Digits()->GetEntriesFast() ;
787 emcalLoader->CleanDigitizer() ;
791 if(strstr(option,"tim")){
792 gBenchmark->Stop("EMCALDigitizer");
793 AliInfo(Form("Exec: took %f seconds for Digitizing %f seconds per event",
794 gBenchmark->GetCpuTime("EMCALDigitizer"), gBenchmark->GetCpuTime("EMCALDigitizer")/nEvents )) ;
798 //__________________________________________________________________
799 Float_t AliEMCALDigitizer::GetTimeResolution(Float_t energy) const
804 res = TMath::Sqrt(fTimeResolutionPar0 +
805 fTimeResolutionPar1/(energy*energy) );
807 // parametrization above is for ns. Convert to seconds:
811 //____________________________________________________________________________
812 void AliEMCALDigitizer::Digits2FastOR(TClonesArray* digitsTMP, TClonesArray* digitsTRG)
814 // FEE digits afterburner to produce TRG digits
815 // we are only interested in the FEE digit deposited energy
816 // to be converted later into a voltage value
818 // push the FEE digit to its associated FastOR (numbered from 0:95)
819 // TRU is in charge of summing module digits
821 AliRunLoader *runLoader = AliRunLoader::Instance();
823 AliRun* run = runLoader->GetAliRun();
825 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(runLoader->GetDetectorLoader("EMCAL"));
827 AliFatal("Did not get the Loader");
830 AliEMCAL* emcal = dynamic_cast<AliEMCAL*>(run->GetDetector("EMCAL"));
832 AliEMCALGeometry* geom = emcal->GetGeometry();
834 // build FOR from simulated digits
835 // and xfer to the corresponding TRU input (mapping)
837 TClonesArray* digits = emcalLoader->Digits();
839 TIter NextDigit(digits);
840 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
842 Int_t id = digit->GetId();
845 if (geom && geom->GetFastORIndexFromCellIndex(id , trgid))
847 AliDebug(1,Form("trigger digit id: %d from cell id: %d\n",trgid,id));
849 AliEMCALDigit* d = static_cast<AliEMCALDigit*>(digitsTMP->At(trgid));
853 new((*digitsTMP)[trgid]) AliEMCALDigit(*digit);
854 d = (AliEMCALDigit*)digitsTMP->At(trgid);
864 if (AliDebugLevel()) printf("Number of TRG digits: %d\n",digitsTMP->GetEntriesFast());
867 Int_t *timeSamples = new Int_t[nSamples];
869 NextDigit = TIter(digitsTMP);
870 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
874 Int_t id = digit->GetId();
875 Float_t time = digit->GetTime();
877 Double_t depositedEnergy = 0.;
878 for (Int_t j = 1; j <= digit->GetNprimary(); j++) depositedEnergy += digit->GetDEPrimary(j);
880 if (AliDebugLevel()) printf("Deposited Energy: %f\n", depositedEnergy);
882 // FIXME: Check digit time!
885 DigitalFastOR(time, depositedEnergy, timeSamples, nSamples);
887 for (Int_t j=0;j<nSamples;j++)
889 timeSamples[j] = ((j << 12) & 0xFF000) | (timeSamples[j] & 0xFFF);
892 new((*digitsTRG)[digitsTRG->GetEntriesFast()]) AliEMCALRawDigit(id, timeSamples, nSamples);
897 delete [] timeSamples;
899 else AliFatal("Could not get AliEMCAL");
904 //____________________________________________________________________________
905 void AliEMCALDigitizer::DigitalFastOR( Double_t time, Double_t dE, Int_t timeSamples[], Int_t nSamples )
909 const Int_t reso = 11; // 11-bit resolution ADC
910 const Double_t vFSR = 1; // Full scale input voltage range
911 const Double_t dNe = 125; // signal of the APD per MeV of energy deposit in a tower: 125 photo-e-/MeV @ M=30
912 const Double_t vA = .136e-6; // CSP output range: 0.136uV/e-
913 const Double_t rise = 40e-9; // rise time (10-90%) of the FastOR signal before shaping
915 const Double_t kTimeBinWidth = 25E-9; // sampling frequency (40MHz)
917 Double_t vV = 1000. * dE * dNe * vA; // GeV 2 MeV
919 TF1 signalF("signal", AnalogFastORFunction, 0, nSamples * kTimeBinWidth, 3);
920 signalF.SetParameter( 0, vV );
921 signalF.SetParameter( 1, time ); // FIXME: when does the signal arrive? Might account for cable lengths
922 signalF.SetParameter( 2, rise );
924 for (Int_t iTime=0; iTime<nSamples; iTime++)
926 // FIXME: add noise (probably not simply Gaussian) according to DA measurements
927 // probably plan an access to OCDB
929 timeSamples[iTime] = int((TMath::Power(2, reso) / vFSR) * signalF.Eval(iTime * kTimeBinWidth) + 0.5);
933 //____________________________________________________________________________
934 Bool_t AliEMCALDigitizer::Init()
936 // Makes all memory allocations
938 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
940 if ( emcalLoader == 0 ) {
941 Fatal("Init", "Could not obtain the AliEMCALLoader");
946 fLastEvent = fFirstEvent ;
949 fInput = fManager->GetNinputs() ;
953 fInputFileNames = new TString[fInput] ;
954 fEventNames = new TString[fInput] ;
955 fInputFileNames[0] = GetTitle() ;
956 fEventNames[0] = fEventFolderName.Data() ;
958 for (index = 1 ; index < fInput ; index++) {
959 fInputFileNames[index] = dynamic_cast<AliStream*>(fManager->GetInputStream(index))->GetFileName(0);
960 TString tempo = fManager->GetInputFolderName(index) ;
961 fEventNames[index] = tempo.Remove(tempo.Length()-1) ; // strip of the stream number added bt fManager
964 //to prevent cleaning of this object while GetEvent is called
965 emcalLoader->GetDigitsDataLoader()->GetBaseTaskLoader()->SetDoNotReload(kTRUE);
967 //Calibration instance
968 fCalibData = emcalLoader->CalibData();
972 //____________________________________________________________________________
973 void AliEMCALDigitizer::InitParameters()
975 // Parameter initialization for digitizer
977 // Get the parameters from the OCDB via the loader
978 AliRunLoader *rl = AliRunLoader::Instance();
979 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
980 AliEMCALSimParam * simParam = 0x0;
981 if(emcalLoader) simParam = emcalLoader->SimulationParameters();
984 simParam = AliEMCALSimParam::GetInstance();
985 AliWarning("Simulation Parameters not available in OCDB?");
988 fMeanPhotonElectron = simParam->GetMeanPhotonElectron();//4400; // electrons per GeV
989 fPinNoise = simParam->GetPinNoise();//0.012; // pin noise in GeV from analysis test beam data
990 if (fPinNoise < 0.0001 )
991 Warning("InitParameters", "No noise added\n") ;
992 fTimeNoise = simParam->GetTimeNoise(); // 1.28E-5 s
993 fDigitThreshold = simParam->GetDigitThreshold(); //fPinNoise * 3; // 3 * sigma
994 fTimeResolutionPar0 = simParam->GetTimeResolutionPar0();
995 fTimeResolutionPar1 = simParam->GetTimeResolutionPar1();
996 fTimeDelay = simParam->GetTimeDelay(); //600e-9 ; // 600 ns
998 // These defaults are normally not used.
999 // Values are read from calibration database instead
1000 fADCchannelEC = 0.0153; // Update 24 Apr 2007: 250./16/1024 - width of one ADC channel in GeV
1001 fADCpedestalEC = 0.0 ; // GeV
1002 fADCchannelECDecal = 1.0; // No decalibration by default
1003 fTimeChannel = 0.0; // No time calibration by default
1004 fTimeChannelDecal = 0.0; // No time decalibration by default
1006 fNADCEC = simParam->GetNADCEC();//(Int_t) TMath::Power(2,16) ; // number of channels in Tower ADC - 65536
1008 AliDebug(2,Form("Mean Photon Electron %d, Noise: APD %f, Time %f; Digit Threshold %d,Time Resolution Par0 %g Par1 %g,NADCEC %d",
1009 fMeanPhotonElectron,fPinNoise,fTimeNoise, fDigitThreshold,fTimeResolutionPar0,fTimeResolutionPar1,fNADCEC));
1013 //__________________________________________________________________
1014 void AliEMCALDigitizer::Print1(Option_t * option)
1015 { // 19-nov-04 - just for convenience
1017 PrintDigits(option);
1020 //__________________________________________________________________
1021 void AliEMCALDigitizer::Print (Option_t * ) const
1023 // Print Digitizer's parameters
1024 printf("Print: \n------------------- %s -------------", GetName() ) ;
1025 if( strcmp(fEventFolderName.Data(), "") != 0 ){
1026 printf(" Writing Digits to branch with title %s\n", fEventFolderName.Data()) ;
1030 nStreams = GetNInputStreams() ;
1037 for (index = 0 ; index < nStreams ; index++) {
1038 TString tempo(fEventNames[index]) ;
1040 if ((rl = AliRunLoader::GetRunLoader(tempo)) == 0)
1041 rl = AliRunLoader::Open(fInputFileNames[index], tempo) ;
1042 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
1044 TString fileName( emcalLoader->GetSDigitsFileName() ) ;
1045 if ( fEventNames[index] != AliConfig::GetDefaultEventFolderName()) // only if not the default folder name
1046 fileName = fileName.ReplaceAll(".root", "") + "_" + fEventNames[index] + ".root" ;
1047 printf ("Adding SDigits from %s %s\n", fInputFileNames[index].Data(), fileName.Data()) ;
1051 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1053 if(emcalLoader) printf("\nWriting digits to %s", emcalLoader->GetDigitsFileName().Data()) ;
1054 else printf("\nNULL LOADER");
1056 printf("\nWith following parameters:\n") ;
1057 printf(" Electronics noise in EMC, APD (fPinNoise) = %f, Time = %f \n", fPinNoise, fTimeNoise) ;
1058 printf(" Threshold in Tower (fDigitThreshold) = %d\n", fDigitThreshold) ;
1059 printf("---------------------------------------------------\n") ;
1062 printf("Print: AliEMCALDigitizer not initialized") ;
1065 //__________________________________________________________________
1066 void AliEMCALDigitizer::PrintDigits(Option_t * option)
1068 //utility method for printing digit information
1070 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1072 TClonesArray * digits = emcalLoader->Digits() ;
1073 TClonesArray * sdigits = emcalLoader->SDigits() ;
1075 printf("\n #Digits: %d : sdigits %d ", digits->GetEntriesFast(), sdigits->GetEntriesFast()) ;
1076 printf("\n event %d", emcalLoader->GetRunLoader()->GetEventNumber());
1078 if(strstr(option,"all")){
1080 AliEMCALDigit * digit;
1081 printf("\nEMC digits (with primaries):\n") ;
1082 printf("\n Id Amplitude Time Index Nprim: Primaries list \n") ;
1084 for (index = 0 ; index < digits->GetEntries() ; index++) {
1085 digit = dynamic_cast<AliEMCALDigit *>(digits->At(index)) ;
1087 printf("\n%6d %8f %6.5e %4d %2d : ",
1088 digit->GetId(), digit->GetAmplitude(), digit->GetTime(), digit->GetIndexInList(), digit->GetNprimary()) ;
1090 for (iprimary=0; iprimary<digit->GetNprimary(); iprimary++) {
1091 printf("%d ",digit->GetPrimary(iprimary+1) ) ;
1098 else printf("NULL LOADER, cannot print\n");
1101 //__________________________________________________________________
1102 Float_t AliEMCALDigitizer::TimeOfNoise(void)
1104 // Calculates the time signal generated by noise
1105 //printf("Time noise %e\n",fTimeNoise);
1106 return gRandom->Rndm() * fTimeNoise;
1109 //__________________________________________________________________
1110 void AliEMCALDigitizer::Unload()
1112 // Unloads the SDigits and Digits
1116 for(i = 1 ; i < fInput ; i++){
1117 TString tempo(fEventNames[i]) ;
1119 if ((rl = AliRunLoader::GetRunLoader(tempo)))
1120 rl->GetDetectorLoader("EMCAL")->UnloadSDigits() ;
1122 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1123 if(emcalLoader)emcalLoader->UnloadDigits() ;
1124 else AliFatal("Did not get the loader");
1127 //_________________________________________________________________________________________
1128 void AliEMCALDigitizer::WriteDigits()
1129 { // Makes TreeD in the output file.
1130 // Check if branch already exists:
1131 // if yes, exit without writing: ROOT TTree does not support overwriting/updating of
1132 // already existing branches.
1133 // else creates branch with Digits, named "EMCAL", title "...",
1134 // and branch "AliEMCALDigitizer", with the same title to keep all the parameters
1135 // and names of files, from which digits are made.
1137 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1140 const TClonesArray * digits = emcalLoader->Digits() ;
1141 TTree * treeD = emcalLoader->TreeD();
1143 emcalLoader->MakeDigitsContainer();
1144 treeD = emcalLoader->TreeD();
1147 // -- create Digits branch
1148 Int_t bufferSize = 32000 ;
1149 TBranch * digitsBranch = 0;
1150 if ((digitsBranch = treeD->GetBranch("EMCAL"))) {
1151 digitsBranch->SetAddress(&digits);
1152 AliWarning("Digits Branch already exists. Not all digits will be visible");
1155 treeD->Branch("EMCAL","TClonesArray",&digits,bufferSize);
1156 //digitsBranch->SetTitle(fEventFolderName);
1160 emcalLoader->WriteDigits("OVERWRITE");
1161 emcalLoader->WriteDigitizer("OVERWRITE");
1167 else AliFatal("Loader not available");
1170 //__________________________________________________________________
1171 void AliEMCALDigitizer::WriteDigits(TClonesArray* digits, const char* branchName)
1172 { // overloaded method
1173 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1176 TTree* treeD = emcalLoader->TreeD();
1179 emcalLoader->MakeDigitsContainer();
1180 treeD = emcalLoader->TreeD();
1183 // -- create Digits branch
1184 Int_t bufferSize = 32000;
1186 if (TBranch* triggerBranch = treeD->GetBranch(branchName))
1188 triggerBranch->SetAddress(&digits);
1192 treeD->Branch(branchName,"TClonesArray",&digits,bufferSize);
1197 else AliFatal("Loader not available");