CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
CSCStripElectronicsSim.cc
Go to the documentation of this file.
12 
13 #include "CLHEP/Random/RandGaussQ.h"
14 #include "CLHEP/Units/GlobalPhysicalConstants.h"
15 #include "CLHEP/Units/GlobalSystemOfUnits.h"
16 
17 #include <boost/bind/bind.hpp>
18 #include <cassert>
19 #include <list>
20 
21 using namespace boost::placeholders;
22 
23 // This is CSCStripElectronicsSim.cc
24 
27  theAmpResponse(theShapingTime, CSCStripAmpResponse::RADICAL),
28  theComparatorThreshold(20.),
29  theComparatorNoise(0.),
30  theComparatorRMSOffset(2.),
31  theComparatorSaturation(1057.),
32  theComparatorWait(50.),
33  theComparatorDeadTime(100.),
34  theDaqDeadTime(200.),
35  theTimingOffset(0.),
36  nScaBins_(p.getParameter<int>("nScaBins")),
37  doSuppression_(p.getParameter<bool>("doSuppression")),
38  doCrosstalk_(p.getParameter<bool>("doCrosstalk")),
39  theStripConditions(nullptr),
40  theCrosstalkGenerator(nullptr),
41  theComparatorClockJump(2),
42  sca_time_bin_size(50.),
43  sca_peak_bin(p.getParameter<int>("scaPeakBin")),
44  theComparatorTimeBinOffset(p.getParameter<double>("comparatorTimeBinOffset")),
45  theComparatorTimeOffset(p.getParameter<double>("comparatorTimeOffset")),
46  theComparatorSamplingTime(p.getParameter<double>("comparatorSamplingTime")),
47  theSCATimingOffsets(p.getParameter<std::vector<double>>("scaTimingOffsets")) {
48  if (doCrosstalk_) {
50  }
51 
53 }
54 
56  if (doCrosstalk_) {
57  delete theCrosstalkGenerator;
58  }
59 }
60 
64  // selfTest();
65 
66  // calculate the offset to the peak
67  float averageDistance = theLayer->surface().position().mag();
68  theAverageTimeOfFlight = averageDistance * cm / c_light; // Units of c_light: mm/ns
69  int chamberType = theSpecs->chamberType();
71  // TODO make sure config gets overridden
74  theNumberOfSamples = nScaBins_ * static_cast<int>(sca_time_bin_size / theSamplingTime);
75 }
76 
78 
80 
81 CSCAnalogSignal CSCStripElectronicsSim::makeNoiseSignal(int element, CLHEP::HepRandomEngine *engine) {
82  std::vector<float> noiseBins(nScaBins_);
83  CSCAnalogSignal tmpSignal(element, sca_time_bin_size, noiseBins);
84  if (doNoise_) {
85  theStripConditions->noisify(layerId(), tmpSignal, engine);
86  }
87  // now rebin it
88  std::vector<float> binValues(theNumberOfSamples);
89  for (int ibin = 0; ibin < theNumberOfSamples; ++ibin) {
90  binValues[ibin] = tmpSignal.getValue(ibin * theSamplingTime);
91  }
92  CSCAnalogSignal finalSignal(element, theSamplingTime, binValues, 0., theSignalStartTime);
93  return finalSignal;
94 }
95 
97  float time,
98  CLHEP::HepRandomEngine *engine) const {
99  return std::min(signal.getValue(time), theComparatorSaturation) +
100  theComparatorRMSOffset * CLHEP::RandGaussQ::shoot(engine);
101 }
102 
103 void CSCStripElectronicsSim::runComparator(std::vector<CSCComparatorDigi> &result, CLHEP::HepRandomEngine *engine) {
104  // first, make a list of all the comparators we actually
105  // need to run
106  std::list<int> comparatorsWithSignal;
107  CSCSignalMap::iterator signalMapItr;
108  for (signalMapItr = theSignalMap.begin(); signalMapItr != theSignalMap.end(); ++signalMapItr) {
109  // Elements in signal map count from 1
110  // 1,2->0, 3,4->1, 5,6->2, ...
111  comparatorsWithSignal.push_back(((*signalMapItr).first - 1) / 2);
112  }
113  // no need to sort
114  comparatorsWithSignal.unique();
115  for (std::list<int>::iterator listItr = comparatorsWithSignal.begin(); listItr != comparatorsWithSignal.end();
116  ++listItr) {
117  int iComparator = *listItr;
118  // find signal1 and signal2
119  // iComparator counts from 0
120  // icomp =0->1,2, =1->3,4, =2->5,6, ...
121  const CSCAnalogSignal &signal1 = find(readoutElement(iComparator * 2 + 1), engine);
122  const CSCAnalogSignal &signal2 = find(readoutElement(iComparator * 2 + 2), engine);
124  time += theComparatorSamplingTime) {
125  if (comparatorReading(signal1, time, engine) > theComparatorThreshold ||
126  comparatorReading(signal2, time, engine) > theComparatorThreshold) {
127  // wait a bit, so we can run the comparator at the signal peak
128  float comparatorTime = time;
129  time += theComparatorWait;
130 
131  float height1 = comparatorReading(signal1, time, engine);
132  float height2 = comparatorReading(signal2, time, engine);
133  int output = 0;
134  int strip = 0;
135  // distrip logic; comparator output is for pairs of strips:
136  // hit bin dec
137  // x--- 100 4
138  // -x-- 101 5
139  // --x- 110 6
140  // ---x 111 7
141  // just to prevent a copy
142  const CSCAnalogSignal *mainSignal = nullptr;
143  // pick the higher of the two strips in the pair
144  if (height1 > height2) {
145  mainSignal = &signal1;
146  float leftStrip = 0.;
147  if (iComparator > 0) {
148  leftStrip = comparatorReading(find(readoutElement(iComparator * 2), engine), time, engine);
149  }
150  // if this strip is higher than either of its neighbors, make a
151  // comparator digi
152  if (leftStrip < height1 && height1 > theComparatorThreshold) {
153  output = (leftStrip < height2);
154  strip = iComparator * 2 + 1;
155  }
156  } else {
157  mainSignal = &signal2;
158  float rightStrip = 0.;
159  if (iComparator * 2 + 3 <= nElements) {
160  rightStrip = comparatorReading(find(readoutElement(iComparator * 2 + 3), engine), time, engine);
161  }
162  if (rightStrip < height2 && height2 > theComparatorThreshold) {
163  output = (height1 < rightStrip);
164  strip = iComparator * 2 + 2;
165  }
166  }
167  if (strip != 0) {
168  float bxFloat =
170 
171  // Comparator digi as of Nov-2006 adapted to real data: time word has
172  // 16 bits with set bit flagging appropriate bunch crossing, and bx 0
173  // corresponding to 9th bit i.e.
174 
175  // 1st bit set (bit 0) <-> bx -9
176  // 2nd 1 <-> bx -8
177  // ... ... ....
178  // 8th 9 <-> bx 0
179  // 9th 10 <-> bx +1
180  // ... ... ....
181  // 16th 15 <-> bx +6
182 
183  // Parameter theOffsetOfBxZero = 9 @@WARNING! This offset may be
184  // changed (hardware)!
185 
186  int timeWord = 0; // and this will remain if too early or late
187  if ((bxFloat >= 0) && (bxFloat < 16))
188  timeWord = (1 << static_cast<int>(bxFloat)); // set appropriate bit
189 
190  CSCComparatorDigi newDigi(strip, output, timeWord);
191  result.push_back(newDigi);
192  }
193 
194  // wait for the comparator to reset
195  time += theComparatorDeadTime;
196  // really should be zero, but strip signal doesn't go negative yet
197  float resetThreshold = 1;
198  while (time < theSignalStopTime && mainSignal->getValue(time) > resetThreshold) {
200  }
201 
202  } // if over threshold
203  } // loop over time samples
204  } // loop over comparators
205  // sort by time
206  sort(result.begin(), result.end());
207 }
208 
209 std::list<int> CSCStripElectronicsSim::getKeyStrips(const std::vector<CSCComparatorDigi> &comparators) const {
210  std::list<int> result;
211  for (std::vector<CSCComparatorDigi>::const_iterator compItr = comparators.begin(); compItr != comparators.end();
212  ++compItr) {
213  if (std::abs(compItr->getTimeBin() - theOffsetOfBxZero) <= 2) {
214  result.push_back(compItr->getStrip());
215  }
216  }
217  // need sort for unique to work.
218  result.sort();
219  result.unique();
220  return result;
221 }
222 
224  // assumes the detector hit map is filled
225  std::list<int> result;
227  theDetectorHitMap.end(),
228  // back_inserter(result),
229  // boost::bind(&DetectorHitMap::value_type::first,_1));
230  // suggested code from Chris Jones
231  back_inserter(result),
232  std::bind(&DetectorHitMap::value_type::first, std::placeholders::_1));
233  // back_inserter(result), [](DetectorHitMap::value_type const& iValue) {
234  // return iValue.first; } );
235  result.sort();
236  result.unique();
237  return result;
238 }
239 
240 std::list<int> CSCStripElectronicsSim::channelsToRead(const std::list<int> &keyStrips, int window) const {
241  std::list<int> result;
242  std::list<int>::const_iterator keyStripItr = keyStrips.begin();
243  if (doSuppression_) {
244  for (; keyStripItr != keyStrips.end(); ++keyStripItr) {
245  // pick the five strips around the comparator
246  for (int istrip = (*keyStripItr) - window; istrip <= (*keyStripItr) + window; ++istrip) {
247  if (istrip > 0 && istrip <= nElements) {
248  result.push_back(readoutElement(istrip));
249  }
250  }
251  }
252  result.sort();
253  result.unique();
254  } else {
255  // read the whole CFEB, 16 strips
256  std::list<int> cfebsToRead;
257  for (; keyStripItr != keyStrips.end(); ++keyStripItr) {
258  int cfeb = (readoutElement(*keyStripItr) - 1) / 16;
259  cfebsToRead.push_back(cfeb);
260  int remainder = (readoutElement(*keyStripItr) - 1) % 16;
261  // if we're within 3 strips of an edge, take neighboring CFEB, too
262  if (remainder < window && cfeb != 0) {
263  cfebsToRead.push_back(cfeb - 1);
264  }
265  // the 'readouElement' makes it so that ME1/1 has just one CFEB
266  int maxCFEBs = readoutElement(nElements) / 16 - 1;
267  if (remainder >= 16 - window && cfeb != maxCFEBs) {
268  cfebsToRead.push_back(cfeb + 1);
269  }
270  }
271  cfebsToRead.sort();
272  cfebsToRead.unique();
273 
274  // now convert the CFEBS to strips
275  for (std::list<int>::const_iterator cfebItr = cfebsToRead.begin(); cfebItr != cfebsToRead.end(); ++cfebItr) {
276  for (int i = 1; i <= 16; ++i) {
277  result.push_back((*cfebItr) * 16 + i);
278  }
279  }
280  }
281  return result;
282 }
283 
285  return (s1.getTotal() > s2.getTotal());
286 }
287 
289  CSCComparatorDigiCollection &comparators,
290  CLHEP::HepRandomEngine *engine) {
291  if (doCrosstalk_) {
292  addCrosstalk(engine);
293  }
294 
295  std::vector<CSCComparatorDigi> comparatorOutputs;
296  runComparator(comparatorOutputs, engine);
297  // copy these to the result
298  if (!comparatorOutputs.empty()) {
299  CSCComparatorDigiCollection::Range range(comparatorOutputs.begin(), comparatorOutputs.end());
300  comparators.put(range, layerId());
301  }
302 
303  // std::list<int> keyStrips = getKeyStrips(comparatorOutputs);
304  std::list<int> keyStrips = getKeyStripsFromMC();
305  fillStripDigis(keyStrips, digis, engine);
306 }
307 
308 void CSCStripElectronicsSim::fillStripDigis(const std::list<int> &keyStrips,
309  CSCStripDigiCollection &digis,
310  CLHEP::HepRandomEngine *engine) {
311  std::list<int> stripsToDo = channelsToRead(keyStrips, 3);
312  std::vector<CSCStripDigi> stripDigis;
313  stripDigis.reserve(stripsToDo.size());
314  for (std::list<int>::const_iterator stripItr = stripsToDo.begin(); stripItr != stripsToDo.end(); ++stripItr) {
315  createDigi(*stripItr, find(*stripItr, engine), stripDigis, engine);
316  }
317 
318  CSCStripDigiCollection::Range stripRange(stripDigis.begin(), stripDigis.end());
319  digis.put(stripRange, layerId());
320 }
321 
322 void CSCStripElectronicsSim::addCrosstalk(CLHEP::HepRandomEngine *engine) {
323  // this is needed so we can add a noise signal to the map
324  // without messing up any iterators
325  std::vector<CSCAnalogSignal> realSignals;
326  realSignals.reserve(theSignalMap.size());
327  CSCSignalMap::iterator mapI = theSignalMap.begin(), mapEnd = theSignalMap.end();
328  for (; mapI != mapEnd; ++mapI) {
329  realSignals.push_back((*mapI).second);
330  }
331  sort(realSignals.begin(), realSignals.end(), SortSignalsByTotal);
332  std::vector<CSCAnalogSignal>::iterator realSignalItr = realSignals.begin(), realSignalsEnd = realSignals.end();
333  for (; realSignalItr != realSignalsEnd; ++realSignalItr) {
334  int thisStrip = (*realSignalItr).getElement();
335  // add it to each neighbor
336  if (thisStrip > 1) {
337  int otherStrip = thisStrip - 1;
338  addCrosstalk(*realSignalItr, thisStrip, otherStrip, engine);
339  }
340  if (thisStrip < nElements) {
341  int otherStrip = thisStrip + 1;
342  addCrosstalk(*realSignalItr, thisStrip, otherStrip, engine);
343  }
344  }
345 }
346 
348  int thisStrip,
349  int otherStrip,
350  CLHEP::HepRandomEngine *engine) {
351  float capacitiveCrosstalk, resistiveCrosstalk;
352  bool leftRight = (otherStrip > thisStrip);
354  layerId(), thisStrip, theLayerGeometry->length(), leftRight, capacitiveCrosstalk, resistiveCrosstalk);
355  theCrosstalkGenerator->setParameters(capacitiveCrosstalk, 0., resistiveCrosstalk);
356  CSCAnalogSignal crosstalkSignal(theCrosstalkGenerator->getCrosstalk(signal));
357  find(readoutElement(otherStrip), engine).superimpose(crosstalkSignal);
358 
359  // Now subtract the crosstalk signal from the original signal
360  crosstalkSignal *= -1.;
361  find(thisStrip, engine).superimpose(crosstalkSignal);
362 }
363 
365  const CSCAnalogSignal &signal,
366  std::vector<CSCStripDigi> &result,
367  CLHEP::HepRandomEngine *engine) {
368  // fill in the sca information
369  std::vector<int> scaCounts(nScaBins_);
370 
371  float pedestal = theStripConditions->pedestal(layerId(), channel);
372  float gain = theStripConditions->smearedGain(layerId(), channel, engine);
373  int chamberType = theSpecs->chamberType();
374  float timeSmearing = CLHEP::RandGaussQ::shoot(engine) * theTimingCalibrationError[chamberType];
375  // undo the correction for TOF, instead, using some nominal
376  // value from ME2/1
377  float t0 = theSignalStartTime + theSCATimingOffsets[chamberType] + timeSmearing + 29. - theAverageTimeOfFlight;
378  for (int scaBin = 0; scaBin < nScaBins_; ++scaBin) {
379  float t = t0 + scaBin * sca_time_bin_size;
380  scaCounts[scaBin] = static_cast<int>(pedestal + signal.getValue(t) * gain);
381  }
382  CSCStripDigi newDigi(channel, scaCounts);
383 
384  // do saturation of 12-bit ADC
385  doSaturation(newDigi);
386 
387  result.push_back(newDigi);
388  addLinks(channelIndex(channel));
389  LogTrace("CSCStripElectronicsSim") << "CSCStripElectronicsSim: CSCStripDigi " << newDigi;
390 }
391 
393  std::vector<int> scaCounts(digi.getADCCounts());
394  for (unsigned scaBin = 0; scaBin < scaCounts.size(); ++scaBin) {
395  scaCounts[scaBin] = std::min(scaCounts[scaBin], 4095);
396  }
397  digi.setADCCounts(scaCounts);
398 }
399 
401  const CSCComparatorDigiCollection &comparators,
402  CSCStripDigiCollection &digis,
403  CLHEP::HepRandomEngine *engine) {
404  theSignalMap.clear();
405  setLayer(layer);
406  CSCDetId chamberId(theLayerId.chamberId());
407  // find all comparator key strips in this chamber
408  std::list<int> chamberKeyStrips;
409  for (CSCComparatorDigiCollection::DigiRangeIterator comparatorItr = comparators.begin();
410  comparatorItr != comparators.end();
411  ++comparatorItr) {
412  // could be more efficient
413  if (CSCDetId((*comparatorItr).first).chamberId() == chamberId) {
414  std::vector<CSCComparatorDigi> layerComparators((*comparatorItr).second.first, (*comparatorItr).second.second);
415  std::list<int> layerKeyStrips = getKeyStrips(layerComparators);
416  chamberKeyStrips.insert(chamberKeyStrips.end(), layerKeyStrips.begin(), layerKeyStrips.end());
417  }
418  }
419  chamberKeyStrips.sort();
420  chamberKeyStrips.unique();
421  fillStripDigis(chamberKeyStrips, digis, engine);
422 }
423 
425  // make sure the zero suppression algorithms work
426  std::list<int> keyStrips, stripsRead;
427  //
428  bool isGanged = (readoutElement(nElements) == 16);
429  keyStrips.push_back(readoutElement(19));
430  keyStrips.push_back(readoutElement(30));
431  keyStrips.push_back(readoutElement(32));
432  stripsRead = channelsToRead(keyStrips, 3);
433  if (doSuppression_) {
434  unsigned int expectedSize = isGanged ? 10 : 12;
435  assert(stripsRead.size() == expectedSize);
436  assert(stripsRead.front() == readoutElement(17));
437  } else {
438  unsigned int expectedSize = isGanged ? 16 : 48;
439  assert(stripsRead.size() == expectedSize);
440  assert(stripsRead.front() == 1);
441  }
442 }
std::vector< double > theBunchTimingOffsets
void initParameters() override
initialization for each layer
const CSCChamberSpecs * theSpecs
def window
Definition: svgfig.py:643
const CSCLayerGeometry * theLayerGeometry
bool SortSignalsByTotal(const CSCAnalogSignal &s1, const CSCAnalogSignal &s2)
std::vector< int > const & getADCCounts() const
Get ADC readings.
Definition: CSCStripDigi.h:47
virtual float pedestal(const CSCDetId &detId, int channel) const =0
in ADC counts
std::list< int > getKeyStripsFromMC() const
get ths strips that have detector hits
void addCrosstalk(CLHEP::HepRandomEngine *)
virtual void crosstalk(const CSCDetId &detId, int channel, double stripLength, bool leftRight, float &capacitive, float &resistive) const =0
void runComparator(std::vector< CSCComparatorDigi > &result, CLHEP::HepRandomEngine *)
int numberOfStrips() const
int readoutElement(int strip) const override
assert(be >=bs)
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
void setADCCounts(const std::vector< int > &ADCCounts)
Definition: CSCStripDigi.cc:27
#define LogTrace(id)
constexpr std::array< uint8_t, layerIndexSize > layer
CSCStripConditions * theStripConditions
const uint16_t range(const Frame &aFrame)
tuple result
Definition: mps_fire.py:311
void setLayer(const CSCLayer *layer)
float comparatorReading(const CSCAnalogSignal &signal, float time, CLHEP::HepRandomEngine *) const
calculates the comparator reading, including saturation and offsets
std::vector< double > theSCATimingOffsets
T mag() const
Definition: PV3DBase.h:64
std::list< int > channelsToRead(const std::list< int > &keyStrips, int window) const
void noisify(const CSCDetId &detId, CSCAnalogSignal &signal, CLHEP::HepRandomEngine *)
superimposes noise, in fC, on the signal
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
CSCAnalogSignal makeNoiseSignal(int element, CLHEP::HepRandomEngine *) override
CSCDetId chamberId() const
Definition: CSCDetId.h:47
void fillMissingLayer(const CSCLayer *layer, const CSCComparatorDigiCollection &comparators, CSCStripDigiCollection &digis, CLHEP::HepRandomEngine *)
CSCCrosstalkGenerator * theCrosstalkGenerator
void superimpose(const CSCAnalogSignal &signal2)
float length() const override
void doSaturation(CSCStripDigi &digi)
int channel(int strip) const
float calculateAmpResponse(float t) const
virtual void addLinks(int channelIndex)
CSCStripElectronicsSim(const edm::ParameterSet &p)
configurable parameters
void setParameters(float crosstalk, float delay, float resistiveFraction)
int chamberType() const
std::list< int > getKeyStrips(const std::vector< CSCComparatorDigi > &comparators) const
finds the key strips from these comparators
std::pair< const_iterator, const_iterator > Range
float getTotal() const
CSCAnalogSignal getCrosstalk(const CSCAnalogSignal &inputSignal) const
CSCDetId layerId() const
the CSCDetId corresponding to the current layer
CSCAnalogSignal & find(int element, CLHEP::HepRandomEngine *)
void fillDigis(CSCStripDigiCollection &digis, CSCComparatorDigiCollection &comparators, CLHEP::HepRandomEngine *)
float getValue(float t) const
virtual float smearedGain(const CSCDetId &detId, int channel, CLHEP::HepRandomEngine *) const
virtual int channelIndex(int channel) const
lets users map channels to different indices for links
const JetExtendedData & getValue(const Container &, const reco::JetBaseRef &)
get value for the association. Throw exception if no association found
float calculateAmpResponse(float t) const override
const PositionType & position() const
CSCStripAmpResponse theAmpResponse
void createDigi(int istrip, const CSCAnalogSignal &signal, std::vector< CSCStripDigi > &result, CLHEP::HepRandomEngine *)
void fillStripDigis(const std::list< int > &keyStrips, CSCStripDigiCollection &digis, CLHEP::HepRandomEngine *)
std::vector< double > theTimingCalibrationError
unsigned transform(const HcalDetId &id, unsigned transformCode)