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 "DataFormats/HcalDetId/interface/HcalDetId.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/RandFlat.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
00023 #include<iostream>
00024
00025 CaloHitResponse::CaloHitResponse(const CaloVSimParameterMap * parametersMap,
00026 const CaloVShape * shape)
00027 : theAnalogSignalMap(),
00028 theParameterMap(parametersMap),
00029 theShapes(0),
00030 theShape(shape),
00031 theHitCorrection(0),
00032 thePECorrection(0),
00033 theHitFilter(0),
00034 theGeometry(0),
00035 theRandPoisson(0),
00036 theMinBunch(-10),
00037 theMaxBunch(10),
00038 thePhaseShift_(1.),
00039 changeScale(false) {}
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 changeScale(false) {}
00056
00057 CaloHitResponse::~CaloHitResponse() {
00058 delete theRandPoisson;
00059 }
00060
00061 void CaloHitResponse::initHBHEScale() {
00062 #ifdef ChangeHcalEnergyScale
00063 for (int ij=0; ij<100; ij++) {
00064 for (int jk=0; jk<72; jk++) {
00065 for (int kl=0; kl<4; kl++) {
00066 hcal_en_scale[ij][jk][kl] = 1.0;
00067 }
00068 }
00069 }
00070 #endif
00071 }
00072
00073 void CaloHitResponse::setHBHEScale(std::string & fileIn) {
00074
00075 ifstream infile(fileIn.c_str());
00076 LogDebug("CaloHitResponse") << "Reading from " << fileIn;
00077 #ifdef ChangeHcalEnergyScale
00078 if (!infile.is_open()) {
00079 edm::LogError("CaloHitResponse") << "** ERROR: Can't open '" << fileIn << "' for the input file";
00080 } else {
00081 int eta, phi, depth;
00082 double cFactor;
00083 while(1) {
00084 infile >> eta >> phi >> depth >> cFactor;
00085 if (!infile.good()) break;
00086 hcal_en_scale[eta][phi][depth] = cFactor;
00087
00088 }
00089 infile.close();
00090 }
00091 changeScale = true;
00092 #endif
00093 }
00094
00095 void CaloHitResponse::setBunchRange(int minBunch, int maxBunch) {
00096 theMinBunch = minBunch;
00097 theMaxBunch = maxBunch;
00098 }
00099
00100
00101 void CaloHitResponse::setRandomEngine(CLHEP::HepRandomEngine & engine) {
00102 theRandPoisson = new CLHEP::RandPoissonQ(engine);
00103 }
00104
00105
00106 void CaloHitResponse::run(MixCollection<PCaloHit> & hits) {
00107
00108 for(MixCollection<PCaloHit>::MixItr hitItr = hits.begin();
00109 hitItr != hits.end(); ++hitItr) {
00110 if(withinBunchRange(hitItr.bunch())) {
00111 add(*hitItr);
00112 }
00113 }
00114 }
00115
00116 void CaloHitResponse::add( const PCaloHit& hit ) {
00117
00118 if ( edm::isNotFinite(hit.time()) ) { return; }
00119
00120
00121 if(theHitFilter == 0 || theHitFilter->accepts(hit)) {
00122 LogDebug("CaloHitResponse") << hit;
00123 CaloSamples signal( makeAnalogSignal( hit ) ) ;
00124
00125 bool keep ( keepBlank() ) ;
00126 if( !keep )
00127 {
00128 const unsigned int size ( signal.size() ) ;
00129 if( 0 != size )
00130 {
00131 for( unsigned int i ( 0 ) ; i != size ; ++i )
00132 {
00133 keep = keep || signal[i] > 1.e-7 ;
00134 }
00135 }
00136 }
00137 LogDebug("CaloHitResponse") << signal;
00138 if( keep ) add(signal);
00139 }
00140 }
00141
00142
00143 void CaloHitResponse::add(const CaloSamples & signal)
00144 {
00145 DetId id(signal.id());
00146 CaloSamples * oldSignal = findSignal(id);
00147 if (oldSignal == 0) {
00148 theAnalogSignalMap[id] = signal;
00149 } else {
00150
00151 int sampleSize = oldSignal->size();
00152 assert(sampleSize == signal.size());
00153 assert(signal.presamples() == oldSignal->presamples());
00154
00155 for(int i = 0; i < sampleSize; ++i) {
00156 (*oldSignal)[i] += signal[i];
00157 }
00158 }
00159 }
00160
00161
00162 CaloSamples CaloHitResponse::makeAnalogSignal(const PCaloHit & hit) const {
00163
00164 DetId detId(hit.id());
00165 const CaloSimParameters & parameters = theParameterMap->simParameters(detId);
00166
00167 double signal = analogSignalAmplitude(detId, hit.energy(), parameters);
00168
00169 double time = hit.time();
00170 if(theHitCorrection != 0) {
00171 time += theHitCorrection->delay(hit);
00172 }
00173 double jitter = hit.time() - timeOfFlight(detId);
00174
00175 const CaloVShape * shape = theShape;
00176 if(!shape) {
00177 shape = theShapes->shape(detId);
00178 }
00179
00180 const double tzero = ( shape->timeToRise()
00181 + parameters.timePhase()
00182 - jitter
00183 - BUNCHSPACE*( parameters.binOfMaximum()
00184 - thePhaseShift_ ) ) ;
00185 double binTime = tzero;
00186
00187 CaloSamples result(makeBlankSignal(detId));
00188
00189 for(int bin = 0; bin < result.size(); bin++) {
00190 result[bin] += (*shape)(binTime)* signal;
00191 binTime += BUNCHSPACE;
00192 }
00193 return result;
00194 }
00195
00196
00197 double CaloHitResponse::analogSignalAmplitude(const DetId & detId, float energy, const CaloSimParameters & parameters) const {
00198
00199 if(!theRandPoisson)
00200 {
00201 edm::Service<edm::RandomNumberGenerator> rng;
00202 if ( ! rng.isAvailable()) {
00203 throw cms::Exception("Configuration")
00204 << "CaloHitResponse requires the RandomNumberGeneratorService\n"
00205 "which is not present in the configuration file. You must add the service\n"
00206 "in the configuration file or remove the modules that require it.";
00207 }
00208 theRandPoisson = new CLHEP::RandPoissonQ(rng->getEngine());
00209 }
00210
00211
00212
00213
00214 double scl =1.0;
00215 #ifdef ChangeHcalEnergyScale
00216 if (changeScale) {
00217 if (detId.det()==DetId::Hcal ) {
00218 HcalDetId dId = HcalDetId(detId);
00219 if (dId.subdet()==HcalBarrel || dId.subdet()==HcalEndcap) {
00220 int ieta = dId.ieta()+50;
00221 int iphi = dId.iphi()-1;
00222 int idep = dId.depth()-1;
00223 scl = hcal_en_scale[ieta][iphi][idep];
00224 LogDebug("CaloHitResponse") << " ID " << dId << " Scale " << scl;
00225 }
00226 }
00227 }
00228 #endif
00229 double npe = scl * energy * parameters.simHitToPhotoelectrons(detId);
00230
00231 if(parameters.doPhotostatistics()) {
00232 npe = theRandPoisson->fire(npe);
00233 }
00234 if(thePECorrection) npe = thePECorrection->correctPE(detId, npe);
00235 return npe;
00236 }
00237
00238
00239 CaloSamples * CaloHitResponse::findSignal(const DetId & detId) {
00240 CaloSamples * result = 0;
00241 AnalogSignalMap::iterator signalItr = theAnalogSignalMap.find(detId);
00242 if(signalItr == theAnalogSignalMap.end()) {
00243 result = 0;
00244 } else {
00245 result = &(signalItr->second);
00246 }
00247 return result;
00248 }
00249
00250
00251 CaloSamples CaloHitResponse::makeBlankSignal(const DetId & detId) const {
00252 const CaloSimParameters & parameters = theParameterMap->simParameters(detId);
00253 CaloSamples result(detId, parameters.readoutFrameSize());
00254 result.setPresamples(parameters.binOfMaximum()-1);
00255 return result;
00256 }
00257
00258
00259 double CaloHitResponse::timeOfFlight(const DetId & detId) const {
00260
00261
00262 double result = 0.;
00263 if(theGeometry == 0) {
00264 edm::LogWarning("CaloHitResponse") << "No Calo Geometry set, so no time of flight correction";
00265 }
00266 else {
00267 const CaloCellGeometry* cellGeometry = theGeometry->getSubdetectorGeometry(detId)->getGeometry(detId);
00268 if(cellGeometry == 0) {
00269 edm::LogWarning("CaloHitResponse") << "No Calo cell found for ID"
00270 << detId.rawId() << " so no time-of-flight subtraction will be done";
00271 }
00272 else {
00273 double distance = cellGeometry->getPosition().mag();
00274 result = distance * cm / c_light;
00275 }
00276 }
00277 return result;
00278 }
00279
00280