CMS 3D CMS Logo

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