Go to the documentation of this file.00001 #include "SimCalorimetry/CaloSimAlgos/interface/CaloHitResponse.h"
00002 #include "SimDataFormats/CaloHit/interface/PCaloHit.h"
00003 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVSimParameterMap.h"
00004 #include "SimCalorimetry/CaloSimAlgos/interface/CaloSimParameters.h"
00005 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVShape.h"
00006 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVHitCorrection.h"
00007 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVHitFilter.h"
00008 #include "FWCore/MessageLogger/interface/MessageLogger.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/RandFlat.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 CaloHitResponse::CaloHitResponse(const CaloVSimParameterMap * parametersMap,
00023 const CaloVShape * shape)
00024 : theAnalogSignalMap(),
00025 theParameterMap(parametersMap),
00026 theShape(shape),
00027 theHitCorrection(0),
00028 thePECorrection(0),
00029 theHitFilter(0),
00030 theGeometry(0),
00031 theRandPoisson(0),
00032 theMinBunch(-10),
00033 theMaxBunch(10),
00034 thePhaseShift_(1.)
00035 {
00036 }
00037
00038
00039 CaloHitResponse::~CaloHitResponse()
00040 {
00041 delete theRandPoisson;
00042 }
00043
00044
00045 void CaloHitResponse::setBunchRange(int minBunch, int maxBunch) {
00046 theMinBunch = minBunch;
00047 theMaxBunch = maxBunch;
00048 }
00049
00050
00051 void CaloHitResponse::setRandomEngine(CLHEP::HepRandomEngine & engine)
00052 {
00053 theRandPoisson = new CLHEP::RandPoissonQ(engine);
00054 }
00055
00056
00057 void CaloHitResponse::run(MixCollection<PCaloHit> & hits) {
00058
00059 for(MixCollection<PCaloHit>::MixItr hitItr = hits.begin();
00060 hitItr != hits.end(); ++hitItr)
00061 {
00062
00063 if ( hitItr.bunch() < theMinBunch || hitItr.bunch() > theMaxBunch )
00064 { continue; }
00065
00066 add(*hitItr);
00067 }
00068 }
00069
00070
00071 void
00072 CaloHitResponse::add( const PCaloHit& hit )
00073 {
00074
00075 if ( isnan(hit.time()) ) { return; }
00076
00077
00078 if(theHitFilter == 0 || theHitFilter->accepts(hit)) {
00079 LogDebug("CaloHitResponse") << hit;
00080 CaloSamples signal( makeAnalogSignal( hit ) ) ;
00081
00082 bool keep ( keepBlank() ) ;
00083 if( !keep )
00084 {
00085 const unsigned int size ( signal.size() ) ;
00086 if( 0 != size )
00087 {
00088 for( unsigned int i ( 0 ) ; i != size ; ++i )
00089 {
00090 keep = keep || signal[i] > 1.e-7 ;
00091 }
00092 }
00093 }
00094 LogDebug("CaloHitResponse") << signal;
00095 if( keep ) add(signal);
00096 }
00097 }
00098
00099
00100 void CaloHitResponse::add(const CaloSamples & signal)
00101 {
00102 DetId id(signal.id());
00103 CaloSamples * oldSignal = findSignal(id);
00104 if (oldSignal == 0) {
00105 theAnalogSignalMap[id] = signal;
00106 } else {
00107
00108 int sampleSize = oldSignal->size();
00109 assert(sampleSize == signal.size());
00110 assert(signal.presamples() == oldSignal->presamples());
00111
00112 for(int i = 0; i < sampleSize; ++i) {
00113 (*oldSignal)[i] += signal[i];
00114 }
00115 }
00116 }
00117
00118
00119 CaloSamples CaloHitResponse::makeAnalogSignal(const PCaloHit & inputHit) const {
00120
00121
00122 PCaloHit hit = inputHit;
00123
00124 if(theHitCorrection != 0) {
00125 theHitCorrection->correct(hit);
00126 }
00127
00128 DetId detId(hit.id());
00129 const CaloSimParameters & parameters = theParameterMap->simParameters(detId);
00130
00131 double signal = analogSignalAmplitude(hit, parameters);
00132
00133 double jitter = hit.time() - timeOfFlight(detId);
00134
00135
00136 const double tzero = ( theShape->timeToRise()
00137 + parameters.timePhase()
00138 - jitter
00139 - BUNCHSPACE*( parameters.binOfMaximum()
00140 - thePhaseShift_ ) ) ;
00141 double binTime = tzero;
00142
00143 CaloSamples result(makeBlankSignal(detId));
00144
00145 for(int bin = 0; bin < result.size(); bin++) {
00146 result[bin] += (*theShape)(binTime)* signal;
00147 binTime += BUNCHSPACE;
00148 }
00149 return result;
00150 }
00151
00152
00153 double CaloHitResponse::analogSignalAmplitude(const PCaloHit & hit, const CaloSimParameters & parameters) const {
00154
00155 if(!theRandPoisson)
00156 {
00157 edm::Service<edm::RandomNumberGenerator> rng;
00158 if ( ! rng.isAvailable()) {
00159 throw cms::Exception("Configuration")
00160 << "CaloHitResponse requires the RandomNumberGeneratorService\n"
00161 "which is not present in the configuration file. You must add the service\n"
00162 "in the configuration file or remove the modules that require it.";
00163 }
00164 theRandPoisson = new CLHEP::RandPoissonQ(rng->getEngine());
00165 }
00166
00167
00168
00169 DetId detId(hit.id());
00170 double npe = hit.energy() * parameters.simHitToPhotoelectrons(detId);
00171
00172 if(parameters.doPhotostatistics()) {
00173 npe = theRandPoisson->fire(npe);
00174 }
00175 if(thePECorrection) npe = thePECorrection->correctPE(detId, npe);
00176 return npe;
00177 }
00178
00179
00180 CaloSamples * CaloHitResponse::findSignal(const DetId & detId) {
00181 CaloSamples * result = 0;
00182 AnalogSignalMap::iterator signalItr = theAnalogSignalMap.find(detId);
00183 if(signalItr == theAnalogSignalMap.end()) {
00184 result = 0;
00185 }
00186 else {
00187 result = &(signalItr->second);
00188 }
00189 return result;
00190 }
00191
00192
00193 CaloSamples CaloHitResponse::makeBlankSignal(const DetId & detId) const {
00194 const CaloSimParameters & parameters = theParameterMap->simParameters(detId);
00195 CaloSamples result(detId, parameters.readoutFrameSize());
00196 result.setPresamples(parameters.binOfMaximum()-1);
00197 return result;
00198 }
00199
00200
00201 double CaloHitResponse::timeOfFlight(const DetId & detId) const {
00202
00203
00204 double result = 0.;
00205 if(theGeometry == 0) {
00206 edm::LogWarning("CaloHitResponse") << "No Calo Geometry set, so no time of flight correction";
00207 }
00208 else {
00209 const CaloCellGeometry* cellGeometry = theGeometry->getSubdetectorGeometry(detId)->getGeometry(detId);
00210 if(cellGeometry == 0) {
00211 edm::LogWarning("CaloHitResponse") << "No Calo cell found for ID"
00212 << detId.rawId() << " so no time-of-flight subtraction will be done";
00213 }
00214 else {
00215 double distance = cellGeometry->getPosition().mag();
00216 result = distance * cm / c_light;
00217 }
00218 }
00219 return result;
00220 }
00221
00222