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 // $Date: 2010/08/04 10:21:20 $
24 // $Revision: 1.41 $
25 //
26 // Modifications:
27 //
28 //-----------------------------------------------------------------------------
29 
33 
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 // These mask the pattern envelope to give the desired accelerator pattern
71 // and collision patterns A and B. These masks were meant to be the default
72 // ones in early 200X, but were never implemented because of limited FPGA
73 // resources.
75  // Accelerator pattern
76  {0, 0, 1,
77  0, 1,
78  1,
79  1, 0,
80  1, 0, 0,
81  1, 0, 0},
82 
83  // Collision pattern A
84  {0, 1, 0,
85  1, 1,
86  1,
87  1, 0,
88  0, 1, 0,
89  0, 1, 0},
90 
91  // Collision pattern B
92  {1, 1, 0,
93  1, 1,
94  1,
95  1, 1,
96  0, 1, 1,
97  0, 0, 1}
98 };
99 
100 // Since the test beams in 2003, both collision patterns are "completely
101 // open". This is our current default.
103  // Accelerator pattern
104  {0, 0, 1,
105  0, 1,
106  1,
107  1, 0,
108  1, 0, 0,
109  1, 0, 0},
110 
111  // Collision pattern A
112  {1, 1, 1,
113  1, 1,
114  1,
115  1, 1,
116  1, 1, 1,
117  1, 1, 1},
118 
119  // Collision pattern B
120  {1, 1, 1,
121  1, 1,
122  1,
123  1, 1,
124  1, 1, 1,
125  1, 1, 1}
126 };
127 
128 // Default values of configuration parameters.
129 const unsigned int CSCAnodeLCTProcessor::def_fifo_tbins = 16;
130 const unsigned int CSCAnodeLCTProcessor::def_fifo_pretrig = 10;
131 const unsigned int CSCAnodeLCTProcessor::def_drift_delay = 2;
132 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pretrig = 2;
133 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pattern = 4;
136 const unsigned int CSCAnodeLCTProcessor::def_trig_mode = 2; // 3?
137 const unsigned int CSCAnodeLCTProcessor::def_accel_mode = 0; // 1?
138 const unsigned int CSCAnodeLCTProcessor::def_l1a_window_width = 7; // 5?
139 
140 //----------------
141 // Constructors --
142 //----------------
143 
145  unsigned sector, unsigned subsector,
146  unsigned chamber,
147  const edm::ParameterSet& conf,
148  const edm::ParameterSet& comm) :
149  theEndcap(endcap), theStation(station), theSector(sector),
150  theSubsector(subsector), theTrigChamber(chamber) {
151  static bool config_dumped = false;
152 
153  // ALCT configuration parameters.
154  fifo_tbins = conf.getParameter<unsigned int>("alctFifoTbins");
155  fifo_pretrig = conf.getParameter<unsigned int>("alctFifoPretrig");
156  drift_delay = conf.getParameter<unsigned int>("alctDriftDelay");
158  conf.getParameter<unsigned int>("alctNplanesHitPretrig");
160  conf.getParameter<unsigned int>("alctNplanesHitPattern");
162  conf.getParameter<unsigned int>("alctNplanesHitAccelPretrig");
164  conf.getParameter<unsigned int>("alctNplanesHitAccelPattern");
165  trig_mode = conf.getParameter<unsigned int>("alctTrigMode");
166  accel_mode = conf.getParameter<unsigned int>("alctAccelMode");
167  l1a_window_width = conf.getParameter<unsigned int>("alctL1aWindowWidth");
168 
169  // Verbosity level, set to 0 (no print) by default.
170  infoV = conf.getUntrackedParameter<int>("verbosity", 0);
171 
172  // Other parameters.
173  // Use open pattern instead of more restrictive (slim) ones.
174  isMTCC = comm.getParameter<bool>("isMTCC");
175  // Use TMB07 flag for DAQ-2006 firmware version (implemented in late 2007).
176  isTMB07 = comm.getParameter<bool>("isTMB07");
177 
178  // Check and print configuration parameters.
180  if (infoV > 0 && !config_dumped) {
182  config_dumped = true;
183  }
184 
185  numWireGroups = 0; // Will be set later.
186  MESelection = (theStation < 3) ? 0 : 1;
187 
188  // Load appropriate pattern mask.
189  for (int i_patt = 0; i_patt < CSCConstants::NUM_ALCT_PATTERNS; i_patt++) {
190  for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++) {
191  if (isMTCC || isTMB07) {
192  pattern_mask[i_patt][i_wire] = pattern_mask_open[i_patt][i_wire];
193  }
194  else {
195  pattern_mask[i_patt][i_wire] = pattern_mask_slim[i_patt][i_wire];
196  }
197  }
198  }
199 }
200 
202  theEndcap(1), theStation(1), theSector(1),
203  theSubsector(1), theTrigChamber(1) {
204  // Used for debugging. -JM
205  static bool config_dumped = false;
206 
207  // ALCT parameters.
209  infoV = 2;
210  isMTCC = false;
211  isTMB07 = true;
212 
213  // Check and print configuration parameters.
215  if (!config_dumped) {
217  config_dumped = true;
218  }
219 
221  MESelection = (theStation < 3) ? 0 : 1;
222 
223  // Load default pattern mask.
224  for (int i_patt = 0; i_patt < CSCConstants::NUM_ALCT_PATTERNS; i_patt++) {
225  for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++) {
226  pattern_mask[i_patt][i_wire] = pattern_mask_open[i_patt][i_wire];
227  }
228  }
229 }
230 
232  // Set default values for configuration parameters.
243 }
244 
245 // Set configuration parameters obtained via EventSetup mechanism.
247  static bool config_dumped = false;
248 
249  fifo_tbins = conf->alctFifoTbins();
250  fifo_pretrig = conf->alctFifoPretrig();
251  drift_delay = conf->alctDriftDelay();
256  trig_mode = conf->alctTrigMode();
257  accel_mode = conf->alctAccelMode();
259 
260  // Check and print configuration parameters.
262  if (!config_dumped) {
264  config_dumped = true;
265  }
266 }
267 
269  // Make sure that the parameter values are within the allowed range.
270 
271  // Max expected values.
272  static const unsigned int max_fifo_tbins = 1 << 5;
273  static const unsigned int max_fifo_pretrig = 1 << 5;
274  static const unsigned int max_drift_delay = 1 << 2;
275  static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
276  static const unsigned int max_nplanes_hit_pattern = 1 << 3;
277  static const unsigned int max_nplanes_hit_accel_pretrig = 1 << 3;
278  static const unsigned int max_nplanes_hit_accel_pattern = 1 << 3;
279  static const unsigned int max_trig_mode = 1 << 2;
280  static const unsigned int max_accel_mode = 1 << 2;
281  static const unsigned int max_l1a_window_width = MAX_ALCT_BINS; // 4 bits
282 
283  // Checks.
284  if (fifo_tbins >= max_fifo_tbins) {
285  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
286  << "+++ Value of fifo_tbins, " << fifo_tbins
287  << ", exceeds max allowed, " << max_fifo_tbins-1 << " +++\n"
288  << "+++ Try to proceed with the default value, fifo_tbins="
289  << def_fifo_tbins << " +++\n";
291  }
292  if (fifo_pretrig >= max_fifo_pretrig) {
293  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
294  << "+++ Value of fifo_pretrig, " << fifo_pretrig
295  << ", exceeds max allowed, " << max_fifo_pretrig-1 << " +++\n"
296  << "+++ Try to proceed with the default value, fifo_pretrig="
297  << def_fifo_pretrig << " +++\n";
299  }
300  if (drift_delay >= max_drift_delay) {
301  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
302  << "+++ Value of drift_delay, " << drift_delay
303  << ", exceeds max allowed, " << max_drift_delay-1 << " +++\n"
304  << "+++ Try to proceed with the default value, drift_delay="
305  << def_drift_delay << " +++\n";
307  }
308  if (nplanes_hit_pretrig >= max_nplanes_hit_pretrig) {
309  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
310  << "+++ Value of nplanes_hit_pretrig, " << nplanes_hit_pretrig
311  << ", exceeds max allowed, " << max_nplanes_hit_pretrig-1 << " +++\n"
312  << "+++ Try to proceed with the default value, nplanes_hit_pretrig="
313  << nplanes_hit_pretrig << " +++\n";
314  nplanes_hit_pretrig = def_nplanes_hit_pretrig;
315  }
316  if (nplanes_hit_pattern >= max_nplanes_hit_pattern) {
317  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
318  << "+++ Value of nplanes_hit_pattern, " << nplanes_hit_pattern
319  << ", exceeds max allowed, " << max_nplanes_hit_pattern-1 << " +++\n"
320  << "+++ Try to proceed with the default value, nplanes_hit_pattern="
321  << nplanes_hit_pattern << " +++\n";
322  nplanes_hit_pattern = def_nplanes_hit_pattern;
323  }
324  if (nplanes_hit_accel_pretrig >= max_nplanes_hit_accel_pretrig) {
325  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
326  << "+++ Value of nplanes_hit_accel_pretrig, "
327  << nplanes_hit_accel_pretrig << ", exceeds max allowed, "
328  << max_nplanes_hit_accel_pretrig-1 << " +++\n"
329  << "+++ Try to proceed with the default value, "
330  << "nplanes_hit_accel_pretrig=" << nplanes_hit_accel_pretrig << " +++\n";
331  nplanes_hit_accel_pretrig = def_nplanes_hit_accel_pretrig;
332  }
333  if (nplanes_hit_accel_pattern >= max_nplanes_hit_accel_pattern) {
334  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
335  << "+++ Value of nplanes_hit_accel_pattern, "
336  << nplanes_hit_accel_pattern << ", exceeds max allowed, "
337  << max_nplanes_hit_accel_pattern-1 << " +++\n"
338  << "+++ Try to proceed with the default value, "
339  << "nplanes_hit_accel_pattern=" << nplanes_hit_accel_pattern << " +++\n";
340  nplanes_hit_accel_pattern = def_nplanes_hit_accel_pattern;
341  }
342  if (trig_mode >= max_trig_mode) {
343  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
344  << "+++ Value of trig_mode, " << trig_mode
345  << ", exceeds max allowed, " << max_trig_mode-1 << " +++\n"
346  << "+++ Try to proceed with the default value, trig_mode="
347  << trig_mode << " +++\n";
348  trig_mode = def_trig_mode;
349  }
350  if (accel_mode >= max_accel_mode) {
351  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
352  << "+++ Value of accel_mode, " << accel_mode
353  << ", exceeds max allowed, " << max_accel_mode-1 << " +++\n"
354  << "+++ Try to proceed with the default value, accel_mode="
355  << accel_mode << " +++\n";
356  accel_mode = def_accel_mode;
357  }
358  if (l1a_window_width >= max_l1a_window_width) {
359  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
360  << "+++ Value of l1a_window_width, " << l1a_window_width
361  << ", exceeds max allowed, " << max_l1a_window_width-1 << " +++\n"
362  << "+++ Try to proceed with the default value, l1a_window_width="
363  << l1a_window_width << " +++\n";
364  l1a_window_width = def_l1a_window_width;
365  }
366 }
367 
369  for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
370  bestALCT[bx].clear();
371  secondALCT[bx].clear();
372  }
373 }
374 
375 void CSCAnodeLCTProcessor::clear(const int wire, const int pattern) {
376  /* Clear the data off of selected pattern */
377  if (pattern == 0) quality[wire][0] = -999;
378  else {
379  quality[wire][1] = -999;
380  quality[wire][2] = -999;
381  }
382 }
383 
384 std::vector<CSCALCTDigi>
386  // This is the main routine for normal running. It gets wire times
387  // from the wire digis and then passes them on to another run() function.
388 
389  // clear(); // redundant; called by L1MuCSCMotherboard.
390 
391  // Get the number of wire groups for the given chamber. Do it only once
392  // per chamber.
393  if (numWireGroups == 0) {
395  CSCChamber* theChamber = theGeom->chamber(theEndcap, theStation, theSector,
397  if (theChamber) {
398  numWireGroups = theChamber->layer(1)->geometry()->numberOfWireGroups();
400  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
401  << "+++ Number of wire groups, " << numWireGroups
402  << " found in ME" << ((theEndcap == 1) ? "+" : "-")
403  << theStation << "/"
405  theTrigChamber) << "/"
408  << " (sector " << theSector << " subsector " << theSubsector
409  << " trig id. " << theTrigChamber << ")"
410  << " exceeds max expected, " << CSCConstants::MAX_NUM_WIRES
411  << " +++\n"
412  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
413  numWireGroups = -1;
414  }
415  }
416  else {
417  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
418  << "+++ ME" << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
420  theTrigChamber) << "/"
423  << " (sector " << theSector << " subsector " << theSubsector
424  << " trig id. " << theTrigChamber << ")"
425  << " is not defined in current geometry! +++\n"
426  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
427  numWireGroups = -1;
428  }
429  }
430 
431  if (numWireGroups < 0) {
432  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
433  << "+++ ME" << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
435  theTrigChamber) << "/"
438  << " (sector " << theSector << " subsector " << theSubsector
439  << " trig id. " << theTrigChamber << "):"
440  << " numWireGroups = " << numWireGroups
441  << "; ALCT emulation skipped! +++";
442  std::vector<CSCALCTDigi> emptyV;
443  return emptyV;
444  }
445 
446  // Get wire digis in this chamber from wire digi collection.
447  bool noDigis = getDigis(wiredc);
448 
449  if (!noDigis) {
450  // First get wire times from the wire digis.
451  std::vector<int>
453  readWireDigis(wire);
454 
455  // Pass an array of wire times on to another run() doing the LCT search.
456  // If the number of layers containing digis is smaller than that
457  // required to trigger, quit right away.
458  const unsigned int min_layers =
462 
463  unsigned int layersHit = 0;
464  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
465  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
466  if (!wire[i_layer][i_wire].empty()) {layersHit++; break;}
467  }
468  }
469  if (layersHit >= min_layers) run(wire);
470  }
471 
472  // Return vector of all found ALCTs.
473  std::vector<CSCALCTDigi> tmpV = getALCTs();
474  return tmpV;
475 }
476 
478  // This version of the run() function can either be called in a standalone
479  // test, being passed the time array, or called by the run() function above.
480  // It gets wire times from an input array and then loops over the keywires.
481  // All found LCT candidates are sorted and the best two are retained.
482 
483  bool trigger = false;
484 
485  // Check if there are any in-time hits and do the pulse extension.
486  bool chamber_empty = pulseExtension(wire);
487 
488  // Only do the rest of the processing if chamber is not empty.
489  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
490  // not have a full set of hits to start pattern search anyway.
491  unsigned int stop_bx = fifo_tbins - drift_delay;
492  if (!chamber_empty) {
493  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
494  unsigned int start_bx = 0;
495  // Allow for more than one pass over the hits in the time window.
496  while (start_bx < stop_bx) {
497  if (preTrigger(i_wire, start_bx)) {
498  if (infoV > 2) showPatterns(i_wire);
499  if (patternDetection(i_wire)) {
500  trigger = true;
501  break;
502  }
503  else {
504  // Assume that the earliest time when another pre-trigger can
505  // occur in case pattern detection failed is bx_pretrigger+6:
506  // this seems to match the data.
507  start_bx = first_bx[i_wire] + drift_delay + 4;
508  }
509  }
510  else {
511  break;
512  }
513  }
514  }
515  }
516 
517  // Do the rest only if there is at least one trigger candidate.
518  if (trigger) {
520  lctSearch();
521  }
522 }
523 
525  // Routine for getting digis and filling digiV vector.
526  bool noDigis = true;
531 
532  // Loop over layers and save wire digis on each one into digiV[layer].
533  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
534  digiV[i_layer].clear();
535 
536  CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer+1);
537  getDigis(wiredc, detid);
538 
539  // If this is ME1/1, fetch digis in corresponding ME1/A (ring=4) as well.
540  if (theStation == 1 && theRing == 1) {
541  CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer+1);
542  getDigis(wiredc, detid_me1a);
543  }
544 
545  if (!digiV[i_layer].empty()) {
546  noDigis = false;
547  if (infoV > 1) {
548  LogTrace("CSCAnodeLCTProcessor")
549  << "found " << digiV[i_layer].size()
550  << " wire digi(s) in layer " << i_layer << " of ME"
551  << ((theEndcap == 1) ? "+" : "-") << theStation << "/" << theRing
552  << "/" << theChamber << " (trig. sector " << theSector
553  << " subsector " << theSubsector << " id " << theTrigChamber << ")";
554  for (std::vector<CSCWireDigi>::iterator pld = digiV[i_layer].begin();
555  pld != digiV[i_layer].end(); pld++) {
556  LogTrace("CSCAnodeLCTProcessor") << " " << (*pld);
557  }
558  }
559  }
560  }
561 
562  return noDigis;
563 }
564 
566  const CSCDetId& id) {
567  const CSCWireDigiCollection::Range rwired = wiredc->get(id);
568  for (CSCWireDigiCollection::const_iterator digiIt = rwired.first;
569  digiIt != rwired.second; ++digiIt) {
570  digiV[id.layer()-1].push_back(*digiIt);
571  }
572 }
573 
575  /* Gets wire times from the wire digis and fills wire[][] vector */
576 
577  // Loop over all 6 layers.
578  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
579  // Loop over all digis in the layer and find the wireGroup and bx
580  // time for each.
581  for (std::vector<CSCWireDigi>::iterator pld = digiV[i_layer].begin();
582  pld != digiV[i_layer].end(); pld++) {
583  int i_wire = pld->getWireGroup()-1;
584  std::vector<int> bx_times = pld->getTimeBinsOn();
585 
586  // Check that the wires and times are appropriate.
587  if (i_wire < 0 || i_wire >= numWireGroups) {
588  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
589  << "+++ Found wire digi with wrong wire number = " << i_wire
590  << " (max wires = " << numWireGroups << "); skipping it... +++\n";
591  continue;
592  }
593  // Accept digis in expected time window. Total number of time
594  // bins in DAQ readout is given by fifo_tbins, which thus
595  // determines the maximum length of time interval. Anode raw
596  // hits in DAQ readout start (fifo_pretrig - 6) clocks before
597  // L1Accept. If times earlier than L1Accept were recorded, we
598  // use them since they can modify the ALCTs found later, via
599  // ghost-cancellation logic.
600  int last_time = -999;
601  if (bx_times.size() == fifo_tbins) {
602  wire[i_layer][i_wire].push_back(0);
603  wire[i_layer][i_wire].push_back(6);
604  }
605  else {
606  for (unsigned int i = 0; i < bx_times.size(); i++) {
607  // Find rising edge change
608  if (i > 0 && bx_times[i] == (bx_times[i-1]+1)) continue;
609  if (bx_times[i] < static_cast<int>(fifo_tbins)) {
610  if (infoV > 2) LogTrace("CSCAnodeLCTProcessor")
611  << "Digi on layer " << i_layer << " wire " << i_wire
612  << " at time " << bx_times[i];
613 
614  // Finally save times of hit wires. One shot module will
615  // not restart if a new pulse comes before the expiration
616  // of the 6-bx period.
617  if (last_time < 0 || ((bx_times[i]-last_time) >= 6) ) {
618  wire[i_layer][i_wire].push_back(bx_times[i]);
619  last_time = bx_times[i];
620  }
621  }
622  else {
623  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
624  << "+++ Skipping wire digi: wire = " << i_wire
625  << " layer = " << i_layer << ", bx = " << bx_times[i] << " +++";
626  }
627  }
628  }
629  }
630  }
631 }
632 
634  /* A pulse array will be used as a bit representation of hit times.
635  For example: if a keywire has a bx_time of 3, then 1 shifted
636  left 3 will be bit pattern 0000000000001000. Bits are then added to
637  signify the duration of a signal (hit_persist, formerly bx_width). So
638  for the pulse with a hit_persist of 6 will look like 0000000111111000. */
639 
640  bool chamber_empty = true;
641  int i_wire, i_layer, digi_num;
642  static unsigned int hit_persist = 6;
643  static unsigned int bits_in_pulse = 8*sizeof(pulse[0][0]);
644 
645  for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
646  for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
647  pulse[i_layer][i_wire] = 0;
648  }
649  first_bx[i_wire] = -999;
650  for (int j = 0; j < 3; j++) quality[i_wire][j] = -999;
651  }
652 
653  for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++){
654  digi_num = 0;
655  for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
656  if (wire[i_layer][i_wire].size() > 0) {
657  std::vector<int> bx_times = wire[i_layer][i_wire];
658  for (unsigned int i = 0; i < bx_times.size(); i++) {
659  // Check that min and max times are within the allowed range.
660  if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
661  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
662  << "+++ BX time of wire digi (wire = " << i_wire
663  << " layer = " << i_layer << ") bx = " << bx_times[i]
664  << " is not within the range (0-" << bits_in_pulse
665  << "] allowed for pulse extension. Skip this digi! +++\n";
666  continue;
667  }
668 
669  // Found at least one in-time digi; set chamber_empty to false
670  if (chamber_empty) chamber_empty = false;
671 
672  // make the pulse
673  for (unsigned int bx = bx_times[i];
674  bx < (bx_times[i] + hit_persist); bx++)
675  pulse[i_layer][i_wire] = pulse[i_layer][i_wire] | (1 << bx);
676 
677  // Debug information.
678  if (infoV > 1) {
679  LogTrace("CSCAnodeLCTProcessor")
680  << "Wire digi: layer " << i_layer
681  << " digi #" << ++digi_num << " wire group " << i_wire
682  << " time " << bx_times[i];
683  if (infoV > 2) {
684  std::ostringstream strstrm;
685  for (int i = 1; i <= 32; i++) {
686  strstrm << ((pulse[i_layer][i_wire]>>(32-i)) & 1);
687  }
688  LogTrace("CSCAnodeLCTProcessor") << " Pulse: " << strstrm.str();
689  }
690  }
691  }
692  }
693  }
694  }
695 
696  if (infoV > 1 && !chamber_empty) {
697  dumpDigis(wire);
698  }
699 
700  return chamber_empty;
701 }
702 
703 bool CSCAnodeLCTProcessor::preTrigger(const int key_wire, const int start_bx) {
704  /* Check that there are nplanes_hit_pretrig or more layers hit in collision
705  or accelerator patterns for a particular key_wire. If so, return
706  true and the PatternDetection process will start. */
707 
708  unsigned int layers_hit;
709  bool hit_layer[CSCConstants::NUM_LAYERS];
710  int this_layer, this_wire;
711  // If nplanes_hit_accel_pretrig is 0, the firmware uses the value
712  // of nplanes_hit_pretrig instead.
713  const unsigned int nplanes_hit_pretrig_acc =
716  const unsigned int pretrig_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
717  nplanes_hit_pretrig_acc, nplanes_hit_pretrig, nplanes_hit_pretrig
718  };
719 
720  // Loop over bx times, accelerator and collision patterns to
721  // look for pretrigger.
722  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
723  // not have a full set of hits to start pattern search anyway.
724  unsigned int stop_bx = fifo_tbins - drift_delay;
725  for (unsigned int bx_time = start_bx; bx_time < stop_bx; bx_time++) {
726  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
727  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
728  hit_layer[i_layer] = false;
729  layers_hit = 0;
730 
731  for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++){
732  if (pattern_mask[i_pattern][i_wire] != 0){
733  this_layer = pattern_envelope[0][i_wire];
734  this_wire = pattern_envelope[1+MESelection][i_wire]+key_wire;
735  if ((this_wire >= 0) && (this_wire < numWireGroups)){
736  // Perform bit operation to see if pulse is 1 at a certain bx_time.
737  if (((pulse[this_layer][this_wire] >> bx_time) & 1) == 1) {
738  // Store number of layers hit.
739  if (hit_layer[this_layer] == false){
740  hit_layer[this_layer] = true;
741  layers_hit++;
742  }
743 
744  // See if number of layers hit is greater than or equal to
745  // pretrig_thresh.
746  if (layers_hit >= pretrig_thresh[i_pattern]) {
747  first_bx[key_wire] = bx_time;
748  if (infoV > 1) {
749  LogTrace("CSCAnodeLCTProcessor")
750  << "Pretrigger was satisfied for wire: " << key_wire
751  << " pattern: " << i_pattern
752  << " bx_time: " << bx_time;
753  }
754  return true;
755  }
756  }
757  }
758  }
759  }
760  }
761  }
762  // If the pretrigger was never satisfied, then return false.
763  return false;
764 }
765 
766 bool CSCAnodeLCTProcessor::patternDetection(const int key_wire) {
767  /* See if there is a pattern that satisfies nplanes_hit_pattern number of
768  layers hit for either the accelerator or collision patterns. Use
769  the pattern with the best quality. */
770 
771  bool trigger = false;
772  bool hit_layer[CSCConstants::NUM_LAYERS];
773  unsigned int temp_quality;
774  int this_layer, this_wire;
775  // If nplanes_hit_accel_pattern is 0, the firmware uses the value
776  // of nplanes_hit_pattern instead.
777  const unsigned int nplanes_hit_pattern_acc =
780  const unsigned int pattern_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
781  nplanes_hit_pattern_acc, nplanes_hit_pattern, nplanes_hit_pattern
782  };
783  const std::string ptn_label[] = {"Accelerator", "CollisionA", "CollisionB"};
784 
785  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++){
786  temp_quality = 0;
787  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
788  hit_layer[i_layer] = false;
789 
790  for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++){
791  if (pattern_mask[i_pattern][i_wire] != 0){
792  this_layer = pattern_envelope[0][i_wire];
793  this_wire = pattern_envelope[1+MESelection][i_wire]+key_wire;
794  if ((this_wire >= 0) && (this_wire < numWireGroups)){
795 
796  // Wait a drift_delay time later and look for layers hit in
797  // the pattern.
798  if (((pulse[this_layer][this_wire] >>
799  (first_bx[key_wire] + drift_delay)) & 1) == 1) {
800 
801  // If layer has never had a hit before, then increment number
802  // of layer hits.
803  if (hit_layer[this_layer] == false){
804  temp_quality++;
805  // keep track of which layers already had hits.
806  hit_layer[this_layer] = true;
807  if (infoV > 1)
808  LogTrace("CSCAnodeLCTProcessor")
809  << "bx_time: " << first_bx[key_wire]
810  << " pattern: " << i_pattern << " keywire: " << key_wire
811  << " layer: " << this_layer
812  << " quality: " << temp_quality;
813  }
814  }
815  }
816  }
817  }
818  if (temp_quality >= pattern_thresh[i_pattern]) {
819  trigger = true;
820 
821  if (!isTMB07) {
822  // Quality reported by the pattern detector is defined as the number
823  // of the layers hit in a pattern minus (pattern_thresh-1) value.
824  temp_quality -= (pattern_thresh[i_pattern]-1);
825  }
826  else {
827  // Quality definition changed on 22 June 2007: it no longer depends
828  // on pattern_thresh.
829  if (temp_quality > 3) temp_quality -= 3;
830  else temp_quality = 0; // quality code 0 is valid!
831  }
832 
833  if (i_pattern == 0) {
834  // Accelerator pattern
835  quality[key_wire][0] = temp_quality;
836  }
837  else {
838  // Only one collision pattern (of the best quality) is reported
839  if (static_cast<int>(temp_quality) > quality[key_wire][1]) {
840  quality[key_wire][1] = temp_quality;
841  quality[key_wire][2] = i_pattern-1;
842  }
843  }
844  if (infoV > 1) {
845  LogTrace("CSCAnodeLCTProcessor")
846  << "Pattern found; keywire: " << key_wire
847  << " type: " << ptn_label[i_pattern]
848  << " quality: " << temp_quality << "\n";
849  }
850  }
851  }
852  if (infoV > 1 && quality[key_wire][1] > 0) {
853  if (quality[key_wire][2] == 0)
854  LogTrace("CSCAnodeLCTProcessor")
855  << "Collision Pattern A is chosen" << "\n";
856  else if (quality[key_wire][2] == 1)
857  LogTrace("CSCAnodeLCTProcessor")
858  << "Collision Pattern B is chosen" << "\n";
859  }
860  return trigger;
861 }
862 
864  /* This function looks for LCTs on the previous and next wires. If one
865  exists and it has a better quality and a bx_time up to 4 clocks earlier
866  than the present, then the present LCT is cancelled. The present LCT
867  also gets cancelled if it has the same quality as the one on the
868  previous wire (this has not been done in 2003 test beam). The
869  cancellation is done separately for collision and accelerator patterns. */
870 
871  int ghost_cleared[CSCConstants::MAX_NUM_WIRES][2];
872 
873  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
874  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
875  ghost_cleared[key_wire][i_pattern] = 0;
876 
877  // Non-empty wire group.
878  int qual_this = quality[key_wire][i_pattern];
879  if (qual_this > 0) {
880 
881  // Previous wire.
882  int qual_prev = (key_wire > 0) ? quality[key_wire-1][i_pattern] : 0;
883  if (qual_prev > 0) {
884  int dt = first_bx[key_wire] - first_bx[key_wire-1];
885  // Cancel this wire
886  // 1) If the candidate at the previous wire is at the same bx
887  // clock and has better quality (or equal quality - this has
888  // been implemented only in 2004).
889  // 2) If the candidate at the previous wire is up to 4 clocks
890  // earlier, regardless of quality.
891  if (dt == 0) {
892  if (qual_prev >= qual_this) ghost_cleared[key_wire][i_pattern] = 1;
893  }
894  else if (dt > 0 && dt <= 4) {
895  // Next "if" check accounts for firmware bug and should be
896  // removed once the next firmware version is used.
897  // The bug is fixed in 5/5/2008 version of ALCT firmware,
898  // which is used in all chambers starting with 26/05/2008.
900  ghost_cleared[key_wire][i_pattern] = 1;
901  }
902  }
903 
904  // Next wire.
905  // Skip this step if this wire is already declared "ghost".
906  if (ghost_cleared[key_wire][i_pattern] == 1) {
907  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
908  << ((i_pattern == 0) ? "Accelerator" : "Collision")
909  << " pattern ghost cancelled on key_wire " << key_wire
910  << " by wire " << key_wire-1;
911  continue;
912  }
913 
914  int qual_next =
915  (key_wire < numWireGroups-1) ? quality[key_wire+1][i_pattern] : 0;
916  if (qual_next > 0) {
917  int dt = first_bx[key_wire] - first_bx[key_wire+1];
918  // Same cancellation logic as for the previous wire.
919  if (dt == 0) {
920  if (qual_next > qual_this) ghost_cleared[key_wire][i_pattern] = 1;
921  }
922  else if (dt > 0 && dt <= 4) {
923  // Next "if" check accounts for firmware bug and should be
924  // removed once the next firmware version is used.
925  // The bug is fixed in 5/5/2008 version of ALCT firmware,
926  // which is used in all chambers starting with 26/05/2008.
928  ghost_cleared[key_wire][i_pattern] = 1;
929  }
930  }
931  if (ghost_cleared[key_wire][i_pattern] == 1) {
932  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
933  << ((i_pattern == 0) ? "Accelerator" : "Collision")
934  << " pattern ghost cancelled on key_wire " << key_wire
935  << " by wire " << key_wire+1;
936  continue;
937  }
938  }
939  }
940  }
941 
942  // All cancellation is done in parallel, so wiregroups do not know what
943  // their neighbors are cancelling.
944  for (int key_wire = 0; key_wire < numWireGroups; key_wire++) {
945  for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
946  if (ghost_cleared[key_wire][i_pattern] > 0) {
947  clear(key_wire, i_pattern);
948  }
949  }
950  }
951 }
952 
954  // First modify the quality according accel_mode, then store all
955  // of the valid LCTs in an array.
956  std::vector<CSCALCTDigi> lct_list;
957 
958  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
959  // If there is either accelerator or collision, perform trigMode
960  // function before storing and sorting.
961  if (quality[i_wire][0] > 0 || quality[i_wire][1] > 0) {
962  trigMode(i_wire);
963 
964  // Store any valid accelerator pattern LCTs.
965  if (quality[i_wire][0] > 0) {
966  int qual = (quality[i_wire][0] & 0x03); // 2 LSBs
967  CSCALCTDigi lct_info(1, qual, 1, 0, i_wire, first_bx[i_wire]);
968  lct_list.push_back(lct_info);
969  }
970 
971  // Store any valid collision pattern LCTs.
972  if (quality[i_wire][1] > 0) {
973  int qual = (quality[i_wire][1] & 0x03); // 2 LSBs
974  CSCALCTDigi lct_info(1, qual, 0, quality[i_wire][2], i_wire,
975  first_bx[i_wire]);
976  lct_list.push_back(lct_info);
977  }
978 
979  // Modify qualities according to accel_mode parameter.
980  accelMode(i_wire);
981  }
982  }
983 
984  // Best track selector selects two collision and two accelerator ALCTs
985  // with the best quality per time bin.
986  std::vector<CSCALCTDigi> fourBest = bestTrackSelector(lct_list);
987 
988  // Select two best of four per time bin, based on quality and
989  // accel_mode parameter.
990  for (std::vector<CSCALCTDigi>::const_iterator plct = fourBest.begin();
991  plct != fourBest.end(); plct++) {
992 
993  int bx = plct->getBX();
994  if (bx >= MAX_ALCT_BINS) {
995  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeALCT")
996  << "+++ Bx of ALCT candidate, " << bx << ", exceeds max allowed, "
997  << MAX_ALCT_BINS-1 << "; skipping it... +++\n";
998  continue;
999  }
1000 
1001  if (isBetterALCT(*plct, bestALCT[bx])) {
1002  if (isBetterALCT(bestALCT[bx], secondALCT[bx])) {
1003  secondALCT[bx] = bestALCT[bx];
1004  }
1005  bestALCT[bx] = *plct;
1006  }
1007  else if (isBetterALCT(*plct, secondALCT[bx])) {
1008  secondALCT[bx] = *plct;
1009  }
1010  }
1011 
1012  if (!isTMB07) {
1013  // Prior to DAQ-2006 format, only ALCTs at the earliest bx were reported.
1014  int first_bx = MAX_ALCT_BINS;
1015  for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
1016  if (bestALCT[bx].isValid()) {
1017  first_bx = bx;
1018  break;
1019  }
1020  }
1021  if (first_bx < MAX_ALCT_BINS) {
1022  for (int bx = first_bx + 1; bx < MAX_ALCT_BINS; bx++) {
1023  if (bestALCT[bx].isValid()) bestALCT[bx].clear();
1024  if (secondALCT[bx].isValid()) secondALCT[bx].clear();
1025  }
1026  }
1027  }
1028 
1029  for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
1030  if (bestALCT[bx].isValid()) {
1031  bestALCT[bx].setTrknmb(1);
1032  if (infoV > 0) {
1033  LogDebug("CSCAnodeLCTProcessor")
1034  << "\n" << bestALCT[bx] << " found in ME"
1035  << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
1037  theTrigChamber) << "/"
1040  << " (sector " << theSector << " subsector " << theSubsector
1041  << " trig id. " << theTrigChamber << ")" << "\n";
1042  }
1043  if (secondALCT[bx].isValid()) {
1044  secondALCT[bx].setTrknmb(2);
1045  if (infoV > 0) {
1046  LogDebug("CSCAnodeLCTProcessor")
1047  << secondALCT[bx] << " found in ME"
1048  << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
1050  theTrigChamber) <<"/"
1053  << " (sector " << theSector << " subsector " << theSubsector
1054  << " trig id. " << theTrigChamber << ")" << "\n";
1055  }
1056  }
1057  }
1058  }
1059 }
1060 
1062  const std::vector<CSCALCTDigi>& all_alcts) {
1063  /* Selects two collision and two accelerator ALCTs per time bin with
1064  the best quality. */
1065  CSCALCTDigi bestALCTs[MAX_ALCT_BINS][2], secondALCTs[MAX_ALCT_BINS][2];
1066 
1067  if (infoV > 1) {
1068  LogTrace("CSCAnodeLCTProcessor") << all_alcts.size() <<
1069  " ALCTs at the input of best-track selector: ";
1070  for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
1071  plct != all_alcts.end(); plct++) {
1072  if (!plct->isValid()) continue;
1073  LogTrace("CSCAnodeLCTProcessor") << (*plct);
1074  }
1075  }
1076 
1077  CSCALCTDigi tA[MAX_ALCT_BINS][2], tB[MAX_ALCT_BINS][2];
1078  for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
1079  plct != all_alcts.end(); plct++) {
1080  if (!plct->isValid()) continue;
1081 
1082  // Select two collision and two accelerator ALCTs with the highest
1083  // quality at every bx. The search for best ALCTs is done in parallel
1084  // for collision and accelerator patterns, and simultaneously for
1085  // two ALCTs, tA and tB. If two or more ALCTs have equal qualities,
1086  // the priority is given to the ALCT with larger wiregroup number
1087  // in the search for tA (collision and accelerator), and to the ALCT
1088  // with smaller wiregroup number in the search for tB.
1089  int bx = (*plct).getBX();
1090  int accel = (*plct).getAccelerator();
1091  int qual = (*plct).getQuality();
1092  int wire = (*plct).getKeyWG();
1093  bool vA = tA[bx][accel].isValid();
1094  bool vB = tB[bx][accel].isValid();
1095  int qA = tA[bx][accel].getQuality();
1096  int qB = tB[bx][accel].getQuality();
1097  int wA = tA[bx][accel].getKeyWG();
1098  int wB = tB[bx][accel].getKeyWG();
1099  if (!vA || qual > qA || (qual == qA && wire > wA)) {
1100  tA[bx][accel] = *plct;
1101  }
1102  if (!vB || qual > qB || (qual == qB && wire < wB)) {
1103  tB[bx][accel] = *plct;
1104  }
1105  }
1106 
1107  for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
1108  for (int accel = 0; accel <= 1; accel++) {
1109  // Best ALCT is always tA.
1110  if (tA[bx][accel].isValid()) {
1111  if (infoV > 2) {
1112  LogTrace("CSCAnodeLCTProcessor") << "tA: " << tA[bx][accel];
1113  LogTrace("CSCAnodeLCTProcessor") << "tB: " << tB[bx][accel];
1114  }
1115  bestALCTs[bx][accel] = tA[bx][accel];
1116 
1117  // If tA exists, tB exists too.
1118  if (tA[bx][accel] != tB[bx][accel] &&
1119  tA[bx][accel].getQuality() == tB[bx][accel].getQuality()) {
1120  secondALCTs[bx][accel] = tB[bx][accel];
1121  }
1122  else {
1123  // Funny part: if tA and tB are the same, or the quality of tB
1124  // is inferior to the quality of tA, the second best ALCT is
1125  // not tB. Instead it is the largest-wiregroup ALCT among those
1126  // ALCT whose qualities are lower than the quality of the best one.
1127  for (std::vector <CSCALCTDigi>::const_iterator plct =
1128  all_alcts.begin(); plct != all_alcts.end(); plct++) {
1129  if ((*plct).isValid() &&
1130  (*plct).getAccelerator() == accel && (*plct).getBX() == bx &&
1131  (*plct).getQuality() < bestALCTs[bx][accel].getQuality() &&
1132  (*plct).getQuality() >= secondALCTs[bx][accel].getQuality() &&
1133  (*plct).getKeyWG() >= secondALCTs[bx][accel].getKeyWG()) {
1134  secondALCTs[bx][accel] = *plct;
1135  }
1136  }
1137  }
1138  }
1139  }
1140  }
1141 
1142  // Fill the vector with up to four best ALCTs per bx and return it.
1143  std::vector<CSCALCTDigi> fourBest;
1144  for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
1145  for (int i = 0; i < 2; i++) {
1146  if (bestALCTs[bx][i].isValid()) fourBest.push_back(bestALCTs[bx][i]);
1147  }
1148  for (int i = 0; i < 2; i++) {
1149  if (secondALCTs[bx][i].isValid()) fourBest.push_back(secondALCTs[bx][i]);
1150  }
1151  }
1152 
1153  if (infoV > 1) {
1154  LogTrace("CSCAnodeLCTProcessor") << fourBest.size() << " ALCTs selected: ";
1155  for (std::vector<CSCALCTDigi>::const_iterator plct = fourBest.begin();
1156  plct != fourBest.end(); plct++) {
1157  LogTrace("CSCAnodeLCTProcessor") << (*plct);
1158  }
1159  }
1160 
1161  return fourBest;
1162 }
1163 
1165  const CSCALCTDigi& rhsALCT) {
1166  /* This method should have been an overloaded > operator, but we
1167  have to keep it here since need to check values in quality[][]
1168  array modified according to accel_mode parameter. */
1169  bool returnValue = false;
1170 
1171  if (lhsALCT.isValid() && !rhsALCT.isValid()) {return true;}
1172 
1173  // ALCTs found at earlier bx times are ranked higher than ALCTs found at
1174  // later bx times regardless of the quality.
1175  if (lhsALCT.getBX() < rhsALCT.getBX()) {returnValue = true;}
1176  if (lhsALCT.getBX() != rhsALCT.getBX()) {return returnValue;}
1177 
1178  // First check the quality of ALCTs.
1179  int qual1 = lhsALCT.getQuality();
1180  int qual2 = rhsALCT.getQuality();
1181  if (qual1 > qual2) {returnValue = true;}
1182  // If qualities are the same, check accelerator bits of both ALCTs.
1183  // If they are not the same, rank according to accel_mode value.
1184  // If they are the same, keep the track selector assignment.
1185  else if (qual1 == qual2 &&
1186  lhsALCT.getAccelerator() != rhsALCT.getAccelerator() &&
1187  quality[lhsALCT.getKeyWG()][1-lhsALCT.getAccelerator()] >
1188  quality[rhsALCT.getKeyWG()][1-rhsALCT.getAccelerator()])
1189  {returnValue = true;}
1190 
1191  return returnValue;
1192 }
1193 
1194 void CSCAnodeLCTProcessor::trigMode(const int key_wire) {
1195  /* Function which enables/disables either collision or accelerator tracks.
1196  The function uses the trig_mode parameter to decide. */
1197 
1198  switch(trig_mode) {
1199  default:
1200  case 0:
1201  // Enables both collision and accelerator tracks
1202  break;
1203  case 1:
1204  // Disables collision tracks
1205  if (quality[key_wire][1] > 0) {
1206  quality[key_wire][1] = 0;
1207  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1208  << "trigMode(): collision track " << key_wire << " disabled" << "\n";
1209  }
1210  break;
1211  case 2:
1212  // Disables accelerator tracks
1213  if (quality[key_wire][0] > 0) {
1214  quality[key_wire][0] = 0;
1215  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1216  << "trigMode(): accelerator track " << key_wire << " disabled" << "\n";
1217  }
1218  break;
1219  case 3:
1220  // Disables collision track if there is an accelerator track found
1221  // in the same wire group at the same time
1222  if (quality[key_wire][0] > 0 && quality[key_wire][1] > 0) {
1223  quality[key_wire][1] = 0;
1224  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1225  << "trigMode(): collision track " << key_wire << " disabled" << "\n";
1226  }
1227  break;
1228  }
1229 }
1230 
1231 void CSCAnodeLCTProcessor::accelMode(const int key_wire) {
1232  /* Function which gives a preference either to the collision patterns
1233  or accelerator patterns. The function uses the accel_mode parameter
1234  to decide. */
1235  int promotionBit = 1 << 2;
1236 
1237  switch(accel_mode) {
1238  default:
1239  case 0:
1240  // Ignore accelerator muons.
1241  if (quality[key_wire][0] > 0) {
1242  quality[key_wire][0] = 0;
1243  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1244  << "alctMode(): accelerator track " << key_wire << " ignored" << "\n";
1245  }
1246  break;
1247  case 1:
1248  // Prefer collision muons by adding promotion bit.
1249  if (quality[key_wire][1] > 0) {
1250  quality[key_wire][1] += promotionBit;
1251  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1252  << "alctMode(): collision track " << key_wire << " promoted" << "\n";
1253  }
1254  break;
1255  case 2:
1256  // Prefer accelerator muons by adding promotion bit.
1257  if (quality[key_wire][0] > 0) {
1258  quality[key_wire][0] += promotionBit;
1259  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1260  << "alctMode(): accelerator track " << key_wire << " promoted"<< "\n";
1261  }
1262  break;
1263  case 3:
1264  // Ignore collision muons.
1265  if (quality[key_wire][1] > 0) {
1266  quality[key_wire][1] = 0;
1267  if (infoV > 1) LogTrace("CSCAnodeLCTProcessor")
1268  << "alctMode(): collision track " << key_wire << " ignored" << "\n";
1269  }
1270  break;
1271  }
1272 }
1273 
1274 // Dump of configuration parameters.
1276  std::ostringstream strm;
1277  strm << "\n";
1278  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1279  strm << "+ ALCT configuration parameters: +\n";
1280  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1281  strm << " fifo_tbins [total number of time bins in DAQ readout] = "
1282  << fifo_tbins << "\n";
1283  strm << " fifo_pretrig [start time of anode raw hits in DAQ readout] = "
1284  << fifo_pretrig << "\n";
1285  strm << " drift_delay [drift delay after pre-trigger, in 25 ns bins] = "
1286  << drift_delay << "\n";
1287  strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = "
1288  << nplanes_hit_pretrig << "\n";
1289  strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = "
1290  << nplanes_hit_pattern << "\n";
1291  strm << " nplanes_hit_accel_pretrig [min. number of layers hit for accel."
1292  << " pre-trig.] = " << nplanes_hit_accel_pretrig << "\n";
1293  strm << " nplanes_hit_accel_pattern [min. number of layers hit for accel."
1294  << " trigger] = " << nplanes_hit_accel_pattern << "\n";
1295  strm << " trig_mode [enabling/disabling collision/accelerator tracks] = "
1296  << trig_mode << "\n";
1297  strm << " accel_mode [preference to collision/accelerator tracks] = "
1298  << accel_mode << "\n";
1299  strm << " l1a_window_width [L1Accept window width, in 25 ns bins] = "
1300  << l1a_window_width << "\n";
1301  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1302  LogDebug("CSCAnodeLCTProcessor") << strm.str();
1303 }
1304 
1305 // Dump of digis on wire groups.
1307  LogDebug("CSCAnodeLCTProcessor")
1308  << "ME" << ((theEndcap == 1) ? "+" : "-") << theStation << "/"
1312  << " nWiregroups " << numWireGroups;
1313 
1314  std::ostringstream strstrm;
1315  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1316  if (i_wire%10 == 0) {
1317  if (i_wire < 100) strstrm << i_wire/10;
1318  else strstrm << (i_wire-100)/10;
1319  }
1320  else strstrm << " ";
1321  }
1322  strstrm << "\n";
1323  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1324  strstrm << i_wire%10;
1325  }
1326  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1327  strstrm << "\n";
1328  for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1329  if (wire[i_layer][i_wire].size() > 0) {
1330  std::vector<int> bx_times = wire[i_layer][i_wire];
1331  strstrm << std::hex << bx_times[0] << std::dec;
1332  }
1333  else {
1334  strstrm << ".";
1335  }
1336  }
1337  }
1338  LogTrace("CSCAnodeLCTProcessor") << strstrm.str();
1339 }
1340 
1341 // Returns vector of read-out ALCTs, if any. Starts with the vector of
1342 // all found ALCTs and selects the ones in the read-out time window.
1343 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::readoutALCTs() {
1344  std::vector<CSCALCTDigi> tmpV;
1345 
1346  static int fpga_latency = 6;
1347  static int early_tbins = fifo_pretrig - fpga_latency;
1348  // The number of LCT bins in the read-out is given by the
1349  // l1a_window_width parameter, but made even by setting the LSB of
1350  // l1a_window_width to 0.
1351  static int lct_bins =
1352  // (l1a_window_width%2 == 0) ? l1a_window_width : l1a_window_width-1;
1354  static int late_tbins = early_tbins + lct_bins;
1355 
1356  static int ifois = 0;
1357  if (ifois == 0) {
1358  if (infoV >= 0 && early_tbins < 0) {
1359  edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
1360  << "+++ fifo_pretrig = " << fifo_pretrig
1361  << "; in-time ALCTs are not getting read-out!!! +++" << "\n";
1362  }
1363 
1364  if (late_tbins > MAX_ALCT_BINS-1) {
1365  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
1366  << "+++ Allowed range of time bins, [0-" << late_tbins
1367  << "] exceeds max allowed, " << MAX_ALCT_BINS-1 << " +++\n"
1368  << "+++ Set late_tbins to max allowed +++\n";
1369  late_tbins = MAX_ALCT_BINS-1;
1370  }
1371  ifois = 1;
1372  }
1373 
1374  // Start from the vector of all found ALCTs and select those within
1375  // the ALCT*L1A coincidence window.
1376  std::vector<CSCALCTDigi> all_alcts = getALCTs();
1377  for (std::vector <CSCALCTDigi>::const_iterator plct = all_alcts.begin();
1378  plct != all_alcts.end(); plct++) {
1379  if (!plct->isValid()) continue;
1380 
1381  int bx = (*plct).getBX();
1382  // Skip ALCTs found too early relative to L1Accept.
1383  if (bx <= early_tbins) {
1384  if (infoV > 1) LogDebug("CSCAnodeLCTProcessor")
1385  << " Do not report ALCT on keywire " << plct->getKeyWG()
1386  << ": found at bx " << bx << ", whereas the earliest allowed bx is "
1387  << early_tbins+1;
1388  continue;
1389  }
1390 
1391  // Skip ALCTs found too late relative to L1Accept.
1392  if (bx > late_tbins) {
1393  if (infoV > 1) LogDebug("CSCAnodeLCTProcessor")
1394  << " Do not report ALCT on keywire " << plct->getKeyWG()
1395  << ": found at bx " << bx << ", whereas the latest allowed bx is "
1396  << late_tbins;
1397  continue;
1398  }
1399 
1400  tmpV.push_back(*plct);
1401  }
1402  return tmpV;
1403 }
1404 
1405 // Returns vector of all found ALCTs, if any. Used in ALCT-CLCT matching.
1406 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::getALCTs() {
1407  std::vector<CSCALCTDigi> tmpV;
1408  for (int bx = 0; bx < MAX_ALCT_BINS; bx++) {
1409  if (bestALCT[bx].isValid()) tmpV.push_back(bestALCT[bx]);
1410  if (secondALCT[bx].isValid()) tmpV.push_back(secondALCT[bx]);
1411  }
1412  return tmpV;
1413 }
1414 
1417 
1418 void CSCAnodeLCTProcessor::showPatterns(const int key_wire) {
1419  /* Method to test the pretrigger */
1420  for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS;
1421  i_pattern++) {
1422  std::ostringstream strstrm_header;
1423  LogTrace("CSCAnodeLCTProcessor")
1424  << "\n" << "Pattern: " << i_pattern << " Key wire: " << key_wire;
1425  for (int i = 1; i <= 32; i++) {
1426  strstrm_header << ((32-i)%10);
1427  }
1428  LogTrace("CSCAnodeLCTProcessor") << strstrm_header.str();
1429  for (int i_wire = 0; i_wire < NUM_PATTERN_WIRES; i_wire++) {
1430  if (pattern_mask[i_pattern][i_wire] != 0) {
1431  std::ostringstream strstrm_pulse;
1432  int this_layer = pattern_envelope[0][i_wire];
1433  int this_wire = pattern_envelope[1+MESelection][i_wire]+key_wire;
1434  if (this_wire >= 0 && this_wire < numWireGroups) {
1435  for (int i = 1; i <= 32; i++) {
1436  strstrm_pulse << ((pulse[this_layer][this_wire]>>(32-i)) & 1);
1437  }
1438  LogTrace("CSCAnodeLCTProcessor")
1439  << strstrm_pulse.str() << " on layer " << this_layer;
1440  }
1441  }
1442  }
1443  LogTrace("CSCAnodeLCTProcessor")
1444  << "-------------------------------------------";
1445  }
1446 }
#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...
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
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
static const unsigned int def_nplanes_hit_accel_pretrig
static const unsigned int def_fifo_pretrig
static CSCTriggerGeomManager * get()
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
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
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)
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