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