CMS 3D CMS Logo

CaloHitResponse.cc

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/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     // check the bunch crossing range
00061     if ( hitItr.bunch() < theMinBunch || hitItr.bunch() > theMaxBunch ) 
00062       { continue; }
00063   
00064     add(*hitItr);
00065   } // loop over hits
00066 }
00067 
00068 
00069 void CaloHitResponse::add(const PCaloHit & hit)
00070 {
00071   // check the hit time makes sense
00072   if ( isnan(hit.time()) ) { return; }
00073 
00074   // maybe it's not from this subdetector
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     // need a "+=" to CaloSamples
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   // see if we need to correct the hit 
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   // assume bins count from zero, go for center of bin
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   // OK, the "energy" in the hit could be a real energy, deposited energy,
00150   // or pe count.  This factor converts to photoelectrons
00151   double npe = hit.energy() * parameters.simHitToPhotoelectrons( DetId(hit.id()) );
00152   // do we need to doPoisson statistics for the photoelectrons?
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   // not going to assume there's one of these per subdetector.
00183   // Take the whole CaloGeometry and find the right subdet
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; // Units of c_light: mm/ns
00197     }
00198   }
00199   return result;
00200 }
00201 
00202 

Generated on Tue Jun 9 17:46:14 2009 for CMSSW by  doxygen 1.5.4