CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/SimCalorimetry/HcalSimAlgos/src/HcalSiPMHitResponse.cc

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   //use to make signal
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   // std::cout << HcalDetId(id) << '\n';
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       // std::cout << " elapsedTime: " << elapsedTime
00235       //                << " sampleBin: " << sampleBin
00236       //                << " preciseBin: " << preciseBin
00237       //                << " pe: " << pe 
00238       //                << " hitPixels: " << hitPixels 
00239       //                << '\n';
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     // signal.preciseAtMod(preciseBin) += sumHits;
00248     elapsedTime += dt;
00249   }
00250 
00251   // differentiatePreciseSamples(signal, 1.);
00252 
00253   // std::cout << "sum pe: " << sumPE 
00254   //        << " sum sipm pixels: " << sumHits
00255   //        << std::endl;
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   // double dy(0.);
00264   for (int i(0); i < samples.preciseSize(); ++i) {
00265     // dy = samples.preciseAt(i+1) - samples.preciseAt(i);
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 }