Go to the documentation of this file.00001 #include "SimCalorimetry/HcalSimAlgos/interface/HcalSiPMHitResponse.h"
00002 #include "SimCalorimetry/HcalSimAlgos/interface/HcalSiPM.h"
00003 #include "SimCalorimetry/HcalSimAlgos/interface/HcalSimParameters.h"
00004 #include "SimCalorimetry/HcalSimAlgos/interface/HcalShapes.h"
00005 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00006 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00007 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVHitFilter.h"
00008 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVSimParameterMap.h"
00009 #include "SimCalorimetry/CaloSimAlgos/interface/CaloSimParameters.h"
00010 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVHitCorrection.h"
00011 #include "SimCalorimetry/CaloSimAlgos/interface/CaloVShape.h"
00012 #include "FWCore/Utilities/interface/isFinite.h"
00013
00014 #include <math.h>
00015
00016 HcalSiPMHitResponse::HcalSiPMHitResponse(const CaloVSimParameterMap * parameterMap,
00017 const CaloShapes * shapes) :
00018 CaloHitResponse(parameterMap, shapes), theSiPM(), theRecoveryTime(250.),
00019 TIMEMULT(1), Y11RANGE(80.), Y11MAX(0.04), Y11TIMETORISE(16.65),
00020 theRndFlat(0) {
00021 theSiPM = new HcalSiPM(2500);
00022 }
00023
00024 HcalSiPMHitResponse::~HcalSiPMHitResponse() {
00025 if (theSiPM)
00026 delete theSiPM;
00027 delete theRndFlat;
00028 }
00029
00030 void HcalSiPMHitResponse::initializeHits() {
00031 precisionTimedPhotons.clear();
00032 }
00033
00034 void HcalSiPMHitResponse::finalizeHits() {
00035
00036 photonTimeMap::iterator channelPhotons;
00037 for (channelPhotons = precisionTimedPhotons.begin();
00038 channelPhotons != precisionTimedPhotons.end();
00039 ++channelPhotons) {
00040 CaloSamples signal(makeSiPMSignal(channelPhotons->first,
00041 channelPhotons->second));
00042 bool keep( keepBlank() );
00043 if (!keep) {
00044 const unsigned int size ( signal.size() ) ;
00045 if( 0 != size ) {
00046 for( unsigned int i ( 0 ) ; i != size ; ++i ) {
00047 keep = keep || signal[i] > 1.e-7 ;
00048 }
00049 }
00050 }
00051
00052 LogDebug("HcalSiPMHitResponse") << HcalDetId(signal.id()) << ' ' << signal;
00053 if (keep) add(signal);
00054 }
00055 }
00056
00057 void HcalSiPMHitResponse::add(const CaloSamples& signal) {
00058 DetId id(signal.id());
00059 CaloSamples * oldSignal = findSignal(id);
00060 if (oldSignal == 0) {
00061 theAnalogSignalMap[id] = signal;
00062 } else {
00063 (*oldSignal) += signal;
00064 }
00065 }
00066
00067 void HcalSiPMHitResponse::add(const PCaloHit& hit) {
00068 if (!edm::isNotFinite(hit.time()) &&
00069 ((theHitFilter == 0) || (theHitFilter->accepts(hit)))) {
00070 HcalDetId id(hit.id());
00071 const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
00072 double signal(analogSignalAmplitude(id, hit.energy(), pars));
00073 unsigned int photons(signal + 0.5);
00074 double time( hit.time() );
00075
00076 if (photons > 0)
00077 if (precisionTimedPhotons.find(id)==precisionTimedPhotons.end()) {
00078 precisionTimedPhotons.insert(
00079 std::pair<DetId, photonTimeHist >(id,
00080 photonTimeHist(theTDCParams.nbins() * TIMEMULT *
00081 pars.readoutFrameSize(), 0)
00082 )
00083 );
00084 }
00085
00086 LogDebug("HcalSiPMHitResponse") << id;
00087 LogDebug("HcalSiPMHitResponse") << " fCtoGeV: " << pars.fCtoGeV(id)
00088 << " samplingFactor: " << pars.samplingFactor(id)
00089 << " photoelectronsToAnalog: " << pars.photoelectronsToAnalog(id)
00090 << " simHitToPhotoelectrons: " << pars.simHitToPhotoelectrons(id);
00091 LogDebug("HcalSiPMHitResponse") << " energy: " << hit.energy()
00092 << " photons: " << photons
00093 << " time: " << time;
00094 if (theHitCorrection != 0)
00095 time += theHitCorrection->delay(hit);
00096 LogDebug("HcalSiPMHitResponse") << " corrected time: " << time;
00097 LogDebug("HcalSiPMHitResponse") << " timePhase: " << pars.timePhase()
00098 << " tof: " << timeOfFlight(id)
00099 << " binOfMaximum: " << pars.binOfMaximum()
00100 << " phaseShift: " << thePhaseShift_;
00101 double tzero(Y11TIMETORISE + pars.timePhase() -
00102 (hit.time() - timeOfFlight(id)) -
00103 BUNCHSPACE*( pars.binOfMaximum() - thePhaseShift_));
00104 LogDebug("HcalSiPMHitResponse") << " tzero: " << tzero;
00105 tzero += BUNCHSPACE*pars.binOfMaximum() + 72.31;
00106 LogDebug("HcalSiPMHitResponse") << " corrected tzero: " << tzero << '\n';
00107 double t_pe(0.);
00108 int t_bin(0);
00109 for (unsigned int pe(0); pe<photons; ++pe) {
00110 t_pe = generatePhotonTime();
00111 t_bin = int((t_pe + tzero)/(theTDCParams.deltaT()/TIMEMULT) + 0.5);
00112 LogDebug("HcalSiPMHitResponse") << "t_pe: " << t_pe << " t_pe + tzero: " << (t_pe+tzero)
00113 << " t_bin: " << t_bin << '\n';
00114 if ((t_bin >= 0) &&
00115 (static_cast<unsigned int>(t_bin) < precisionTimedPhotons[id].size()))
00116 precisionTimedPhotons[id][t_bin] += 1;
00117 }
00118 }
00119 }
00120
00121 void HcalSiPMHitResponse::run(MixCollection<PCaloHit> & hits) {
00122 typedef std::multiset <const PCaloHit *, PCaloHitCompareTimes> SortedHitSet;
00123
00124 std::map< DetId, SortedHitSet > sortedhits;
00125 for (MixCollection<PCaloHit>::MixItr hitItr = hits.begin();
00126 hitItr != hits.end(); ++hitItr) {
00127 if (!((hitItr.bunch() < theMinBunch) || (hitItr.bunch() > theMaxBunch)) &&
00128 !(edm::isNotFinite(hitItr->time())) &&
00129 ((theHitFilter == 0) || (theHitFilter->accepts(*hitItr)))) {
00130 DetId id(hitItr->id());
00131 if (sortedhits.find(id)==sortedhits.end())
00132 sortedhits.insert(std::pair<DetId, SortedHitSet>(id, SortedHitSet()));
00133 sortedhits[id].insert(&(*hitItr));
00134 }
00135 }
00136 int pixelIntegral, oldIntegral;
00137 HcalSiPMRecovery pixelHistory(theRecoveryTime);
00138 for (std::map<DetId, SortedHitSet>::iterator i = sortedhits.begin();
00139 i!=sortedhits.end(); ++i) {
00140 pixelHistory.clearHistory();
00141 for (SortedHitSet::iterator itr = i->second.begin();
00142 itr != i->second.end(); ++itr) {
00143 const PCaloHit& hit = **itr;
00144 pixelIntegral = pixelHistory.getIntegral(hit.time());
00145 oldIntegral = pixelIntegral;
00146 CaloSamples signal(makeSiPMSignal(i->first, hit, pixelIntegral));
00147 pixelHistory.addToHistory(hit.time(), pixelIntegral-oldIntegral);
00148 add(signal);
00149 }
00150 }
00151 }
00152
00153
00154 void HcalSiPMHitResponse::setRandomEngine(CLHEP::HepRandomEngine & engine)
00155 {
00156 theSiPM->initRandomEngine(engine);
00157 CaloHitResponse::setRandomEngine(engine);
00158 theRndFlat = new CLHEP::RandFlat(engine);
00159 }
00160
00161 CaloSamples HcalSiPMHitResponse::makeBlankSignal(const DetId& detId) const {
00162 const CaloSimParameters & parameters = theParameterMap->simParameters(detId);
00163 int preciseSize(parameters.readoutFrameSize()*theTDCParams.nbins());
00164 CaloSamples result(detId, parameters.readoutFrameSize(), preciseSize);
00165 result.setPresamples(parameters.binOfMaximum()-1);
00166 result.setPrecise(result.presamples()*theTDCParams.nbins(),
00167 theTDCParams.deltaT());
00168 return result;
00169 }
00170
00171 CaloSamples HcalSiPMHitResponse::makeSiPMSignal(const DetId & id,
00172 const PCaloHit & inHit,
00173 int & integral ) const {
00174
00175 PCaloHit hit = inHit;
00176 if (theHitCorrection != 0) {
00177 hit.setTime(hit.time() + theHitCorrection->delay(hit));
00178 }
00179
00180 const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
00181 theSiPM->setNCells(pars.pixels());
00182
00183 double signal = analogSignalAmplitude(id, hit.energy(), pars);
00184 int photons = static_cast<int>(signal + 0.5);
00185 int pixels = theSiPM->hitCells(photons, integral);
00186 integral += pixels;
00187 signal = double(pixels);
00188
00189 CaloSamples result(makeBlankSignal(id));
00190
00191 if(pixels > 0)
00192 {
00193 const CaloVShape * shape = theShapes->shape(id);
00194 double jitter = hit.time() - timeOfFlight(id);
00195
00196 const double tzero = pars.timePhase() - jitter -
00197 BUNCHSPACE*(pars.binOfMaximum() - thePhaseShift_);
00198 double binTime = tzero;
00199
00200 for (int bin = 0; bin < result.size(); bin++) {
00201 result[bin] += (*shape)(binTime)*signal;
00202 binTime += BUNCHSPACE;
00203 }
00204 }
00205
00206 return result;
00207 }
00208
00209 CaloSamples HcalSiPMHitResponse::makeSiPMSignal(DetId const& id,
00210 photonTimeHist const& photons) const {
00211 const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
00212 theSiPM->setNCells(pars.pixels());
00213 theSiPM->setTau(5.);
00214
00215 CaloSamples signal( makeBlankSignal(id) );
00216 double const dt(theTDCParams.deltaT()/TIMEMULT);
00217 double const invdt(1./theTDCParams.deltaT());
00218 int sampleBin(0), preciseBin(0);
00219 signal.resetPrecise();
00220 unsigned int pe(0);
00221 double hitPixels(0.), elapsedTime(0.);
00222 unsigned int sumPE(0);
00223 double sumHits(0.);
00224
00225 for (unsigned int pt(0); pt < photons.size(); ++pt) {
00226 pe = photons[pt];
00227 sumPE += pe;
00228 preciseBin = pt/TIMEMULT;
00229 sampleBin = preciseBin/theTDCParams.nbins();
00230 if (pe > 0) {
00231 hitPixels = theSiPM->hitCells(pe, 0., elapsedTime);
00232 signal[sampleBin] += hitPixels;
00233 sumHits += hitPixels;
00234
00235
00236
00237
00238
00239
00240 hitPixels *= invdt;
00241 signal.preciseAtMod(preciseBin) += 0.6*hitPixels;
00242 if (preciseBin > 0)
00243 signal.preciseAtMod(preciseBin-1) += 0.2*hitPixels;
00244 if (preciseBin < signal.preciseSize() -1)
00245 signal.preciseAtMod(preciseBin+1) += 0.2*hitPixels;
00246 }
00247
00248 elapsedTime += dt;
00249 }
00250
00251
00252
00253
00254
00255
00256
00257 return signal;
00258 }
00259
00260 void HcalSiPMHitResponse::differentiatePreciseSamples(CaloSamples& samples,
00261 double diffNorm) const {
00262 static double const invdt(1./samples.preciseDeltaT());
00263
00264 for (int i(0); i < samples.preciseSize(); ++i) {
00265
00266 samples.preciseAtMod(i) *= invdt*diffNorm;
00267 }
00268 }
00269
00270 double HcalSiPMHitResponse::generatePhotonTime() const {
00271 double result(0.);
00272 while (true) {
00273 result = theRndFlat->fire(Y11RANGE);
00274 if (theRndFlat->fire(Y11MAX) < Y11TimePDF(result))
00275 return result;
00276 }
00277 }
00278
00279 double HcalSiPMHitResponse::Y11TimePDF(double t) {
00280 return exp(-0.0635-0.1518*t)*pow(t, 2.528)/2485.9;
00281 }