CMS 3D CMS Logo

CSCAnodeLCTProcessor.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // Class: CSCAnodeLCTProcessor
4 //
5 // Description:
6 // This is the simulation for the Anode LCT Processor for the Level-1
7 // Trigger. This processor consists of several stages:
8 //
9 // 1. Pulse extension of signals coming from wires.
10 // 2. Pretrigger for each key-wire.
11 // 3. Pattern detector if a pretrigger is found for the given key-wire.
12 // 4. Ghost Cancellation Logic (GCL).
13 // 5. Best track search and promotion.
14 // 6. Second best track search and promotion.
15 //
16 // The inputs to the ALCT Processor are wire digis.
17 // The output is up to two ALCT digi words.
18 //
19 // Author List: Benn Tannenbaum (1999), Jason Mumford (2002), Slava Valuev.
20 // Porting from ORCA by S. Valuev (Slava.Valuev@cern.ch),
21 // May 2006.
22 //
23 //
24 // Modifications:
25 //
26 //-----------------------------------------------------------------------------
27 
30 
33 #include <set>
34 
35 //-----------------
36 // Static variables
37 //-----------------
38 
39 /* This is the pattern envelope, which is used to define the collision
40  patterns A and B.
41  pattern_envelope[0][i]=layer;
42  pattern_envelope[1+MEposition][i]=key_wire offset. */
44  //Layer
45  { 0, 0, 0,
46  1, 1,
47  2,
48  3, 3,
49  4, 4, 4,
50  5, 5, 5},
51 
52  //Keywire offset for ME1 and ME2
53  {-2, -1, 0,
54  -1, 0,
55  0,
56  0, 1,
57  0, 1, 2,
58  0, 1, 2},
59 
60  //Keywire offset for ME3 and ME4
61  {2, 1, 0,
62  1, 0,
63  0,
64  0, -1,
65  0, -1, -2,
66  0, -1, -2}
67 };
68 
69 // time averaging weights for pattern (used for SLHC version)
71  //Layer
72  { 0, 1, 1,
73  1, 2,
74  2,
75  2, 1,
76  2, 1, 0,
77  1, 1, 0};
78 
79 
80 // These mask the pattern envelope to give the desired accelerator pattern
81 // and collision patterns A and B. These masks were meant to be the default
82 // ones in early 200X, but were never implemented because of limited FPGA
83 // resources.
85  // Accelerator pattern
86  {0, 0, 1,
87  0, 1,
88  1,
89  1, 0,
90  1, 0, 0,
91  1, 0, 0},
92 
93  // Collision pattern A
94  {0, 1, 0,
95  1, 1,
96  1,
97  1, 0,
98  0, 1, 0,
99  0, 1, 0},
100 
101  // Collision pattern B
102  {1, 1, 0,
103  1, 1,
104  1,
105  1, 1,
106  0, 1, 1,
107  0, 0, 1}
108 };
109 
110 // Since the test beams in 2003, both collision patterns are "completely
111 // open". This is our current default.
113  // Accelerator pattern
114  {0, 0, 1,
115  0, 1,
116  1,
117  1, 0,
118  1, 0, 0,
119  1, 0, 0},
120 
121  // Collision pattern A
122  {1, 1, 1,
123  1, 1,
124  1,
125  1, 1,
126  1, 1, 1,
127  1, 1, 1},
128 
129  // Collision pattern B
130  {1, 1, 1,
131  1, 1,
132  1,
133  1, 1,
134  1, 1, 1,
135  1, 1, 1}
136 };
137 
138 // Special option for narrow pattern for ring 1 stations
140  // Accelerator pattern
141  {0, 0, 1,
142  0, 1,
143  1,
144  1, 0,
145  1, 0, 0,
146  1, 0, 0},
147 
148  // Collision pattern A
149  {0, 1, 1,
150  1, 1,
151  1,
152  1, 0,
153  1, 1, 0,
154  1, 1, 0},
155 
156  // Collision pattern B
157  {0, 1, 1,
158  1, 1,
159  1,
160  1, 0,
161  1, 1, 0,
162  1, 1, 0}
163 };
164 
165 
166 
167 // Default values of configuration parameters.
168 const unsigned int CSCAnodeLCTProcessor::def_fifo_tbins = 16;
169 const unsigned int CSCAnodeLCTProcessor::def_fifo_pretrig = 10;
170 const unsigned int CSCAnodeLCTProcessor::def_drift_delay = 2;
171 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pretrig = 2;
172 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pattern = 4;
175 const unsigned int CSCAnodeLCTProcessor::def_trig_mode = 2; // 3?
176 const unsigned int CSCAnodeLCTProcessor::def_accel_mode = 0; // 1?
177 const unsigned int CSCAnodeLCTProcessor::def_l1a_window_width = 7; // 5?
178 
179 //----------------
180 // Constructors --
181 //----------------
182 
184  unsigned sector, unsigned subsector,
185  unsigned chamber,
186  const edm::ParameterSet& conf,
187  const edm::ParameterSet& comm) :
188  theEndcap(endcap), theStation(station), theSector(sector),
189  theSubsector(subsector), theTrigChamber(chamber) {
190  static std::atomic<bool> config_dumped{false};
191 
192  // ALCT configuration parameters.
193  fifo_tbins = conf.getParameter<unsigned int>("alctFifoTbins");
194  fifo_pretrig = conf.getParameter<unsigned int>("alctFifoPretrig");
195  drift_delay = conf.getParameter<unsigned int>("alctDriftDelay");
197  conf.getParameter<unsigned int>("alctNplanesHitPretrig");
199  conf.getParameter<unsigned int>("alctNplanesHitPattern");
201  conf.getParameter<unsigned int>("alctNplanesHitAccelPretrig");
203  conf.getParameter<unsigned int>("alctNplanesHitAccelPattern");
204  trig_mode = conf.getParameter<unsigned int>("alctTrigMode");
205  accel_mode = conf.getParameter<unsigned int>("alctAccelMode");
206  l1a_window_width = conf.getParameter<unsigned int>("alctL1aWindowWidth");
207 
208  hit_persist = conf.getParameter<unsigned int>("alctHitPersist");
209 
210  // Verbosity level, set to 0 (no print) by default.
211  infoV = conf.getParameter<int>("verbosity");
212 
213  // Other parameters.
214  // Use open pattern instead of more restrictive (slim) ones.
215  isMTCC = comm.getParameter<bool>("isMTCC");
216  // Use TMB07 flag for DAQ-2006 firmware version (implemented in late 2007).
217  isTMB07 = comm.getParameter<bool>("isTMB07");
218 
219  // Flag for SLHC studies
220  isSLHC = comm.getParameter<bool>("isSLHC");
221 
222  // special configuration parameters for ME11 treatment
223  disableME1a = comm.getParameter<bool>("disableME1a");
224 
225  // separate handle for early time bins
226  early_tbins = conf.getParameter<int>("alctEarlyTbins");
227  if (early_tbins<0) early_tbins = fifo_pretrig - CSCConstants::ALCT_EMUL_TIME_OFFSET;
228 
229  // delta BX time depth for ghostCancellationLogic
230  ghost_cancellation_bx_depth = conf.getParameter<int>("alctGhostCancellationBxDepth");
231 
232  // whether to consider ALCT candidates' qualities while doing ghostCancellationLogic on +-1 wire groups
233  ghost_cancellation_side_quality = conf.getParameter<bool>("alctGhostCancellationSideQuality");
234 
235  // deadtime clocks after pretrigger (extra in addition to drift_delay)
236  pretrig_extra_deadtime = conf.getParameter<unsigned int>("alctPretrigDeadtime");
237 
238  // whether to use narrow pattern mask for the rings close to the beam
239  narrow_mask_r1 = conf.getParameter<bool>("alctNarrowMaskForR1");
240 
241  // Check and print configuration parameters.
243  if ((infoV > 0 || isSLHC) && !config_dumped) {
244  //std::cout<<"**** ALCT constructor parameters dump ****"<<std::endl;
246  config_dumped = true;
247  }
248 
249  numWireGroups = 0; // Will be set later.
250  MESelection = (theStation < 3) ? 0 : 1;
251 
253 
256 
257  // trigger numbering doesn't distinguish between ME1a and ME1b chambers:
258  isME11 = (theStation == 1 && theRing == 1);
259 
260  // whether to calculate bx as corrected_bx instead of pretrigger one
261  use_corrected_bx = false;
262  if (isSLHC && isME11) {
263  use_corrected_bx = conf.getParameter<bool>("alctUseCorrectedBx");
264  }
265 
266  // run the ALCT processor for the Phase-II ME2/1 integrated local trigger
267  runME21ILT_ = comm.existsAs<bool>("runME21ILT")?
268  comm.getParameter<bool>("runME21ILT"):false;
269 
270  // run the ALCT processor for the Phase-II ME3/1-ME4/1 integrated local trigger
271  runME3141ILT_ = comm.existsAs<bool>("runME3141ILT")?
272  comm.getParameter<bool>("runME3141ILT"):false;
273 
274  //if (theStation==1 && theRing==2) infoV = 3;
275 
276  // Load appropriate pattern mask.
277  loadPatternMask();
278 }
279 
281  theEndcap(1), theStation(1), theSector(1),
283  // Used for debugging. -JM
284  static std::atomic<bool> config_dumped{false};
285 
286  // ALCT parameters.
288  infoV = 2;
289  isMTCC = false;
290  isTMB07 = true;
291 
292  isSLHC = false;
293  disableME1a = false;
294 
295  early_tbins = 4;
296 
297  // Check and print configuration parameters.
299  if (!config_dumped) {
300  //std::cout<<"**** ALCT default constructor parameters dump ****"<<std::endl;
302  config_dumped = true;
303  }
304 
306  MESelection = (theStation < 3) ? 0 : 1;
307 
311  isME11 = (theStation == 1 && theRing == 1);
312 
313  // Load pattern mask.
314  loadPatternMask();
315 }
316 
317 
319  // Load appropriate pattern mask.
320  for (int i_patt = 0; i_patt < CSCConstants::NUM_ALCT_PATTERNS; i_patt++) {
321  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++) {
322  if (isMTCC || isTMB07) {
323  pattern_mask[i_patt][i_wire] = pattern_mask_open[i_patt][i_wire];
324  if (narrow_mask_r1 && (theRing == 1 || theRing == 4))
325  pattern_mask[i_patt][i_wire] = pattern_mask_r1[i_patt][i_wire];
326  }
327  else {
328  pattern_mask[i_patt][i_wire] = pattern_mask_slim[i_patt][i_wire];
329  }
330  }
331  }
332 }
333 
334 
336  // Set default values for configuration parameters.
347 }
348 
349 // Set configuration parameters obtained via EventSetup mechanism.
351  static std::atomic<bool> config_dumped{false};
352 
353  fifo_tbins = conf->alctFifoTbins();
354  fifo_pretrig = conf->alctFifoPretrig();
355  drift_delay = conf->alctDriftDelay();
360  trig_mode = conf->alctTrigMode();
361  accel_mode = conf->alctAccelMode();
363 
364  // Check and print configuration parameters.
366  if (!config_dumped) {
367  //std::cout<<"**** ALCT setConfigParam parameters dump ****"<<std::endl;
369  config_dumped = true;
370  }
371 }
372 
374  // Make sure that the parameter values are within the allowed range.
375 
376  // Max expected values.
377  static const unsigned int max_fifo_tbins = 1 << 5;
378  static const unsigned int max_fifo_pretrig = 1 << 5;
379  static const unsigned int max_drift_delay = 1 << 2;
380  static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
381  static const unsigned int max_nplanes_hit_pattern = 1 << 3;
382  static const unsigned int max_nplanes_hit_accel_pretrig = 1 << 3;
383  static const unsigned int max_nplanes_hit_accel_pattern = 1 << 3;
384  static const unsigned int max_trig_mode = 1 << 2;
385  static const unsigned int max_accel_mode = 1 << 2;
386  static const unsigned int max_l1a_window_width = CSCConstants::MAX_ALCT_TBINS; // 4 bits
387 
388  // Checks.
389  if (fifo_tbins >= max_fifo_tbins) {
390  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
391  << "+++ Value of fifo_tbins, " << fifo_tbins
392  << ", exceeds max allowed, " << max_fifo_tbins-1 << " +++\n"
393  << "+++ Try to proceed with the default value, fifo_tbins="
394  << def_fifo_tbins << " +++\n";
396  }
397  if (fifo_pretrig >= max_fifo_pretrig) {
398  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
399  << "+++ Value of fifo_pretrig, " << fifo_pretrig
400  << ", exceeds max allowed, " << max_fifo_pretrig-1 << " +++\n"
401  << "+++ Try to proceed with the default value, fifo_pretrig="
402  << def_fifo_pretrig << " +++\n";
404  }
405  if (drift_delay >= max_drift_delay) {
406  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
407  << "+++ Value of drift_delay, " << drift_delay
408  << ", exceeds max allowed, " << max_drift_delay-1 << " +++\n"
409  << "+++ Try to proceed with the default value, drift_delay="
410  << def_drift_delay << " +++\n";
412  }
413  if (nplanes_hit_pretrig >= max_nplanes_hit_pretrig) {
414  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
415  << "+++ Value of nplanes_hit_pretrig, " << nplanes_hit_pretrig
416  << ", exceeds max allowed, " << max_nplanes_hit_pretrig-1 << " +++\n"
417  << "+++ Try to proceed with the default value, nplanes_hit_pretrig="
418  << nplanes_hit_pretrig << " +++\n";
419  nplanes_hit_pretrig = def_nplanes_hit_pretrig;
420  }
421  if (nplanes_hit_pattern >= max_nplanes_hit_pattern) {
422  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
423  << "+++ Value of nplanes_hit_pattern, " << nplanes_hit_pattern
424  << ", exceeds max allowed, " << max_nplanes_hit_pattern-1 << " +++\n"
425  << "+++ Try to proceed with the default value, nplanes_hit_pattern="
426  << nplanes_hit_pattern << " +++\n";
427  nplanes_hit_pattern = def_nplanes_hit_pattern;
428  }
429  if (nplanes_hit_accel_pretrig >= max_nplanes_hit_accel_pretrig) {
430  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
431  << "+++ Value of nplanes_hit_accel_pretrig, "
432  << nplanes_hit_accel_pretrig << ", exceeds max allowed, "
433  << max_nplanes_hit_accel_pretrig-1 << " +++\n"
434  << "+++ Try to proceed with the default value, "
435  << "nplanes_hit_accel_pretrig=" << nplanes_hit_accel_pretrig << " +++\n";
436  nplanes_hit_accel_pretrig = def_nplanes_hit_accel_pretrig;
437  }
438  if (nplanes_hit_accel_pattern >= max_nplanes_hit_accel_pattern) {
439  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
440  << "+++ Value of nplanes_hit_accel_pattern, "
441  << nplanes_hit_accel_pattern << ", exceeds max allowed, "
442  << max_nplanes_hit_accel_pattern-1 << " +++\n"
443  << "+++ Try to proceed with the default value, "
444  << "nplanes_hit_accel_pattern=" << nplanes_hit_accel_pattern << " +++\n";
445  nplanes_hit_accel_pattern = def_nplanes_hit_accel_pattern;
446  }
447  if (trig_mode >= max_trig_mode) {
448  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
449  << "+++ Value of trig_mode, " << trig_mode
450  << ", exceeds max allowed, " << max_trig_mode-1 << " +++\n"
451  << "+++ Try to proceed with the default value, trig_mode="
452  << trig_mode << " +++\n";
453  trig_mode = def_trig_mode;
454  }
455  if (accel_mode >= max_accel_mode) {
456  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
457  << "+++ Value of accel_mode, " << accel_mode
458  << ", exceeds max allowed, " << max_accel_mode-1 << " +++\n"
459  << "+++ Try to proceed with the default value, accel_mode="
460  << accel_mode << " +++\n";
461  accel_mode = def_accel_mode;
462  }
463  if (l1a_window_width >= max_l1a_window_width) {
464  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
465  << "+++ Value of l1a_window_width, " << l1a_window_width
466  << ", exceeds max allowed, " << max_l1a_window_width-1 << " +++\n"
467  << "+++ Try to proceed with the default value, l1a_window_width="
468  << l1a_window_width << " +++\n";
469  l1a_window_width = def_l1a_window_width;
470  }
471 }
472 
474  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
475  bestALCT[bx].clear();
476  secondALCT[bx].clear();
477  }
478 }
479 
480 void CSCAnodeLCTProcessor::clear(const int wire, const int pattern) {
481  /* Clear the data off of selected pattern */
482  if (pattern == 0) quality[wire][0] = -999;
483  else {
484  quality[wire][1] = -999;
485  quality[wire][2] = -999;
486  }
487 }
488 
489 std::vector<CSCALCTDigi>
491  // This is the main routine for normal running. It gets wire times
492  // from the wire digis and then passes them on to another run() function.
493 
494  static std::atomic<bool> config_dumped{false};
495  if ((infoV > 0 || isSLHC) && !config_dumped) {
496  //std::cout<<"**** ALCT run parameters dump ****"<<std::endl;
498  config_dumped = true;
499  }
500 
501 
502  // Get the number of wire groups for the given chamber. Do it only once
503  // per chamber.
504  if (numWireGroups == 0) {
507  CSCDetId detid(theEndcap, theStation, ring, chid, 0);
508  const auto& chamber = csc_g->chamber(detid);
509  if (chamber) {
510  numWireGroups = chamber->layer(1)->geometry()->numberOfWireGroups();
512  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
513  << "+++ Number of wire groups, " << numWireGroups
514  << " found in ME" << ((theEndcap == 1) ? "+" : "-")
515  << theStation << "/" << theRing << "/" << theChamber
516  << " (sector " << theSector << " subsector " << theSubsector
517  << " trig id. " << theTrigChamber << ")"
518  << " exceeds max expected, " << CSCConstants::MAX_NUM_WIRES
519  << " +++\n"
520  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
521  numWireGroups = -1;
522  }
523  }
524  else {
525  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
526  << "+++ ME" << ((theEndcap == 1) ? "+" : "-")
527  << theStation << "/" << theRing << "/" << theChamber
528  << " (sector " << theSector << " subsector " << theSubsector
529  << " trig id. " << theTrigChamber << ")"
530  << " is not defined in current geometry! +++\n"
531  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
532  numWireGroups = -1;
533  }
534  }
535 
536  if (numWireGroups < 0) {
537  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
538  << "+++ ME" << ((theEndcap == 1) ? "+" : "-")
539  << theStation << "/" << theRing << "/" << theChamber
540  << " (sector " << theSector << " subsector " << theSubsector
541  << " trig id. " << theTrigChamber << "):"
542  << " numWireGroups = " << numWireGroups
543  << "; ALCT emulation skipped! +++";
544  std::vector<CSCALCTDigi> emptyV;
545  return emptyV;
546  }
547 
548  // Get wire digis in this chamber from wire digi collection.
549  bool noDigis = getDigis(wiredc);
550 
551  if (!noDigis) {
552  // First get wire times from the wire digis.
553  std::vector<int>
555  readWireDigis(wire);
556 
557  // Pass an array of wire times on to another run() doing the LCT search.
558  // If the number of layers containing digis is smaller than that
559  // required to trigger, quit right away.
560  const unsigned int min_layers =
566  );
567 
568  unsigned int layersHit = 0;
569  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
570  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
571  if (!wire[i_layer][i_wire].empty()) {layersHit++; break;}
572  }
573  }
574  if (layersHit >= min_layers) run(wire);
575  }
576 
577  // Return vector of all found ALCTs.
578  std::vector<CSCALCTDigi> tmpV = getALCTs();
579  return tmpV;
580 }
581 
583  // This version of the run() function can either be called in a standalone
584  // test, being passed the time array, or called by the run() function above.
585  // It gets wire times from an input array and then loops over the keywires.
586  // All found LCT candidates are sorted and the best two are retained.
587 
588  bool trigger = false;
589 
590  // Check if there are any in-time hits and do the pulse extension.
591  bool chamber_empty = pulseExtension(wire);
592 
593  // Only do the rest of the processing if chamber is not empty.
594  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
595  // not have a full set of hits to start pattern search anyway.
596  unsigned int stop_bx = fifo_tbins - drift_delay;
597  if (!chamber_empty) {
598  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
599  unsigned int start_bx = 0;
600  // Allow for more than one pass over the hits in the time window.
601  while (start_bx < stop_bx) {
602  if (preTrigger(i_wire, start_bx)) {
603  if (infoV > 2) showPatterns(i_wire);
604  if (patternDetection(i_wire)) {
605  trigger = true;
606  break;
607  }
608  else {
609  // Assume that the earliest time when another pre-trigger can
610  // occur in case pattern detection failed is bx_pretrigger+4:
611  // this seems to match the data.
612  start_bx = first_bx[i_wire] + drift_delay + pretrig_extra_deadtime;
613  }
614  }
615  else {
616  break;
617  }
618  }
619  }
620  }
621 
622  // Do the rest only if there is at least one trigger candidate.
623  if (trigger) {
625  else ghostCancellationLogic();
626  lctSearch();
627  }
628 }
629 
631  // Routine for getting digis and filling digiV vector.
632  bool noDigis = true;
633 
634  // Loop over layers and save wire digis on each one into digiV[layer].
635  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
636  digiV[i_layer].clear();
637 
638  CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer+1);
639  getDigis(wiredc, detid);
640 
641  // If this is ME1/1, fetch digis in corresponding ME1/A (ring=4) as well.
642  if (isME11 && !disableME1a) {
643  CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer+1);
644  getDigis(wiredc, detid_me1a);
645  }
646 
647  if (!digiV[i_layer].empty()) {
648  noDigis = false;
649  if (infoV > 1) {
650  LogTrace("CSCAnodeLCTProcessor")
651  << "found " << digiV[i_layer].size()
652  << " wire digi(s) in layer " << i_layer << " of ME"
653  << ((theEndcap == 1) ? "+" : "-") << theStation << "/" << theRing
654  << "/" << theChamber << " (trig. sector " << theSector
655  << " subsector " << theSubsector << " id " << theTrigChamber << ")";
656  for (std::vector<CSCWireDigi>::iterator pld = digiV[i_layer].begin();
657  pld != digiV[i_layer].end(); pld++) {
658  LogTrace("CSCAnodeLCTProcessor") << " " << (*pld);
659  }
660  }
661  }
662  }
663 
664  return noDigis;
665 }
666 
668  const CSCDetId& id) {
669  const CSCWireDigiCollection::Range rwired = wiredc->get(id);
670  for (CSCWireDigiCollection::const_iterator digiIt = rwired.first;
671  digiIt != rwired.second; ++digiIt) {
672  digiV[id.layer()-1].push_back(*digiIt);
673  }
674 }
675 
677  /* Gets wire times from the wire digis and fills wire[][] vector */
678 
679  // Loop over all 6 layers.
680  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
681  // Loop over all digis in the layer and find the wireGroup and bx
682  // time for each.
683  for (std::vector<CSCWireDigi>::iterator pld = digiV[i_layer].begin();
684  pld != digiV[i_layer].end(); pld++) {
685  int i_wire = pld->getWireGroup()-1;
686  std::vector<int> bx_times = pld->getTimeBinsOn();
687 
688  // Check that the wires and times are appropriate.
689  if (i_wire < 0 || i_wire >= numWireGroups) {
690  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
691  << "+++ Found wire digi with wrong wire number = " << i_wire
692  << " (max wires = " << numWireGroups << "); skipping it... +++\n";
693  continue;
694  }
695  // Accept digis in expected time window. Total number of time
696  // bins in DAQ readout is given by fifo_tbins, which thus
697  // determines the maximum length of time interval. Anode raw
698  // hits in DAQ readout start (fifo_pretrig - 6) clocks before
699  // L1Accept. If times earlier than L1Accept were recorded, we
700  // use them since they can modify the ALCTs found later, via
701  // ghost-cancellation logic.
702  int last_time = -999;
703  if (bx_times.size() == fifo_tbins) {
704  wire[i_layer][i_wire].push_back(0);
705  wire[i_layer][i_wire].push_back(6);
706  }
707  else {
708  for (unsigned int i = 0; i < bx_times.size(); i++) {
709  // Find rising edge change
710  if (i > 0 && bx_times[i] == (bx_times[i-1]+1)) continue;
711  if (bx_times[i] < static_cast<int>(fifo_tbins)) {
712  if (infoV > 2) LogTrace("CSCAnodeLCTProcessor")
713  << "Digi on layer " << i_layer << " wire " << i_wire
714  << " at time " << bx_times[i];
715 
716  // Finally save times of hit wires. One shot module will
717  // not restart if a new pulse comes before the expiration
718  // of the 6-bx period.
719  if (last_time < 0 || ((bx_times[i]-last_time) >= 6) ) {
720  wire[i_layer][i_wire].push_back(bx_times[i]);
721  last_time = bx_times[i];
722  }
723  }
724  else {
725  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
726  << "+++ Skipping wire digi: wire = " << i_wire
727  << " layer = " << i_layer << ", bx = " << bx_times[i] << " +++";
728  }
729  }
730  }
731  }
732  }
733 }
734 
736  /* A pulse array will be used as a bit representation of hit times.
737  For example: if a keywire has a bx_time of 3, then 1 shifted
738  left 3 will be bit pattern 0000000000001000. Bits are then added to
739  signify the duration of a signal (hit_persist, formerly bx_width). So
740  for the pulse with a hit_persist of 6 will look like 0000000111111000. */
741 
742  bool chamber_empty = true;
743  int i_wire, i_layer, digi_num;
744  const unsigned int bits_in_pulse = 8*sizeof(pulse[0][0]);
745 
746  for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
747  for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
748  pulse[i_layer][i_wire] = 0;
749  }
750  first_bx[i_wire] = -999;
751  first_bx_corrected[i_wire] = -999;
752  for (int j = 0; j < 3; j++) quality[i_wire][j] = -999;
753  }
754 
755  for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++){
756  digi_num = 0;
757  for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
758  if (!wire[i_layer][i_wire].empty()) {
759  std::vector<int> bx_times = wire[i_layer][i_wire];
760  for (unsigned int i = 0; i < bx_times.size(); i++) {
761  // Check that min and max times are within the allowed range.
762  if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
763  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
764  << "+++ BX time of wire digi (wire = " << i_wire
765  << " layer = " << i_layer << ") bx = " << bx_times[i]
766  << " is not within the range (0-" << bits_in_pulse
767  << "] allowed for pulse extension. Skip this digi! +++\n";
768  continue;
769  }
770 
771  // Found at least one in-time digi; set chamber_empty to false
772  if (chamber_empty) chamber_empty = false;
773 
774  // make the pulse
775  for (unsigned int bx = bx_times[i];
776  bx < (bx_times[i] + hit_persist); bx++)
777  pulse[i_layer][i_wire] = pulse[i_layer][i_wire] | (1 << bx);
778 
779  // Debug information.
780  if (infoV > 1) {
781  LogTrace("CSCAnodeLCTProcessor")
782  << "Wire digi: layer " << i_layer
783  << " digi #" << ++digi_num << " wire group " << i_wire
784  << " time " << bx_times[i];
785  if (infoV > 2) {
786  std::ostringstream strstrm;
787  for (int i = 1; i <= 32; i++) {
788  strstrm << ((pulse[i_layer][i_wire]>>(32-i)) & 1);
789  }
790  LogTrace("CSCAnodeLCTProcessor") << " Pulse: " << strstrm.str();
791  }
792  }
793  }
794  }
795  }
796  }
797 
798  if (infoV > 1 && !chamber_empty) {
799  dumpDigis(wire);
800  }
801 
802  return chamber_empty;
803 }
804 
805 bool CSCAnodeLCTProcessor::preTrigger(const int key_wire, const int start_bx) {
806  /* Check that there are nplanes_hit_pretrig or more layers hit in collision
807  or accelerator patterns for a particular key_wire. If so, return
808  true and the PatternDetection process will start. */
809 
810  unsigned int layers_hit;
811  bool hit_layer[CSCConstants::NUM_LAYERS];
812  int this_layer, this_wire;
813  // If nplanes_hit_accel_pretrig is 0, the firmware uses the value
814  // of nplanes_hit_pretrig instead.
815  const unsigned int nplanes_hit_pretrig_acc =
818  const unsigned int pretrig_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
819  nplanes_hit_pretrig_acc, nplanes_hit_pretrig, nplanes_hit_pretrig
820  };
821 
822  // Loop over bx times, accelerator and collision patterns to
823  // look for pretrigger.
824  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
825  // not have a full set of hits to start pattern search anyway.
826  unsigned int stop_bx = fifo_tbins - drift_delay;
827  for (unsigned int bx_time = start_bx; bx_time < stop_bx; bx_time++) {
828  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
829  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
830  hit_layer[i_layer] = false;
831  layers_hit = 0;
832 
833  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++){
834  if (pattern_mask[i_pattern][i_wire] != 0){
835  this_layer = pattern_envelope[0][i_wire];
836  this_wire = pattern_envelope[1+MESelection][i_wire]+key_wire;
837  if ((this_wire >= 0) && (this_wire < numWireGroups)){
838  // Perform bit operation to see if pulse is 1 at a certain bx_time.
839  if (((pulse[this_layer][this_wire] >> bx_time) & 1) == 1) {
840  // Store number of layers hit.
841  if (hit_layer[this_layer] == false){
842  hit_layer[this_layer] = true;
843  layers_hit++;
844  }
845 
846  // See if number of layers hit is greater than or equal to
847  // pretrig_thresh.
848  if (layers_hit >= pretrig_thresh[i_pattern]) {
849  first_bx[key_wire] = bx_time;
850  if (infoV > 1) {
851  LogTrace("CSCAnodeLCTProcessor")
852  << "Pretrigger was satisfied for wire: " << key_wire
853  << " pattern: " << i_pattern
854  << " bx_time: " << bx_time;
855  }
856  return true;
857  }
858  }
859  }
860  }
861  }
862  }
863  }
864  // If the pretrigger was never satisfied, then return false.
865  return false;
866 }
867 
868 bool CSCAnodeLCTProcessor::patternDetection(const int key_wire) {
869  /* See if there is a pattern that satisfies nplanes_hit_pattern number of
870  layers hit for either the accelerator or collision patterns. Use
871  the pattern with the best quality. */
872 
873  bool trigger = false;
874  bool hit_layer[CSCConstants::NUM_LAYERS];
875  unsigned int temp_quality;
876  int this_layer, this_wire, delta_wire;
877  // If nplanes_hit_accel_pattern is 0, the firmware uses the value
878  // of nplanes_hit_pattern instead.
879  const unsigned int nplanes_hit_pattern_acc =
882  const unsigned int pattern_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
883  nplanes_hit_pattern_acc, nplanes_hit_pattern, nplanes_hit_pattern
884  };
885  const std::string ptn_label[] = {"Accelerator", "CollisionA", "CollisionB"};
886 
887  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++){
888  temp_quality = 0;
889  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
890  hit_layer[i_layer] = false;
891 
892  double num_pattern_hits=0., times_sum=0.;
893  std::multiset<int> mset_for_median;
894  mset_for_median.clear();
895 
896  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++){
897  if (pattern_mask[i_pattern][i_wire] != 0){
898  this_layer = pattern_envelope[0][i_wire];
899  delta_wire = pattern_envelope[1+MESelection][i_wire];
900  this_wire = delta_wire + key_wire;
901  if ((this_wire >= 0) && (this_wire < numWireGroups)){
902 
903  // Wait a drift_delay time later and look for layers hit in
904  // the pattern.
905  if ( ( (pulse[this_layer][this_wire] >>
906  (first_bx[key_wire] + drift_delay)) & 1) == 1) {
907 
908  // If layer has never had a hit before, then increment number
909  // of layer hits.
910  if (hit_layer[this_layer] == false){
911  temp_quality++;
912  // keep track of which layers already had hits.
913  hit_layer[this_layer] = true;
914  if (infoV > 1)
915  LogTrace("CSCAnodeLCTProcessor")
916  << "bx_time: " << first_bx[key_wire]
917  << " pattern: " << i_pattern << " keywire: " << key_wire
918  << " layer: " << this_layer
919  << " quality: " << temp_quality;
920  }
921 
922  // for averaged time use only the closest WGs around the key WG
923  if (abs(delta_wire)<2) {
924  // find at what bx did pulse on this wire&layer start
925  // use hit_pesrist constraint on how far back we can go
926  int first_bx_layer = first_bx[key_wire] + drift_delay;
927  for (unsigned int dbx=0; dbx<hit_persist; dbx++) {
928  if (((pulse[this_layer][this_wire] >> (first_bx_layer-1)) & 1) == 1) first_bx_layer--;
929  else break;
930  }
931  times_sum += (double)first_bx_layer;
932  num_pattern_hits += 1.;
933  mset_for_median.insert(first_bx_layer);
934  if (infoV > 2)
935  LogTrace("CSCAnodeLCTProcessor")
936  <<" 1st bx in layer: "<<first_bx_layer
937  <<" sum bx: "<<times_sum
938  <<" #pat. hits: "<<num_pattern_hits;
939  }
940  }
941  }
942  }
943  }
944 
945  // calculate median
946  const int sz = mset_for_median.size();
947  if (sz > 0) {
948  std::multiset<int>::iterator im = mset_for_median.begin();
949  if (sz > 1) std::advance(im,sz/2-1);
950  if (sz == 1) first_bx_corrected[key_wire] = *im;
951  else if ((sz % 2) == 1) first_bx_corrected[key_wire] = *(++im);
952  else first_bx_corrected[key_wire] = ((*im) + (*(++im)))/2;
953 
954 #if defined(EDM_ML_DEBUG)
955  if (infoV > 1) {
956  auto lt = LogTrace("CSCAnodeLCTProcessor") <<"bx="<<first_bx[key_wire]<<" bx_cor="<< first_bx_corrected[key_wire]<<" bxset=";
957  for (im = mset_for_median.begin(); im != mset_for_median.end(); im++) {
958  lt<<" "<<*im;
959  }
960  }
961 #endif
962  }
963 
964  if (temp_quality >= pattern_thresh[i_pattern]) {
965  trigger = true;
966 
967  if (!isTMB07) {
968  // Quality reported by the pattern detector is defined as the number
969  // of the layers hit in a pattern minus (pattern_thresh-1) value.
970  temp_quality -= (pattern_thresh[i_pattern]-1);
971  }
972  else {
973  // Quality definition changed on 22 June 2007: it no longer depends
974  // on pattern_thresh.
975  int Q;
976  // hack to run the Phase-II ME2/1, ME3/1 and ME4/1 ILT
977  if (temp_quality == 3 and (runME21ILT_ or runME3141ILT_)) Q = 4;
978  else if (temp_quality > 3) Q = temp_quality - 3;
979  else Q = 0; // quality code 0 is valid!
980  temp_quality = Q;
981  }
982 
983  if (i_pattern == 0) {
984  // Accelerator pattern
985  quality[key_wire][0] = temp_quality;
986  }
987  else {
988  // Only one collision pattern (of the best quality) is reported
989  if (static_cast<int>(temp_quality) > quality[key_wire][1]) {
990  quality[key_wire][1] = temp_quality;
991  quality[key_wire][2] = i_pattern-1;
992  }
993  }
994  if (infoV > 1) {
995  LogTrace("CSCAnodeLCTProcessor")
996  << "Pattern found; keywire: " << key_wire
997  << " type: " << ptn_label[i_pattern]
998  << " quality: " << temp_quality << "\n";
999  }
1000  }
1001  }
1002  if (infoV > 1 && quality[key_wire][1] > 0) {
1003  if (quality[key_wire][2] == 0)
1004  LogTrace("CSCAnodeLCTProcessor")
1005  << "Collision Pattern A is chosen" << "\n";
1006  else if (quality[key_wire][2] == 1)
1007  LogTrace("CSCAnodeLCTProcessor")
1008  << "Collision Pattern B is chosen" << "\n";
1009  }
1010  return trigger;
1011 }
1012 
1014  /* This function looks for LCTs on the previous and next wires. If one
1015  exists and it has a better quality and a bx_time up to 4 clocks earlier
1016  than the present, then the present LCT is cancelled. The present LCT
1017  also gets cancelled if it has the same quality as the one on the
1018  previous wire (this has not been done in 2003 test beam). The
1019  cancellation is done separately for collision and accelerator patterns. */
1020 
1021  int ghost_cleared[CSCConstants::MAX_NUM_WIRES][2];
1022 
1023  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
1024  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
1025  ghost_cleared[key_wire][i_pattern] = 0;
1026 
1027  // Non-empty wire group.
1028  int qual_this = quality[key_wire][i_pattern];
1029  if (qual_this > 0) {
1030 
1031  // Previous wire.
1032  int qual_prev = (key_wire > 0) ? quality[key_wire-1][i_pattern] : 0;
1033  if (qual_prev > 0) {
1034  int dt = first_bx[key_wire] - first_bx[key_wire-1];
1035  // Cancel this wire
1036  // 1) If the candidate at the previous wire is at the same bx
1037  // clock and has better quality (or equal quality - this has
1038  // been implemented only in 2004).
1039  // 2) If the candidate at the previous wire is up to 4 clocks
1040  // earlier, regardless of quality.
1041  if (dt == 0) {
1042  if (qual_prev >= qual_this) ghost_cleared[key_wire][i_pattern] = 1;
1043  }
1044  else if (dt > 0 && dt <= ghost_cancellation_bx_depth ) {
1045  // Next "if" check accounts for firmware bug and should be
1046  // removed once the next firmware version is used.
1047  // The bug is fixed in 5/5/2008 version of ALCT firmware,
1048  // which is used in all chambers starting with 26/05/2008.
1051  (qual_prev > qual_this) )
1052  ghost_cleared[key_wire][i_pattern] = 1;
1053  }
1054  }
1055 
1056  // Next wire.
1057  // Skip this step if this wire is already declared "ghost".
1058  if (ghost_cleared[key_wire][i_pattern] == 1) {
1059  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1060  << ((i_pattern == 0) ? "Accelerator" : "Collision")
1061  << " pattern ghost cancelled on key_wire " << key_wire <<" q="<<qual_this
1062  << " by wire " << key_wire-1<<" q="<<qual_prev;
1063  continue;
1064  }
1065 
1066  int qual_next =
1067  (key_wire < numWireGroups-1) ? quality[key_wire+1][i_pattern] : 0;
1068  if (qual_next > 0) {
1069  int dt = first_bx[key_wire] - first_bx[key_wire+1];
1070  // Same cancellation logic as for the previous wire.
1071  if (dt == 0) {
1072  if (qual_next > qual_this) ghost_cleared[key_wire][i_pattern] = 1;
1073  }
1074  else if (dt > 0 && dt <= ghost_cancellation_bx_depth ) {
1075  // Next "if" check accounts for firmware bug and should be
1076  // removed once the next firmware version is used.
1077  // The bug is fixed in 5/5/2008 version of ALCT firmware,
1078  // which is used in all chambers starting with 26/05/2008.
1081  (qual_next >= qual_this) )
1082  ghost_cleared[key_wire][i_pattern] = 1;
1083  }
1084  }
1085  if (ghost_cleared[key_wire][i_pattern] == 1) {
1086  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1087  << ((i_pattern == 0) ? "Accelerator" : "Collision")
1088  << " pattern ghost cancelled on key_wire " << key_wire <<" q="<<qual_this
1089  << " by wire " << key_wire+1<<" q="<<qual_next;
1090  continue;
1091  }
1092  }
1093  }
1094  }
1095 
1096  // All cancellation is done in parallel, so wiregroups do not know what
1097  // their neighbors are cancelling.
1098  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
1099  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
1100  if (ghost_cleared[key_wire][i_pattern] > 0) {
1101  clear(key_wire, i_pattern);
1102  }
1103  }
1104  }
1105 }
1106 
1107 
1109  /* This function looks for LCTs on the previous and next wires. If one
1110  exists and it has a better quality and a bx_time up to
1111  ghost_cancellation_bx_depth clocks earlier than the present,
1112  then the present LCT is cancelled. The present LCT
1113  also gets cancelled if it has the same quality as the one on the
1114  previous wire (this has not been done in 2003 test beam). The
1115  cancellation is done separately for collision and accelerator patterns. */
1116 
1117  int ghost_cleared[CSCConstants::MAX_NUM_WIRES][2];
1118 
1119  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
1120  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
1121  ghost_cleared[key_wire][i_pattern] = 0;
1122 
1123  // Non-empty wire group.
1124  int qual_this = quality[key_wire][i_pattern];
1125  if (qual_this > 0) {
1126 
1127  if (runME21ILT_ or runME3141ILT_) qual_this = (qual_this & 0x03);
1128  // Previous wire.
1129  int dt = -1;
1130  int qual_prev = (key_wire > 0) ? quality[key_wire-1][i_pattern] : 0;
1131  if (qual_prev > 0) {
1132  if (use_corrected_bx)
1133  dt = first_bx_corrected[key_wire] - first_bx_corrected[key_wire-1];
1134  else
1135  dt = first_bx[key_wire] - first_bx[key_wire-1];
1136  // hack to run the Phase-II ME2/1, ME3/1 and ME4/1 ILT
1137  if (runME21ILT_ or runME3141ILT_) qual_prev = (qual_prev & 0x03);
1138 
1139  // Cancel this wire
1140  // 1) If the candidate at the previous wire is at the same bx
1141  // clock and has better quality (or equal? quality - this has
1142  // been implemented only in 2004).
1143  // 2) If the candidate at the previous wire is up to 4 clocks
1144  // earlier, regardless of quality.
1145  if (dt == 0) {
1146  if (qual_prev > qual_this) ghost_cleared[key_wire][i_pattern] = 1;
1147  }
1148  else if (dt > 0 && dt <= ghost_cancellation_bx_depth ) {
1149  // Next "if" check accounts for firmware bug and should be
1150  // removed once the next firmware version is used.
1151  // The bug is fixed in 5/5/2008 version of ALCT firmware,
1152  // which is used in all chambers starting with 26/05/2008.
1155  (qual_prev > qual_this) )
1156  ghost_cleared[key_wire][i_pattern] = 1;
1157  }
1158  }
1159 
1160  // Next wire.
1161  // Skip this step if this wire is already declared "ghost".
1162  if (ghost_cleared[key_wire][i_pattern] == 1) {
1163  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1164  << ((i_pattern == 0) ? "Accelerator" : "Collision")
1165  << " pattern ghost cancelled on key_wire " << key_wire <<" q="<<qual_this
1166  << " by wire " << key_wire-1<<" q="<<qual_prev<<" dt="<<dt;
1167  continue;
1168  }
1169 
1170  dt = -1;
1171  int qual_next =
1172  (key_wire < numWireGroups-1) ? quality[key_wire+1][i_pattern] : 0;
1173  if (qual_next > 0) {
1174  if (use_corrected_bx)
1175  dt = first_bx_corrected[key_wire] - first_bx_corrected[key_wire+1];
1176  else
1177  dt = first_bx[key_wire] - first_bx[key_wire+1];
1178  // hack to run the Phase-II ME2/1, ME3/1 and ME4/1 ILT
1179  if (runME21ILT_ or runME3141ILT_)
1180  qual_next = (qual_next & 0x03);
1181  // Same cancellation logic as for the previous wire.
1182  if (dt == 0) {
1183  if (qual_next >= qual_this) ghost_cleared[key_wire][i_pattern] = 1;
1184  }
1185  else if (dt > 0 && dt <= ghost_cancellation_bx_depth ) {
1186  // Next "if" check accounts for firmware bug and should be
1187  // removed once the next firmware version is used.
1188  // The bug is fixed in 5/5/2008 version of ALCT firmware,
1189  // which is used in all chambers starting with 26/05/2008.
1192  (qual_next >= qual_this) )
1193  ghost_cleared[key_wire][i_pattern] = 1;
1194  }
1195  }
1196  if (ghost_cleared[key_wire][i_pattern] == 1) {
1197  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1198  << ((i_pattern == 0) ? "Accelerator" : "Collision")
1199  << " pattern ghost cancelled on key_wire " << key_wire <<" q="<<qual_this
1200  << " by wire " << key_wire+1<<" q="<<qual_next<<" dt="<<dt;
1201  continue;
1202  }
1203  }
1204  }
1205  }
1206 
1207  // All cancellation is done in parallel, so wiregroups do not know what
1208  // their neighbors are cancelling.
1209  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
1210  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
1211  if (ghost_cleared[key_wire][i_pattern] > 0) {
1212  clear(key_wire, i_pattern);
1213  }
1214  }
1215  }
1216 }
1217 
1218 
1220  // First modify the quality according accel_mode, then store all
1221  // of the valid LCTs in an array.
1222  std::vector<CSCALCTDigi> lct_list;
1223 
1224  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1225  // If there is either accelerator or collision, perform trigMode
1226  // function before storing and sorting.
1227  if (quality[i_wire][0] > 0 || quality[i_wire][1] > 0) {
1228  trigMode(i_wire);
1229 
1230  int bx = first_bx[i_wire];
1231  int fbx = first_bx_corrected[i_wire];
1232  if (infoV>1) LogTrace("CSCAnodeLCTProcessor")<<" bx="<<bx<<" fbx="<<fbx;
1233  if (use_corrected_bx) {
1234  bx = fbx;
1235  fbx = first_bx[i_wire];
1236  }
1237  if (infoV>1) LogTrace("CSCAnodeLCTProcessor")<<" bx="<<bx<<" fbx="<<fbx;
1238  // Store any valid accelerator pattern LCTs.
1239  if (quality[i_wire][0] > 0) {
1240  int qual = (quality[i_wire][0] & 0x03); // 2 LSBs
1241  CSCALCTDigi lct_info(1, qual, 1, 0, i_wire, bx);
1242  lct_info.setFullBX(fbx);
1243  lct_list.push_back(lct_info);
1244  }
1245 
1246  // Store any valid collision pattern LCTs.
1247  if (quality[i_wire][1] > 0) {
1248  int qual = (quality[i_wire][1] & 0x03); // 2 LSBs
1249  CSCALCTDigi lct_info(1, qual, 0, quality[i_wire][2], i_wire, bx);
1250  //lct_info.setFullBX(fbx); // uncomment if one wants, e.g., to keep corrected time here
1251  lct_list.push_back(lct_info);
1252  if (infoV>1) LogTrace("CSCAnodeLCTProcessor")<<" got lct_info: "<<lct_info;
1253  }
1254 
1255  // Modify qualities according to accel_mode parameter.
1256  accelMode(i_wire);
1257  }
1258  }
1259 
1260  // Best track selector selects two collision and two accelerator ALCTs
1261  // with the best quality per time bin.
1262  std::vector<CSCALCTDigi> fourBest = bestTrackSelector(lct_list);
1263 
1264  if (infoV > 0) {
1265  int n_alct_all=0, n_alct=0;
1266  for (std::vector <CSCALCTDigi>::const_iterator plct = lct_list.begin(); plct != lct_list.end(); plct++)
1267  if (plct->isValid() && plct->getBX()==6) n_alct_all++;
1268  for (std::vector <CSCALCTDigi>::const_iterator plct = fourBest.begin(); plct != fourBest.end(); plct++)
1269  if (plct->isValid() && plct->getBX()==6) n_alct++;
1270 
1271  LogTrace("CSCAnodeLCTProcessor")<<"alct_count E:"<<theEndcap<<"S:"<<theStation<<"R:"<<theRing<<"C:"<<theChamber
1272  <<" all "<<n_alct_all<<" found "<<n_alct;
1273  }
1274 
1275  // Select two best of four per time bin, based on quality and
1276  // accel_mode parameter.
1277  for (std::vector<CSCALCTDigi>::const_iterator plct = fourBest.begin();
1278  plct != fourBest.end(); plct++) {
1279 
1280  int bx = plct->getBX();
1281  if (bx >= CSCConstants::MAX_ALCT_TBINS) {
1282  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeALCT")
1283  << "+++ Bx of ALCT candidate, " << bx << ", exceeds max allowed, "
1284  << CSCConstants::MAX_ALCT_TBINS-1 << "; skipping it... +++\n";
1285  continue;
1286  }
1287 
1288  if (isBetterALCT(*plct, bestALCT[bx])) {
1289  if (isBetterALCT(bestALCT[bx], secondALCT[bx])) {
1290  secondALCT[bx] = bestALCT[bx];
1291  }
1292  bestALCT[bx] = *plct;
1293  }
1294  else if (isBetterALCT(*plct, secondALCT[bx])) {
1295  secondALCT[bx] = *plct;
1296  }
1297  }
1298 
1299  if (!isTMB07) {
1300  // Prior to DAQ-2006 format, only ALCTs at the earliest bx were reported.
1302  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1303  if (bestALCT[bx].isValid()) {
1304  first_bx = bx;
1305  break;
1306  }
1307  }
1308  if (first_bx < CSCConstants::MAX_ALCT_TBINS) {
1309  for (int bx = first_bx + 1; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1310  if (bestALCT[bx].isValid()) bestALCT[bx].clear();
1311  if (secondALCT[bx].isValid()) secondALCT[bx].clear();
1312  }
1313  }
1314  }
1315 
1316  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1317  if (bestALCT[bx].isValid()) {
1318  bestALCT[bx].setTrknmb(1);
1319  if (infoV > 0) {
1320  LogDebug("CSCAnodeLCTProcessor")
1321  << "\n" << bestALCT[bx] << " fullBX = "<<bestALCT[bx].getFullBX()
1322  << " found in ME"
1323  << ((theEndcap == 1) ? "+" : "-")
1324  << theStation << "/" << theRing << "/" << theChamber
1325  << " (sector " << theSector << " subsector " << theSubsector
1326  << " trig id. " << theTrigChamber << ")" << "\n";
1327  }
1328  if (secondALCT[bx].isValid()) {
1329  secondALCT[bx].setTrknmb(2);
1330  if (infoV > 0) {
1331  LogDebug("CSCAnodeLCTProcessor")
1332  << secondALCT[bx] << " fullBX = "<<secondALCT[bx].getFullBX()
1333  << " found in ME"
1334  << ((theEndcap == 1) ? "+" : "-")
1335  << theStation << "/" << theRing << "/" << theChamber
1336  << " (sector " << theSector << " subsector " << theSubsector
1337  << " trig id. " << theTrigChamber << ")" << "\n";
1338  }
1339  }
1340  }
1341  }
1342 }
1343 
1345  const std::vector<CSCALCTDigi>& all_alcts) {
1346  /* Selects two collision and two accelerator ALCTs per time bin with
1347  the best quality. */
1349 
1350  if (infoV > 1) {
1351  LogTrace("CSCAnodeLCTProcessor") << all_alcts.size() <<
1352  " ALCTs at the input of best-track selector: ";
1353  for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
1354  plct != all_alcts.end(); plct++) {
1355  if (!plct->isValid()) continue;
1356  LogTrace("CSCAnodeLCTProcessor") << (*plct);
1357  }
1358  }
1359 
1361  for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
1362  plct != all_alcts.end(); plct++) {
1363  if (!plct->isValid()) continue;
1364 
1365  // Select two collision and two accelerator ALCTs with the highest
1366  // quality at every bx. The search for best ALCTs is done in parallel
1367  // for collision and accelerator patterns, and simultaneously for
1368  // two ALCTs, tA and tB. If two or more ALCTs have equal qualities,
1369  // the priority is given to the ALCT with larger wiregroup number
1370  // in the search for tA (collision and accelerator), and to the ALCT
1371  // with smaller wiregroup number in the search for tB.
1372  int bx = (*plct).getBX();
1373  int accel = (*plct).getAccelerator();
1374  int qual = (*plct).getQuality();
1375  int wire = (*plct).getKeyWG();
1376  bool vA = tA[bx][accel].isValid();
1377  bool vB = tB[bx][accel].isValid();
1378  int qA = tA[bx][accel].getQuality();
1379  int qB = tB[bx][accel].getQuality();
1380  int wA = tA[bx][accel].getKeyWG();
1381  int wB = tB[bx][accel].getKeyWG();
1382  if (!vA || qual > qA || (qual == qA && wire > wA)) {
1383  tA[bx][accel] = *plct;
1384  }
1385  if (!vB || qual > qB || (qual == qB && wire < wB)) {
1386  tB[bx][accel] = *plct;
1387  }
1388  }
1389 
1390  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1391  for (int accel = 0; accel <= 1; accel++) {
1392  // Best ALCT is always tA.
1393  if (tA[bx][accel].isValid()) {
1394  if (infoV > 2) {
1395  LogTrace("CSCAnodeLCTProcessor") << "tA: " << tA[bx][accel];
1396  LogTrace("CSCAnodeLCTProcessor") << "tB: " << tB[bx][accel];
1397  }
1398  bestALCTs[bx][accel] = tA[bx][accel];
1399 
1400  // If tA exists, tB exists too.
1401  if (tA[bx][accel] != tB[bx][accel] &&
1402  tA[bx][accel].getQuality() == tB[bx][accel].getQuality()) {
1403  secondALCTs[bx][accel] = tB[bx][accel];
1404  }
1405  else {
1406  // Funny part: if tA and tB are the same, or the quality of tB
1407  // is inferior to the quality of tA, the second best ALCT is
1408  // not tB. Instead it is the largest-wiregroup ALCT among those
1409  // ALCT whose qualities are lower than the quality of the best one.
1410  for (std::vector <CSCALCTDigi>::const_iterator plct =
1411  all_alcts.begin(); plct != all_alcts.end(); plct++) {
1412  if ((*plct).isValid() &&
1413  (*plct).getAccelerator() == accel && (*plct).getBX() == bx &&
1414  (*plct).getQuality() < bestALCTs[bx][accel].getQuality() &&
1415  (*plct).getQuality() >= secondALCTs[bx][accel].getQuality() &&
1416  (*plct).getKeyWG() >= secondALCTs[bx][accel].getKeyWG()) {
1417  secondALCTs[bx][accel] = *plct;
1418  }
1419  }
1420  }
1421  }
1422  }
1423  }
1424 
1425  // Fill the vector with up to four best ALCTs per bx and return it.
1426  std::vector<CSCALCTDigi> fourBest;
1427  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1428  for (int i = 0; i < 2; i++) {
1429  if (bestALCTs[bx][i].isValid()) fourBest.push_back(bestALCTs[bx][i]);
1430  }
1431  for (int i = 0; i < 2; i++) {
1432  if (secondALCTs[bx][i].isValid()) fourBest.push_back(secondALCTs[bx][i]);
1433  }
1434  }
1435 
1436  if (infoV > 1) {
1437  LogTrace("CSCAnodeLCTProcessor") << fourBest.size() << " ALCTs selected: ";
1438  for (std::vector<CSCALCTDigi>::const_iterator plct = fourBest.begin();
1439  plct != fourBest.end(); plct++) {
1440  LogTrace("CSCAnodeLCTProcessor") << (*plct);
1441  }
1442  }
1443 
1444  return fourBest;
1445 }
1446 
1448  const CSCALCTDigi& rhsALCT) {
1449  /* This method should have been an overloaded > operator, but we
1450  have to keep it here since need to check values in quality[][]
1451  array modified according to accel_mode parameter. */
1452  bool returnValue = false;
1453 
1454  if (lhsALCT.isValid() && !rhsALCT.isValid()) {return true;}
1455 
1456  // ALCTs found at earlier bx times are ranked higher than ALCTs found at
1457  // later bx times regardless of the quality.
1458  if (lhsALCT.getBX() < rhsALCT.getBX()) {returnValue = true;}
1459  if (lhsALCT.getBX() != rhsALCT.getBX()) {return returnValue;}
1460 
1461  // First check the quality of ALCTs.
1462  int qual1 = lhsALCT.getQuality();
1463  int qual2 = rhsALCT.getQuality();
1464  if (qual1 > qual2) {returnValue = true;}
1465  // If qualities are the same, check accelerator bits of both ALCTs.
1466  // If they are not the same, rank according to accel_mode value.
1467  // If they are the same, keep the track selector assignment.
1468  else if (qual1 == qual2 &&
1469  lhsALCT.getAccelerator() != rhsALCT.getAccelerator() &&
1470  quality[lhsALCT.getKeyWG()][1-lhsALCT.getAccelerator()] >
1471  quality[rhsALCT.getKeyWG()][1-rhsALCT.getAccelerator()])
1472  {returnValue = true;}
1473 
1474  return returnValue;
1475 }
1476 
1477 void CSCAnodeLCTProcessor::trigMode(const int key_wire) {
1478  /* Function which enables/disables either collision or accelerator tracks.
1479  The function uses the trig_mode parameter to decide. */
1480 
1481  switch(trig_mode) {
1482  default:
1483  case 0:
1484  // Enables both collision and accelerator tracks
1485  break;
1486  case 1:
1487  // Disables collision tracks
1488  if (quality[key_wire][1] > 0) {
1489  quality[key_wire][1] = 0;
1490  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1491  << "trigMode(): collision track " << key_wire << " disabled" << "\n";
1492  }
1493  break;
1494  case 2:
1495  // Disables accelerator tracks
1496  if (quality[key_wire][0] > 0) {
1497  quality[key_wire][0] = 0;
1498  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1499  << "trigMode(): accelerator track " << key_wire << " disabled" << "\n";
1500  }
1501  break;
1502  case 3:
1503  // Disables collision track if there is an accelerator track found
1504  // in the same wire group at the same time
1505  if (quality[key_wire][0] > 0 && quality[key_wire][1] > 0) {
1506  quality[key_wire][1] = 0;
1507  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1508  << "trigMode(): collision track " << key_wire << " disabled" << "\n";
1509  }
1510  break;
1511  }
1512 }
1513 
1514 void CSCAnodeLCTProcessor::accelMode(const int key_wire) {
1515  /* Function which gives a preference either to the collision patterns
1516  or accelerator patterns. The function uses the accel_mode parameter
1517  to decide. */
1518  int promotionBit = 1 << 2;
1519 
1520  switch(accel_mode) {
1521  default:
1522  case 0:
1523  // Ignore accelerator muons.
1524  if (quality[key_wire][0] > 0) {
1525  quality[key_wire][0] = 0;
1526  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1527  << "alctMode(): accelerator track " << key_wire << " ignored" << "\n";
1528  }
1529  break;
1530  case 1:
1531  // Prefer collision muons by adding promotion bit.
1532  if (quality[key_wire][1] > 0) {
1533  quality[key_wire][1] += promotionBit;
1534  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1535  << "alctMode(): collision track " << key_wire << " promoted" << "\n";
1536  }
1537  break;
1538  case 2:
1539  // Prefer accelerator muons by adding promotion bit.
1540  if (quality[key_wire][0] > 0) {
1541  quality[key_wire][0] += promotionBit;
1542  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1543  << "alctMode(): accelerator track " << key_wire << " promoted"<< "\n";
1544  }
1545  break;
1546  case 3:
1547  // Ignore collision muons.
1548  if (quality[key_wire][1] > 0) {
1549  quality[key_wire][1] = 0;
1550  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1551  << "alctMode(): collision track " << key_wire << " ignored" << "\n";
1552  }
1553  break;
1554  }
1555 }
1556 
1557 // Dump of configuration parameters.
1559  std::ostringstream strm;
1560  strm << "\n";
1561  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1562  strm << "+ ALCT configuration parameters: +\n";
1563  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1564  strm << " fifo_tbins [total number of time bins in DAQ readout] = "
1565  << fifo_tbins << "\n";
1566  strm << " fifo_pretrig [start time of anode raw hits in DAQ readout] = "
1567  << fifo_pretrig << "\n";
1568  strm << " drift_delay [drift delay after pre-trigger, in 25 ns bins] = "
1569  << drift_delay << "\n";
1570  strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = "
1571  << nplanes_hit_pretrig << "\n";
1572  strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = "
1573  << nplanes_hit_pattern << "\n";
1574  strm << " nplanes_hit_accel_pretrig [min. number of layers hit for accel."
1575  << " pre-trig.] = " << nplanes_hit_accel_pretrig << "\n";
1576  strm << " nplanes_hit_accel_pattern [min. number of layers hit for accel."
1577  << " trigger] = " << nplanes_hit_accel_pattern << "\n";
1578  strm << " trig_mode [enabling/disabling collision/accelerator tracks] = "
1579  << trig_mode << "\n";
1580  strm << " accel_mode [preference to collision/accelerator tracks] = "
1581  << accel_mode << "\n";
1582  strm << " l1a_window_width [L1Accept window width, in 25 ns bins] = "
1583  << l1a_window_width << "\n";
1584  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1585  LogDebug("CSCAnodeLCTProcessor") << strm.str();
1586  //std::cout<<strm.str()<<std::endl;
1587 }
1588 
1589 // Dump of digis on wire groups.
1591  LogDebug("CSCAnodeLCTProcessor")
1592  << "ME" << ((theEndcap == 1) ? "+" : "-")
1593  << theStation << "/" << theRing << "/" << theChamber
1594  << " nWiregroups " << numWireGroups;
1595 
1596  std::ostringstream strstrm;
1597  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1598  if (i_wire%10 == 0) {
1599  if (i_wire < 100) strstrm << i_wire/10;
1600  else strstrm << (i_wire-100)/10;
1601  }
1602  else strstrm << " ";
1603  }
1604  strstrm << "\n";
1605  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1606  strstrm << i_wire%10;
1607  }
1608  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1609  strstrm << "\n";
1610  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1611  if (!wire[i_layer][i_wire].empty()) {
1612  std::vector<int> bx_times = wire[i_layer][i_wire];
1613  strstrm << std::hex << bx_times[0] << std::dec;
1614  }
1615  else {
1616  strstrm << ".";
1617  }
1618  }
1619  }
1620  LogTrace("CSCAnodeLCTProcessor") << strstrm.str();
1621 }
1622 
1623 // Returns vector of read-out ALCTs, if any. Starts with the vector of
1624 // all found ALCTs and selects the ones in the read-out time window.
1625 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::readoutALCTs() {
1626  std::vector<CSCALCTDigi> tmpV;
1627 
1628  // The number of LCT bins in the read-out is given by the
1629  // l1a_window_width parameter, but made even by setting the LSB of
1630  // l1a_window_width to 0.
1631  const int lct_bins =
1632  // (l1a_window_width%2 == 0) ? l1a_window_width : l1a_window_width-1;
1634  static std::atomic<int> late_tbins{early_tbins + lct_bins};
1635 
1636  static std::atomic<int> ifois{0};
1637  if (ifois == 0) {
1638 
1639  //std::cout<<"ALCT early_tbins="<<early_tbins<<" lct_bins="<<lct_bins<<" l1a_window_width="<<l1a_window_width<<" late_tbins="<<late_tbins<<std::endl;
1640  //std::cout<<"**** ALCT readoutALCTs config dump ****"<<std::endl;
1641  //dumpConfigParams();
1642 
1643  if (infoV >= 0 && early_tbins < 0) {
1644  edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
1645  << "+++ fifo_pretrig = " << fifo_pretrig
1646  << "; in-time ALCTs are not getting read-out!!! +++" << "\n";
1647  }
1648 
1649  if (late_tbins > CSCConstants::MAX_ALCT_TBINS-1) {
1650  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
1651  << "+++ Allowed range of time bins, [0-" << late_tbins
1652  << "] exceeds max allowed, " << CSCConstants::MAX_ALCT_TBINS-1 << " +++\n"
1653  << "+++ Set late_tbins to max allowed +++\n";
1654  late_tbins = CSCConstants::MAX_ALCT_TBINS-1;
1655  }
1656  ifois = 1;
1657  }
1658 
1659  // Start from the vector of all found ALCTs and select those within
1660  // the ALCT*L1A coincidence window.
1661  std::vector<CSCALCTDigi> all_alcts = getALCTs();
1662  for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
1663  plct != all_alcts.end(); plct++) {
1664  if (!plct->isValid()) continue;
1665 
1666  int bx = (*plct).getBX();
1667  // Skip ALCTs found too early relative to L1Accept.
1668  if (bx <= early_tbins) {
1669  if (infoV > 1) LogDebug("CSCAnodeLCTProcessor")
1670  << " Do not report ALCT on keywire " << plct->getKeyWG()
1671  << ": found at bx " << bx << ", whereas the earliest allowed bx is "
1672  << early_tbins+1;
1673  continue;
1674  }
1675 
1676  // Skip ALCTs found too late relative to L1Accept.
1677  if (bx > late_tbins) {
1678  if (infoV > 1) LogDebug("CSCAnodeLCTProcessor")
1679  << " Do not report ALCT on keywire " << plct->getKeyWG()
1680  << ": found at bx " << bx << ", whereas the latest allowed bx is "
1681  << late_tbins;
1682  continue;
1683  }
1684 
1685  tmpV.push_back(*plct);
1686  }
1687 
1688  // shift the BX from 8 to 3
1689  // ALCTs in real data have the central BX in bin 3
1690  // which is the middle of the 7BX wide L1A window
1691  // ALCTs used in the TMB emulator have central BX at bin 8
1692  // but right before we put emulated ALCTs in the event, we shift the BX
1693  // by -5 to make sure they are compatible with real data ALCTs!
1694  for (auto& p : tmpV){
1695  p.setBX(p.getBX() - (CSCConstants::LCT_CENTRAL_BX - l1a_window_width/2));
1696  }
1697  return tmpV;
1698 }
1699 
1700 // Returns vector of all found ALCTs, if any. Used in ALCT-CLCT matching.
1701 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::getALCTs() {
1702  std::vector<CSCALCTDigi> tmpV;
1703  for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1704  if (bestALCT[bx].isValid()) tmpV.push_back(bestALCT[bx]);
1705  if (secondALCT[bx].isValid()) tmpV.push_back(secondALCT[bx]);
1706  }
1707  return tmpV;
1708 }
1709 
1712 
1713 void CSCAnodeLCTProcessor::showPatterns(const int key_wire) {
1714  /* Method to test the pretrigger */
1715  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS;
1716  i_pattern++) {
1717  std::ostringstream strstrm_header;
1718  LogTrace("CSCAnodeLCTProcessor")
1719  << "\n" << "Pattern: " << i_pattern << " Key wire: " << key_wire;
1720  for (int i = 1; i <= 32; i++) {
1721  strstrm_header << ((32-i)%10);
1722  }
1723  LogTrace("CSCAnodeLCTProcessor") << strstrm_header.str();
1724  for (int i_wire = 0; i_wire < CSCConstants::MAX_WIRES_IN_PATTERN; i_wire++) {
1725  if (pattern_mask[i_pattern][i_wire] != 0) {
1726  std::ostringstream strstrm_pulse;
1727  int this_layer = pattern_envelope[0][i_wire];
1728  int this_wire = pattern_envelope[1+MESelection][i_wire]+key_wire;
1729  if (this_wire >= 0 && this_wire < numWireGroups) {
1730  for (int i = 1; i <= 32; i++) {
1731  strstrm_pulse << ((pulse[this_layer][this_wire]>>(32-i)) & 1);
1732  }
1733  LogTrace("CSCAnodeLCTProcessor")
1734  << strstrm_pulse.str() << " on layer " << this_layer;
1735  }
1736  }
1737  }
1738  LogTrace("CSCAnodeLCTProcessor")
1739  << "-------------------------------------------";
1740  }
1741 }
#define LogDebug(id)
static const int time_weights[CSCConstants::MAX_WIRES_IN_PATTERN]
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])
bool existsAs(std::string const &parameterName, bool trackiness=true) const
checks if a parameter exists as a given type
Definition: ParameterSet.h:186
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
bool getDigis(const CSCWireDigiCollection *wiredc)
bool isValid() const
check ALCT validity (1 - valid ALCT)
Definition: CSCALCTDigi.h:30
void clear()
clear this ALCT
Definition: CSCALCTDigi.cc:35
unsigned int alctNplanesHitPretrig() const
void setConfigParameters(const CSCDBL1TPParameters *conf)
void trigMode(const int key_wire)
static int ringFromTriggerLabels(int station, int triggerCSCID)
static const unsigned int def_accel_mode
unsigned int alctL1aWindowWidth() const
int getFullBX() const
return 12-bit full BX.
Definition: CSCALCTDigi.h:75
static const int pattern_envelope[CSCConstants::NUM_ALCT_PATTERNS][CSCConstants::MAX_WIRES_IN_PATTERN]
static const unsigned int def_nplanes_hit_accel_pretrig
static const unsigned int def_fifo_pretrig
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
void accelMode(const int key_wire)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int pattern_mask[CSCConstants::NUM_ALCT_PATTERNS][CSCConstants::MAX_WIRES_IN_PATTERN]
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:63
CSCALCTDigi secondALCT[CSCConstants::MAX_ALCT_TBINS]
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:36
bool isBetterALCT(const CSCALCTDigi &lhsALCT, const CSCALCTDigi &rhsALCT)
unsigned int alctAccelMode() const
static const unsigned int def_trig_mode
int getAccelerator() const
Definition: CSCALCTDigi.h:43
static const unsigned int def_nplanes_hit_accel_pattern
unsigned int alctFifoPretrig() const
std::vector< CSCALCTDigi > readoutALCTs()
const CSCGeometry * csc_g
unsigned int alctNplanesHitAccelPretrig() const
const CSCChamber * chamber(CSCDetId id) const
Return the chamber corresponding to given DetId.
Definition: CSCGeometry.cc:118
std::vector< CSCWireDigi >::const_iterator const_iterator
unsigned int alctNplanesHitAccelPattern() const
std::vector< CSCALCTDigi > bestTrackSelector(const std::vector< CSCALCTDigi > &all_alcts)
#define begin
Definition: vmac.h:32
CSCALCTDigi bestALCT[CSCConstants::MAX_ALCT_TBINS]
int first_bx[CSCConstants::MAX_NUM_WIRES]
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:72
void setFullBX(const uint16_t fullbx)
Set 12-bit full BX.
Definition: CSCALCTDigi.h:78
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:57
std::vector< CSCWireDigi > digiV[CSCConstants::NUM_LAYERS]
static int chamberFromTriggerLabels(int TriggerSector, int TriggerSubSector, int station, int TriggerCSCID)
static const int pattern_mask_slim[CSCConstants::NUM_ALCT_PATTERNS][CSCConstants::MAX_WIRES_IN_PATTERN]
std::vector< CSCALCTDigi > getALCTs()
static const unsigned int def_nplanes_hit_pretrig
unsigned int nplanes_hit_accel_pretrig
unsigned int alctFifoTbins() const