CMS 3D CMS Logo

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