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