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 LogDebug("HcalSiPMHitResponse") << "HcalSiPMHitResponse::initalizeHits()";
00032 precisionTimedPhotons.clear();
00033 LogDebug("HcalSiPMHitResponse") << " precisionTimedPhotons size: " << precisionTimedPhotons.size()
00034 << std::endl;
00035 }
00036
00037 void HcalSiPMHitResponse::finalizeHits() {
00038
00039 photonTimeMap::iterator channelPhotons;
00040 for (channelPhotons = precisionTimedPhotons.begin();
00041 channelPhotons != precisionTimedPhotons.end();
00042 ++channelPhotons) {
00043 CaloSamples signal(makeSiPMSignal(channelPhotons->first,
00044 channelPhotons->second));
00045 bool keep( keepBlank() );
00046 if (!keep) {
00047 const unsigned int size ( signal.size() ) ;
00048 if( 0 != size ) {
00049 for( unsigned int i ( 0 ) ; i != size ; ++i ) {
00050 keep = keep || signal[i] > 1.e-7 ;
00051 }
00052 }
00053 }
00054
00055
00056 LogDebug("HcalSiPMHitResponse") << HcalDetId(signal.id()) << ' ' << signal;
00057 if (keep) add(signal);
00058 }
00059 }
00060
00061 void HcalSiPMHitResponse::add(const CaloSamples& signal) {
00062 DetId id(signal.id());
00063 CaloSamples * oldSignal = findSignal(id);
00064 if (oldSignal == 0) {
00065 theAnalogSignalMap[id] = signal;
00066 } else {
00067 (*oldSignal) += signal;
00068 }
00069 }
00070
00071 void HcalSiPMHitResponse::add(const PCaloHit& hit) {
00072 if (!edm::isNotFinite(hit.time()) &&
00073 ((theHitFilter == 0) || (theHitFilter->accepts(hit)))) {
00074 HcalDetId id(hit.id());
00075 const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
00076 if (precisionTimedPhotons.find(id)==precisionTimedPhotons.end()) {
00077 precisionTimedPhotons.insert(std::pair<DetId, photonTimeHist >(id, photonTimeHist(theTDCParams.nbins()*TIMEMULT*pars.readoutFrameSize(), 0)));
00078 }
00079 double signal(analogSignalAmplitude(id, hit.energy(), pars));
00080 unsigned int photons(signal + 0.5);
00081 double time( hit.time() );
00082
00083 LogDebug("HcalSiPMHitResponse") << id;
00084 LogDebug("HcalSiPMHitResponse") << " fCtoGeV: " << pars.fCtoGeV(id)
00085 << " samplingFactor: " << pars.samplingFactor(id)
00086 << " photoelectronsToAnalog: " << pars.photoelectronsToAnalog(id)
00087 << " simHitToPhotoelectrons: " << pars.simHitToPhotoelectrons(id);
00088 LogDebug("HcalSiPMHitResponse") << " energy: " << hit.energy()
00089 << " photons: " << photons
00090 << " time: " << time;
00091 if (theHitCorrection != 0)
00092 time += theHitCorrection->delay(hit);
00093 LogDebug("HcalSiPMHitResponse") << " corrected time: " << time;
00094 LogDebug("HcalSiPMHitResponse") << " timePhase: " << pars.timePhase()
00095 << " tof: " << timeOfFlight(id)
00096 << " binOfMaximum: " << pars.binOfMaximum()
00097 << " phaseShift: " << thePhaseShift_;
00098 double tzero(Y11TIMETORISE + pars.timePhase() -
00099 (hit.time() - timeOfFlight(id)) -
00100 BUNCHSPACE*( pars.binOfMaximum() - thePhaseShift_));
00101 LogDebug("HcalSiPMHitResponse") << " tzero: " << tzero;
00102 tzero += BUNCHSPACE*pars.binOfMaximum() + 72.31;
00103 LogDebug("HcalSiPMHitResponse") << " corrected tzero: " << tzero << '\n';
00104 double t_pe(0.);
00105 int t_bin(0);
00106 for (unsigned int pe(0); pe<photons; ++pe) {
00107 t_pe = generatePhotonTime();
00108 t_bin = int((t_pe + tzero)/(theTDCParams.deltaT()/TIMEMULT) + 0.5);
00109 LogDebug("HcalSiPMHitResponse") << "t_pe: " << t_pe << " t_pe + tzero: " << (t_pe+tzero)
00110 << " t_bin: " << t_bin << '\n';
00111 if ((t_bin >= 0) &&
00112 (static_cast<unsigned int>(t_bin) < precisionTimedPhotons[id].size()))
00113 precisionTimedPhotons[id][t_bin] += 1;
00114 }
00115 }
00116 }
00117
00118 void HcalSiPMHitResponse::run(MixCollection<PCaloHit> & hits) {
00119 typedef std::multiset <const PCaloHit *, PCaloHitCompareTimes> SortedHitSet;
00120
00121 std::map< DetId, SortedHitSet > sortedhits;
00122 for (MixCollection<PCaloHit>::MixItr hitItr = hits.begin();
00123 hitItr != hits.end(); ++hitItr) {
00124 if (!((hitItr.bunch() < theMinBunch) || (hitItr.bunch() > theMaxBunch)) &&
00125 !(edm::isNotFinite(hitItr->time())) &&
00126 ((theHitFilter == 0) || (theHitFilter->accepts(*hitItr)))) {
00127 DetId id(hitItr->id());
00128 if (sortedhits.find(id)==sortedhits.end())
00129 sortedhits.insert(std::pair<DetId, SortedHitSet>(id, SortedHitSet()));
00130 sortedhits[id].insert(&(*hitItr));
00131 }
00132 }
00133 int pixelIntegral, oldIntegral;
00134 HcalSiPMRecovery pixelHistory(theRecoveryTime);
00135 for (std::map<DetId, SortedHitSet>::iterator i = sortedhits.begin();
00136 i!=sortedhits.end(); ++i) {
00137 pixelHistory.clearHistory();
00138 for (SortedHitSet::iterator itr = i->second.begin();
00139 itr != i->second.end(); ++itr) {
00140 const PCaloHit& hit = **itr;
00141 pixelIntegral = pixelHistory.getIntegral(hit.time());
00142 oldIntegral = pixelIntegral;
00143 CaloSamples signal(makeSiPMSignal(i->first, hit, pixelIntegral));
00144 pixelHistory.addToHistory(hit.time(), pixelIntegral-oldIntegral);
00145 add(signal);
00146 }
00147 }
00148 }
00149
00150
00151 void HcalSiPMHitResponse::setRandomEngine(CLHEP::HepRandomEngine & engine)
00152 {
00153 theSiPM->initRandomEngine(engine);
00154 CaloHitResponse::setRandomEngine(engine);
00155 theRndFlat = new CLHEP::RandFlat(engine);
00156 }
00157
00158 CaloSamples HcalSiPMHitResponse::makeBlankSignal(const DetId& detId) const {
00159 const CaloSimParameters & parameters = theParameterMap->simParameters(detId);
00160 int preciseSize(parameters.readoutFrameSize()*theTDCParams.nbins());
00161 CaloSamples result(detId, parameters.readoutFrameSize(), preciseSize);
00162 result.setPresamples(parameters.binOfMaximum()-1);
00163 result.setPrecise(result.presamples()*theTDCParams.nbins(),
00164 theTDCParams.deltaT());
00165 return result;
00166 }
00167
00168 CaloSamples HcalSiPMHitResponse::makeSiPMSignal(const DetId & id,
00169 const PCaloHit & inHit,
00170 int & integral ) const {
00171
00172 PCaloHit hit = inHit;
00173 if (theHitCorrection != 0) {
00174 hit.setTime(hit.time() + theHitCorrection->delay(hit));
00175 }
00176
00177 const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
00178 theSiPM->setNCells(pars.pixels());
00179
00180 double signal = analogSignalAmplitude(id, hit.energy(), pars);
00181 int photons = static_cast<int>(signal + 0.5);
00182 int pixels = theSiPM->hitCells(photons, integral);
00183 integral += pixels;
00184 signal = double(pixels);
00185
00186 CaloSamples result(makeBlankSignal(id));
00187
00188 if(pixels > 0)
00189 {
00190 const CaloVShape * shape = theShapes->shape(id);
00191 double jitter = hit.time() - timeOfFlight(id);
00192
00193 const double tzero = pars.timePhase() - jitter -
00194 BUNCHSPACE*(pars.binOfMaximum() - thePhaseShift_);
00195 double binTime = tzero;
00196
00197 for (int bin = 0; bin < result.size(); bin++) {
00198 result[bin] += (*shape)(binTime)*signal;
00199 binTime += BUNCHSPACE;
00200 }
00201 }
00202
00203 return result;
00204 }
00205
00206 CaloSamples HcalSiPMHitResponse::makeSiPMSignal(DetId const& id,
00207 photonTimeHist const& photons) const {
00208 const HcalSimParameters& pars = dynamic_cast<const HcalSimParameters&>(theParameterMap->simParameters(id));
00209 theSiPM->setNCells(pars.pixels());
00210 theSiPM->setTau(5.);
00211
00212 CaloSamples signal( makeBlankSignal(id) );
00213 double dt(theTDCParams.deltaT()/TIMEMULT);
00214 int sampleBin(0), preciseBin(0);
00215 signal.resetPrecise();
00216 unsigned int pe(0);
00217 double hitPixels(0.);
00218 double elapsedTime(0.);
00219 unsigned int sumPE(0);
00220 double sumHits(0.);
00221 LogDebug("HcalSiPMHitResponse") << HcalDetId(id) << '\n';
00222 for (unsigned int pt(0); pt < photons.size(); ++pt) {
00223 pe = photons[pt];
00224 sumPE += pe;
00225 preciseBin = pt/TIMEMULT;
00226 sampleBin = preciseBin/theTDCParams.nbins();
00227 if (pe > 0) {
00228 hitPixels = theSiPM->hitCells(pe, 0., elapsedTime);
00229 signal[sampleBin] += hitPixels;
00230 signal.preciseAtMod(preciseBin) += hitPixels;
00231 sumHits += hitPixels;
00232 LogDebug("HcalSiPMHitResponse") << " elapsedTime: " << dt << " sampleBin: " << sampleBin
00233 << " preciseBin: " << preciseBin
00234 << " pe: " << pe << " hitPixels: " << hitPixels << '\n';
00235 }
00236 elapsedTime += dt;
00237 }
00238 LogDebug("HcalSiPMHitResponse") << "sum pe: " << sumPE << " sum sipm pixels: " << sumHits
00239 << std::endl;
00240
00241 return signal;
00242 }
00243
00244 double HcalSiPMHitResponse::generatePhotonTime() const {
00245 double result(0.);
00246 while (true) {
00247 result = theRndFlat->fire(Y11RANGE);
00248 if (theRndFlat->fire(Y11MAX) < Y11TimePDF(result))
00249 return result;
00250 }
00251 }
00252
00253 double HcalSiPMHitResponse::Y11TimePDF(double t) {
00254 return exp(-0.0635-0.1518*t)*pow(t, 2.528)/2485.9;
00255 }