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