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 of summable digits from different events.
25 // For each event two branches are created in TreeD:
26 // "EMCAL" - list of digits
27 // "AliEMCALDigitizer" - AliEMCALDigitizer with all parameters used in digitization
29 // Note, that one cset title for new digits branch, and repeat digitization with
30 // another set of parameters.
33 // root[0] AliEMCALDigitizer * d = new AliEMCALDigitizer() ;
34 // root[1] d->ExecuteTask()
35 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
36 // //Digitizes SDigitis in all events found in file galice.root
38 // root[2] AliEMCALDigitizer * d1 = new AliEMCALDigitizer("galice1.root") ;
39 // // Will read sdigits from galice1.root
40 // root[3] d1->MixWith("galice2.root")
41 // Warning in <TDatabasePDG::TDatabasePDG>: object already instantiated
42 // // Reads another portion of sdigits from galice2.root
43 // root[3] d1->MixWith("galice3.root")
44 // // Reads another portion of sdigits from galice3.root
45 // root[4] d->ExecuteTask("deb timing")
46 // // Reads SDigits from files galice1.root, galice2.root ....
47 // // mixes them and stores produced Digits in file galice1.root
48 // // deb - prints number of produced digits
49 // // deb all - prints list of produced digits
50 // // timing - prints time used for digitization
51 ////////////////////////////////////////////////////////////////////////////////////
53 //*-- Author: Sahal Yacoob (LBL)
54 // based on : AliEMCALDigitizer
56 // August 2002 Yves Schutz: clone PHOS as closely as possible and intoduction
57 // of new IO (à la PHOS)
58 // November 2003 Aleksei Pavlinov : adopted for Shish-Kebab geometry
59 //_________________________________________________________________________________
61 // --- ROOT system ---
65 #include <TBenchmark.h>
67 #include <TObjectTable.h>
72 // --- AliRoot header files ---
75 #include "AliRunDigitizer.h"
76 #include "AliRunLoader.h"
77 #include "AliCDBManager.h"
78 #include "AliCDBEntry.h"
79 #include "AliEMCALDigit.h"
81 #include "AliEMCALLoader.h"
82 #include "AliEMCALDigitizer.h"
83 #include "AliEMCALSDigitizer.h"
84 #include "AliEMCALGeometry.h"
85 //#include "AliEMCALTick.h"
86 #include "AliEMCALCalibData.h"
87 #include "AliEMCALSimParam.h"
88 #include "AliEMCALRawDigit.h"
92 Double_t HeavisideTheta(Double_t x)
96 if (x > 0.) signal = 1.;
101 Double_t AnalogFastORFunction(Double_t *x, Double_t *par)
103 Double_t v0 = par[0];
104 Double_t t0 = par[1];
105 Double_t tr = par[2];
108 Double_t C1 = 33e-12;
110 Double_t C2 = 22e-12;
114 return (((0.8*(-((TMath::Power(C1,2)*C2*TMath::Power(TMath::E(),(-t + t0)/(C1*R1))*
115 TMath::Power(R1,2)*R2)/(C1*R1 - C2*R2)) +
116 C1*C2*R1*R2*(1 - (C2*TMath::Power(TMath::E(),(-t + t0)/(C2*R2))*R2)/(-(C1*R1) + C2*R2)))*v0*
117 HeavisideTheta(t - t0))/tr
118 - (0.8*(C1*C2*R1*R2 -
119 (TMath::Power(C1,2)*C2*TMath::Power(TMath::E(),(-1.*t + t0 + 1.25*tr)/(C1*R1))*
120 TMath::Power(R1,2)*R2)/(C1*R1 - C2*R2) +
121 (C1*TMath::Power(C2,2)*TMath::Power(TMath::E(),(-1.*t + t0 + 1.25*tr)/(C2*R2))*
122 R1*TMath::Power(R2,2))/(C1*R1 - C2*R2))*v0*
123 HeavisideTheta(t - t0 - 1.25*tr))/tr)/(C2*R1));
127 ClassImp(AliEMCALDigitizer)
130 //____________________________________________________________________________
131 AliEMCALDigitizer::AliEMCALDigitizer()
132 : AliDigitizer("",""),
137 fInputFileNames(0x0),
140 fMeanPhotonElectron(0),
143 fTimeResolutionPar0(0),
144 fTimeResolutionPar1(0),
148 fEventFolderName(""),
155 fManager = 0 ; // We work in the standalone mode
158 //____________________________________________________________________________
159 AliEMCALDigitizer::AliEMCALDigitizer(TString alirunFileName, TString eventFolderName)
160 : AliDigitizer("EMCAL"+AliConfig::Instance()->GetDigitizerTaskName(), alirunFileName),
161 fDefaultInit(kFALSE),
168 fMeanPhotonElectron(0),
171 fTimeResolutionPar0(0),
172 fTimeResolutionPar1(0),
176 fEventFolderName(eventFolderName),
184 fManager = 0 ; // We work in the standalone mode
187 //____________________________________________________________________________
188 AliEMCALDigitizer::AliEMCALDigitizer(const AliEMCALDigitizer & d)
189 : AliDigitizer(d.GetName(),d.GetTitle()),
190 fDefaultInit(d.fDefaultInit),
191 fDigitsInRun(d.fDigitsInRun),
194 fInputFileNames(d.fInputFileNames),
195 fEventNames(d.fEventNames),
196 fDigitThreshold(d.fDigitThreshold),
197 fMeanPhotonElectron(d.fMeanPhotonElectron),
198 fPinNoise(d.fPinNoise),
199 fTimeDelay(d.fTimeDelay),
200 fTimeResolutionPar0(d.fTimeResolutionPar0),
201 fTimeResolutionPar1(d.fTimeResolutionPar1),
202 fADCchannelEC(d.fADCchannelEC),
203 fADCpedestalEC(d.fADCpedestalEC),
205 fEventFolderName(d.fEventFolderName),
206 fFirstEvent(d.fFirstEvent),
207 fLastEvent(d.fLastEvent),
208 fCalibData(d.fCalibData)
213 //____________________________________________________________________________
214 AliEMCALDigitizer::AliEMCALDigitizer(AliRunDigitizer * rd)
215 : AliDigitizer(rd,"EMCAL"+AliConfig::Instance()->GetDigitizerTaskName()),
216 fDefaultInit(kFALSE),
223 fMeanPhotonElectron(0),
226 fTimeResolutionPar0(0.),
227 fTimeResolutionPar1(0.),
236 // ctor Init() is called by RunDigitizer
238 fEventFolderName = fManager->GetInputFolderName(0) ;
239 SetTitle(dynamic_cast<AliStream*>(fManager->GetInputStream(0))->GetFileName(0));
243 //____________________________________________________________________________
244 AliEMCALDigitizer::~AliEMCALDigitizer()
247 if (AliRunLoader::Instance()) {
248 AliLoader *emcalLoader=0;
249 if ((emcalLoader = AliRunLoader::Instance()->GetDetectorLoader("EMCAL")))
250 emcalLoader->CleanDigitizer();
253 AliDebug(1," no runloader present");
255 delete [] fInputFileNames ;
256 delete [] fEventNames ;
260 //____________________________________________________________________________
261 void AliEMCALDigitizer::Digitize(Int_t event)
264 // Makes the digitization of the collected summable digits
265 // for this it first creates the array of all EMCAL modules
266 // filled with noise and after that adds contributions from
267 // SDigits. This design helps to avoid scanning over the
268 // list of digits to add contribution of any new SDigit.
271 // Note that SDigit energy info is stored as an amplitude, so we
272 // must call the Calibrate() method of the SDigitizer to convert it
273 // back to an energy in GeV before adding it to the Digit
275 static int nEMC=0; //max number of digits possible
277 AliRunLoader *rl = AliRunLoader::Instance();
278 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
281 Int_t readEvent = event ;
282 // fManager is data member from AliDigitizer
284 readEvent = dynamic_cast<AliStream*>(fManager->GetInputStream(0))->GetCurrentEventNumber() ;
285 AliDebug(1,Form("Adding event %d from input stream 0 %s %s",
286 readEvent, GetTitle(), fEventFolderName.Data())) ;
287 rl->GetEvent(readEvent);
289 TClonesArray * digits = emcalLoader->Digits() ;
290 digits->Delete() ; //correct way to clear array when memory is
291 //allocated by objects stored in array
294 AliEMCALGeometry *geom = 0;
295 if (!rl->GetAliRun()) {
296 AliFatal("Could not get AliRun from runLoader");
299 AliEMCAL * emcal = (AliEMCAL*)rl->GetAliRun()->GetDetector("EMCAL");
300 geom = emcal->GetGeometry();
301 nEMC = geom->GetNCells();
302 AliDebug(1,Form("nEMC %i (number cells in EMCAL) | %s \n", nEMC, geom->GetName()));
307 digits->Expand(nEMC) ;
309 // get first the sdigitizer from the tasks list (must have same name as the digitizer)
310 if ( !emcalLoader->SDigitizer() )
311 emcalLoader->LoadSDigitizer();
312 AliEMCALSDigitizer * sDigitizer = dynamic_cast<AliEMCALSDigitizer*>(emcalLoader->SDigitizer());
316 Fatal("Digitize", "SDigitizer with name %s %s not found", fEventFolderName.Data(), GetTitle() ) ;
320 //take all the inputs to add together and load the SDigits
321 TObjArray * sdigArray = new TObjArray(fInput) ;
322 sdigArray->AddAt(emcalLoader->SDigits(), 0) ;
325 for(i = 1 ; i < fInput ; i++){
326 TString tempo(fEventNames[i]) ;
329 AliRunLoader * rl2 = AliRunLoader::GetRunLoader(tempo) ;
332 rl2 = AliRunLoader::Open(fInputFileNames[i], tempo) ;
335 readEvent = dynamic_cast<AliStream*>(fManager->GetInputStream(i))->GetCurrentEventNumber() ;
336 Info("Digitize", "Adding event %d from input stream %d %s %s", readEvent, i, fInputFileNames[i].Data(), tempo.Data()) ;
338 rl2->GetEvent(readEvent);
339 if(rl2->GetDetectorLoader("EMCAL"))
341 AliEMCALLoader *emcalLoader2 = dynamic_cast<AliEMCALLoader*>(rl2->GetDetectorLoader("EMCAL"));
342 if(emcalLoader2) sdigArray->AddAt(emcalLoader2->SDigits(), i) ;
343 else AliFatal("EMCAL Loader of second event not available!");
345 else Fatal("Digitize", "Loader of second input not found");
348 //Find the first tower with signal
349 Int_t nextSig = nEMC + 1 ;
350 TClonesArray * sdigits ;
351 for(i = 0 ; i < fInput ; i++){
353 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
355 if (sdigits->GetEntriesFast() ){
356 AliEMCALDigit *sd = dynamic_cast<AliEMCALDigit *>(sdigits->At(0));
358 Int_t curNext = sd->GetId() ;
359 if(curNext < nextSig)
361 AliDebug(1,Form("input %i : #sdigits %i \n",
362 i, sdigits->GetEntriesFast()));
364 }//First entry is not NULL
366 Info("Digitize", "NULL sdigit pointer");
369 }//There is at least one entry
371 Info("Digitize", "NULL sdigits array");
374 }// SDigits array exists
376 Info("Digitizer","Null sdigit pointer");
380 AliDebug(1,Form("FIRST tower with signal %i \n", nextSig));
382 TArrayI index(fInput) ;
383 index.Reset() ; //Set all indexes to zero
385 AliEMCALDigit * digit ;
386 AliEMCALDigit * curSDigit ;
388 // TClonesArray * ticks = new TClonesArray("AliEMCALTick",1000) ;
390 //Put Noise contribution
391 for(absID = 0; absID < nEMC; absID++){ // Nov 30, 2006 by PAI; was from 1 to nEMC
393 // amplitude set to zero, noise will be added later
394 new((*digits)[absID]) AliEMCALDigit( -1, -1, absID, 0., TimeOfNoise(),kFALSE); // absID-1->absID
395 //look if we have to add signal?
397 digit = dynamic_cast<AliEMCALDigit *>(digits->At(absID)); // absID-1->absID
402 //Add SDigits from all inputs
404 //Int_t contrib = 0 ;
406 //Follow PHOS and comment out this timing model til a better one
407 //can be developed - JLK 28-Apr-2008
409 //Float_t a = digit->GetAmplitude() ;
410 //Float_t b = TMath::Abs( a /fTimeSignalLength) ;
411 //Mark the beginning of the signal
412 //new((*ticks)[contrib++]) AliEMCALTick(digit->GetTime(),0, b);
413 //Mark the end of the signal
414 //new((*ticks)[contrib++]) AliEMCALTick(digit->GetTime()+fTimeSignalLength, -a, -b);
416 // Calculate time as time of the largest digit
417 Float_t time = digit->GetTime() ;
418 Float_t aTime= digit->GetAmplitude() ;
421 for(i = 0; i< fInput ; i++){ //loop over (possible) merge sources
422 TClonesArray* sdtclarr = dynamic_cast<TClonesArray *>(sdigArray->At(i));
424 Int_t sDigitEntries = sdtclarr->GetEntriesFast();
426 if(sDigitEntries > index[i] )
427 curSDigit = dynamic_cast<AliEMCALDigit*>(sdtclarr->At(index[i])) ;
431 //May be several digits will contribute from the same input
432 while(curSDigit && (curSDigit->GetId() == absID)){
433 //Shift primary to separate primaries belonging different inputs
434 Int_t primaryoffset ;
436 primaryoffset = fManager->GetMask(i) ;
439 curSDigit->ShiftPrimary(primaryoffset) ;
441 //Remove old timing model - JLK 28-April-2008
442 //a = curSDigit->GetAmplitude() ;
443 //b = a /fTimeSignalLength ;
444 //new((*ticks)[contrib++]) AliEMCALTick(curSDigit->GetTime(),0, b);
445 //new((*ticks)[contrib++]) AliEMCALTick(curSDigit->GetTime()+fTimeSignalLength, -a, -b);
446 if(curSDigit->GetAmplitude()>aTime) {
447 aTime = curSDigit->GetAmplitude();
448 time = curSDigit->GetTime();
451 *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
462 //Here we convert the summed amplitude to an energy in GeV
463 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ; // GeV
464 // add fluctuations for photo-electron creation
465 energy *= static_cast<Float_t>(gRandom->Poisson(fMeanPhotonElectron)) / static_cast<Float_t>(fMeanPhotonElectron) ;
467 //calculate and set time
468 //New timing model needed - JLK 28-April-2008
469 //Float_t time = FrontEdgeTime(ticks) ;
470 digit->SetTime(time) ;
472 //Find next signal module
474 for(i = 0 ; i < fInput ; i++){
475 sdigits = dynamic_cast<TClonesArray *>(sdigArray->At(i)) ;
477 Int_t curNext = nextSig ;
478 AliEMCALDigit * tmpdigit = dynamic_cast<AliEMCALDigit *>(sdigits->At(index[i]));
479 if(sdigits->GetEntriesFast() > index[i] && tmpdigit){
480 curNext = tmpdigit->GetId() ;
482 if(curNext < nextSig) nextSig = curNext ;
489 energy += TMath::Abs(gRandom->Gaus(0., fPinNoise)) ;
491 //Now digitize the energy according to the sDigitizer method,
492 //which merely converts the energy to an integer. Later we will
493 //check that the stored value matches our allowed dynamic ranges
494 digit->SetAmplitude(sDigitizer->Digitize(energy)) ;
495 AliDebug(10,Form(" absID %5i energy %f nextSig %5i\n",
496 absID, energy, nextSig));
497 }// Digit pointer exists
499 Info("Digitizer","Digit pointer is null");
501 } // for(absID = 0; absID < nEMC; absID++)
506 //JLK is it better to call Clear() here?
507 delete sdigArray ; //We should not delete its contents
509 //remove digits below thresholds
510 // until 10-02-2010 remove digits with energy smaller than fDigitThreshold 3*fPinNoise
511 // now, remove digits with Digitized ADC smaller than fDigitThreshold = 3
513 Float_t timeResolution = 0;
514 for(i = 0 ; i < nEMC ; i++){
515 digit = dynamic_cast<AliEMCALDigit*>( digits->At(i) ) ;
517 //First get the energy in GeV units.
518 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ;
519 //Then digitize using the calibration constants of the ocdb
520 Float_t ampADC = DigitizeEnergy(energy, digit->GetId()) ;
521 //if(ampADC>2)printf("Digit energy %f, amp %d, amp cal %d, threshold %d\n",energy,digit->GetAmplitude(),ampADC,fDigitThreshold);
522 if(ampADC < fDigitThreshold)
523 digits->RemoveAt(i) ;
525 timeResolution = GetTimeResolution(energy);
526 digit->SetTime(gRandom->Gaus(digit->GetTime(),timeResolution) ) ;
533 Int_t ndigits = digits->GetEntriesFast() ;
536 //After we have done the summing and digitizing to create the
537 //digits, now we want to calibrate the resulting amplitude to match
538 //the dynamic range of our real data.
539 for (i = 0 ; i < ndigits ; i++) {
540 digit = dynamic_cast<AliEMCALDigit *>( digits->At(i) ) ;
542 digit->SetIndexInList(i) ;
543 energy = sDigitizer->Calibrate(digit->GetAmplitude()) ;
544 digit->SetAmplitude(DigitizeEnergy(energy, digit->GetId()) ) ;
546 digit->SetTime(digit->GetTime()+fTimeDelay) ;
547 // printf("digit amplitude set at end: i %d, amp %f\n",i,digit->GetAmplitude());
551 }//SDigitizer not null
553 else AliFatal("EMCALLoader is NULL!") ;
557 // //_____________________________________________________________________
558 Float_t AliEMCALDigitizer::DigitizeEnergy(Float_t energy, Int_t AbsId)
561 // Returns digitized value of the energy in a cell absId
562 // using the calibration constants stored in the OCDB
563 // or default values if no CalibData object is found.
564 // This effectively converts everything to match the dynamic range
565 // of the real data we will collect
568 const AliEMCALGeometry * geom = AliEMCALGeometry::GetInstance();
570 Float_t channel = -999;
573 AliFatal("Did not get geometry from EMCALLoader");
582 Bool_t bCell = geom->GetCellIndex(AbsId, iSupMod, nModule, nIphi, nIeta) ;
584 Error("DigitizeEnergy","Wrong cell id number : AbsId %i ", AbsId) ;
585 geom->GetCellPhiEtaIndexInSModule(iSupMod,nModule,nIphi, nIeta,iphi,ieta);
588 fADCpedestalEC = fCalibData->GetADCpedestal(iSupMod,ieta,iphi);
589 fADCchannelEC = fCalibData->GetADCchannel(iSupMod,ieta,iphi);
592 //channel = static_cast<Int_t> (TMath::Floor( (energy + fADCpedestalEC)/fADCchannelEC )) ;
593 channel = (energy + fADCpedestalEC)/fADCchannelEC ;
595 if(channel > fNADCEC )
603 //____________________________________________________________________________
604 void AliEMCALDigitizer::Exec(Option_t *option)
606 // Steering method to process digitization for events
607 // in the range from fFirstEvent to fLastEvent.
608 // This range is optionally set by SetEventRange().
609 // if fLastEvent=-1, then process events until the end.
610 // by default fLastEvent = fFirstEvent (process only one event)
612 if (!fInit) { // to prevent overwrite existing file
613 Error( "Exec", "Give a version name different from %s", fEventFolderName.Data() ) ;
617 if (strstr(option,"print")) {
623 if(strstr(option,"tim"))
624 gBenchmark->Start("EMCALDigitizer");
626 AliRunLoader *rl = AliRunLoader::Instance();
627 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
630 AliFatal("Did not get the Loader");
633 // Post Digitizer to the white board
634 emcalLoader->PostDigitizer(this) ;
636 if (fLastEvent == -1) {
637 fLastEvent = rl->GetNumberOfEvents() - 1 ;
640 fLastEvent = fFirstEvent ; // what is this ??
642 nEvents = fLastEvent - fFirstEvent + 1;
645 TClonesArray* digitsTMP = new TClonesArray("AliEMCALDigit", 32*96);
646 TClonesArray* digitsTRG = new TClonesArray("AliEMCALRawDigit", 32*96);
648 rl->LoadSDigits("EMCAL");
649 for (ievent = fFirstEvent; ievent <= fLastEvent; ievent++) {
651 rl->GetEvent(ievent);
653 Digitize(ievent) ; //Add prepared SDigits to digits and add the noise
658 //-------------------------------------
661 Digits2FastOR(digitsTMP, digitsTRG);
663 WriteDigits(digitsTRG);
665 (emcalLoader->TreeD())->Fill();
667 emcalLoader->WriteDigits( "OVERWRITE");
668 emcalLoader->WriteDigitizer("OVERWRITE");
672 digitsTRG ->Delete();
673 digitsTMP ->Delete();
675 //-------------------------------------
677 if(strstr(option,"deb"))
679 if(strstr(option,"table")) gObjectTable->Print();
681 //increment the total number of Digits per run
682 fDigitsInRun += emcalLoader->Digits()->GetEntriesFast() ;
685 emcalLoader->CleanDigitizer() ;
689 if(strstr(option,"tim")){
690 gBenchmark->Stop("EMCALDigitizer");
691 AliInfo(Form("Exec: took %f seconds for Digitizing %f seconds per event",
692 gBenchmark->GetCpuTime("EMCALDigitizer"), gBenchmark->GetCpuTime("EMCALDigitizer")/nEvents )) ;
696 //__________________________________________________________________
697 Float_t AliEMCALDigitizer::GetTimeResolution(Float_t energy) const
702 res = TMath::Sqrt(fTimeResolutionPar0 +
703 fTimeResolutionPar1/(energy*energy) );
709 //____________________________________________________________________________
710 void AliEMCALDigitizer::Digits2FastOR(TClonesArray* digitsTMP, TClonesArray* digitsTRG)
712 // FEE digits afterburner to produce TRG digits
713 // we are only interested in the FEE digit deposited energy
714 // to be converted later into a voltage value
716 // push the FEE digit to its associated FastOR (numbered from 0:95)
717 // TRU is in charge of summing module digits
719 AliRunLoader *runLoader = AliRunLoader::Instance();
721 AliRun* run = runLoader->GetAliRun();
723 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(runLoader->GetDetectorLoader("EMCAL"));
725 AliFatal("Did not get the Loader");
728 AliEMCAL* emcal = dynamic_cast<AliEMCAL*>(run->GetDetector("EMCAL"));
730 AliEMCALGeometry* geom = emcal->GetGeometry();
732 // build FOR from simulated digits
733 // and xfer to the corresponding TRU input (mapping)
735 TClonesArray* digits = emcalLoader->Digits();
737 TIter NextDigit(digits);
738 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
740 Int_t id = digit->GetId();
743 if (geom && geom->GetFastORIndexFromCellIndex(id , trgid))
745 AliDebug(1,Form("trigger digit id: %d from cell id: %d\n",trgid,id));
747 AliEMCALDigit* d = static_cast<AliEMCALDigit*>(digitsTMP->At(trgid));
751 new((*digitsTMP)[trgid]) AliEMCALDigit(*digit);
752 d = (AliEMCALDigit*)digitsTMP->At(trgid);
762 if (AliDebugLevel()) printf("Number of TRG digits: %d\n",digitsTMP->GetEntriesFast());
765 Int_t *timeSamples = new Int_t[nSamples];
767 NextDigit = TIter(digitsTMP);
768 while (AliEMCALDigit* digit = (AliEMCALDigit*)NextDigit())
772 Int_t id = digit->GetId();
773 Float_t time = digit->GetTime();
775 Double_t depositedEnergy = 0.;
776 for (Int_t j = 1; j <= digit->GetNprimary(); j++) depositedEnergy += digit->GetDEPrimary(j);
778 if (AliDebugLevel()) printf("Deposited Energy: %f\n", depositedEnergy);
780 // FIXME: Check digit time!
783 DigitalFastOR(time, depositedEnergy, timeSamples, nSamples);
785 for (Int_t j=0;j<nSamples;j++)
787 timeSamples[j] = ((j << 12) & 0xFF000) | (timeSamples[j] & 0xFFF);
790 new((*digitsTRG)[digitsTRG->GetEntriesFast()]) AliEMCALRawDigit(id, timeSamples, nSamples);
795 delete [] timeSamples;
797 else AliFatal("Could not get AliEMCAL");
802 //____________________________________________________________________________
803 void AliEMCALDigitizer::DigitalFastOR( Double_t time, Double_t dE, Int_t timeSamples[], Int_t nSamples )
807 const Int_t reso = 11; // 11-bit resolution ADC
808 const Double_t vFSR = 1; // Full scale input voltage range
809 const Double_t dNe = 125; // signal of the APD per MeV of energy deposit in a tower: 125 photo-e-/MeV @ M=30
810 const Double_t vA = .136e-6; // CSP output range: 0.136uV/e-
811 const Double_t rise = 40e-9; // rise time (10-90%) of the FastOR signal before shaping
813 const Double_t kTimeBinWidth = 25E-9; // sampling frequency (40MHz)
815 Double_t vV = 1000. * dE * dNe * vA; // GeV 2 MeV
817 TF1 signalF("signal", AnalogFastORFunction, 0, nSamples * kTimeBinWidth, 3);
818 signalF.SetParameter( 0, vV );
819 signalF.SetParameter( 1, time ); // FIXME: when does the signal arrive? Might account for cable lengths
820 signalF.SetParameter( 2, rise );
822 for (Int_t iTime=0; iTime<nSamples; iTime++)
824 // FIXME: add noise (probably not simply Gaussian) according to DA measurements
825 // probably plan an access to OCDB
827 timeSamples[iTime] = int((TMath::Power(2, reso) / vFSR) * signalF.Eval(iTime * kTimeBinWidth) + 0.5);
832 //____________________________________________________________________________
833 //Float_t AliEMCALDigitizer::FrontEdgeTime(TClonesArray * ticks)
835 // // Returns the shortest time among all time ticks
837 // ticks->Sort() ; //Sort in accordance with times of ticks
839 // AliEMCALTick * ctick = (AliEMCALTick *) it.Next() ;
840 // Float_t time = ctick->CrossingTime(fTimeThreshold) ;
842 // AliEMCALTick * t ;
843 // while((t=(AliEMCALTick*) it.Next())){
844 // if(t->GetTime() < time) //This tick starts before crossing
849 // time = ctick->CrossingTime(fTimeThreshold) ;
855 //____________________________________________________________________________
856 Bool_t AliEMCALDigitizer::Init()
858 // Makes all memory allocations
860 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
862 if ( emcalLoader == 0 ) {
863 Fatal("Init", "Could not obtain the AliEMCALLoader");
868 fLastEvent = fFirstEvent ;
871 fInput = fManager->GetNinputs() ;
875 fInputFileNames = new TString[fInput] ;
876 fEventNames = new TString[fInput] ;
877 fInputFileNames[0] = GetTitle() ;
878 fEventNames[0] = fEventFolderName.Data() ;
880 for (index = 1 ; index < fInput ; index++) {
881 fInputFileNames[index] = dynamic_cast<AliStream*>(fManager->GetInputStream(index))->GetFileName(0);
882 TString tempo = fManager->GetInputFolderName(index) ;
883 fEventNames[index] = tempo.Remove(tempo.Length()-1) ; // strip of the stream number added bt fManager
886 //to prevent cleaning of this object while GetEvent is called
887 emcalLoader->GetDigitsDataLoader()->GetBaseTaskLoader()->SetDoNotReload(kTRUE);
889 //Calibration instance
890 fCalibData = emcalLoader->CalibData();
894 //____________________________________________________________________________
895 void AliEMCALDigitizer::InitParameters()
897 // Parameter initialization for digitizer
899 // Get the parameters from the OCDB via the loader
900 AliRunLoader *rl = AliRunLoader::Instance();
901 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
902 AliEMCALSimParam * simParam = 0x0;
903 if(emcalLoader) simParam = emcalLoader->SimulationParameters();
906 simParam = AliEMCALSimParam::GetInstance();
907 AliWarning("Simulation Parameters not available in OCDB?");
910 fMeanPhotonElectron = simParam->GetMeanPhotonElectron();//4400; // electrons per GeV
911 fPinNoise = simParam->GetPinNoise();//0.012; // pin noise in GeV from analysis test beam data
912 if (fPinNoise < 0.0001 )
913 Warning("InitParameters", "No noise added\n") ;
914 fDigitThreshold = simParam->GetDigitThreshold(); //fPinNoise * 3; // 3 * sigma
915 fTimeResolutionPar0 = simParam->GetTimeResolutionPar0();
916 fTimeResolutionPar1 = simParam->GetTimeResolutionPar1();
917 fTimeDelay = simParam->GetTimeDelay(); //600e-9 ; // 600 ns
919 // These defaults are normally not used.
920 // Values are read from calibration database instead
921 fADCchannelEC = 0.0153; // Update 24 Apr 2007: 250./16/1024 - width of one ADC channel in GeV
922 fADCpedestalEC = 0.0 ; // GeV
924 fNADCEC = simParam->GetNADCEC();//(Int_t) TMath::Power(2,16) ; // number of channels in Tower ADC - 65536
926 AliDebug(2,Form("Mean Photon Electron %d, Noise %f, Digit Threshold %d,Time Resolution Par0 %g Par1 %g,NADCEC %d",
927 fMeanPhotonElectron,fPinNoise,fDigitThreshold,fTimeResolutionPar0,fTimeResolutionPar1,fNADCEC));
929 // Not used anymore, remove?
930 // fTimeSignalLength = 1.0e-9 ;
931 // fTimeThreshold = 0.001*10000000 ; // Means 1 MeV in terms of SDigits amplitude ??
935 //__________________________________________________________________
936 void AliEMCALDigitizer::MixWith(TString alirunFileName, TString eventFolderName)
938 // Allows to produce digits by superimposing background and signal event.
939 // It is assumed, that headers file with SIGNAL events is opened in
941 // Sets the BACKGROUND event, with which the SIGNAL event is to be mixed
942 // Thus we avoid writing (changing) huge and expensive
943 // backgound files: all output will be writen into SIGNAL, i.e.
944 // opened in constructor file.
946 // One can open as many files to mix with as one needs.
947 // However only Sdigits with the same name (i.e. constructed with the same SDigitizer)
950 if( strcmp(GetName(), "") == 0 )
954 Error("MixWith", "Cannot use this method under AliRunDigitizer") ;
957 // looking for file which contains AliRun
958 if (gSystem->AccessPathName(alirunFileName)) {// file does not exist
959 Error("MixWith", "File %s does not exist!", alirunFileName.Data()) ;
962 // looking for the file which contains SDigits
963 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
966 AliFatal("Did not get the Loader");
969 TString fileName( emcalLoader->GetSDigitsFileName() ) ;
970 if ( eventFolderName != AliConfig::GetDefaultEventFolderName()) // only if not the default folder name
971 fileName = fileName.ReplaceAll(".root", "") + "_" + eventFolderName + ".root" ;
972 if ( (gSystem->AccessPathName(fileName)) ) {
973 Error("MixWith", "The file %s does not exist!", fileName.Data()) ;
976 // need to increase the arrays
977 // MvL: This code only works when fInput == 1, I think.
978 TString tempo = fInputFileNames[fInput-1] ;
979 delete [] fInputFileNames ;
980 fInputFileNames = new TString[fInput+1] ;
981 fInputFileNames[fInput-1] = tempo ;
983 tempo = fEventNames[fInput-1] ;
984 delete [] fEventNames ;
985 fEventNames = new TString[fInput+1] ;
986 fEventNames[fInput-1] = tempo ;
988 fInputFileNames[fInput] = alirunFileName ;
989 fEventNames[fInput] = eventFolderName ;
996 //__________________________________________________________________
997 void AliEMCALDigitizer::Print1(Option_t * option)
998 { // 19-nov-04 - just for convinience
1000 PrintDigits(option);
1003 //__________________________________________________________________
1004 void AliEMCALDigitizer::Print(Option_t*)const
1006 // Print Digitizer's parameters
1007 printf("Print: \n------------------- %s -------------", GetName() ) ;
1008 if( strcmp(fEventFolderName.Data(), "") != 0 ){
1009 printf(" Writing Digits to branch with title %s\n", fEventFolderName.Data()) ;
1013 nStreams = GetNInputStreams() ;
1020 for (index = 0 ; index < nStreams ; index++) {
1021 TString tempo(fEventNames[index]) ;
1023 if ((rl = AliRunLoader::GetRunLoader(tempo)) == 0)
1024 rl = AliRunLoader::Open(fInputFileNames[index], tempo) ;
1025 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(rl->GetDetectorLoader("EMCAL"));
1027 TString fileName( emcalLoader->GetSDigitsFileName() ) ;
1028 if ( fEventNames[index] != AliConfig::GetDefaultEventFolderName()) // only if not the default folder name
1029 fileName = fileName.ReplaceAll(".root", "") + "_" + fEventNames[index] + ".root" ;
1030 printf ("Adding SDigits from %s %s\n", fInputFileNames[index].Data(), fileName.Data()) ;
1034 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1036 if(emcalLoader) printf("\nWriting digits to %s", emcalLoader->GetDigitsFileName().Data()) ;
1037 else printf("\nNULL LOADER");
1039 printf("\nWith following parameters:\n") ;
1041 printf(" Electronics noise in EMC (fPinNoise) = %f\n", fPinNoise) ;
1042 printf(" Threshold in Tower (fDigitThreshold) = %d\n", fDigitThreshold) ;
1043 printf("---------------------------------------------------\n") ;
1046 printf("Print: AliEMCALDigitizer not initialized") ;
1049 //__________________________________________________________________
1050 void AliEMCALDigitizer::PrintDigits(Option_t * option)
1052 //utility method for printing digit information
1054 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1056 TClonesArray * digits = emcalLoader->Digits() ;
1057 TClonesArray * sdigits = emcalLoader->SDigits() ;
1059 printf("\n #Digits: %d : sdigits %d ", digits->GetEntriesFast(), sdigits->GetEntriesFast()) ;
1060 printf("\n event %d", emcalLoader->GetRunLoader()->GetEventNumber());
1062 if(strstr(option,"all")){
1064 AliEMCALDigit * digit;
1065 printf("\nEMC digits (with primaries):\n") ;
1066 printf("\n Id Amplitude Time Index Nprim: Primaries list \n") ;
1068 for (index = 0 ; index < digits->GetEntries() ; index++) {
1069 digit = dynamic_cast<AliEMCALDigit *>(digits->At(index)) ;
1071 printf("\n%6d %8f %6.5e %4d %2d : ",
1072 digit->GetId(), digit->GetAmplitude(), digit->GetTime(), digit->GetIndexInList(), digit->GetNprimary()) ;
1074 for (iprimary=0; iprimary<digit->GetNprimary(); iprimary++) {
1075 printf("%d ",digit->GetPrimary(iprimary+1) ) ;
1082 else printf("NULL LOADER, cannot print\n");
1085 //__________________________________________________________________
1086 Float_t AliEMCALDigitizer::TimeOfNoise(void)
1088 // Calculates the time signal generated by noise
1089 //PH Info("TimeOfNoise", "Change me") ;
1090 return gRandom->Rndm() * 1.28E-5;
1093 //__________________________________________________________________
1094 void AliEMCALDigitizer::Unload()
1096 // Unloads the SDigits and Digits
1100 for(i = 1 ; i < fInput ; i++){
1101 TString tempo(fEventNames[i]) ;
1103 if ((rl = AliRunLoader::GetRunLoader(tempo)))
1104 rl->GetDetectorLoader("EMCAL")->UnloadSDigits() ;
1106 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1107 if(emcalLoader)emcalLoader->UnloadDigits() ;
1108 else AliFatal("Did not get the loader");
1111 //_________________________________________________________________________________________
1112 void AliEMCALDigitizer::WriteDigits()
1113 { // Makes TreeD in the output file.
1114 // Check if branch already exists:
1115 // if yes, exit without writing: ROOT TTree does not support overwriting/updating of
1116 // already existing branches.
1117 // else creates branch with Digits, named "EMCAL", title "...",
1118 // and branch "AliEMCALDigitizer", with the same title to keep all the parameters
1119 // and names of files, from which digits are made.
1121 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1124 const TClonesArray * digits = emcalLoader->Digits() ;
1125 TTree * treeD = emcalLoader->TreeD();
1127 emcalLoader->MakeDigitsContainer();
1128 treeD = emcalLoader->TreeD();
1131 // -- create Digits branch
1132 Int_t bufferSize = 32000 ;
1133 TBranch * digitsBranch = 0;
1134 if ((digitsBranch = treeD->GetBranch("EMCAL"))) {
1135 digitsBranch->SetAddress(&digits);
1136 AliWarning("Digits Branch already exists. Not all digits will be visible");
1139 treeD->Branch("EMCAL","TClonesArray",&digits,bufferSize);
1140 //digitsBranch->SetTitle(fEventFolderName);
1144 emcalLoader->WriteDigits("OVERWRITE");
1145 emcalLoader->WriteDigitizer("OVERWRITE");
1151 else AliFatal("Loader not available");
1154 //__________________________________________________________________
1155 void AliEMCALDigitizer::WriteDigits(TClonesArray* digits, const char* branchName)
1156 { // overloaded method
1157 AliEMCALLoader *emcalLoader = dynamic_cast<AliEMCALLoader*>(AliRunLoader::Instance()->GetDetectorLoader("EMCAL"));
1160 TTree* treeD = emcalLoader->TreeD();
1163 emcalLoader->MakeDigitsContainer();
1164 treeD = emcalLoader->TreeD();
1167 // -- create Digits branch
1168 Int_t bufferSize = 32000;
1170 if (TBranch* triggerBranch = treeD->GetBranch(branchName))
1172 triggerBranch->SetAddress(&digits);
1176 treeD->Branch(branchName,"TClonesArray",&digits,bufferSize);
1181 else AliFatal("Loader not available");
1184 //__________________________________________________________________
1185 void AliEMCALDigitizer::Browse(TBrowser* b)