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 ) ;
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 ) ;
00066 }
00067 else
00068 {
00069 assert( 0 != m_detIds &&
00070 0 != m_detIds->size() ) ;
00071
00072 assert( 1 == gain ||
00073 2 == gain ) ;
00074
00075 m_ESGain = gain ;
00076
00077 if( addNoise() )
00078 {
00079 assert( 0 != m_engine ) ;
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
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
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 ) ) ) ;
00199
00200
00201 output.reserve( 2*( (int) m_meanNoisy ) + hitResponse()->samplesSize() ) ;
00202
00203 EcalTDigitizer< ESDigitizerTraits >::run( input, output ) ;
00204
00205
00206 std::vector<DetId> abThreshCh ;
00207 if( addNoise() ) createNoisyList( abThreshCh ) ;
00208
00209
00210 for( std::vector<DetId>::const_iterator idItr ( abThreshCh.begin() ) ;
00211 idItr != abThreshCh.end(); ++idItr )
00212 {
00213 if( hitResponse()->findDetId( *idItr )->zero() )
00214 {
00215 ESHitResponse::ESSamples analogSignal ( *idItr, 3 ) ;
00216 uint32_t myBin ( (uint32_t) m_trip.size()*m_ranGeneral->fire() ) ;
00217 if( myBin == m_trip.size() ) --myBin ;
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
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 ;
00249 assert( m_detIds->size() > iChan ) ;
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 }