CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
CSCCathodeLCTProcessor.cc
Go to the documentation of this file.
2 
3 #include <iomanip>
4 #include <memory>
5 
6 // Default values of configuration parameters.
7 const unsigned int CSCCathodeLCTProcessor::def_fifo_tbins = 12;
8 const unsigned int CSCCathodeLCTProcessor::def_fifo_pretrig = 7;
9 const unsigned int CSCCathodeLCTProcessor::def_hit_persist = 6;
10 const unsigned int CSCCathodeLCTProcessor::def_drift_delay = 2;
14 const unsigned int CSCCathodeLCTProcessor::def_min_separation = 10;
16 
17 //----------------
18 // Constructors --
19 //----------------
20 
22  unsigned station,
23  unsigned sector,
24  unsigned subsector,
25  unsigned chamber,
26  const edm::ParameterSet& conf)
27  : CSCBaseboard(endcap, station, sector, subsector, chamber, conf) {
28  static std::atomic<bool> config_dumped{false};
29 
30  // CLCT configuration parameters.
31  fifo_tbins = clctParams_.getParameter<unsigned int>("clctFifoTbins");
32  hit_persist = clctParams_.getParameter<unsigned int>("clctHitPersist");
33  drift_delay = clctParams_.getParameter<unsigned int>("clctDriftDelay");
34  nplanes_hit_pretrig = clctParams_.getParameter<unsigned int>("clctNplanesHitPretrig");
35  nplanes_hit_pattern = clctParams_.getParameter<unsigned int>("clctNplanesHitPattern");
36 
37  // Not used yet.
38  fifo_pretrig = clctParams_.getParameter<unsigned int>("clctFifoPretrig");
39 
40  pid_thresh_pretrig = clctParams_.getParameter<unsigned int>("clctPidThreshPretrig");
41  min_separation = clctParams_.getParameter<unsigned int>("clctMinSeparation");
42 
43  start_bx_shift = clctParams_.getParameter<int>("clctStartBxShift");
44 
45  // Motherboard parameters: common for all configurations.
46  tmb_l1a_window_size = // Common to CLCT and TMB
47  tmbParams_.getParameter<unsigned int>("tmbL1aWindowSize");
48 
49  /*
50  In Summer 2021 the CLCT readout function was updated so that the
51  window is based on a number of time bins around the central CLCT
52  time BX7. In the past the window was based on early_tbins and late_tbins.
53  The parameter is kept, but is not used.
54  */
55  early_tbins = tmbParams_.getParameter<int>("tmbEarlyTbins");
56  if (early_tbins < 0)
57  early_tbins = fifo_pretrig - CSCConstants::CLCT_EMUL_TIME_OFFSET;
58 
59  // wether to readout only the earliest two LCTs in readout window
60  readout_earliest_2 = tmbParams_.getParameter<bool>("tmbReadoutEarliest2");
61 
62  // Verbosity level, set to 0 (no print) by default.
63  infoV = clctParams_.getParameter<int>("verbosity");
64 
65  // Do not exclude pattern 0 and 1 when the Run-3 patterns are enabled!!
66  // Valid Run-3 patterns are 0,1,2,3,4
67  if (runCCLUT_) {
68  pid_thresh_pretrig = 0;
69  }
70 
71  // Check and print configuration parameters.
73  if ((infoV > 0) && !config_dumped) {
75  config_dumped = true;
76  }
77 
78  numStrips_ = 0; // Will be set later.
79  // Provisional, but should be OK for all stations except ME1.
80  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
81  if ((i_layer + 1) % 2 == 0)
82  stagger[i_layer] = 0;
83  else
84  stagger[i_layer] = 1;
85  }
86 
87  // which patterns should we use?
88  if (runCCLUT_) {
90  // comparator code lookup table algorithm for Phase-2
91  cclut_ = std::make_unique<ComparatorCodeLUT>(conf);
92  } else {
94  }
95 
96  const auto& shower = showerParams_.getParameterSet("cathodeShower");
97  thresholds_ = shower.getParameter<std::vector<unsigned>>("showerThresholds");
98  showerMinInTBin_ = shower.getParameter<unsigned>("showerMinInTBin");
99  showerMaxInTBin_ = shower.getParameter<unsigned>("showerMaxInTBin");
100  showerMinOutTBin_ = shower.getParameter<unsigned>("showerMinOutTBin");
101  showerMaxOutTBin_ = shower.getParameter<unsigned>("showerMaxOutTBin");
102  minLayersCentralTBin_ = shower.getParameter<unsigned>("minLayersCentralTBin");
103  thePreTriggerDigis.clear();
104 
105  // quality control of stubs
106  qualityControl_ = std::make_unique<LCTQualityControl>(endcap, station, sector, subsector, chamber, conf);
107 }
108 
110  // Set default values for configuration parameters.
120 }
121 
122 // Set configuration parameters obtained via EventSetup mechanism.
124  static std::atomic<bool> config_dumped{false};
125 
126  fifo_tbins = conf->clctFifoTbins();
127  fifo_pretrig = conf->clctFifoPretrig();
128  hit_persist = conf->clctHitPersist();
129  drift_delay = conf->clctDriftDelay();
134 
135  // Check and print configuration parameters.
137  if (!config_dumped) {
139  config_dumped = true;
140  }
141 }
142 
143 void CSCCathodeLCTProcessor::setESLookupTables(const CSCL1TPLookupTableCCLUT* conf) { cclut_->setESLookupTables(conf); }
144 
146  // Make sure that the parameter values are within the allowed range.
147 
148  // Max expected values.
149  static const unsigned int max_fifo_tbins = 1 << 5;
150  static const unsigned int max_fifo_pretrig = 1 << 5;
151  static const unsigned int max_hit_persist = 1 << 4;
152  static const unsigned int max_drift_delay = 1 << 2;
153  static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
154  static const unsigned int max_nplanes_hit_pattern = 1 << 3;
155  static const unsigned int max_pid_thresh_pretrig = 1 << 4;
156  static const unsigned int max_min_separation = CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER;
157  static const unsigned int max_tmb_l1a_window_size = 1 << 4;
158 
159  // Checks.
160  CSCBaseboard::checkConfigParameters(fifo_tbins, max_fifo_tbins, def_fifo_tbins, "fifo_tbins");
161  CSCBaseboard::checkConfigParameters(fifo_pretrig, max_fifo_pretrig, def_fifo_pretrig, "fifo_pretrig");
162  CSCBaseboard::checkConfigParameters(hit_persist, max_hit_persist, def_hit_persist, "hit_persist");
163  CSCBaseboard::checkConfigParameters(drift_delay, max_drift_delay, def_drift_delay, "drift_delay");
165  nplanes_hit_pretrig, max_nplanes_hit_pretrig, def_nplanes_hit_pretrig, "nplanes_hit_pretrig");
167  nplanes_hit_pattern, max_nplanes_hit_pattern, def_nplanes_hit_pattern, "nplanes_hit_pattern");
169  pid_thresh_pretrig, max_pid_thresh_pretrig, def_pid_thresh_pretrig, "pid_thresh_pretrig");
170  CSCBaseboard::checkConfigParameters(min_separation, max_min_separation, def_min_separation, "min_separation");
172  tmb_l1a_window_size, max_tmb_l1a_window_size, def_tmb_l1a_window_size, "tmb_l1a_window_size");
173 }
174 
176  thePreTriggerDigis.clear();
177  thePreTriggerBXs.clear();
178  for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
179  bestCLCT[bx].clear();
180  secondCLCT[bx].clear();
181  }
182  inTimeHMT_ = 0;
183 }
184 
185 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::run(const CSCComparatorDigiCollection* compdc) {
186  // This is the version of the run() function that is called when running
187  // over the entire detector. It gets the comparator & timing info from the
188  // comparator digis and then passes them on to another run() function.
189 
190  static std::atomic<bool> config_dumped{false};
191  if ((infoV > 0) && !config_dumped) {
193  config_dumped = true;
194  }
195 
196  // Get the number of strips and stagger of layers for the given chamber.
197  // Do it only once per chamber.
198  if (numStrips_ <= 0 or numStrips_ > CSCConstants::MAX_NUM_STRIPS_RUN2) {
199  if (cscChamber_) {
201 
202  // ME1/a is known to the readout hardware as strips 65-80 of ME1/1.
203  // Still need to decide whether we do any special adjustments to
204  // reconstruct LCTs in this region (3:1 ganged strips); for now, we
205  // simply allow for hits in ME1/a and apply standard reconstruction
206  // to them.
207  // For Phase2 ME1/1 is set to have 4 CFEBs in ME1/b and 3 CFEBs in ME1/a
208  if (isME11_) {
209  if (theRing == 4) {
210  edm::LogError("CSCCathodeLCTProcessor|SetupError")
211  << "+++ Invalid ring number for this processor " << theRing << " was set in the config."
212  << " +++\n"
213  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
214  }
215  if (!disableME1a_ && theRing == 1 && !gangedME1a_)
217  if (!disableME1a_ && theRing == 1 && gangedME1a_)
219  if (disableME1a_ && theRing == 1)
221  }
222 
223  numHalfStrips_ = 2 * numStrips_ + 1;
225 
226  if (numStrips_ > CSCConstants::MAX_NUM_STRIPS_RUN2) {
227  edm::LogError("CSCCathodeLCTProcessor|SetupError")
228  << "+++ Number of strips, " << numStrips_ << " found in " << theCSCName_ << " (sector " << theSector
229  << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
230  << " exceeds max expected, " << CSCConstants::MAX_NUM_STRIPS_RUN2 << " +++\n"
231  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
232  numStrips_ = -1;
233  numHalfStrips_ = -1;
234  numCFEBs_ = -1;
235  }
236  // The strips for a given layer may be offset from the adjacent layers.
237  // This was done in order to improve resolution. We need to find the
238  // 'staggering' for each layer and make necessary conversions in our
239  // arrays. -JM
240  // In the TMB-07 firmware, half-strips in odd layers (layers are
241  // counted as ly0-ly5) are shifted by -1 half-strip, whereas in
242  // the previous firmware versions half-strips in even layers
243  // were shifted by +1 half-strip. This difference is due to a
244  // change from ly3 to ly2 in the choice of the key layer, and
245  // the intention to keep half-strips in the key layer unchanged.
246  // In the emulator, we use the old way for both cases, to avoid
247  // negative half-strip numbers. This will necessitate a
248  // subtraction of 1 half-strip for TMB-07 later on. -SV.
249  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
250  stagger[i_layer] = (cscChamber_->layer(i_layer + 1)->geometry()->stagger() + 1) / 2;
251  }
252  } else {
253  edm::LogError("CSCCathodeLCTProcessor|ConfigError")
254  << " " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
255  << theTrigChamber << ")"
256  << " is not defined in current geometry! +++\n"
257  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
258  numStrips_ = -1;
259  numHalfStrips_ = -1;
260  numCFEBs_ = -1;
261  }
262  }
263 
264  if (numStrips_ <= 0 or 2 * (unsigned)numStrips_ > qualityControl_->get_csc_max_halfstrip(theStation, theRing)) {
265  edm::LogError("CSCCathodeLCTProcessor|ConfigError")
266  << " " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
267  << theTrigChamber << "):"
268  << " numStrips_ = " << numStrips_ << "; CLCT emulation skipped! +++";
269  std::vector<CSCCLCTDigi> emptyV;
270  return emptyV;
271  }
272 
273  // Get comparator digis in this chamber.
274  bool hasDigis = getDigis(compdc);
275 
276  if (hasDigis) {
277  // Get halfstrip times from comparator digis.
279  readComparatorDigis(halfStripTimes);
280 
281  // Pass arrays of halfstrips on to another run() doing the
282  // LCT search.
283  // If the number of layers containing digis is smaller than that
284  // required to trigger, quit right away. (If LCT-based digi suppression
285  // is implemented one day, this condition will have to be changed
286  // to the number of planes required to pre-trigger.)
287  unsigned int layersHit = 0;
288  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
289  for (int i_hstrip = 0; i_hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; i_hstrip++) {
290  if (!halfStripTimes[i_layer][i_hstrip].empty()) {
291  layersHit++;
292  break;
293  }
294  }
295  }
296  // Run the algorithm only if the probability for the pre-trigger
297  // to fire is not null. (Pre-trigger decisions are used for the
298  // strip read-out conditions in DigiToRaw.)
299  if (layersHit >= nplanes_hit_pretrig)
300  run(halfStripTimes);
301 
302  // Get the high multiplicity bits in this chamber
303  encodeHighMultiplicityBits(halfStripTimes);
304  }
305 
306  // Return vector of CLCTs.
307  std::vector<CSCCLCTDigi> tmpV = getCLCTs();
308 
309  // shift the BX from 7 to 8
310  // the unpacked real data CLCTs have central BX at bin 7
311  // however in simulation the central BX is bin 8
312  // to make a proper comparison with ALCTs we need
313  // CLCT and ALCT to have the central BX in the same bin
314  // this shift does not affect the readout of the CLCTs
315  // emulated CLCTs put in the event should be centered at bin 7 (as in data)
316  for (auto& p : tmpV) {
317  p.setBX(p.getBX() + CSCConstants::ALCT_CLCT_OFFSET);
318  }
319 
320  return tmpV;
321 }
322 
325  // This version of the run() function can either be called in a standalone
326  // test, being passed the halfstrip times, or called by the
327  // run() function above. It uses the findLCTs() method to find vectors
328  // of LCT candidates. These candidates are sorted and the best two per bx
329  // are returned.
330 
331  // initialize the pulse array.
332  // add 1 for possible stagger
334 
335  std::vector<CSCCLCTDigi> CLCTlist = findLCTs(halfstrip);
336 
337  // LCT sorting.
338  if (CLCTlist.size() > 1)
339  sort(CLCTlist.begin(), CLCTlist.end(), std::greater<CSCCLCTDigi>());
340 
341  for (const auto& p : CLCTlist) {
342  const int bx = p.getBX();
343  if (bx >= CSCConstants::MAX_CLCT_TBINS) {
344  if (infoV > 0)
345  edm::LogWarning("L1CSCTPEmulatorOutOfTimeCLCT")
346  << "+++ Bx of CLCT candidate, " << bx << ", exceeds max allowed, " << CSCConstants::MAX_CLCT_TBINS - 1
347  << "; skipping it... +++\n";
348  continue;
349  }
350 
351  if (!bestCLCT[bx].isValid()) {
352  bestCLCT[bx] = p;
353  } else if (!secondCLCT[bx].isValid()) {
354  secondCLCT[bx] = p;
355  }
356  }
357 
358  for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
359  if (bestCLCT[bx].isValid()) {
360  bestCLCT[bx].setTrknmb(1);
361 
362  // check if the LCT is valid
363  qualityControl_->checkValid(bestCLCT[bx]);
364 
365  if (infoV > 0)
366  LogDebug("CSCCathodeLCTProcessor")
368  << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
369  << "\n";
370  }
371  if (secondCLCT[bx].isValid()) {
372  secondCLCT[bx].setTrknmb(2);
373 
374  // check if the LCT is valid
375  qualityControl_->checkValid(secondCLCT[bx]);
376 
377  if (infoV > 0)
378  LogDebug("CSCCathodeLCTProcessor")
380  << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
381  << "\n";
382  }
383  }
384  // Now that we have our best CLCTs, they get correlated with the best
385  // ALCTs and then get sent to the MotherBoard. -JM
386 }
387 
389  bool hasDigis = false;
390 
391  // Loop over layers and save comparator digis on each one into digiV[layer].
392  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
393  digiV[i_layer].clear();
394 
395  CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer + 1);
396  getDigis(compdc, detid);
397 
398  if (isME11_ && !disableME1a_) {
399  CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer + 1);
400  getDigis(compdc, detid_me1a);
401  }
402 
403  if (!digiV[i_layer].empty()) {
404  hasDigis = true;
405  if (infoV > 1) {
406  LogTrace("CSCCathodeLCTProcessor") << "found " << digiV[i_layer].size() << " comparator digi(s) in layer "
407  << i_layer << " of " << detid.chamberName() << " (trig. sector " << theSector
408  << " subsector " << theSubsector << " id " << theTrigChamber << ")";
409  }
410  }
411  }
412 
413  return hasDigis;
414 }
415 
417  const bool me1a = (id.station() == 1) && (id.ring() == 4);
418  const CSCComparatorDigiCollection::Range rcompd = compdc->get(id);
419  for (CSCComparatorDigiCollection::const_iterator digiIt = rcompd.first; digiIt != rcompd.second; ++digiIt) {
420  const unsigned int origStrip = digiIt->getStrip();
421  const unsigned int maxStripsME1a =
423  // this special case can only be reached in MC
424  // in real data, the comparator digis have always ring==1
425  if (me1a && origStrip <= maxStripsME1a && !disableME1a_) {
426  // Move ME1/A comparators from CFEB=0 to CFEB=4 if this has not
427  // been done already.
428  CSCComparatorDigi digi_corr(
429  origStrip + CSCConstants::NUM_STRIPS_ME1B, digiIt->getComparator(), digiIt->getTimeBinWord());
430  digiV[id.layer() - 1].push_back(digi_corr);
431  } else {
432  digiV[id.layer() - 1].push_back(*digiIt);
433  }
434  }
435 }
436 
439  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
440  int i_digi = 0; // digi counter, for dumps.
441  for (std::vector<CSCComparatorDigi>::iterator pld = digiV[i_layer].begin(); pld != digiV[i_layer].end();
442  pld++, i_digi++) {
443  // Dump raw digi info.
444  if (infoV > 1) {
445  std::ostringstream strstrm;
446  strstrm << "Comparator digi: comparator = " << pld->getComparator() << " strip #" << pld->getStrip()
447  << " time bins on:";
448  std::vector<int> bx_times = pld->getTimeBinsOn();
449  for (unsigned int tbin = 0; tbin < bx_times.size(); tbin++)
450  strstrm << " " << bx_times[tbin];
451  LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
452  }
453 
454  // Get comparator: 0/1 for left/right halfstrip for each comparator
455  // that fired.
456  int thisComparator = pld->getComparator();
457  if (thisComparator != 0 && thisComparator != 1) {
458  if (infoV >= 0)
459  edm::LogWarning("L1CSCTPEmulatorWrongInput")
460  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
461  << " Found comparator digi with wrong comparator value = " << thisComparator << "; skipping it... +++\n";
462  continue;
463  }
464 
465  // Get strip number.
466  int thisStrip = pld->getStrip() - 1; // count from 0
467  if (thisStrip < 0 || thisStrip >= numStrips_) {
468  if (infoV >= 0)
469  edm::LogWarning("L1CSCTPEmulatorWrongInput")
470  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
471  << " Found comparator digi with wrong strip number = " << thisStrip << " (max strips = " << numStrips_
472  << "); skipping it... +++\n";
473  continue;
474  }
475  // 2*strip: convert strip to 1/2 strip
476  // comp : comparator output
477  // stagger: stagger for this layer
478  int thisHalfstrip = 2 * thisStrip + thisComparator + stagger[i_layer];
479  if (thisHalfstrip >= numHalfStrips_) {
480  if (infoV >= 0)
481  edm::LogWarning("L1CSCTPEmulatorWrongInput")
482  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
483  << " Found wrong halfstrip number = " << thisHalfstrip << "; skipping this digi... +++\n";
484  continue;
485  }
486 
487  // Get bx times on this digi and check that they are within the bounds.
488  std::vector<int> bx_times = pld->getTimeBinsOn();
489  for (unsigned int i = 0; i < bx_times.size(); i++) {
490  // Total number of time bins in DAQ readout is given by fifo_tbins,
491  // which thus determines the maximum length of time interval.
492  //
493  // In data, only the CLCT in the time bin that was matched with L1A are read out
494  // while comparator digi is read out by 12 time bin, which includes 12 time bin info
495  // in other word, CLCTs emulated from comparator digis usually showed the OTMB behavior in 12 time bin
496  // while CLCT from data only showed 1 time bin OTMB behavior
497  // the CLCT emulated from comparator digis usually is centering at time bin 7 (BX7) and
498  // it is definitly safe to ignore any CLCTs in bx 0 or 1 and those CLCTs will never impacts on any triggers
499  if (bx_times[i] > 1 && bx_times[i] < static_cast<int>(fifo_tbins)) {
500  if (i == 0 || (i > 0 && bx_times[i] - bx_times[i - 1] >= static_cast<int>(hit_persist))) {
501  // A later hit on the same strip is ignored during the
502  // number of clocks defined by the "hit_persist" parameter
503  // (i.e., 6 bx's by default).
504  if (infoV > 1)
505  LogTrace("CSCCathodeLCTProcessor")
506  << "Comp digi: layer " << i_layer + 1 << " digi #" << i_digi + 1 << " strip " << thisStrip
507  << " halfstrip " << thisHalfstrip << " time " << bx_times[i] << " comparator " << thisComparator
508  << " stagger " << stagger[i_layer];
509  halfstrip[i_layer][thisHalfstrip].push_back(bx_times[i]);
510  } else if (i > 0) {
511  if (infoV > 1)
512  LogTrace("CSCCathodeLCTProcessor")
513  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
514  << " Skipping comparator digi: strip = " << thisStrip << ", layer = " << i_layer + 1
515  << ", bx = " << bx_times[i] << ", bx of previous hit = " << bx_times[i - 1];
516  }
517  } else {
518  if (infoV > 1)
519  LogTrace("CSCCathodeLCTProcessor") << "+++ station " << theStation << " ring " << theRing << " chamber "
520  << theChamber << "+++ Skipping comparator digi: strip = " << thisStrip
521  << ", layer = " << i_layer + 1 << ", bx = " << bx_times[i] << " +++";
522  }
523  }
524  }
525  }
526 }
527 
528 // TMB-07 version.
529 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(
531  std::vector<CSCCLCTDigi> lctList;
532 
533  if (infoV > 1)
534  dumpDigis(halfstrip);
535 
536  // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
537  pulseExtension(halfstrip);
538 
539  unsigned int start_bx = start_bx_shift;
540  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
541  // not have a full set of hits to start pattern search anyway.
542  unsigned int stop_bx = fifo_tbins - drift_delay;
543  // Allow for more than one pass over the hits in the time window.
544  while (start_bx < stop_bx) {
545  // temp CLCT objects
546  CSCCLCTDigi tempBestCLCT;
547  CSCCLCTDigi tempSecondCLCT;
548 
549  // All half-strip pattern envelopes are evaluated simultaneously, on every
550  // clock cycle.
551  int first_bx = 999;
552  bool pre_trig = preTrigger(start_bx, first_bx);
553 
554  // If any of half-strip envelopes has enough layers hit in it, TMB
555  // will pre-trigger.
556  if (pre_trig) {
557  thePreTriggerBXs.push_back(first_bx);
558  if (infoV > 1)
559  LogTrace("CSCCathodeLCTProcessor") << "..... pretrigger at bx = " << first_bx << "; waiting drift delay .....";
560 
561  // TMB latches LCTs drift_delay clocks after pretrigger.
562  // in the configuration the drift_delay is set to 2bx by default
563  // this is the time that is required for the electrons to drift to the
564  // cathode strips. 15ns drift time --> 45 ns is 3 sigma for the delay
565  // this corresponds to 2bx
566  int latch_bx = first_bx + drift_delay;
567 
568  // define a new pattern map
569  // for each key half strip, and for each pattern, store the 2D collection of fired comparator digis
570  std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer>> hits_in_patterns;
571  hits_in_patterns.clear();
572 
573  // We check if there is at least one key half strip for which at least
574  // one pattern id has at least the minimum number of hits
575  bool hits_in_time = patternFinding(latch_bx, hits_in_patterns);
576  if (infoV > 1) {
577  if (hits_in_time) {
578  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
579  if (nhits[hstrip] > 0) {
580  LogTrace("CSCCathodeLCTProcessor")
581  << " bx = " << std::setw(2) << latch_bx << " --->"
582  << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
583  << " nhits = " << nhits[hstrip];
584  }
585  }
586  }
587  }
588  // This trigger emulator does not have an active CFEB flag for DAQ (csc trigger hardware: AFF)
589  // This is a fundamental difference with the firmware where the TMB prepares the DAQ to
590  // read out the chamber
591 
592  // The pattern finder runs continuously, so another pre-trigger
593  // could occur already at the next bx.
594 
595  // Quality for sorting.
597  int best_halfstrip[CSCConstants::MAX_CLCTS_PER_PROCESSOR];
598  int best_quality[CSCConstants::MAX_CLCTS_PER_PROCESSOR];
599 
600  for (int ilct = 0; ilct < CSCConstants::MAX_CLCTS_PER_PROCESSOR; ilct++) {
601  best_halfstrip[ilct] = -1;
602  best_quality[ilct] = 0;
603  }
604 
605  // Calculate quality from pattern id and number of hits, and
606  // simultaneously select best-quality LCT.
607  if (hits_in_time) {
608  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
609  // The bend-direction bit pid[0] is ignored (left and right
610  // bends have equal quality).
611  quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
612  if (quality[hstrip] > best_quality[0]) {
613  best_halfstrip[0] = hstrip;
614  best_quality[0] = quality[hstrip];
615  }
616  // temporary alias
617  const int best_hs(best_halfstrip[0]);
618  // construct a CLCT if the trigger condition has been met
619  if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
620  // overwrite the current best CLCT
621  tempBestCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pid[best_hs]]);
622  }
623  }
624  }
625 
626  // If 1st best CLCT is found, look for the 2nd best.
627  if (best_halfstrip[0] >= 0) {
628  // Get the half-strip of the best CLCT in this BX that was put into the list.
629  // You do need to re-add the any stagger, because the busy keys are based on
630  // the pulse array which takes into account strip stagger!!!
631  const unsigned halfStripBestCLCT(tempBestCLCT.getKeyStrip() + stagger[CSCConstants::KEY_CLCT_LAYER - 1]);
632 
633  // Mark keys near best CLCT as busy by setting their quality to
634  // zero, and repeat the search.
635  markBusyKeys(halfStripBestCLCT, best_pid[halfStripBestCLCT], quality);
636 
637  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
638  if (quality[hstrip] > best_quality[1]) {
639  best_halfstrip[1] = hstrip;
640  best_quality[1] = quality[hstrip];
641  }
642  // temporary alias
643  const int best_hs(best_halfstrip[1]);
644  // construct a CLCT if the trigger condition has been met
645  if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
646  // overwrite the current second best CLCT
647  tempSecondCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pid[best_hs]]);
648  }
649  }
650  // add the CLCTs to the collection
651  if (tempBestCLCT.isValid()) {
652  lctList.push_back(tempBestCLCT);
653  }
654  if (tempSecondCLCT.isValid()) {
655  lctList.push_back(tempSecondCLCT);
656  }
657  } //find CLCT, end of best_halfstrip[0] >= 0
658 
659  // If there is a trigger, CLCT pre-trigger state machine
660  // checks the number of hits that lie within a pattern template
661  // at every bx, and waits for it to drop below threshold.
662  // The search for CLCTs resumes only when the number of hits
663  // drops below threshold.
664  start_bx = fifo_tbins;
665  // Stop checking drift_delay bx's short of fifo_tbins since
666  // at later bx's we won't have a full set of hits for a
667  // pattern search anyway.
668  unsigned int stop_time = fifo_tbins - drift_delay;
669  for (unsigned int bx = latch_bx + 1; bx < stop_time; bx++) {
670  bool return_to_idle = true;
671  bool hits_in_time = patternFinding(bx, hits_in_patterns);
672  if (hits_in_time) {
673  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
674  // the dead-time is done at the pre-trigger, not at the trigger
675  if (nhits[hstrip] >= nplanes_hit_pretrig) {
676  if (infoV > 1)
677  LogTrace("CSCCathodeLCTProcessor") << " State machine busy at bx = " << bx;
678  return_to_idle = false;
679  break;
680  }
681  }
682  }
683  if (return_to_idle) {
684  if (infoV > 1)
685  LogTrace("CSCCathodeLCTProcessor") << " State machine returns to idle state at bx = " << bx;
686  start_bx = bx;
687  break;
688  }
689  }
690  } //pre_trig
691  else {
692  start_bx = first_bx + 1; // no dead time
693  }
694  }
695 
696  return lctList;
697 } // findLCTs -- TMB-07 version.
698 
699 // Common to all versions.
702  const unsigned bits_in_pulse = pulse_.bitsInPulse();
703 
704  // Clear pulse array. This array will be used as a bit representation of
705  // hit times. For example: if strip[1][2] has a value of 3, then 1 shifted
706  // left 3 will be bit pattern of pulse[1][2]. This would make the pattern
707  // look like 0000000000001000. Then add on additional bits to signify
708  // the duration of a signal (hit_persist, formerly bx_width) to simulate
709  // the TMB's drift delay. So for the same pulse[1][2] with a hit_persist
710  // of 3 would look like 0000000000111000. This is similating the digital
711  // one-shot in the TMB.
712  pulse_.clear();
713 
714  // Loop over all layers and halfstrips.
715  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
716  for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
717  // If there is a hit, simulate digital one-shot persistence starting
718  // in the bx of the initial hit. Fill this into pulse[][].
719  if (!time[i_layer][i_strip].empty()) {
720  std::vector<int> bx_times = time[i_layer][i_strip];
721  for (unsigned int i = 0; i < bx_times.size(); i++) {
722  // Check that min and max times are within the allowed range.
723  if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
724  if (infoV > 0)
725  edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
726  << "+++ BX time of comparator digi (halfstrip = " << i_strip << " layer = " << i_layer
727  << ") bx = " << bx_times[i] << " is not within the range (0-" << bits_in_pulse
728  << "] allowed for pulse extension. Skip this digi! +++\n";
729  continue;
730  }
731  if (bx_times[i] >= start_bx_shift) {
732  pulse_.extend(i_layer, i_strip, bx_times[i], hit_persist);
733  }
734  }
735  }
736  }
737  }
738 } // pulseExtension.
739 
740 // TMB-07 version.
741 bool CSCCathodeLCTProcessor::preTrigger(const int start_bx, int& first_bx) {
742  if (infoV > 1)
743  LogTrace("CSCCathodeLCTProcessor") << "....................PreTrigger...........................";
744 
745  int nPreTriggers = 0;
746 
747  bool pre_trig = false;
748  // Now do a loop over bx times to see (if/when) track goes over threshold
749  for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
750  // For any given bunch-crossing, start at the lowest keystrip and look for
751  // the number of separate layers in the pattern for that keystrip that have
752  // pulses at that bunch-crossing time. Do the same for the next keystrip,
753  // etc. Then do the entire process again for the next bunch-crossing, etc
754  // until you find a pre-trigger.
755 
756  std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer>> hits_in_patterns;
757  hits_in_patterns.clear();
758 
759  bool hits_in_time = patternFinding(bx_time, hits_in_patterns);
760  if (hits_in_time) {
761  // clear the pretriggers
763 
764  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
765  // check the properties of the pattern on this halfstrip
766  if (infoV > 1) {
767  if (nhits[hstrip] > 0) {
768  LogTrace("CSCCathodeLCTProcessor")
769  << " bx = " << std::setw(2) << bx_time << " --->"
770  << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
771  << " nhits = " << nhits[hstrip];
772  }
773  }
774  // a pretrigger was found
775  if (nhits[hstrip] >= nplanes_hit_pretrig && best_pid[hstrip] >= pid_thresh_pretrig) {
776  pre_trig = true;
777  ispretrig_[hstrip] = true;
778 
779  // write each pre-trigger to output
780  nPreTriggers++;
781  thePreTriggerDigis.push_back(constructPreCLCT(bx_time, hstrip, nPreTriggers));
782  }
783  }
784 
785  // upon the first pretrigger, we save first BX and exit
786  if (pre_trig) {
787  first_bx = bx_time; // bx at time of pretrigger
788  return true;
789  }
790  }
791  } // end loop over bx times
792 
793  if (infoV > 1)
794  LogTrace("CSCCathodeLCTProcessor") << "no pretrigger, returning \n";
795  first_bx = fifo_tbins;
796  return false;
797 } // preTrigger -- TMB-07 version.
798 
799 // TMB-07 version.
801  const unsigned int bx_time, std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer>>& hits_in_patterns) {
802  if (bx_time >= fifo_tbins)
803  return false;
804 
805  unsigned layers_hit = pulse_.numberOfLayersAtBX(bx_time);
806  if (layers_hit < nplanes_hit_pretrig)
807  return false;
808 
809  for (int key_hstrip = 0; key_hstrip < numHalfStrips_; key_hstrip++) {
810  best_pid[key_hstrip] = 0;
811  nhits[key_hstrip] = 0;
812  }
813 
814  bool hit_layer[CSCConstants::NUM_LAYERS];
815 
816  // Loop over candidate key strips.
817  for (int key_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; key_hstrip < numHalfStrips_; key_hstrip++) {
818  // Loop over patterns and look for hits matching each pattern.
819  for (unsigned int pid = clct_pattern_.size() - 1; pid >= pid_thresh_pretrig and pid < clct_pattern_.size(); pid--) {
820  layers_hit = 0;
821  // clear all layers
822  for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++) {
823  hit_layer[ilayer] = false;
824  }
825 
826  // clear a single pattern!
827  CSCCLCTDigi::ComparatorContainer hits_single_pattern;
828  hits_single_pattern.resize(6);
829  for (auto& p : hits_single_pattern) {
831  }
832 
833  // clear all medians
834  double num_pattern_hits = 0., times_sum = 0.;
835  std::multiset<int> mset_for_median;
836  mset_for_median.clear();
837 
838  // Loop over halfstrips in trigger pattern mask and calculate the
839  // "absolute" halfstrip number for each.
840  for (int this_layer = 0; this_layer < CSCConstants::NUM_LAYERS; this_layer++) {
841  for (int strip_num = 0; strip_num < CSCConstants::CLCT_PATTERN_WIDTH; strip_num++) {
842  // ignore "0" half-strips in the pattern
843  if (clct_pattern_[pid][this_layer][strip_num] == 0)
844  continue;
845 
846  // the current strip is the key half-strip plus the offset (can be negative or positive)
847  int this_strip = CSCPatternBank::clct_pattern_offset_[strip_num] + key_hstrip;
848 
849  // current strip should be valid of course
850  if (this_strip >= 0 && this_strip < numHalfStrips_) {
851  if (infoV > 3) {
852  LogTrace("CSCCathodeLCTProcessor") << " In patternFinding: key_strip = " << key_hstrip << " pid = " << pid
853  << " layer = " << this_layer << " strip = " << this_strip << std::endl;
854  }
855  // Determine if "one shot" is high at this bx_time
856  if (pulse_.isOneShotHighAtBX(this_layer, this_strip, bx_time)) {
857  if (hit_layer[this_layer] == false) {
858  hit_layer[this_layer] = true;
859  layers_hit++; // determines number of layers hit
860  // add this strip in this layer to the pattern we are currently considering
861  hits_single_pattern[this_layer][strip_num] = this_strip - stagger[this_layer];
862  }
863 
864  // find at what bx did pulse on this halsfstrip & layer have started
865  // use hit_persist constraint on how far back we can go
866  int first_bx_layer = bx_time;
867  for (unsigned int dbx = 0; dbx < hit_persist; dbx++) {
868  if (pulse_.isOneShotHighAtBX(this_layer, this_strip, first_bx_layer - 1))
869  first_bx_layer--;
870  else
871  break;
872  }
873  times_sum += (double)first_bx_layer;
874  num_pattern_hits += 1.;
875  mset_for_median.insert(first_bx_layer);
876  if (infoV > 2)
877  LogTrace("CSCCathodeLCTProcessor") << " 1st bx in layer: " << first_bx_layer << " sum bx: " << times_sum
878  << " #pat. hits: " << num_pattern_hits;
879  }
880  }
881  } // end loop over strips in pretrigger pattern
882  } // end loop over layers
883 
884  // save the pattern information when a trigger was formed!
885  if (layers_hit >= nplanes_hit_pattern) {
886  hits_in_patterns[key_hstrip][pid] = hits_single_pattern;
887  }
888 
889  // determine the current best pattern!
890  if (layers_hit > nhits[key_hstrip]) {
891  best_pid[key_hstrip] = pid;
892  nhits[key_hstrip] = layers_hit;
893  // Do not loop over the other (worse) patterns if max. numbers of
894  // hits is found.
895  if (nhits[key_hstrip] == CSCConstants::NUM_LAYERS)
896  break;
897  }
898  } // end loop over pid
899  } // end loop over candidate key strips
900 
901  // At this point there exists at least one halfstrip for which at least one pattern
902  // has at least 3 layers --> definition of a pre-trigger
903  return true;
904 } // patternFinding -- TMB-07 version.
905 
906 // TMB-07 version.
907 void CSCCathodeLCTProcessor::markBusyKeys(const int best_hstrip,
908  const int best_patid,
910  int nspan = min_separation;
911  int pspan = min_separation;
912 
913  for (int hstrip = best_hstrip - nspan; hstrip <= best_hstrip + pspan; hstrip++) {
914  if (hstrip >= 0 && hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER) {
915  quality[hstrip] = 0;
916  }
917  }
918 } // markBusyKeys -- TMB-07 version.
919 
921  const unsigned halfstrip_withstagger,
922  const CSCCLCTDigi::ComparatorContainer& hits) {
923  // Assign the CLCT properties
924  const unsigned quality = nhits[halfstrip_withstagger];
925  const unsigned pattern = best_pid[halfstrip_withstagger];
926  const unsigned bend = CSCPatternBank::getPatternBend(clct_pattern_[pattern]);
927  const unsigned keyhalfstrip = halfstrip_withstagger - stagger[CSCConstants::KEY_CLCT_LAYER - 1];
928  const unsigned cfeb = keyhalfstrip / CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
929  const unsigned halfstrip = keyhalfstrip % CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
930 
931  // set the Run-2 properties
932  CSCCLCTDigi clct(1,
933  quality,
934  pattern,
935  // CLCTs are always of type halfstrip (not strip or distrip)
936  1,
937  bend,
938  halfstrip,
939  cfeb,
940  bx,
941  0,
942  0,
943  -1,
945 
946  // set the hit collection
947  clct.setHits(hits);
948 
949  // do the CCLUT procedures for Run-3
950  if (runCCLUT_) {
951  cclut_->run(clct, numCFEBs_);
952  }
953 
954  // purge the comparator digi collection from the obsolete "65535" entries...
956 
957  if (infoV > 1) {
958  LogTrace("CSCCathodeLCTProcessor") << "Produce CLCT " << clct << std::endl;
959  }
960 
961  return clct;
962 }
963 
965  const unsigned hstrip,
966  const unsigned nPreTriggers) const {
968  const int halfstrip = hstrip % CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
969  const int cfeb = hstrip / CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
970  return CSCCLCTPreTriggerDigi(1, nhits[hstrip], best_pid[hstrip], 1, bend, halfstrip, cfeb, bx_time, nPreTriggers, 0);
971 }
972 
974  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
975  ispretrig_[hstrip] = false;
976  }
977 }
978 
980  CSCCLCTDigi::ComparatorContainer newHits = clct.getHits();
981  for (auto& p : newHits) {
982  p.erase(
983  std::remove_if(p.begin(), p.end(), [](unsigned i) -> bool { return i == CSCConstants::INVALID_HALF_STRIP; }),
984  p.end());
985  }
986  clct.setHits(newHits);
987 }
988 
989 // --------------------------------------------------------------------------
990 // Auxiliary code.
991 // --------------------------------------------------------------------------
992 // Dump of configuration parameters.
994  std::ostringstream strm;
995  strm << "\n";
996  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
997  strm << "+ CLCT configuration parameters: +\n";
998  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
999  strm << " fifo_tbins [total number of time bins in DAQ readout] = " << fifo_tbins << "\n";
1000  strm << " fifo_pretrig [start time of cathode raw hits in DAQ readout] = " << fifo_pretrig << "\n";
1001  strm << " hit_persist [duration of signal pulse, in 25 ns bins] = " << hit_persist << "\n";
1002  strm << " drift_delay [time after pre-trigger before TMB latches LCTs] = " << drift_delay << "\n";
1003  strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = " << nplanes_hit_pretrig << "\n";
1004  strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = " << nplanes_hit_pattern << "\n";
1005  strm << " pid_thresh_pretrig [lower threshold on pattern id] = " << pid_thresh_pretrig << "\n";
1006  strm << " min_separation [region of busy key strips] = " << min_separation << "\n";
1007  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1008  LogDebug("CSCCathodeLCTProcessor") << strm.str();
1009 }
1010 
1011 // Reasonably nice dump of digis on half-strips.
1014  LogDebug("CSCCathodeLCTProcessor") << theCSCName_ << " strip type: half-strip, numHalfStrips " << numHalfStrips_;
1015 
1016  std::ostringstream strstrm;
1017  for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
1018  if (i_strip % 10 == 0) {
1019  if (i_strip < 100)
1020  strstrm << i_strip / 10;
1021  else
1022  strstrm << (i_strip - 100) / 10;
1023  } else
1024  strstrm << " ";
1025  if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1026  strstrm << " ";
1027  }
1028  strstrm << "\n";
1029  for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
1030  strstrm << i_strip % 10;
1031  if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1032  strstrm << " ";
1033  }
1034  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1035  strstrm << "\n";
1036  for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
1037  if (!strip[i_layer][i_strip].empty()) {
1038  std::vector<int> bx_times = strip[i_layer][i_strip];
1039  // Dump only the first in time.
1040  strstrm << std::hex << bx_times[0] << std::dec;
1041  } else {
1042  strstrm << "-";
1043  }
1044  if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1045  strstrm << " ";
1046  }
1047  }
1048  LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
1049 }
1050 
1051 // Returns vector of read-out CLCTs, if any. Starts with the vector
1052 // of all found CLCTs and selects the ones in the read-out time window.
1053 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::readoutCLCTs() const {
1054  // temporary container for further selection
1055  std::vector<CSCCLCTDigi> tmpV;
1056 
1057  /*
1058  CLCTs in the BX window [early_tbin,...,late_tbin] are considered good for physics
1059  The central CLCT BX is time bin 7.
1060  For tmb_l1a_window_size set to 7 (Run-1, Run-2), the window is [4, 5, 6, 7, 8, 9, 10]
1061  For tmb_l1a_window_size set to 5 (Run-3), the window is [5, 6, 7, 8, 9]
1062  For tmb_l1a_window_size set to 3 (Run-4?), the window is [6, 7, 8]
1063  */
1064  const unsigned delta_tbin = tmb_l1a_window_size / 2;
1065  int early_tbin = CSCConstants::CLCT_CENTRAL_BX - delta_tbin;
1066  int late_tbin = CSCConstants::CLCT_CENTRAL_BX + delta_tbin;
1067  /*
1068  Special case for an even-numbered time-window,
1069  For instance tmb_l1a_window_size set to 6: [4, 5, 6, 7, 8, 9]
1070  */
1071  if (tmb_l1a_window_size % 2 == 0)
1072  late_tbin = CSCConstants::CLCT_CENTRAL_BX + delta_tbin - 1;
1073  const int max_late_tbin = CSCConstants::MAX_CLCT_TBINS - 1;
1074 
1075  // debugging messages when early_tbin or late_tbin has a suspicious value
1076  if (early_tbin < 0) {
1077  edm::LogWarning("CSCCathodeLCTProcessor|SuspiciousParameters")
1078  << "Early time bin (early_tbin) smaller than minimum allowed, which is 0. set early_tbin to 0.";
1079  early_tbin = 0;
1080  }
1081  if (late_tbin > max_late_tbin) {
1082  edm::LogWarning("CSCCathodeLCTProcessor|SuspiciousParameters")
1083  << "Late time bin (late_tbin) larger than maximum allowed, which is " << max_late_tbin
1084  << ". set early_tbin to max allowed";
1085  late_tbin = CSCConstants::MAX_CLCT_TBINS - 1;
1086  }
1087 
1088  // get the valid LCTs. No BX selection is done here
1089  const auto& all_clcts = getCLCTs();
1090 
1091  // Start from the vector of all found CLCTs and select those within
1092  // the CLCT*L1A coincidence window.
1093  int bx_readout = -1;
1094  for (const auto& clct : all_clcts) {
1095  // only consider valid CLCTs
1096  if (!clct.isValid())
1097  continue;
1098 
1099  const int bx = clct.getBX();
1100  // Skip CLCTs found too early relative to L1Accept.
1101  if (bx < early_tbin) {
1102  if (infoV > 1)
1103  LogDebug("CSCCathodeLCTProcessor")
1104  << " Do not report correlated CLCT on key halfstrip " << clct.getStrip() << ": found at bx " << bx
1105  << ", whereas the earliest allowed bx is " << early_tbin;
1106  continue;
1107  }
1108 
1109  // Skip CLCTs found too late relative to L1Accept.
1110  if (bx > late_tbin) {
1111  if (infoV > 1)
1112  LogDebug("CSCCathodeLCTProcessor")
1113  << " Do not report correlated CLCT on key halfstrip " << clct.getStrip() << ": found at bx " << bx
1114  << ", whereas the latest allowed bx is " << late_tbin;
1115  continue;
1116  }
1117 
1118  // If (readout_earliest_2) take only CLCTs in the earliest bx in the read-out window:
1119  if (readout_earliest_2) {
1120  // the first CLCT passes
1121  // the second CLCT passes if the BX matches to the first
1122  if (bx_readout == -1 || bx == bx_readout) {
1123  tmpV.push_back(clct);
1124  if (bx_readout == -1)
1125  bx_readout = bx;
1126  }
1127  } else
1128  tmpV.push_back(clct);
1129  }
1130 
1131  // do a final check on the CLCTs in readout
1132  qualityControl_->checkMultiplicityBX(tmpV);
1133  for (const auto& clct : tmpV) {
1134  qualityControl_->checkValid(clct);
1135  }
1136 
1137  return tmpV;
1138 }
1139 
1140 // Returns vector of all found CLCTs, if any. Used for ALCT-CLCT matching.
1141 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::getCLCTs() const {
1142  std::vector<CSCCLCTDigi> tmpV;
1143  for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
1144  if (bestCLCT[bx].isValid())
1145  tmpV.push_back(bestCLCT[bx]);
1146  if (secondCLCT[bx].isValid())
1147  tmpV.push_back(secondCLCT[bx]);
1148  }
1149  return tmpV;
1150 }
1151 
1152 // shift the BX from 7 to 8
1153 // the unpacked real data CLCTs have central BX at bin 7
1154 // however in simulation the central BX is bin 8
1155 // to make a proper comparison with ALCTs we need
1156 // CLCT and ALCT to have the central BX in the same bin
1158  CSCCLCTDigi lct = bestCLCT[bx];
1160  return lct;
1161 }
1162 
1164  CSCCLCTDigi lct = secondCLCT[bx];
1166  return lct;
1167 }
1168 
1171 
1173  const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) {
1174  inTimeHMT_ = 0;
1175 
1176  auto layerTime = [=](unsigned time) { return time == CSCConstants::CLCT_CENTRAL_BX; };
1177  // Calculate layers with hits
1178  unsigned nLayersWithHits = 0;
1179  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1180  bool atLeastOneWGHit = false;
1181  for (int i_hstrip = 0; i_hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; i_hstrip++) {
1182  // there is at least one halfstrip...
1183  if (!halfstrip[i_layer][i_hstrip].empty()) {
1184  auto times = halfstrip[i_layer][i_hstrip];
1185  int nLayerTime = std::count_if(times.begin(), times.end(), layerTime);
1186  // ...for which at least one time bin was on for the central BX
1187  if (nLayerTime > 0) {
1188  atLeastOneWGHit = true;
1189  break;
1190  }
1191  }
1192  }
1193  // add this layer to the number of layers hit
1194  if (atLeastOneWGHit) {
1195  nLayersWithHits++;
1196  }
1197  }
1198 
1199  // require at least nLayersWithHits for the central time bin
1200  // do nothing if there are not enough layers with hits
1201  if (nLayersWithHits < minLayersCentralTBin_)
1202  return;
1203 
1204  // functions for in-time and out-of-time
1205  auto inTime = [=](unsigned time) { return time >= showerMinInTBin_ and time <= showerMaxInTBin_; };
1206 
1207  // count the half-strips in-time and out-time
1208  unsigned hitsInTime = 0;
1209  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1210  for (int i_hstrip = 0; i_hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; i_hstrip++) {
1211  auto times = halfstrip[i_layer][i_hstrip];
1212  hitsInTime += std::count_if(times.begin(), times.end(), inTime);
1213  }
1214  }
1215 
1216  // convert station and ring number to index
1217  // index runs from 2 to 10, subtract 2
1218  unsigned csc_idx = CSCDetId::iChamberType(theStation, theRing) - 2;
1219 
1220  // loose, nominal and tight
1221  std::vector<unsigned> station_thresholds = {
1222  thresholds_[csc_idx * 3], thresholds_[csc_idx * 3 + 1], thresholds_[csc_idx * 3 + 2]};
1223 
1224  // assign the bits
1225  for (unsigned i = 0; i < station_thresholds.size(); i++) {
1226  if (hitsInTime >= station_thresholds[i]) {
1227  inTimeHMT_ = i + 1;
1228  }
1229  }
1230 
1231  // create a new object
1233 }
std::unique_ptr< ComparatorCodeLUT > cclut_
void setESLookupTables(const CSCL1TPLookupTableCCLUT *conf)
static const unsigned int def_drift_delay
void dumpDigis(const std::vector< int > strip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) const
CSCCLCTDigi bestCLCT[CSCConstants::MAX_CLCT_TBINS]
void clear()
Definition: PulseArray.cc:14
std::vector< CSCCLCTDigi > readoutCLCTs() const
static const unsigned int def_fifo_tbins
CSCCathodeLCTProcessor(unsigned endcap, unsigned station, unsigned sector, unsigned subsector, unsigned chamber, const edm::ParameterSet &conf)
const bool isValid(const Frame &aFrame, const FrameQuality &aQuality, const uint16_t aExpectedPos)
uint16_t getBX() const
return BX
Definition: CSCCLCTDigi.h:123
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
const unsigned theEndcap
Definition: CSCBaseboard.h:42
unsigned int clctHitPersist() const
static std::string chamberName(int endcap, int station, int ring, int chamber)
Definition: CSCDetId.cc:74
const CSCChamber * cscChamber_
Definition: CSCBaseboard.h:72
uint32_t const *__restrict__ Quality * quality
CSCShowerDigi readoutShower() const
void checkConfigParameters(unsigned int &var, const unsigned int var_max, const unsigned int var_def, const std::string &var_str)
unsigned int clctNplanesHitPattern() const
void pulseExtension(const std::vector< int > time[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER])
const unsigned theSector
Definition: CSCBaseboard.h:44
static const unsigned int def_min_separation
int numberOfStrips() const
CSCPatternBank::LCTPatterns clct_pattern_
bool patternFinding(const unsigned int bx_time, std::map< int, std::map< int, CSCCLCTDigi::ComparatorContainer > > &hits_in_patterns)
bool disableME1a_
Definition: CSCBaseboard.h:97
Log< level::Error, false > LogError
std::unique_ptr< LCTQualityControl > qualityControl_
unsigned int clctMinSeparation() const
std::string theCSCName_
Definition: CSCBaseboard.h:90
unsigned int clctNplanesHitPretrig() const
static const unsigned int def_nplanes_hit_pretrig
#define LogTrace(id)
unsigned int clctDriftDelay() const
bool gangedME1a_
Definition: CSCBaseboard.h:97
uint16_t getKeyStrip(const uint16_t n=2) const
Definition: CSCCLCTDigi.cc:107
static const unsigned int def_pid_thresh_pretrig
unsigned numberOfLayersAtBX(const unsigned bx) const
Definition: PulseArray.cc:41
std::vector< std::vector< uint16_t > > ComparatorContainer
Definition: CSCCLCTDigi.h:19
unsigned int nhits[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]
const unsigned theTrigChamber
Definition: CSCBaseboard.h:46
static const LCTPatterns clct_pattern_run3_
CSCCLCTDigi getSecondCLCT(int bx) const
unsigned int clctPidThreshPretrig() const
unsigned bitsInPulse() const
Definition: PulseArray.cc:25
static const unsigned int def_tmb_l1a_window_size
bool getDigis(const CSCComparatorDigiCollection *compdc)
static const unsigned int def_nplanes_hit_pattern
void setHits(const ComparatorContainer &hits)
Definition: CSCCLCTDigi.h:178
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:30
bool isValid() const
check CLCT validity (1 - valid CLCT)
Definition: CSCCLCTDigi.h:50
static const int clct_pattern_offset_[CSCConstants::CLCT_PATTERN_WIDTH]
unsigned theChamber
Definition: CSCBaseboard.h:49
unsigned short iChamberType() const
Definition: CSCDetId.h:96
bool isOneShotHighAtBX(const unsigned layer, const unsigned channel, const unsigned bx) const
Definition: PulseArray.cc:37
static int getPatternBend(const LCTPattern &pattern)
unsigned int clctFifoPretrig() const
edm::ParameterSet clctParams_
Definition: CSCBaseboard.h:84
CSCCLCTDigi getBestCLCT(int bx) const
CSCCLCTPreTriggerDigi constructPreCLCT(const int bx, const unsigned halfstrip, const unsigned index) const
std::vector< CSCCLCTPreTriggerDigi > thePreTriggerDigis
static const LCTPatterns clct_pattern_legacy_
edm::ParameterSet tmbParams_
Definition: CSCBaseboard.h:78
std::string chamberName() const
Definition: CSCDetId.cc:92
int stagger() const
std::vector< CSCCLCTDigi > getCLCTs() const
virtual std::vector< CSCCLCTDigi > findLCTs(const std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER])
void markBusyKeys(const int best_hstrip, const int best_patid, int quality[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER])
ParameterSet const & getParameterSet(std::string const &) const
static const unsigned int def_fifo_pretrig
std::vector< int > thePreTriggerBXs
std::pair< const_iterator, const_iterator > Range
static const unsigned int def_hit_persist
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
const unsigned theStation
Definition: CSCBaseboard.h:43
int stagger[CSCConstants::NUM_LAYERS]
std::vector< DigiType >::const_iterator const_iterator
const ComparatorContainer & getHits() const
Definition: CSCCLCTDigi.h:176
void cleanComparatorContainer(CSCCLCTDigi &lct) const
std::vector< CSCCLCTDigi > run(const CSCComparatorDigiCollection *compdc)
void initialize(unsigned numberOfChannels)
Definition: PulseArray.cc:5
void setBX(const uint16_t bx)
set bx
Definition: CSCCLCTDigi.h:129
unsigned int clctFifoTbins() const
virtual bool preTrigger(const int start_bx, int &first_bx)
CSCCLCTDigi secondCLCT[CSCConstants::MAX_CLCT_TBINS]
void clear()
clear this CLCT
Definition: CSCCLCTDigi.cc:73
std::vector< CSCComparatorDigi > digiV[CSCConstants::NUM_LAYERS]
unsigned theRing
Definition: CSCBaseboard.h:48
Log< level::Warning, false > LogWarning
edm::ParameterSet showerParams_
Definition: CSCBaseboard.h:87
void readComparatorDigis(std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER])
CSCCLCTDigi constructCLCT(const int bx, const unsigned halfstrip_withstagger, const CSCCLCTDigi::ComparatorContainer &hits)
void encodeHighMultiplicityBits(const std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER])
const CSCLayerGeometry * geometry() const
Definition: CSCLayer.h:44
void extend(const unsigned layer, const unsigned channel, const unsigned bx, const unsigned hit_persist)
Definition: PulseArray.cc:27
bool ispretrig_[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]
void setConfigParameters(const CSCDBL1TPParameters *conf)
const unsigned theSubsector
Definition: CSCBaseboard.h:45
void setTrknmb(const uint16_t number)
Set track number (1,2) after sorting CLCTs.
Definition: CSCCLCTDigi.h:162
#define LogDebug(id)
unsigned int best_pid[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]
std::vector< unsigned > thresholds_