Go to the documentation of this file.00001 #include "SimCalorimetry/EcalSimAlgos/interface/EcalHitResponse.h"
00002 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVSimParameterMap.h"
00003 #include "SimCalorimetry/CaloSimAlgos/interface/CaloSimParameters.h"
00004 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVShape.h"
00005 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVHitCorrection.h"
00006 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVHitFilter.h"
00007 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVPECorrection.h"
00008 #include "Geometry/CaloGeometry/interface/CaloGenericDetId.h"
00009 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00010 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00011 #include "FWCore/ServiceRegistry/interface/Service.h"
00012 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00013 #include "CLHEP/Random/RandPoissonQ.h"
00014 #include "CLHEP/Random/RandGaussQ.h"
00015 #include "FWCore/Utilities/interface/Exception.h"
00016
00017 #include "CLHEP/Units/GlobalPhysicalConstants.h"
00018 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00019 #include <iostream>
00020
00021
00022
00023 EcalHitResponse::EcalHitResponse( const CaloVSimParameterMap* parameterMap ,
00024 const CaloVShape* shape ) :
00025 m_parameterMap ( parameterMap ) ,
00026 m_shape ( shape ) ,
00027 m_hitCorrection ( 0 ) ,
00028 m_PECorrection ( 0 ) ,
00029 m_hitFilter ( 0 ) ,
00030 m_geometry ( 0 ) ,
00031 m_RandPoisson ( 0 ) ,
00032 m_RandGauss ( 0 ) ,
00033 m_minBunch ( -10 ) ,
00034 m_maxBunch ( 10 ) ,
00035 m_phaseShift ( 1 )
00036 {
00037 edm::Service<edm::RandomNumberGenerator> rng ;
00038 if ( !rng.isAvailable() )
00039 {
00040 throw cms::Exception("Configuration")
00041 << "EcalHitResponse requires the RandomNumberGeneratorService\n"
00042 "which is not present in the configuration file. You must add the service\n"
00043 "in the configuration file or remove the modules that require it.";
00044 }
00045 m_RandPoisson = new CLHEP::RandPoissonQ( rng->getEngine() ) ;
00046 m_RandGauss = new CLHEP::RandGaussQ( rng->getEngine() ) ;
00047 }
00048
00049 EcalHitResponse::~EcalHitResponse()
00050 {
00051 delete m_RandPoisson ;
00052 delete m_RandGauss ;
00053 }
00054
00055 CLHEP::RandPoissonQ*
00056 EcalHitResponse::ranPois() const
00057 {
00058 return m_RandPoisson ;
00059 }
00060
00061 CLHEP::RandGaussQ*
00062 EcalHitResponse::ranGauss() const
00063 {
00064 return m_RandGauss ;
00065 }
00066
00067 const CaloSimParameters*
00068 EcalHitResponse::params( const DetId& detId ) const
00069 {
00070 assert( 0 != m_parameterMap ) ;
00071 return &m_parameterMap->simParameters( detId ) ;
00072 }
00073
00074 const CaloVShape*
00075 EcalHitResponse::shape() const
00076 {
00077 assert( 0 != m_shape ) ;
00078 return m_shape ;
00079 }
00080
00081 const CaloSubdetectorGeometry*
00082 EcalHitResponse::geometry() const
00083 {
00084 assert( 0 != m_geometry ) ;
00085 return m_geometry ;
00086 }
00087
00088 void
00089 EcalHitResponse::setBunchRange( int minBunch ,
00090 int maxBunch )
00091 {
00092 m_minBunch = minBunch ;
00093 m_maxBunch = maxBunch ;
00094 }
00095
00096 void
00097 EcalHitResponse::setGeometry( const CaloSubdetectorGeometry* geometry )
00098 {
00099 m_geometry = geometry ;
00100 }
00101
00102 void
00103 EcalHitResponse::setPhaseShift( double phaseShift )
00104 {
00105 m_phaseShift = phaseShift ;
00106 }
00107
00108 double
00109 EcalHitResponse::phaseShift() const
00110 {
00111 return m_phaseShift ;
00112 }
00113
00114 void
00115 EcalHitResponse::setHitFilter( const CaloVHitFilter* filter)
00116 {
00117 m_hitFilter = filter ;
00118 }
00119
00120 void
00121 EcalHitResponse::setHitCorrection( const CaloVHitCorrection* hitCorrection)
00122 {
00123 m_hitCorrection = hitCorrection ;
00124 }
00125
00126 void
00127 EcalHitResponse::setPECorrection( const CaloVPECorrection* peCorrection )
00128 {
00129 m_PECorrection = peCorrection ;
00130 }
00131
00132 void
00133 EcalHitResponse::blankOutUsedSamples()
00134 {
00135 const unsigned int size ( m_index.size() ) ;
00136
00137 for( unsigned int i ( 0 ) ; i != size ; ++i )
00138 {
00139 vSamAll( m_index[i] )->setZero() ;
00140 }
00141 m_index.erase( m_index.begin() ,
00142 m_index.end() ) ;
00143 }
00144
00145 void
00146 EcalHitResponse::run( MixCollection<PCaloHit>& hits )
00147 {
00148 blankOutUsedSamples() ;
00149
00150 for( MixCollection<PCaloHit>::MixItr hitItr ( hits.begin() ) ;
00151 hitItr != hits.end() ; ++hitItr )
00152 {
00153 const PCaloHit& hit ( *hitItr ) ;
00154 const int bunch ( hitItr.bunch() ) ;
00155 if( m_minBunch <= bunch &&
00156 m_maxBunch >= bunch &&
00157 !isnan( hit.time() ) &&
00158 ( 0 == m_hitFilter ||
00159 m_hitFilter->accepts( hit ) ) ) putAnalogSignal( hit ) ;
00160 }
00161 }
00162
00163 void
00164 EcalHitResponse::putAnalogSignal( const PCaloHit& inputHit )
00165 {
00166 PCaloHit hit ( inputHit ) ;
00167
00168 if( 0 != m_hitCorrection ) m_hitCorrection->correct( hit ) ;
00169
00170 const DetId detId ( hit.id() ) ;
00171
00172 const CaloSimParameters* parameters ( params( detId ) ) ;
00173
00174 const double signal ( analogSignalAmplitude( hit ) ) ;
00175
00176 const double jitter ( hit.time() - timeOfFlight( detId ) ) ;
00177
00178 const double tzero = ( shape()->timeToRise()
00179 + parameters->timePhase()
00180 - jitter
00181 - BUNCHSPACE*( parameters->binOfMaximum()
00182 - m_phaseShift ) ) ;
00183 double binTime ( tzero ) ;
00184
00185 EcalSamples& result ( *findSignal( detId ) ) ;
00186
00187 const unsigned int rsize ( result.size() ) ;
00188
00189 for( unsigned int bin ( 0 ) ; bin != rsize ; ++bin )
00190 {
00191 result[ bin ] += (*shape())( binTime )*signal ;
00192 binTime += BUNCHSPACE ;
00193 }
00194 }
00195
00196 EcalHitResponse::EcalSamples*
00197 EcalHitResponse::findSignal( const DetId& detId )
00198 {
00199 const unsigned int di ( CaloGenericDetId( detId ).denseIndex() ) ;
00200 EcalSamples* result ( vSamAll( di ) ) ;
00201 if( result->zero() ) m_index.push_back( di ) ;
00202 return result ;
00203 }
00204
00205 double
00206 EcalHitResponse::analogSignalAmplitude( const PCaloHit& hit ) const
00207 {
00208 const DetId& detId ( hit.id() ) ;
00209
00210 const CaloSimParameters& parameters ( *params( detId ) ) ;
00211
00212
00213
00214
00215 double npe ( hit.energy()*parameters.simHitToPhotoelectrons( detId ) ) ;
00216
00217
00218 if( parameters.doPhotostatistics() ) npe = ranPois()->fire( npe ) ;
00219
00220 if( 0 != m_PECorrection ) npe = m_PECorrection->correctPE( detId, npe ) ;
00221
00222 return npe ;
00223 }
00224
00225 double
00226 EcalHitResponse::timeOfFlight( const DetId& detId ) const
00227 {
00228 const CaloCellGeometry* cellGeometry ( geometry()->getGeometry( detId ) ) ;
00229 assert( 0 != cellGeometry ) ;
00230 return cellGeometry->getPosition().mag()*cm/c_light ;
00231 }
00232
00233 void
00234 EcalHitResponse::add( const EcalSamples* pSam )
00235 {
00236 EcalSamples& sam ( *findSignal( pSam->id() ) ) ;
00237 sam += (*pSam) ;
00238 }
00239
00240 int
00241 EcalHitResponse::minBunch() const
00242 {
00243 return m_minBunch ;
00244 }
00245
00246 int
00247 EcalHitResponse::maxBunch() const
00248 {
00249 return m_maxBunch ;
00250 }
00251
00252 EcalHitResponse::VecInd&
00253 EcalHitResponse::index()
00254 {
00255 return m_index ;
00256 }
00257
00258 const EcalHitResponse::VecInd&
00259 EcalHitResponse::index() const
00260 {
00261 return m_index ;
00262 }
00263
00264 const CaloVHitFilter*
00265 EcalHitResponse::hitFilter() const
00266 {
00267 return m_hitFilter ;
00268 }
00269
00270 const EcalHitResponse::EcalSamples*
00271 EcalHitResponse::findDetId( const DetId& detId ) const
00272 {
00273 const unsigned int di ( CaloGenericDetId( detId ).denseIndex() ) ;
00274 return vSamAll( di ) ;
00275 }