CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/SimMuon/CSCDigitizer/src/CSCBaseElectronicsSim.cc

Go to the documentation of this file.
00001 // This is CSCBaseElectronicsSim.cc
00002 
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 #include "SimMuon/CSCDigitizer/src/CSCBaseElectronicsSim.h"
00005 #include "SimMuon/CSCDigitizer/src/CSCDetectorHit.h"
00006 #include "Geometry/CSCGeometry/interface/CSCLayer.h"
00007 #include "CLHEP/Units/GlobalPhysicalConstants.h"
00008 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
00009 
00010 #include<list>
00011 #include<algorithm>
00012 
00013 CSCBaseElectronicsSim::CSCBaseElectronicsSim(const edm::ParameterSet & p)
00014 : 
00015   theSpecs(0),
00016   theLayerGeometry(0),
00017   theLayer(0),
00018   theSignalMap(),
00019   theAmpResponse(),
00020   theBunchSpacing(25.),
00021   theNoiseWasAdded(false),
00022   nElements(0),
00023   theShapingTime(p.getParameter<int>("shapingTime")),
00024   thePeakTimeSigma(p.getParameter<double>("peakTimeSigma")),
00025   theBunchTimingOffsets(p.getParameter<std::vector<double> >("bunchTimingOffsets")),
00026   theSignalStartTime(p.getParameter<double>("signalStartTime")),
00027   theSignalStopTime(p.getParameter<double>("signalStopTime")),
00028   theSamplingTime(p.getParameter<double>("samplingTime")),
00029   theNumberOfSamples(static_cast<int>((theSignalStopTime-theSignalStartTime)/theSamplingTime)),
00030   theOffsetOfBxZero(p.getParameter<int>("timeBitForBxZero")),
00031   theSignalPropagationSpeed(p.getParameter<std::vector<double> >("signalSpeed")),
00032   theTimingCalibrationError(p.getParameter<std::vector<double> >("timingCalibrationError")),
00033   doNoise_(p.getParameter<bool>("doNoise")),
00034   theRandGaussQ(0)
00035 {
00036   assert(theBunchTimingOffsets.size() == 11);
00037 }
00038 
00039 
00040 CSCBaseElectronicsSim::~CSCBaseElectronicsSim()
00041 {
00042   delete theRandGaussQ;
00043 }
00044 
00045 
00046 void CSCBaseElectronicsSim::setRandomEngine(CLHEP::HepRandomEngine& engine)
00047 {
00048   if(theRandGaussQ) delete theRandGaussQ;
00049   theRandGaussQ = new CLHEP::RandGaussQ(engine);
00050 }
00051 
00052 
00053 void CSCBaseElectronicsSim::simulate(const CSCLayer * layer,
00054                                const std::vector<CSCDetectorHit> & detectorHits)
00055 {
00056   theNoiseWasAdded = false;
00057 
00058   {
00059     theSignalMap.clear();
00060     theDetectorHitMap.clear();
00061     setLayer(layer);
00062     // can we swap for efficiency?
00063     theDigiSimLinks = DigiSimLinks(layerId().rawId());
00064   }
00065   
00066   {
00067     size_t nHits = detectorHits.size();
00068       // turn each detector hit into an analog signal
00069     for( size_t i = 0; i < nHits; ++i) {
00070       int element = readoutElement( detectorHits[i].getElement() );
00071 
00072       // skip if  hit element is not part of a readout element
00073       // e.g. wire in non-readout group
00074       if ( element != 0 ) add( amplifySignal(detectorHits[i]) );
00075     }
00076   }
00077   
00078   {
00079     if(doNoise_) {
00080       addNoise();
00081     }
00082   }
00083 } 
00084 
00085 
00086 void CSCBaseElectronicsSim::setLayer(const CSCLayer * layer) 
00087 {
00088   // fill the specs member data
00089   theSpecs = layer->chamber()->specs();
00090   theLayerGeometry = layer->geometry();
00091 
00092   theLayer = layer;
00093   theLayerId = CSCDetId(theLayer->geographicalId().rawId());
00094   initParameters();
00095 }
00096 
00097 
00098 void CSCBaseElectronicsSim::fillAmpResponse() {
00099   std::vector<float> ampBinValues(theNumberOfSamples);
00100   int i = 0;
00101   for( ; i < theNumberOfSamples; ++i) {
00102     ampBinValues[i] = calculateAmpResponse(i*theSamplingTime);
00103     // truncate any entries that are trivially small
00104     if(i>5 && ampBinValues[i] < 0.000001) break;
00105   }
00106   ampBinValues.resize(i);
00107   theAmpResponse = CSCAnalogSignal(0, theSamplingTime, ampBinValues, 1., 0.);
00108 
00109   LogTrace("CSCBaseElectronicsSim") << 
00110     "CSCBaseElectronicsSim: dump of theAmpResponse follows...\n"
00111          << theAmpResponse;
00112 }
00113 
00114 
00115 
00116 CSCAnalogSignal
00117 CSCBaseElectronicsSim::amplifySignal(const CSCDetectorHit & detectorHit)  {
00118   int element = readoutElement(detectorHit.getElement());
00119 
00120   float readoutTime = detectorHit.getTime() 
00121                     + signalDelay(element, detectorHit.getPosition());
00122 
00123   // start from the amp response, and modify it.
00124   CSCAnalogSignal thisSignal(theAmpResponse);
00125   thisSignal *= detectorHit.getCharge();
00126   thisSignal.setTimeOffset(readoutTime);
00127   thisSignal.setElement(element);
00128   // keep track of links between digis and hits
00129   theDetectorHitMap.insert( DetectorHitMap::value_type(channelIndex(element), detectorHit) );
00130   return thisSignal;
00131 } 
00132 
00133 
00134 CSCAnalogSignal CSCBaseElectronicsSim::makeNoiseSignal(int element) {
00135   std::vector<float> binValues(theNumberOfSamples);
00136   // default is empty
00137   return CSCAnalogSignal(element, theSamplingTime, binValues, 0., theSignalStartTime);
00138 } 
00139 
00140 
00141 void CSCBaseElectronicsSim::addNoise() {
00142   for(CSCSignalMap::iterator mapI = theSignalMap.begin(); 
00143       mapI!=  theSignalMap.end(); ++mapI) {
00144     // superimpose electronics noise
00145     (*mapI).second.superimpose(makeNoiseSignal((*mapI).first));
00146     // DON'T do amp gain variations.  Handled in strips by calibration code
00147     // and variations in the shaper peaking time.
00148      double timeOffset = theRandGaussQ->fire((*mapI).second.getTimeOffset(), thePeakTimeSigma);
00149     (*mapI).second.setTimeOffset(timeOffset);
00150   }
00151   theNoiseWasAdded = true;
00152 }
00153 
00154 
00155 CSCAnalogSignal & CSCBaseElectronicsSim::find(int element) {
00156   if(element <= 0 || element > nElements) {
00157     LogTrace("CSCBaseElectronicsSim") << "CSCBaseElectronicsSim: bad element = " << element << 
00158          ". There are " << nElements  << " elements.";
00159     edm::LogError("Error in CSCBaseElectronicsSim:  element out of bounds");
00160   }
00161   CSCSignalMap::iterator signalMapItr = theSignalMap.find(element);
00162   if(signalMapItr == theSignalMap.end()) {
00163     CSCAnalogSignal newSignal;
00164     if(theNoiseWasAdded) {
00165       newSignal = makeNoiseSignal(element);
00166     } else {
00167       std::vector<float> emptyV(theNumberOfSamples);
00168       newSignal = CSCAnalogSignal(element, theSamplingTime, emptyV, 0., theSignalStartTime);
00169     }
00170     signalMapItr = theSignalMap.insert( std::pair<int, CSCAnalogSignal>(element, newSignal) ).first;
00171   }
00172   return (*signalMapItr).second;
00173 }
00174 
00175 
00176 CSCAnalogSignal & CSCBaseElectronicsSim::add(const CSCAnalogSignal & signal) {
00177   int element = signal.getElement();
00178   CSCAnalogSignal & newSignal = find(element);
00179   newSignal.superimpose(signal);
00180   return newSignal;
00181 }
00182  
00183 
00184 float CSCBaseElectronicsSim::signalDelay(int element, float pos) const {
00185   // readout is on top edge of chamber for strips, right edge
00186   // for wires.
00187   // zero calibrated to chamber center
00188   float distance = -1. * pos;
00189   float speed = theSignalPropagationSpeed[theSpecs->chamberType()];
00190   return distance / speed;
00191 }
00192 
00193 
00194 void CSCBaseElectronicsSim::addLinks(int channelIndex) {
00195   std::pair<DetectorHitMap::iterator, DetectorHitMap::iterator> channelHitItr 
00196     = theDetectorHitMap.equal_range(channelIndex);
00197 
00198   // find the fraction contribution for each SimTrack
00199   std::map<int,float> simTrackChargeMap;
00200   std::map<int, EncodedEventId> eventIdMap;
00201   float totalCharge = 0;
00202   for( DetectorHitMap::iterator hitItr = channelHitItr.first; 
00203                                 hitItr != channelHitItr.second; ++hitItr){
00204     const PSimHit * hit = hitItr->second.getSimHit();
00205     // might be zero for unit tests and such
00206     if(hit != 0) {
00207       int simTrackId = hitItr->second.getSimHit()->trackId();
00208       float charge = hitItr->second.getCharge();
00209       std::map<int,float>::iterator chargeItr = simTrackChargeMap.find(simTrackId);
00210       if( chargeItr == simTrackChargeMap.end() ) {
00211         simTrackChargeMap[simTrackId] = charge;
00212         eventIdMap[simTrackId] = hit->eventId();
00213       } else {
00214         chargeItr->second += charge;
00215       }
00216       totalCharge += charge;
00217     }
00218   }
00219 
00220   for(std::map<int,float>::iterator chargeItr = simTrackChargeMap.begin(); 
00221                           chargeItr != simTrackChargeMap.end(); ++chargeItr) {
00222     int simTrackId = chargeItr->first;
00223     theDigiSimLinks.push_back( StripDigiSimLink(channelIndex, simTrackId,  
00224                                   eventIdMap[simTrackId], chargeItr->second/totalCharge ) );
00225     
00226   }
00227 }
00228 
00229 
00230