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 "AliDigitizationInput.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"
70 #include "AliCaloCalibPedestal.h"
74 Double_t HeavisideTheta(Double_t x)
78 if (x > 0.) signal = 1.;
83 Double_t AnalogFastORFunction(Double_t *x, Double_t *par)
96 return (((0.8*(-((TMath::Power(C1,2)*C2*TMath::Power(TMath::E(),(-t + t0)/(C1*R1))*
97 TMath::Power(R1,2)*R2)/(C1*R1 - C2*R2)) +
98 C1*C2*R1*R2*(1 - (C2*TMath::Power(TMath::E(),(-t + t0)/(C2*R2))*R2)/(-(C1*R1) + C2*R2)))*v0*
99 HeavisideTheta(t - t0))/tr
100 - (0.8*(C1*C2*R1*R2 -
101 (TMath::Power(C1,2)*C2*TMath::Power(TMath::E(),(-1.*t + t0 + 1.25*tr)/(C1*R1))*
102 TMath::Power(R1,2)*R2)/(C1*R1 - C2*R2) +
103 (C1*TMath::Power(C2,2)*TMath::Power(TMath::E(),(-1.*t + t0 + 1.25*tr)/(C2*R2))*
104 R1*TMath::Power(R2,2))/(C1*R1 - C2*R2))*v0*
105 HeavisideTheta(t - t0 - 1.25*tr))/tr)/(C2*R1));
109 ClassImp(AliEMCALDigitizer)
112 //____________________________________________________________________________
113 AliEMCALDigitizer::AliEMCALDigitizer()
114 : AliDigitizer("",""),
119 fInputFileNames(0x0),
122 fMeanPhotonElectron(0),
123 fGainFluctuations(0),
127 fTimeResolutionPar0(0),
128 fTimeResolutionPar1(0),
131 fADCchannelECDecal(0),
133 fTimeChannelDecal(0),
135 fEventFolderName(""),
143 fDigInput = 0 ; // We work in the standalone mode
146 //____________________________________________________________________________
147 AliEMCALDigitizer::AliEMCALDigitizer(TString alirunFileName, TString eventFolderName)
148 : AliDigitizer("EMCALDigitizer", alirunFileName),
149 fDefaultInit(kFALSE),
156 fMeanPhotonElectron(0),
157 fGainFluctuations(0),
161 fTimeResolutionPar0(0),
162 fTimeResolutionPar1(0),
165 fADCchannelECDecal(0),
167 fTimeChannelDecal(0),
169 fEventFolderName(eventFolderName),
178 fDigInput = 0 ; // We work in the standalone mode
181 //____________________________________________________________________________
182 AliEMCALDigitizer::AliEMCALDigitizer(const AliEMCALDigitizer & d)
183 : AliDigitizer(d.GetName(),d.GetTitle()),
184 fDefaultInit(d.fDefaultInit),
185 fDigitsInRun(d.fDigitsInRun),
188 fInputFileNames(d.fInputFileNames),
189 fEventNames(d.fEventNames),
190 fDigitThreshold(d.fDigitThreshold),
191 fMeanPhotonElectron(d.fMeanPhotonElectron),
192 fGainFluctuations(d.fGainFluctuations),
193 fPinNoise(d.fPinNoise),
194 fTimeNoise(d.fTimeNoise),
195 fTimeDelay(d.fTimeDelay),
196 fTimeResolutionPar0(d.fTimeResolutionPar0),
197 fTimeResolutionPar1(d.fTimeResolutionPar1),
198 fADCchannelEC(d.fADCchannelEC),
199 fADCpedestalEC(d.fADCpedestalEC),
200 fADCchannelECDecal(d.fADCchannelECDecal),
201 fTimeChannel(d.fTimeChannel), fTimeChannelDecal(d.fTimeChannelDecal),
203 fEventFolderName(d.fEventFolderName),
204 fFirstEvent(d.fFirstEvent),
205 fLastEvent(d.fLastEvent),
206 fCalibData(d.fCalibData),
207 fSDigitizer(d.fSDigitizer ? new AliEMCALSDigitizer(*d.fSDigitizer) : 0)
212 //____________________________________________________________________________
213 AliEMCALDigitizer::AliEMCALDigitizer(AliDigitizationInput * rd)
214 : AliDigitizer(rd,"EMCALDigitizer"),
215 fDefaultInit(kFALSE),
222 fMeanPhotonElectron(0),
223 fGainFluctuations(0),
227 fTimeResolutionPar0(0.),
228 fTimeResolutionPar1(0.),
231 fADCchannelECDecal(0),
233 fTimeChannelDecal(0),
241 // ctor Init() is called by RunDigitizer
243 fEventFolderName = fDigInput->GetInputFolderName(0) ;
244 SetTitle(dynamic_cast<AliStream*>(fDigInput->GetInputStream(0))->GetFileName(0));
248 //____________________________________________________________________________
249 AliEMCALDigitizer::~AliEMCALDigitizer()
252 delete [] fInputFileNames ;
253 delete [] fEventNames ;
254 if (fSDigitizer) delete fSDigitizer;
257 //____________________________________________________________________________
258 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
272 AliRunLoader *rl = AliRunLoader::Instance();
273 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
277 AliFatal("EMCALLoader is NULL!") ;
278 return; // not needed but in case coverity complains ...
281 Int_t readEvent = event ;
282 if (fDigInput) // fDigInput is data member from AliDigitizer
283 readEvent = dynamic_cast<AliStream*>(fDigInput->GetInputStream(0))->GetCurrentEventNumber() ;
284 AliDebug(1,Form("Adding event %d from input stream 0 %s %s",
285 readEvent, GetTitle(), fEventFolderName.Data())) ;
286 rl->GetEvent(readEvent);
288 TClonesArray * digits = emcalLoader->Digits() ;
289 digits->Delete() ; //correct way to clear array when memory is
290 //allocated by objects stored in array
293 if (!rl->GetAliRun())
295 AliFatal("Could not get AliRun from runLoader");
296 return; // not needed but in case coverity complains ...
299 AliEMCAL * emcal = (AliEMCAL*)rl->GetAliRun()->GetDetector("EMCAL");
300 AliEMCALGeometry *geom = emcal->GetGeometry();
301 static int nEMC = geom->GetNCells();//max number of digits possible
302 AliDebug(1,Form("nEMC %i (number cells in EMCAL) | %s \n", nEMC, geom->GetName()));
304 digits->Expand(nEMC) ;
306 // RS create a digitizer on the fly
307 if (!fSDigitizer) fSDigitizer = new AliEMCALSDigitizer(rl->GetFileName().Data());
308 fSDigitizer->SetEventRange(0, -1) ;
310 //-------------------------------------------------------
311 //take all the inputs to add together and load the SDigits
312 TObjArray * sdigArray = new TObjArray(fInput) ;
313 sdigArray->AddAt(emcalLoader->SDigits(), 0) ;
316 Int_t embed = kFALSE;
317 for(i = 1 ; i < fInput ; i++)
319 TString tempo(fEventNames[i]) ;
322 AliRunLoader * rl2 = AliRunLoader::GetRunLoader(tempo) ;
325 rl2 = AliRunLoader::Open(fInputFileNames[i], tempo) ;
329 AliFatal("Run Loader of second event not available!");
330 return; // not needed but in case coverity complains ...
334 readEvent = dynamic_cast<AliStream*>(fDigInput->GetInputStream(i))->GetCurrentEventNumber() ;
336 Info("Digitize", "Adding event %d from input stream %d %s %s", readEvent, i, fInputFileNames[i].Data(), tempo.Data()) ;
339 // rl2->LoadDigits();
340 rl2->GetEvent(readEvent);
342 if(!rl2->GetDetectorLoader("EMCAL"))
344 AliFatal("Loader of second input not found");
345 return; // not needed but in case coverity complains ...
348 AliEMCALLoader *emcalLoader2 = dynamic_cast<AliEMCALLoader*>(rl2->GetDetectorLoader("EMCAL"));
352 AliFatal("EMCAL Loader of second event not available!");
353 return; // not needed but in case coverity complains ...
356 //Merge 2 simulated sdigits
357 if(!emcalLoader2->SDigits()) continue;
359 TClonesArray* sdigits2 = emcalLoader2->SDigits();
360 sdigArray->AddAt(sdigits2, i) ;
362 // Check if first sdigit is of embedded type, if so, handle the sdigits differently:
363 // do not smear energy of embedded, do not add noise to any sdigits
364 if( sdigits2->GetEntriesFast() <= 0 ) continue;
366 //printf("Merged digit type: %d\n",dynamic_cast<AliEMCALDigit*> (sdigits2->At(0))->GetType());
367 AliEMCALDigit * digit2 = dynamic_cast<AliEMCALDigit*> (sdigits2->At(0));
368 if( digit2 && digit2->GetType()==AliEMCALDigit::kEmbedded ) embed = kTRUE;
372 //--------------------------------
373 //Find the first tower with signal
374 Int_t nextSig = nEMC + 1 ;
375 TClonesArray * sdigits ;
376 for(i = 0 ; i < fInput ; i++)
378 if(i > 0 && embed) continue;
380 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
383 AliDebug(1,"Null sdigit pointer");
387 if (sdigits->GetEntriesFast() <= 0 )
389 AliDebug(1, "No sdigits entries");
393 AliEMCALDigit *sd = dynamic_cast<AliEMCALDigit *>(sdigits->At(0));
396 AliDebug(1, "NULL sdigit pointer");
400 Int_t curNext = sd->GetId() ;
401 if(curNext < nextSig)
403 AliDebug(1,Form("input %i : #sdigits %i \n",i, sdigits->GetEntriesFast()));
407 AliDebug(1,Form("FIRST tower with signal %i \n", nextSig));
409 TArrayI index(fInput) ;
410 index.Reset() ; //Set all indexes to zero
412 AliEMCALDigit * digit ;
413 AliEMCALDigit * curSDigit ;
415 //---------------------------------------------
416 //Put Noise contribution, smear time and energy
417 Float_t timeResolution = 0;
419 for(absID = 0; absID < nEMC; absID++)
420 { // Nov 30, 2006 by PAI; was from 1 to nEMC
422 if (IsDead(absID)) continue; // Don't instantiate dead digits
426 // amplitude set to zero, noise will be added later
427 Float_t noiseTime = 0.;
428 if(!embed) noiseTime = TimeOfNoise(); //No need for embedded events?
429 new((*digits)[absID]) AliEMCALDigit( -1, -1, absID, 0., noiseTime,kFALSE); // absID-1->absID
430 //look if we have to add signal?
431 digit = dynamic_cast<AliEMCALDigit *>(digits->At(absID)); // absID-1->absID
435 AliDebug(1,"Digit pointer is null");
441 // Calculate time as time of the largest digit
442 Float_t time = digit->GetTime() ;
443 Float_t aTime= digit->GetAmplitude() ;
446 Int_t nInputs = fInput;
447 if(embed) nInputs = 1; // In case of embedding, merge later real digits, do not smear energy and time of data
448 for(i = 0; i< nInputs ; i++)
450 //loop over (possible) merge sources
451 TClonesArray* sdtclarr = dynamic_cast<TClonesArray *>(sdigArray->At(i));
454 Int_t sDigitEntries = sdtclarr->GetEntriesFast();
456 if(sDigitEntries > index[i] ) curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ;
459 //May be several digits will contribute from the same input
460 while(curSDigit && (curSDigit->GetId() == absID))
462 //Shift primary to separate primaries belonging different inputs
463 Int_t primaryoffset = i ;
464 if(fDigInput) primaryoffset = fDigInput->GetMask(i) ;
465 curSDigit->ShiftPrimary(primaryoffset) ;
467 if(curSDigit->GetAmplitude()>aTime)
469 aTime = curSDigit->GetAmplitude();
470 time = curSDigit->GetTime();
473 *digit = *digit + *curSDigit ; //adds amplitudes of each digit
477 if( sDigitEntries > index[i] ) curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ;
481 }// loop over merging sources
483 //Here we convert the summed amplitude to an energy in GeV only for simulation or mixing of simulations
484 energy = fSDigitizer->Calibrate(digit->GetAmplitude()) ; // GeV
486 // add fluctuations for photo-electron creation
487 // corrected fluctuations after comparison with beam test, Paraskevi Ganoti (06/11/2011)
488 Float_t fluct = static_cast<Float_t>((energy*fMeanPhotonElectron)/fGainFluctuations);
489 energy *= static_cast<Float_t>(gRandom->Poisson(fluct)) / fluct ;
491 //calculate and set time
492 digit->SetTime(time) ;
494 //Find next signal module
496 for(i = 0 ; i < nInputs ; i++)
498 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
502 Int_t curNext = nextSig ;
503 if(sdigits->GetEntriesFast() > index[i])
505 AliEMCALDigit * tmpdigit = dynamic_cast<AliEMCALDigit *>(sdigits->At(index[i]));
508 curNext = tmpdigit->GetId() ;
511 if(curNext < nextSig) nextSig = curNext ;
517 // add the noise now, no need for embedded events with real data
519 energy += gRandom->Gaus(0., fPinNoise) ;
522 //Now digitize the energy according to the fSDigitizer method,
523 //which merely converts the energy to an integer. Later we will
524 //check that the stored value matches our allowed dynamic ranges
525 digit->SetAmplitude(fSDigitizer->Digitize(energy)) ;
527 //Set time resolution with final energy
528 timeResolution = GetTimeResolution(energy);
529 digit->SetTime(gRandom->Gaus(digit->GetTime(),timeResolution) ) ;
530 AliDebug(10,Form(" absID %5i energy %f nextSig %5i\n",
531 absID, energy, nextSig));
533 digit->SetTime(digit->GetTime()+fTimeDelay) ;
535 } // for(absID = 0; absID < nEMC; absID++)
537 //---------------------------------------------------------
538 //Embed simulated amplitude (and time?) to real data digits
541 for(Int_t input = 1; input<fInput; input++)
543 TClonesArray *realDigits = dynamic_cast<TClonesArray*> (sdigArray->At(input));
546 AliDebug(1,"No sdigits to merge\n");
550 for(Int_t i2 = 0 ; i2 < realDigits->GetEntriesFast() ; i2++)
552 AliEMCALDigit * digit2 = dynamic_cast<AliEMCALDigit*>( realDigits->At(i2) ) ;
555 digit = dynamic_cast<AliEMCALDigit*>( digits->At(digit2->GetId()) ) ;
558 // Put the embedded cell energy in same units as simulated sdigits -> transform to energy units
559 // and multiply to get a big int.
560 Float_t time2 = digit2->GetTime();
561 Float_t e2 = digit2->GetAmplitude();
562 CalibrateADCTime(e2,time2,digit2->GetId());
563 Float_t amp2 = fSDigitizer->Digitize(e2);
565 Float_t e0 = digit ->GetAmplitude();
567 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",
568 digit ->GetId(),digit ->GetAmplitude(), digit ->GetType(), digit->GetTime(),
569 digit2->GetId(),amp2, digit2->GetType(), time2 ));
571 // Sum amplitudes, change digit amplitude
572 digit->SetAmplitude( digit->GetAmplitude() + amp2);
573 // Rough assumption, assign time of the largest of the 2 digits,
574 // data or signal to the final digit.
575 if(amp2 > digit->GetAmplitude()) digit->SetTime(time2);
576 //Mark the new digit as embedded
577 digit->SetType(AliEMCALDigit::kEmbedded);
579 if(digit2->GetAmplitude()>0.01 && e0> 0.01 )
580 AliDebug(1,Form("Embedded digit: Abs ID %d, amp %f, type %d\n",
581 digit->GetId(), digit->GetAmplitude(), digit->GetType()));
588 //JLK is it better to call Clear() here?
589 delete sdigArray ; //We should not delete its contents
591 //------------------------------
592 //remove digits below thresholds
593 // until 10-02-2010 remove digits with energy smaller than fDigitThreshold 3*fPinNoise
594 // now, remove digits with Digitized ADC smaller than fDigitThreshold = 3,
595 // before merge in the same loop real data digits if available
598 for(i = 0 ; i < nEMC ; i++)
600 digit = dynamic_cast<AliEMCALDigit*>( digits->At(i) ) ;
603 //Then get the energy in GeV units.
604 energy = fSDigitizer->Calibrate(digit->GetAmplitude()) ;
605 //Then digitize using the calibration constants of the ocdb
606 Float_t ampADC = energy;
607 DigitizeEnergyTime(ampADC, time, digit->GetId()) ;
608 if(ampADC < fDigitThreshold)
609 digits->RemoveAt(i) ;
616 Int_t ndigits = digits->GetEntriesFast() ;
618 //---------------------------------------------------------------
620 //After we have done the summing and digitizing to create the
621 //digits, now we want to calibrate the resulting amplitude to match
622 //the dynamic range of our real data.
623 for (i = 0 ; i < ndigits ; i++)
625 digit = dynamic_cast<AliEMCALDigit *>( digits->At(i) ) ;
628 digit->SetIndexInList(i) ;
629 energy = fSDigitizer->Calibrate(digit->GetAmplitude()) ;
630 time = digit->GetTime();
631 Float_t ampADC = energy;
632 DigitizeEnergyTime(ampADC, time, digit->GetId());
633 digit->SetAmplitude(ampADC) ;
634 digit->SetTime(time);
635 // printf("digit amplitude set at end: i %d, amp %f\n",i,digit->GetAmplitude());
641 //_____________________________________________________________________
642 void AliEMCALDigitizer::DigitizeEnergyTime(Float_t & energy, Float_t & time, const Int_t absId)
645 // Returns digitized value of the energy in a cell absId
646 // using the calibration constants stored in the OCDB
647 // or default values if no CalibData object is found.
648 // This effectively converts everything to match the dynamic range
649 // of the real data we will collect
652 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
656 AliFatal("Did not get geometry from EMCALLoader");
666 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
668 Error("DigitizeEnergyTime","Wrong cell id number : absId %i ", absId) ;
669 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
673 fADCpedestalEC = fCalibData->GetADCpedestal (iSupMod,ieta,iphi);
674 fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi);
675 fADCchannelECDecal = fCalibData->GetADCchannelDecal (iSupMod,ieta,iphi);
676 fTimeChannel = fCalibData->GetTimeChannel (iSupMod,ieta,iphi,0); // Assign bunch crossing number equal to 0 (has simulation different bunch crossings?)
677 fTimeChannelDecal = fCalibData->GetTimeChannelDecal(iSupMod,ieta,iphi);
680 //Apply calibration to get ADC counts and partial decalibration as especified in OCDB
681 energy = (energy + fADCpedestalEC)/fADCchannelEC/fADCchannelECDecal ;
682 time += fTimeChannel-fTimeChannelDecal;
684 if(energy > fNADCEC )
688 //_____________________________________________________________________
689 void AliEMCALDigitizer::Decalibrate(AliEMCALDigit *digit)
691 // Decalibrate, used in Trigger digits
693 const AliEMCALGeometry *geom = AliEMCALGeometry::GetInstance();
697 AliFatal("Did not get geometry from EMCALLoader");
701 Int_t absId = digit->GetId();
709 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
711 if (!bCell) Error("Decalibrate","Wrong cell id number : absId %i ", absId) ;
712 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
716 fADCchannelEC = fCalibData->GetADCchannel(iSupMod,ieta,iphi);
717 Float_t factor = 1./(fADCchannelEC/0.0162);
719 *digit = *digit * factor;
723 //_____________________________________________________________________
724 void AliEMCALDigitizer::CalibrateADCTime(Float_t & adc, Float_t & time, const Int_t absId)
726 // Returns the energy in a cell absId with a given adc value
727 // using the calibration constants stored in the OCDB. Time also corrected from parameter in OCDB
728 // Used in case of embedding, transform ADC counts from real event into energy
729 // so that we can add the energy of the simulated sdigits which are in energy
731 // Same as in AliEMCALClusterizer::Calibrate() but here we do not reject channels being marked as hot
732 // or with time out of window
735 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
739 AliFatal("Did not get geometry from EMCALLoader");
749 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
750 if(!bCell) Error("CalibrateADCTime","Wrong cell id number : absId %i ", absId) ;
751 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
755 fADCpedestalEC = fCalibData->GetADCpedestal(iSupMod,ieta,iphi);
756 fADCchannelEC = fCalibData->GetADCchannel (iSupMod,ieta,iphi);
757 fTimeChannel = fCalibData->GetTimeChannel(iSupMod,ieta,iphi,0);// Assign bunch crossing number equal to 0 (has simulation different bunch crossings?)
760 adc = adc * fADCchannelEC - fADCpedestalEC;
761 time -= fTimeChannel;
766 //____________________________________________________________________________
767 void AliEMCALDigitizer::Digitize(Option_t *option)
769 // Steering method to process digitization for events
770 // in the range from fFirstEvent to fLastEvent.
771 // This range is optionally set by SetEventRange().
772 // if fLastEvent=-1, then process events until the end.
773 // by default fLastEvent = fFirstEvent (process only one event)
775 if (!fInit) { // to prevent overwrite existing file
776 Error( "Digitize", "Give a version name different from %s", fEventFolderName.Data() ) ;
780 if (strstr(option,"print")) {
786 if(strstr(option,"tim"))
787 gBenchmark->Start("EMCALDigitizer");
789 AliRunLoader *rl = AliRunLoader::Instance();
790 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
793 AliFatal("Did not get the Loader");
797 if (fLastEvent == -1) {
798 fLastEvent = rl->GetNumberOfEvents() - 1 ;
801 fLastEvent = fFirstEvent ; // what is this ??
803 nEvents = fLastEvent - fFirstEvent + 1;
806 AliEMCALGeometry *geom = dynamic_cast<AliEMCAL*>(rl->GetAliRun()->GetDetector("EMCAL"))->GetGeometry();
807 const Int_t nTRU = geom->GetNTotalTRU();
808 TClonesArray* digitsTMP = new TClonesArray("AliEMCALDigit", nTRU*96);
809 TClonesArray* digitsTRG = new TClonesArray("AliEMCALRawDigit", nTRU*96);
811 rl->LoadSDigits("EMCAL");
812 for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) {
814 rl->GetEvent(ievent);
816 Digitize(ievent) ; //Add prepared SDigits to digits and add the noise
821 //-------------------------------------
824 Digits2FastOR(digitsTMP, digitsTRG);
826 WriteDigits(digitsTRG);
828 (emcalLoader->TreeD())->Fill();
830 emcalLoader->WriteDigits( "OVERWRITE");
834 digitsTRG ->Delete();
835 digitsTMP ->Delete();
837 //-------------------------------------
839 if(strstr(option,"deb"))
841 if(strstr(option,"table")) gObjectTable->Print();
843 //increment the total number of Digits per run
844 fDigitsInRun += emcalLoader->Digits()->GetEntriesFast() ;
849 if(strstr(option,"tim")){
850 gBenchmark->Stop("EMCALDigitizer");
851 Float_t cputime = gBenchmark->GetCpuTime("EMCALDigitizer");
852 Float_t avcputime = cputime;
853 if(nEvents==0) avcputime = 0 ;
854 AliInfo(Form("Digitize: took %f seconds for Digitizing %f seconds per event", cputime, avcputime)) ;
858 //__________________________________________________________________
859 Float_t AliEMCALDigitizer::GetTimeResolution(Float_t energy) const
861 // Assign a smeared time to the digit, from observed distribution in LED system (?).
866 res = TMath::Sqrt(fTimeResolutionPar0 +
867 fTimeResolutionPar1/(energy*energy) );
869 // parametrization above is for ns. Convert to seconds:
873 //____________________________________________________________________________
874 void AliEMCALDigitizer::Digits2FastOR(TClonesArray* digitsTMP, TClonesArray* digitsTRG)
876 // FEE digits afterburner to produce TRG digits
877 // we are only interested in the FEE digit deposited energy
878 // to be converted later into a voltage value
880 // push the FEE digit to its associated FastOR (numbered from 0:95)
881 // TRU is in charge of summing module digits
883 AliRunLoader *runLoader = AliRunLoader::Instance();
885 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(runLoader->GetDetectorLoader("EMCAL"));
886 if (!emcalLoader) AliFatal("Did not get the Loader");
888 const AliEMCALGeometry* geom = AliEMCALGeometry::GetInstance();
890 // build FOR from simulated digits
891 // and xfer to the corresponding TRU input (mapping)
893 TClonesArray* sdigits = emcalLoader->SDigits();
895 TClonesArray *digits = (TClonesArray*)sdigits->Clone();
897 AliDebug(999,Form("=== %d SDigits to trigger digits ===",digits->GetEntriesFast()));
899 TIter NextDigit(digits);
900 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
902 if (IsDead(digit)) continue;
906 Int_t id = digit->GetId();
909 if (geom && geom->GetFastORIndexFromCellIndex(id , trgid))
911 AliDebug(1,Form("trigger digit id: %d from cell id: %d\n",trgid,id));
913 AliEMCALDigit* d = static_cast<AliEMCALDigit*>(digitsTMP->At(trgid));
917 new((*digitsTMP)[trgid]) AliEMCALDigit(*digit);
918 d = (AliEMCALDigit*)digitsTMP->At(trgid);
928 if (AliDebugLevel()) printf("Number of TRG digits: %d\n",digitsTMP->GetEntriesFast());
930 Int_t nSamples = geom->GetNTotalTRU();
931 Int_t *timeSamples = new Int_t[nSamples];
933 NextDigit = TIter(digitsTMP);
934 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
938 Int_t id = digit->GetId();
939 Float_t time = 50.e-9;
941 Double_t depositedEnergy = 0.;
942 for (Int_t j = 1; j <= digit->GetNprimary(); j++) depositedEnergy += digit->GetDEPrimary(j);
944 if (AliDebugLevel()) printf("Deposited Energy: %f\n", depositedEnergy);
946 // FIXME: Check digit time!
947 if (depositedEnergy) {
948 depositedEnergy += gRandom->Gaus(0., .08);
949 DigitalFastOR(time, depositedEnergy, timeSamples, nSamples);
951 for (Int_t j=0;j<nSamples;j++) {
952 if (AliDebugLevel()) printf("timeSamples[%d]: %d\n",j,timeSamples[j]);
953 timeSamples[j] = ((j << 16) | (timeSamples[j] & 0xFFFF));
956 new((*digitsTRG)[digitsTRG->GetEntriesFast()]) AliEMCALRawDigit(id, timeSamples, nSamples);
958 if (AliDebugLevel()) ((AliEMCALRawDigit*)digitsTRG->At(digitsTRG->GetEntriesFast() - 1))->Print("");
963 delete [] timeSamples;
965 if (digits && digits->GetEntriesFast()) digits->Delete();
968 //____________________________________________________________________________
969 void AliEMCALDigitizer::DigitalFastOR( Double_t time, Double_t dE, Int_t timeSamples[], Int_t nSamples )
973 const Int_t reso = 12; // 11-bit resolution ADC
974 const Double_t vFSR = 2.; // Full scale input voltage range 2V (p-p)
975 //const Double_t dNe = 125; // signal of the APD per MeV of energy deposit in a tower: 125 photo-e-/MeV @ M=30
976 const Double_t dNe = 125/1.3; // F-ALTRO max V. FEE: factor 4
977 const Double_t vA = .136e-6; // CSP output range: 0.136uV/e-
978 const Double_t rise = 50e-9; // rise time (10-90%) of the FastOR signal before shaping
980 const Double_t kTimeBinWidth = 25E-9; // sampling frequency (40MHz)
982 Double_t vV = 1000. * dE * dNe * vA; // GeV 2 MeV
984 TF1 signalF("signal", AnalogFastORFunction, 0, nSamples * kTimeBinWidth, 3);
985 signalF.SetParameter( 0, vV );
986 signalF.SetParameter( 1, time ); // FIXME: when does the signal arrive? Might account for cable lengths
987 signalF.SetParameter( 2, rise );
989 for (Int_t iTime=0; iTime<nSamples; iTime++)
991 // FIXME: add noise (probably not simply Gaussian) according to DA measurements
992 // probably plan an access to OCDB
993 Double_t sig = signalF.Eval(iTime * kTimeBinWidth);
994 if (TMath::Abs(sig) > vFSR/2.) {
995 AliError("Signal overflow!");
996 timeSamples[iTime] = (1 << reso) - 1;
998 AliDebug(999,Form("iTime: %d sig: %f\n",iTime,sig));
999 timeSamples[iTime] = ((1 << reso) / vFSR) * sig + 0.5;
1004 //____________________________________________________________________________
1005 Bool_t AliEMCALDigitizer::Init()
1007 // Makes all memory allocations
1009 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1011 if ( emcalLoader == 0 ) {
1012 Fatal("Init", "Could not obtain the AliEMCALLoader");
1017 fLastEvent = fFirstEvent ;
1020 fInput = fDigInput->GetNinputs() ;
1024 fInputFileNames = new TString[fInput] ;
1025 fEventNames = new TString[fInput] ;
1026 fInputFileNames[0] = GetTitle() ;
1027 fEventNames[0] = fEventFolderName.Data() ;
1029 for (index = 1 ; index < fInput ; index++) {
1030 fInputFileNames[index] = dynamic_cast<AliStream*>(fDigInput->GetInputStream(index))->GetFileName(0);
1031 TString tempo = fDigInput->GetInputFolderName(index) ;
1032 fEventNames[index] = tempo.Remove(tempo.Length()-1) ; // strip of the stream number added bt fDigInput
1035 //Calibration instance
1036 fCalibData = emcalLoader->CalibData();
1040 //____________________________________________________________________________
1041 void AliEMCALDigitizer::InitParameters()
1043 // Parameter initialization for digitizer
1045 // Get the parameters from the OCDB via the loader
1046 AliRunLoader *rl = AliRunLoader::Instance();
1047 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
1048 AliEMCALSimParam * simParam = 0x0;
1049 if(emcalLoader) simParam = emcalLoader->SimulationParameters();
1052 simParam = AliEMCALSimParam::GetInstance();
1053 AliWarning("Simulation Parameters not available in OCDB?");
1056 fMeanPhotonElectron = simParam->GetMeanPhotonElectron() ; // 4400; // electrons per GeV
1057 fGainFluctuations = simParam->GetGainFluctuations() ; // 15.0;
1059 fPinNoise = simParam->GetPinNoise();//0.012; // pin noise in GeV from analysis test beam data
1060 if (fPinNoise < 0.0001 )
1061 Warning("InitParameters", "No noise added\n") ;
1062 fTimeNoise = simParam->GetTimeNoise(); // 1.28E-5 s
1063 fDigitThreshold = simParam->GetDigitThreshold(); //fPinNoise * 3; // 3 * sigma
1064 fTimeResolutionPar0 = simParam->GetTimeResolutionPar0();
1065 fTimeResolutionPar1 = simParam->GetTimeResolutionPar1();
1066 fTimeDelay = simParam->GetTimeDelay(); //600e-9 ; // 600 ns
1068 // These defaults are normally not used.
1069 // Values are read from calibration database instead
1070 fADCchannelEC = 0.0153; // Update 24 Apr 2007: 250./16/1024 - width of one ADC channel in GeV
1071 fADCpedestalEC = 0.0 ; // GeV
1072 fADCchannelECDecal = 1.0; // No decalibration by default
1073 fTimeChannel = 0.0; // No time calibration by default
1074 fTimeChannelDecal = 0.0; // No time decalibration by default
1076 fNADCEC = simParam->GetNADCEC();//(Int_t) TMath::Power(2,16) ; // number of channels in Tower ADC - 65536
1078 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",
1079 fMeanPhotonElectron, fGainFluctuations, fPinNoise,fTimeNoise, fDigitThreshold,fTimeResolutionPar0,fTimeResolutionPar1,fNADCEC));
1083 //__________________________________________________________________
1084 void AliEMCALDigitizer::Print1(Option_t * option)
1085 { // 19-nov-04 - just for convenience
1087 PrintDigits(option);
1090 //__________________________________________________________________
1091 void AliEMCALDigitizer::Print (Option_t * ) const
1093 // Print Digitizer's parameters
1094 printf("Print: \n------------------- %s -------------", GetName() ) ;
1095 if( strcmp(fEventFolderName.Data(), "") != 0 ){
1096 printf(" Writing Digits to branch with title %s\n", fEventFolderName.Data()) ;
1100 nStreams = GetNInputStreams() ;
1107 for (index = 0 ; index < nStreams ; index++) {
1108 TString tempo(fEventNames[index]) ;
1110 if ((rl = AliRunLoader::GetRunLoader(tempo)) == 0)
1111 rl = AliRunLoader::Open(fInputFileNames[index], tempo) ;
1112 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
1114 TString fileName( emcalLoader->GetSDigitsFileName() ) ;
1115 if ( fEventNames[index] != AliConfig::GetDefaultEventFolderName()) // only if not the default folder name
1116 fileName = fileName.ReplaceAll(".root", "") + "_" + fEventNames[index] + ".root" ;
1117 printf ("Adding SDigits from %s %s\n", fInputFileNames[index].Data(), fileName.Data()) ;
1121 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1123 if(emcalLoader) printf("\nWriting digits to %s", emcalLoader->GetDigitsFileName().Data()) ;
1124 else printf("\nNULL LOADER");
1126 printf("\nWith following parameters:\n") ;
1127 printf(" Electronics noise in EMC, APD (fPinNoise) = %f, Time = %f \n", fPinNoise, fTimeNoise) ;
1128 printf(" Threshold in Tower (fDigitThreshold) = %d\n", fDigitThreshold) ;
1129 printf("---------------------------------------------------\n") ;
1132 printf("Print: AliEMCALDigitizer not initialized") ;
1135 //__________________________________________________________________
1136 void AliEMCALDigitizer::PrintDigits(Option_t * option)
1138 //utility method for printing digit information
1140 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1142 TClonesArray * digits = emcalLoader->Digits() ;
1143 TClonesArray * sdigits = emcalLoader->SDigits() ;
1145 printf("\n #Digits: %d : sdigits %d ", digits->GetEntriesFast(), sdigits->GetEntriesFast()) ;
1146 printf("\n event %d", emcalLoader->GetRunLoader()->GetEventNumber());
1148 if(strstr(option,"all")){
1150 AliEMCALDigit * digit;
1151 printf("\nEMC digits (with primaries):\n") ;
1152 printf("\n Id Amplitude Time Index Nprim: Primaries list \n") ;
1154 for (index = 0 ; index < digits->GetEntries() ; index++) {
1155 digit = dynamic_cast<AliEMCALDigit *>(digits->At(index)) ;
1157 printf("\n%6d %8f %6.5e %4d %2d : ",
1158 digit->GetId(), digit->GetAmplitude(), digit->GetTime(), digit->GetIndexInList(), digit->GetNprimary()) ;
1160 for (iprimary=0; iprimary<digit->GetNprimary(); iprimary++) {
1161 printf("%d ",digit->GetPrimary(iprimary+1) ) ;
1168 else printf("NULL LOADER, cannot print\n");
1171 //__________________________________________________________________
1172 Float_t AliEMCALDigitizer::TimeOfNoise(void)
1174 // Calculates the time signal generated by noise
1175 //printf("Time noise %e\n",fTimeNoise);
1176 return gRandom->Rndm() * fTimeNoise;
1179 //__________________________________________________________________
1180 void AliEMCALDigitizer::Unload()
1182 // Unloads the SDigits and Digits
1186 for(i = 1 ; i < fInput ; i++){
1187 TString tempo(fEventNames[i]) ;
1189 if ((rl = AliRunLoader::GetRunLoader(tempo)))
1190 rl->GetDetectorLoader("EMCAL")->UnloadSDigits() ;
1192 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1193 if(emcalLoader)emcalLoader->UnloadDigits() ;
1194 else AliFatal("Did not get the loader");
1197 //_________________________________________________________________________________________
1198 void AliEMCALDigitizer::WriteDigits()
1199 { // Makes TreeD in the output file.
1200 // Check if branch already exists:
1201 // if yes, exit without writing: ROOT TTree does not support overwriting/updating of
1202 // already existing branches.
1203 // else creates branch with Digits, named "EMCAL", title "...",
1204 // and branch "AliEMCALDigitizer", with the same title to keep all the parameters
1205 // and names of files, from which digits are made.
1207 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1210 const TClonesArray * digits = emcalLoader->Digits() ;
1211 TTree * treeD = emcalLoader->TreeD();
1213 emcalLoader->MakeDigitsContainer();
1214 treeD = emcalLoader->TreeD();
1217 // -- create Digits branch
1218 Int_t bufferSize = 32000 ;
1219 TBranch * digitsBranch = 0;
1220 if ((digitsBranch = treeD->GetBranch("EMCAL"))) {
1221 digitsBranch->SetAddress(&digits);
1222 AliWarning("Digits Branch already exists. Not all digits will be visible");
1225 treeD->Branch("EMCAL","TClonesArray",&digits,bufferSize);
1226 //digitsBranch->SetTitle(fEventFolderName);
1230 emcalLoader->WriteDigits("OVERWRITE");
1231 emcalLoader->WriteDigitizer("OVERWRITE");
1237 else AliFatal("Loader not available");
1240 //__________________________________________________________________
1241 void AliEMCALDigitizer::WriteDigits(TClonesArray* digits, const char* branchName)
1242 { // overloaded method
1243 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1246 TTree* treeD = emcalLoader->TreeD();
1249 emcalLoader->MakeDigitsContainer();
1250 treeD = emcalLoader->TreeD();
1253 // -- create Digits branch
1254 Int_t bufferSize = 32000;
1256 if (TBranch* triggerBranch = treeD->GetBranch(branchName))
1258 triggerBranch->SetAddress(&digits);
1262 treeD->Branch(branchName,"TClonesArray",&digits,bufferSize);
1267 else AliFatal("Loader not available");
1270 //__________________________________________________________________
1271 Bool_t AliEMCALDigitizer::IsDead(AliEMCALDigit *digit)
1273 AliRunLoader *runLoader = AliRunLoader::Instance();
1274 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(runLoader->GetDetectorLoader("EMCAL"));
1275 if (!emcalLoader) AliFatal("Did not get the Loader");
1277 AliCaloCalibPedestal *caloPed = emcalLoader->PedestalData();
1279 AliWarning("Could not access pedestal data! No dead channel removal applied");
1284 const AliEMCALGeometry *geom = AliEMCALGeometry::GetInstance();
1285 if (!geom) AliFatal("Did not get geometry from EMCALLoader");
1287 Int_t absId = digit->GetId();
1295 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
1297 if (!bCell) Error("IsDead","Wrong cell id number : absId %i ", absId) ;
1298 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
1300 Int_t channelStatus = (Int_t)(caloPed->GetDeadMap(iSupMod))->GetBinContent(ieta,iphi);
1302 if (channelStatus == AliCaloCalibPedestal::kDead)
1309 //__________________________________________________________________
1310 Bool_t AliEMCALDigitizer::IsDead(Int_t absId)
1312 AliRunLoader *runLoader = AliRunLoader::Instance();
1313 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(runLoader->GetDetectorLoader("EMCAL"));
1314 if (!emcalLoader) AliFatal("Did not get the Loader");
1316 AliCaloCalibPedestal *caloPed = emcalLoader->PedestalData();
1318 AliWarning("Could not access pedestal data! No dead channel removal applied");
1323 const AliEMCALGeometry *geom = AliEMCALGeometry::GetInstance();
1324 if (!geom) AliFatal("Did not get geometry from EMCALLoader");
1333 Bool_t bCell = geom->GetCellIndex(absId, iSupMod, nModule, nIphi, nIeta) ;
1335 if (!bCell) Error("IsDead","Wrong cell id number : absId %i ", absId) ;
1336 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
1338 Int_t channelStatus = (Int_t)(caloPed->GetDeadMap(iSupMod))->GetBinContent(ieta,iphi);
1340 if (channelStatus == AliCaloCalibPedestal::kDead)