CMS 3D CMS Logo

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