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