CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/SimCalorimetry/EcalSimAlgos/src/EcalHitResponse.cc

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 "CalibCalorimetry/EcalLaserCorrection/interface/EcalLaserDbService.h"
00012 #include "DataFormats/EcalDetId/interface/ESDetId.h"
00013 #include "FWCore/ServiceRegistry/interface/Service.h"
00014 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00015 #include "CLHEP/Random/RandPoissonQ.h"
00016 #include "CLHEP/Random/RandGaussQ.h"
00017 #include "FWCore/Utilities/interface/Exception.h"
00018 #include "FWCore/Utilities/interface/isFinite.h"
00019 
00020 #include "CLHEP/Units/GlobalPhysicalConstants.h"
00021 #include "CLHEP/Units/GlobalSystemOfUnits.h" 
00022 #include <iostream>
00023 
00024 
00025 
00026 EcalHitResponse::EcalHitResponse( const CaloVSimParameterMap* parameterMap ,
00027                                   const CaloVShape*           shape         ) :
00028    m_parameterMap    ( parameterMap ) ,
00029    m_shape           ( shape        ) ,
00030    m_hitCorrection   ( 0            ) ,
00031    m_PECorrection    ( 0            ) ,
00032    m_hitFilter       ( 0            ) ,
00033    m_geometry        ( 0            ) ,
00034    m_lasercals       ( 0            ) ,
00035    m_RandPoisson     ( 0            ) ,
00036    m_RandGauss       ( 0            ) ,
00037    m_minBunch        ( -10          ) ,
00038    m_maxBunch        (  10          ) ,
00039    m_phaseShift      ( 1            ) ,
00040    m_iTime           ( 0            ) ,
00041    m_useLCcorrection ( 0            )  
00042 {
00043    edm::Service<edm::RandomNumberGenerator> rng ;
00044    if ( !rng.isAvailable() ) 
00045    {
00046       throw cms::Exception("Configuration")
00047          << "EcalHitResponse requires the RandomNumberGeneratorService\n"
00048          "which is not present in the configuration file.  You must add the service\n"
00049          "in the configuration file or remove the modules that require it.";
00050    }
00051    m_RandPoisson = new CLHEP::RandPoissonQ( rng->getEngine() ) ;
00052    m_RandGauss   = new CLHEP::RandGaussQ(   rng->getEngine() ) ;
00053 }
00054 
00055 EcalHitResponse::~EcalHitResponse()
00056 {
00057    delete m_RandPoisson ;
00058    delete m_RandGauss   ;
00059 }
00060 
00061 CLHEP::RandPoissonQ* 
00062 EcalHitResponse::ranPois() const
00063 {
00064    return m_RandPoisson ;
00065 }
00066 
00067 CLHEP::RandGaussQ* 
00068 EcalHitResponse::ranGauss() const
00069 {
00070    return m_RandGauss ;
00071 }
00072 
00073 const CaloSimParameters*
00074 EcalHitResponse::params( const DetId& detId ) const
00075 {
00076    assert( 0 != m_parameterMap ) ;
00077    return &m_parameterMap->simParameters( detId ) ;
00078 }
00079 
00080 const CaloVShape*
00081 EcalHitResponse::shape() const
00082 {
00083    assert( 0 != m_shape ) ;
00084    return m_shape ;
00085 }
00086 
00087 const CaloSubdetectorGeometry*
00088 EcalHitResponse::geometry() const
00089 {
00090    assert( 0 != m_geometry ) ;
00091    return m_geometry ;
00092 }
00093 
00094 void 
00095 EcalHitResponse::setBunchRange( int minBunch , 
00096                                 int maxBunch  ) 
00097 {
00098    m_minBunch = minBunch ;
00099    m_maxBunch = maxBunch ;
00100 }
00101 
00102 void 
00103 EcalHitResponse::setGeometry( const CaloSubdetectorGeometry* geometry )
00104 {
00105    m_geometry = geometry ;
00106 }
00107 
00108 void 
00109 EcalHitResponse::setPhaseShift( double phaseShift )
00110 {
00111    m_phaseShift = phaseShift ;
00112 }
00113 
00114 double
00115 EcalHitResponse::phaseShift() const
00116 {
00117    return m_phaseShift ;
00118 }
00119 
00120 void 
00121 EcalHitResponse::setHitFilter( const CaloVHitFilter* filter)
00122 {
00123    m_hitFilter = filter ;
00124 }
00125 
00126 void 
00127 EcalHitResponse::setHitCorrection( const CaloVHitCorrection* hitCorrection)
00128 {
00129    m_hitCorrection = hitCorrection ;
00130 }
00131 
00132 void 
00133 EcalHitResponse::setPECorrection( const CaloVPECorrection* peCorrection )
00134 {
00135    m_PECorrection = peCorrection ;
00136 }
00137 
00138 void
00139 EcalHitResponse::setEventTime(const edm::TimeValue_t& iTime)
00140 {
00141   m_iTime = iTime;
00142 }
00143 
00144 void 
00145 EcalHitResponse::setLaserConstants(const EcalLaserDbService* laser, bool& useLCcorrection)
00146 {
00147   m_lasercals = laser;
00148   m_useLCcorrection = useLCcorrection;
00149 }
00150 
00151 void 
00152 EcalHitResponse::blankOutUsedSamples()  // blank out previously used elements
00153 {
00154    const unsigned int size ( m_index.size() ) ;
00155 
00156    for( unsigned int i ( 0 ) ; i != size ; ++i )
00157    {
00158       vSamAll( m_index[i] )->setZero() ;
00159    }
00160    m_index.erase( m_index.begin() ,    // done and make ready to start over
00161                   m_index.end()    ) ;
00162 }
00163 
00164 void 
00165 EcalHitResponse::add( const PCaloHit& hit ) 
00166 {
00167   if (!edm::isNotFinite( hit.time() ) && ( 0 == m_hitFilter || m_hitFilter->accepts( hit ) ) ) {
00168      putAnalogSignal( hit ) ;
00169   }
00170 }
00171 
00172 bool
00173 EcalHitResponse::withinBunchRange(int bunchCrossing) const
00174 {
00175    return(m_minBunch <= bunchCrossing && m_maxBunch >= bunchCrossing);
00176 }
00177 
00178 void
00179 EcalHitResponse::initializeHits()
00180 {
00181    blankOutUsedSamples() ;
00182 }
00183 
00184 void
00185 EcalHitResponse::finalizeHits()
00186 {
00187 }
00188 
00189 void 
00190 EcalHitResponse::run( MixCollection<PCaloHit>& hits ) 
00191 {
00192    blankOutUsedSamples() ;
00193 
00194    for( MixCollection<PCaloHit>::MixItr hitItr ( hits.begin() ) ;
00195         hitItr != hits.end() ; ++hitItr )
00196    {
00197       const PCaloHit& hit ( *hitItr ) ;
00198       const int bunch ( hitItr.bunch() ) ;
00199       if( withinBunchRange(bunch)  &&
00200           !edm::isNotFinite( hit.time() ) &&
00201           ( 0 == m_hitFilter ||
00202             m_hitFilter->accepts( hit ) ) ) putAnalogSignal( hit ) ;
00203    }
00204 }
00205 
00206 void
00207 EcalHitResponse::putAnalogSignal( const PCaloHit& hit )
00208 {
00209    const DetId detId ( hit.id() ) ;
00210 
00211    const CaloSimParameters* parameters ( params( detId ) ) ;
00212 
00213    const double signal ( analogSignalAmplitude( detId, hit.energy() ) ) ;
00214 
00215    double time = hit.time();
00216 
00217    if(m_hitCorrection) {
00218      time += m_hitCorrection->delay( hit ) ;
00219    }
00220 
00221    const double jitter ( time - timeOfFlight( detId ) ) ;
00222 
00223    const double tzero = ( shape()->timeToRise()
00224                           + parameters->timePhase() 
00225                           - jitter 
00226                           - BUNCHSPACE*( parameters->binOfMaximum()
00227                                          - m_phaseShift             ) ) ;
00228    double binTime ( tzero ) ;
00229 
00230    EcalSamples& result ( *findSignal( detId ) ) ;
00231 
00232    const unsigned int rsize ( result.size() ) ;
00233 
00234    for( unsigned int bin ( 0 ) ; bin != rsize ; ++bin )
00235    {
00236       result[ bin ] += (*shape())( binTime )*signal ;
00237       binTime += BUNCHSPACE ;
00238    }
00239 }
00240 
00241 double
00242 EcalHitResponse::findLaserConstant(const DetId& detId) const
00243 {
00244   const edm::Timestamp& evtTimeStamp = edm::Timestamp(m_iTime);
00245   return (m_lasercals->getLaserCorrection(detId, evtTimeStamp));
00246 }
00247 
00248 EcalHitResponse::EcalSamples* 
00249 EcalHitResponse::findSignal( const DetId& detId )
00250 {
00251    const unsigned int di ( CaloGenericDetId( detId ).denseIndex() ) ;
00252    EcalSamples* result ( vSamAll( di ) ) ;
00253    if( result->zero() ) m_index.push_back( di ) ;
00254    return result ;
00255 }
00256 
00257 double 
00258 EcalHitResponse::analogSignalAmplitude( const DetId& detId, float energy ) const
00259 {
00260   const CaloSimParameters& parameters ( *params( detId ) ) ;
00261 
00262    // OK, the "energy" in the hit could be a real energy, deposited energy,
00263    // or pe count.  This factor converts to photoelectrons
00264 
00265    float lasercalib = 1.;
00266    if(m_useLCcorrection == true && detId.subdetId() != 3) {
00267      lasercalib = findLaserConstant(detId);
00268    }
00269 
00270    double npe ( energy/lasercalib*parameters.simHitToPhotoelectrons( detId ) ) ;
00271 
00272    // do we need to doPoisson statistics for the photoelectrons?
00273    if( parameters.doPhotostatistics() ) npe = ranPois()->fire( npe ) ;
00274 
00275    if( 0 != m_PECorrection ) npe = m_PECorrection->correctPE( detId, npe ) ;
00276 
00277    return npe ;
00278 }
00279 
00280 double 
00281 EcalHitResponse::timeOfFlight( const DetId& detId ) const 
00282 {
00283    const CaloCellGeometry* cellGeometry ( geometry()->getGeometry( detId ) ) ;
00284    assert( 0 != cellGeometry ) ;
00285    return cellGeometry->getPosition().mag()*cm/c_light ; // Units of c_light: mm/ns
00286 }
00287 
00288 void 
00289 EcalHitResponse::add( const EcalSamples* pSam )
00290 {
00291    EcalSamples& sam ( *findSignal( pSam->id() ) ) ;
00292    sam += (*pSam) ;
00293 }
00294 
00295 int 
00296 EcalHitResponse::minBunch() const 
00297 {
00298    return m_minBunch ; 
00299 }
00300 
00301 int 
00302 EcalHitResponse::maxBunch() const 
00303 {
00304    return m_maxBunch ; 
00305 }
00306 
00307 EcalHitResponse::VecInd& 
00308 EcalHitResponse::index() 
00309 {
00310    return m_index ; 
00311 }
00312 
00313 const EcalHitResponse::VecInd& 
00314 EcalHitResponse::index() const
00315 {
00316    return m_index ; 
00317 }
00318 
00319 const CaloVHitFilter* 
00320 EcalHitResponse::hitFilter() const 
00321 { 
00322    return m_hitFilter ; 
00323 }
00324 
00325 const EcalHitResponse::EcalSamples* 
00326 EcalHitResponse::findDetId( const DetId& detId ) const
00327 {
00328    const unsigned int di ( CaloGenericDetId( detId ).denseIndex() ) ;
00329    return vSamAll( di ) ;
00330 }