CMS 3D CMS Logo

CSCMotherboard.cc
Go to the documentation of this file.
2 #include <iostream>
3 #include <memory>
4 
5 // Default values of configuration parameters.
6 const unsigned int CSCMotherboard::def_mpc_block_me1a = 1;
7 const unsigned int CSCMotherboard::def_alct_trig_enable = 0;
8 const unsigned int CSCMotherboard::def_clct_trig_enable = 0;
9 const unsigned int CSCMotherboard::def_match_trig_enable = 1;
10 const unsigned int CSCMotherboard::def_match_trig_window_size = 7;
11 const unsigned int CSCMotherboard::def_tmb_l1a_window_size = 7;
12 
14  unsigned station,
15  unsigned sector,
16  unsigned subsector,
17  unsigned chamber,
18  const edm::ParameterSet& conf)
19  : CSCBaseboard(endcap, station, sector, subsector, chamber, conf) {
20  // Normal constructor. -JM
21  // Pass ALCT, CLCT, and common parameters on to ALCT and CLCT processors.
22  static std::atomic<bool> config_dumped{false};
23 
24  mpc_block_me1a = tmbParams_.getParameter<unsigned int>("mpcBlockMe1a");
25  alct_trig_enable = tmbParams_.getParameter<unsigned int>("alctTrigEnable");
26  clct_trig_enable = tmbParams_.getParameter<unsigned int>("clctTrigEnable");
27  match_trig_enable = tmbParams_.getParameter<unsigned int>("matchTrigEnable");
28  match_trig_window_size = tmbParams_.getParameter<unsigned int>("matchTrigWindowSize");
29  tmb_l1a_window_size = // Common to CLCT and TMB
30  tmbParams_.getParameter<unsigned int>("tmbL1aWindowSize");
31 
32  // configuration handle for number of early time bins
33  early_tbins = tmbParams_.getParameter<int>("tmbEarlyTbins");
34 
35  // whether to not reuse CLCTs that were used by previous matching ALCTs
36  drop_used_clcts = tmbParams_.getParameter<bool>("tmbDropUsedClcts");
37 
38  // whether to readout only the earliest two LCTs in readout window
39  readout_earliest_2 = tmbParams_.getParameter<bool>("tmbReadoutEarliest2");
40 
41  match_earliest_clct_only_ = tmbParams_.getParameter<bool>("matchEarliestClctOnly");
42 
43  infoV = tmbParams_.getParameter<int>("verbosity");
44 
45  alctProc = std::make_unique<CSCAnodeLCTProcessor>(endcap, station, sector, subsector, chamber, conf);
46  clctProc = std::make_unique<CSCCathodeLCTProcessor>(endcap, station, sector, subsector, chamber, conf);
47 
48  // Check and print configuration parameters.
50  if (infoV > 0 && !config_dumped) {
52  config_dumped = true;
53  }
54 
56 
57  // get the preferred CLCT BX match array
58  preferred_bx_match_ = tmbParams_.getParameter<std::vector<int>>("preferredBxMatch");
59 
60  // sort CLCT only by bx or by quality+bending for ALCT-CLCT match
61  sort_clct_bx_ = tmbParams_.getParameter<bool>("sortClctBx");
62 
63  // quality assignment
64  qualityAssignment_ = std::make_unique<LCTQualityAssignment>(endcap, station, sector, subsector, chamber, conf);
65 
66  // quality control of stubs
67  qualityControl_ = std::make_unique<LCTQualityControl>(endcap, station, sector, subsector, chamber, conf);
68 
69  // shower-trigger source
70  showerSource_ = showerParams_.getParameter<std::vector<unsigned>>("source");
71 
72  unsigned csc_idx = CSCDetId::iChamberType(theStation, theRing) - 2;
74 
75  // shower readout window
79 
80  // enable the upgrade processors for ring 1 stations
81  if (runPhase2_ and theRing == 1) {
82  clctProc = std::make_unique<CSCUpgradeCathodeLCTProcessor>(endcap, station, sector, subsector, chamber, conf);
83  if (enableAlctPhase2_) {
84  alctProc = std::make_unique<CSCUpgradeAnodeLCTProcessor>(endcap, station, sector, subsector, chamber, conf);
85  }
86  }
87 
88  // set up helper class to check if ALCT and CLCT cross
89  ignoreAlctCrossClct_ = tmbParams_.getParameter<bool>("ignoreAlctCrossClct");
90  if (!ignoreAlctCrossClct_) {
91  cscOverlap_ = std::make_unique<CSCALCTCrossCLCT>(endcap, station, theRing, ignoreAlctCrossClct_, conf);
92  }
93 }
94 
96  // clear the processors
97  if (alctProc)
98  alctProc->clear();
99  if (clctProc)
100  clctProc->clear();
101 
102  // clear the ALCT and CLCT containers
103  alctV.clear();
104  clctV.clear();
105  lctV.clear();
106 
107  allLCTs_.clear();
108 
109  for (int bx = 0; bx < CSCConstants::MAX_LCT_TBINS; bx++) {
110  showers_[bx].clear();
111  }
112 }
113 
114 // Set configuration parameters obtained via EventSetup mechanism.
116  static std::atomic<bool> config_dumped{false};
117 
118  // Config. parameters for the TMB itself.
125 
126  // Config. paramteres for ALCT and CLCT processors.
127  alctProc->setConfigParameters(conf);
128  clctProc->setConfigParameters(conf);
129 
130  // Check and print configuration parameters.
132  if (!config_dumped) {
134  config_dumped = true;
135  }
138 }
139 
141 
143 
145 
147  // Step 1: Setup
148  clear();
149 
150  // Check for existing processors
151  if (!(alctProc && clctProc)) {
152  edm::LogError("CSCMotherboard|SetupError") << "+++ run() called for non-existing ALCT/CLCT processor! +++ \n";
153  return;
154  }
155 
156  // set geometry
157  alctProc->setCSCGeometry(cscGeometry_);
158  clctProc->setCSCGeometry(cscGeometry_);
159 
160  // set CCLUT parameters if necessary
161  if (runCCLUT_) {
162  clctProc->setESLookupTables(lookupTableCCLUT_);
163  }
164 
165  // Step 2: Run the processors
166  alctV = alctProc->run(wiredc); // run anodeLCT
167  clctV = clctProc->run(compdc); // run cathodeLCT
168 
169  // Step 2b: encode high multiplicity bits (independent of LCT construction)
171 
172  // if there are no ALCTs and no CLCTs, it does not make sense to run this TMB
173  if (alctV.empty() and clctV.empty())
174  return;
175 
176  // step 3: match the ALCTs to the CLCTs
177  matchALCTCLCT();
178 
179  // Step 4: Select at most 2 LCTs per BX
180  selectLCTs();
181 }
182 
184  // array to mask CLCTs
185  bool used_clct_mask[CSCConstants::MAX_CLCT_TBINS] = {false};
186 
187  // Step 3: ALCT-centric ALCT-to-CLCT matching
188  int bx_clct_matched = 0; // bx of last matched CLCT
189  for (int bx_alct = 0; bx_alct < CSCConstants::MAX_ALCT_TBINS; bx_alct++) {
190  // There should be at least one valid CLCT or ALCT for a
191  // correlated LCT to be formed. Decision on whether to reject
192  // non-complete LCTs (and if yes of which type) is made further
193  // upstream.
194  if (alctProc->getBestALCT(bx_alct).isValid()) {
195  // Look for CLCTs within the match-time window. The window is
196  // centered at the ALCT bx; therefore, we make an assumption
197  // that anode and cathode hits are perfectly synchronized. This
198  // is always true for MC, but only an approximation when the
199  // data is analyzed (which works fairly good as long as wide
200  // windows are used). To get rid of this assumption, one would
201  // need to access "full BX" words, which are not readily
202  // available.
203  bool is_matched = false;
204  // we can use single value to best CLCT but here use vector to keep the
205  // the future option to do multiple ALCT-CLCT matches wiht CLCT from different bx
206  std::vector<unsigned> clctBx_qualbend_match;
207  sortCLCTByQualBend(bx_alct, clctBx_qualbend_match);
208 
209  bool hasLocalShower = false;
210  for (unsigned ibx = 1; ibx <= match_trig_window_size / 2; ibx++)
211  hasLocalShower =
212  (hasLocalShower or clctProc->getLocalShowerFlag(bx_alct - CSCConstants::ALCT_CLCT_OFFSET - ibx));
213 
214  // loop on the preferred "delta BX" array
215  for (unsigned mbx = 0; mbx < match_trig_window_size; mbx++) {
216  // evaluate the preffered CLCT BX, taking into account that there is an offset in the simulation
217  //bx_clct_run2 would be overflow when bx_alct is small but it is okay
218  unsigned bx_clct_run2 = bx_alct + preferred_bx_match_[mbx] - CSCConstants::ALCT_CLCT_OFFSET;
219  unsigned bx_clct_qualbend = clctBx_qualbend_match[mbx];
220  unsigned bx_clct = (sort_clct_bx_ or not(hasLocalShower)) ? bx_clct_run2 : bx_clct_qualbend;
221  // check that the CLCT BX is valid
222  if (bx_clct >= CSCConstants::MAX_CLCT_TBINS)
223  continue;
224  // do not consider previously matched CLCTs
225  if (drop_used_clcts && used_clct_mask[bx_clct])
226  continue;
227  // only consider >=4 layer CLCTs for ALCT-CLCT type LCTs
228  // this condition is lowered to >=3 layers for CLCTs in the
229  // matchALCTCLCTGEM function
230  if (clctProc->getBestCLCT(bx_clct).getQuality() <= 3)
231  continue;
232  // a valid CLCT with sufficient layers!
233  if (clctProc->getBestCLCT(bx_clct).isValid()) {
234  if (infoV > 1)
235  LogTrace("CSCMotherboard") << "Successful ALCT-CLCT match: bx_alct = " << bx_alct
236  << "; bx_clct = " << bx_clct << "; mbx = " << mbx;
237  // now correlate the ALCT and CLCT into LCT.
238  // smaller mbx means more preferred!
239  correlateLCTs(alctProc->getBestALCT(bx_alct),
240  alctProc->getSecondALCT(bx_alct),
241  clctProc->getBestCLCT(bx_clct),
242  clctProc->getSecondCLCT(bx_clct),
243  allLCTs_(bx_alct, mbx, 0),
244  allLCTs_(bx_alct, mbx, 1),
246  // when the first LCT is valid, you can mask the matched CLCT and/or
247  // move on to the next ALCT if match_earliest_clct_only_ is set to true
248  if (allLCTs_(bx_alct, mbx, 0).isValid()) {
249  is_matched = true;
250  used_clct_mask[bx_clct] = true;
251  bx_clct_matched = bx_clct;
253  break;
254  }
255  }
256  }
257  // No CLCT within the match time interval found: report ALCT-only LCT
258  // (use dummy CLCTs).
259  if (!is_matched) {
260  if (infoV > 1)
261  LogTrace("CSCMotherboard") << "Unsuccessful ALCT-CLCT match (ALCT only): bx_alct = " << bx_alct
262  << " first ALCT " << alctProc->getBestALCT(bx_alct);
263  if (alct_trig_enable)
264  correlateLCTs(alctProc->getBestALCT(bx_alct),
265  alctProc->getSecondALCT(bx_alct),
266  clctProc->getBestCLCT(bx_alct),
267  clctProc->getSecondCLCT(bx_alct),
268  allLCTs_(bx_alct, 0, 0),
269  allLCTs_(bx_alct, 0, 1),
271  }
272  }
273  // No valid ALCTs; attempt to make CLCT-only LCT. Use only CLCTs
274  // which have zeroth chance to be matched at later cathode times.
275  // (I am not entirely sure this perfectly matches the firmware logic.)
276  // Use dummy ALCTs.
277  else {
278  int bx_clct = bx_alct - match_trig_window_size / 2;
279  if (bx_clct >= 0 && bx_clct > bx_clct_matched) {
280  if (clctProc->getBestCLCT(bx_clct).isValid() and clct_trig_enable) {
281  if (infoV > 1)
282  LogTrace("CSCMotherboard") << "Unsuccessful ALCT-CLCT match (CLCT only): bx_clct = " << bx_clct;
283  correlateLCTs(alctProc->getBestALCT(bx_alct),
284  alctProc->getSecondALCT(bx_alct),
285  clctProc->getBestCLCT(bx_clct),
286  clctProc->getSecondCLCT(bx_clct),
287  allLCTs_(bx_clct, 0, 0),
288  allLCTs_(bx_clct, 0, 1),
290  }
291  }
292  }
293  }
294 }
295 
296 // Returns vector of read-out correlated LCTs, if any. Starts with
297 // the vector of all found LCTs and selects the ones in the read-out
298 // time window.
299 std::vector<CSCCorrelatedLCTDigi> CSCMotherboard::readoutLCTs() const {
300  // temporary container for further selection
301  std::vector<CSCCorrelatedLCTDigi> tmpV;
302 
303  /*
304  LCTs in the BX window [early_tbin,...,late_tbin] are considered good for physics
305  The central LCT BX is time bin 8.
306  For tmb_l1a_window_size set to 7 (Run-1, Run-2), the window is [5, 6, 7, 8, 9, 10, 11]
307  For tmb_l1a_window_size set to 5 (Run-3), the window is [6, 7, 8, 9, 10]
308  For tmb_l1a_window_size set to 3 (Run-4?), the window is [ 7, 8, 9]
309  */
310  const unsigned delta_tbin = tmb_l1a_window_size / 2;
311  int early_tbin = CSCConstants::LCT_CENTRAL_BX - delta_tbin;
312  int late_tbin = CSCConstants::LCT_CENTRAL_BX + delta_tbin;
313  /*
314  Special case for an even-numbered time-window,
315  For instance tmb_l1a_window_size set to 6: [5, 6, 7, 8, 9, 10]
316  */
317  if (tmb_l1a_window_size % 2 == 0)
318  late_tbin = CSCConstants::LCT_CENTRAL_BX + delta_tbin - 1;
319  const int max_late_tbin = CSCConstants::MAX_LCT_TBINS - 1;
320 
321  // debugging messages when early_tbin or late_tbin has a suspicious value
322  if (early_tbin < 0) {
323  edm::LogWarning("CSCMotherboard|SuspiciousParameters")
324  << "Early time bin (early_tbin) smaller than minimum allowed, which is 0. set early_tbin to 0.";
325  early_tbin = 0;
326  }
327  if (late_tbin > max_late_tbin) {
328  edm::LogWarning("CSCMotherboard|SuspiciousParameters")
329  << "Late time bin (late_tbin) larger than maximum allowed, which is " << max_late_tbin
330  << ". set early_tbin to max allowed";
331  late_tbin = CSCConstants::MAX_LCT_TBINS - 1;
332  }
333 
334  // Start from the vector of all found correlated LCTs and select
335  // those within the LCT*L1A coincidence window.
336  int bx_readout = -1;
337  for (const auto& lct : lctV) {
338  // extra check on invalid LCTs
339  if (!lct.isValid()) {
340  continue;
341  }
342 
343  const int bx = lct.getBX();
344  // Skip LCTs found too early relative to L1Accept.
345  if (bx < early_tbin) {
346  if (infoV > 1)
347  LogDebug("CSCMotherboard") << " Do not report correlated LCT on key halfstrip " << lct.getStrip()
348  << " and key wire " << lct.getKeyWG() << ": found at bx " << bx
349  << ", whereas the earliest allowed bx is " << early_tbin;
350  continue;
351  }
352 
353  // Skip LCTs found too late relative to L1Accept.
354  if (bx > late_tbin) {
355  if (infoV > 1)
356  LogDebug("CSCMotherboard") << " Do not report correlated LCT on key halfstrip " << lct.getStrip()
357  << " and key wire " << lct.getKeyWG() << ": found at bx " << bx
358  << ", whereas the latest allowed bx is " << late_tbin;
359  continue;
360  }
361 
362  // Do not report LCTs found in ME1/A if mpc_block_me1a is set.
363  if (mpc_block_me1a and isME11_ and lct.getStrip() > CSCConstants::MAX_HALF_STRIP_ME1B) {
364  continue;
365  }
366 
367  // If (readout_earliest_2) take only LCTs in the earliest bx in the read-out window:
368  // in digi->raw step, LCTs have to be packed into the TMB header, and
369  // currently there is room just for two.
370  if (readout_earliest_2) {
371  if (bx_readout == -1 || bx == bx_readout) {
372  tmpV.push_back(lct);
373  if (bx_readout == -1)
374  bx_readout = bx;
375  }
376  }
377  // if readout_earliest_2 == false, save all LCTs
378  else {
379  tmpV.push_back(lct);
380  }
381  }
382 
383  // do a final check on the LCTs in readout
384  qualityControl_->checkMultiplicityBX(tmpV);
385  for (const auto& lct : tmpV) {
386  qualityControl_->checkValid(lct);
387  /*std::cout << "\n########################################## Emu LCT ##########################################\n" << std::endl;
388  std::cout << "Emu LCT: " << lct << std::endl;
389  std::cout << "\n########################################## THE END ##########################################\n" << std::endl;*/
390  }
391 
392  return tmpV;
393 }
394 
395 std::vector<CSCShowerDigi> CSCMotherboard::readoutShower() const {
396  unsigned minBXdiff = 2 * tmb_l1a_window_size; //impossible value
397  unsigned minBX = 0;
398  std::vector<CSCShowerDigi> showerOut;
399  for (unsigned bx = minbx_readout_; bx < maxbx_readout_; bx++) {
402  if (showers_[bx].isValid() and bx_diff < minBXdiff) {
403  minBXdiff = bx_diff;
404  minBX = bx;
405  }
406  }
407 
408  for (unsigned bx = minbx_readout_; bx < maxbx_readout_; bx++)
409  if (bx == minBX)
410  showerOut.push_back(showers_[bx]);
411  return showerOut;
412 }
413 
415  const CSCALCTDigi& sALCT,
416  const CSCCLCTDigi& bCLCT,
417  const CSCCLCTDigi& sCLCT,
418  CSCCorrelatedLCTDigi& bLCT,
419  CSCCorrelatedLCTDigi& sLCT,
420  int type) const {
421  CSCALCTDigi bestALCT = bALCT;
422  CSCALCTDigi secondALCT = sALCT;
423  CSCCLCTDigi bestCLCT = bCLCT;
424  CSCCLCTDigi secondCLCT = sCLCT;
425 
426  // extra check to make sure that both CLCTs have at least 4 layers
427  // for regular ALCT-CLCT type LCTs. A check was already done on the
428  // best CLCT, but not yet on the second best CLCT. The check on best
429  // CLCT is repeated for completeness
430  if (bestCLCT.getQuality() <= 3)
431  bestCLCT.clear();
432  if (secondCLCT.getQuality() <= 3)
433  secondCLCT.clear();
434 
435  // if the best ALCT/CLCT is valid, but the second ALCT/CLCT is not,
436  // the information is copied over
437  copyValidToInValidALCT(bestALCT, secondALCT);
438  copyValidToInValidCLCT(bestCLCT, secondCLCT);
439 
440  // ALCT-only LCTs
441  const bool bestCase1(alct_trig_enable and bestALCT.isValid());
442  // CLCT-only LCTs
443  const bool bestCase2(clct_trig_enable and bestCLCT.isValid());
444  /*
445  Normal case: ALCT-CLCT matched LCTs. We require ALCT and CLCT to be valid.
446  Optionally, we can check if the ALCT cross the CLCT. This check will always return true
447  for a valid ALCT-CLCT pair in non-ME1/1 chambers. For ME1/1 chambers, it returns true,
448  only when the ALCT-CLCT pair crosses and when the parameter "checkAlctCrossClct" is set to True.
449  It is recommended to keep "checkAlctCrossClct" set to False, so that the EMTF receives
450  all information, even if it's unphysical.
451  */
452  const bool bestCase3(match_trig_enable and bestALCT.isValid() and bestCLCT.isValid() and
453  doesALCTCrossCLCT(bestALCT, bestCLCT));
454 
455  // at least one of the cases must be valid
456  if (bestCase1 or bestCase2 or bestCase3) {
457  constructLCTs(bestALCT, bestCLCT, type, 1, bLCT);
458  }
459 
460  // ALCT-only LCTs
461  const bool secondCase1(alct_trig_enable and secondALCT.isValid());
462  // CLCT-only LCTs
463  const bool secondCase2(clct_trig_enable and secondCLCT.isValid());
464  /*
465  Normal case: ALCT-CLCT matched LCTs. We require ALCT and CLCT to be valid.
466  Optionally, we can check if the ALCT cross the CLCT. This check will always return true
467  for a valid ALCT-CLCT pair in non-ME1/1 chambers. For ME1/1 chambers, it returns true,
468  only when the ALCT-CLCT pair crosses and when the parameter "checkAlctCrossClct" is set to True.
469  It is recommended to keep "checkAlctCrossClct" set to False, so that the EMTF receives
470  all information, even if it's unphysical.
471  */
472  const bool secondCase3(match_trig_enable and secondALCT.isValid() and secondCLCT.isValid() and
473  doesALCTCrossCLCT(secondALCT, secondCLCT));
474 
475  // at least one component must be different in order to consider the secondLCT
476  if ((secondALCT != bestALCT) or (secondCLCT != bestCLCT)) {
477  // at least one of the cases must be valid
478  if (secondCase1 or secondCase2 or secondCase3)
479  constructLCTs(secondALCT, secondCLCT, type, 2, sLCT);
480  }
481 }
482 
483 // copy the valid ALCT/CLCT information to the valid ALCT
485  if (bestALCT.isValid() and !secondALCT.isValid())
486  secondALCT = bestALCT;
487 }
488 
489 // copy the valid CLCT information to the valid CLCT
491  if (bestCLCT.isValid() and !secondCLCT.isValid())
492  secondCLCT = bestCLCT;
493 }
494 
495 bool CSCMotherboard::doesALCTCrossCLCT(const CSCALCTDigi& alct, const CSCCLCTDigi& clct) const {
497  return true;
498  else
499  return cscOverlap_->doesALCTCrossCLCT(alct, clct);
500 }
501 
502 // This method calculates all the TMB words and then passes them to the
503 // constructor of correlated LCTs.
505  const CSCALCTDigi& aLCT, const CSCCLCTDigi& cLCT, int type, int trknmb, CSCCorrelatedLCTDigi& thisLCT) const {
506  thisLCT.setValid(true);
507  thisLCT.setType(type);
508  // make sure to shift the ALCT BX from 8 to 3 and the CLCT BX from 8 to 7!
509  thisLCT.setALCT(getBXShiftedALCT(aLCT));
510  thisLCT.setCLCT(getBXShiftedCLCT(cLCT));
511  thisLCT.setPattern(encodePattern(cLCT.getPattern()));
512  thisLCT.setMPCLink(0);
513  thisLCT.setBX0(0);
514  thisLCT.setSyncErr(0);
515  thisLCT.setCSCID(theTrigChamber);
516  thisLCT.setTrknmb(trknmb);
517  thisLCT.setWireGroup(aLCT.getKeyWG());
518  thisLCT.setStrip(cLCT.getKeyStrip());
519  thisLCT.setBend(cLCT.getBend());
520  // Bunch crossing: get it from cathode LCT if anode LCT is not there.
521  int bx = aLCT.isValid() ? aLCT.getBX() : cLCT.getBX();
522  thisLCT.setBX(bx);
523  thisLCT.setQuality(qualityAssignment_->findQuality(aLCT, cLCT));
524  if (runCCLUT_) {
525  thisLCT.setRun3(true);
526  // 4-bit slope value derived with the CCLUT algorithm
527  thisLCT.setSlope(cLCT.getSlope());
528  thisLCT.setQuartStripBit(cLCT.getQuartStripBit());
529  thisLCT.setEighthStripBit(cLCT.getEighthStripBit());
530  thisLCT.setRun3Pattern(cLCT.getRun3Pattern());
531  }
532 }
533 
534 // CLCT pattern number: encodes the pattern number itself
535 unsigned int CSCMotherboard::encodePattern(const int ptn) const {
536  const int kPatternBitWidth = 4;
537 
538  // In the TMB07 firmware, LCT pattern is just a 4-bit CLCT pattern.
539  unsigned int pattern = (abs(ptn) & ((1 << kPatternBitWidth) - 1));
540 
541  return pattern;
542 }
543 
545  // in each of the LCT time bins
546  for (int bx = 0; bx < CSCConstants::MAX_LCT_TBINS; bx++) {
547  unsigned nLCTs = 0;
548 
549  std::vector<CSCCorrelatedLCTDigi> tempV;
550  // check each of the preferred combinations
551  for (unsigned int mbx = 0; mbx < match_trig_window_size; mbx++) {
552  // select at most 2
553  for (int i = 0; i < CSCConstants::MAX_LCTS_PER_CSC; i++) {
554  if (allLCTs_(bx, mbx, i).isValid() and nLCTs < 2) {
555  tempV.push_back(allLCTs_(bx, mbx, i));
556  ++nLCTs;
557  }
558  }
559  }
560  // store the best 2
561  for (const auto& lct : tempV) {
562  lctV.push_back(lct);
563  }
564  }
565 
566  // Show the pre-selected LCTs. They're not final yet. Some selection is done in the readoutLCTs function
567  if (infoV > 0) {
568  for (const auto& lct : lctV) {
569  LogDebug("CSCMotherboard") << "Selected LCT" << lct;
570  }
571  }
572 }
573 
574 void CSCMotherboard::sortCLCTByQualBend(int bx_alct, std::vector<unsigned>& clctBxVector) {
575  //find clct bx range in [centerbx-window_size/2, center_bx+window_size/2]
576  //Then sort CLCT based quality+bend within the match window
577  //if two CLCTs from different BX has same qual+bend, the in-time one has higher priority
578  clctBxVector.clear();
579  int clctQualBendArray[CSCConstants::MAX_CLCT_TBINS + 1] = {0};
580  for (unsigned mbx = 0; mbx < match_trig_window_size; mbx++) {
581  unsigned bx_clct = bx_alct + preferred_bx_match_[mbx] - CSCConstants::ALCT_CLCT_OFFSET;
582  int tempQualBend = 0;
583  if (bx_clct >= CSCConstants::MAX_CLCT_TBINS)
584  continue;
585  if (!clctProc->getBestCLCT(bx_clct).isValid()) {
586  clctQualBendArray[bx_clct] = tempQualBend;
587  continue;
588  }
589  CSCCLCTDigi bestCLCT = clctProc->getBestCLCT(bx_clct);
590  //for run2 pattern, ignore direction and use &0xe
591  //for run3, slope=0 is straighest pattern
592  int clctBend = bestCLCT.isRun3() ? (16 - bestCLCT.getSlope()) : (bestCLCT.getPattern() & 0xe);
593  //shift quality to left for 4 bits
594  int clctQualBend = clctBend | (bestCLCT.getQuality() << 5);
595  clctQualBendArray[bx_clct] = clctQualBend;
596  if (clctBxVector.empty())
597  clctBxVector.push_back(bx_clct);
598  else {
599  for (auto it = clctBxVector.begin(); it != clctBxVector.end(); it++)
600  if (clctQualBend > clctQualBendArray[*it]) { //insert the Bx with better clct
601  clctBxVector.insert(it, bx_clct);
602  break;
603  }
604  }
605  }
606  //fill rest of vector with MAX_CLCT_TBINS
607  for (unsigned bx = clctBxVector.size(); bx < match_trig_window_size; bx++)
608  clctBxVector.push_back(CSCConstants::MAX_CLCT_TBINS);
609 }
610 
612  // Make sure that the parameter values are within the allowed range.
613 
614  // Max expected values.
615  static const unsigned int max_mpc_block_me1a = 1 << 1;
616  static const unsigned int max_alct_trig_enable = 1 << 1;
617  static const unsigned int max_clct_trig_enable = 1 << 1;
618  static const unsigned int max_match_trig_enable = 1 << 1;
619  static const unsigned int max_match_trig_window_size = 1 << 4;
620  static const unsigned int max_tmb_l1a_window_size = 1 << 4;
621 
622  // Checks.
623  CSCBaseboard::checkConfigParameters(mpc_block_me1a, max_mpc_block_me1a, def_mpc_block_me1a, "mpc_block_me1a");
624  CSCBaseboard::checkConfigParameters(alct_trig_enable, max_alct_trig_enable, def_alct_trig_enable, "alct_trig_enable");
625  CSCBaseboard::checkConfigParameters(clct_trig_enable, max_clct_trig_enable, def_clct_trig_enable, "clct_trig_enable");
627  match_trig_enable, max_match_trig_enable, def_match_trig_enable, "match_trig_enable");
629  match_trig_window_size, max_match_trig_window_size, def_match_trig_window_size, "match_trig_window_size");
631  tmb_l1a_window_size, max_tmb_l1a_window_size, def_tmb_l1a_window_size, "tmb_l1a_window_size");
633 }
634 
636  std::ostringstream strm;
637  strm << "\n";
638  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
639  strm << "+ TMB configuration parameters: +\n";
640  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
641  strm << " mpc_block_me1a [block/not block triggers which come from ME1/A] = " << mpc_block_me1a << "\n";
642  strm << " alct_trig_enable [allow ALCT-only triggers] = " << alct_trig_enable << "\n";
643  strm << " clct_trig_enable [allow CLCT-only triggers] = " << clct_trig_enable << "\n";
644  strm << " match_trig_enable [allow matched ALCT-CLCT triggers] = " << match_trig_enable << "\n";
645  strm << " match_trig_window_size [ALCT-CLCT match window width, in 25 ns] = " << match_trig_window_size << "\n";
646  strm << " tmb_l1a_window_size [L1Accept window width, in 25 ns bins] = " << tmb_l1a_window_size << "\n";
647  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
648  LogDebug("CSCMotherboard") << strm.str();
649 }
650 
652  CSCALCTDigi aLCT_shifted = aLCT;
653  aLCT_shifted.setBX(aLCT_shifted.getBX() - (CSCConstants::LCT_CENTRAL_BX - CSCConstants::ALCT_CENTRAL_BX));
654  return aLCT_shifted;
655 }
656 
658  CSCCLCTDigi cLCT_shifted = cLCT;
659  cLCT_shifted.setBX(cLCT_shifted.getBX() - CSCConstants::ALCT_CLCT_OFFSET);
660  return cLCT_shifted;
661 }
662 
663 void CSCMotherboard::matchShowers(CSCShowerDigi* anode_showers, CSCShowerDigi* cathode_showers, bool andlogic) {
664  CSCShowerDigi ashower, cshower;
665  bool used_cshower_mask[CSCConstants::MAX_CLCT_TBINS] = {false};
666  for (unsigned bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
667  ashower = anode_showers[bx];
668  cshower = CSCShowerDigi(); //use empty shower digi to initialize cshower
669  if (ashower.isValid()) {
670  for (unsigned mbx = 0; mbx < match_trig_window_size; mbx++) {
672  //check bx range [0, CSCConstants::MAX_LCT_TBINS]
673  if (cbx < 0 || cbx >= CSCConstants::MAX_CLCT_TBINS)
674  continue;
675  if (cathode_showers[cbx].isValid() and not used_cshower_mask[cbx]) {
676  cshower = cathode_showers[cbx];
677  used_cshower_mask[cbx] = true;
678  break;
679  }
680  }
681  } else
682  cshower = cathode_showers[bx]; //if anode shower is not valid, use the cshower from this bx
683 
684  //matched HMT, with and/or logic
685  unsigned matchHMT = 0;
686  if (andlogic) {
687  if (ashower.isTightInTime() and cshower.isTightInTime())
688  matchHMT = 3;
689  else if (ashower.isNominalInTime() and cshower.isNominalInTime())
690  matchHMT = 2;
691  else if (ashower.isLooseInTime() and cshower.isLooseInTime())
692  matchHMT = 1;
693  } else {
694  if (ashower.isTightInTime() or cshower.isTightInTime())
695  matchHMT = 3;
696  else if (ashower.isNominalInTime() or cshower.isNominalInTime())
697  matchHMT = 2;
698  else if (ashower.isLooseInTime() or cshower.isLooseInTime())
699  matchHMT = 1;
700  }
701  //LCTShower with showerType = 3
702  showers_[bx] = CSCShowerDigi(matchHMT & 3,
703  false,
704  ashower.getCSCID(),
705  bx,
706  CSCShowerDigi::ShowerType::kLCTShower,
707  ashower.getWireNHits(),
708  cshower.getComparatorNHits());
709  }
710 }
711 
713  // get the high multiplicity
714  // for anode this reflects what is already in the anode CSCShowerDigi object
717  auto cshowers_v = clctProc->getAllShower();
718  auto ashowers_v = alctProc->getAllShower();
719 
720  std::copy(cshowers_v.begin(), cshowers_v.end(), cathode_showers);
721  std::copy(ashowers_v.begin(), ashowers_v.end(), anode_showers);
722 
723  // set the value according to source
724  switch (thisShowerSource_) {
725  case 0:
726  std::copy(std::begin(cathode_showers), std::end(cathode_showers), std::begin(showers_));
727  break;
728  case 1:
729  std::copy(std::begin(anode_showers), std::end(anode_showers), std::begin(showers_));
730  break;
731  case 2:
732  matchShowers(anode_showers, cathode_showers, false);
733  break;
734  case 3:
735  matchShowers(anode_showers, cathode_showers, true);
736  break;
737  default:
738  std::copy(std::begin(anode_showers), std::end(anode_showers), std::begin(showers_));
739  break;
740  };
741 }
bool isValid() const
check ALCT validity (1 - valid ALCT)
Definition: CSCALCTDigi.h:40
LCTContainer allLCTs_
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
unsigned thisShowerSource_
virtual std::vector< CSCCorrelatedLCTDigi > readoutLCTs() const
void setPattern(const uint16_t p)
set pattern
void setALCT(const CSCALCTDigi &alct)
uint16_t getBX() const
return BX - five low bits of BXN counter tagged by the ALCT
Definition: CSCALCTDigi.h:73
const CSCL1TPLookupTableME11ILT * lookupTableME11ILT_
unsigned maxbx_readout_
std::vector< CSCCLCTDigi > clctV
unsigned int clct_trig_enable
void setESLookupTables(const CSCL1TPLookupTableCCLUT *conf)
unsigned int encodePattern(const int clctPattern) const
const bool isValid(const Frame &aFrame, const FrameQuality &aQuality, const uint16_t aExpectedPos)
unsigned int match_trig_window_size
bool enableAlctPhase2_
Definition: CSCBaseboard.h:94
void setSlope(const uint16_t slope)
set the slope
static const unsigned int def_alct_trig_enable
void checkConfigParameters(unsigned int &var, const unsigned int var_max, const unsigned int var_def, const std::string &var_str)
uint16_t getQuality() const
return quality of a pattern (number of layers hit!)
Definition: CSCCLCTDigi.h:56
bool isValid() const
data
unsigned int tmbMpcBlockMe1a() const
uint16_t getComparatorNHits() const
Definition: CSCShowerDigi.h:55
CSCShowerDigi showers_[CSCConstants::MAX_LCT_TBINS]
uint16_t getKeyStrip(const uint16_t n=2) const
Definition: CSCCLCTDigi.cc:107
static const unsigned int def_mpc_block_me1a
void setQuartStripBit(const bool quartStripBit)
set single quart strip bit
bool getEighthStripBit() const
get single eighth strip bit
Definition: CSCCLCTDigi.h:114
void setEighthStripBit(const bool eighthStripBit)
set single eighth strip bit
std::vector< CSCCorrelatedLCTDigi > lctV
void matchShowers(CSCShowerDigi *anode_showers, CSCShowerDigi *cathode_showers, bool andlogic)
void setBend(const uint16_t b)
set bend
std::unique_ptr< CSCCathodeLCTProcessor > clctProc
static const unsigned int def_clct_trig_enable
Log< level::Error, false > LogError
void setValid(const uint16_t v)
set valid
unsigned short iChamberType() const
Definition: CSCDetId.h:96
assert(be >=bs)
unsigned int tmbTmbL1aWindowSize() const
bool isRun3() const
Distinguish Run-1/2 from Run-3.
Definition: CSCCLCTDigi.h:195
#define LogTrace(id)
bool isLooseInTime() const
void copyValidToInValidALCT(CSCALCTDigi &, CSCALCTDigi &) const
CSCCLCTDigi getBXShiftedCLCT(const CSCCLCTDigi &) const
void setMatchTrigWindowSize(unsigned trig_window_size)
Definition: LCTContainer.h:41
unsigned int mpc_block_me1a
void setMPCLink(const uint16_t &link)
Set mpc link number after MPC sorting.
unsigned minbx_readout_
bool getQuartStripBit() const
get single quart strip bit
Definition: CSCCLCTDigi.h:108
const unsigned theTrigChamber
Definition: CSCBaseboard.h:46
void setWireGroup(const uint16_t wiregroup)
set wiregroup number
void correlateLCTs(const CSCALCTDigi &bestALCT, const CSCALCTDigi &secondALCT, const CSCCLCTDigi &bestCLCT, const CSCCLCTDigi &secondCLCT, CSCCorrelatedLCTDigi &bLCT, CSCCorrelatedLCTDigi &sLCT, int type) const
bool isTightInTime() const
unsigned int tmbMatchTrigWindowSize() const
std::vector< int > preferred_bx_match_
bool match_earliest_clct_only_
CSCMotherboard(unsigned endcap, unsigned station, unsigned sector, unsigned subsector, unsigned chamber, const edm::ParameterSet &conf)
std::unique_ptr< CSCALCTCrossCLCT > cscOverlap_
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
std::vector< CSCALCTDigi > alctV
void dumpConfigParams() const
uint16_t getKeyWG() const
return key wire group
Definition: CSCALCTDigi.h:67
uint16_t getBend() const
Definition: CSCCLCTDigi.h:93
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
unsigned int tmb_l1a_window_size
void checkConfigParameters()
unsigned int match_trig_enable
void copyValidToInValidCLCT(CSCCLCTDigi &, CSCCLCTDigi &) const
void setRun3Pattern(const uint16_t pattern)
set Run-3 pattern
void setBX0(const uint16_t b)
set bx0
bool isValid() const
check CLCT validity (1 - valid CLCT)
Definition: CSCCLCTDigi.h:50
std::vector< unsigned > showerSource_
bool isNominalInTime() const
void setBX(const uint16_t BX)
set BX
Definition: CSCALCTDigi.h:76
const CSCGeometry * cscGeometry_
Definition: CSCBaseboard.h:71
edm::ParameterSet tmbParams_
Definition: CSCBaseboard.h:78
void setCSCID(const uint16_t c)
set cscID
void run(const CSCWireDigiCollection *wiredc, const CSCComparatorDigiCollection *compdc)
uint16_t getCSCID() const
Definition: CSCShowerDigi.h:52
void setRun3(const bool isRun3)
bool doesALCTCrossCLCT(const CSCALCTDigi &, const CSCCLCTDigi &) const
void sortCLCTByQualBend(int alct_bx, std::vector< unsigned > &clctBxVector)
void setBX(const uint16_t b)
set bx
const unsigned theStation
Definition: CSCBaseboard.h:43
static const unsigned int def_match_trig_window_size
unsigned int tmbMatchTrigEnable() const
uint16_t getBX() const
return BX
Definition: CSCCLCTDigi.h:123
uint16_t getPattern() const
return pattern
Definition: CSCCLCTDigi.h:62
unsigned int alct_trig_enable
const CSCL1TPLookupTableME21ILT * lookupTableME21ILT_
void setBX(const uint16_t bx)
set bx
Definition: CSCCLCTDigi.h:129
std::unique_ptr< CSCAnodeLCTProcessor > alctProc
uint16_t getWireNHits() const
Definition: CSCShowerDigi.h:54
const CSCL1TPLookupTableCCLUT * lookupTableCCLUT_
uint16_t getSlope() const
return the slope
Definition: CSCCLCTDigi.h:74
unsigned int tmbClctTrigEnable() const
void setStrip(const uint16_t s)
set strip
void encodeHighMultiplicityBits()
unsigned int tmbAlctTrigEnable() const
uint16_t getRun3Pattern() const
return pattern
Definition: CSCCLCTDigi.h:68
void clear()
clear this CLCT
Definition: CSCCLCTDigi.cc:73
std::vector< CSCShowerDigi > readoutShower() const
void clear()
clear this Shower
unsigned theRing
Definition: CSCBaseboard.h:48
void setQuality(const uint16_t q)
set quality code
CSCALCTDigi getBXShiftedALCT(const CSCALCTDigi &) const
Log< level::Warning, false > LogWarning
edm::ParameterSet showerParams_
Definition: CSCBaseboard.h:87
void setConfigParameters(const CSCDBL1TPParameters *conf)
std::unique_ptr< LCTQualityControl > qualityControl_
void setTrknmb(const uint16_t number)
Set track number (1,2) after sorting LCTs.
void setCLCT(const CSCCLCTDigi &clct)
static const unsigned int def_match_trig_enable
void setSyncErr(const uint16_t s)
set syncErr
#define LogDebug(id)
std::unique_ptr< LCTQualityAssignment > qualityAssignment_
void constructLCTs(const CSCALCTDigi &aLCT, const CSCCLCTDigi &cLCT, int type, int trknmb, CSCCorrelatedLCTDigi &lct) const