CMS 3D CMS Logo

CSCBaseElectronicsSim.cc
Go to the documentation of this file.
1 // This is CSCBaseElectronicsSim.cc
2 
7 #include "CLHEP/Units/GlobalPhysicalConstants.h"
9 
10 #include "CLHEP/Random/RandGaussQ.h"
11 
12 #include<list>
13 #include<algorithm>
14 
16 :
17  theSpecs(nullptr),
18  theLayerGeometry(nullptr),
19  theLayer(nullptr),
20  theSignalMap(),
21  theAmpResponse(),
22  theBunchSpacing(25.),
23  theNoiseWasAdded(false),
24  nElements(0),
25  theShapingTime(p.getParameter<int>("shapingTime")),
26  thePeakTimeSigma(p.getParameter<double>("peakTimeSigma")),
27  theBunchTimingOffsets(p.getParameter<std::vector<double> >("bunchTimingOffsets")),
28  theSignalStartTime(p.getParameter<double>("signalStartTime")),
29  theSignalStopTime(p.getParameter<double>("signalStopTime")),
30  theSamplingTime(p.getParameter<double>("samplingTime")),
31  theNumberOfSamples(static_cast<int>((theSignalStopTime-theSignalStartTime)/theSamplingTime)),
32  theOffsetOfBxZero(p.getParameter<int>("timeBitForBxZero")),
33  theSignalPropagationSpeed(p.getParameter<std::vector<double> >("signalSpeed")),
34  theTimingCalibrationError(p.getParameter<std::vector<double> >("timingCalibrationError")),
35  doNoise_(p.getParameter<bool>("doNoise"))
36 {
37  assert(theBunchTimingOffsets.size() == 11);
38 }
39 
40 
42 {
43 }
44 
45 
47  const std::vector<CSCDetectorHit> & detectorHits,
48  CLHEP::HepRandomEngine* engine)
49 {
50  theNoiseWasAdded = false;
51 
52  {
53  theSignalMap.clear();
54  theDetectorHitMap.clear();
55  setLayer(layer);
56  // can we swap for efficiency?
58  }
59 
60  {
61  size_t nHits = detectorHits.size();
62  // turn each detector hit into an analog signal
63  for( size_t i = 0; i < nHits; ++i) {
64  int element = readoutElement( detectorHits[i].getElement() );
65 
66  // skip if hit element is not part of a readout element
67  // e.g. wire in non-readout group
68  if ( element != 0 ) add( amplifySignal(detectorHits[i]), engine );
69  }
70  }
71 
72  {
73  if(doNoise_) {
74  addNoise(engine);
75  }
76  }
77 }
78 
79 
81 {
82  // fill the specs member data
83  theSpecs = layer->chamber()->specs();
84  theLayerGeometry = layer->geometry();
85 
86  theLayer = layer;
89 }
90 
91 
93  std::vector<float> ampBinValues(theNumberOfSamples);
94  int i = 0;
95  for( ; i < theNumberOfSamples; ++i) {
96  ampBinValues[i] = calculateAmpResponse(i*theSamplingTime);
97  // truncate any entries that are trivially small
98  if(i>5 && ampBinValues[i] < 0.000001) break;
99  }
100  ampBinValues.resize(i);
101  theAmpResponse = CSCAnalogSignal(0, theSamplingTime, ampBinValues, 1., 0.);
102 
103  LogTrace("CSCBaseElectronicsSim") <<
104  "CSCBaseElectronicsSim: dump of theAmpResponse follows...\n"
105  << theAmpResponse;
106 }
107 
108 
109 
112  int element = readoutElement(detectorHit.getElement());
113 
114  float readoutTime = detectorHit.getTime()
115  + signalDelay(element, detectorHit.getPosition());
116 
117  // start from the amp response, and modify it.
118  CSCAnalogSignal thisSignal(theAmpResponse);
119  thisSignal *= detectorHit.getCharge();
120  thisSignal.setTimeOffset(readoutTime);
121  thisSignal.setElement(element);
122  // keep track of links between digis and hits
123  theDetectorHitMap.insert( DetectorHitMap::value_type(channelIndex(element), detectorHit) );
124  return thisSignal;
125 }
126 
127 
128 CSCAnalogSignal CSCBaseElectronicsSim::makeNoiseSignal(int element, CLHEP::HepRandomEngine*) {
129  std::vector<float> binValues(theNumberOfSamples);
130  // default is empty
131  return CSCAnalogSignal(element, theSamplingTime, binValues, 0., theSignalStartTime);
132 }
133 
134 
135 void CSCBaseElectronicsSim::addNoise(CLHEP::HepRandomEngine* engine) {
136  for(CSCSignalMap::iterator mapI = theSignalMap.begin();
137  mapI!= theSignalMap.end(); ++mapI) {
138  // superimpose electronics noise
139  (*mapI).second.superimpose(makeNoiseSignal((*mapI).first, engine));
140  // DON'T do amp gain variations. Handled in strips by calibration code
141  // and variations in the shaper peaking time.
142  double timeOffset = CLHEP::RandGaussQ::shoot(engine, (*mapI).second.getTimeOffset(), thePeakTimeSigma);
143  (*mapI).second.setTimeOffset(timeOffset);
144  }
145  theNoiseWasAdded = true;
146 }
147 
148 
149 CSCAnalogSignal & CSCBaseElectronicsSim::find(int element, CLHEP::HepRandomEngine* engine) {
150  if(element <= 0 || element > nElements) {
151  LogTrace("CSCBaseElectronicsSim") << "CSCBaseElectronicsSim: bad element = " << element <<
152  ". There are " << nElements << " elements.";
153  edm::LogError("Error in CSCBaseElectronicsSim: element out of bounds");
154  }
155  CSCSignalMap::iterator signalMapItr = theSignalMap.find(element);
156  if(signalMapItr == theSignalMap.end()) {
157  CSCAnalogSignal newSignal;
158  if(theNoiseWasAdded) {
159  newSignal = makeNoiseSignal(element, engine);
160  } else {
161  std::vector<float> emptyV(theNumberOfSamples);
162  newSignal = CSCAnalogSignal(element, theSamplingTime, emptyV, 0., theSignalStartTime);
163  }
164  signalMapItr = theSignalMap.insert( std::pair<int, CSCAnalogSignal>(element, newSignal) ).first;
165  }
166  return (*signalMapItr).second;
167 }
168 
169 
170 CSCAnalogSignal & CSCBaseElectronicsSim::add(const CSCAnalogSignal & signal, CLHEP::HepRandomEngine* engine) {
171  int element = signal.getElement();
172  CSCAnalogSignal & newSignal = find(element, engine);
173  newSignal.superimpose(signal);
174  return newSignal;
175 }
176 
177 
178 float CSCBaseElectronicsSim::signalDelay(int element, float pos) const {
179  // readout is on top edge of chamber for strips, right edge
180  // for wires.
181  // zero calibrated to chamber center
182  float distance = -1. * pos;
184  return distance / speed;
185 }
186 
187 
189  std::pair<DetectorHitMap::iterator, DetectorHitMap::iterator> channelHitItr
190  = theDetectorHitMap.equal_range(channelIndex);
191 
192  // find the fraction contribution for each SimTrack
193  std::map<int,float> simTrackChargeMap;
194  std::map<int, EncodedEventId> eventIdMap;
195  float totalCharge = 0;
196  for( DetectorHitMap::iterator hitItr = channelHitItr.first;
197  hitItr != channelHitItr.second; ++hitItr){
198  const PSimHit * hit = hitItr->second.getSimHit();
199  // might be zero for unit tests and such
200  if(hit != nullptr) {
201  int simTrackId = hitItr->second.getSimHit()->trackId();
202  float charge = hitItr->second.getCharge();
203  std::map<int,float>::iterator chargeItr = simTrackChargeMap.find(simTrackId);
204  if( chargeItr == simTrackChargeMap.end() ) {
205  simTrackChargeMap[simTrackId] = charge;
206  eventIdMap[simTrackId] = hit->eventId();
207  } else {
208  chargeItr->second += charge;
209  }
210  totalCharge += charge;
211  }
212  }
213 
214  for(std::map<int,float>::iterator chargeItr = simTrackChargeMap.begin();
215  chargeItr != simTrackChargeMap.end(); ++chargeItr) {
216  int simTrackId = chargeItr->first;
217  theDigiSimLinks.push_back( StripDigiSimLink(channelIndex, simTrackId,
218  eventIdMap[simTrackId], chargeItr->second/totalCharge ) );
219 
220  }
221 }
222 
223 
224 
std::vector< double > theBunchTimingOffsets
CSCBaseElectronicsSim(const edm::ParameterSet &p)
float getPosition() const
int getElement() const
virtual float signalDelay(int element, float pos) const
const CSCChamberSpecs * theSpecs
const CSCLayerGeometry * theLayerGeometry
void push_back(const T &t)
Definition: DetSet.h:68
virtual int readoutElement(int element) const =0
#define nullptr
CSCAnalogSignal amplifySignal(const CSCDetectorHit &)
virtual CSCAnalogSignal makeNoiseSignal(int element, CLHEP::HepRandomEngine *)
virtual float calculateAmpResponse(float t) const =0
void setLayer(const CSCLayer *layer)
uint32_t rawId() const
get the raw id
Definition: DetId.h:44
int getElement() const
constructor from time and amp shape
std::vector< double > theSignalPropagationSpeed
const CSCChamberSpecs * specs() const
Definition: CSCChamber.h:42
edm::DetSet< StripDigiSimLink > DigiSimLinks
float getCharge() const
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:79
EncodedEventId eventId() const
Definition: PSimHit.h:105
float getTime() const
void superimpose(const CSCAnalogSignal &signal2)
#define LogTrace(id)
virtual void addLinks(int channelIndex)
int chamberType() const
CSCDetId layerId() const
the CSCDetId corresponding to the current layer
CSCAnalogSignal & find(int element, CLHEP::HepRandomEngine *)
void addNoise(CLHEP::HepRandomEngine *)
virtual int channelIndex(int channel) const
lets users map channels to different indices for links
void simulate(const CSCLayer *layer, const std::vector< CSCDetectorHit > &inputHits, CLHEP::HepRandomEngine *)
virtual void initParameters()=0
const CSCChamber * chamber() const
Definition: CSCLayer.h:52
const CSCLayerGeometry * geometry() const
Definition: CSCLayer.h:47
CSCAnalogSignal & add(const CSCAnalogSignal &, CLHEP::HepRandomEngine *)