LCOV - code coverage report
Current view: top level - EMCAL/EMCALbase - AliEMCALDigitizer.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 386 683 56.5 %
Date: 2016-06-14 17:26:59 Functions: 23 33 69.7 %

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

Generated by: LCOV version 1.11