CMS 3D CMS Logo

CSCAnodeLCTProcessor.cc
Go to the documentation of this file.
2 #include <set>
3 
4 // Default values of configuration parameters.
5 const unsigned int CSCAnodeLCTProcessor::def_fifo_tbins = 16;
6 const unsigned int CSCAnodeLCTProcessor::def_fifo_pretrig = 10;
7 const unsigned int CSCAnodeLCTProcessor::def_drift_delay = 2;
12 const unsigned int CSCAnodeLCTProcessor::def_trig_mode = 2; // 3?
13 const unsigned int CSCAnodeLCTProcessor::def_accel_mode = 0; // 1?
14 const unsigned int CSCAnodeLCTProcessor::def_l1a_window_width = 7; // 5?
15 
16 //----------------
17 // Constructors --
18 //----------------
19 
21  unsigned station,
22  unsigned sector,
23  unsigned subsector,
24  unsigned chamber,
25  const edm::ParameterSet& conf)
26  : CSCBaseboard(endcap, station, sector, subsector, chamber, conf) {
27  static std::atomic<bool> config_dumped{false};
28 
29  // ALCT configuration parameters.
30  fifo_tbins = alctParams_.getParameter<unsigned int>("alctFifoTbins");
31  fifo_pretrig = alctParams_.getParameter<unsigned int>("alctFifoPretrig");
32  drift_delay = alctParams_.getParameter<unsigned int>("alctDriftDelay");
33  nplanes_hit_pretrig = alctParams_.getParameter<unsigned int>("alctNplanesHitPretrig");
34  nplanes_hit_pattern = alctParams_.getParameter<unsigned int>("alctNplanesHitPattern");
35  nplanes_hit_accel_pretrig = alctParams_.getParameter<unsigned int>("alctNplanesHitAccelPretrig");
36  nplanes_hit_accel_pattern = alctParams_.getParameter<unsigned int>("alctNplanesHitAccelPattern");
37  trig_mode = alctParams_.getParameter<unsigned int>("alctTrigMode");
38  accel_mode = alctParams_.getParameter<unsigned int>("alctAccelMode");
39  l1a_window_width = alctParams_.getParameter<unsigned int>("alctL1aWindowWidth");
40 
41  hit_persist = alctParams_.getParameter<unsigned int>("alctHitPersist");
42 
43  // Verbosity level, set to 0 (no print) by default.
44  infoV = alctParams_.getParameter<int>("verbosity");
45 
46  // separate handle for early time bins
47  early_tbins = alctParams_.getParameter<int>("alctEarlyTbins");
48  if (early_tbins < 0)
49  early_tbins = fifo_pretrig - CSCConstants::ALCT_EMUL_TIME_OFFSET;
50 
51  // delta BX time depth for ghostCancellationLogic
52  ghost_cancellation_bx_depth = alctParams_.getParameter<int>("alctGhostCancellationBxDepth");
53 
54  // whether to consider ALCT candidates' qualities while doing ghostCancellationLogic on +-1 wire groups
55  ghost_cancellation_side_quality = alctParams_.getParameter<bool>("alctGhostCancellationSideQuality");
56 
57  // deadtime clocks after pretrigger (extra in addition to drift_delay)
58  pretrig_extra_deadtime = alctParams_.getParameter<unsigned int>("alctPretrigDeadtime");
59 
60  // whether to use narrow pattern mask for the rings close to the beam
61  narrow_mask_r1 = alctParams_.getParameter<bool>("alctNarrowMaskForR1");
62 
63  // Check and print configuration parameters.
65  if ((infoV > 0 || (isSLHC_)) && !config_dumped) {
66  //std::cout<<"**** ALCT constructor parameters dump ****"<<std::endl;
68  config_dumped = true;
69  }
70 
71  numWireGroups = 0; // Will be set later.
72  MESelection = (theStation < 3) ? 0 : 1;
73 
74  // whether to calculate bx as corrected_bx instead of pretrigger one
75  use_corrected_bx = false;
76  if (isSLHC_) {
77  use_corrected_bx = alctParams_.getParameter<bool>("alctUseCorrectedBx");
78  }
79 
80  // Load appropriate pattern mask.
82 }
83 
85  // Used for debugging. -JM
86  static std::atomic<bool> config_dumped{false};
87 
88  // ALCT parameters.
90  infoV = 2;
91 
92  early_tbins = 4;
93 
94  // Check and print configuration parameters.
96  if (!config_dumped) {
97  //std::cout<<"**** ALCT default constructor parameters dump ****"<<std::endl;
99  config_dumped = true;
100  }
101 
103  MESelection = (theStation < 3) ? 0 : 1;
104 
105  // Load pattern mask.
106  loadPatternMask();
107 }
108 
110  // Load appropriate pattern mask.
111  for (int i_patt = 0; i_patt < CSCConstants::NUM_ALCT_PATTERNS; i_patt++) {
112  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++) {
113  pattern_mask[i_patt][i_wire] = CSCPatternBank::alct_pattern_mask_open[i_patt][i_wire];
114  if (narrow_mask_r1 && (theRing == 1 || theRing == 4))
115  pattern_mask[i_patt][i_wire] = CSCPatternBank::alct_pattern_mask_r1[i_patt][i_wire];
116  }
117  }
118 }
119 
121  // Set default values for configuration parameters.
132 }
133 
134 // Set configuration parameters obtained via EventSetup mechanism.
136  static std::atomic<bool> config_dumped{false};
137 
138  fifo_tbins = conf->alctFifoTbins();
139  fifo_pretrig = conf->alctFifoPretrig();
140  drift_delay = conf->alctDriftDelay();
145  trig_mode = conf->alctTrigMode();
146  accel_mode = conf->alctAccelMode();
148 
149  // Check and print configuration parameters.
151  if (!config_dumped) {
152  //std::cout<<"**** ALCT setConfigParam parameters dump ****"<<std::endl;
154  config_dumped = true;
155  }
156 }
157 
159  // Make sure that the parameter values are within the allowed range.
160 
161  // Max expected values.
162  static const unsigned int max_fifo_tbins = 1 << 5;
163  static const unsigned int max_fifo_pretrig = 1 << 5;
164  static const unsigned int max_drift_delay = 1 << 2;
165  static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
166  static const unsigned int max_nplanes_hit_pattern = 1 << 3;
167  static const unsigned int max_nplanes_hit_accel_pretrig = 1 << 3;
168  static const unsigned int max_nplanes_hit_accel_pattern = 1 << 3;
169  static const unsigned int max_trig_mode = 1 << 2;
170  static const unsigned int max_accel_mode = 1 << 2;
171  static const unsigned int max_l1a_window_width = CSCConstants::MAX_ALCT_TBINS; // 4 bits
172 
173  // Checks.
174  if (fifo_tbins >= max_fifo_tbins) {
175  if (infoV >= 0)
176  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
177  << "+++ Value of fifo_tbins, " << fifo_tbins << ", exceeds max allowed, " << max_fifo_tbins - 1 << " +++\n"
178  << "+++ Try to proceed with the default value, fifo_tbins=" << def_fifo_tbins << " +++\n";
180  }
181  if (fifo_pretrig >= max_fifo_pretrig) {
182  if (infoV >= 0)
183  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
184  << "+++ Value of fifo_pretrig, " << fifo_pretrig << ", exceeds max allowed, " << max_fifo_pretrig - 1
185  << " +++\n"
186  << "+++ Try to proceed with the default value, fifo_pretrig=" << def_fifo_pretrig << " +++\n";
188  }
189  if (drift_delay >= max_drift_delay) {
190  if (infoV >= 0)
191  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
192  << "+++ Value of drift_delay, " << drift_delay << ", exceeds max allowed, " << max_drift_delay - 1 << " +++\n"
193  << "+++ Try to proceed with the default value, drift_delay=" << def_drift_delay << " +++\n";
195  }
196  if (nplanes_hit_pretrig >= max_nplanes_hit_pretrig) {
197  if (infoV >= 0)
198  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
199  << "+++ Value of nplanes_hit_pretrig, " << nplanes_hit_pretrig << ", exceeds max allowed, "
200  << max_nplanes_hit_pretrig - 1 << " +++\n"
201  << "+++ Try to proceed with the default value, nplanes_hit_pretrig=" << nplanes_hit_pretrig << " +++\n";
202  nplanes_hit_pretrig = def_nplanes_hit_pretrig;
203  }
204  if (nplanes_hit_pattern >= max_nplanes_hit_pattern) {
205  if (infoV >= 0)
206  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
207  << "+++ Value of nplanes_hit_pattern, " << nplanes_hit_pattern << ", exceeds max allowed, "
208  << max_nplanes_hit_pattern - 1 << " +++\n"
209  << "+++ Try to proceed with the default value, nplanes_hit_pattern=" << nplanes_hit_pattern << " +++\n";
210  nplanes_hit_pattern = def_nplanes_hit_pattern;
211  }
212  if (nplanes_hit_accel_pretrig >= max_nplanes_hit_accel_pretrig) {
213  if (infoV >= 0)
214  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
215  << "+++ Value of nplanes_hit_accel_pretrig, " << nplanes_hit_accel_pretrig << ", exceeds max allowed, "
216  << max_nplanes_hit_accel_pretrig - 1 << " +++\n"
217  << "+++ Try to proceed with the default value, "
218  << "nplanes_hit_accel_pretrig=" << nplanes_hit_accel_pretrig << " +++\n";
219  nplanes_hit_accel_pretrig = def_nplanes_hit_accel_pretrig;
220  }
221  if (nplanes_hit_accel_pattern >= max_nplanes_hit_accel_pattern) {
222  if (infoV >= 0)
223  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
224  << "+++ Value of nplanes_hit_accel_pattern, " << nplanes_hit_accel_pattern << ", exceeds max allowed, "
225  << max_nplanes_hit_accel_pattern - 1 << " +++\n"
226  << "+++ Try to proceed with the default value, "
227  << "nplanes_hit_accel_pattern=" << nplanes_hit_accel_pattern << " +++\n";
228  nplanes_hit_accel_pattern = def_nplanes_hit_accel_pattern;
229  }
230  if (trig_mode >= max_trig_mode) {
231  if (infoV >= 0)
232  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
233  << "+++ Value of trig_mode, " << trig_mode << ", exceeds max allowed, " << max_trig_mode - 1 << " +++\n"
234  << "+++ Try to proceed with the default value, trig_mode=" << trig_mode << " +++\n";
235  trig_mode = def_trig_mode;
236  }
237  if (accel_mode >= max_accel_mode) {
238  if (infoV >= 0)
239  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
240  << "+++ Value of accel_mode, " << accel_mode << ", exceeds max allowed, " << max_accel_mode - 1 << " +++\n"
241  << "+++ Try to proceed with the default value, accel_mode=" << accel_mode << " +++\n";
242  accel_mode = def_accel_mode;
243  }
244  if (l1a_window_width >= max_l1a_window_width) {
245  if (infoV >= 0)
246  edm::LogError("CSCAnodeLCTProcessor|ConfigError")
247  << "+++ Value of l1a_window_width, " << l1a_window_width << ", exceeds max allowed, "
248  << max_l1a_window_width - 1 << " +++\n"
249  << "+++ Try to proceed with the default value, l1a_window_width=" << l1a_window_width << " +++\n";
250  l1a_window_width = def_l1a_window_width;
251  }
252 }
253 
255  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
256  bestALCT[bx].clear();
257  secondALCT[bx].clear();
258  }
259  lct_list.clear();
260 }
261 
262 void CSCAnodeLCTProcessor::clear(const int wire, const int pattern) {
263  /* Clear the data off of selected pattern */
264  if (pattern == 0)
265  quality[wire][0] = -999;
266  else {
267  quality[wire][1] = -999;
268  quality[wire][2] = -999;
269  }
270 }
271 
272 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::run(const CSCWireDigiCollection* wiredc) {
273  static std::atomic<bool> config_dumped{false};
274  if ((infoV > 0 || (isSLHC_)) && !config_dumped) {
275  //std::cout<<"**** ALCT run parameters dump ****"<<std::endl;
277  config_dumped = true;
278  }
279 
280  // Get the number of wire groups for the given chamber. Do it only once
281  // per chamber.
282  if (numWireGroups == 0) {
283  if (cscChamber_) {
286  if (infoV >= 0)
287  edm::LogError("CSCAnodeLCTProcessor|SetupError")
288  << "+++ Number of wire groups, " << numWireGroups << " found in " << theCSCName_ << " (sector "
289  << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
290  << " exceeds max expected, " << CSCConstants::MAX_NUM_WIRES << " +++\n"
291  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
292  numWireGroups = -1;
293  }
294  } else {
295  if (infoV >= 0)
296  edm::LogError("CSCAnodeLCTProcessor|SetupError")
297  << "+++ " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
298  << theTrigChamber << ")"
299  << " is not defined in current geometry! +++\n"
300  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
301  numWireGroups = -1;
302  }
303  }
304 
305  if (numWireGroups < 0) {
306  if (infoV >= 0)
307  edm::LogError("CSCAnodeLCTProcessor|SetupError")
308  << "+++ " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
309  << theTrigChamber << "):"
310  << " numWireGroups = " << numWireGroups << "; ALCT emulation skipped! +++";
311  std::vector<CSCALCTDigi> emptyV;
312  return emptyV;
313  }
314 
315  // Get wire digis in this chamber from wire digi collection.
316  bool noDigis = getDigis(wiredc);
317 
318  if (!noDigis) {
319  // First get wire times from the wire digis.
321  readWireDigis(wire);
322 
323  // Pass an array of wire times on to another run() doing the LCT search.
324  // If the number of layers containing digis is smaller than that
325  // required to trigger, quit right away.
326  const unsigned int min_layers =
330 
331  unsigned int layersHit = 0;
332  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
333  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
334  if (!wire[i_layer][i_wire].empty()) {
335  layersHit++;
336  break;
337  }
338  }
339  }
340  if (layersHit >= min_layers)
341  run(wire);
342  }
343 
344  // Return vector of all found ALCTs.
345  return getALCTs();
346 }
347 
349  bool trigger = false;
350 
351  // Check if there are any in-time hits and do the pulse extension.
352  bool chamber_empty = pulseExtension(wire);
353 
354  // Only do the rest of the processing if chamber is not empty.
355  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
356  // not have a full set of hits to start pattern search anyway.
357  unsigned int stop_bx = fifo_tbins - drift_delay;
358  if (!chamber_empty) {
359  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
360  unsigned int start_bx = 0;
361  // Allow for more than one pass over the hits in the time window.
362  while (start_bx < stop_bx) {
363  if (preTrigger(i_wire, start_bx)) {
364  if (infoV > 2)
365  showPatterns(i_wire);
366  if (patternDetection(i_wire)) {
367  trigger = true;
368  int ghost_cleared[2] = {0, 0};
369  ghostCancellationLogicOneWire(i_wire, ghost_cleared);
370 
371  int bx = (use_corrected_bx) ? first_bx_corrected[i_wire] : first_bx[i_wire];
373  edm::LogError("CSCAnodeLCTProcessor")
374  << " bx of valid trigger : " << bx << " > max allowed value " << CSCConstants::MAX_ALCT_TBINS;
375 
376  //acceloration mode
377  if (quality[i_wire][0] > 0 and bx < CSCConstants::MAX_ALCT_TBINS) {
378  int valid = (ghost_cleared[0] == 0) ? 1 : 0; //cancelled, valid=0, otherwise it is 1
379  lct_list.push_back(CSCALCTDigi(valid, quality[i_wire][0], 1, 0, i_wire, bx));
380  if (infoV > 1)
381  LogTrace("CSCAnodeLCTProcessor") << "Add one ALCT to list " << lct_list.back();
382  }
383 
384  //collision mode
385  if (quality[i_wire][1] > 0 and bx < CSCConstants::MAX_ALCT_TBINS) {
386  int valid = (ghost_cleared[1] == 0) ? 1 : 0; //cancelled, valid=0, otherwise it is 1
387  lct_list.push_back(CSCALCTDigi(valid, quality[i_wire][1], 0, quality[i_wire][2], i_wire, bx));
388  if (infoV > 1)
389  LogTrace("CSCAnodeLCTProcessor") << "Add one ALCT to list " << lct_list.back();
390  }
391 
392  //break;
393  // Assume that the earliest time when another pre-trigger can
394  // occur in case pattern detection failed is bx_pretrigger+4:
395  // this seems to match the data.
396  start_bx = first_bx[i_wire] + drift_delay + pretrig_extra_deadtime;
397  } else {
398  //only pretrigger, no trigger ==> no dead time, continue to find next pretrigger
399  start_bx = first_bx[i_wire] + 1;
400  }
401  } else { //no pretrigger, skip this wiregroup
402  break;
403  }
404  } // end of while
405  }
406  }
407 
408  // Do the rest only if there is at least one trigger candidate.
409  if (trigger) {
410  //ghostCancellationLogic();
411  lctSearch();
412  }
413 }
414 
416  // Routine for getting digis and filling digiV vector.
417  bool noDigis = true;
418 
419  // Loop over layers and save wire digis on each one into digiV[layer].
420  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
421  digiV[i_layer].clear();
422 
423  CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer + 1);
424  getDigis(wiredc, detid);
425 
426  // If this is ME1/1, fetch digis in corresponding ME1/A (ring=4) as well.
427  if (isME11_ && !disableME1a_) {
428  CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer + 1);
429  getDigis(wiredc, detid_me1a);
430  }
431 
432  if (!digiV[i_layer].empty()) {
433  noDigis = false;
434  if (infoV > 1) {
435  LogTrace("CSCAnodeLCTProcessor") << "found " << digiV[i_layer].size() << " wire digi(s) in layer " << i_layer
436  << " of " << theCSCName_ << " (trig. sector " << theSector << " subsector "
437  << theSubsector << " id " << theTrigChamber << ")";
438  for (const auto& wd : digiV[i_layer]) {
439  LogTrace("CSCAnodeLCTProcessor") << " " << wd;
440  }
441  }
442  }
443  }
444 
445  return noDigis;
446 }
447 
449  CSCWireDigiCollection::Range rwired = wiredc->get(id);
450  for (CSCWireDigiCollection::const_iterator digiIt = rwired.first; digiIt != rwired.second; ++digiIt) {
451  digiV[id.layer() - 1].push_back(*digiIt);
452  }
453 }
454 
456  // Loop over all 6 layers.
457  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
458  // Loop over all digis in the layer and find the wireGroup and bx
459  // time for each.
460  for (const auto& wd : digiV[i_layer]) {
461  int i_wire = wd.getWireGroup() - 1;
462  std::vector<int> bx_times = wd.getTimeBinsOn();
463 
464  // Check that the wires and times are appropriate.
465  if (i_wire < 0 || i_wire >= numWireGroups) {
466  if (infoV >= 0)
467  edm::LogWarning("CSCAnodeLCTProcessor|WrongInput")
468  << "+++ Found wire digi with wrong wire number = " << i_wire << " (max wires = " << numWireGroups
469  << "); skipping it... +++\n";
470  continue;
471  }
472  // Accept digis in expected time window. Total number of time
473  // bins in DAQ readout is given by fifo_tbins, which thus
474  // determines the maximum length of time interval. Anode raw
475  // hits in DAQ readout start (fifo_pretrig - 6) clocks before
476  // L1Accept. If times earlier than L1Accept were recorded, we
477  // use them since they can modify the ALCTs found later, via
478  // ghost-cancellation logic.
479  int last_time = -999;
480  if (bx_times.size() == fifo_tbins) {
481  wire[i_layer][i_wire].push_back(0);
482  wire[i_layer][i_wire].push_back(6);
483  } else {
484  for (unsigned int i = 0; i < bx_times.size(); i++) {
485  // Find rising edge change
486  if (i > 0 && bx_times[i] == (bx_times[i - 1] + 1))
487  continue;
488  if (bx_times[i] < static_cast<int>(fifo_tbins)) {
489  if (infoV > 2)
490  LogTrace("CSCAnodeLCTProcessor")
491  << "Digi on layer " << i_layer << " wire " << i_wire << " at time " << bx_times[i];
492 
493  // Finally save times of hit wires. One shot module will
494  // not restart if a new pulse comes before the expiration
495  // of the 6-bx period.
496  if (last_time < 0 || ((bx_times[i] - last_time) >= 6)) {
497  wire[i_layer][i_wire].push_back(bx_times[i]);
498  last_time = bx_times[i];
499  }
500  } else {
501  if (infoV > 1)
502  LogTrace("CSCAnodeLCTProcessor") << "+++ Skipping wire digi: wire = " << i_wire << " layer = " << i_layer
503  << ", bx = " << bx_times[i] << " +++";
504  }
505  }
506  }
507  }
508  }
509 }
510 
512  const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]) {
513  bool chamber_empty = true;
514  int i_wire, i_layer, digi_num;
515  const unsigned int bits_in_pulse = 8 * sizeof(pulse[0][0]);
516 
517  for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
518  for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
519  pulse[i_layer][i_wire] = 0;
520  }
521  first_bx[i_wire] = -999;
522  first_bx_corrected[i_wire] = -999;
523  for (int j = 0; j < 3; j++)
524  quality[i_wire][j] = -999;
525  }
526 
527  for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
528  digi_num = 0;
529  for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
530  if (!wire[i_layer][i_wire].empty()) {
531  std::vector<int> bx_times = wire[i_layer][i_wire];
532  for (unsigned int i = 0; i < bx_times.size(); i++) {
533  // Check that min and max times are within the allowed range.
534  if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
535  if (infoV > 0)
536  edm::LogWarning("CSCAnodeLCTProcessor|OutOfTimeDigi")
537  << "+++ BX time of wire digi (wire = " << i_wire << " layer = " << i_layer << ") bx = " << bx_times[i]
538  << " is not within the range (0-" << bits_in_pulse
539  << "] allowed for pulse extension. Skip this digi! +++\n";
540  continue;
541  }
542 
543  // Found at least one in-time digi; set chamber_empty to false
544  if (chamber_empty)
545  chamber_empty = false;
546 
547  // make the pulse
548  for (unsigned int bx = bx_times[i]; bx < (bx_times[i] + hit_persist); bx++)
549  pulse[i_layer][i_wire] = pulse[i_layer][i_wire] | (1 << bx);
550 
551  // Debug information.
552  if (infoV > 1) {
553  LogTrace("CSCAnodeLCTProcessor") << "Wire digi: layer " << i_layer << " digi #" << ++digi_num
554  << " wire group " << i_wire << " time " << bx_times[i];
555  if (infoV > 2) {
556  std::ostringstream strstrm;
557  for (int i = 1; i <= 32; i++) {
558  strstrm << ((pulse[i_layer][i_wire] >> (32 - i)) & 1);
559  }
560  LogTrace("CSCAnodeLCTProcessor") << " Pulse: " << strstrm.str();
561  }
562  }
563  }
564  }
565  }
566  }
567 
568  if (infoV > 1 && !chamber_empty) {
569  dumpDigis(wire);
570  }
571 
572  return chamber_empty;
573 }
574 
575 bool CSCAnodeLCTProcessor::preTrigger(const int key_wire, const int start_bx) {
576  int nPreTriggers = 0;
577 
578  unsigned int layers_hit;
579  bool hit_layer[CSCConstants::NUM_LAYERS];
580  int this_layer, this_wire;
581  // If nplanes_hit_accel_pretrig is 0, the firmware uses the value
582  // of nplanes_hit_pretrig instead.
583  const unsigned int nplanes_hit_pretrig_acc =
585  const unsigned int pretrig_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
586  nplanes_hit_pretrig_acc, nplanes_hit_pretrig, nplanes_hit_pretrig};
587 
588  // Loop over bx times, accelerator and collision patterns to
589  // look for pretrigger.
590  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
591  // not have a full set of hits to start pattern search anyway.
592  unsigned int stop_bx = fifo_tbins - drift_delay;
593  for (unsigned int bx_time = start_bx; bx_time < stop_bx; bx_time++) {
594  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
595  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
596  hit_layer[i_layer] = false;
597  layers_hit = 0;
598 
599  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++) {
600  if (pattern_mask[i_pattern][i_wire] != 0) {
601  this_layer = CSCPatternBank::alct_pattern_envelope[i_wire];
602  this_wire = CSCPatternBank::alct_keywire_offset[MESelection][i_wire] + key_wire;
603  if ((this_wire >= 0) && (this_wire < numWireGroups)) {
604  // Perform bit operation to see if pulse is 1 at a certain bx_time.
605  if (((pulse[this_layer][this_wire] >> bx_time) & 1) == 1) {
606  // Store number of layers hit.
607  if (hit_layer[this_layer] == false) {
608  hit_layer[this_layer] = true;
609  layers_hit++;
610  }
611 
612  // See if number of layers hit is greater than or equal to
613  // pretrig_thresh.
614  if (layers_hit >= pretrig_thresh[i_pattern]) {
615  first_bx[key_wire] = bx_time;
616  if (infoV > 1) {
617  LogTrace("CSCAnodeLCTProcessor") << "Pretrigger was satisfied for wire: " << key_wire
618  << " pattern: " << i_pattern << " bx_time: " << bx_time;
619  }
620  // make a new pre-trigger
621  nPreTriggers++;
622  thePreTriggerDigis.emplace_back(
623  CSCALCTPreTriggerDigi(1, layers_hit - 3, 0, 0, this_wire, bx_time, nPreTriggers));
624  return true;
625  }
626  }
627  }
628  }
629  }
630  }
631  }
632  // If the pretrigger was never satisfied, then return false.
633  return false;
634 }
635 
636 bool CSCAnodeLCTProcessor::patternDetection(const int key_wire) {
637  bool trigger = false;
638  bool hit_layer[CSCConstants::NUM_LAYERS];
639  unsigned int temp_quality;
640  int this_layer, this_wire, delta_wire;
641  // If nplanes_hit_accel_pattern is 0, the firmware uses the value
642  // of nplanes_hit_pattern instead.
643  const unsigned int nplanes_hit_pattern_acc =
645  const unsigned int pattern_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
646  nplanes_hit_pattern_acc, nplanes_hit_pattern, nplanes_hit_pattern};
647  const std::string ptn_label[] = {"Accelerator", "CollisionA", "CollisionB"};
648 
649  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
650  temp_quality = 0;
651  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
652  hit_layer[i_layer] = false;
653 
654  double num_pattern_hits = 0., times_sum = 0.;
655  std::multiset<int> mset_for_median;
656  mset_for_median.clear();
657 
658  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++) {
659  if (pattern_mask[i_pattern][i_wire] != 0) {
660  this_layer = CSCPatternBank::alct_pattern_envelope[i_wire];
661  delta_wire = CSCPatternBank::alct_keywire_offset[MESelection][i_wire];
662  this_wire = delta_wire + key_wire;
663  if ((this_wire >= 0) && (this_wire < numWireGroups)) {
664  // Wait a drift_delay time later and look for layers hit in
665  // the pattern.
666  if (((pulse[this_layer][this_wire] >> (first_bx[key_wire] + drift_delay)) & 1) == 1) {
667  // If layer has never had a hit before, then increment number
668  // of layer hits.
669  if (hit_layer[this_layer] == false) {
670  temp_quality++;
671  // keep track of which layers already had hits.
672  hit_layer[this_layer] = true;
673  if (infoV > 1)
674  LogTrace("CSCAnodeLCTProcessor")
675  << "bx_time: " << first_bx[key_wire] << " pattern: " << i_pattern << " keywire: " << key_wire
676  << " layer: " << this_layer << " quality: " << temp_quality;
677  }
678 
679  // for averaged time use only the closest WGs around the key WG
680  if (abs(delta_wire) < 2) {
681  // find at what bx did pulse on this wire&layer start
682  // use hit_pesrist constraint on how far back we can go
683  int first_bx_layer = first_bx[key_wire] + drift_delay;
684  for (unsigned int dbx = 0; dbx < hit_persist; dbx++) {
685  if (((pulse[this_layer][this_wire] >> (first_bx_layer - 1)) & 1) == 1)
686  first_bx_layer--;
687  else
688  break;
689  }
690  times_sum += (double)first_bx_layer;
691  num_pattern_hits += 1.;
692  mset_for_median.insert(first_bx_layer);
693  if (infoV > 2)
694  LogTrace("CSCAnodeLCTProcessor") << " 1st bx in layer: " << first_bx_layer << " sum bx: " << times_sum
695  << " #pat. hits: " << num_pattern_hits;
696  }
697  }
698  }
699  }
700  }
701 
702  // calculate median
703  const int sz = mset_for_median.size();
704  if (sz > 0) {
705  std::multiset<int>::iterator im = mset_for_median.begin();
706  if (sz > 1)
707  std::advance(im, sz / 2 - 1);
708  if (sz == 1)
709  first_bx_corrected[key_wire] = *im;
710  else if ((sz % 2) == 1)
711  first_bx_corrected[key_wire] = *(++im);
712  else
713  first_bx_corrected[key_wire] = ((*im) + (*(++im))) / 2;
714 
715 #if defined(EDM_ML_DEBUG)
716  if (infoV > 1) {
717  auto lt = LogTrace("CSCAnodeLCTProcessor")
718  << "bx=" << first_bx[key_wire] << " bx_cor=" << first_bx_corrected[key_wire] << " bxset=";
719  for (im = mset_for_median.begin(); im != mset_for_median.end(); im++) {
720  lt << " " << *im;
721  }
722  }
723 #endif
724  }
725 
726  if (temp_quality >= pattern_thresh[i_pattern]) {
727  trigger = true;
728 
729  // Quality definition changed on 22 June 2007: it no longer depends
730  // on pattern_thresh.
731  temp_quality = getTempALCTQuality(temp_quality);
732 
733  if (i_pattern == 0) {
734  // Accelerator pattern
735  quality[key_wire][0] = temp_quality;
736  } else {
737  // Only one collision pattern (of the best quality) is reported
738  if (static_cast<int>(temp_quality) > quality[key_wire][1]) {
739  quality[key_wire][1] = temp_quality; //real quality
740  quality[key_wire][2] = i_pattern - 1; // pattern, left or right
741  }
742  }
743  if (infoV > 1) {
744  LogTrace("CSCAnodeLCTProcessor") << "Pattern found; keywire: " << key_wire << " type: " << ptn_label[i_pattern]
745  << " quality: " << temp_quality << "\n";
746  }
747  }
748  }
749  if (infoV > 1 && quality[key_wire][1] > 0) {
750  if (quality[key_wire][2] == 0)
751  LogTrace("CSCAnodeLCTProcessor") << "Collision Pattern A is chosen"
752  << "\n";
753  else if (quality[key_wire][2] == 1)
754  LogTrace("CSCAnodeLCTProcessor") << "Collision Pattern B is chosen"
755  << "\n";
756  }
757 
758  trigMode(key_wire);
759 
760  return trigger;
761 }
762 
764  int ghost_cleared[CSCConstants::MAX_NUM_WIRES][2];
765 
766  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
767  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
768  ghost_cleared[key_wire][i_pattern] = 0;
769 
770  // Non-empty wire group.
771  int qual_this = quality[key_wire][i_pattern];
772  if (qual_this > 0) {
773  // Previous wire.
774  int qual_prev = (key_wire > 0) ? quality[key_wire - 1][i_pattern] : 0;
775  if (qual_prev > 0) {
776  int dt = first_bx[key_wire] - first_bx[key_wire - 1];
777  // Cancel this wire
778  // 1) If the candidate at the previous wire is at the same bx
779  // clock and has better quality (or equal quality - this has
780  // been implemented only in 2004).
781  // 2) If the candidate at the previous wire is up to 4 clocks
782  // earlier, regardless of quality.
783  if (dt == 0) {
784  if (qual_prev >= qual_this)
785  ghost_cleared[key_wire][i_pattern] = 1;
786  } else if (dt > 0 && dt <= ghost_cancellation_bx_depth) {
787  if ((!ghost_cancellation_side_quality) || (qual_prev > qual_this))
788  ghost_cleared[key_wire][i_pattern] = 1;
789  }
790  }
791 
792  // Next wire.
793  // Skip this step if this wire is already declared "ghost".
794  if (ghost_cleared[key_wire][i_pattern] == 1) {
795  if (infoV > 1)
796  LogTrace("CSCAnodeLCTProcessor")
797  << ((i_pattern == 0) ? "Accelerator" : "Collision") << " pattern ghost cancelled on key_wire "
798  << key_wire << " q=" << qual_this << " by wire " << key_wire - 1 << " q=" << qual_prev;
799  continue;
800  }
801 
802  int qual_next = (key_wire < numWireGroups - 1) ? quality[key_wire + 1][i_pattern] : 0;
803  if (qual_next > 0) {
804  int dt = first_bx[key_wire] - first_bx[key_wire + 1];
805  // Same cancellation logic as for the previous wire.
806  if (dt == 0) {
807  if (qual_next > qual_this)
808  ghost_cleared[key_wire][i_pattern] = 1;
809  } else if (dt > 0 && dt <= ghost_cancellation_bx_depth) {
810  if ((!ghost_cancellation_side_quality) || (qual_next >= qual_this))
811  ghost_cleared[key_wire][i_pattern] = 1;
812  }
813  }
814  if (ghost_cleared[key_wire][i_pattern] == 1) {
815  if (infoV > 1)
816  LogTrace("CSCAnodeLCTProcessor")
817  << ((i_pattern == 0) ? "Accelerator" : "Collision") << " pattern ghost cancelled on key_wire "
818  << key_wire << " q=" << qual_this << " by wire " << key_wire + 1 << " q=" << qual_next;
819  continue;
820  }
821  }
822  }
823  }
824 
825  // All cancellation is done in parallel, so wiregroups do not know what
826  // their neighbors are cancelling.
827  // namely, if wiregroup 10, 11, 12 all have trigger and same quality, only wiregroup 10 can keep the trigger
828  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
829  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
830  if (ghost_cleared[key_wire][i_pattern] > 0) {
831  clear(key_wire, i_pattern);
832  }
833  }
834  }
835 }
836 
837 void CSCAnodeLCTProcessor::ghostCancellationLogicOneWire(const int key_wire, int* ghost_cleared) {
838  //int ghost_cleared[2];
839 
840  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
841  ghost_cleared[i_pattern] = 0;
842  if (key_wire == 0)
843  continue; //ignore
844 
845  // Non-empty wire group.
846  int qual_this = quality[key_wire][i_pattern];
847  if (qual_this > 0) {
848  // Previous wire.
849  //int qual_prev = (key_wire > 0) ? quality[key_wire-1][i_pattern] : 0;
850  //previous ALCTs were pushed to lct_list, stop use the array quality[key_wire-1][i_pattern]
851  for (auto& p : lct_list) {
852  //ignore whether ALCT is valid or not in ghost cancellation
853  //if wiregroup 10, 11, 12 all have trigger and same quality, only wiregroup 10 can keep the trigger
854  //this met with firmware
855  if (not(p.getKeyWG() == key_wire - 1 and 1 - p.getAccelerator() == i_pattern))
856  continue;
857 
858  bool ghost_cleared_prev = false;
859  int qual_prev = p.getQuality();
860  int first_bx_prev = p.getBX();
861  if (infoV > 1)
862  LogTrace("CSCAnodeLCTProcessor")
863  << "ghost concellation logic " << ((i_pattern == 0) ? "Accelerator" : "Collision") << " key_wire "
864  << key_wire << " quality " << qual_this << " bx " << first_bx[key_wire] << " previous key_wire "
865  << key_wire - 1 << " quality " << qual_prev << " bx " << first_bx[key_wire - 1];
866 
867  //int dt = first_bx[key_wire] - first_bx[key_wire-1];
868  int dt = first_bx[key_wire] - first_bx_prev;
869  // Cancel this wire
870  // 1) If the candidate at the previous wire is at the same bx
871  // clock and has better quality (or equal quality - this has
872  // been implemented only in 2004).
873  // 2) If the candidate at the previous wire is up to 4 clocks
874  // earlier, regardless of quality.
875  if (dt == 0) {
876  if (qual_prev >= qual_this)
877  ghost_cleared[i_pattern] = 1;
878  else if (qual_prev < qual_this)
879  ghost_cleared_prev = true;
880  } else if (dt > 0 && dt <= ghost_cancellation_bx_depth) {
881  if ((!ghost_cancellation_side_quality) || (qual_prev > qual_this))
882  ghost_cleared[i_pattern] = 1;
883  } else if (dt < 0 && dt * (-1) <= ghost_cancellation_bx_depth) {
884  if ((!ghost_cancellation_side_quality) || (qual_prev < qual_this))
885  ghost_cleared_prev = true;
886  }
887 
888  if (ghost_cleared[i_pattern] == 1) {
889  if (infoV > 1)
890  LogTrace("CSCAnodeLCTProcessor")
891  << ((i_pattern == 0) ? "Accelerator" : "Collision") << " pattern ghost cancelled on key_wire "
892  << key_wire << " q=" << qual_this << " by wire " << key_wire - 1 << " q=" << qual_prev;
893  //cancellation for key_wire is done when ALCT is created and pushed to lct_list
894  }
895 
896  if (ghost_cleared_prev) {
897  if (infoV > 1)
898  LogTrace("CSCAnodeLCTProcessor")
899  << ((i_pattern == 0) ? "Accelerator" : "Collision") << " pattern ghost cancelled on key_wire "
900  << key_wire - 1 << " q=" << qual_prev << " by wire " << key_wire << " q=" << qual_this;
901  p.setValid(0); //clean prev ALCT
902  }
903  }
904 
905  } // if qual_this > 0
906  } //i_pattern
907 }
908 
910  // Best track selector selects two collision and two accelerator ALCTs
911  // with the best quality per time bin.
912  const std::vector<CSCALCTDigi>& fourBest = bestTrackSelector(lct_list);
913 
914  if (infoV > 0) {
915  int n_alct_all = 0, n_alct = 0;
916  for (const auto& p : lct_list) {
917  if (p.isValid() && p.getBX() == CSCConstants::LCT_CENTRAL_BX)
918  n_alct_all++;
919  }
920  for (const auto& p : fourBest) {
921  if (p.isValid() && p.getBX() == CSCConstants::LCT_CENTRAL_BX)
922  n_alct++;
923  }
924 
925  LogTrace("CSCAnodeLCTProcessor") << "alct_count E:" << theEndcap << "S:" << theStation << "R:" << theRing
926  << "C:" << theChamber << " all " << n_alct_all << " found " << n_alct;
927  }
928 
929  // Select two best of four per time bin, based on quality and
930  // accel_mode parameter.
931  for (const auto& p : fourBest) {
932  const int bx = p.getBX();
933  if (bx >= CSCConstants::MAX_ALCT_TBINS) {
934  if (infoV > 0)
935  edm::LogWarning("CSCAnodeLCTProcessor|OutOfTimeALCT")
936  << "+++ Bx of ALCT candidate, " << bx << ", exceeds max allowed, " << CSCConstants::MAX_ALCT_TBINS - 1
937  << "; skipping it... +++\n";
938  continue;
939  }
940 
941  if (isBetterALCT(p, bestALCT[bx])) {
942  if (isBetterALCT(bestALCT[bx], secondALCT[bx])) {
943  secondALCT[bx] = bestALCT[bx];
944  }
945  bestALCT[bx] = p;
946  } else if (isBetterALCT(p, secondALCT[bx])) {
947  secondALCT[bx] = p;
948  }
949  }
950 
951  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
952  if (bestALCT[bx].isValid()) {
953  bestALCT[bx].setTrknmb(1);
954  if (infoV > 0) {
955  LogDebug("CSCAnodeLCTProcessor") << "\n"
956  << bestALCT[bx] << " fullBX = " << bestALCT[bx].getFullBX() << " found in "
957  << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector
958  << " trig id. " << theTrigChamber << ")"
959  << "\n";
960  }
961  if (secondALCT[bx].isValid()) {
962  secondALCT[bx].setTrknmb(2);
963  if (infoV > 0) {
964  LogDebug("CSCAnodeLCTProcessor")
965  << secondALCT[bx] << " fullBX = " << secondALCT[bx].getFullBX() << " found in " << theCSCName_
966  << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
967  << "\n";
968  }
969  }
970  }
971  }
972 }
973 
974 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::bestTrackSelector(const std::vector<CSCALCTDigi>& all_alcts) {
977 
978  if (infoV > 1) {
979  LogTrace("CSCAnodeLCTProcessor") << all_alcts.size() << " ALCTs at the input of best-track selector: ";
980  for (const auto& p : all_alcts) {
981  if (!p.isValid())
982  continue;
983  LogTrace("CSCAnodeLCTProcessor") << p;
984  }
985  }
986 
989  for (const auto& p : all_alcts) {
990  if (!p.isValid())
991  continue;
992 
993  // Select two collision and two accelerator ALCTs with the highest
994  // quality at every bx. The search for best ALCTs is done in parallel
995  // for collision and accelerator patterns, and simultaneously for
996  // two ALCTs, tA and tB. If two or more ALCTs have equal qualities,
997  // the priority is given to the ALCT with larger wiregroup number
998  // in the search for tA (collision and accelerator), and to the ALCT
999  // with smaller wiregroup number in the search for tB.
1000  int bx = p.getBX();
1001  int accel = p.getAccelerator();
1002  int qual = p.getQuality();
1003  int wire = p.getKeyWG();
1004  bool vA = tA[bx][accel].isValid();
1005  bool vB = tB[bx][accel].isValid();
1006  int qA = tA[bx][accel].getQuality();
1007  int qB = tB[bx][accel].getQuality();
1008  int wA = tA[bx][accel].getKeyWG();
1009  int wB = tB[bx][accel].getKeyWG();
1010  if (!vA || qual > qA || (qual == qA && wire > wA)) {
1011  tA[bx][accel] = p;
1012  }
1013  if (!vB || qual > qB || (qual == qB && wire < wB)) {
1014  tB[bx][accel] = p;
1015  }
1016  }
1017 
1018  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1019  for (int accel = 0; accel <= 1; accel++) {
1020  // Best ALCT is always tA.
1021  if (tA[bx][accel].isValid()) {
1022  if (infoV > 2) {
1023  LogTrace("CSCAnodeLCTProcessor") << "tA: " << tA[bx][accel];
1024  LogTrace("CSCAnodeLCTProcessor") << "tB: " << tB[bx][accel];
1025  }
1026  bestALCTs[bx][accel] = tA[bx][accel];
1027 
1028  // If tA exists, tB exists too.
1029  if (tA[bx][accel] != tB[bx][accel] && tA[bx][accel].getQuality() == tB[bx][accel].getQuality()) {
1030  secondALCTs[bx][accel] = tB[bx][accel];
1031  } else {
1032  // Funny part: if tA and tB are the same, or the quality of tB
1033  // is inferior to the quality of tA, the second best ALCT is
1034  // not tB. Instead it is the largest-wiregroup ALCT among those
1035  // ALCT whose qualities are lower than the quality of the best one.
1036  for (const auto& p : all_alcts) {
1037  if (p.isValid() && p.getAccelerator() == accel && p.getBX() == bx &&
1038  p.getQuality() < bestALCTs[bx][accel].getQuality() &&
1039  p.getQuality() >= secondALCTs[bx][accel].getQuality() &&
1040  p.getKeyWG() >= secondALCTs[bx][accel].getKeyWG()) {
1041  secondALCTs[bx][accel] = p;
1042  }
1043  }
1044  }
1045  }
1046  }
1047  }
1048 
1049  // Fill the vector with up to four best ALCTs per bx and return it.
1050  std::vector<CSCALCTDigi> fourBest;
1051  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1052  for (int i = 0; i < CSCConstants::MAX_ALCTS_PER_PROCESSOR; i++) {
1053  if (bestALCTs[bx][i].isValid()) {
1054  fourBest.push_back(bestALCTs[bx][i]);
1055  }
1056  }
1057  for (int i = 0; i < CSCConstants::MAX_ALCTS_PER_PROCESSOR; i++) {
1058  if (secondALCTs[bx][i].isValid()) {
1059  fourBest.push_back(secondALCTs[bx][i]);
1060  }
1061  }
1062  }
1063 
1064  if (infoV > 1) {
1065  LogTrace("CSCAnodeLCTProcessor") << fourBest.size() << " ALCTs selected: ";
1066  for (const auto& p : fourBest) {
1067  LogTrace("CSCAnodeLCTProcessor") << p;
1068  }
1069  }
1070 
1071  return fourBest;
1072 }
1073 
1074 bool CSCAnodeLCTProcessor::isBetterALCT(const CSCALCTDigi& lhsALCT, const CSCALCTDigi& rhsALCT) const {
1075  bool returnValue = false;
1076 
1077  if (lhsALCT.isValid() && !rhsALCT.isValid()) {
1078  return true;
1079  }
1080 
1081  // ALCTs found at earlier bx times are ranked higher than ALCTs found at
1082  // later bx times regardless of the quality.
1083  if (lhsALCT.getBX() < rhsALCT.getBX()) {
1084  returnValue = true;
1085  }
1086  if (lhsALCT.getBX() != rhsALCT.getBX()) {
1087  return returnValue;
1088  }
1089 
1090  // First check the quality of ALCTs.
1091  const int qual1 = lhsALCT.getQuality();
1092  const int qual2 = rhsALCT.getQuality();
1093  if (qual1 > qual2) {
1094  returnValue = true;
1095  }
1096  // If qualities are the same, check accelerator bits of both ALCTs.
1097  // If they are not the same, rank according to accel_mode value.
1098  // If they are the same, keep the track selector assignment.
1099  //else if (qual1 == qual2 &&
1100  // lhsALCT.getAccelerator() != rhsALCT.getAccelerator() &&
1101  // quality[lhsALCT.getKeyWG()][1-lhsALCT.getAccelerator()] >
1102  // quality[rhsALCT.getKeyWG()][1-rhsALCT.getAccelerator()])
1103  // {returnValue = true;}
1104  else if (qual1 == qual2 && lhsALCT.getAccelerator() != rhsALCT.getAccelerator()) {
1105  if ((accel_mode == 0 || accel_mode == 1) && rhsALCT.getAccelerator() == 0)
1106  returnValue = true;
1107  if ((accel_mode == 2 || accel_mode == 3) && lhsALCT.getAccelerator() == 0)
1108  returnValue = true;
1109  }
1110 
1111  return returnValue;
1112 }
1113 
1114 void CSCAnodeLCTProcessor::trigMode(const int key_wire) {
1115  switch (trig_mode) {
1116  default:
1117  case 0:
1118  // Enables both collision and accelerator tracks
1119  break;
1120  case 1:
1121  // Disables collision tracks
1122  if (quality[key_wire][1] > 0) {
1123  quality[key_wire][1] = 0;
1124  if (infoV > 1)
1125  LogTrace("CSCAnodeLCTProcessor") << "trigMode(): collision track " << key_wire << " disabled"
1126  << "\n";
1127  }
1128  break;
1129  case 2:
1130  // Disables accelerator tracks
1131  if (quality[key_wire][0] > 0) {
1132  quality[key_wire][0] = 0;
1133  if (infoV > 1)
1134  LogTrace("CSCAnodeLCTProcessor") << "trigMode(): accelerator track " << key_wire << " disabled"
1135  << "\n";
1136  }
1137  break;
1138  case 3:
1139  // Disables collision track if there is an accelerator track found
1140  // in the same wire group at the same time
1141  if (quality[key_wire][0] > 0 && quality[key_wire][1] > 0) {
1142  quality[key_wire][1] = 0;
1143  if (infoV > 1)
1144  LogTrace("CSCAnodeLCTProcessor") << "trigMode(): collision track " << key_wire << " disabled"
1145  << "\n";
1146  }
1147  break;
1148  }
1149 }
1150 
1151 void CSCAnodeLCTProcessor::accelMode(const int key_wire) {
1152  int promotionBit = 1 << 2;
1153 
1154  switch (accel_mode) {
1155  default:
1156  case 0:
1157  // Ignore accelerator muons.
1158  if (quality[key_wire][0] > 0) {
1159  quality[key_wire][0] = 0;
1160  if (infoV > 1)
1161  LogTrace("CSCAnodeLCTProcessor") << "alctMode(): accelerator track " << key_wire << " ignored"
1162  << "\n";
1163  }
1164  break;
1165  case 1:
1166  // Prefer collision muons by adding promotion bit.
1167  if (quality[key_wire][1] > 0) {
1168  quality[key_wire][1] += promotionBit;
1169  if (infoV > 1)
1170  LogTrace("CSCAnodeLCTProcessor") << "alctMode(): collision track " << key_wire << " promoted"
1171  << "\n";
1172  }
1173  break;
1174  case 2:
1175  // Prefer accelerator muons by adding promotion bit.
1176  if (quality[key_wire][0] > 0) {
1177  quality[key_wire][0] += promotionBit;
1178  if (infoV > 1)
1179  LogTrace("CSCAnodeLCTProcessor") << "alctMode(): accelerator track " << key_wire << " promoted"
1180  << "\n";
1181  }
1182  break;
1183  case 3:
1184  // Ignore collision muons.
1185  if (quality[key_wire][1] > 0) {
1186  quality[key_wire][1] = 0;
1187  if (infoV > 1)
1188  LogTrace("CSCAnodeLCTProcessor") << "alctMode(): collision track " << key_wire << " ignored"
1189  << "\n";
1190  }
1191  break;
1192  }
1193 }
1194 
1195 // Dump of configuration parameters.
1197  std::ostringstream strm;
1198  strm << "\n";
1199  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1200  strm << "+ ALCT configuration parameters: +\n";
1201  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1202  strm << " fifo_tbins [total number of time bins in DAQ readout] = " << fifo_tbins << "\n";
1203  strm << " fifo_pretrig [start time of anode raw hits in DAQ readout] = " << fifo_pretrig << "\n";
1204  strm << " drift_delay [drift delay after pre-trigger, in 25 ns bins] = " << drift_delay << "\n";
1205  strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = " << nplanes_hit_pretrig << "\n";
1206  strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = " << nplanes_hit_pattern << "\n";
1207  strm << " nplanes_hit_accel_pretrig [min. number of layers hit for accel."
1208  << " pre-trig.] = " << nplanes_hit_accel_pretrig << "\n";
1209  strm << " nplanes_hit_accel_pattern [min. number of layers hit for accel."
1210  << " trigger] = " << nplanes_hit_accel_pattern << "\n";
1211  strm << " trig_mode [enabling/disabling collision/accelerator tracks] = " << trig_mode << "\n";
1212  strm << " accel_mode [preference to collision/accelerator tracks] = " << accel_mode << "\n";
1213  strm << " l1a_window_width [L1Accept window width, in 25 ns bins] = " << l1a_window_width << "\n";
1214  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1215  LogDebug("CSCAnodeLCTProcessor") << strm.str();
1216  //std::cout<<strm.str()<<std::endl;
1217 }
1218 
1219 // Dump of digis on wire groups.
1221  const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]) const {
1222  LogDebug("CSCAnodeLCTProcessor") << theCSCName_ << " nWiregroups " << numWireGroups;
1223 
1224  std::ostringstream strstrm;
1225  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1226  if (i_wire % 10 == 0) {
1227  if (i_wire < 100)
1228  strstrm << i_wire / 10;
1229  else
1230  strstrm << (i_wire - 100) / 10;
1231  } else
1232  strstrm << " ";
1233  }
1234  strstrm << "\n";
1235  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1236  strstrm << i_wire % 10;
1237  }
1238  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1239  strstrm << "\n";
1240  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1241  if (!wire[i_layer][i_wire].empty()) {
1242  std::vector<int> bx_times = wire[i_layer][i_wire];
1243  strstrm << std::hex << bx_times[0] << std::dec;
1244  } else {
1245  strstrm << ".";
1246  }
1247  }
1248  }
1249  LogTrace("CSCAnodeLCTProcessor") << strstrm.str();
1250 }
1251 
1252 // Returns vector of read-out ALCTs, if any. Starts with the vector of
1253 // all found ALCTs and selects the ones in the read-out time window.
1254 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::readoutALCTs() const {
1255  std::vector<CSCALCTDigi> tmpV;
1256 
1257  // The number of LCT bins in the read-out is given by the
1258  // l1a_window_width parameter, but made even by setting the LSB of
1259  // l1a_window_width to 0.
1260  const int lct_bins =
1261  // (l1a_window_width%2 == 0) ? l1a_window_width : l1a_window_width-1;
1263  static std::atomic<int> late_tbins{early_tbins + lct_bins};
1264 
1265  static std::atomic<int> ifois{0};
1266  if (ifois == 0) {
1267  //std::cout<<"ALCT early_tbins="<<early_tbins<<" lct_bins="<<lct_bins<<" l1a_window_width="<<l1a_window_width<<" late_tbins="<<late_tbins<<std::endl;
1268  //std::cout<<"**** ALCT readoutALCTs config dump ****"<<std::endl;
1269  //dumpConfigParams();
1270 
1271  if (infoV >= 0 && early_tbins < 0) {
1272  edm::LogWarning("CSCAnodeLCTProcessor|SuspiciousParameters")
1273  << "+++ fifo_pretrig = " << fifo_pretrig << "; in-time ALCTs are not getting read-out!!! +++"
1274  << "\n";
1275  }
1276 
1277  if (late_tbins > CSCConstants::MAX_ALCT_TBINS - 1) {
1278  if (infoV >= 0)
1279  edm::LogWarning("CSCAnodeLCTProcessor|SuspiciousParameters")
1280  << "+++ Allowed range of time bins, [0-" << late_tbins << "] exceeds max allowed, "
1281  << CSCConstants::MAX_ALCT_TBINS - 1 << " +++\n"
1282  << "+++ Set late_tbins to max allowed +++\n";
1283  late_tbins = CSCConstants::MAX_ALCT_TBINS - 1;
1284  }
1285  ifois = 1;
1286  }
1287 
1288  // Start from the vector of all found ALCTs and select those within
1289  // the ALCT*L1A coincidence window.
1290  const std::vector<CSCALCTDigi>& all_alcts = getALCTs();
1291  for (const auto& p : all_alcts) {
1292  if (!p.isValid())
1293  continue;
1294 
1295  int bx = p.getBX();
1296  // Skip ALCTs found too early relative to L1Accept.
1297  if (bx <= early_tbins) {
1298  if (infoV > 1)
1299  LogDebug("CSCAnodeLCTProcessor") << " Do not report ALCT on keywire " << p.getKeyWG() << ": found at bx " << bx
1300  << ", whereas the earliest allowed bx is " << early_tbins + 1;
1301  continue;
1302  }
1303 
1304  // Skip ALCTs found too late relative to L1Accept.
1305  if (bx > late_tbins) {
1306  if (infoV > 1)
1307  LogDebug("CSCAnodeLCTProcessor") << " Do not report ALCT on keywire " << p.getKeyWG() << ": found at bx " << bx
1308  << ", whereas the latest allowed bx is " << late_tbins;
1309  continue;
1310  }
1311 
1312  tmpV.push_back(p);
1313  }
1314 
1315  // shift the BX from 8 to 3
1316  // ALCTs in real data have the central BX in bin 3
1317  // which is the middle of the 7BX wide L1A window
1318  // ALCTs used in the TMB emulator have central BX at bin 8
1319  // but right before we put emulated ALCTs in the event, we shift the BX
1320  // by -5 to make sure they are compatible with real data ALCTs!
1321  for (auto& p : tmpV) {
1322  p.setBX(p.getBX() - (CSCConstants::LCT_CENTRAL_BX - l1a_window_width / 2));
1323  }
1324  return tmpV;
1325 }
1326 
1327 // Returns vector of all found ALCTs, if any. Used in ALCT-CLCT matching.
1328 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::getALCTs() const {
1329  std::vector<CSCALCTDigi> tmpV;
1330  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1331  if (bestALCT[bx].isValid())
1332  tmpV.push_back(bestALCT[bx]);
1333  if (secondALCT[bx].isValid())
1334  tmpV.push_back(secondALCT[bx]);
1335  }
1336  return tmpV;
1337 }
1338 
1340 
1342 
1345 
1346 void CSCAnodeLCTProcessor::showPatterns(const int key_wire) {
1347  /* Method to test the pretrigger */
1348  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
1349  std::ostringstream strstrm_header;
1350  LogTrace("CSCAnodeLCTProcessor") << "\n"
1351  << "Pattern: " << i_pattern << " Key wire: " << key_wire;
1352  for (int i = 1; i <= 32; i++) {
1353  strstrm_header << ((32 - i) % 10);
1354  }
1355  LogTrace("CSCAnodeLCTProcessor") << strstrm_header.str();
1356  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++) {
1357  if (pattern_mask[i_pattern][i_wire] != 0) {
1358  std::ostringstream strstrm_pulse;
1359  int this_layer = CSCPatternBank::alct_pattern_envelope[i_wire];
1360  int this_wire = CSCPatternBank::alct_keywire_offset[MESelection][i_wire] + key_wire;
1361  if (this_wire >= 0 && this_wire < numWireGroups) {
1362  for (int i = 1; i <= 32; i++) {
1363  strstrm_pulse << ((pulse[this_layer][this_wire] >> (32 - i)) & 1);
1364  }
1365  LogTrace("CSCAnodeLCTProcessor")
1366  << strstrm_pulse.str() << " on layer " << this_layer << " wire " << this_wire;
1367  }
1368  }
1369  }
1370  LogTrace("CSCAnodeLCTProcessor") << "-------------------------------------------";
1371  }
1372 }
1373 
1374 int CSCAnodeLCTProcessor::getTempALCTQuality(int temp_quality) const {
1375  int Q;
1376  if (temp_quality > 3)
1377  Q = temp_quality - 3;
1378  else
1379  Q = 0; // quality code 0 is valid!
1380 
1381  return Q;
1382 }
#define LogDebug(id)
T getParameter(std::string const &) const
float dt
Definition: AMPTWrapper.h:136
void showPatterns(const int key_wire)
void readWireDigis(std::vector< int > wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES])
int quality[CSCConstants::MAX_NUM_WIRES][3]
unsigned int alctDriftDelay() const
int first_bx_corrected[CSCConstants::MAX_NUM_WIRES]
static const unsigned int def_drift_delay
static const unsigned int def_fifo_tbins
CSCALCTDigi getSecondALCT(int bx) const
const unsigned theEndcap
Definition: CSCBaseboard.h:37
bool getDigis(const CSCWireDigiCollection *wiredc)
const CSCChamber * cscChamber_
Definition: CSCBaseboard.h:59
bool isValid() const
check ALCT validity (1 - valid ALCT)
Definition: CSCALCTDigi.h:32
std::vector< CSCALCTPreTriggerDigi > thePreTriggerDigis
static const int alct_pattern_envelope[CSCConstants::MAX_WIRES_IN_PATTERN]
const unsigned theSector
Definition: CSCBaseboard.h:39
void clear()
clear this ALCT
Definition: CSCALCTDigi.cc:39
unsigned int alctNplanesHitPretrig() const
bool disableME1a_
Definition: CSCBaseboard.h:81
bool isBetterALCT(const CSCALCTDigi &lhsALCT, const CSCALCTDigi &rhsALCT) const
std::string theCSCName_
Definition: CSCBaseboard.h:74
void setConfigParameters(const CSCDBL1TPParameters *conf)
void trigMode(const int key_wire)
int numberOfWireGroups() const
static const unsigned int def_accel_mode
std::vector< CSCALCTDigi > lct_list
unsigned int alctL1aWindowWidth() const
int getFullBX() const
return 12-bit full BX.
Definition: CSCALCTDigi.h:77
virtual void ghostCancellationLogic()
static const unsigned int def_nplanes_hit_accel_pretrig
const unsigned theTrigChamber
Definition: CSCBaseboard.h:41
static const unsigned int def_fifo_pretrig
std::vector< CSCALCTDigi > getALCTs() const
std::vector< CSCALCTDigi > readoutALCTs() const
void accelMode(const int key_wire)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:30
int pattern_mask[CSCConstants::NUM_ALCT_PATTERNS][CSCConstants::MAX_WIRES_IN_PATTERN]
unsigned theChamber
Definition: CSCBaseboard.h:44
static const unsigned int def_nplanes_hit_pattern
unsigned int alctTrigMode() const
#define LogTrace(id)
static const int alct_pattern_mask_open[CSCConstants::NUM_ALCT_PATTERNS][CSCConstants::MAX_WIRES_IN_PATTERN]
bool preTrigger(const int key_wire, const int start_bx)
bool pulseExtension(const std::vector< int > wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES])
int getBX() const
return BX - five low bits of BXN counter tagged by the ALCT
Definition: CSCALCTDigi.h:65
CSCALCTDigi secondALCT[CSCConstants::MAX_ALCT_TBINS]
virtual int getTempALCTQuality(int temp_quality) const
static const unsigned int def_l1a_window_width
int getQuality() const
return quality of a pattern
Definition: CSCALCTDigi.h:38
unsigned int alctAccelMode() const
static const unsigned int def_trig_mode
int getAccelerator() const
Definition: CSCALCTDigi.h:45
static const unsigned int def_nplanes_hit_accel_pattern
unsigned int alctFifoPretrig() const
unsigned int alctNplanesHitAccelPretrig() const
std::pair< const_iterator, const_iterator > Range
const unsigned theStation
Definition: CSCBaseboard.h:38
std::vector< DigiType >::const_iterator const_iterator
unsigned int alctNplanesHitAccelPattern() const
std::vector< CSCALCTDigi > bestTrackSelector(const std::vector< CSCALCTDigi > &all_alcts)
static const int alct_pattern_mask_r1[CSCConstants::NUM_ALCT_PATTERNS][CSCConstants::MAX_WIRES_IN_PATTERN]
static const int alct_keywire_offset[2][CSCConstants::MAX_WIRES_IN_PATTERN]
CSCALCTDigi bestALCT[CSCConstants::MAX_ALCT_TBINS]
virtual void ghostCancellationLogicOneWire(const int key_wire, int *ghost_cleared)
int first_bx[CSCConstants::MAX_NUM_WIRES]
edm::ParameterSet alctParams_
Definition: CSCBaseboard.h:68
void dumpDigis(const std::vector< int > wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]) const
void setTrknmb(const uint16_t number)
Set track number (1,2) after sorting ALCTs.
Definition: CSCALCTDigi.h:74
unsigned theRing
Definition: CSCBaseboard.h:43
unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIRES]
unsigned int alctNplanesHitPattern() const
bool patternDetection(const int key_wire)
unsigned int nplanes_hit_accel_pattern
std::vector< CSCALCTDigi > run(const CSCWireDigiCollection *wiredc)
unsigned int pretrig_extra_deadtime
int getKeyWG() const
return key wire group
Definition: CSCALCTDigi.h:59
const CSCLayerGeometry * geometry() const
Definition: CSCLayer.h:44
std::vector< CSCWireDigi > digiV[CSCConstants::NUM_LAYERS]
static const unsigned int def_nplanes_hit_pretrig
const unsigned theSubsector
Definition: CSCBaseboard.h:40
unsigned int nplanes_hit_accel_pretrig
CSCALCTDigi getBestALCT(int bx) const
unsigned int alctFifoTbins() const