CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/SimCalorimetry/EcalSimAlgos/src/ESDigitizer.cc

Go to the documentation of this file.
00001 #include "SimCalorimetry/EcalSimAlgos/interface/ESDigitizer.h"
00002 #include "SimCalorimetry/EcalSimAlgos/interface/ESElectronicsSimFast.h"
00003 #include "SimCalorimetry/EcalSimAlgos/interface/ESHitResponse.h"
00004 #include "SimDataFormats/CaloHit/interface/PCaloHit.h"
00005 
00006 #include "FWCore/ServiceRegistry/interface/Service.h"
00007 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00008 #include "CLHEP/Random/RandGeneral.h"
00009 #include "CLHEP/Random/RandPoissonQ.h"
00010 #include "CLHEP/Random/RandFlat.h"
00011 
00012 #include <gsl/gsl_sf_erf.h>
00013 #include <gsl/gsl_sf_result.h>
00014 
00015 ESDigitizer::ESDigitizer( EcalHitResponse*      hitResponse    , 
00016                           ESElectronicsSimFast* electronicsSim ,
00017                           bool                  addNoise         ) :
00018    EcalTDigitizer< ESDigitizerTraits >( hitResponse, electronicsSim, addNoise ) ,
00019    m_detIds      ( 0              ) ,
00020    m_engine      ( 0              ) ,
00021    m_ranGeneral  ( 0              ) ,
00022    m_ranPois     ( 0              ) ,
00023    m_ranFlat     ( 0              ) ,
00024    m_ESGain      ( 0              ) ,
00025    m_histoBin    ( 0              ) ,
00026    m_histoInf    ( 0              ) ,
00027    m_histoWid    ( 0              ) ,
00028    m_meanNoisy   ( 0              ) ,
00029    m_trip        (                )
00030 {
00031    m_trip.reserve( 2500 ) ; 
00032 
00033    edm::Service<edm::RandomNumberGenerator> rng ;
00034    if( !rng.isAvailable() )
00035    {
00036       throw cms::Exception( "Configuration" )
00037          << "ESDigitizer requires the RandomNumberGeneratorService\n"
00038          "which is not present in the configuration file.  You must add the service\n"
00039          "in the configuration file or remove the modules that require it.";
00040    }
00041    m_engine = &rng->getEngine() ;
00042 }
00043 
00044 ESDigitizer::~ESDigitizer() 
00045 {
00046    delete m_ranGeneral ;
00047    delete m_ranPois    ;
00048    delete m_ranFlat    ;
00049 }
00050 
00052 void 
00053 ESDigitizer::setDetIds( const std::vector<DetId>& detIds )
00054 {
00055    assert( 0       == m_detIds ||
00056            &detIds == m_detIds    ) ; // sanity check; don't allow to change midstream
00057    m_detIds = &detIds ;
00058 }
00059 
00060 void 
00061 ESDigitizer::setGain( const int gain ) 
00062 {
00063    if( 0 != m_ESGain )
00064    {
00065       assert( gain == m_ESGain ) ; // only allow one value
00066    }
00067    else
00068    {
00069       assert( 0 != m_detIds &&
00070               0 != m_detIds->size() ) ; // detIds must already be set as we need size
00071 
00072       assert( 1 == gain ||
00073               2 == gain    ) ; // legal values
00074       
00075       m_ESGain = gain ;
00076       
00077       if( addNoise() ) 
00078       {
00079          assert( 0 != m_engine ) ; // sanity check
00080 
00081          double zsThresh ( 0. ) ;
00082          std::string refFile ;
00083 
00084          if( 1 == m_ESGain ) 
00085          {
00086             zsThresh = 3 ;
00087             refFile = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_LG.txt";
00088          }
00089          else
00090          {
00091             zsThresh = 4 ;
00092             refFile = "SimCalorimetry/EcalSimProducers/data/esRefHistosFile_HG.txt";
00093          }
00094 
00095          gsl_sf_result result ;
00096          int status  = gsl_sf_erf_Q_e( zsThresh, &result ) ;
00097          if( status != 0 ) std::cerr << "ESDigitizer::could not compute gaussian tail probability for the threshold chosen" << std::endl ;
00098 
00099          const double probabilityLeft ( result.val ) ;
00100          m_meanNoisy = probabilityLeft * m_detIds->size() ;
00101 
00102          m_ranPois = new CLHEP::RandPoissonQ( *m_engine, m_meanNoisy      ) ;
00103          m_ranFlat = new CLHEP::RandFlat(     *m_engine, m_detIds->size() ) ;
00104 
00105          std::ifstream histofile ( edm::FileInPath( refFile ).fullPath().c_str() ) ;
00106          if( !histofile.good() )
00107          { 
00108             throw edm::Exception(edm::errors::InvalidReference,"NullPointer")
00109                << "Reference histos file not opened" ;
00110          }
00111          else
00112          {
00113             // number of bins
00114             char buffer[200] ;
00115             int thisLine = 0 ;
00116             while( 0 == thisLine ) 
00117             {
00118                histofile.getline( buffer, 200 ) ;
00119                if( !strstr(buffer,"#")  && 
00120                    !(strspn(buffer," ") == strlen(buffer) ) )
00121                {        
00122                   float histoBin ; 
00123                   sscanf( buffer, "%f" , &histoBin ) ; 
00124                   m_histoBin = (double) histoBin ;
00125                   ++thisLine ;
00126                }
00127             }
00128             const uint32_t histoBin1 ( (int) m_histoBin    ) ;
00129             const uint32_t histoBin2 ( histoBin1*histoBin1 ) ;
00130 
00131             double t_histoSup ( 0 ) ;
00132 
00133             std::vector<double> t_refHistos ;
00134             t_refHistos.reserve( 2500 ) ;
00135 
00136             int thisBin = -2 ;
00137             while( !( histofile.eof() ) )
00138             {
00139                histofile.getline( buffer, 200 ) ;
00140                if( !strstr( buffer, "#" ) &&
00141                    !( strspn( buffer, " " ) == strlen( buffer ) ) )
00142                {
00143                   if( -2 == thisBin )
00144                   {
00145                      float histoInf ;
00146                      sscanf( buffer, "%f" , &histoInf ) ;
00147                      m_histoInf = (double) histoInf ;
00148                   }
00149                   if( -1 == thisBin  )
00150                   {
00151                      float histoSup ;
00152                      sscanf( buffer, "%f" , &histoSup ) ;
00153                      t_histoSup = (double) histoSup ;
00154                   }
00155                   if( 0 <= thisBin )
00156                   { 
00157                      float refBin ; 
00158                      sscanf( buffer, "%f", &refBin ) ;
00159                      if( 0.5 < refBin ) 
00160                      {
00161                         t_refHistos.push_back( (double) refBin ) ;
00162                         const uint32_t i2 ( thisBin/histoBin2 ) ;
00163                         const uint32_t off ( i2*histoBin2 ) ;
00164                         const uint32_t i1 ( ( thisBin - off )/histoBin1 ) ;
00165                         const uint32_t i0 ( thisBin - off - i1*histoBin1 ) ;
00166                         m_trip.push_back( Triplet( i0, i1, i2 ) ) ;
00167                      }
00168                   }
00169                   ++thisBin ;
00170                }
00171             }
00172             m_histoWid = ( t_histoSup - m_histoInf )/m_histoBin ;
00173 
00174             m_histoInf -= 1000. ;
00175 
00176             // creating the reference distribution to extract random numbers
00177             m_ranGeneral = new CLHEP::RandGeneral( *m_engine            ,
00178                                                    &t_refHistos.front() ,
00179                                                    t_refHistos.size()   ,
00180                                                    0             ) ;
00181             histofile.close();
00182          }
00183       }
00184    }
00185 }
00186 
00188 void 
00189 ESDigitizer::run( MixCollection<PCaloHit>& input  ,
00190                   ESDigiCollection&        output   )
00191 {
00192     assert( 0 != m_detIds         &&
00193             0 != m_detIds->size() &&
00194             ( !addNoise()         ||
00195               ( 0 != m_engine     &&
00196                 0 != m_ranPois    &&
00197                 0 != m_ranFlat    &&
00198                 0 != m_ranGeneral        ) ) ) ; // sanity check
00199 
00200     // reserve space for how many digis we expect, with some cushion
00201     output.reserve( 2*( (int) m_meanNoisy ) + hitResponse()->samplesSize() ) ;
00202 
00203     EcalTDigitizer< ESDigitizerTraits >::run( input, output ) ;
00204 
00205     // random generation of channel above threshold
00206     std::vector<DetId> abThreshCh ;
00207     if( addNoise() ) createNoisyList( abThreshCh ) ;
00208 
00209     // first make a raw digi for every cell where we have noise
00210     for( std::vector<DetId>::const_iterator idItr ( abThreshCh.begin() ) ;
00211          idItr != abThreshCh.end(); ++idItr ) 
00212     {
00213        if( hitResponse()->findDetId( *idItr )->zero() ) // only if no true hit!
00214        {
00215           ESHitResponse::ESSamples analogSignal ( *idItr, 3 ) ; // space for the noise hit
00216           uint32_t myBin ( (uint32_t) m_trip.size()*m_ranGeneral->fire() ) ;
00217           if( myBin == m_trip.size() ) --myBin ; // guard against roundup
00218           assert( myBin < m_trip.size() ) ;
00219           const Triplet& trip ( m_trip[ myBin ] ) ;
00220           analogSignal[ 0 ] = m_histoInf + m_histoWid*trip.first  ;
00221           analogSignal[ 1 ] = m_histoInf + m_histoWid*trip.second ;
00222           analogSignal[ 2 ] = m_histoInf + m_histoWid*trip.third  ;
00223           ESDataFrame digi( *idItr ) ;
00224           const_cast<ESElectronicsSimFast*>(elecSim())->
00225              analogToDigital( analogSignal ,
00226                               digi         ,
00227                               true           ) ;        
00228           output.push_back( digi ) ;  
00229        }
00230     }
00231 }
00232 
00233 // preparing the list of channels where the noise has to be generated
00234 void 
00235 ESDigitizer::createNoisyList( std::vector<DetId>& abThreshCh )
00236 {
00237    const unsigned int nChan ( m_ranPois->fire() ) ;
00238    abThreshCh.reserve( nChan ) ;
00239 
00240    for( unsigned int i ( 0 ) ; i != nChan ; ++i )
00241    {
00242       std::vector<DetId>::const_iterator idItr ( abThreshCh.end() ) ;
00243       uint32_t iChan ( 0 ) ;
00244       DetId id ;
00245       do 
00246       {
00247          iChan = (uint32_t) m_ranFlat->fire() ;
00248          if( iChan == m_detIds->size() ) --iChan ; //protect against roundup at end
00249          assert( m_detIds->size() > iChan ) ;      // sanity check
00250          id = (*m_detIds)[ iChan ] ;
00251          idItr = find( abThreshCh.begin() ,
00252                        abThreshCh.end()   ,
00253                        id                  ) ;
00254       }
00255       while( idItr != abThreshCh.end() ) ;
00256 
00257       abThreshCh.push_back( id ) ;
00258    }
00259 }