CMS 3D CMS Logo

CSCCathodeLCTProcessor.cc
Go to the documentation of this file.
2 
3 #include <iomanip>
4 #include <iostream>
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  // separate handle for early time bins
50  early_tbins = tmbParams_.getParameter<int>("tmbEarlyTbins");
51  if (early_tbins < 0)
52  early_tbins = fifo_pretrig - CSCConstants::CLCT_EMUL_TIME_OFFSET;
53 
54  // wether to readout only the earliest two LCTs in readout window
55  readout_earliest_2 = tmbParams_.getParameter<bool>("tmbReadoutEarliest2");
56 
57  // Verbosity level, set to 0 (no print) by default.
58  infoV = clctParams_.getParameter<int>("verbosity");
59 
60  // Check and print configuration parameters.
62  if ((infoV > 0) && !config_dumped) {
64  config_dumped = true;
65  }
66 
67  numStrips = 0; // Will be set later.
68  // Provisional, but should be OK for all stations except ME1.
69  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
70  if ((i_layer + 1) % 2 == 0)
71  stagger[i_layer] = 0;
72  else
73  stagger[i_layer] = 1;
74  }
75 
76  thePreTriggerDigis.clear();
77 }
78 
80  // constructor for debugging.
81  static std::atomic<bool> config_dumped{false};
82 
83  // CLCT configuration parameters.
85  infoV = 2;
86 
87  early_tbins = 4;
88 
89  start_bx_shift = 0;
90 
91  // Check and print configuration parameters.
93  if (!config_dumped) {
95  config_dumped = true;
96  }
97 
99  // Should be OK for all stations except ME1.
100  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
101  if ((i_layer + 1) % 2 == 0)
102  stagger[i_layer] = 0;
103  else
104  stagger[i_layer] = 1;
105  }
106 
107  thePreTriggerDigis.clear();
108 }
109 
111  // Set default values for configuration parameters.
121 }
122 
123 // Set configuration parameters obtained via EventSetup mechanism.
125  static std::atomic<bool> config_dumped{false};
126 
127  fifo_tbins = conf->clctFifoTbins();
128  fifo_pretrig = conf->clctFifoPretrig();
129  hit_persist = conf->clctHitPersist();
130  drift_delay = conf->clctDriftDelay();
135 
136  // Check and print configuration parameters.
138  if (!config_dumped) {
140  config_dumped = true;
141  }
142 }
143 
145  // Make sure that the parameter values are within the allowed range.
146 
147  // Max expected values.
148  static const unsigned int max_fifo_tbins = 1 << 5;
149  static const unsigned int max_fifo_pretrig = 1 << 5;
150  static const unsigned int max_hit_persist = 1 << 4;
151  static const unsigned int max_drift_delay = 1 << 2;
152  static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
153  static const unsigned int max_nplanes_hit_pattern = 1 << 3;
154  static const unsigned int max_pid_thresh_pretrig = 1 << 4;
155  static const unsigned int max_min_separation = CSCConstants::NUM_HALF_STRIPS_7CFEBS;
156  static const unsigned int max_tmb_l1a_window_size = 1 << 4;
157 
158  // Checks.
159  if (fifo_tbins >= max_fifo_tbins) {
160  if (infoV >= 0)
161  edm::LogError("L1CSCTPEmulatorConfigError")
162  << "+++ Value of fifo_tbins, " << fifo_tbins << ", exceeds max allowed, " << max_fifo_tbins - 1 << " +++\n"
163  << "+++ Try to proceed with the default value, fifo_tbins=" << def_fifo_tbins << " +++\n";
165  }
166  if (fifo_pretrig >= max_fifo_pretrig) {
167  if (infoV >= 0)
168  edm::LogError("L1CSCTPEmulatorConfigError")
169  << "+++ Value of fifo_pretrig, " << fifo_pretrig << ", exceeds max allowed, " << max_fifo_pretrig - 1
170  << " +++\n"
171  << "+++ Try to proceed with the default value, fifo_pretrig=" << def_fifo_pretrig << " +++\n";
173  }
174  if (hit_persist >= max_hit_persist) {
175  if (infoV >= 0)
176  edm::LogError("L1CSCTPEmulatorConfigError")
177  << "+++ Value of hit_persist, " << hit_persist << ", exceeds max allowed, " << max_hit_persist - 1 << " +++\n"
178  << "+++ Try to proceed with the default value, hit_persist=" << def_hit_persist << " +++\n";
180  }
181  if (drift_delay >= max_drift_delay) {
182  if (infoV >= 0)
183  edm::LogError("L1CSCTPEmulatorConfigError")
184  << "+++ Value of drift_delay, " << drift_delay << ", exceeds max allowed, " << max_drift_delay - 1 << " +++\n"
185  << "+++ Try to proceed with the default value, drift_delay=" << def_drift_delay << " +++\n";
187  }
188  if (nplanes_hit_pretrig >= max_nplanes_hit_pretrig) {
189  if (infoV >= 0)
190  edm::LogError("L1CSCTPEmulatorConfigError")
191  << "+++ Value of nplanes_hit_pretrig, " << nplanes_hit_pretrig << ", exceeds max allowed, "
192  << max_nplanes_hit_pretrig - 1 << " +++\n"
193  << "+++ Try to proceed with the default value, nplanes_hit_pretrig=" << def_nplanes_hit_pretrig << " +++\n";
195  }
196  if (nplanes_hit_pattern >= max_nplanes_hit_pattern) {
197  if (infoV >= 0)
198  edm::LogError("L1CSCTPEmulatorConfigError")
199  << "+++ Value of nplanes_hit_pattern, " << nplanes_hit_pattern << ", exceeds max allowed, "
200  << max_nplanes_hit_pattern - 1 << " +++\n"
201  << "+++ Try to proceed with the default value, nplanes_hit_pattern=" << def_nplanes_hit_pattern << " +++\n";
203  }
204 
205  if (pid_thresh_pretrig >= max_pid_thresh_pretrig) {
206  if (infoV >= 0)
207  edm::LogError("L1CSCTPEmulatorConfigError")
208  << "+++ Value of pid_thresh_pretrig, " << pid_thresh_pretrig << ", exceeds max allowed, "
209  << max_pid_thresh_pretrig - 1 << " +++\n"
210  << "+++ Try to proceed with the default value, pid_thresh_pretrig=" << def_pid_thresh_pretrig << " +++\n";
212  }
213  if (min_separation >= max_min_separation) {
214  if (infoV >= 0)
215  edm::LogError("L1CSCTPEmulatorConfigError")
216  << "+++ Value of min_separation, " << min_separation << ", exceeds max allowed, " << max_min_separation - 1
217  << " +++\n"
218  << "+++ Try to proceed with the default value, min_separation=" << def_min_separation << " +++\n";
220  }
221 
222  if (tmb_l1a_window_size >= max_tmb_l1a_window_size) {
223  if (infoV > 0)
224  edm::LogError("L1CSCTPEmulatorConfigError")
225  << "+++ Value of tmb_l1a_window_size, " << tmb_l1a_window_size << ", exceeds max allowed, "
226  << max_tmb_l1a_window_size - 1 << " +++\n"
227  << "+++ Try to proceed with the default value, tmb_l1a_window_size=" << def_tmb_l1a_window_size << " +++\n";
229  }
230 }
231 
233  thePreTriggerDigis.clear();
234  thePreTriggerBXs.clear();
235  for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
236  bestCLCT[bx].clear();
237  secondCLCT[bx].clear();
238  }
239 }
240 
241 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::run(const CSCComparatorDigiCollection* compdc) {
242  // This is the version of the run() function that is called when running
243  // over the entire detector. It gets the comparator & timing info from the
244  // comparator digis and then passes them on to another run() function.
245 
246  // clear(); // redundant; called by L1MuCSCMotherboard.
247 
248  static std::atomic<bool> config_dumped{false};
249  if ((infoV > 0) && !config_dumped) {
251  config_dumped = true;
252  }
253 
254  // Get the number of strips and stagger of layers for the given chamber.
255  // Do it only once per chamber.
256  if (numStrips == 0) {
257  if (cscChamber_) {
259  // ME1/a is known to the readout hardware as strips 65-80 of ME1/1.
260  // Still need to decide whether we do any special adjustments to
261  // reconstruct LCTs in this region (3:1 ganged strips); for now, we
262  // simply allow for hits in ME1/a and apply standard reconstruction
263  // to them.
264  // For SLHC ME1/1 is set to have 4 CFEBs in ME1/b and 3 CFEBs in ME1/a
265  if (isME11_) {
266  if (theRing == 4) {
267  if (infoV >= 0) {
268  edm::LogError("L1CSCTPEmulatorSetupError")
269  << "+++ Invalid ring number for this processor " << theRing << " was set in the config."
270  << " +++\n"
271  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
272  }
273  }
274  if (!disableME1a_ && theRing == 1 && !gangedME1a_)
276  if (!disableME1a_ && theRing == 1 && gangedME1a_)
278  if (disableME1a_ && theRing == 1)
280  }
281 
283  if (infoV >= 0)
284  edm::LogError("L1CSCTPEmulatorSetupError")
285  << "+++ Number of strips, " << numStrips << " found in "
287  << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
288  << " exceeds max expected, " << CSCConstants::MAX_NUM_STRIPS_7CFEBS << " +++\n"
289  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
290  numStrips = -1;
291  }
292  // The strips for a given layer may be offset from the adjacent layers.
293  // This was done in order to improve resolution. We need to find the
294  // 'staggering' for each layer and make necessary conversions in our
295  // arrays. -JM
296  // In the TMB-07 firmware, half-strips in odd layers (layers are
297  // counted as ly0-ly5) are shifted by -1 half-strip, whereas in
298  // the previous firmware versions half-strips in even layers
299  // were shifted by +1 half-strip. This difference is due to a
300  // change from ly3 to ly2 in the choice of the key layer, and
301  // the intention to keep half-strips in the key layer unchanged.
302  // In the emulator, we use the old way for both cases, to avoid
303  // negative half-strip numbers. This will necessitate a
304  // subtraction of 1 half-strip for TMB-07 later on. -SV.
305  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
306  stagger[i_layer] = (cscChamber_->layer(i_layer + 1)->geometry()->stagger() + 1) / 2;
307  }
308  } else {
309  if (infoV >= 0)
310  edm::LogError("L1CSCTPEmulatorConfigError")
311  << " " << CSCDetId::chamberName(theEndcap, theStation, theRing, theChamber) << " (sector " << theSector
312  << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
313  << " is not defined in current geometry! +++\n"
314  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
315  numStrips = -1;
316  }
317  }
318 
319  if (numStrips < 0) {
320  if (infoV >= 0)
321  edm::LogError("L1CSCTPEmulatorConfigError")
322  << " " << CSCDetId::chamberName(theEndcap, theStation, theRing, theChamber) << " (sector " << theSector
323  << " subsector " << theSubsector << " trig id. " << theTrigChamber << "):"
324  << " numStrips = " << numStrips << "; CLCT emulation skipped! +++";
325  std::vector<CSCCLCTDigi> emptyV;
326  return emptyV;
327  }
328 
329  // Get comparator digis in this chamber.
330  bool noDigis = getDigis(compdc);
331 
332  if (!noDigis) {
333  // Get halfstrip times from comparator digis.
335  readComparatorDigis(halfstrip);
336 
337  // Pass arrays of halfstrips on to another run() doing the
338  // LCT search.
339  // If the number of layers containing digis is smaller than that
340  // required to trigger, quit right away. (If LCT-based digi suppression
341  // is implemented one day, this condition will have to be changed
342  // to the number of planes required to pre-trigger.)
343  unsigned int layersHit = 0;
344  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
345  for (int i_hstrip = 0; i_hstrip < CSCConstants::NUM_HALF_STRIPS_7CFEBS; i_hstrip++) {
346  if (!halfstrip[i_layer][i_hstrip].empty()) {
347  layersHit++;
348  break;
349  }
350  }
351  }
352  // Run the algorithm only if the probability for the pre-trigger
353  // to fire is not null. (Pre-trigger decisions are used for the
354  // strip read-out conditions in DigiToRaw.)
355  if (layersHit >= nplanes_hit_pretrig)
356  run(halfstrip);
357  }
358 
359  // Return vector of CLCTs.
360  std::vector<CSCCLCTDigi> tmpV = getCLCTs();
361 
362  // shift the BX from 7 to 8
363  // the unpacked real data CLCTs have central BX at bin 7
364  // however in simulation the central BX is bin 8
365  // to make a proper comparison with ALCTs we need
366  // CLCT and ALCT to have the central BX in the same bin
367  // this shift does not affect the readout of the CLCTs
368  // emulated CLCTs put in the event should be centered at bin 7 (as in data)
369  for (auto& p : tmpV) {
370  p.setBX(p.getBX() + alctClctOffset_);
371  }
372 
373  return tmpV;
374 }
375 
377  const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
378  // This version of the run() function can either be called in a standalone
379  // test, being passed the halfstrip times, or called by the
380  // run() function above. It uses the findLCTs() method to find vectors
381  // of LCT candidates. These candidates are sorted and the best two per bx
382  // are returned.
383  std::vector<CSCCLCTDigi> CLCTlist = findLCTs(halfstrip);
384 
385  // LCT sorting.
386  if (CLCTlist.size() > 1)
387  sort(CLCTlist.begin(), CLCTlist.end(), std::greater<CSCCLCTDigi>());
388 
389  // Take the best two candidates per bx.
390  for (const auto& p : CLCTlist) {
391  const int bx = p.getBX();
392  if (bx >= CSCConstants::MAX_CLCT_TBINS) {
393  if (infoV > 0)
394  edm::LogWarning("L1CSCTPEmulatorOutOfTimeCLCT")
395  << "+++ Bx of CLCT candidate, " << bx << ", exceeds max allowed, " << CSCConstants::MAX_CLCT_TBINS - 1
396  << "; skipping it... +++\n";
397  continue;
398  }
399 
400  if (!bestCLCT[bx].isValid()) {
401  bestCLCT[bx] = p;
402  } else if (!secondCLCT[bx].isValid()) {
403  secondCLCT[bx] = p;
404  }
405  }
406 
407  for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
408  if (bestCLCT[bx].isValid()) {
409  bestCLCT[bx].setTrknmb(1);
410  if (infoV > 0)
411  LogDebug("CSCCathodeLCTProcessor")
413  << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
414  << "\n";
415  }
416  if (secondCLCT[bx].isValid()) {
417  secondCLCT[bx].setTrknmb(2);
418  if (infoV > 0)
419  LogDebug("CSCCathodeLCTProcessor")
421  << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
422  << "\n";
423  }
424  }
425  // Now that we have our best CLCTs, they get correlated with the best
426  // ALCTs and then get sent to the MotherBoard. -JM
427 }
428 
430  bool noDigis = true;
431 
432  // Loop over layers and save comparator digis on each one into digiV[layer].
433  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
434  digiV[i_layer].clear();
435 
436  CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer + 1);
437  getDigis(compdc, detid);
438 
439  if (isME11_ && !disableME1a_) {
440  CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer + 1);
441  getDigis(compdc, detid_me1a);
442  }
443 
444  if (!digiV[i_layer].empty()) {
445  noDigis = false;
446  if (infoV > 1) {
447  LogTrace("CSCCathodeLCTProcessor") << "found " << digiV[i_layer].size() << " comparator digi(s) in layer "
448  << i_layer << " of " << detid.chamberName() << " (trig. sector " << theSector
449  << " subsector " << theSubsector << " id " << theTrigChamber << ")";
450  }
451  }
452  }
453 
454  return noDigis;
455 }
456 
458  const bool me1a = (id.station() == 1) && (id.ring() == 4);
459  const CSCComparatorDigiCollection::Range rcompd = compdc->get(id);
460  for (CSCComparatorDigiCollection::const_iterator digiIt = rcompd.first; digiIt != rcompd.second; ++digiIt) {
461  const unsigned int origStrip = digiIt->getStrip();
462  const unsigned int maxStripsME1a =
464  // this special case can only be reached in MC
465  // in real data, the comparator digis have always ring==1
466  if (me1a && origStrip <= maxStripsME1a && !disableME1a_) {
467  // Move ME1/A comparators from CFEB=0 to CFEB=4 if this has not
468  // been done already.
469  CSCComparatorDigi digi_corr(
470  origStrip + CSCConstants::MAX_NUM_STRIPS_ME1B, digiIt->getComparator(), digiIt->getTimeBinWord());
471  digiV[id.layer() - 1].push_back(digi_corr);
472  } else {
473  digiV[id.layer() - 1].push_back(*digiIt);
474  }
475  }
476 }
477 
479  std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
480  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
481  int i_digi = 0; // digi counter, for dumps.
482  for (std::vector<CSCComparatorDigi>::iterator pld = digiV[i_layer].begin(); pld != digiV[i_layer].end();
483  pld++, i_digi++) {
484  // Dump raw digi info.
485  if (infoV > 1) {
486  std::ostringstream strstrm;
487  strstrm << "Comparator digi: comparator = " << pld->getComparator() << " strip #" << pld->getStrip()
488  << " time bins on:";
489  std::vector<int> bx_times = pld->getTimeBinsOn();
490  for (unsigned int tbin = 0; tbin < bx_times.size(); tbin++)
491  strstrm << " " << bx_times[tbin];
492  LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
493  }
494 
495  // Get comparator: 0/1 for left/right halfstrip for each comparator
496  // that fired.
497  int thisComparator = pld->getComparator();
498  if (thisComparator != 0 && thisComparator != 1) {
499  if (infoV >= 0)
500  edm::LogWarning("L1CSCTPEmulatorWrongInput")
501  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
502  << " Found comparator digi with wrong comparator value = " << thisComparator << "; skipping it... +++\n";
503  continue;
504  }
505 
506  // Get strip number.
507  int thisStrip = pld->getStrip() - 1; // count from 0
508  if (thisStrip < 0 || thisStrip >= numStrips) {
509  if (infoV >= 0)
510  edm::LogWarning("L1CSCTPEmulatorWrongInput")
511  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
512  << " Found comparator digi with wrong strip number = " << thisStrip << " (max strips = " << numStrips
513  << "); skipping it... +++\n";
514  continue;
515  }
516  // 2*strip: convert strip to 1/2 strip
517  // comp : comparator output
518  // stagger: stagger for this layer
519  int thisHalfstrip = 2 * thisStrip + thisComparator + stagger[i_layer];
520  if (thisHalfstrip >= 2 * numStrips + 1) {
521  if (infoV >= 0)
522  edm::LogWarning("L1CSCTPEmulatorWrongInput")
523  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
524  << " Found wrong halfstrip number = " << thisHalfstrip << "; skipping this digi... +++\n";
525  continue;
526  }
527 
528  // Get bx times on this digi and check that they are within the bounds.
529  std::vector<int> bx_times = pld->getTimeBinsOn();
530  for (unsigned int i = 0; i < bx_times.size(); i++) {
531  // Total number of time bins in DAQ readout is given by fifo_tbins,
532  // which thus determines the maximum length of time interval.
533  //
534  // In data, only the CLCT in the time bin that was matched with L1A are read out
535  // while comparator digi is read out by 12 time bin, which includes 12 time bin info
536  // in other word, CLCTs emulated from comparator digis usually showed the OTMB behavior in 12 time bin
537  // while CLCT from data only showed 1 time bin OTMB behavior
538  // the CLCT emulated from comparator digis usually is centering at time bin 7 (BX7) and
539  // it is definitly safe to ignore any CLCTs in bx 0 or 1 and those CLCTs will never impacts on any triggers
540  if (bx_times[i] > 1 && bx_times[i] < static_cast<int>(fifo_tbins)) {
541  if (i == 0 || (i > 0 && bx_times[i] - bx_times[i - 1] >= static_cast<int>(hit_persist))) {
542  // A later hit on the same strip is ignored during the
543  // number of clocks defined by the "hit_persist" parameter
544  // (i.e., 6 bx's by default).
545  if (infoV > 1)
546  LogTrace("CSCCathodeLCTProcessor")
547  << "Comp digi: layer " << i_layer + 1 << " digi #" << i_digi + 1 << " strip " << thisStrip
548  << " halfstrip " << thisHalfstrip << " time " << bx_times[i] << " comparator " << thisComparator
549  << " stagger " << stagger[i_layer];
550  halfstrip[i_layer][thisHalfstrip].push_back(bx_times[i]);
551  } else if (i > 0) {
552  if (infoV > 1)
553  LogTrace("CSCCathodeLCTProcessor")
554  << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
555  << " Skipping comparator digi: strip = " << thisStrip << ", layer = " << i_layer + 1
556  << ", bx = " << bx_times[i] << ", bx of previous hit = " << bx_times[i - 1];
557  }
558  } else {
559  if (infoV > 1)
560  LogTrace("CSCCathodeLCTProcessor") << "+++ station " << theStation << " ring " << theRing << " chamber "
561  << theChamber << "+++ Skipping comparator digi: strip = " << thisStrip
562  << ", layer = " << i_layer + 1 << ", bx = " << bx_times[i] << " +++";
563  }
564  }
565  }
566  }
567 }
568 
569 // TMB-07 version.
570 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(
571  const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
572  std::vector<CSCCLCTDigi> lctList;
573 
574  // Max. number of half-strips for this chamber.
575  const int maxHalfStrips = 2 * numStrips + 1;
576 
577  if (infoV > 1)
578  dumpDigis(halfstrip, maxHalfStrips);
579 
580  // 2 possible LCTs per CSC x 7 LCT quantities
583 
584  // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
585  pulseExtension(halfstrip, maxHalfStrips, pulse);
586 
587  unsigned int start_bx = start_bx_shift;
588  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
589  // not have a full set of hits to start pattern search anyway.
590  unsigned int stop_bx = fifo_tbins - drift_delay;
591  // Allow for more than one pass over the hits in the time window.
592  while (start_bx < stop_bx) {
593  // All half-strip pattern envelopes are evaluated simultaneously, on every
594  // clock cycle.
595  int first_bx = 999;
596  bool pre_trig = preTrigger(pulse, start_bx, first_bx);
597 
598  // If any of half-strip envelopes has enough layers hit in it, TMB
599  // will pre-trigger.
600  if (pre_trig) {
601  thePreTriggerBXs.push_back(first_bx);
602  if (infoV > 1)
603  LogTrace("CSCCathodeLCTProcessor") << "..... pretrigger at bx = " << first_bx << "; waiting drift delay .....";
604 
605  // TMB latches LCTs drift_delay clocks after pretrigger.
606  int latch_bx = first_bx + drift_delay;
607  bool hits_in_time = patternFinding(pulse, maxHalfStrips, latch_bx);
608  if (infoV > 1) {
609  if (hits_in_time) {
610  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++) {
611  if (nhits[hstrip] > 0) {
612  LogTrace("CSCCathodeLCTProcessor")
613  << " bx = " << std::setw(2) << latch_bx << " --->"
614  << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
615  << " nhits = " << nhits[hstrip];
616  }
617  }
618  }
619  }
620  // The pattern finder runs continuously, so another pre-trigger
621  // could occur already at the next bx.
622  //start_bx = first_bx + 1;
623 
624  // Quality for sorting.
627  for (int ilct = 0; ilct < CSCConstants::MAX_CLCTS_PER_PROCESSOR; ilct++) {
628  best_halfstrip[ilct] = -1;
629  best_quality[ilct] = 0;
630  }
631 
632  // Calculate quality from pattern id and number of hits, and
633  // simultaneously select best-quality LCT.
634  if (hits_in_time) {
635  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++) {
636  // The bend-direction bit pid[0] is ignored (left and right
637  // bends have equal quality).
638  quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
639  if (quality[hstrip] > best_quality[0]) {
640  best_halfstrip[0] = hstrip;
641  best_quality[0] = quality[hstrip];
642  }
643  if (infoV > 1 && quality[hstrip] > 0) {
644  LogTrace("CSCCathodeLCTProcessor")
645  << " 1st CLCT: halfstrip = " << std::setw(3) << hstrip << " quality = " << std::setw(3)
646  << quality[hstrip] << " nhits = " << std::setw(3) << nhits[hstrip] << " pid = " << std::setw(3)
647  << best_pid[hstrip] << " best halfstrip = " << std::setw(3) << best_halfstrip[0]
648  << " best quality = " << std::setw(3) << best_quality[0];
649  }
650  }
651  }
652 
653  // If 1st best CLCT is found, look for the 2nd best.
654  if (best_halfstrip[0] >= 0) {
655  // Mark keys near best CLCT as busy by setting their quality to
656  // zero, and repeat the search.
657  markBusyKeys(best_halfstrip[0], best_pid[best_halfstrip[0]], quality);
658 
659  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++) {
660  if (quality[hstrip] > best_quality[1]) {
661  best_halfstrip[1] = hstrip;
662  best_quality[1] = quality[hstrip];
663  }
664  if (infoV > 1 && quality[hstrip] > 0) {
665  LogTrace("CSCCathodeLCTProcessor")
666  << " 2nd CLCT: halfstrip = " << std::setw(3) << hstrip << " quality = " << std::setw(3)
667  << quality[hstrip] << " nhits = " << std::setw(3) << nhits[hstrip] << " pid = " << std::setw(3)
668  << best_pid[hstrip] << " best halfstrip = " << std::setw(3) << best_halfstrip[1]
669  << " best quality = " << std::setw(3) << best_quality[1];
670  }
671  }
672 
673  // Pattern finder.
674  //bool ptn_trig = false;
675  for (int ilct = 0; ilct < CSCConstants::MAX_CLCTS_PER_PROCESSOR; ilct++) {
676  int best_hs = best_halfstrip[ilct];
677  if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
678  //ptn_trig = true;
679  keystrip_data[ilct][CLCT_PATTERN] = best_pid[best_hs];
680  keystrip_data[ilct][CLCT_BEND] =
682  // Remove stagger if any.
683  keystrip_data[ilct][CLCT_STRIP] = best_hs - stagger[CSCConstants::KEY_CLCT_LAYER - 1];
684  keystrip_data[ilct][CLCT_BX] = first_bx;
685  keystrip_data[ilct][CLCT_STRIP_TYPE] = 1; // obsolete
686  keystrip_data[ilct][CLCT_QUALITY] = nhits[best_hs];
687  keystrip_data[ilct][CLCT_CFEB] = keystrip_data[ilct][CLCT_STRIP] / CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
688  int halfstrip_in_cfeb = keystrip_data[ilct][CLCT_STRIP] -
689  CSCConstants::NUM_HALF_STRIPS_PER_CFEB * keystrip_data[ilct][CLCT_CFEB];
690 
691  if (infoV > 1)
692  LogTrace("CSCCathodeLCTProcessor")
693  << " Final selection: ilct " << ilct << " key halfstrip " << keystrip_data[ilct][CLCT_STRIP]
694  << " quality " << keystrip_data[ilct][CLCT_QUALITY] << " pattern "
695  << keystrip_data[ilct][CLCT_PATTERN] << " bx " << keystrip_data[ilct][CLCT_BX];
696 
697  CSCCLCTDigi thisLCT(1,
698  keystrip_data[ilct][CLCT_QUALITY],
699  keystrip_data[ilct][CLCT_PATTERN],
700  keystrip_data[ilct][CLCT_STRIP_TYPE],
701  keystrip_data[ilct][CLCT_BEND],
702  halfstrip_in_cfeb,
703  keystrip_data[ilct][CLCT_CFEB],
704  keystrip_data[ilct][CLCT_BX]);
705  lctList.push_back(thisLCT);
706  }
707  }
708  } //find CLCT, end of best_halfstrip[0] >= 0
709 
710  //if (ptn_trig) {
711  // Once there was a trigger, CLCT pre-trigger state machine
712  // checks the number of hits that lie on a pattern template
713  // at every bx, and waits for it to drop below threshold.
714  // The search for CLCTs resumes only when the number of hits
715  // drops below threshold.
716  start_bx = fifo_tbins;
717  // Stop checking drift_delay bx's short of fifo_tbins since
718  // at later bx's we won't have a full set of hits for a
719  // pattern search anyway.
720  unsigned int stop_time = fifo_tbins - drift_delay;
721  for (unsigned int bx = latch_bx + 1; bx < stop_time; bx++) {
722  bool return_to_idle = true;
723  bool hits_in_time = patternFinding(pulse, maxHalfStrips, bx);
724  if (hits_in_time) {
725  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++) {
726  //if (nhits[hstrip] >= nplanes_hit_pattern) {
727  if (nhits[hstrip] >= nplanes_hit_pretrig) { //Tao, move dead time to pretrigger level
728  if (infoV > 1)
729  LogTrace("CSCCathodeLCTProcessor") << " State machine busy at bx = " << bx;
730  return_to_idle = false;
731  break;
732  }
733  }
734  }
735  if (return_to_idle) {
736  if (infoV > 1)
737  LogTrace("CSCCathodeLCTProcessor") << " State machine returns to idle state at bx = " << bx;
738  start_bx = bx;
739  break;
740  }
741  }
742  //}
743  } //pre_trig
744  else {
745  start_bx = first_bx + 1; // no dead time
746  }
747  }
748 
749  return lctList;
750 } // findLCTs -- TMB-07 version.
751 
752 // Common to all versions.
755  const int nStrips,
756  unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
757  static const unsigned int bits_in_pulse = 8 * sizeof(pulse[0][0]);
758 
759  // Clear pulse array. This array will be used as a bit representation of
760  // hit times. For example: if strip[1][2] has a value of 3, then 1 shifted
761  // left 3 will be bit pattern of pulse[1][2]. This would make the pattern
762  // look like 0000000000001000. Then add on additional bits to signify
763  // the duration of a signal (hit_persist, formerly bx_width) to simulate
764  // the TMB's drift delay. So for the same pulse[1][2] with a hit_persist
765  // of 3 would look like 0000000000111000. This is similating the digital
766  // one-shot in the TMB.
767  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
768  for (int i_strip = 0; i_strip < nStrips; i_strip++)
769  pulse[i_layer][i_strip] = 0;
770 
771  // Loop over all layers and halfstrips.
772  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
773  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
774  // If there is a hit, simulate digital one-shot persistence starting
775  // in the bx of the initial hit. Fill this into pulse[][].
776  if (!time[i_layer][i_strip].empty()) {
777  std::vector<int> bx_times = time[i_layer][i_strip];
778  for (unsigned int i = 0; i < bx_times.size(); i++) {
779  // Check that min and max times are within the allowed range.
780  if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
781  if (infoV > 0)
782  edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
783  << "+++ BX time of comparator digi (halfstrip = " << i_strip << " layer = " << i_layer
784  << ") bx = " << bx_times[i] << " is not within the range (0-" << bits_in_pulse
785  << "] allowed for pulse extension. Skip this digi! +++\n";
786  continue;
787  }
788  if (bx_times[i] >= start_bx_shift) {
789  for (unsigned int bx = bx_times[i]; bx < bx_times[i] + hit_persist; ++bx)
790  pulse[i_layer][i_strip] = pulse[i_layer][i_strip] | (1 << bx);
791  }
792  }
793  }
794  }
795  }
796 } // pulseExtension.
797 
798 // TMB-07 version.
801  const int start_bx,
802  int& first_bx) {
803  if (infoV > 1)
804  LogTrace("CSCCathodeLCTProcessor") << "....................PreTrigger...........................";
805 
806  // Max. number of half-strips for this chamber.
807  const int nStrips = 2 * numStrips + 1;
808 
809  int nPreTriggers = 0;
810 
811  bool pre_trig = false;
812  // Now do a loop over bx times to see (if/when) track goes over threshold
813  for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
814  // For any given bunch-crossing, start at the lowest keystrip and look for
815  // the number of separate layers in the pattern for that keystrip that have
816  // pulses at that bunch-crossing time. Do the same for the next keystrip,
817  // etc. Then do the entire process again for the next bunch-crossing, etc
818  // until you find a pre-trigger.
819  bool hits_in_time = patternFinding(pulse, nStrips, bx_time);
820  if (hits_in_time) {
821  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < nStrips; hstrip++) {
822  if (infoV > 1) {
823  if (nhits[hstrip] > 0) {
824  LogTrace("CSCCathodeLCTProcessor")
825  << " bx = " << std::setw(2) << bx_time << " --->"
826  << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
827  << " nhits = " << nhits[hstrip];
828  }
829  }
830  ispretrig[hstrip] = false;
831  if (nhits[hstrip] >= nplanes_hit_pretrig && best_pid[hstrip] >= pid_thresh_pretrig) {
832  pre_trig = true;
833  ispretrig[hstrip] = true;
834 
835  // write each pre-trigger to output
836  nPreTriggers++;
838  const int halfstrip = hstrip % CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
839  const int cfeb = hstrip / CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
841  1, nhits[hstrip], best_pid[hstrip], 1, bend, halfstrip, cfeb, bx_time, nPreTriggers, 0));
842  }
843  }
844 
845  if (pre_trig) {
846  first_bx = bx_time; // bx at time of pretrigger
847  return true;
848  }
849  }
850  } // end loop over bx times
851 
852  if (infoV > 1)
853  LogTrace("CSCCathodeLCTProcessor") << "no pretrigger, returning \n";
854  first_bx = fifo_tbins;
855  return false;
856 } // preTrigger -- TMB-07 version.
857 
858 // TMB-07 version.
861  const int nStrips,
862  const unsigned int bx_time) {
863  if (bx_time >= fifo_tbins)
864  return false;
865 
866  // This loop is a quick check of a number of layers hit at bx_time: since
867  // most of the time it is 0, this check helps to speed-up the execution
868  // substantially.
869  unsigned int layers_hit = 0;
870  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
871  for (int i_hstrip = 0; i_hstrip < nStrips; i_hstrip++) {
872  if (((pulse[i_layer][i_hstrip] >> bx_time) & 1) == 1) {
873  layers_hit++;
874  break;
875  }
876  }
877  }
878  if (layers_hit < nplanes_hit_pretrig)
879  return false;
880 
881  for (int key_hstrip = 0; key_hstrip < nStrips; key_hstrip++) {
882  best_pid[key_hstrip] = 0;
883  nhits[key_hstrip] = 0;
884  first_bx_corrected[key_hstrip] = -999;
885  }
886 
887  // Loop over candidate key strips.
888  bool hit_layer[CSCConstants::NUM_LAYERS];
889  for (int key_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; key_hstrip < nStrips; key_hstrip++) {
890  // Loop over patterns and look for hits matching each pattern.
891  for (unsigned int pid = CSCConstants::NUM_CLCT_PATTERNS - 1; pid >= pid_thresh_pretrig; pid--) {
892  layers_hit = 0;
893  for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++)
894  hit_layer[ilayer] = false;
895 
896  double num_pattern_hits = 0., times_sum = 0.;
897  std::multiset<int> mset_for_median;
898  mset_for_median.clear();
899 
900  // Loop over halfstrips in trigger pattern mask and calculate the
901  // "absolute" halfstrip number for each.
902  for (int strip_num = 0; strip_num < CSCConstants::MAX_HALFSTRIPS_IN_PATTERN; strip_num++) {
903  int this_layer = CSCPatternBank::clct_pattern[pid][strip_num];
904  if (this_layer >= 0 && this_layer < CSCConstants::NUM_LAYERS) {
905  int this_strip = CSCPatternBank::clct_pattern_offset[strip_num] + key_hstrip;
906  if (this_strip >= 0 && this_strip < nStrips) {
907  if (infoV > 3)
908  LogTrace("CSCCathodeLCTProcessor")
909  << " In patternFinding: key_strip = " << key_hstrip << " pid = " << pid
910  << " strip_num = " << strip_num << " layer = " << this_layer << " strip = " << this_strip;
911  // Determine if "one shot" is high at this bx_time
912  if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1) {
913  if (hit_layer[this_layer] == false) {
914  hit_layer[this_layer] = true;
915  layers_hit++; // determines number of layers hit
916  }
917 
918  // find at what bx did pulse on this halsfstrip&layer have started
919  // use hit_pesrist constraint on how far back we can go
920  int first_bx_layer = bx_time;
921  for (unsigned int dbx = 0; dbx < hit_persist; dbx++) {
922  if (((pulse[this_layer][this_strip] >> (first_bx_layer - 1)) & 1) == 1)
923  first_bx_layer--;
924  else
925  break;
926  }
927  times_sum += (double)first_bx_layer;
928  num_pattern_hits += 1.;
929  mset_for_median.insert(first_bx_layer);
930  if (infoV > 2)
931  LogTrace("CSCCathodeLCTProcessor") << " 1st bx in layer: " << first_bx_layer << " sum bx: " << times_sum
932  << " #pat. hits: " << num_pattern_hits;
933  }
934  }
935  }
936  } // end loop over strips in pretrigger pattern
937 
938  if (layers_hit > nhits[key_hstrip]) {
939  best_pid[key_hstrip] = pid;
940  nhits[key_hstrip] = layers_hit;
941 
942  // calculate median
943  const int sz = mset_for_median.size();
944  if (sz > 0) {
945  std::multiset<int>::iterator im = mset_for_median.begin();
946  if (sz > 1)
947  std::advance(im, sz / 2 - 1);
948  if (sz == 1)
949  first_bx_corrected[key_hstrip] = *im;
950  else if ((sz % 2) == 1)
951  first_bx_corrected[key_hstrip] = *(++im);
952  else
953  first_bx_corrected[key_hstrip] = ((*im) + (*(++im))) / 2;
954 
955 #if defined(EDM_ML_DEBUG)
956  //LogTrace only ever prints if EDM_ML_DEBUG is defined
957  if (infoV > 1) {
958  auto lt = LogTrace("CSCCathodeLCTProcessor")
959  << "bx=" << bx_time << " bx_cor=" << first_bx_corrected[key_hstrip] << " bxset=";
960  for (im = mset_for_median.begin(); im != mset_for_median.end(); im++) {
961  lt << " " << *im;
962  }
963  }
964 #endif
965  }
966  // Do not loop over the other (worse) patterns if max. numbers of
967  // hits is found.
968  if (nhits[key_hstrip] == CSCConstants::NUM_LAYERS)
969  break;
970  }
971  } // end loop over pid
972  } // end loop over candidate key strips
973  return true;
974 } // patternFinding -- TMB-07 version.
975 
976 // TMB-07 version.
977 void CSCCathodeLCTProcessor::markBusyKeys(const int best_hstrip,
978  const int best_patid,
980  int nspan = min_separation;
981  int pspan = min_separation;
982 
983  for (int hstrip = best_hstrip - nspan; hstrip <= best_hstrip + pspan; hstrip++) {
984  if (hstrip >= 0 && hstrip < CSCConstants::NUM_HALF_STRIPS_7CFEBS) {
985  quality[hstrip] = 0;
986  }
987  }
988 } // markBusyKeys -- TMB-07 version.
989 
990 // --------------------------------------------------------------------------
991 // Auxiliary code.
992 // --------------------------------------------------------------------------
993 // Dump of configuration parameters.
995  std::ostringstream strm;
996  strm << "\n";
997  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
998  strm << "+ CLCT configuration parameters: +\n";
999  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1000  strm << " fifo_tbins [total number of time bins in DAQ readout] = " << fifo_tbins << "\n";
1001  strm << " fifo_pretrig [start time of cathode raw hits in DAQ readout] = " << fifo_pretrig << "\n";
1002  strm << " hit_persist [duration of signal pulse, in 25 ns bins] = " << hit_persist << "\n";
1003  strm << " drift_delay [time after pre-trigger before TMB latches LCTs] = " << drift_delay << "\n";
1004  strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = " << nplanes_hit_pretrig << "\n";
1005  strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = " << nplanes_hit_pattern << "\n";
1006  strm << " pid_thresh_pretrig [lower threshold on pattern id] = " << pid_thresh_pretrig << "\n";
1007  strm << " min_separation [region of busy key strips] = " << min_separation << "\n";
1008  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1009  LogDebug("CSCCathodeLCTProcessor") << strm.str();
1010 }
1011 
1012 // Reasonably nice dump of digis on half-strips.
1015  const int nStrips) const {
1016  LogDebug("CSCCathodeLCTProcessor") << CSCDetId::chamberName(theEndcap, theStation, theRing, theChamber)
1017  << " strip type: half-strip, nStrips " << nStrips;
1018 
1019  std::ostringstream strstrm;
1020  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
1021  if (i_strip % 10 == 0) {
1022  if (i_strip < 100)
1023  strstrm << i_strip / 10;
1024  else
1025  strstrm << (i_strip - 100) / 10;
1026  } else
1027  strstrm << " ";
1028  if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1029  strstrm << " ";
1030  }
1031  strstrm << "\n";
1032  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
1033  strstrm << i_strip % 10;
1034  if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1035  strstrm << " ";
1036  }
1037  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1038  strstrm << "\n";
1039  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
1040  if (!strip[i_layer][i_strip].empty()) {
1041  std::vector<int> bx_times = strip[i_layer][i_strip];
1042  // Dump only the first in time.
1043  strstrm << std::hex << bx_times[0] << std::dec;
1044  } else {
1045  strstrm << "-";
1046  }
1047  if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1048  strstrm << " ";
1049  }
1050  }
1051  LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
1052 }
1053 
1054 // Returns vector of read-out CLCTs, if any. Starts with the vector
1055 // of all found CLCTs and selects the ones in the read-out time window.
1056 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::readoutCLCTs() const {
1057  std::vector<CSCCLCTDigi> tmpV;
1058 
1059  // The start time of the L1A*CLCT coincidence window should be
1060  // related to the fifo_pretrig parameter, but I am not completely
1061  // sure how. For now, just choose it such that the window is
1062  // centered at bx=7. This may need further tweaking if the value of
1063  // tmb_l1a_window_size changes.
1064 
1065  // The number of CLCT bins in the read-out is given by the
1066  // tmb_l1a_window_size parameter, but made even by setting the LSB
1067  // of tmb_l1a_window_size to 0.
1068  //
1069  static std::atomic<int> lct_bins;
1070  lct_bins = (tmb_l1a_window_size % 2 == 0) ? tmb_l1a_window_size : tmb_l1a_window_size - 1;
1071  static std::atomic<int> late_tbins;
1072  late_tbins = early_tbins + lct_bins;
1073 
1074  static std::atomic<int> ifois{0};
1075  if (ifois == 0) {
1076  if (infoV >= 0 && early_tbins < 0) {
1077  edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
1078  << "+++ early_tbins = " << early_tbins << "; in-time CLCTs are not getting read-out!!! +++"
1079  << "\n";
1080  }
1081 
1082  if (late_tbins > CSCConstants::MAX_CLCT_TBINS - 1) {
1083  if (infoV >= 0)
1084  edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
1085  << "+++ Allowed range of time bins, [0-" << late_tbins << "] exceeds max allowed, "
1086  << CSCConstants::MAX_CLCT_TBINS - 1 << " +++\n"
1087  << "+++ Set late_tbins to max allowed +++\n";
1088  late_tbins = CSCConstants::MAX_CLCT_TBINS - 1;
1089  }
1090  ifois = 1;
1091  }
1092 
1093  // Start from the vector of all found CLCTs and select those within
1094  // the CLCT*L1A coincidence window.
1095  int bx_readout = -1;
1096  const std::vector<CSCCLCTDigi>& all_lcts = getCLCTs();
1097  for (const auto& p : all_lcts) {
1098  if (!p.isValid())
1099  continue;
1100 
1101  const int bx = p.getBX();
1102  // Skip CLCTs found too early relative to L1Accept.
1103  if (bx <= early_tbins) {
1104  if (infoV > 1)
1105  LogDebug("CSCCathodeLCTProcessor")
1106  << " Do not report CLCT on key halfstrip " << p.getKeyStrip() << ": found at bx " << bx
1107  << ", whereas the earliest allowed bx is " << early_tbins + 1;
1108  continue;
1109  }
1110 
1111  // Skip CLCTs found too late relative to L1Accept.
1112  if (bx > late_tbins) {
1113  if (infoV > 1)
1114  LogDebug("CSCCathodeLCTProcessor")
1115  << " Do not report CLCT on key halfstrip " << p.getKeyStrip() << ": found at bx " << bx
1116  << ", whereas the latest allowed bx is " << late_tbins;
1117  continue;
1118  }
1119 
1120  // If (readout_earliest_2) take only CLCTs in the earliest bx in the read-out window:
1121  // in digi->raw step, LCTs have to be packed into the TMB header, and
1122  // currently there is room just for two.
1123  if (readout_earliest_2) {
1124  if (bx_readout == -1 || bx == bx_readout) {
1125  tmpV.push_back(p);
1126  if (bx_readout == -1)
1127  bx_readout = bx;
1128  }
1129  } else
1130  tmpV.push_back(p);
1131  }
1132  return tmpV;
1133 }
1134 
1135 // Returns vector of read-out CLCTs, if any. Starts with the vector
1136 // of all found CLCTs and selects the ones in the read-out time window.
1137 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::readoutCLCTsME1a() const {
1138  std::vector<CSCCLCTDigi> tmpV;
1139  if (not(theStation == 1 and (theRing == 1 or theRing == 4)))
1140  return tmpV;
1141  const std::vector<CSCCLCTDigi>& allCLCTs = readoutCLCTs();
1142  for (const auto& clct : allCLCTs)
1143  if (clct.getCFEB() >= 4)
1144  tmpV.push_back(clct);
1145  return tmpV;
1146 }
1147 
1148 // Returns vector of read-out CLCTs, if any. Starts with the vector
1149 // of all found CLCTs and selects the ones in the read-out time window.
1150 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::readoutCLCTsME1b() const {
1151  std::vector<CSCCLCTDigi> tmpV;
1152  if (not(theStation == 1 and (theRing == 1 or theRing == 4)))
1153  return tmpV;
1154  const std::vector<CSCCLCTDigi>& allCLCTs = readoutCLCTs();
1155  for (const auto& clct : allCLCTs)
1156  if (clct.getCFEB() < 4)
1157  tmpV.push_back(clct);
1158  return tmpV;
1159 }
1160 
1161 std::vector<CSCCLCTPreTriggerDigi> CSCCathodeLCTProcessor::preTriggerDigisME1a() const {
1162  std::vector<CSCCLCTPreTriggerDigi> tmpV;
1163  if (not(theStation == 1 and (theRing == 1 or theRing == 4)))
1164  return tmpV;
1165  const std::vector<CSCCLCTPreTriggerDigi>& allPretriggerdigis = preTriggerDigis();
1166  for (const auto& preclct : allPretriggerdigis)
1167  if (preclct.getCFEB() >= 4)
1168  tmpV.push_back(preclct);
1169  return tmpV;
1170 }
1171 
1172 std::vector<CSCCLCTPreTriggerDigi> CSCCathodeLCTProcessor::preTriggerDigisME1b() const {
1173  std::vector<CSCCLCTPreTriggerDigi> tmpV;
1174  if (not(theStation == 1 and (theRing == 1 or theRing == 4)))
1175  return tmpV;
1176  const std::vector<CSCCLCTPreTriggerDigi>& allPretriggerdigis = preTriggerDigis();
1177  for (const auto& preclct : allPretriggerdigis)
1178  if (preclct.getCFEB() < 4)
1179  tmpV.push_back(preclct);
1180  return tmpV;
1181 }
1182 
1183 // Returns vector of all found CLCTs, if any. Used for ALCT-CLCT matching.
1184 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::getCLCTs() const {
1185  std::vector<CSCCLCTDigi> tmpV;
1186  for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
1187  if (bestCLCT[bx].isValid())
1188  tmpV.push_back(bestCLCT[bx]);
1189  if (secondCLCT[bx].isValid())
1190  tmpV.push_back(secondCLCT[bx]);
1191  }
1192  return tmpV;
1193 }
1194 
1195 // shift the BX from 7 to 8
1196 // the unpacked real data CLCTs have central BX at bin 7
1197 // however in simulation the central BX is bin 8
1198 // to make a proper comparison with ALCTs we need
1199 // CLCT and ALCT to have the central BX in the same bin
1201  CSCCLCTDigi lct = bestCLCT[bx];
1202  lct.setBX(lct.getBX() + alctClctOffset_);
1203  return lct;
1204 }
1205 
1207  CSCCLCTDigi lct = secondCLCT[bx];
1208  lct.setBX(lct.getBX() + alctClctOffset_);
1209  return lct;
1210 }
#define LogDebug(id)
static const unsigned int def_drift_delay
T getParameter(std::string const &) const
CSCCLCTDigi bestCLCT[CSCConstants::MAX_CLCT_TBINS]
void dumpDigis(const std::vector< int > strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int nStrips) const
bool patternFinding(const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int nStrips, const unsigned int bx_time)
std::vector< CSCCLCTDigi > readoutCLCTs() const
static const unsigned int def_fifo_tbins
bool ispretrig[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
const unsigned theEndcap
Definition: CSCBaseboard.h:37
unsigned int clctHitPersist() const
virtual std::vector< CSCCLCTDigi > findLCTs(const std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
static std::string chamberName(int endcap, int station, int ring, int chamber)
Definition: CSCDetId.cc:62
const CSCChamber * cscChamber_
Definition: CSCBaseboard.h:59
int first_bx_corrected[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
unsigned int clctNplanesHitPattern() const
const unsigned theSector
Definition: CSCBaseboard.h:39
static const unsigned int def_min_separation
int numberOfStrips() const
std::vector< CSCCLCTDigi > readoutCLCTsME1b() const
bool disableME1a_
Definition: CSCBaseboard.h:81
unsigned int clctMinSeparation() const
unsigned int clctNplanesHitPretrig() const
static const unsigned int def_nplanes_hit_pretrig
virtual bool preTrigger(const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int start_bx, int &first_bx)
nStrips
1.2 is to make the matching window safely the two nearest strips 0.35 is the size of an ME0 chamber i...
unsigned int clctDriftDelay() const
bool gangedME1a_
Definition: CSCBaseboard.h:81
static const unsigned int def_pid_thresh_pretrig
static const int clct_pattern_offset[CSCConstants::MAX_HALFSTRIPS_IN_PATTERN]
unsigned int best_pid[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
void markBusyKeys(const int best_hstrip, const int best_patid, int quality[CSCConstants::NUM_HALF_STRIPS_7CFEBS])
const unsigned theTrigChamber
Definition: CSCBaseboard.h:41
void setBX(const int bx)
set bx
Definition: CSCCLCTDigi.h:80
CSCCLCTDigi getSecondCLCT(int bx) const
unsigned int clctPidThreshPretrig() const
void readComparatorDigis(std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
std::vector< CSCCLCTDigi > readoutCLCTsME1a() const
static const unsigned int def_tmb_l1a_window_size
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::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
int getBX() const
return BX
Definition: CSCCLCTDigi.h:77
bool getDigis(const CSCComparatorDigiCollection *compdc)
static const unsigned int def_nplanes_hit_pattern
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:30
unsigned theChamber
Definition: CSCBaseboard.h:44
unsigned int clctFifoPretrig() const
edm::ParameterSet clctParams_
Definition: CSCBaseboard.h:71
CSCCLCTDigi getBestCLCT(int bx) const
#define LogTrace(id)
std::vector< CSCCLCTPreTriggerDigi > thePreTriggerDigis
std::vector< CSCCLCTPreTriggerDigi > preTriggerDigisME1b() const
edm::ParameterSet tmbParams_
Definition: CSCBaseboard.h:65
std::string chamberName() const
Definition: CSCDetId.cc:67
int stagger() const
std::vector< CSCCLCTDigi > getCLCTs() const
double pulse(double x, double y, double z, double t)
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
const unsigned theStation
Definition: CSCBaseboard.h:38
int stagger[CSCConstants::NUM_LAYERS]
std::vector< DigiType >::const_iterator const_iterator
unsigned int nhits[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
std::vector< CSCCLCTDigi > run(const CSCComparatorDigiCollection *compdc)
unsigned int clctFifoTbins() const
#define begin
Definition: vmac.h:32
CSCCLCTDigi secondCLCT[CSCConstants::MAX_CLCT_TBINS]
void clear()
clear this CLCT
Definition: CSCCLCTDigi.cc:54
std::vector< CSCComparatorDigi > digiV[CSCConstants::NUM_LAYERS]
unsigned theRing
Definition: CSCBaseboard.h:43
void pulseExtension(const std::vector< int > time[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int nStrips, unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
std::vector< CSCCLCTPreTriggerDigi > preTriggerDigisME1a() const
unsigned int alctClctOffset_
Definition: CSCBaseboard.h:90
const CSCLayerGeometry * geometry() const
Definition: CSCLayer.h:44
std::vector< CSCCLCTPreTriggerDigi > preTriggerDigis() const
void setConfigParameters(const CSCDBL1TPParameters *conf)
const unsigned theSubsector
Definition: CSCBaseboard.h:40
static const int clct_pattern[CSCConstants::NUM_CLCT_PATTERNS][CSCConstants::MAX_HALFSTRIPS_IN_PATTERN+2]
void setTrknmb(const uint16_t number)
Set track number (1,2) after sorting CLCTs.
Definition: CSCCLCTDigi.h:100