CMS 3D CMS Logo

CSCMotherboard.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // Class: CSCMotherboard
4 //
5 // Description:
6 // When the Trigger MotherBoard is instantiated it instantiates an ALCT
7 // and CLCT board. The Motherboard takes up to two LCTs from each anode
8 // and cathode LCT card and combines them into a single Correlated LCT.
9 // The output is up to two Correlated LCTs.
10 //
11 // It can be run in either a test mode, where the arguments are a collection
12 // of wire times and arrays of halfstrip and distrip times, or
13 // for general use, with with wire digi and comparator digi collections as
14 // arguments. In the latter mode, the wire & strip info is passed on the
15 // LCTProcessors, where it is decoded and converted into a convenient form.
16 // After running the anode and cathode LCTProcessors, TMB correlates the
17 // anode and cathode LCTs. At present, it simply matches the best CLCT
18 // with the best ALCT; perhaps a better algorithm will be determined in
19 // the future. The MotherBoard then determines a few more numbers (such as
20 // quality and pattern) from the ALCT and CLCT information, and constructs
21 // two correlated LCTs.
22 //
23 // correlateLCTs() may need to be modified to take into account a
24 // possibility of ALCTs and CLCTs arriving at different bx times.
25 //
26 // Author List: Benn Tannenbaum 28 August 1999 benn@physics.ucla.edu
27 // Based on code by Nick Wisniewski (nw@its.caltech.edu)
28 // and a framework by Darin Acosta (acosta@phys.ufl.edu).
29 //
30 //
31 // Modifications: Numerous later improvements by Jason Mumford and
32 // Slava Valuev (see cvs in ORCA).
33 // Porting from ORCA by S. Valuev (Slava.Valuev@cern.ch), May 2006.
34 //
35 //-----------------------------------------------------------------------------
36 
40 #include <iostream>
41 
42 // Default values of configuration parameters.
43 const unsigned int CSCMotherboard::def_mpc_block_me1a = 1;
44 const unsigned int CSCMotherboard::def_alct_trig_enable = 0;
45 const unsigned int CSCMotherboard::def_clct_trig_enable = 0;
46 const unsigned int CSCMotherboard::def_match_trig_enable = 1;
47 const unsigned int CSCMotherboard::def_match_trig_window_size = 7;
48 const unsigned int CSCMotherboard::def_tmb_l1a_window_size = 7;
49 
51  unsigned sector, unsigned subsector,
52  unsigned chamber,
53  const edm::ParameterSet& conf) :
54  theEndcap(endcap), theStation(station), theSector(sector),
55  theSubsector(subsector), theTrigChamber(chamber) {
56 
58 
59  // Normal constructor. -JM
60  // Pass ALCT, CLCT, and common parameters on to ALCT and CLCT processors.
61  static std::atomic<bool> config_dumped{false};
62 
63  // Some configuration parameters and some details of the emulator
64  // algorithms depend on whether we want to emulate the trigger logic
65  // used in TB/MTCC or its idealized version (the latter was used in MC
66  // studies since early ORCA days until (and including) CMSSW_2_1_X).
67  edm::ParameterSet commonParams =
68  conf.getParameter<edm::ParameterSet>("commonParam");
69  isMTCC = commonParams.getParameter<bool>("isMTCC");
70 
71  // Switch for a new (2007) version of the TMB firmware.
72  isTMB07 = commonParams.getParameter<bool>("isTMB07");
73 
74  // is it (non-upgrade algorithm) run along with upgrade one?
75  isSLHC = commonParams.getParameter<bool>("isSLHC");
76 
77  // Choose the appropriate set of configuration parameters depending on
78  // isTMB07 and isMTCC flags.
79  // Starting with CMSSW_3_1_X, these settings are overwritten by the
80  // ones delivered by the EventSetup mechanism.
81  edm::ParameterSet alctParams, clctParams;
82  if (isTMB07) {
83  alctParams = conf.getParameter<edm::ParameterSet>("alctParam07");
84  clctParams = conf.getParameter<edm::ParameterSet>("clctParam07");
85  }
86  else if (isMTCC) {
87  alctParams = conf.getParameter<edm::ParameterSet>("alctParamMTCC");
88  clctParams = conf.getParameter<edm::ParameterSet>("clctParamMTCC");
89  }
90  else {
91  alctParams = conf.getParameter<edm::ParameterSet>("alctParamOldMC");
92  clctParams = conf.getParameter<edm::ParameterSet>("clctParamOldMC");
93  }
94 
95  // Motherboard parameters:
96  edm::ParameterSet tmbParams = conf.getParameter<edm::ParameterSet>("tmbParam");
97  const edm::ParameterSet me11tmbGemParams(conf.existsAs<edm::ParameterSet>("me11tmbSLHCGEM")?
98  conf.getParameter<edm::ParameterSet>("me11tmbSLHCGEM"):edm::ParameterSet());
99  const edm::ParameterSet me21tmbGemParams(conf.existsAs<edm::ParameterSet>("me21tmbSLHCGEM")?
100  conf.getParameter<edm::ParameterSet>("me21tmbSLHCGEM"):edm::ParameterSet());
101 
102  const bool runME11ILT(commonParams.existsAs<bool>("runME11ILT")?commonParams.getParameter<bool>("runME11ILT"):false);
103  const bool runME21ILT(commonParams.existsAs<bool>("runME21ILT")?commonParams.getParameter<bool>("runME21ILT"):false);
104 
105  // run upgrade TMBs for all MEX/1 stations
106  if (isSLHC and theRing == 1){
107  if (theStation == 1) {
108  tmbParams = conf.getParameter<edm::ParameterSet>("tmbSLHC");
109  alctParams = conf.getParameter<edm::ParameterSet>("alctSLHC");
110  clctParams = conf.getParameter<edm::ParameterSet>("clctSLHC");
111  if (runME11ILT) {
112  tmbParams = me11tmbGemParams;
113  }
114  }
115  else if (theStation == 2 and runME21ILT) {
116  tmbParams = me21tmbGemParams;
117  alctParams = conf.getParameter<edm::ParameterSet>("alctSLHCME21");
118  clctParams = conf.getParameter<edm::ParameterSet>("clctSLHCME21");
119  }
120  }
121 
122  mpc_block_me1a = tmbParams.getParameter<unsigned int>("mpcBlockMe1a");
123  alct_trig_enable = tmbParams.getParameter<unsigned int>("alctTrigEnable");
124  clct_trig_enable = tmbParams.getParameter<unsigned int>("clctTrigEnable");
125  match_trig_enable = tmbParams.getParameter<unsigned int>("matchTrigEnable");
127  tmbParams.getParameter<unsigned int>("matchTrigWindowSize");
128  tmb_l1a_window_size = // Common to CLCT and TMB
129  tmbParams.getParameter<unsigned int>("tmbL1aWindowSize");
130 
131  lct_central_bx = 6;
132 
133  // configuration handle for number of early time bins
134  early_tbins = tmbParams.getParameter<int>("tmbEarlyTbins");
135 
136  // whether to not reuse ALCTs that were used by previous matching CLCTs
137  drop_used_alcts = tmbParams.getParameter<bool>("tmbDropUsedAlcts");
138 
139  // whether to readout only the earliest two LCTs in readout window
140  readout_earliest_2 = tmbParams.getParameter<bool>("tmbReadoutEarliest2");
141 
142  infoV = tmbParams.getParameter<int>("verbosity");
143 
144  alct.reset( new CSCAnodeLCTProcessor(endcap, station, sector, subsector, chamber, alctParams, commonParams) );
145  clct.reset( new CSCCathodeLCTProcessor(endcap, station, sector, subsector, chamber, clctParams, commonParams, tmbParams) );
146 
147  //if (theStation==1 && CSCTriggerNumbering::ringFromTriggerLabels(theStation, theTrigChamber)==2) infoV = 3;
148 
149  // Check and print configuration parameters.
151  if (infoV > 0 && !config_dumped) {
153  config_dumped = true;
154  }
155 
156  // test to make sure that what goes into a correlated LCT is also what
157  // comes back out.
158  // testLCT();
159 }
160 
162  theEndcap(1), theStation(1), theSector(1),
164  // Constructor used only for testing. -JM
165  static std::atomic<bool> config_dumped{false};
166 
167  isMTCC = false;
168  isTMB07 = true;
169 
170  early_tbins = 4;
171 
172  alct.reset( new CSCAnodeLCTProcessor() );
173  clct.reset( new CSCCathodeLCTProcessor() );
180 
181  infoV = 2;
182 
183  // Check and print configuration parameters.
185  if (infoV > 0 && !config_dumped) {
187  config_dumped = true;
188  }
189 }
190 
192  if (alct) alct->clear();
193  if (clct) clct->clear();
194  for (int bx = 0; bx < CSCConstants::MAX_LCT_TBINS; bx++) {
195  firstLCT[bx].clear();
196  secondLCT[bx].clear();
197  }
198 }
199 
200 // Set configuration parameters obtained via EventSetup mechanism.
202  static std::atomic<bool> config_dumped{false};
203 
204  // Config. parameters for the TMB itself.
211 
212  // Config. paramteres for ALCT and CLCT processors.
213  alct->setConfigParameters(conf);
214  clct->setConfigParameters(conf);
215 
216  // Check and print configuration parameters.
218  if (!config_dumped) {
220  config_dumped = true;
221  }
222 }
223 
225  // Make sure that the parameter values are within the allowed range.
226 
227  // Max expected values.
228  static const unsigned int max_mpc_block_me1a = 1 << 1;
229  static const unsigned int max_alct_trig_enable = 1 << 1;
230  static const unsigned int max_clct_trig_enable = 1 << 1;
231  static const unsigned int max_match_trig_enable = 1 << 1;
232  static const unsigned int max_match_trig_window_size = 1 << 4;
233  static const unsigned int max_tmb_l1a_window_size = 1 << 4;
234 
235  // Checks.
236  if (mpc_block_me1a >= max_mpc_block_me1a) {
237  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
238  << "+++ Value of mpc_block_me1a, " << mpc_block_me1a
239  << ", exceeds max allowed, " << max_mpc_block_me1a-1 << " +++\n"
240  << "+++ Try to proceed with the default value, mpc_block_me1a="
241  << def_mpc_block_me1a << " +++\n";
243  }
244  if (alct_trig_enable >= max_alct_trig_enable) {
245  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
246  << "+++ Value of alct_trig_enable, " << alct_trig_enable
247  << ", exceeds max allowed, " << max_alct_trig_enable-1 << " +++\n"
248  << "+++ Try to proceed with the default value, alct_trig_enable="
249  << def_alct_trig_enable << " +++\n";
251  }
252  if (clct_trig_enable >= max_clct_trig_enable) {
253  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
254  << "+++ Value of clct_trig_enable, " << clct_trig_enable
255  << ", exceeds max allowed, " << max_clct_trig_enable-1 << " +++\n"
256  << "+++ Try to proceed with the default value, clct_trig_enable="
257  << def_clct_trig_enable << " +++\n";
259  }
260  if (match_trig_enable >= max_match_trig_enable) {
261  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
262  << "+++ Value of match_trig_enable, " << match_trig_enable
263  << ", exceeds max allowed, " << max_match_trig_enable-1 << " +++\n"
264  << "+++ Try to proceed with the default value, match_trig_enable="
265  << def_match_trig_enable << " +++\n";
267  }
268  if (match_trig_window_size >= max_match_trig_window_size) {
269  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
270  << "+++ Value of match_trig_window_size, " << match_trig_window_size
271  << ", exceeds max allowed, " << max_match_trig_window_size-1 << " +++\n"
272  << "+++ Try to proceed with the default value, match_trig_window_size="
273  << def_match_trig_window_size << " +++\n";
275  }
276  if (tmb_l1a_window_size >= max_tmb_l1a_window_size) {
277  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
278  << "+++ Value of tmb_l1a_window_size, " << tmb_l1a_window_size
279  << ", exceeds max allowed, " << max_tmb_l1a_window_size-1 << " +++\n"
280  << "+++ Try to proceed with the default value, tmb_l1a_window_size="
281  << def_tmb_l1a_window_size << " +++\n";
283  }
284 }
285 
287  const std::vector<int> w_times[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES],
288  const std::vector<int> hs_times[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS],
289  const std::vector<int> ds_times[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
290  // Debug version. -JM
291  clear();
292 
293  // set geometry
294  alct->setCSCGeometry(csc_g);
295  clct->setCSCGeometry(csc_g);
296 
297  alct->run(w_times); // run anode LCT
298  clct->run(hs_times, ds_times); // run cathodeLCT
299 
300  int bx_alct_matched = 0;
301  for (int bx_clct = 0; bx_clct < CSCConstants::MAX_CLCT_TBINS;
302  bx_clct++) {
303  if (clct->bestCLCT[bx_clct].isValid()) {
304  bool is_matched = false;
305  int bx_alct_start = bx_clct - match_trig_window_size/2;
306  int bx_alct_stop = bx_clct + match_trig_window_size/2;
307  // Empirical correction to match 2009 collision data (firmware change?)
308  if (!isSLHC) bx_alct_stop += match_trig_window_size%2;
309 
310  for (int bx_alct = bx_alct_start; bx_alct <= bx_alct_stop; bx_alct++) {
311  if (bx_alct < 0 || bx_alct >= CSCConstants::MAX_ALCT_TBINS)
312  continue;
313  if (alct->bestALCT[bx_alct].isValid()) {
314  correlateLCTs(alct->bestALCT[bx_alct], alct->secondALCT[bx_alct],
315  clct->bestCLCT[bx_clct], clct->secondCLCT[bx_clct]);
316  is_matched = true;
317  bx_alct_matched = bx_alct;
318  break;
319  }
320  }
321  // No ALCT within the match time interval found: report CLCT-only LCT
322  // (use dummy ALCTs).
323  if (!is_matched) {
324  correlateLCTs(alct->bestALCT[bx_clct], alct->secondALCT[bx_clct],
325  clct->bestCLCT[bx_clct], clct->secondCLCT[bx_clct]);
326  }
327  }
328  // No valid CLCTs; attempt to make ALCT-only LCT (use dummy CLCTs).
329  else {
330  int bx_alct = bx_clct - match_trig_window_size/2;
331  if (bx_alct >= 0 && bx_alct > bx_alct_matched) {
332  if (alct->bestALCT[bx_alct].isValid()) {
333  correlateLCTs(alct->bestALCT[bx_alct], alct->secondALCT[bx_alct],
334  clct->bestCLCT[bx_clct], clct->secondCLCT[bx_clct]);
335  }
336  }
337  }
338  }
339 }
340 
341 void
343  const CSCComparatorDigiCollection* compdc) {
344  clear();
345 
346  // set geometry
347  alct->setCSCGeometry(csc_g);
348  clct->setCSCGeometry(csc_g);
349 
350  if (alct && clct) {
351  {
352  std::vector<CSCALCTDigi> alctV = alct->run(wiredc); // run anodeLCT
353  }
354  {
355  std::vector<CSCCLCTDigi> clctV = clct->run(compdc); // run cathodeLCT
356  }
357 
358  int used_alct_mask[20];
359  for (int a=0;a<20;++a) used_alct_mask[a]=0;
360 
361  int bx_alct_matched = 0; // bx of last matched ALCT
362  for (int bx_clct = 0; bx_clct < CSCConstants::MAX_CLCT_TBINS;
363  bx_clct++) {
364  // There should be at least one valid ALCT or CLCT for a
365  // correlated LCT to be formed. Decision on whether to reject
366  // non-complete LCTs (and if yes of which type) is made further
367  // upstream.
368  if (clct->bestCLCT[bx_clct].isValid()) {
369  // Look for ALCTs within the match-time window. The window is
370  // centered at the CLCT bx; therefore, we make an assumption
371  // that anode and cathode hits are perfectly synchronized. This
372  // is always true for MC, but only an approximation when the
373  // data is analyzed (which works fairly good as long as wide
374  // windows are used). To get rid of this assumption, one would
375  // need to access "full BX" words, which are not readily
376  // available.
377  bool is_matched = false;
378  int bx_alct_start = bx_clct - match_trig_window_size/2;
379  int bx_alct_stop = bx_clct + match_trig_window_size/2;
380  // Empirical correction to match 2009 collision data (firmware change?)
381  // (but don't do it for SLHC case, assume it would not be there)
382  if (!isSLHC) bx_alct_stop += match_trig_window_size%2;
383 
384  for (int bx_alct = bx_alct_start; bx_alct <= bx_alct_stop; bx_alct++) {
385  if (bx_alct < 0 || bx_alct >= CSCConstants::MAX_ALCT_TBINS)
386  continue;
387  // default: do not reuse ALCTs that were used with previous CLCTs
388  if (drop_used_alcts && used_alct_mask[bx_alct]) continue;
389  if (alct->bestALCT[bx_alct].isValid()) {
390  if (infoV > 1) LogTrace("CSCMotherboard")
391  << "Successful ALCT-CLCT match: bx_clct = " << bx_clct
392  << "; match window: [" << bx_alct_start << "; " << bx_alct_stop
393  << "]; bx_alct = " << bx_alct;
394  correlateLCTs(alct->bestALCT[bx_alct], alct->secondALCT[bx_alct],
395  clct->bestCLCT[bx_clct], clct->secondCLCT[bx_clct]);
396  used_alct_mask[bx_alct] += 1;
397  is_matched = true;
398  bx_alct_matched = bx_alct;
399  break;
400  }
401  }
402  // No ALCT within the match time interval found: report CLCT-only LCT
403  // (use dummy ALCTs).
404  if (!is_matched) {
405  if (infoV > 1) LogTrace("CSCMotherboard")
406  << "Unsuccessful ALCT-CLCT match (CLCT only): bx_clct = "
407  << bx_clct << "; match window: [" << bx_alct_start
408  << "; " << bx_alct_stop << "]";
409  correlateLCTs(alct->bestALCT[bx_clct], alct->secondALCT[bx_clct],
410  clct->bestCLCT[bx_clct], clct->secondCLCT[bx_clct]);
411  }
412  }
413  // No valid CLCTs; attempt to make ALCT-only LCT. Use only ALCTs
414  // which have zeroth chance to be matched at later cathode times.
415  // (I am not entirely sure this perfectly matches the firmware logic.)
416  // Use dummy CLCTs.
417  else {
418  int bx_alct = bx_clct - match_trig_window_size/2;
419  if (bx_alct >= 0 && bx_alct > bx_alct_matched) {
420  if (alct->bestALCT[bx_alct].isValid()) {
421  if (infoV > 1) LogTrace("CSCMotherboard")
422  << "Unsuccessful ALCT-CLCT match (ALCT only): bx_alct = "
423  << bx_alct;
424  correlateLCTs(alct->bestALCT[bx_alct], alct->secondALCT[bx_alct],
425  clct->bestCLCT[bx_clct], clct->secondCLCT[bx_clct]);
426  }
427  }
428  }
429  }
430 
431  if (infoV > 0) {
432  for (int bx = 0; bx < CSCConstants::MAX_LCT_TBINS; bx++) {
433  if (firstLCT[bx].isValid())
434  LogDebug("CSCMotherboard") << firstLCT[bx];
435  if (secondLCT[bx].isValid())
436  LogDebug("CSCMotherboard") << secondLCT[bx];
437  }
438  }
439  }
440  else {
441  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
442  << "+++ run() called for non-existing ALCT/CLCT processor! +++ \n";
443  }
444 }
445 
446 // Returns vector of read-out correlated LCTs, if any. Starts with
447 // the vector of all found LCTs and selects the ones in the read-out
448 // time window.
449 std::vector<CSCCorrelatedLCTDigi> CSCMotherboard::readoutLCTs() {
450  std::vector<CSCCorrelatedLCTDigi> tmpV;
451 
452  // The start time of the L1A*LCT coincidence window should be related
453  // to the fifo_pretrig parameter, but I am not completely sure how.
454  // Just choose it such that the window is centered at bx=7. This may
455  // need further tweaking if the value of tmb_l1a_window_size changes.
456  //static int early_tbins = 4;
457 
458  // Empirical correction to match 2009 collision data (firmware change?)
459  int lct_bins = tmb_l1a_window_size;
460  int late_tbins = early_tbins + lct_bins;
461 
462  int ifois = 0;
463  if (ifois == 0) {
464  if (infoV >= 0 && early_tbins < 0) {
465  edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
466  << "+++ early_tbins = " << early_tbins
467  << "; in-time LCTs are not getting read-out!!! +++" << "\n";
468  }
469 
470  if (late_tbins > CSCConstants::MAX_LCT_TBINS-1) {
471  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
472  << "+++ Allowed range of time bins, [0-" << late_tbins
473  << "] exceeds max allowed, " << CSCConstants::MAX_LCT_TBINS-1 << " +++\n"
474  << "+++ Set late_tbins to max allowed +++\n";
475  late_tbins = CSCConstants::MAX_LCT_TBINS-1;
476  }
477  ifois = 1;
478  }
479 
480  // Start from the vector of all found correlated LCTs and select
481  // those within the LCT*L1A coincidence window.
482  int bx_readout = -1;
483  std::vector<CSCCorrelatedLCTDigi> all_lcts = getLCTs();
484  for (std::vector <CSCCorrelatedLCTDigi>::const_iterator plct =
485  all_lcts.begin(); plct != all_lcts.end(); plct++) {
486  if (!plct->isValid()) continue;
487 
488  int bx = (*plct).getBX();
489  // Skip LCTs found too early relative to L1Accept.
490  if (bx <= early_tbins) {
491  if (infoV > 1) LogDebug("CSCMotherboard")
492  << " Do not report correlated LCT on key halfstrip "
493  << plct->getStrip() << " and key wire " << plct->getKeyWG()
494  << ": found at bx " << bx << ", whereas the earliest allowed bx is "
495  << early_tbins+1;
496  continue;
497  }
498 
499  // Skip LCTs found too late relative to L1Accept.
500  if (bx > late_tbins) {
501  if (infoV > 1) LogDebug("CSCMotherboard")
502  << " Do not report correlated LCT on key halfstrip "
503  << plct->getStrip() << " and key wire " << plct->getKeyWG()
504  << ": found at bx " << bx << ", whereas the latest allowed bx is "
505  << late_tbins;
506  continue;
507  }
508 
509  // If (readout_earliest_2) take only LCTs in the earliest bx in the read-out window:
510  // in digi->raw step, LCTs have to be packed into the TMB header, and
511  // currently there is room just for two.
512  if (readout_earliest_2) {
513  if (bx_readout == -1 || bx == bx_readout) {
514  tmpV.push_back(*plct);
515  if (bx_readout == -1) bx_readout = bx;
516  }
517  }
518  // if readout_earliest_2 == false, save all LCTs
519  else tmpV.push_back(*plct);
520  }
521  return tmpV;
522 }
523 
524 // Returns vector of all found correlated LCTs, if any.
525 std::vector<CSCCorrelatedLCTDigi> CSCMotherboard::getLCTs() {
526  std::vector<CSCCorrelatedLCTDigi> tmpV;
527 
528  bool me11 = (theStation == 1 &&
530  theTrigChamber)==1);
531 
532  // Do not report LCTs found in ME1/A if mpc_block_me1/a is set.
533  for (int bx = 0; bx < CSCConstants::MAX_LCT_TBINS; bx++) {
534  if (firstLCT[bx].isValid())
535  if (!mpc_block_me1a || (!me11 || firstLCT[bx].getStrip() <= 127))
536  tmpV.push_back(firstLCT[bx]);
537  if (secondLCT[bx].isValid())
538  if (!mpc_block_me1a || (!me11 || secondLCT[bx].getStrip() <= 127))
539  tmpV.push_back(secondLCT[bx]);
540  }
541  return tmpV;
542 }
543 
545  CSCALCTDigi& secondALCT,
546  CSCCLCTDigi& bestCLCT,
547  CSCCLCTDigi& secondCLCT) {
548 
549  bool anodeBestValid = bestALCT.isValid();
550  bool anodeSecondValid = secondALCT.isValid();
551  bool cathodeBestValid = bestCLCT.isValid();
552  bool cathodeSecondValid = secondCLCT.isValid();
553 
554  if (anodeBestValid && !anodeSecondValid) secondALCT = bestALCT;
555  if (!anodeBestValid && anodeSecondValid) bestALCT = secondALCT;
556  if (cathodeBestValid && !cathodeSecondValid) secondCLCT = bestCLCT;
557  if (!cathodeBestValid && cathodeSecondValid) bestCLCT = secondCLCT;
558 
559  // ALCT-CLCT matching conditions are defined by "trig_enable" configuration
560  // parameters.
561  if ((alct_trig_enable && bestALCT.isValid()) ||
562  (clct_trig_enable && bestCLCT.isValid()) ||
563  (match_trig_enable && bestALCT.isValid() && bestCLCT.isValid())) {
565  int bx = lct.getBX();
566  if (bx >= 0 && bx < CSCConstants::MAX_LCT_TBINS) {
567  firstLCT[bx] = lct;
568  firstLCT[bx].setTrknmb(1);
569  }
570  else {
571  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeLCT")
572  << "+++ Bx of first LCT candidate, " << bx
573  << ", is not within the allowed range, [0-" << CSCConstants::MAX_LCT_TBINS-1
574  << "); skipping it... +++\n";
575  }
576  }
577 
578  if (((secondALCT != bestALCT) || (secondCLCT != bestCLCT)) &&
579  ((alct_trig_enable && secondALCT.isValid()) ||
580  (clct_trig_enable && secondCLCT.isValid()) ||
581  (match_trig_enable && secondALCT.isValid() && secondCLCT.isValid()))) {
583  int bx = lct.getBX();
584  if (bx >= 0 && bx < CSCConstants::MAX_LCT_TBINS) {
585  secondLCT[bx] = lct;
586  secondLCT[bx].setTrknmb(2);
587  }
588  else {
589  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeLCT")
590  << "+++ Bx of second LCT candidate, " << bx
591  << ", is not within the allowed range, [0-" << CSCConstants::MAX_LCT_TBINS-1
592  << "); skipping it... +++\n";
593  }
594  }
595 }
596 
597 // This method calculates all the TMB words and then passes them to the
598 // constructor of correlated LCTs.
600  const CSCCLCTDigi& cLCT,
601  int type) const {
602  // CLCT pattern number
603  unsigned int pattern = encodePattern(cLCT.getPattern(), cLCT.getStripType());
604 
605  // LCT quality number
606  unsigned int quality = findQuality(aLCT, cLCT);
607 
608  // Bunch crossing: get it from cathode LCT if anode LCT is not there.
609  int bx = aLCT.isValid() ? aLCT.getBX() : cLCT.getBX();
610 
611  // construct correlated LCT; temporarily assign track number of 0.
612  int trknmb = 0;
613  CSCCorrelatedLCTDigi thisLCT(trknmb, 1, quality, aLCT.getKeyWG(),
614  cLCT.getKeyStrip(), pattern, cLCT.getBend(),
615  bx, 0, 0, 0, theTrigChamber);
616  thisLCT.setType(type);
617  thisLCT.setALCT(aLCT);
618  thisLCT.setCLCT(cLCT);
619  return thisLCT;
620 }
621 
622 // CLCT pattern number: encodes the pattern number itself and
623 // whether the pattern consists of half-strips or di-strips.
624 unsigned int CSCMotherboard::encodePattern(const int ptn,
625  const int stripType) const {
626  const int kPatternBitWidth = 4;
627  unsigned int pattern;
628 
629  if (!isTMB07) {
630  // Cathode pattern number is a kPatternBitWidth-1 bit word.
631  pattern = (abs(ptn) & ((1<<(kPatternBitWidth-1))-1));
632 
633  // The pattern has the MSB (4th bit in the default version) set if it
634  // consists of half-strips.
635  if (stripType) {
636  pattern = pattern | (1<<(kPatternBitWidth-1));
637  }
638  }
639  else {
640  // In the TMB07 firmware, LCT pattern is just a 4-bit CLCT pattern.
641  pattern = (abs(ptn) & ((1<<kPatternBitWidth)-1));
642  }
643 
644  return pattern;
645 }
646 
647 // 4-bit LCT quality number. Definition can be found in
648 // http://www.phys.ufl.edu/~acosta/tb/tmb_quality.txt. Made by TMB lookup
649 // tables and used for MPC sorting.
650 unsigned int CSCMotherboard::findQuality(const CSCALCTDigi& aLCT,
651  const CSCCLCTDigi& cLCT) const {
652  unsigned int quality = 0;
653 
654  if (!isTMB07) {
655  bool isDistrip = (cLCT.getStripType() == 0);
656 
657  if (aLCT.isValid() && !(cLCT.isValid())) { // no CLCT
658  if (aLCT.getAccelerator()) {quality = 1;}
659  else {quality = 3;}
660  }
661  else if (!(aLCT.isValid()) && cLCT.isValid()) { // no ALCT
662  if (isDistrip) {quality = 4;}
663  else {quality = 5;}
664  }
665  else if (aLCT.isValid() && cLCT.isValid()) { // both ALCT and CLCT
666  if (aLCT.getAccelerator()) {quality = 2;} // accelerator muon
667  else { // collision muon
668  // CLCT quality is, in fact, the number of layers hit, so subtract 3
669  // to get quality analogous to ALCT one.
670  int sumQual = aLCT.getQuality() + (cLCT.getQuality()-3);
671  if (sumQual < 1 || sumQual > 6) {
672  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongValues")
673  << "+++ findQuality: sumQual = " << sumQual << "+++ \n";
674  }
675  if (isDistrip) { // distrip pattern
676  if (sumQual == 2) {quality = 6;}
677  else if (sumQual == 3) {quality = 7;}
678  else if (sumQual == 4) {quality = 8;}
679  else if (sumQual == 5) {quality = 9;}
680  else if (sumQual == 6) {quality = 10;}
681  }
682  else { // halfstrip pattern
683  if (sumQual == 2) {quality = 11;}
684  else if (sumQual == 3) {quality = 12;}
685  else if (sumQual == 4) {quality = 13;}
686  else if (sumQual == 5) {quality = 14;}
687  else if (sumQual == 6) {quality = 15;}
688  }
689  }
690  }
691  }
692 #ifdef OLD
693  else {
694  // Temporary definition, used until July 2008.
695  // First if statement is fictitious, just to help the CSC TF emulator
696  // handle such cases (one needs to make sure they will be accounted for
697  // in the new quality definition.
698  if (!(aLCT.isValid()) || !(cLCT.isValid())) {
699  if (aLCT.isValid() && !(cLCT.isValid())) quality = 1; // no CLCT
700  else if (!(aLCT.isValid()) && cLCT.isValid()) quality = 2; // no ALCT
701  else quality = 0; // both absent; should never happen.
702  }
703  else {
704  // Sum of ALCT and CLCT quality bits. CLCT quality is, in fact, the
705  // number of layers hit, so subtract 3 to put it to the same footing as
706  // the ALCT quality.
707  int sumQual = aLCT.getQuality() + (cLCT.getQuality()-3);
708  if (sumQual < 1 || sumQual > 6) {
709  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongValues")
710  << "+++ findQuality: Unexpected sumQual = " << sumQual << "+++\n";
711  }
712 
713  // LCT quality is basically the sum of ALCT and CLCT qualities, but split
714  // in two groups depending on the CLCT pattern id (higher quality for
715  // straighter patterns).
716  int offset = 0;
717  if (cLCT.getPattern() <= 7) offset = 4;
718  else offset = 9;
719  quality = offset + sumQual;
720  }
721  }
722 #endif
723  else {
724  // 2008 definition.
725  if (!(aLCT.isValid()) || !(cLCT.isValid())) {
726  if (aLCT.isValid() && !(cLCT.isValid())) quality = 1; // no CLCT
727  else if (!(aLCT.isValid()) && cLCT.isValid()) quality = 2; // no ALCT
728  else quality = 0; // both absent; should never happen.
729  }
730  else {
731  int pattern = cLCT.getPattern();
732  if (pattern == 1) quality = 3; // layer-trigger in CLCT
733  else {
734  // CLCT quality is the number of layers hit minus 3.
735  // CLCT quality is the number of layers hit.
736  bool a4 = (aLCT.getQuality() >= 1);
737  bool c4 = (cLCT.getQuality() >= 4);
738  // quality = 4; "reserved for low-quality muons in future"
739  if (!a4 && !c4) quality = 5; // marginal anode and cathode
740  else if ( a4 && !c4) quality = 6; // HQ anode, but marginal cathode
741  else if (!a4 && c4) quality = 7; // HQ cathode, but marginal anode
742  else if ( a4 && c4) {
743  if (aLCT.getAccelerator()) quality = 8; // HQ muon, but accel ALCT
744  else {
745  // quality = 9; "reserved for HQ muons with future patterns
746  // quality = 10; "reserved for HQ muons with future patterns
747  if (pattern == 2 || pattern == 3) quality = 11;
748  else if (pattern == 4 || pattern == 5) quality = 12;
749  else if (pattern == 6 || pattern == 7) quality = 13;
750  else if (pattern == 8 || pattern == 9) quality = 14;
751  else if (pattern == 10) quality = 15;
752  else {
753  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongValues")
754  << "+++ findQuality: Unexpected CLCT pattern id = "
755  << pattern << "+++\n";
756  }
757  }
758  }
759  }
760  }
761  }
762  return quality;
763 }
764 
766  unsigned int lctPattern, lctQuality;
767  for (int pattern = 0; pattern < 8; pattern++) {
768  for (int bend = 0; bend < 2; bend++) {
769  for (int cfeb = 0; cfeb < 5; cfeb++) {
770  for (int strip = 0; strip < 32; strip++) {
771  for (int bx = 0; bx < 7; bx++) {
772  for (int stripType = 0; stripType < 2; stripType++) {
773  for (int quality = 3; quality < 7; quality++) {
774  CSCCLCTDigi cLCT(1, quality, pattern, stripType, bend,
775  strip, cfeb, bx);
776  lctPattern = encodePattern(cLCT.getPattern(),
777  cLCT.getStripType());
778  for (int aQuality = 0; aQuality < 4; aQuality++) {
779  for (int wireGroup = 0; wireGroup < 120; wireGroup++) {
780  for (int abx = 0; abx < 7; abx++) {
781  CSCALCTDigi aLCT(1, aQuality, 0, 1, wireGroup, abx);
782  lctQuality = findQuality(aLCT, cLCT);
784  thisLCT(0, 1, lctQuality, aLCT.getKeyWG(),
785  cLCT.getKeyStrip(), lctPattern, cLCT.getBend(),
786  aLCT.getBX());
787  if (lctPattern != static_cast<unsigned int>(thisLCT.getPattern()) )
788  LogTrace("CSCMotherboard")
789  << "pattern mismatch: " << lctPattern
790  << " " << thisLCT.getPattern();
791  if (bend != thisLCT.getBend())
792  LogTrace("CSCMotherboard")
793  << "bend mismatch: " << bend
794  << " " << thisLCT.getBend();
795  int key_strip = 32*cfeb + strip;
796  if (key_strip != thisLCT.getStrip())
797  LogTrace("CSCMotherboard")
798  << "strip mismatch: " << key_strip
799  << " " << thisLCT.getStrip();
800  if (wireGroup != thisLCT.getKeyWG())
801  LogTrace("CSCMotherboard")
802  << "wire group mismatch: " << wireGroup
803  << " " << thisLCT.getKeyWG();
804  if (abx != thisLCT.getBX())
805  LogTrace("CSCMotherboard")
806  << "bx mismatch: " << abx << " " << thisLCT.getBX();
807  if (lctQuality != static_cast<unsigned int>(thisLCT.getQuality()))
808  LogTrace("CSCMotherboard")
809  << "quality mismatch: " << lctQuality
810  << " " << thisLCT.getQuality();
811  }
812  }
813  }
814  }
815  }
816  }
817  }
818  }
819  }
820  }
821 }
822 
824  std::ostringstream strm;
825  strm << "\n";
826  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
827  strm << "+ TMB configuration parameters: +\n";
828  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
829  strm << " mpc_block_me1a [block/not block triggers which come from ME1/A] = "
830  << mpc_block_me1a << "\n";
831  strm << " alct_trig_enable [allow ALCT-only triggers] = "
832  << alct_trig_enable << "\n";
833  strm << " clct_trig_enable [allow CLCT-only triggers] = "
834  << clct_trig_enable << "\n";
835  strm << " match_trig_enable [allow matched ALCT-CLCT triggers] = "
836  << match_trig_enable << "\n";
837  strm << " match_trig_window_size [ALCT-CLCT match window width, in 25 ns] = "
838  << match_trig_window_size << "\n";
839  strm << " tmb_l1a_window_size [L1Accept window width, in 25 ns bins] = "
840  << tmb_l1a_window_size << "\n";
841  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
842  LogDebug("CSCMotherboard") << strm.str();
843 }
#define LogDebug(id)
int getQuality() const
return quality of a pattern (number of layers hit!)
Definition: CSCCLCTDigi.h:33
type
Definition: HCALResponse.h:21
const unsigned theSector
T getParameter(std::string const &) const
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:186
unsigned int clct_trig_enable
std::vector< CSCCorrelatedLCTDigi > getLCTs()
std::vector< CSCCorrelatedLCTDigi > readoutLCTs()
unsigned int match_trig_window_size
const unsigned theTrigChamber
static const unsigned int def_alct_trig_enable
bool isValid() const
check ALCT validity (1 - valid ALCT)
Definition: CSCALCTDigi.h:30
const unsigned theEndcap
static const unsigned int def_mpc_block_me1a
unsigned int tmbClctTrigEnable() const
CSCCorrelatedLCTDigi secondLCT[CSCConstants::MAX_LCT_TBINS]
static const unsigned int def_clct_trig_enable
const CSCGeometry * csc_g
static int ringFromTriggerLabels(int station, int triggerCSCID)
int getStripType() const
return striptype
Definition: CSCCLCTDigi.h:39
int getBend() const
return bend
Definition: CSCCLCTDigi.h:42
unsigned int mpc_block_me1a
unsigned int tmbTmbL1aWindowSize() const
const unsigned theStation
unsigned int tmbMatchTrigWindowSize() const
static const unsigned int def_tmb_l1a_window_size
const unsigned theSubsector
void run(const std::vector< int > w_time[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES], const std::vector< int > hs_times[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const std::vector< int > ds_times[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
int getBX() const
return BX
Definition: CSCCLCTDigi.h:51
unsigned int tmbAlctTrigEnable() const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
unsigned int tmb_l1a_window_size
void checkConfigParameters()
bool isValid() const
check CLCT validity (1 - valid CLCT)
Definition: CSCCLCTDigi.h:30
unsigned int match_trig_enable
#define LogTrace(id)
int getBX() const
return BX
int getBX() const
return BX - five low bits of BXN counter tagged by the ALCT
Definition: CSCALCTDigi.h:48
unsigned int tmbMpcBlockMe1a() const
int getQuality() const
return quality of a pattern
Definition: CSCALCTDigi.h:33
int getAccelerator() const
Definition: CSCALCTDigi.h:37
unsigned int findQuality(const CSCALCTDigi &aLCT, const CSCCLCTDigi &cLCT) const
int getPattern() const
return pattern
Definition: CSCCLCTDigi.h:36
static const unsigned int def_match_trig_window_size
unsigned int encodePattern(const int ptn, const int highPt) const
unsigned int alct_trig_enable
std::unique_ptr< CSCAnodeLCTProcessor > alct
double a
Definition: hdecay.h:121
void dumpConfigParams() const
std::unique_ptr< CSCCathodeLCTProcessor > clct
int getKeyStrip() const
Definition: CSCCLCTDigi.h:65
void setConfigParameters(const CSCDBL1TPParameters *conf)
CSCCorrelatedLCTDigi constructLCTs(const CSCALCTDigi &aLCT, const CSCCLCTDigi &cLCT, int type) const
void setTrknmb(const uint16_t number)
Set track number (1,2) after sorting LCTs.
void correlateLCTs(CSCALCTDigi &bestALCT, CSCALCTDigi &secondALCT, CSCCLCTDigi &bestCLCT, CSCCLCTDigi &secondCLCT)
int getKeyWG() const
return key wire group
Definition: CSCALCTDigi.h:45
static const unsigned int def_match_trig_enable
unsigned int tmbMatchTrigEnable() const
CSCCorrelatedLCTDigi firstLCT[CSCConstants::MAX_LCT_TBINS]