CMS 3D CMS Logo

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