CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCCathodeLCTProcessor.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // Class: CSCCathodeLCTProcessor
4 //
5 // Description:
6 // This class simulates the functionality of the cathode LCT card. It is
7 // run by the MotherBoard and returns up to two CathodeLCTs. It can be
8 // run either in a test mode, where it is passed arrays of halfstrip
9 // and distrip times, or in normal mode where it determines
10 // the time and comparator information from the comparator digis.
11 //
12 // Additional comments by Jason Mumford 01/31/01 (mumford@physics.ucla.edu)
13 // Removed the card boundaries. Changed the Pretrigger to emulate
14 // the hardware electronic logic. Also changed the keylayer to be the 4th
15 // layer in a chamber instead of the 3rd layer from the interaction region.
16 // The code is a more realistic simulation of hardware LCT logic now.
17 //
18 // Author List: Benn Tannenbaum (1999), Jason Mumford (2001-2), Slava Valuev.
19 // Porting from ORCA by S. Valuev (Slava.Valuev@cern.ch),
20 // May 2006.
21 //
22 //
23 // Modifications:
24 //
25 //-----------------------------------------------------------------------------
26 
30 
32 #include <algorithm>
33 #include <iomanip>
34 #include <iostream>
35 #include <set>
36 
37 //-----------------
38 // Static variables
39 //-----------------
40 
41 // This is the strip pattern that we use for pretrigger.
42 // pre_hit_pattern[0][i] = layer. pre_hit_pattern[1][i] = key_strip offset.
43 const int CSCCathodeLCTProcessor::pre_hit_pattern[2][NUM_PATTERN_STRIPS] = {
44  { 999, 0, 0, 0, 999,
45  999, 1, 1, 1, 999,
46  999, 2, 2, 2, 999,
47  3, // layer
48  999, 4, 4, 4, 999,
49  999, 5, 5, 5, 999},
50  //-------------------------------------------
51  { 999, -1, 0, 1, 999,
52  999, -1, 0, 1, 999,
53  999, -1, 0, 1, 999,
54  0, // offset
55  999, -1, 0, 1, 999,
56  999, -1, 0, 1, 999}
57 };
58 
59 // The old set of half-strip/di-strip patterns used prior to 2007.
60 // For the given pattern, set the unused parts of the pattern to 999.
61 // Pattern[i][NUM_PATTERN_STRIPS] contains pt bend value. JM
62 // bend of 0 is left/straight and bend of 1 is right bht 21 June 2001
63 // note that the left/right-ness of this is exactly opposite of what one would
64 // expect naively (at least it was for me). The only way to make sure you've
65 // got the patterns you want is to use the printPatterns() method to dump
66 // them. BHT 21 June 2001
68  { 999, 999, 999, 999, 999,
69  999, 999, 999, 999, 999,
70  999, 999, 999, 999, 999,
71  999, // dummy (reserved)
72  999, 999, 999, 999, 999,
73  999, 999, 999, 999, 999, 0},
74  //-------------------------------------------------------------
75  { 999, 999, 999, 0, 999,
76  999, 999, 999, 1, 999,
77  999, 999, 2, 2, 999,
78  3, // right bending pattern (large)
79  999, 4, 4, 999, 999,
80  999, 5, 999, 999, 999, 1},
81  //-------------------------------------------------------------
82  { 999, 0, 999, 999, 999,
83  999, 1, 999, 999, 999,
84  999, 2, 2, 999, 999,
85  3, // left bending pattern (large)
86  999, 999, 4, 4, 999,
87  999, 999, 999, 5, 999, 0},
88  //-------------------------------------------------------------
89  { 999, 999, 0, 999, 999,
90  999, 999, 1, 999, 999,
91  999, 999, 2, 999, 999,
92  3, // right bending pattern (medium)
93  999, 4, 999, 999, 999,
94  999, 5, 999, 999, 999, 1},
95  //-------------------------------------------------------------
96  { 999, 999, 0, 999, 999,
97  999, 999, 1, 999, 999,
98  999, 999, 2, 999, 999,
99  3, // left bending pattern (medium)
100  999, 999, 999, 4, 999,
101  999, 999, 999, 5, 999, 0},
102  //-------------------------------------------------------------
103  { 999, 999, 999, 0, 999,
104  999, 999, 999, 1, 999,
105  999, 999, 2, 2, 999,
106  3, // right bending pattern (small)
107  999, 999, 4, 999, 999,
108  999, 999, 5, 999, 999, 1},
109  //-------------------------------------------------------------
110  { 999, 0, 999, 999, 999,
111  999, 1, 999, 999, 999,
112  999, 2, 2, 999, 999,
113  3, // left bending pattern (small)
114  999, 999, 4, 999, 999,
115  999, 999, 5, 999, 999, 0},
116  //-------------------------------------------------------------
117  { 999, 999, 0, 999, 999,
118  999, 999, 1, 999, 999,
119  999, 999, 2, 999, 999,
120  3, // straight through pattern
121  999, 999, 4, 999, 999,
122  999, 999, 5, 999, 999, 1}
123 };
124 
125 // New set of halfstrip patterns for 2007 version of the algorithm.
126 // For the given pattern, set the unused parts of the pattern to 999.
127 // Pattern[i][NUM_PATTERN_HALFSTRIPS] contains bend direction.
128 // Bend of 0 is right/straight and bend of 1 is left.
129 // Pattern[i][NUM_PATTERN_HALFSTRIPS+1] contains pattern maximum width
130 const int CSCCathodeLCTProcessor::pattern2007_offset[NUM_PATTERN_HALFSTRIPS] =
131  { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5,
132  -2, -1, 0, 1, 2,
133  0,
134  -2, -1, 0, 1, 2,
135  -4, -3, -2, -1, 0, 1, 2, 3, 4,
136  -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5 };
137 
138 const int CSCCathodeLCTProcessor::pattern2007[CSCConstants::NUM_CLCT_PATTERNS][NUM_PATTERN_HALFSTRIPS+2] = {
139  { 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999,
140  999, 999, 999, 999, 999,
141  999, // pid=0: no pattern found
142  999, 999, 999, 999, 999,
143  999, 999, 999, 999, 999, 999, 999, 999, 999,
144  999, 999, 999, 999, 999, 999, 999, 999, 999, 999, 999, -1, 0},
145  //-------------------------------------------------------------
146  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
147  1, 1, 1, 1, 1,
148  2, // pid=1: layer-OR trigger
149  3, 3, 3, 3, 3,
150  4, 4, 4, 4, 4, 4, 4, 4, 4,
151  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -1, 11},
152  //-------------------------------------------------------------
153  { 999, 999, 999, 999, 999, 999, 999, 999, 0, 0, 0,
154  999, 999, 999, 1, 1,
155  2, // pid=2: right-bending (large)
156  3, 3, 3, 999, 999,
157  4, 4, 4, 999, 999, 999, 999, 999, 999,
158  5, 5, 5, 999, 999, 999, 999, 999, 999, 999, 999, 0, 11},
159  //-------------------------------------------------------------
160  { 0, 0, 0, 999, 999, 999, 999, 999, 999, 999, 999,
161  1, 1, 999, 999, 999,
162  2, // pid=3: left-bending (large)
163  999, 999, 3, 3, 3,
164  999, 999, 999, 999, 999, 999, 4, 4, 4,
165  999, 999, 999, 999, 999, 999, 999, 999, 5, 5, 5, 1, 11},
166  //-------------------------------------------------------------
167  { 999, 999, 999, 999, 999, 999, 999, 0, 0, 0, 999,
168  999, 999, 999, 1, 1,
169  2, // pid=4: right-bending (medium)
170  3, 3, 999, 999, 999,
171  4, 4, 4, 999, 999, 999, 999, 999, 999,
172  999, 5, 5, 5, 999, 999, 999, 999, 999, 999, 999, 0, 9},
173  //-------------------------------------------------------------
174  { 999, 0, 0, 0, 999, 999, 999, 999, 999, 999, 999,
175  1, 1, 999, 999, 999,
176  2, // pid=5: left-bending (medium)
177  999, 999, 999, 3, 3,
178  999, 999, 999, 999, 999, 999, 4, 4, 4,
179  999, 999, 999, 999, 999, 999, 999, 5, 5, 5, 999, 1, 9},
180  //-------------------------------------------------------------
181  { 999, 999, 999, 999, 999, 999, 0, 0, 0, 999, 999,
182  999, 999, 1, 1, 999,
183  2, // pid=6: right-bending (medium)
184  999, 3, 3, 999, 999,
185  999, 999, 4, 4, 999, 999, 999, 999, 999,
186  999, 999, 5, 5, 5, 999, 999, 999, 999, 999, 999, 0, 7},
187  //-------------------------------------------------------------
188  { 999, 999, 0, 0, 0, 999, 999, 999, 999, 999, 999,
189  999, 1, 1, 999, 999,
190  2, // pid=7: left-bending (medium)
191  999, 999, 3, 3, 999,
192  999, 999, 999, 999, 999, 4, 4, 999, 999,
193  999, 999, 999, 999, 999, 999, 5, 5, 5, 999, 999, 1, 7},
194  //-------------------------------------------------------------
195  { 999, 999, 999, 999, 999, 0, 0, 0, 999, 999, 999,
196  999, 999, 1, 1, 999,
197  2, // pid=8: right-bending (small)
198  999, 3, 3, 999, 999,
199  999, 999, 4, 4, 4, 999, 999, 999, 999,
200  999, 999, 999, 5, 5, 5, 999, 999, 999, 999, 999, 0, 5},
201  //-------------------------------------------------------------
202  { 999, 999, 999, 0, 0, 0, 999, 999, 999, 999, 999,
203  999, 1, 1, 999, 999,
204  2, // pid=9: left-bending (small)
205  999, 999, 3, 3, 999,
206  999, 999, 999, 999, 4, 4, 4, 999, 999,
207  999, 999, 999, 999, 999, 5, 5, 5, 999, 999, 999, 1, 5},
208  //-------------------------------------------------------------
209  { 999, 999, 999, 999, 0, 0, 0, 999, 999, 999, 999,
210  999, 999, 1, 999, 999,
211  2, // pid=A: straight-through
212  999, 999, 3, 999, 999,
213  999, 999, 999, 4, 4, 4, 999, 999, 999,
214  999, 999, 999, 999, 5, 5, 5, 999, 999, 999, 999, 0, 3}
215  // pid's=B-F are not yet defined
216 };
217 
218 // Default values of configuration parameters.
219 const unsigned int CSCCathodeLCTProcessor::def_fifo_tbins = 12;
220 const unsigned int CSCCathodeLCTProcessor::def_fifo_pretrig = 7;
221 const unsigned int CSCCathodeLCTProcessor::def_hit_persist = 6;
222 const unsigned int CSCCathodeLCTProcessor::def_drift_delay = 2;
226 const unsigned int CSCCathodeLCTProcessor::def_min_separation = 10;
228 
229 // Number of di-strips/half-strips per CFEB.
230 const int CSCCathodeLCTProcessor::cfeb_strips[2] = { 8, 32};
231 
232 //----------------
233 // Constructors --
234 //----------------
235 
237  unsigned station,
238  unsigned sector,
239  unsigned subsector,
240  unsigned chamber,
241  const edm::ParameterSet& conf,
242  const edm::ParameterSet& comm,
243  const edm::ParameterSet& ctmb) :
244  theEndcap(endcap), theStation(station), theSector(sector),
245  theSubsector(subsector), theTrigChamber(chamber) {
246  static std::atomic<bool> config_dumped{false};
247 
248  // CLCT configuration parameters.
249  fifo_tbins = conf.getParameter<unsigned int>("clctFifoTbins");
250  hit_persist = conf.getParameter<unsigned int>("clctHitPersist");
251  drift_delay = conf.getParameter<unsigned int>("clctDriftDelay");
253  conf.getParameter<unsigned int>("clctNplanesHitPretrig");
255  conf.getParameter<unsigned int>("clctNplanesHitPattern");
256 
257  // Not used yet.
258  fifo_pretrig = conf.getParameter<unsigned int>("clctFifoPretrig");
259 
260  // Defines pre-2007 version of the CLCT algorithm used in test beams and
261  // MTCC.
262  isMTCC = comm.getParameter<bool>("isMTCC");
263 
264  // TMB07 firmware used since 2007: switch and config. parameters.
265  isTMB07 = comm.getParameter<bool>("isTMB07");
266 
267  // Flag for SLHC studies
268  isSLHC = comm.getUntrackedParameter<bool>("isSLHC",false);
269 
270  // special configuration parameters for ME11 treatment
271  smartME1aME1b = comm.getUntrackedParameter<bool>("smartME1aME1b",false);
272  disableME1a = comm.getUntrackedParameter<bool>("disableME1a",false);
273  gangedME1a = comm.getUntrackedParameter<bool>("gangedME1a",true);
274 
275  if (isSLHC && !smartME1aME1b) edm::LogError("L1CSCTPEmulatorConfigError")
276  << "+++ SLHC upgrade configuration is used (isSLHC=True) but smartME1aME1b=False!\n"
277  << "Only smartME1aME1b algorithm is so far supported for upgrade! +++\n";
278 
279  if (isTMB07) {
281  conf.getParameter<unsigned int>("clctPidThreshPretrig");
283  conf.getParameter<unsigned int>("clctMinSeparation");
284 
285  start_bx_shift = conf.getUntrackedParameter<int>("clctStartBxShift",0);
286  }
287 
288  if (smartME1aME1b) {
289  // use of localized dead-time zones
291  conf.getUntrackedParameter<bool>("useDeadTimeZoning",true);
293  conf.getUntrackedParameter<unsigned int>("clctStateMachineZone",8);
295  conf.getUntrackedParameter<bool>("useDynamicStateMachineZone",true);
296 
297  // how far away may trigger happen from pretrigger
299  conf.getUntrackedParameter<unsigned int>("clctPretriggerTriggerZone",5);
300 
301  // whether to calculate bx as corrected_bx instead of pretrigger one
302  use_corrected_bx = conf.getUntrackedParameter<bool>("clctUseCorrectedBx",false);
303  }
304 
305  // Motherboard parameters: common for all configurations.
306  tmb_l1a_window_size = // Common to CLCT and TMB
307  ctmb.getParameter<unsigned int>("tmbL1aWindowSize");
308 
309  // separate handle for early time bins
310  early_tbins = ctmb.getUntrackedParameter<int>("tmbEarlyTbins",-1);
311  static int fpga_latency = 3;
312  if (early_tbins<0) early_tbins = fifo_pretrig - fpga_latency;
313 
314  // wether to readout only the earliest two LCTs in readout window
315  readout_earliest_2 = ctmb.getUntrackedParameter<bool>("tmbReadoutEarliest2",0);
316 
317  // Verbosity level, set to 0 (no print) by default.
318  infoV = conf.getUntrackedParameter<int>("verbosity", 0);
319 
320  // Check and print configuration parameters.
322  if ((infoV > 0 || isSLHC) && !config_dumped) {
323  //std::cerr<<"**** CLCT constructor parameters dump ****"<<std::endl;
325  config_dumped = true;
326  }
327 
328  numStrips = 0; // Will be set later.
329  // Provisional, but should be OK for all stations except ME1.
330  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
331  if ((i_layer+1)%2 == 0) stagger[i_layer] = 0;
332  else stagger[i_layer] = 1;
333  }
334 
336 
339 
340  // trigger numbering doesn't distinguish between ME1a and ME1b chambers:
341  isME11 = (theStation == 1 && theRing == 1);
342 
343  //if (theStation==1 && theRing==2) infoV = 3;
344 
346  //if (theStation == 2 && theSector == 1 &&
347  // theRing == 1 &&
348  // theChamber == 1) {
350  // testPatterns();
352  // testLCTs();
354  // printPatterns();
355  //}
356 }
357 
359  theEndcap(1), theStation(1), theSector(1),
360  theSubsector(1), theTrigChamber(1) {
361  // constructor for debugging.
362  static std::atomic<bool> config_dumped{false};
363 
364  // CLCT configuration parameters.
366  infoV = 2;
367  isMTCC = false;
368  isTMB07 = true;
369 
370  smartME1aME1b = false;
371  disableME1a = false;
372  gangedME1a = true;
373 
374  early_tbins = 4;
375 
376  start_bx_shift = 0;
379 
380  // Check and print configuration parameters.
382  if (!config_dumped) {
383  //std::cerr<<"**** CLCT default constructor parameters dump ****"<<std::endl;
385  config_dumped = true;
386  }
387 
389  // Should be OK for all stations except ME1.
390  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
391  if ((i_layer+1)%2 == 0) stagger[i_layer] = 0;
392  else stagger[i_layer] = 1;
393  }
394 
396  isME11 = (theStation == 1 && theRing == 1);
397 }
398 
400  // Set default values for configuration parameters.
407 
408  isMTCC = false;
409 
410  // New TMB07 parameters.
411  isTMB07 = true;
412  if (isTMB07) {
415  }
416 
418 }
419 
420 // Set configuration parameters obtained via EventSetup mechanism.
422  static std::atomic<bool> config_dumped{false};
423 
424  fifo_tbins = conf->clctFifoTbins();
425  fifo_pretrig = conf->clctFifoPretrig();
426  hit_persist = conf->clctHitPersist();
427  drift_delay = conf->clctDriftDelay();
430 
431  // TMB07 parameters.
432  if (isTMB07) {
435  }
436 
437  // Check and print configuration parameters.
439  if (!config_dumped) {
440  //std::cerr<<"**** CLCT setConfigParams parameters dump ****"<<std::endl;
442  config_dumped = true;
443  }
444 }
445 
447  // Make sure that the parameter values are within the allowed range.
448 
449  // Max expected values.
450  static const unsigned int max_fifo_tbins = 1 << 5;
451  static const unsigned int max_fifo_pretrig = 1 << 5;
452  static const unsigned int max_hit_persist = 1 << 4;
453  static const unsigned int max_drift_delay = 1 << 2;
454  static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
455  static const unsigned int max_nplanes_hit_pattern = 1 << 3;
456  static const unsigned int max_pid_thresh_pretrig = 1 << 4;
457  static const unsigned int max_min_separation = CSCConstants::NUM_HALF_STRIPS_7CFEBS;
458  static const unsigned int max_tmb_l1a_window_size = 1 << 4;
459 
460  // Checks.
461  if (fifo_tbins >= max_fifo_tbins) {
462  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
463  << "+++ Value of fifo_tbins, " << fifo_tbins
464  << ", exceeds max allowed, " << max_fifo_tbins-1 << " +++\n"
465  << "+++ Try to proceed with the default value, fifo_tbins="
466  << def_fifo_tbins << " +++\n";
468  }
469  if (fifo_pretrig >= max_fifo_pretrig) {
470  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
471  << "+++ Value of fifo_pretrig, " << fifo_pretrig
472  << ", exceeds max allowed, " << max_fifo_pretrig-1 << " +++\n"
473  << "+++ Try to proceed with the default value, fifo_pretrig="
474  << def_fifo_pretrig << " +++\n";
476  }
477  if (hit_persist >= max_hit_persist) {
478  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
479  << "+++ Value of hit_persist, " << hit_persist
480  << ", exceeds max allowed, " << max_hit_persist-1 << " +++\n"
481  << "+++ Try to proceed with the default value, hit_persist="
482  << def_hit_persist << " +++\n";
484  }
485  if (drift_delay >= max_drift_delay) {
486  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
487  << "+++ Value of drift_delay, " << drift_delay
488  << ", exceeds max allowed, " << max_drift_delay-1 << " +++\n"
489  << "+++ Try to proceed with the default value, drift_delay="
490  << def_drift_delay << " +++\n";
492  }
493  if (nplanes_hit_pretrig >= max_nplanes_hit_pretrig) {
494  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
495  << "+++ Value of nplanes_hit_pretrig, " << nplanes_hit_pretrig
496  << ", exceeds max allowed, " << max_nplanes_hit_pretrig-1 << " +++\n"
497  << "+++ Try to proceed with the default value, nplanes_hit_pretrig="
498  << def_nplanes_hit_pretrig << " +++\n";
500  }
501  if (nplanes_hit_pattern >= max_nplanes_hit_pattern) {
502  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
503  << "+++ Value of nplanes_hit_pattern, " << nplanes_hit_pattern
504  << ", exceeds max allowed, " << max_nplanes_hit_pattern-1 << " +++\n"
505  << "+++ Try to proceed with the default value, nplanes_hit_pattern="
506  << def_nplanes_hit_pattern << " +++\n";
508  }
509 
510  if (isTMB07) {
511  if (pid_thresh_pretrig >= max_pid_thresh_pretrig) {
512  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
513  << "+++ Value of pid_thresh_pretrig, " << pid_thresh_pretrig
514  << ", exceeds max allowed, " << max_pid_thresh_pretrig-1 << " +++\n"
515  << "+++ Try to proceed with the default value, pid_thresh_pretrig="
516  << def_pid_thresh_pretrig << " +++\n";
518  }
519  if (min_separation >= max_min_separation) {
520  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
521  << "+++ Value of min_separation, " << min_separation
522  << ", exceeds max allowed, " << max_min_separation-1 << " +++\n"
523  << "+++ Try to proceed with the default value, min_separation="
524  << def_min_separation << " +++\n";
526  }
527  }
528 
529  if (tmb_l1a_window_size >= max_tmb_l1a_window_size) {
530  if (infoV > 0) edm::LogError("L1CSCTPEmulatorConfigError")
531  << "+++ Value of tmb_l1a_window_size, " << tmb_l1a_window_size
532  << ", exceeds max allowed, " << max_tmb_l1a_window_size-1 << " +++\n"
533  << "+++ Try to proceed with the default value, tmb_l1a_window_size="
534  << def_tmb_l1a_window_size << " +++\n";
536  }
537 }
538 
540  thePreTriggerBXs.clear();
541  for (int bx = 0; bx < MAX_CLCT_BINS; bx++) {
542  bestCLCT[bx].clear();
543  secondCLCT[bx].clear();
544  }
545 }
546 
547 std::vector<CSCCLCTDigi>
549  // This is the version of the run() function that is called when running
550  // over the entire detector. It gets the comparator & timing info from the
551  // comparator digis and then passes them on to another run() function.
552 
553  // clear(); // redundant; called by L1MuCSCMotherboard.
554 
555  static std::atomic<bool> config_dumped{false};
556  if ((infoV > 0 || isSLHC) && !config_dumped) {
557  //std::cerr<<"**** CLCT run parameters dump ****"<<std::endl;
559  config_dumped = true;
560  }
561 
562  // Get the number of strips and stagger of layers for the given chamber.
563  // Do it only once per chamber.
564  if (numStrips == 0) {
566  CSCChamber* chamber = theGeom->chamber(theEndcap, theStation, theSector,
568  if (chamber) {
569  numStrips = chamber->layer(1)->geometry()->numberOfStrips();
570  // ME1/a is known to the readout hardware as strips 65-80 of ME1/1.
571  // Still need to decide whether we do any special adjustments to
572  // reconstruct LCTs in this region (3:1 ganged strips); for now, we
573  // simply allow for hits in ME1/a and apply standard reconstruction
574  // to them.
575  // For SLHC ME1/1 is set to have 4 CFEBs in ME1/b and 3 CFEBs in ME1/a
576  if (isME11) {
577  if (!smartME1aME1b && !disableME1a && theRing == 1 && !gangedME1a) numStrips = 112;
578  if (!smartME1aME1b && !disableME1a && theRing == 1 && gangedME1a) numStrips = 80;
579  if (!smartME1aME1b && disableME1a && theRing == 1 ) numStrips = 64;
580  if ( smartME1aME1b && !disableME1a && theRing == 1 ) numStrips = 64;
581  if ( smartME1aME1b && !disableME1a && theRing == 4 ) {
582  if (gangedME1a) numStrips = 16;
583  else numStrips = 48;
584  }
585  }
586 
588  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorSetupError")
589  << "+++ Number of strips, " << numStrips
590  << " found in ME" << ((theEndcap == 1) ? "+" : "-")
591  << theStation << "/" << theRing << "/" << theChamber
592  << " (sector " << theSector << " subsector " << theSubsector
593  << " trig id. " << theTrigChamber << ")"
594  << " exceeds max expected, " << CSCConstants::MAX_NUM_STRIPS_7CFEBS
595  << " +++\n"
596  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
597  numStrips = -1;
598  }
599  // The strips for a given layer may be offset from the adjacent layers.
600  // This was done in order to improve resolution. We need to find the
601  // 'staggering' for each layer and make necessary conversions in our
602  // arrays. -JM
603  // In the TMB-07 firmware, half-strips in odd layers (layers are
604  // counted as ly0-ly5) are shifted by -1 half-strip, whereas in
605  // the previous firmware versions half-strips in even layers
606  // were shifted by +1 half-strip. This difference is due to a
607  // change from ly3 to ly2 in the choice of the key layer, and
608  // the intention to keep half-strips in the key layer unchanged.
609  // In the emulator, we use the old way for both cases, to avoid
610  // negative half-strip numbers. This will necessitate a
611  // subtraction of 1 half-strip for TMB-07 later on. -SV.
612  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
613  stagger[i_layer] =
614  (chamber->layer(i_layer+1)->geometry()->stagger() + 1) / 2;
615  }
616  }
617  else {
618  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
619  << " ME" << ((theEndcap == 1) ? "+" : "-")
620  << theStation << "/" << theRing << "/" << theChamber
621  << " (sector " << theSector << " subsector " << theSubsector
622  << " trig id. " << theTrigChamber << ")"
623  << " is not defined in current geometry! +++\n"
624  << "+++ CSC geometry looks garbled; no emulation possible +++\n";
625  numStrips = -1;
626  }
627  }
628 
629  if (numStrips < 0) {
630  if (infoV >= 0) edm::LogError("L1CSCTPEmulatorConfigError")
631  << " ME" << ((theEndcap == 1) ? "+" : "-")
632  << theStation << "/" << theRing << "/" << theChamber
633  << " (sector " << theSector << " subsector " << theSubsector
634  << " trig id. " << theTrigChamber << "):"
635  << " numStrips = " << numStrips << "; CLCT emulation skipped! +++";
636  std::vector<CSCCLCTDigi> emptyV;
637  return emptyV;
638  }
639 
640  // Get comparator digis in this chamber.
641  bool noDigis = getDigis(compdc);
642 
643  if (!noDigis) {
644  // Get halfstrip (and possibly distrip) times from comparator digis.
645  std::vector<int>
647  std::vector<int>
649  if (isTMB07) { // TMB07 (latest) version: halfstrips only.
650  readComparatorDigis(halfstrip);
651  }
652  else { // Earlier versions: halfstrips and distrips.
653  readComparatorDigis(halfstrip, distrip);
654  }
655 
656  // Pass arrays of halfstrips and distrips on to another run() doing the
657  // LCT search.
658  // If the number of layers containing digis is smaller than that
659  // required to trigger, quit right away. (If LCT-based digi suppression
660  // is implemented one day, this condition will have to be changed
661  // to the number of planes required to pre-trigger.)
662  unsigned int layersHit = 0;
663  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
664  for (int i_hstrip = 0; i_hstrip < CSCConstants::NUM_HALF_STRIPS_7CFEBS;
665  i_hstrip++) {
666  if (!halfstrip[i_layer][i_hstrip].empty()) {layersHit++; break;}
667  }
668  }
669  // Run the algorithm only if the probability for the pre-trigger
670  // to fire is not null. (Pre-trigger decisions are used for the
671  // strip read-out conditions in DigiToRaw.)
672  if (layersHit >= nplanes_hit_pretrig) run(halfstrip, distrip);
673  }
674 
675  // Return vector of CLCTs.
676  std::vector<CSCCLCTDigi> tmpV = getCLCTs();
677  return tmpV;
678 }
679 
681  const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS],
682  const std::vector<int> distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
683  // This version of the run() function can either be called in a standalone
684  // test, being passed the halfstrip and distrip times, or called by the
685  // run() function above. It uses the findLCTs() method to find vectors
686  // of LCT candidates. These candidates are sorted and the best two per bx
687  // are returned.
688  std::vector<CSCCLCTDigi> LCTlist;
689 
690  if (isTMB07) {
691  // Upgrade version for ME11 with better dead-time handling
692  if (isSLHC && smartME1aME1b && isME11 && use_dead_time_zoning) LCTlist = findLCTsSLHC(halfstrip);
693  // TMB07 version of the CLCT algorithm.
694  else LCTlist = findLCTs(halfstrip);
695  }
696  else if (isMTCC) { // MTCC version.
697  LCTlist = findLCTs(halfstrip, distrip);
698  }
699  else { // Idealized algorithm of many years ago.
700  std::vector<CSCCLCTDigi> halfStripLCTs = findLCTs(halfstrip, 1);
701  std::vector<CSCCLCTDigi> diStripLCTs = findLCTs(distrip, 0);
702  // Put all the candidates into a single vector and sort them.
703  for (unsigned int i = 0; i < halfStripLCTs.size(); i++)
704  LCTlist.push_back(halfStripLCTs[i]);
705  for (unsigned int i = 0; i < diStripLCTs.size(); i++)
706  LCTlist.push_back(diStripLCTs[i]);
707  }
708 
709  // LCT sorting.
710  if (LCTlist.size() > 1)
711  sort(LCTlist.begin(), LCTlist.end(), std::greater<CSCCLCTDigi>());
712 
713  // Take the best two candidates per bx.
714  for (std::vector<CSCCLCTDigi>::const_iterator plct = LCTlist.begin();
715  plct != LCTlist.end(); plct++) {
716  int bx = plct->getBX();
717  if (bx >= MAX_CLCT_BINS) {
718  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeCLCT")
719  << "+++ Bx of CLCT candidate, " << bx << ", exceeds max allowed, "
720  << MAX_CLCT_BINS-1 << "; skipping it... +++\n";
721  continue;
722  }
723 
724  if (!bestCLCT[bx].isValid()) bestCLCT[bx] = *plct;
725  else if (!secondCLCT[bx].isValid()) {
726  // Ignore CLCT if it is the same as the best (i.e. if the same
727  // CLCT was found in both half- and di-strip pattern search).
728  // This can never happen in the test beam and MTCC
729  // implementations.
730  if (!isMTCC && !isTMB07 && *plct == bestCLCT[bx]) continue;
731  secondCLCT[bx] = *plct;
732  }
733  }
734 
735  for (int bx = 0; bx < MAX_CLCT_BINS; bx++) {
736  if (bestCLCT[bx].isValid()) {
737  bestCLCT[bx].setTrknmb(1);
738  if (infoV > 0) LogDebug("CSCCathodeLCTProcessor")
739  << bestCLCT[bx] << " found in ME" << ((theEndcap == 1) ? "+" : "-")
740  << theStation << "/" << theRing << "/" << theChamber
741  << " (sector " << theSector << " subsector " << theSubsector
742  << " trig id. " << theTrigChamber << ")" << "\n";
743  }
744  if (secondCLCT[bx].isValid()) {
745  secondCLCT[bx].setTrknmb(2);
746  if (infoV > 0) LogDebug("CSCCathodeLCTProcessor")
747  << secondCLCT[bx] << " found in ME" << ((theEndcap == 1) ? "+" : "-")
748  << theStation << "/" << theRing << "/" << theChamber
749  << " (sector " << theSector << " subsector " << theSubsector
750  << " trig id. " << theTrigChamber << ")" << "\n";
751  }
752  }
753  // Now that we have our best CLCTs, they get correlated with the best
754  // ALCTs and then get sent to the MotherBoard. -JM
755 }
756 
758  bool noDigis = true;
759 
760  // Loop over layers and save comparator digis on each one into digiV[layer].
761  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
762  digiV[i_layer].clear();
763 
765  getDigis(compdc, detid);
766 
767  // If this is ME1/1, fetch digis in corresponding ME1/A (ring=4) as well.
768  if (theStation == 1 && theRing == 1 && !disableME1a && !smartME1aME1b) {
769  CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer+1);
770  getDigis(compdc, detid_me1a);
771  }
772 
773  // If this is ME1/1, fetch digis in corresponding ME1/B (ring=1) as well.
774  // needed only for the "smart" A/B case; and, actually, only for data
775  if (theStation == 1 && theRing == 4 && !disableME1a && smartME1aME1b
776  && digiV[i_layer].empty()) {
777  CSCDetId detid_me1b(theEndcap, theStation, 1, theChamber, i_layer+1);
778  getDigis(compdc, detid_me1b);
779  }
780 
781  if (!digiV[i_layer].empty()) {
782  noDigis = false;
783  if (infoV > 1) {
784  LogTrace("CSCCathodeLCTProcessor")
785  << "found " << digiV[i_layer].size()
786  << " comparator digi(s) in layer " << i_layer << " of ME"
787  << ((theEndcap == 1) ? "+" : "-") << theStation << "/" << theRing
788  << "/" << theChamber << " (trig. sector " << theSector
789  << " subsector " << theSubsector << " id " << theTrigChamber << ")";
790  }
791  }
792  }
793 
794  return noDigis;
795 }
796 
798  const CSCDetId& id) {
799  bool me1bProc = theStation == 1 && theRing == 1;
800  bool me1aProc = theStation == 1 && theRing == 4;
801  bool me1b = (id.station() == 1) && (id.ring() == 1);
802  bool me1a = (id.station() == 1) && (id.ring() == 4);
803  const CSCComparatorDigiCollection::Range rcompd = compdc->get(id);
804  for (CSCComparatorDigiCollection::const_iterator digiIt = rcompd.first;
805  digiIt != rcompd.second; ++digiIt) {
806  unsigned int origStrip = digiIt->getStrip();
807  unsigned int maxStripsME1a = gangedME1a ? 16 : 48;
808  if (me1a && origStrip <= maxStripsME1a && !disableME1a && !smartME1aME1b) {
809  // Move ME1/A comparators from CFEB=0 to CFEB=4 if this has not
810  // been done already.
811  CSCComparatorDigi digi_corr(origStrip+64,
812  digiIt->getComparator(),
813  digiIt->getTimeBinWord());
814  digiV[id.layer()-1].push_back(digi_corr);
815  }
816  else if (smartME1aME1b && (me1bProc || me1aProc)){
817  //stay within bounds; in data all comps are in ME11B DetId
818 
819  if (me1aProc && me1b && origStrip > 64){//this is data
820  //shift back to start from 1
821  CSCComparatorDigi digi_corr(origStrip-64,
822  digiIt->getComparator(),
823  digiIt->getTimeBinWord());
824  digiV[id.layer()-1].push_back(digi_corr);
825  } else if ((me1bProc && me1b && origStrip <= 64)
826  || ((me1aProc && me1a))//this is MC for ME11a
827  ){
828  digiV[id.layer()-1].push_back(*digiIt);
829  }
830  }
831  else {
832  digiV[id.layer()-1].push_back(*digiIt);
833  }
834  }
835 }
836 
838  std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
839  // Single-argument version for TMB07 (halfstrip-only) firmware.
840  // Takes the comparator & time info and stuffs it into halfstrip vector.
841  // Multiple hits on the same strip are allowed.
842 
843  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
844  int i_digi = 0; // digi counter, for dumps.
845  for (std::vector<CSCComparatorDigi>::iterator pld = digiV[i_layer].begin();
846  pld != digiV[i_layer].end(); pld++, i_digi++) {
847  // Dump raw digi info.
848  if (infoV > 1) {
849  std::ostringstream strstrm;
850  strstrm << "Comparator digi: comparator = " << pld->getComparator()
851  << " strip #" << pld->getStrip()
852  << " time bins on:";
853  std::vector<int> bx_times = pld->getTimeBinsOn();
854  for (unsigned int tbin = 0; tbin < bx_times.size(); tbin++)
855  strstrm << " " << bx_times[tbin];
856  LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
857  }
858 
859  // Get comparator: 0/1 for left/right halfstrip for each comparator
860  // that fired.
861  int thisComparator = pld->getComparator();
862  if (thisComparator != 0 && thisComparator != 1) {
863  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
864  << "+++ Found comparator digi with wrong comparator value = "
865  << thisComparator << "; skipping it... +++\n";
866  continue;
867  }
868 
869  // Get strip number.
870  int thisStrip = pld->getStrip() - 1; // count from 0
871  if (thisStrip < 0 || thisStrip >= numStrips) {
872  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
873  << "+++ Found comparator digi with wrong strip number = "
874  << thisStrip
875  << " (max strips = " << numStrips << "); skipping it... +++\n";
876  continue;
877  }
878  // 2*strip: convert strip to 1/2 strip
879  // comp : comparator output
880  // stagger: stagger for this layer
881  int thisHalfstrip = 2*thisStrip + thisComparator + stagger[i_layer];
882  if (thisHalfstrip >= 2*numStrips + 1) {
883  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
884  << "+++ Found wrong halfstrip number = " << thisHalfstrip
885  << "; skipping this digi... +++\n";
886  continue;
887  }
888 
889  // Get bx times on this digi and check that they are within the bounds.
890  std::vector<int> bx_times = pld->getTimeBinsOn();
891  for (unsigned int i = 0; i < bx_times.size(); i++) {
892  // Total number of time bins in DAQ readout is given by fifo_tbins,
893  // which thus determines the maximum length of time interval.
894  //
895  // In TMB07 version, better data-emulator agreement is
896  // achieved when hits in the first 2 time bins are excluded.
897  // As of May 2009, the reasons for this are not fully
898  // understood yet (the work is on-going).
899  if (bx_times[i] > 1 && bx_times[i] < static_cast<int>(fifo_tbins)) {
900 
901  if (i == 0 || (i > 0 && bx_times[i]-bx_times[i-1] >=
902  static_cast<int>(hit_persist))) {
903  // A later hit on the same strip is ignored during the
904  // number of clocks defined by the "hit_persist" parameter
905  // (i.e., 6 bx's by default).
906  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
907  << "Comp digi: layer " << i_layer+1
908  << " digi #" << i_digi+1
909  << " strip " << thisStrip
910  << " halfstrip " << thisHalfstrip
911  << " distrip " << thisStrip/2 + // [0-39]
912  ((thisStrip%2 == 1 && thisComparator == 1 && stagger[i_layer] == 1) ? 1 : 0)
913  << " time " << bx_times[i]
914  << " comparator " << thisComparator
915  << " stagger " << stagger[i_layer];
916  halfstrip[i_layer][thisHalfstrip].push_back(bx_times[i]);
917  }
918  else if (i > 0) {
919  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
920  << " Skipping comparator digi: strip = " << thisStrip
921  << ", layer = " << i_layer+1 << ", bx = " << bx_times[i]
922  << ", bx of previous hit = " << bx_times[i-1];
923  }
924  }
925  else {
926  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
927  << "+++ Skipping comparator digi: strip = " << thisStrip
928  << ", layer = " << i_layer+1 << ", bx = " << bx_times[i] << " +++";
929  }
930  }
931  }
932  }
933 }
934 
937  std::vector<int> distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
938  // Two-argument version for pre-TMB07 (halfstrip and distrips) firmware.
939  // Takes the comparator & time info and stuffs it into halfstrip and (and
940  // possibly distrip) vector.
941 
945  for (int i = 0; i < CSCConstants::NUM_LAYERS; i++){
946  for (int j = 0; j < CSCConstants::MAX_NUM_STRIPS_7CFEBS; j++) {
947  time[i][j] = -999;
948  comp[i][j] = 0;
949  digiNum[i][j] = -999;
950  }
951  }
952 
953  for (int i = 0; i < CSCConstants::NUM_LAYERS; i++) {
954  std::vector <CSCComparatorDigi> layerDigiV = digiV[i];
955  for (unsigned int j = 0; j < layerDigiV.size(); j++) {
956  // Get one digi at a time for the layer. -Jm
957  CSCComparatorDigi thisDigi = layerDigiV[j];
958 
959  // Dump raw digi info
960  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
961  << "Comparator digi: comparator = " << thisDigi.getComparator()
962  << " strip #" << thisDigi.getStrip()
963  << " time bin = " << thisDigi.getTimeBin();
964 
965  // Get comparator: 0/1 for left/right halfstrip for each comparator
966  // that fired.
967  int thisComparator = thisDigi.getComparator();
968  if (thisComparator != 0 && thisComparator != 1) {
969  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
970  << "+++ Comparator digi with wrong comparator value: digi #" << j
971  << ", comparator = " << thisComparator << "; skipping it... +++\n";
972  continue;
973  }
974 
975  // Get strip number.
976  int thisStrip = thisDigi.getStrip() - 1; // count from 0
977  if (thisStrip < 0 || thisStrip >= numStrips) {
978  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
979  << "+++ Comparator digi with wrong strip number: digi #" << j
980  << ", strip = " << thisStrip
981  << ", max strips = " << numStrips << "; skipping it... +++\n";
982  continue;
983  }
984 
985  // Get Bx of this Digi and check that it is within the bounds
986  int thisDigiBx = thisDigi.getTimeBin();
987 
988  // Total number of time bins in DAQ readout is given by fifo_tbins,
989  // which thus determines the maximum length of time interval.
990  if (thisDigiBx >= 0 && thisDigiBx < static_cast<int>(fifo_tbins)) {
991 
992  // If there is more than one hit in the same strip, pick one
993  // which occurred earlier.
994  // In reality, the second hit on the same distrip is ignored only
995  // during the number of clocks defined by the "hit_persist"
996  // parameter (i.e., 6 bx's by default). So if one simulates
997  // a large number of bx's in a crowded environment, this
998  // approximation here may not be sufficiently good.
999  if (time[i][thisStrip] == -999 || time[i][thisStrip] > thisDigiBx) {
1000  digiNum[i][thisStrip] = j;
1001  time[i][thisStrip] = thisDigiBx;
1002  comp[i][thisStrip] = thisComparator;
1003  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1004  << "Comp digi: layer " << i+1
1005  << " digi #" << j+1
1006  << " strip " << thisStrip
1007  << " halfstrip " << 2*thisStrip + comp[i][thisStrip] + stagger[i]
1008  << " distrip " << thisStrip/2 + // [0-39]
1009  ((thisStrip%2 == 1 && comp[i][thisStrip] == 1 && stagger[i] == 1) ? 1 : 0)
1010  << " time " << time[i][thisStrip]
1011  << " comparator " << comp[i][thisStrip]
1012  << " stagger " << stagger[i];
1013  }
1014  }
1015  else {
1016  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1017  << "+++ Skipping comparator digi: strip = " << thisStrip
1018  << ", layer = " << i+1 << ", bx = " << thisDigiBx << " +++";
1019  }
1020  }
1021  }
1022 
1023  // Take the comparator & time info and stuff it into half- and di-strip
1024  // arrays.
1025  for (int i = 0; i < CSCConstants::NUM_LAYERS; i++) {
1026  // Use the comparator info to setup the halfstrips and distrips. -BT
1027  // This loop is only for halfstrips.
1028  for (int j = 0; j < CSCConstants::MAX_NUM_STRIPS_7CFEBS; j++) {
1029  if (time[i][j] >= 0) {
1030  int i_halfstrip = 2*j + comp[i][j] + stagger[i];
1031  // 2*j : convert strip to 1/2 strip
1032  // comp : comparator output
1033  // stagger: stagger for this layer
1034  if (i_halfstrip >= 2*numStrips + 1) {
1035  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
1036  << "+++ Found wrong halfstrip number = " << i_halfstrip
1037  << "; skipping this digi... +++\n";
1038  continue;
1039  }
1040  halfstrip[i][i_halfstrip].push_back(time[i][j]);
1041  }
1042  }
1043 
1044  // There are no di-strips in the 2007 version of the TMB firmware.
1045  if (!isTMB07) {
1046  // This loop is only for distrips. We have to separate the routines
1047  // because triad and time arrays can be changed by the distripStagger
1048  // routine which could mess up the halfstrips.
1049  static std::atomic<int> test_iteration{0};
1050  for (int j = 0; j < CSCConstants::MAX_NUM_STRIPS; j++){
1051  if (time[i][j] >= 0) {
1052  int i_distrip = j/2;
1053  if (j%2 == 1 && comp[i][j] == 1 && stagger[i] == 1) {
1054  // @@ Needs to be checked.
1055  bool stagger_debug = (infoV > 2);
1056  distripStagger(comp[i], time[i], digiNum[i], j, stagger_debug);
1057  }
1058  // comp[i][j] == 1 : hit on right half-strip.
1059  // stagger[i] == 1 : half-strips are shifted by 1.
1060  // if these conditions are met add 1; otherwise add 0.
1061  // So if there is a hit on the far right half-strip, and the
1062  // half-strips have been staggered to the right, then the di-strip
1063  // would actually correspond to the next highest di-strip. -JM
1064  if (infoV > 2 && test_iteration == 1) {
1066  test_iteration++;
1067  }
1068  if (i_distrip >= numStrips/2 + 1) {
1069  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
1070  << "+++ Found wrong distrip number = " << i_distrip
1071  << "; skipping this digi... +++\n";
1072  continue;
1073  }
1074  distrip[i][i_distrip].push_back(time[i][j]);
1075  }
1076  }
1077  }
1078  }
1079 }
1080 
1082  int stag_time[CSCConstants::MAX_NUM_STRIPS_7CFEBS],
1083  int stag_digi[CSCConstants::MAX_NUM_STRIPS_7CFEBS],
1084  int i_strip, bool debug) {
1085  // Author: Jason Mumford (mumford@physics.ucla.edu)
1086  // This routine takes care of the stagger situation where there is a hit
1087  // on the right half-strip of a di-strip. If there is a stagger, then
1088  // we must associate that distrip with the next distrip. The situation
1089  // gets more complicated if the next distrip also has a hit on its right
1090  // half-strip. One could imagine a whole chain of these in which case
1091  // we need to go into this routine recursively. The formula is that
1092  // while this condition is satisfied, we enquire the next distrip,
1093  // until we have a hit on any other halfstrip (or triad!=3). Then we
1094  // must compare the 2 different bx times and take the smallest one.
1095  // Afterwards, we must cycle out of the routine assigning the bx times
1096  // to the one strip over.
1097 
1098  // Used only for pre-TMB07 firmware.
1099 
1100  if (i_strip >= CSCConstants::MAX_NUM_STRIPS) {
1101  if (debug) edm::LogWarning("L1CSCTPEmulatorWrongInput")
1102  << "+++ Found wrong strip number = " << i_strip
1103  << "; cannot apply distrip staggering... +++\n";
1104  return;
1105  }
1106 
1107  if (debug)
1108  LogDebug("CSCCathodeLCTProcessor")
1109  << " Enter distripStagger: i_strip = " << i_strip
1110  << " stag_triad[i_strip] = " << stag_triad[i_strip]
1111  << " stag_time[i_strip] = " << stag_time[i_strip]
1112  << " stag_triad[i_strip+2] = " << stag_triad[i_strip+2]
1113  << " stag_time[i_strip+2] = " << stag_time[i_strip+2];
1114 
1115  // So if the next distrip has a stagger hit, go into the routine again
1116  // for the next distrip.
1117  if (i_strip+2 < CSCConstants::MAX_NUM_STRIPS && stag_triad[i_strip+2] == 1)
1118  distripStagger(stag_triad, stag_time, stag_digi, i_strip+2);
1119 
1120  // When we have reached a distrip that does not have a staggered hit,
1121  // if it has a hit, we compare the bx times of the
1122  // staggered distrip with the non-staggered distrip and we take the
1123  // smallest of the two and assign it to the shifted distrip time.
1124  if (stag_time[i_strip+2] >= 0) {
1125  if (stag_time[i_strip] < stag_time[i_strip+2]) {
1126  stag_time[i_strip+2] = stag_time[i_strip];
1127  stag_digi[i_strip+2] = stag_digi[i_strip];
1128  }
1129  }
1130  // If the next distrip did not have a hit, then we merely assign the
1131  // shifted time to the time associated with the staggered distrip.
1132  else {
1133  stag_time[i_strip+2] = stag_time[i_strip];
1134  stag_digi[i_strip+2] = stag_digi[i_strip];
1135  }
1136 
1137  // Then to prevent previous staggers from being overwritten, we assign
1138  // the unshifted time to -999, and then mark the triads that were shifted
1139  // so that we don't go into the routine ever again (such as when making
1140  // the next loop over strips).
1141  stag_time[i_strip] = -999;
1142  stag_triad[i_strip] = 4;
1143  stag_digi[i_strip] = -999;
1144 
1145  if (debug)
1146  LogDebug("CSCCathodeLCTProcessor")
1147  << " Exit distripStagger: i_strip = " << i_strip
1148  << " stag_triad[i_strip] = " << stag_triad[i_strip]
1149  << " stag_time[i_strip] = " << stag_time[i_strip]
1150  << " stag_triad[i_strip+2] = " << stag_triad[i_strip+2]
1151  << " stag_time[i_strip+2] = " << stag_time[i_strip+2];
1152 }
1153 
1154 // --------------------------------------------------------------------------
1155 // The code below is a description of the idealized CLCT algorithm which
1156 // was used in Monte Carlo studies since early ORCA days and until
1157 // CMSSW_2_0_0 (March 2008) but was never realized in the firmware.
1158 //
1159 // Starting with CMSSW_3_1_0, it may no longer give the same results as
1160 // before since old versions of overloaded < > == operators in CLCTDigi
1161 // class were discarded.
1162 // --------------------------------------------------------------------------
1163 // Idealized version for MC studies.
1164 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], int stripType)
1165 {
1166  int j;
1167  int best_strip = 0;
1168  int first_bx = 999;
1169  const int max_lct_num = 2;
1170  const int adjacent_strips = 2;
1171  // Distrip, halfstrip pattern threshold.
1172  const unsigned int ptrn_thrsh[2] = {nplanes_hit_pattern, nplanes_hit_pattern};
1173  int highest_quality = 0;
1174 
1175  int keystrip_data[CSCConstants::NUM_HALF_STRIPS_7CFEBS][7];
1176  int final_lcts[max_lct_num];
1177 
1178  std::vector <CSCCLCTDigi> lctList;
1179 
1180  int nStrips = 0;
1181  if (stripType == 1) nStrips = 2*numStrips + 1;
1182  else if (stripType == 0) nStrips = numStrips/2 + 1;
1183 
1184  if (infoV > 1) dumpDigis(strip, stripType, nStrips);
1185 
1186  // Send data to a pretrigger so that we don't excessively look at data
1187  // that won't give an LCT. If there is a pretrigger, then get all quality
1188  // and bend for all keystrips.
1189  if (preTrigger(strip, stripType, nStrips, first_bx)){
1190  getKeyStripData(strip, keystrip_data, nStrips, first_bx, best_strip, stripType);
1191 
1192  /* Set all final_lcts to impossible key_strip numbers */
1193  for (j = 0; j < max_lct_num; j++)
1194  final_lcts[j] = -999;
1195 
1196  // Now take the keystrip with the best quality, and do a search over the
1197  // rest of the strips for the next highest quality. Do the search over a
1198  // range excluding a certain number of keystrips adjacent to the original
1199  // best key_strip.
1200  final_lcts[0] = best_strip;
1201 
1202  for (int key_strip = 0; key_strip < (nStrips-stripType); key_strip++){
1203  // If indexed strip does not fall within excluded range, then continue
1204  if (abs(best_strip - key_strip) > adjacent_strips){
1205  // Match with highest quality
1206  if (keystrip_data[key_strip][CLCT_QUALITY] > highest_quality){
1207  highest_quality = keystrip_data[key_strip][CLCT_QUALITY];
1208  final_lcts[1] = key_strip;
1209  }
1210  }
1211  }
1212 
1213  for (j = 0; j < max_lct_num; j++){
1214  // Only report LCTs if the number of layers hit is greater than or
1215  // equal to the (variable) valid pattern threshold ptrn_thrsh.
1216  int keystrip = final_lcts[j];
1217  if (keystrip >= 0 &&
1218  keystrip_data[keystrip][CLCT_QUALITY] >= static_cast<int>(ptrn_thrsh[stripType])) {
1219  // assign the stripType here. 1 = halfstrip, 0 = distrip.
1220  keystrip_data[keystrip][CLCT_STRIP_TYPE] = stripType;
1221  // Now make the LCT words for the 2 highest, and store them in a list
1222  int theHalfStrip = (keystrip_data[keystrip][CLCT_STRIP_TYPE] ?
1223  keystrip_data[keystrip][CLCT_STRIP] :
1224  4*keystrip_data[keystrip][CLCT_STRIP]);
1225  keystrip_data[keystrip][CLCT_CFEB] = theHalfStrip/32;
1226  int halfstrip_in_cfeb =
1227  theHalfStrip - 32*keystrip_data[keystrip][CLCT_CFEB];
1228 
1229  CSCCLCTDigi thisLCT(1, keystrip_data[keystrip][CLCT_QUALITY],
1230  keystrip_data[keystrip][CLCT_PATTERN],
1231  keystrip_data[keystrip][CLCT_STRIP_TYPE],
1232  keystrip_data[keystrip][CLCT_BEND],
1233  halfstrip_in_cfeb,
1234  keystrip_data[keystrip][CLCT_CFEB],
1235  keystrip_data[keystrip][CLCT_BX]);
1236  if (infoV > 2) {
1237  char stripType =
1238  (keystrip_data[keystrip][CLCT_STRIP_TYPE] == 0) ? 'D' : 'H';
1239  char bend =
1240  (keystrip_data[keystrip][CLCT_BEND] == 0) ? 'L' : 'R';
1241  LogTrace("CSCCathodeLCTProcessor")
1242  << " Raw Find: "
1243  << "Key Strip: " << std::setw(3)
1244  << keystrip_data[keystrip][CLCT_STRIP]
1245  << " Pattern: " << std::setw(2)
1246  << keystrip_data[keystrip][CLCT_PATTERN]
1247  << " Bend: " << std::setw(1) << bend
1248  << " Quality: " << std::setw(1)
1249  << keystrip_data[keystrip][CLCT_QUALITY]
1250  << " stripType: " << std::setw(1) << stripType
1251  << " BX: " << std::setw(1)
1252  << keystrip_data[keystrip][CLCT_BX];
1253  }
1254  lctList.push_back(thisLCT);
1255  }
1256  }
1257  }
1258 
1259  return lctList;
1260 } // findLCTs -- idealized version for MC studies.
1261 
1262 
1263 // Idealized version for MC studies.
1265  const int stripType, const int nStrips,
1266  int& first_bx)
1267 {
1268  static const int hs_thresh = nplanes_hit_pretrig;
1269  static const int ds_thresh = nplanes_hit_pretrig;
1270 
1272  int i_layer, i_strip, this_layer, this_strip;
1273  int hits, layers_hit;
1274  bool hit_layer[CSCConstants::NUM_LAYERS];
1275 
1276  const int pre_trigger_layer_min = (stripType == 1) ? hs_thresh : ds_thresh;
1277 
1278  // Fire half-strip/di-strip one-shots for hit_persist bx's (6 bx's by
1279  // default).
1280  pulseExtension(strip, nStrips, pulse);
1281 
1282  // Now do a loop over different bunch-crossing times.
1283  for (unsigned int bx_time = 0; bx_time < fifo_tbins; bx_time++) {
1284  // For any given bunch-crossing, start at the lowest keystrip and look for
1285  // the number of separate layers in the pattern for that keystrip that have
1286  // pulses at that bunch-crossing time. Do the same for the next keystrip,
1287  // etc. Then do the entire process again for the next bunch-crossing, etc
1288  // until you find a pre-trigger.
1289  for (int key_strip = 0; key_strip < nStrips; key_strip++){
1290  // Clear variables
1291  hits = 0;
1292  layers_hit = 0;
1293  for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
1294  hit_layer[i_layer] = false;
1295  // Loop over pattern strips and look for hits.
1296  for (i_strip = 0; i_strip < NUM_PATTERN_STRIPS; i_strip++){
1297  this_layer = pre_hit_pattern[0][i_strip];
1298  this_strip = pre_hit_pattern[1][i_strip]+key_strip;
1299  if (this_strip >= 0 && this_strip < nStrips) {
1300  // Perform bit operation to see if pulse is 1 at a certain bx_time.
1301  if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1) {
1302  hits++;
1303  // Store number of layers hit.
1304  if (hit_layer[this_layer] == false) {
1305  hit_layer[this_layer] = true;
1306  layers_hit++;
1307 
1308  // Look if number of layers hit is greater or equal than some
1309  // pre-defined threshold.
1310  if (layers_hit >= pre_trigger_layer_min) {
1311  first_bx = bx_time;
1312  return true;
1313  }
1314  }
1315  }
1316  }
1317  }
1318  }
1319  }
1320  // If the pretrigger was never satisfied, then return false.
1321  return false;
1322 } // preTrigger -- idealized version for MC studies.
1323 
1324 
1325 // Idealized version for MC studies.
1327  int keystrip_data[CSCConstants::NUM_HALF_STRIPS_7CFEBS][7],
1328  int nStrips, int first_bx, int& best_strip, int stripType) {
1329  int lct_pattern[NUM_PATTERN_STRIPS];
1330  int key_strip, this_layer, this_strip;
1331  int quality, best_quality;
1332  int bend = 0;
1333  int highest_quality = 0;
1334  bool nullPattern;
1335 
1336  for (key_strip = 0; key_strip < nStrips; key_strip++)
1337  for (int i = 0; i < 7; i++)
1338  keystrip_data[key_strip][i] = 0;
1339 
1340  // Now we need to look at all the keystrips and take the best pattern
1341  // for each. There are multiple patterns available for each keystrip.
1342 
1343  for (key_strip = 0; key_strip < (nStrips-stripType); key_strip++){
1344  nullPattern = true;
1345  for (int pattern_strip = 0; pattern_strip < NUM_PATTERN_STRIPS; pattern_strip++){
1346  this_layer = pre_hit_pattern[0][pattern_strip];
1347  this_strip = pre_hit_pattern[1][pattern_strip] + key_strip;
1348  // This conditional statement prevents us from looking at strips
1349  // that don't exist along the chamber boundaries.
1350  if ((this_strip >= 0 && this_strip < nStrips) &&
1351  !strip[this_layer][this_strip].empty()) {
1352  if (nullPattern) nullPattern = false;
1353  std::vector<int> bx_times = strip[this_layer][this_strip];
1354  lct_pattern[pattern_strip] = bx_times[0];
1355  }
1356  else
1357  lct_pattern[pattern_strip] = -999;
1358  }
1359  // do the rest only if there is at least one DIGI in the pattern for
1360  // this keystrip
1361  if (nullPattern) continue;
1362 
1363  // Initialize best_quality to zero so that we can look for best pattern
1364  // within a keystrip.
1365  best_quality = 0;
1366 
1367  // Loop over all possible patterns.
1368  // Loop in reverse order, in order to give priority to a straighter
1369  // pattern (larger pattern_num) in case of equal qualities.
1370  // Exclude pattern 0 since it is not defined.
1371  for (int pattern_num = CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07-1; pattern_num > 0; pattern_num--) {
1372  // Get the pattern quality from lct_pattern.
1373  // TMB latches LCTs drift_delay clocks after pretrigger.
1374  int latch_bx = first_bx + drift_delay;
1375  getPattern(pattern_num, lct_pattern, latch_bx, quality, bend);
1376  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1377  << "Key_strip " << key_strip << " quality of pattern_num "
1378  << pattern_num << ": " << quality;
1379  if (quality > best_quality){
1380  // Store the best pattern, quality, etc., for each key_strip.
1381  keystrip_data[key_strip][CLCT_PATTERN] = pattern_num;
1382  keystrip_data[key_strip][CLCT_BEND] = bend;
1383  keystrip_data[key_strip][CLCT_STRIP] = key_strip;
1384  keystrip_data[key_strip][CLCT_BX] = first_bx;
1385  // keystrip_data[key_strip][CLCT_STRIP_TYPE] = stripType; //assign the stripType elsewhere
1386  keystrip_data[key_strip][CLCT_QUALITY] = quality;
1387  if (quality > highest_quality){
1388  // Keep track of which strip had the highest quality.
1389  // highest_quality refers to the overall highest quality for all
1390  // key strips. This is different than best_quality which refers
1391  // to the best quality in a keystrip from different patterns.
1392  best_strip = key_strip;
1393  highest_quality = quality;
1394  }
1395  best_quality = quality;
1396  }
1397  }
1398  }
1399 } // getKeyStripData -- idealized version for MC studies.
1400 
1401 
1402 // Idealized version for MC studies.
1404  int strip_value[NUM_PATTERN_STRIPS], int bx_time,
1405  int& quality, int& bend){
1406  // This function takes strip values and bx_time to find out which hits fall
1407  // within a certain pattern. Quality, and bend are then calculated based on
1408  // which strip pattern and how many layers were hit within the pattern.
1409  int layers_hit = 0;
1410  bool hit_layer[CSCConstants::NUM_LAYERS];
1411 
1412  // Clear hit_layer array to keep track of number of layers hit.
1413  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
1414  hit_layer[i_layer] = false;
1415 
1416  // Loop over all designated patterns.
1417  for (int strip_num = 0; strip_num < NUM_PATTERN_STRIPS; strip_num++){
1418  if (hitIsGood(strip_value[strip_num], bx_time)){
1419  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++){
1420  // Loop over layer and see if corresponding strip is on same layer
1421  // If so then increment number of hits.
1422  if (i_layer == pattern[pattern_num][strip_num]){
1423  // If layer has no hits, then increment number of layers hit.
1424  if (hit_layer[i_layer] == false){
1425  layers_hit++;
1426  hit_layer[i_layer] = true;
1427  }
1428  }
1429  }
1430  }
1431  }
1432  // Get bend value from pattern.
1433  bend = pattern[pattern_num][NUM_PATTERN_STRIPS];
1434  quality = layers_hit;
1435 } // getPattern -- idealized version for MC studies.
1436 
1437 
1438 // Idealized version for MC studies.
1439 bool CSCCathodeLCTProcessor::hitIsGood(int hitTime, int BX) {
1440  // Find out if hit time is good. Hit should have occurred no more than
1441  // hit_persist clocks before the latching time.
1442  int dt = BX - hitTime;
1443  if (dt >= 0 && dt <= static_cast<int>(hit_persist)) {return true;}
1444  else {return false;}
1445 } // hitIsGood -- idealized version for MC studies.
1446 
1447 
1448 // --------------------------------------------------------------------------
1449 // The code below is a description of the pre-2007 version of the CLCT
1450 // algorithm. It was used in numerous CSC test beams and MTCC for
1451 // firmware-emulator comparisons, but due to a number of known limitations
1452 // it was never used in Monte Carlo studies.
1453 //
1454 // Starting with CMSSW_3_1_0, it may no longer give the same results as
1455 // before since old versions of overloaded < > == operators in CLCTDigi
1456 // class were discarded.
1457 // --------------------------------------------------------------------------
1458 // Pre-2007 version.
1459 std::vector <CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(
1460  const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS],
1461  const std::vector<int> distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
1462  std::vector <CSCCLCTDigi> lctList;
1463  int _bx[2] = {999, 999};
1464  int first_bx = 999;
1465 
1466  const int nhStrips = 2*numStrips + 1;
1467  const int ndStrips = numStrips/2 + 1;
1468 
1469  if (infoV > 1) {
1470  dumpDigis(halfstrip, 1, nhStrips);
1471  dumpDigis(distrip, 0, ndStrips);
1472  }
1473 
1474  // Test beam version of TMB pretrigger and LCT sorting
1475  int h_keyStrip[MAX_CFEBS]; // one key per CFEB
1476  unsigned int h_nhits[MAX_CFEBS]; // number of hits in envelope for each key
1477  int d_keyStrip[MAX_CFEBS]; // one key per CFEB
1478  unsigned int d_nhits[MAX_CFEBS]; // number of hits in envelope for each key
1479  int keystrip_data[2][7]; // 2 possible LCTs per CSC x 7 LCT quantities
1480  unsigned int h_pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]; // simulate digital one-shot
1481  unsigned int d_pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]; // simulate digital one-shot
1482  bool pre_trig[2] = {false, false};
1483 
1484  // All half-strip and di-strip pattern envelopes are evaluated
1485  // simultaneously, on every clock cycle.
1486  pre_trig[0] = preTrigger(halfstrip, h_pulse, 1, nhStrips, 0, _bx[0]);
1487  pre_trig[1] = preTrigger( distrip, d_pulse, 0, ndStrips, 0, _bx[1]);
1488 
1489  // If any of 200 half-strip and di-strip envelopes has enough layers hit in
1490  // it, TMB will pre-trigger.
1491  if (pre_trig[0] || pre_trig[1]) {
1492  first_bx = (_bx[0] < _bx[1]) ? _bx[0] : _bx[1];
1493  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1494  << "half bx " << _bx[0] << " di bx " << _bx[1] << " first " << first_bx
1495  << "\n ..... waiting drift delay ..... ";
1496 
1497  // Empirically-found trick allowing to dramatically improve agreement
1498  // with MTCC-II data.
1499  // The trick is to ignore hits in a few first time bins when latching
1500  // hits for priority encode envelopes. For MTCC-II, we need to ignore
1501  // hits in time bins 0-3 inclusively.
1502  //
1503  // Firmware configuration has been fixed for most of 2007 runs, so
1504  // this trick should NOT be used when emulating 2007 trigger.
1505  /*
1506  int max_bx = 4;
1507  for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++) {
1508  for (int istrip = 0; istrip < CSCConstants::NUM_HALF_STRIPS; istrip++) {
1509  for (int bx = 0; bx < max_bx; bx++) {
1510  if (((h_pulse[ilayer][istrip] >> bx) & 1) == 1) {
1511  h_pulse[ilayer][istrip] = 0;
1512  }
1513  }
1514  }
1515  for (int istrip = 0; istrip < CSCConstants::NUM_DI_STRIPS; istrip++) {
1516  for (int bx = 0; bx < max_bx; bx++) {
1517  if (((d_pulse[ilayer][istrip] >> bx) & 1) == 1) {
1518  d_pulse[ilayer][istrip] = 0;
1519  }
1520  }
1521  }
1522  }
1523  */
1524 
1525  // TMB latches LCTs drift_delay clocks after pretrigger.
1526  int latch_bx = first_bx + drift_delay;
1527  latchLCTs(h_pulse, h_keyStrip, h_nhits, 1, CSCConstants::NUM_HALF_STRIPS,
1528  latch_bx);
1529  latchLCTs(d_pulse, d_keyStrip, d_nhits, 0, CSCConstants::NUM_DI_STRIPS,
1530  latch_bx);
1531 
1532  if (infoV > 1) {
1533  LogTrace("CSCCathodeLCTProcessor")
1534  << "...............................\n"
1535  << "Final halfstrip hits and keys (after drift delay) ...";
1536  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1537  LogTrace("CSCCathodeLCTProcessor")
1538  << "cfeb " << icfeb << " key: " << h_keyStrip[icfeb]
1539  << " hits " << h_nhits[icfeb];
1540  }
1541  LogTrace("CSCCathodeLCTProcessor")
1542  << "Final distrip hits and keys (after drift delay) ...";
1543  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1544  LogTrace("CSCCathodeLCTProcessor")
1545  << "cfeb " << icfeb << " key: " << d_keyStrip[icfeb]
1546  << " hits " << d_nhits[icfeb];
1547  }
1548  }
1549  priorityEncode(h_keyStrip, h_nhits, d_keyStrip, d_nhits, keystrip_data);
1550  getKeyStripData(h_pulse, d_pulse, keystrip_data, first_bx);
1551 
1552  for (int ilct = 0; ilct < 2; ilct++) {
1553  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1554  << "found lcts: ilct " << ilct
1555  << " key strip " << keystrip_data[ilct][CLCT_STRIP];
1556  if (keystrip_data[ilct][CLCT_STRIP] != -1) {
1557  int halfstrip_in_cfeb = 0;
1558  if (keystrip_data[ilct][CLCT_STRIP_TYPE] == 0)
1559  halfstrip_in_cfeb = 4*keystrip_data[ilct][CLCT_STRIP] -
1560  32*keystrip_data[ilct][CLCT_CFEB];
1561  else
1562  halfstrip_in_cfeb = keystrip_data[ilct][CLCT_STRIP] -
1563  32*keystrip_data[ilct][CLCT_CFEB];
1564 
1565  CSCCLCTDigi thisLCT(1, keystrip_data[ilct][CLCT_QUALITY],
1566  keystrip_data[ilct][CLCT_PATTERN],
1567  keystrip_data[ilct][CLCT_STRIP_TYPE],
1568  keystrip_data[ilct][CLCT_BEND],
1569  halfstrip_in_cfeb,
1570  keystrip_data[ilct][CLCT_CFEB],
1571  keystrip_data[ilct][CLCT_BX]);
1572  lctList.push_back(thisLCT);
1573  }
1574  }
1575  }
1576 
1577  return lctList;
1578 
1579 } // findLCTs -- pre-2007 version.
1580 
1581 
1582 // Pre-2007 version.
1584  const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS],
1585  unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS],
1586  const int stripType, const int nStrips,
1587  const int start_bx, int& first_bx) {
1588  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1589  << "....................PreTrigger...........................";
1590 
1591  if (start_bx == 0) {
1592  // Fire one-shots for hit_persist bx's (6 bx's by default).
1593  pulseExtension(strip, nStrips, pulse);
1594  }
1595 
1596  bool pre_trig = false;
1597  // Now do a loop over bx times to see (if/when) track goes over threshold
1598  for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
1599  // For any given bunch-crossing, start at the lowest keystrip and look for
1600  // the number of separate layers in the pattern for that keystrip that have
1601  // pulses at that bunch-crossing time. Do the same for the next keystrip,
1602  // etc. Then do the entire process again for the next bunch-crossing, etc
1603  // until you find a pre-trigger.
1604  pre_trig = preTrigLookUp(pulse, stripType, nStrips, bx_time);
1605  if (pre_trig) {
1606  first_bx = bx_time; // bx at time of pretrigger
1607  return true;
1608  }
1609  } // end loop over bx times
1610 
1611  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1612  << "no pretrigger for strip type " << stripType << ", returning \n";
1613  first_bx = fifo_tbins;
1614  return false;
1615 } // preTrigger -- pre-2007 version.
1616 
1617 
1618 // Pre-2007 version.
1621  const int stripType, const int nStrips,
1622  const unsigned int bx_time) {
1623  static const int hs_thresh = nplanes_hit_pretrig;
1624  static const int ds_thresh = nplanes_hit_pretrig;
1625 
1626  bool hit_layer[CSCConstants::NUM_LAYERS];
1627  int key_strip, this_layer, this_strip, layers_hit;
1628 
1629  // Layers hit threshold for pretrigger
1630  const int pre_trigger_layer_min = (stripType == 1) ? hs_thresh : ds_thresh;
1631 
1632  if (stripType != 0 && stripType != 1) {
1633  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
1634  << "+++ preTrigLookUp: stripType = " << stripType
1635  << " does not correspond to half-strip/di-strip patterns! +++\n";
1636  return false;
1637  }
1638 
1639  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) { // loop over cfebs
1640  // Loop over (di-/half-)strips in CFEB.
1641  for (int istrip = 0; istrip < cfeb_strips[stripType]; istrip++) {
1642  // Calculate candidate key.
1643  key_strip = icfeb*cfeb_strips[stripType] + istrip;
1644  layers_hit = 0;
1645  for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++)
1646  hit_layer[ilayer] = false;
1647 
1648  // Loop over strips in pretrigger pattern mask and look for hits.
1649  for (int pstrip = 0; pstrip < NUM_PATTERN_STRIPS; pstrip++) {
1650  this_layer = pre_hit_pattern[0][pstrip];
1651  this_strip = pre_hit_pattern[1][pstrip]+key_strip;
1652 
1653  if (this_strip >= 0 && this_strip < nStrips) {
1654  // Determine if "one shot" is high at this bx_time
1655  if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1) {
1656  if (hit_layer[this_layer] == false) {
1657  hit_layer[this_layer] = true;
1658  layers_hit++; // determines number of layers hit
1659  if (layers_hit >= pre_trigger_layer_min) {
1660  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1661  << "pretrigger at bx: " << bx_time
1662  << ", cfeb " << icfeb << ", returning";
1663  return true;
1664  }
1665  }
1666  }
1667  }
1668  } // end loop over strips in pretrigger pattern
1669  } // end loop over candidate key strips in cfeb
1670  } // end loop over cfebs, if pretrigger is found, stop looking and return
1671 
1672  return false;
1673 
1674 } // preTrigLookUp -- pre-2007 version.
1675 
1676 
1677 // Pre-2007 version.
1680  int keyStrip[MAX_CFEBS], unsigned int n_hits[MAX_CFEBS],
1681  const int stripType, const int nStrips, const int bx_time) {
1682 
1683  bool hit_layer[CSCConstants::NUM_LAYERS];
1684  int key_strip, this_layer, this_strip;
1685  int layers_hit, prev_hits;
1686 
1687  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1688  keyStrip[icfeb] = -1;
1689  n_hits[icfeb] = 0;
1690  }
1691 
1692  if (stripType != 0 && stripType != 1) {
1693  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorWrongInput")
1694  << "+++ latchLCTs: stripType = " << stripType
1695  << " does not correspond to half-strip/di-strip patterns! +++\n";
1696  return;
1697  }
1698 
1699  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) { // loop over CFEBs
1700  prev_hits = 0;
1701  // Loop over (di-/half-)strips in CFEB.
1702  for (int istrip = 0; istrip < cfeb_strips[stripType]; istrip++) {
1703  // Calculate candidate key.
1704  key_strip = icfeb*cfeb_strips[stripType] + istrip;
1705  layers_hit = 0;
1706  for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++)
1707  hit_layer[ilayer] = false;
1708 
1709  // Loop over strips in pretrigger pattern mask and look for hits.
1710  for (int pstrip = 0; pstrip < NUM_PATTERN_STRIPS; pstrip++) {
1711  this_layer = pre_hit_pattern[0][pstrip];
1712  this_strip = pre_hit_pattern[1][pstrip]+key_strip;
1713 
1714  if (this_strip >= 0 && this_strip < nStrips) {
1715  // Determine if "one shot" is high at this bx_time
1716  if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1) {
1717  if (hit_layer[this_layer] == false) {
1718  hit_layer[this_layer] = true;
1719  layers_hit++; // number of layers hit
1720  }
1721  }
1722  }
1723  } // end loop over strips in pretrigger pattern
1724  if (infoV > 1) {
1725  if (layers_hit > 0) LogTrace("CSCCathodeLCTProcessor")
1726  << "cfeb: " << icfeb << " key_strip: " << key_strip
1727  << " n_hits: " << layers_hit;
1728  }
1729  // If two or more keys have an equal number of hits, the lower number
1730  // key is taken. Hence, replace the previous key only if this key has
1731  // more hits.
1732  if (layers_hit > prev_hits) {
1733  prev_hits = layers_hit;
1734  keyStrip[icfeb] = key_strip; // key with highest hits is LCT key strip
1735  n_hits[icfeb] = layers_hit; // corresponding hits in envelope
1736  }
1737  } // end loop over candidate key strips in cfeb
1738  } // end loop over cfebs
1739 } // latchLCTs -- pre-2007 version.
1740 
1741 
1742 // Pre-2007 version.
1744  const int h_keyStrip[MAX_CFEBS], const unsigned int h_nhits[MAX_CFEBS],
1745  const int d_keyStrip[MAX_CFEBS], const unsigned int d_nhits[MAX_CFEBS],
1746  int keystrip_data[2][7]) {
1747  static const unsigned int hs_thresh = nplanes_hit_pretrig;
1748  //static const unsigned int ds_thresh = nplanes_hit_pretrig;
1749 
1750  int ihits[2]; // hold hits for sorting
1751  int cfebs[2]; // holds CFEB numbers corresponding to highest hits
1752  const int nlcts = 2;
1753  int key_strip[MAX_CFEBS], key_phits[MAX_CFEBS], strip_type[MAX_CFEBS];
1754 
1755  // initialize arrays
1756  for (int ilct = 0; ilct < nlcts; ilct++) {
1757  for (int j = 0; j < 7; j++) keystrip_data[ilct][j] = -1;
1758  ihits[ilct] = 0;
1759  cfebs[ilct] = -1;
1760  }
1761  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1762  key_strip[icfeb] = -1;
1763  key_phits[icfeb] = -1;
1764  strip_type[icfeb] = -1;
1765  }
1766 
1767  if (infoV > 1) {
1768  LogTrace("CSCCathodeLCTProcessor")
1769  << ".....................PriorityEncode.......................";
1770  std::ostringstream strstrm;
1771  strstrm << "hkeys:";
1772  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1773  strstrm << std::setw(4) << h_keyStrip[icfeb];
1774  }
1775  strstrm << "\ndkeys:";
1776  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1777  strstrm << std::setw(4) << d_keyStrip[icfeb];
1778  }
1779  LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
1780  }
1781 
1782  // Loop over CFEBs and determine better of half- or di- strip pattern.
1783  // If select halfstrip, promote it by adding an extra bit to its hits.
1784  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1785  if (h_keyStrip[icfeb] != -1 && d_keyStrip[icfeb] != -1) {
1786  if (h_nhits[icfeb] >= hs_thresh) {
1787  key_strip[icfeb] = h_keyStrip[icfeb];
1788  key_phits[icfeb] = h_nhits[icfeb] + 8; // halfstrip promotion
1789  strip_type[icfeb]= 1;
1790  }
1791  // For di-strip envelope there is no requirement that the number of
1792  // layers hit is >= ds_thresh!!!
1793  // else if (d_nhits[icfeb] >= ds_thresh) {
1794  else {
1795  key_strip[icfeb] = d_keyStrip[icfeb];
1796  key_phits[icfeb] = d_nhits[icfeb];
1797  strip_type[icfeb]= 0;
1798  }
1799  }
1800  else if (h_keyStrip[icfeb] != -1) {
1801  if (h_nhits[icfeb] >= hs_thresh) {
1802  key_strip[icfeb] = h_keyStrip[icfeb];
1803  key_phits[icfeb] = h_nhits[icfeb] + 8; // halfstrip promotion
1804  strip_type[icfeb]= 1;
1805  }
1806  }
1807  else if (d_keyStrip[icfeb] != -1) {
1808  // if (d_nhits[icfeb] >= ds_thresh) {
1809  key_strip[icfeb] = d_keyStrip[icfeb];
1810  key_phits[icfeb] = d_nhits[icfeb];
1811  strip_type[icfeb]= 0;
1812  // }
1813  }
1814  if (infoV > 1 && strip_type[icfeb] != -1) {
1815  if (strip_type[icfeb] == 0)
1816  LogTrace("CSCCathodeLCTProcessor")
1817  << " taking distrip pattern on cfeb " << icfeb;
1818  else if (strip_type[icfeb] == 1)
1819  LogTrace("CSCCathodeLCTProcessor")
1820  << " taking halfstrip pattern on cfeb " << icfeb;
1821  LogTrace("CSCCathodeLCTProcessor")
1822  << " cfeb " << icfeb << " key " << key_strip[icfeb]
1823  << " hits " << key_phits[icfeb] << " type " << strip_type[icfeb];
1824  }
1825  }
1826 
1827  // Remove duplicate LCTs at boundaries -- it is possilbe to have key[0]
1828  // be the higher of the two key strips, take this into account, but
1829  // preserve rank of lcts.
1830  int key[MAX_CFEBS];
1831  int loedge, hiedge;
1832 
1833  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1834  << "...... Remove Duplicates ......";
1835  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1836  if(strip_type[icfeb] == 0) key[icfeb] = key_strip[icfeb]*4;
1837  else key[icfeb] = key_strip[icfeb];
1838  }
1839  for (int icfeb = 0; icfeb < MAX_CFEBS-1; icfeb++) {
1840  if (key[icfeb] >= 0 && key[icfeb+1] >= 0) {
1841  loedge = cfeb_strips[1]*(icfeb*8+7)/8;
1842  hiedge = cfeb_strips[1]*(icfeb*8+9)/8 - 1;
1843  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1844  << " key 1: " << key[icfeb] << " key 2: " << key[icfeb+1]
1845  << " low edge: " << loedge << " high edge: " << hiedge;
1846  if (key[icfeb] >= loedge && key[icfeb+1] <= hiedge) {
1847  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1848  << "Duplicate LCTs found at boundary of CFEB " << icfeb << " ...";
1849  if (key_phits[icfeb+1] > key_phits[icfeb]) {
1850  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1851  << " deleting LCT on CFEB " << icfeb;
1852  key_strip[icfeb] = -1;
1853  key_phits[icfeb] = -1;
1854  }
1855  else {
1856  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1857  << " deleting LCT on CFEB " << icfeb+1;
1858  key_strip[icfeb+1] = -1;
1859  key_phits[icfeb+1] = -1;
1860  }
1861  }
1862  }
1863  }
1864 
1865  // Now loop over CFEBs and pick best two lcts based on no. hits in envelope.
1866  // In case of equal quality, select the one on lower-numbered CFEBs.
1867  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1868  << "\n...... Select best LCTs ......";
1869  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1870  if (key_phits[icfeb] > ihits[0]) {
1871  ihits[1] = ihits[0];
1872  cfebs[1] = cfebs[0];
1873  ihits[0] = key_phits[icfeb];
1874  cfebs[0] = icfeb;
1875  if (infoV > 1) {
1876  std::ostringstream strstrm;
1877  for (int icfeb = 0; icfeb < MAX_CFEBS; icfeb++) {
1878  strstrm << std::setw(4) << strip_type[icfeb];
1879  }
1880  LogTrace("CSCCathodeLCTProcessor")
1881  << "strip_type" << strstrm.str()
1882  << "\n best: ihits " << ihits[0] << " cfeb " << cfebs[0]
1883  << " strip_type " << ((cfebs[0] >= 0) ? strip_type[cfebs[0]] : -1)
1884  << "\n next: ihits " << ihits[1] << " cfeb " << cfebs[1]
1885  << " strip_type " << ((cfebs[1] >= 0) ? strip_type[cfebs[1]] : -1);
1886  }
1887  }
1888  else if (key_phits[icfeb] > ihits[1]) {
1889  ihits[1] = key_phits[icfeb];
1890  cfebs[1] = icfeb;
1891  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1892  << "\n next: ihits " << ihits[1] << " cfeb " << cfebs[1]
1893  << " strip_type " << ((cfebs[1] >= 0) ? strip_type[cfebs[1]] : -1);
1894  }
1895  }
1896 
1897  // fill lct data array key strip with 2 highest hit lcts (if they exist)
1898  int jlct = 0;
1899  for (int ilct = 0; ilct < nlcts; ilct++) {
1900  if (cfebs[ilct] != -1) {
1901  keystrip_data[jlct][CLCT_CFEB] = cfebs[ilct];
1902  keystrip_data[jlct][CLCT_STRIP] = key_strip[cfebs[ilct]];
1903  keystrip_data[jlct][CLCT_STRIP_TYPE] = strip_type[cfebs[ilct]];
1904  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1905  << "filling key: " << key_strip[cfebs[ilct]]
1906  << " type: " << strip_type[cfebs[ilct]];
1907  jlct++;
1908  }
1909  }
1910 } // priorityEncode -- pre-2007 version.
1911 
1912 
1913 // Pre-2007 version.
1916  const unsigned int d_pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS],
1917  int keystrip_data[2][7], const int first_bx) {
1918 
1919  int lct_pattern[NUM_PATTERN_STRIPS];
1920  int this_layer, this_strip;
1921  unsigned int quality = 0, bend = 0;
1922  unsigned int best_quality, best_pattern;
1923  bool valid[2] = {false,false};
1924 
1925  // Time at which TMB latches LCTs.
1926  int latch_bx = first_bx + drift_delay;
1927 
1928  // Look at keystrips determined from priorityEncode and find their best
1929  // pattern based on number of hits matching that pattern (quality). Also
1930  // find bend angle. There are multiple patterns available for each keystrip.
1931 
1932  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1933  << "...............getKeyStripData....................";
1934 
1935  for (int ilct = 0; ilct < 2; ilct++) {
1936  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1937  << "lct " << ilct << " keystrip " << keystrip_data[ilct][CLCT_STRIP]
1938  << " type " << keystrip_data[ilct][CLCT_STRIP_TYPE];
1939  if (keystrip_data[ilct][CLCT_STRIP] == -1) {// flag set in priorityEncode()
1940  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1941  << "no lct at ilct " << ilct;
1942  continue;
1943  }
1944  for (int pattern_strip = 0; pattern_strip < NUM_PATTERN_STRIPS;
1945  pattern_strip++) {
1946  lct_pattern[pattern_strip] = -999;
1947  this_layer = pre_hit_pattern[0][pattern_strip];
1948  this_strip = pre_hit_pattern[1][pattern_strip] +
1949  keystrip_data[ilct][CLCT_STRIP];
1950  // This conditional statement prevents us from looking at strips
1951  // that don't exist along the chamber boundaries.
1952  if (keystrip_data[ilct][CLCT_STRIP_TYPE] == 1) {
1953  if (this_strip >= 0 && this_strip < CSCConstants::NUM_HALF_STRIPS) {
1954  // Now look at one-shots in bx where TMB latches the LCTs
1955  if (((h_pulse[this_layer][this_strip] >> latch_bx) & 1) == 1)
1956  lct_pattern[pattern_strip] = 1;
1957  }
1958  }
1959  else {
1960  if (this_strip >= 0 && this_strip < CSCConstants::NUM_DI_STRIPS) {
1961  // Now look at one-shots in bx where TMB latches the LCTs
1962  if (((d_pulse[this_layer][this_strip] >> latch_bx) & 1) == 1)
1963  lct_pattern[pattern_strip] = 1;
1964  }
1965  }
1966  }
1967 
1968  // Find best pattern and quality associated with key by looping over all
1969  // possible patterns
1970  best_quality = 0;
1971  best_pattern = 0;
1972 
1973  for (unsigned int pattern_num = 0;
1974  pattern_num < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; pattern_num++) {
1975  getPattern(pattern_num, lct_pattern, quality, bend);
1976  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1977  << "pattern " << pattern_num << " quality " << quality
1978  << " bend " << bend;
1979  // Number of layers hit matching a pattern template is compared
1980  // to nplanes_hit_pattern. The threshold is the same for both half- and
1981  // di-strip patterns.
1982  if (quality >= nplanes_hit_pattern) {
1983  // If the number of matches is the same for two pattern templates,
1984  // the higher pattern-template number is selected.
1985  if ((quality == best_quality && pattern_num > best_pattern) ||
1986  (quality > best_quality)) {
1987  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
1988  << "valid = true at quality " << quality
1989  << " thresh " << nplanes_hit_pattern;
1990  valid[ilct] = true;
1991  keystrip_data[ilct][CLCT_PATTERN] = pattern_num;
1992  keystrip_data[ilct][CLCT_BEND] = bend;
1993  keystrip_data[ilct][CLCT_BX] = first_bx;
1994  //keystrip_data[ilct][CLCT_STRIP_TYPE] = stripType;
1995  keystrip_data[ilct][CLCT_QUALITY] = quality;
1996  best_quality = quality;
1997  best_pattern = pattern_num;
1998  }
1999  }
2000  }
2001 
2002  if (!valid[ilct]) {
2003  keystrip_data[ilct][CLCT_STRIP] = -1; // delete lct
2004  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
2005  << "lct " << ilct << " not over threshold: deleting";
2006  }
2007  else {
2008  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
2009  << "\n" << "--------- final LCT: " << ilct << " -------------\n"
2010  << " key strip " << keystrip_data[ilct][CLCT_STRIP]
2011  << " pattern_num " << keystrip_data[ilct][CLCT_PATTERN]
2012  << " quality " << keystrip_data[ilct][CLCT_QUALITY]
2013  << " bend " << keystrip_data[ilct][CLCT_BEND]
2014  << " bx " << keystrip_data[ilct][CLCT_BX]
2015  << " type " << keystrip_data[ilct][CLCT_STRIP_TYPE] << "\n";
2016  }
2017  } // end loop over lcts
2018 } // getKeyStripData -- pre-2007 version.
2019 
2020 
2021 // Pre-2007 version.
2022 void CSCCathodeLCTProcessor::getPattern(unsigned int pattern_num,
2023  const int strip_value[NUM_PATTERN_STRIPS],
2024  unsigned int& quality, unsigned int& bend) {
2025 
2026  // This function takes strip "one-shots" at the correct bx to find out
2027  // which hits fall within a certain pattern. Quality and bend are then
2028  // calculated based on which strip pattern and how many layers were hit
2029  // within the pattern.
2030 
2031  unsigned int layers_hit = 0;
2032  bool hit_layer[CSCConstants::NUM_LAYERS];
2033 
2034  // Clear hit_layer array to keep track of number of layers hit.
2035  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
2036  hit_layer[i_layer] = false;
2037 
2038  // Loop over all designated patterns.
2039  for (int strip_num = 0; strip_num < NUM_PATTERN_STRIPS; strip_num++){
2040  if (strip_value[strip_num] == 1){
2041  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++){
2042  // Loop over layer and see if corresponding strip is on same layer
2043  // If so then increment number of hits.
2044  if (i_layer == pattern[pattern_num][strip_num]){
2045  // If layer has no hits, then increment number of layers hit.
2046  if (hit_layer[i_layer] == false){
2047  layers_hit++;
2048  hit_layer[i_layer] = true;
2049  }
2050  }
2051  }
2052  }
2053  }
2054  // Get bend value from pattern.
2055  bend = pattern[pattern_num][NUM_PATTERN_STRIPS];
2056  quality = layers_hit;
2057 
2058 } // getPattern -- pre-2007 version.
2059 
2060 
2061 // --------------------------------------------------------------------------
2062 // The code below is a description of the 2007 version of the CLCT
2063 // algorithm (half-strips only). It was first used in 2008 CRUZET runs,
2064 // and later in CRAFT. The algorithm became the default version for
2065 // Monte Carlo studies in March 2008 (CMSSW_2_0_0).
2066 // --------------------------------------------------------------------------
2067 // TMB-07 version.
2068 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
2069  std::vector<CSCCLCTDigi> lctList;
2070 
2071  // Max. number of half-strips for this chamber.
2072  const int maxHalfStrips = 2*numStrips + 1;
2073 
2074  if (infoV > 1) dumpDigis(halfstrip, 1, maxHalfStrips);
2075 
2076  // Test beam version of TMB pretrigger and LCT sorting
2077  enum {max_lcts = 2};
2078  // 2 possible LCTs per CSC x 7 LCT quantities
2079  int keystrip_data[max_lcts][7] = {{0}};
2081 
2082  // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
2083  pulseExtension(halfstrip, maxHalfStrips, pulse);
2084 
2085  unsigned int start_bx = start_bx_shift;
2086  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
2087  // not have a full set of hits to start pattern search anyway.
2088  unsigned int stop_bx = fifo_tbins - drift_delay;
2089  // Allow for more than one pass over the hits in the time window.
2090  while (start_bx < stop_bx) {
2091  // All half-strip pattern envelopes are evaluated simultaneously, on every
2092  // clock cycle.
2093  int first_bx = 999;
2094  bool pre_trig = preTrigger(pulse, start_bx, first_bx);
2095 
2096  // If any of half-strip envelopes has enough layers hit in it, TMB
2097  // will pre-trigger.
2098  if (pre_trig) {
2099  thePreTriggerBXs.push_back(first_bx);
2100  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
2101  << "..... pretrigger at bx = " << first_bx
2102  << "; waiting drift delay .....";
2103 
2104  // TMB latches LCTs drift_delay clocks after pretrigger.
2105  int latch_bx = first_bx + drift_delay;
2106  bool hits_in_time = ptnFinding(pulse, maxHalfStrips, latch_bx);
2107  if (infoV > 1) {
2108  if (hits_in_time) {
2109  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
2110  hstrip < maxHalfStrips; hstrip++) {
2111  if (nhits[hstrip] > 0) {
2112  LogTrace("CSCCathodeLCTProcessor")
2113  << " bx = " << std::setw(2) << latch_bx << " --->"
2114  << " halfstrip = " << std::setw(3) << hstrip
2115  << " best pid = " << std::setw(2) << best_pid[hstrip]
2116  << " nhits = " << nhits[hstrip];
2117  }
2118  }
2119  }
2120  }
2121  // The pattern finder runs continuously, so another pre-trigger
2122  // could occur already at the next bx.
2123  start_bx = first_bx + 1;
2124 
2125  // Quality for sorting.
2127  int best_halfstrip[max_lcts], best_quality[max_lcts];
2128  for (int ilct = 0; ilct < max_lcts; ilct++) {
2129  best_halfstrip[ilct] = -1;
2130  best_quality[ilct] = 0;
2131  }
2132 
2133  // Calculate quality from pattern id and number of hits, and
2134  // simultaneously select best-quality LCT.
2135  if (hits_in_time) {
2136  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
2137  hstrip < maxHalfStrips; hstrip++) {
2138  // The bend-direction bit pid[0] is ignored (left and right
2139  // bends have equal quality).
2140  quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
2141  if (quality[hstrip] > best_quality[0]) {
2142  best_halfstrip[0] = hstrip;
2143  best_quality[0] = quality[hstrip];
2144  }
2145  if (infoV > 1 && quality[hstrip] > 0) {
2146  LogTrace("CSCCathodeLCTProcessor")
2147  << " 1st CLCT: halfstrip = " << std::setw(3) << hstrip
2148  << " quality = " << std::setw(3) << quality[hstrip]
2149  << " best halfstrip = " << std::setw(3) << best_halfstrip[0]
2150  << " best quality = " << std::setw(3) << best_quality[0];
2151  }
2152  }
2153  }
2154 
2155  // If 1st best CLCT is found, look for the 2nd best.
2156  if (best_halfstrip[0] >= 0) {
2157  // Mark keys near best CLCT as busy by setting their quality to
2158  // zero, and repeat the search.
2159  markBusyKeys(best_halfstrip[0], best_pid[best_halfstrip[0]], quality);
2160 
2161  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
2162  hstrip < maxHalfStrips; hstrip++) {
2163  if (quality[hstrip] > best_quality[1]) {
2164  best_halfstrip[1] = hstrip;
2165  best_quality[1] = quality[hstrip];
2166  }
2167  if (infoV > 1 && quality[hstrip] > 0) {
2168  LogTrace("CSCCathodeLCTProcessor")
2169  << " 2nd CLCT: halfstrip = " << std::setw(3) << hstrip
2170  << " quality = " << std::setw(3) << quality[hstrip]
2171  << " best halfstrip = " << std::setw(3) << best_halfstrip[1]
2172  << " best quality = " << std::setw(3) << best_quality[1];
2173  }
2174  }
2175 
2176  // Pattern finder.
2177  bool ptn_trig = false;
2178  for (int ilct = 0; ilct < max_lcts; ilct++) {
2179  int best_hs = best_halfstrip[ilct];
2180  if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
2181  ptn_trig = true;
2182  keystrip_data[ilct][CLCT_PATTERN] = best_pid[best_hs];
2183  keystrip_data[ilct][CLCT_BEND] =
2185  // Remove stagger if any.
2186  keystrip_data[ilct][CLCT_STRIP] =
2188  keystrip_data[ilct][CLCT_BX] = first_bx;
2189  keystrip_data[ilct][CLCT_STRIP_TYPE] = 1; // obsolete
2190  keystrip_data[ilct][CLCT_QUALITY] = nhits[best_hs];
2191  keystrip_data[ilct][CLCT_CFEB] =
2192  keystrip_data[ilct][CLCT_STRIP]/cfeb_strips[1];
2193  int halfstrip_in_cfeb = keystrip_data[ilct][CLCT_STRIP] -
2194  cfeb_strips[1]*keystrip_data[ilct][CLCT_CFEB];
2195 
2196  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
2197  << " Final selection: ilct " << ilct
2198  << " key halfstrip " << keystrip_data[ilct][CLCT_STRIP]
2199  << " quality " << keystrip_data[ilct][CLCT_QUALITY]
2200  << " pattern " << keystrip_data[ilct][CLCT_PATTERN]
2201  << " bx " << keystrip_data[ilct][CLCT_BX];
2202 
2203  CSCCLCTDigi thisLCT(1, keystrip_data[ilct][CLCT_QUALITY],
2204  keystrip_data[ilct][CLCT_PATTERN],
2205  keystrip_data[ilct][CLCT_STRIP_TYPE],
2206  keystrip_data[ilct][CLCT_BEND],
2207  halfstrip_in_cfeb,
2208  keystrip_data[ilct][CLCT_CFEB],
2209  keystrip_data[ilct][CLCT_BX]);
2210  lctList.push_back(thisLCT);
2211  }
2212  }
2213 
2214  if (ptn_trig) {
2215  // Once there was a trigger, CLCT pre-trigger state machine
2216  // checks the number of hits that lie on a pattern template
2217  // at every bx, and waits for it to drop below threshold.
2218  // The search for CLCTs resumes only when the number of hits
2219  // drops below threshold.
2220  start_bx = fifo_tbins;
2221  // Stop checking drift_delay bx's short of fifo_tbins since
2222  // at later bx's we won't have a full set of hits for a
2223  // pattern search anyway.
2224  unsigned int stop_time = fifo_tbins - drift_delay;
2225  for (unsigned int bx = latch_bx + 1; bx < stop_time; bx++) {
2226  bool return_to_idle = true;
2227  bool hits_in_time = ptnFinding(pulse, maxHalfStrips, bx);
2228  if (hits_in_time) {
2229  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
2230  hstrip < maxHalfStrips; hstrip++) {
2231  if (nhits[hstrip] >= nplanes_hit_pattern) {
2232  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
2233  << " State machine busy at bx = " << bx;
2234  return_to_idle = false;
2235  break;
2236  }
2237  }
2238  }
2239  if (return_to_idle) {
2240  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
2241  << " State machine returns to idle state at bx = " << bx;
2242  start_bx = bx;
2243  break;
2244  }
2245  }
2246  }
2247  }
2248  }
2249  else {
2250  start_bx = first_bx + 1; // no dead time
2251  }
2252  }
2253 
2254  return lctList;
2255 } // findLCTs -- TMB-07 version.
2256 
2257 
2258 // Common to all versions.
2261  const int nStrips,
2262  unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS]) {
2263 
2264  static const unsigned int bits_in_pulse = 8*sizeof(pulse[0][0]);
2265 
2266  // Clear pulse array. This array will be used as a bit representation of
2267  // hit times. For example: if strip[1][2] has a value of 3, then 1 shifted
2268  // left 3 will be bit pattern of pulse[1][2]. This would make the pattern
2269  // look like 0000000000001000. Then add on additional bits to signify
2270  // the duration of a signal (hit_persist, formerly bx_width) to simulate
2271  // the TMB's drift delay. So for the same pulse[1][2] with a hit_persist
2272  // of 3 would look like 0000000000111000. This is similating the digital
2273  // one-shot in the TMB.
2274  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
2275  for (int i_strip = 0; i_strip < nStrips; i_strip++)
2276  pulse[i_layer][i_strip] = 0;
2277 
2278  // Loop over all layers and halfstrips.
2279  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
2280  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
2281  // If there is a hit, simulate digital one-shot persistence starting
2282  // in the bx of the initial hit. Fill this into pulse[][].
2283  if (time[i_layer][i_strip].size() > 0) {
2284  std::vector<int> bx_times = time[i_layer][i_strip];
2285  for (unsigned int i = 0; i < bx_times.size(); i++) {
2286  // Check that min and max times are within the allowed range.
2287  if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
2288  if (infoV > 0) edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
2289  << "+++ BX time of comparator digi (halfstrip = " << i_strip
2290  << " layer = " << i_layer << ") bx = " << bx_times[i]
2291  << " is not within the range (0-" << bits_in_pulse
2292  << "] allowed for pulse extension. Skip this digi! +++\n";
2293  continue;
2294  }
2295  if (bx_times[i] >= start_bx_shift) {
2296  for (unsigned int bx = bx_times[i]; bx < bx_times[i] + hit_persist; ++bx)
2297  pulse[i_layer][i_strip] = pulse[i_layer][i_strip] | (1 << bx);
2298  }
2299  }
2300  }
2301  }
2302  }
2303 } // pulseExtension.
2304 
2305 
2306 // TMB-07 version.
2309  const int start_bx, int& first_bx) {
2310  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor")
2311  << "....................PreTrigger...........................";
2312 
2313  // Max. number of half-strips for this chamber.
2314  const int nStrips = 2*numStrips + 1;
2315 
2316  bool pre_trig = false;
2317  // Now do a loop over bx times to see (if/when) track goes over threshold
2318  for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
2319  // For any given bunch-crossing, start at the lowest keystrip and look for
2320  // the number of separate layers in the pattern for that keystrip that have
2321  // pulses at that bunch-crossing time. Do the same for the next keystrip,
2322  // etc. Then do the entire process again for the next bunch-crossing, etc
2323  // until you find a pre-trigger.
2324  bool hits_in_time = ptnFinding(pulse, nStrips, bx_time);
2325  if (hits_in_time) {
2326  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER-1];
2327  hstrip < nStrips; hstrip++) {
2328  if (infoV > 1) {
2329  if (nhits[hstrip] > 0) {
2330  LogTrace("CSCCathodeLCTProcessor")
2331  << " bx = " << std::setw(2) << bx_time << " --->"
2332  << " halfstrip = " << std::setw(3) << hstrip
2333  << " best pid = " << std::setw(2) << best_pid[hstrip]
2334  << " nhits = " << nhits[hstrip];
2335  }
2336  }
2337  ispretrig[hstrip] = 0;
2338  if (nhits[hstrip] >= nplanes_hit_pretrig &&
2339  best_pid[hstrip] >= pid_thresh_pretrig) {
2340  pre_trig = true;
2341  ispretrig[hstrip] = 1;
2342  }
2343  }
2344 
2345  if (pre_trig) {
2346  first_bx = bx_time; // bx at time of pretrigger
2347  return true;
2348  }
2349  }
2350  } // end loop over bx times
2351 
2352  if (infoV > 1) LogTrace("CSCCathodeLCTProcessor") <<
2353  "no pretrigger, returning \n";
2354  first_bx = fifo_tbins;
2355  return false;
2356 } // preTrigger -- TMB-07 version.
2357 
2358 
2359 // TMB-07 version.
2362  const int nStrips, const unsigned int bx_time)
2363 {
2364  if (bx_time >= fifo_tbins) return false;
2365 
2366  // This loop is a quick check of a number of layers hit at bx_time: since
2367  // most of the time it is 0, this check helps to speed-up the execution
2368  // substantially.
2369  unsigned int layers_hit = 0;
2370  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
2371  {
2372  for (int i_hstrip = 0; i_hstrip < nStrips; i_hstrip++)
2373  {
2374  if (((pulse[i_layer][i_hstrip] >> bx_time) & 1) == 1)
2375  {
2376  layers_hit++;
2377  break;
2378  }
2379  }
2380  }
2381  if (layers_hit < nplanes_hit_pretrig) return false;
2382 
2383  for (int key_hstrip = 0; key_hstrip < nStrips; key_hstrip++)
2384  {
2385  best_pid[key_hstrip] = 0;
2386  nhits[key_hstrip] = 0;
2387  first_bx_corrected[key_hstrip] = -999;
2388  }
2389 
2390  // Loop over candidate key strips.
2391  bool hit_layer[CSCConstants::NUM_LAYERS];
2392  for (int key_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; key_hstrip < nStrips; key_hstrip++)
2393  {
2394  // Loop over patterns and look for hits matching each pattern.
2395  for (unsigned int pid = CSCConstants::NUM_CLCT_PATTERNS - 1; pid >= pid_thresh_pretrig; pid--)
2396  {
2397  layers_hit = 0;
2398  for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++)
2399  hit_layer[ilayer] = false;
2400 
2401  double num_pattern_hits=0., times_sum=0.;
2402  std::multiset<int> mset_for_median;
2403  mset_for_median.clear();
2404 
2405  // Loop over halfstrips in trigger pattern mask and calculate the
2406  // "absolute" halfstrip number for each.
2407  for (int strip_num = 0; strip_num < NUM_PATTERN_HALFSTRIPS; strip_num++)
2408  {
2409  int this_layer = pattern2007[pid][strip_num];
2410  if (this_layer >= 0 && this_layer < CSCConstants::NUM_LAYERS)
2411  {
2412  int this_strip = pattern2007_offset[strip_num] + key_hstrip;
2413  if (this_strip >= 0 && this_strip < nStrips) {
2414  if (infoV > 3) LogTrace("CSCCathodeLCTProcessor")
2415  << " In ptnFinding: key_strip = " << key_hstrip
2416  << " pid = " << pid << " strip_num = " << strip_num
2417  << " layer = " << this_layer << " strip = " << this_strip;
2418  // Determine if "one shot" is high at this bx_time
2419  if (((pulse[this_layer][this_strip] >> bx_time) & 1) == 1)
2420  {
2421  if (hit_layer[this_layer] == false)
2422  {
2423  hit_layer[this_layer] = true;
2424  layers_hit++; // determines number of layers hit
2425  }
2426 
2427  // find at what bx did pulse on this halsfstrip&layer have started
2428  // use hit_pesrist constraint on how far back we can go
2429  int first_bx_layer = bx_time;
2430  for (unsigned int dbx = 0; dbx < hit_persist; dbx++)
2431  {
2432  if (((pulse[this_layer][this_strip] >> (first_bx_layer - 1)) & 1) == 1)
2433  first_bx_layer--;
2434  else
2435  break;
2436  }
2437  times_sum += (double) first_bx_layer;
2438  num_pattern_hits += 1.;
2439  mset_for_median.insert(first_bx_layer);
2440  if (infoV > 2)
2441  LogTrace("CSCCathodeLCTProcessor") << " 1st bx in layer: " << first_bx_layer << " sum bx: " << times_sum
2442  << " #pat. hits: " << num_pattern_hits;
2443  }
2444  }
2445  }
2446  } // end loop over strips in pretrigger pattern
2447 
2448  if (layers_hit > nhits[key_hstrip])
2449  {
2450  best_pid[key_hstrip] = pid;
2451  nhits[key_hstrip] = layers_hit;
2452 
2453  // calculate median
2454  const int sz = mset_for_median.size();
2455  if (sz>0){
2456  std::multiset<int>::iterator im = mset_for_median.begin();
2457  if (sz>1) std::advance(im,sz/2-1);
2458  if (sz==1) first_bx_corrected[key_hstrip] = *im;
2459  else if ((sz % 2) == 1) first_bx_corrected[key_hstrip] = *(++im);
2460  else first_bx_corrected[key_hstrip] = ((*im) + (*(++im)))/2;
2461 
2462  if (infoV > 1) {
2463  char bxs[300]="";
2464  for (im = mset_for_median.begin(); im != mset_for_median.end(); im++)
2465  sprintf(bxs,"%s %d", bxs, *im);
2466  LogTrace("CSCCathodeLCTProcessor")
2467  <<"bx="<<bx_time<<" bx_cor="<< first_bx_corrected[key_hstrip]<<" bxset="<<bxs;
2468  }
2469  }
2470 
2471  // Do not loop over the other (worse) patterns if max. numbers of
2472  // hits is found.
2473  if (nhits[key_hstrip] == CSCConstants::NUM_LAYERS) break;
2474  }
2475  } // end loop over pid
2476  } // end loop over candidate key strips
2477  return true;
2478 } // ptnFinding -- TMB-07 version.
2479 
2480 
2481 // TMB-07 version.
2482 void CSCCathodeLCTProcessor::markBusyKeys(const int best_hstrip,
2483  const int best_patid,
2485  int nspan = min_separation;
2486  int pspan = min_separation;
2487 
2488  // if dynamic spacing is enabled, separation is defined by pattern width
2489  //if (dynamic_spacing)
2490  // nspan = pspan = pattern2007[best_patid][NUM_PATTERN_HALFSTRIPS+1]-1;
2491 
2492  for (int hstrip = best_hstrip-nspan; hstrip <= best_hstrip+pspan; hstrip++) {
2493  if (hstrip >= 0 && hstrip < CSCConstants::NUM_HALF_STRIPS_7CFEBS) {
2494  quality[hstrip] = 0;
2495  }
2496  }
2497 } // markBusyKeys -- TMB-07 version.
2498 
2499 
2500 
2501 // --------------------------------------------------------------------------
2502 // The code below is for SLHC studies of the CLCT algorithm (half-strips only).
2503 // --------------------------------------------------------------------------
2504 // SLHC version.
2505 std::vector<CSCCLCTDigi>
2507 {
2508  std::vector<CSCCLCTDigi> lctList;
2509 
2510  // Max. number of half-strips for this chamber.
2511  const int maxHalfStrips = 2 * numStrips + 1;
2512 
2513  if (infoV > 1) dumpDigis(halfstrip, 1, maxHalfStrips);
2514 
2515  enum { max_lcts = 2 };
2516 
2517  // keeps dead-time zones around key halfstrips of triggered CLCTs
2519  for (int i = 0; i < CSCConstants::NUM_HALF_STRIPS_7CFEBS; i++)
2520  for (int j = 0; j < MAX_CLCT_BINS; j++)
2521  busyMap[i][j] = false;
2522 
2523  std::vector<CSCCLCTDigi> lctListBX;
2524 
2526 
2527  // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
2528  pulseExtension(halfstrip, maxHalfStrips, pulse);
2529 
2530  unsigned int start_bx = start_bx_shift;
2531  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
2532  // not have a full set of hits to start pattern search anyway.
2533  unsigned int stop_bx = fifo_tbins - drift_delay;
2534 
2535  // Allow for more than one pass over the hits in the time window.
2536  // Do search in every BX
2537  while (start_bx < stop_bx)
2538  {
2539  lctListBX.clear();
2540 
2541  // All half-strip pattern envelopes are evaluated simultaneously, on every clock cycle.
2542  int first_bx = 999;
2543  bool pre_trig = preTrigger(pulse, start_bx, first_bx);
2544 
2545  // If any of half-strip envelopes has enough layers hit in it, TMB
2546  // will pre-trigger.
2547  if (pre_trig)
2548  {
2549  if (infoV > 1)
2550  LogTrace("CSCCathodeLCTProcessor") << "..... pretrigger at bx = " << first_bx << "; waiting drift delay .....";
2551 
2552  // TMB latches LCTs drift_delay clocks after pretrigger.
2553  int latch_bx = first_bx + drift_delay;
2554  bool hits_in_time = ptnFinding(pulse, maxHalfStrips, latch_bx);
2555  if (infoV > 1)
2556  {
2557  if (hits_in_time)
2558  {
2559  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++)
2560  {
2561  if (nhits[hstrip] > 0)
2562  {
2563  LogTrace("CSCCathodeLCTProcessor") << " bx = " << std::setw(2) << latch_bx << " --->" << " halfstrip = "
2564  << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip] << " nhits = " << nhits[hstrip];
2565  }
2566  }
2567  }
2568  }
2569  // The pattern finder runs continuously, so another pre-trigger
2570  // could occur already at the next bx.
2571  start_bx = first_bx + 1;
2572 
2573  // 2 possible LCTs per CSC x 7 LCT quantities per BX
2574  int keystrip_data[max_lcts][7] = {{0}};
2575 
2576  // Quality for sorting.
2578  int best_halfstrip[max_lcts], best_quality[max_lcts];
2579  for (int ilct = 0; ilct < max_lcts; ilct++)
2580  {
2581  best_halfstrip[ilct] = -1;
2582  best_quality[ilct] = 0;
2583  }
2584 
2585  bool pretrig_zone[CSCConstants::NUM_HALF_STRIPS_7CFEBS];
2586 
2587  // Calculate quality from pattern id and number of hits, and
2588  // simultaneously select best-quality LCT.
2589  if (hits_in_time)
2590  {
2591  // first, mark half-strip zones around pretriggers
2592  // that happened at the current first_bx
2593  for (int hstrip = 0; hstrip < CSCConstants::NUM_HALF_STRIPS_7CFEBS; hstrip++)
2594  pretrig_zone[hstrip] = 0;
2595  for (int hstrip = 0; hstrip < CSCConstants::NUM_HALF_STRIPS_7CFEBS; hstrip++)
2596  {
2597  if (ispretrig[hstrip])
2598  {
2599  int min_hs = hstrip - pretrig_trig_zone;
2600  int max_hs = hstrip + pretrig_trig_zone;
2601  if (min_hs < 0)
2602  min_hs = 0;
2603  if (max_hs > CSCConstants::NUM_HALF_STRIPS_7CFEBS - 1)
2604  max_hs = CSCConstants::NUM_HALF_STRIPS_7CFEBS - 1;
2605  for (int hs = min_hs; hs <= max_hs; hs++)
2606  pretrig_zone[hs] = 1;
2607  if (infoV > 1)
2608  LogTrace("CSCCathodeLCTProcessor") << " marked pretrigger halfstrip zone [" << min_hs << "," << max_hs << "]";
2609  }
2610  }
2611 
2612  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++)
2613  {
2614  // The bend-direction bit pid[0] is ignored (left and right bends have equal quality).
2615  quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
2616  // do not consider halfstrips:
2617  // - out of pretrigger-trigger zones
2618  // - in busy zones from previous trigger
2619  if (quality[hstrip] > best_quality[0] &&
2620  pretrig_zone[hstrip] &&
2621  !busyMap[hstrip][first_bx] )
2622  {
2623  best_halfstrip[0] = hstrip;
2624  best_quality[0] = quality[hstrip];
2625  if (infoV > 1)
2626  {
2627  LogTrace("CSCCathodeLCTProcessor") << " 1st CLCT: halfstrip = " << std::setw(3) << hstrip << " quality = "
2628  << std::setw(3) << quality[hstrip] << " best halfstrip = " << std::setw(3) << best_halfstrip[0]
2629  << " best quality = " << std::setw(3) << best_quality[0];
2630  }
2631  }
2632  }
2633  }
2634 
2635  // If 1st best CLCT is found, look for the 2nd best.
2636  if (best_halfstrip[0] >= 0)
2637  {
2638  // Mark keys near best CLCT as busy by setting their quality to zero, and repeat the search.
2639  markBusyKeys(best_halfstrip[0], best_pid[best_halfstrip[0]], quality);
2640 
2641  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < maxHalfStrips; hstrip++)
2642  {
2643  if (quality[hstrip] > best_quality[1] &&
2644  pretrig_zone[hstrip] &&
2645  !busyMap[hstrip][first_bx] )
2646  {
2647  best_halfstrip[1] = hstrip;
2648  best_quality[1] = quality[hstrip];
2649  if (infoV > 1)
2650  {
2651  LogTrace("CSCCathodeLCTProcessor") << " 2nd CLCT: halfstrip = " << std::setw(3) << hstrip << " quality = "
2652  << std::setw(3) << quality[hstrip] << " best halfstrip = " << std::setw(3) << best_halfstrip[1]
2653  << " best quality = " << std::setw(3) << best_quality[1];
2654  }
2655  }
2656  }
2657 
2658  // Pattern finder.
2659  bool ptn_trig = false;
2660  for (int ilct = 0; ilct < max_lcts; ilct++)
2661  {
2662  int best_hs = best_halfstrip[ilct];
2663  if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern)
2664  {
2665  int bx = first_bx;
2666  int fbx = first_bx_corrected[best_hs];
2667  if (use_corrected_bx) {
2668  bx = fbx;
2669  fbx = first_bx;
2670  }
2671  ptn_trig = true;
2672  keystrip_data[ilct][CLCT_PATTERN] = best_pid[best_hs];
2673  keystrip_data[ilct][CLCT_BEND] = pattern2007[best_pid[best_hs]][NUM_PATTERN_HALFSTRIPS];
2674  // Remove stagger if any.
2675  keystrip_data[ilct][CLCT_STRIP] = best_hs - stagger[CSCConstants::KEY_CLCT_LAYER - 1];
2676  keystrip_data[ilct][CLCT_BX] = bx;
2677  keystrip_data[ilct][CLCT_STRIP_TYPE] = 1; // obsolete
2678  keystrip_data[ilct][CLCT_QUALITY] = nhits[best_hs];
2679  keystrip_data[ilct][CLCT_CFEB] = keystrip_data[ilct][CLCT_STRIP] / cfeb_strips[1];
2680  int halfstrip_in_cfeb = keystrip_data[ilct][CLCT_STRIP] - cfeb_strips[1] * keystrip_data[ilct][CLCT_CFEB];
2681 
2682  if (infoV > 1)
2683  LogTrace("CSCCathodeLCTProcessor") << " Final selection: ilct " << ilct << " key halfstrip "
2684  << keystrip_data[ilct][CLCT_STRIP] << " quality " << keystrip_data[ilct][CLCT_QUALITY] << " pattern "
2685  << keystrip_data[ilct][CLCT_PATTERN] << " bx " << keystrip_data[ilct][CLCT_BX];
2686 
2687  CSCCLCTDigi thisLCT(1, keystrip_data[ilct][CLCT_QUALITY], keystrip_data[ilct][CLCT_PATTERN],
2688  keystrip_data[ilct][CLCT_STRIP_TYPE], keystrip_data[ilct][CLCT_BEND], halfstrip_in_cfeb,
2689  keystrip_data[ilct][CLCT_CFEB], keystrip_data[ilct][CLCT_BX]);
2690  thisLCT.setFullBX(fbx);
2691  lctList.push_back(thisLCT);
2692  lctListBX.push_back(thisLCT);
2693  }
2694  }
2695 
2696  // state-machine
2697  if (ptn_trig)
2698  {
2699  // Once there was a trigger, CLCT pre-trigger state machine checks the number of hits
2700  // that lie on a key halfstrip pattern template at every bx, and waits for it to drop below threshold.
2701  // During that time no CLCTs could be found with its key halfstrip in the area of
2702  // [clct_key-clct_state_machine_zone, clct_key+clct_state_machine_zone]
2703  // starting from first_bx+1.
2704  // The search for CLCTs resumes only when the number of hits on key halfstrip drops below threshold.
2705  for (unsigned int ilct = 0; ilct < lctListBX.size(); ilct++)
2706  {
2707  int key_hstrip = lctListBX[ilct].getKeyStrip() + stagger[CSCConstants::KEY_CLCT_LAYER - 1];
2708 
2709  int delta_hs = clct_state_machine_zone;
2711  delta_hs = pattern2007[lctListBX[ilct].getPattern()][NUM_PATTERN_HALFSTRIPS + 1] - 1;
2712 
2713  int min_hstrip = key_hstrip - delta_hs;
2714  int max_hstrip = key_hstrip + delta_hs;
2715 
2716  if (min_hstrip < stagger[CSCConstants::KEY_CLCT_LAYER - 1])
2717  min_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1];
2718  if (max_hstrip > maxHalfStrips)
2719  max_hstrip = maxHalfStrips;
2720 
2721  if (infoV > 2)
2722  LogTrace("CSCCathodeLCTProcessor") << " marking post-trigger zone after bx=" << lctListBX[ilct].getBX() << " ["
2723  << min_hstrip << "," << max_hstrip << "]";
2724 
2725  // Stop checking drift_delay bx's short of fifo_tbins since
2726  // at later bx's we won't have a full set of hits for a
2727  // pattern search anyway.
2728  //int stop_time = fifo_tbins - drift_delay;
2729  // -- no, need to extend busyMap over fifo_tbins - drift_delay
2730  for (size_t bx = first_bx + 1; bx < fifo_tbins; bx++)
2731  {
2732  bool busy_bx = false;
2733  if (bx <= (size_t)latch_bx)
2734  busy_bx = true; // always busy before drift time
2735  if (!busy_bx)
2736  {
2737  bool hits_in_time = ptnFinding(pulse, maxHalfStrips, bx);
2738  if (hits_in_time && nhits[key_hstrip] >= nplanes_hit_pattern)
2739  busy_bx = true;
2740  if (infoV > 2)
2741  LogTrace("CSCCathodeLCTProcessor") << " at bx=" << bx << " hits_in_time=" << hits_in_time << " nhits="
2742  << nhits[key_hstrip];
2743  }
2744  if (infoV > 2)
2745  LogTrace("CSCCathodeLCTProcessor") << " at bx=" << bx << " busy=" << busy_bx;
2746  if (busy_bx)
2747  for (int hstrip = min_hstrip; hstrip <= max_hstrip; hstrip++)
2748  busyMap[hstrip][bx] = true;
2749  else
2750  break;
2751  }
2752  }
2753  } // if (ptn_trig)
2754  }
2755  }
2756  else
2757  {
2758  start_bx = first_bx + 1; // no dead time
2759  }
2760  }
2761 
2762  return lctList;
2763 } // findLCTs -- SLHC version.
2764 
2765 
2766 // --------------------------------------------------------------------------
2767 // Auxiliary code.
2768 // --------------------------------------------------------------------------
2769 // Dump of configuration parameters.
2771  std::ostringstream strm;
2772  strm << "\n";
2773  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
2774  strm << "+ CLCT configuration parameters: +\n";
2775  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
2776  strm << " fifo_tbins [total number of time bins in DAQ readout] = "
2777  << fifo_tbins << "\n";
2778  strm << " fifo_pretrig [start time of cathode raw hits in DAQ readout] = "
2779  << fifo_pretrig << "\n";
2780  strm << " hit_persist [duration of signal pulse, in 25 ns bins] = "
2781  << hit_persist << "\n";
2782  strm << " drift_delay [time after pre-trigger before TMB latches LCTs] = "
2783  << drift_delay << "\n";
2784  strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = "
2785  << nplanes_hit_pretrig << "\n";
2786  strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = "
2787  << nplanes_hit_pattern << "\n";
2788  if (isTMB07) {
2789  strm << " pid_thresh_pretrig [lower threshold on pattern id] = "
2790  << pid_thresh_pretrig << "\n";
2791  strm << " min_separation [region of busy key strips] = "
2792  << min_separation << "\n";
2793  }
2794  strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
2795  LogDebug("CSCCathodeLCTProcessor") << strm.str();
2796  //std::cerr<<strm.str()<<std::endl;
2797 }
2798 
2799 // Reasonably nice dump of digis on half-strips and di-strips.
2800 void CSCCathodeLCTProcessor::dumpDigis(const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int stripType, const int nStrips) const
2801 {
2802  LogDebug("CSCCathodeLCTProcessor")
2803  << "ME" << ((theEndcap == 1) ? "+" : "-")
2804  << theStation << "/" << theRing << "/" << theChamber
2805  << " strip type " << stripType << " nStrips " << nStrips;
2806 
2807  std::ostringstream strstrm;
2808  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
2809  if (i_strip%10 == 0) {
2810  if (i_strip < 100) strstrm << i_strip/10;
2811  else strstrm << (i_strip-100)/10;
2812  }
2813  else strstrm << " ";
2814  if ((i_strip+1)%cfeb_strips[stripType] == 0) strstrm << " ";
2815  }
2816  strstrm << "\n";
2817  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
2818  strstrm << i_strip%10;
2819  if ((i_strip+1)%cfeb_strips[stripType] == 0) strstrm << " ";
2820  }
2821  for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
2822  strstrm << "\n";
2823  for (int i_strip = 0; i_strip < nStrips; i_strip++) {
2824  if (!strip[i_layer][i_strip].empty()) {
2825  std::vector<int> bx_times = strip[i_layer][i_strip];
2826  // Dump only the first in time.
2827  strstrm << std::hex << bx_times[0] << std::dec;
2828  }
2829  else {
2830  strstrm << "-";
2831  }
2832  if ((i_strip+1)%cfeb_strips[stripType] == 0) strstrm << " ";
2833  }
2834  }
2835  LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
2836 }
2837 
2838 // Returns vector of read-out CLCTs, if any. Starts with the vector
2839 // of all found CLCTs and selects the ones in the read-out time window.
2840 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::readoutCLCTs() {
2841  std::vector<CSCCLCTDigi> tmpV;
2842 
2843  // The start time of the L1A*CLCT coincidence window should be
2844  // related to the fifo_pretrig parameter, but I am not completely
2845  // sure how. For now, just choose it such that the window is
2846  // centered at bx=7. This may need further tweaking if the value of
2847  // tmb_l1a_window_size changes.
2848  // static int fpga_latency = 3;
2849  // static int early_tbins = fifo_pretrig - fpga_latency;
2850  // static int early_tbins = 4;
2851 
2852  // The number of CLCT bins in the read-out is given by the
2853  // tmb_l1a_window_size parameter, but made even by setting the LSB
2854  // of tmb_l1a_window_size to 0.
2855  //
2856  static std::atomic<int> lct_bins;
2858  static std::atomic<int> late_tbins;
2859  late_tbins = early_tbins + lct_bins;
2860 
2861  static std::atomic<int> ifois{0};
2862  if (ifois == 0) {
2863  if (infoV >= 0 && early_tbins < 0) {
2864  edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
2865  << "+++ early_tbins = " << early_tbins
2866  << "; in-time CLCTs are not getting read-out!!! +++" << "\n";
2867  }
2868 
2869  if (late_tbins > MAX_CLCT_BINS-1) {
2870  if (infoV >= 0) edm::LogWarning("L1CSCTPEmulatorSuspiciousParameters")
2871  << "+++ Allowed range of time bins, [0-" << late_tbins
2872  << "] exceeds max allowed, " << MAX_CLCT_BINS-1 << " +++\n"
2873  << "+++ Set late_tbins to max allowed +++\n";
2874  late_tbins = MAX_CLCT_BINS-1;
2875  }
2876  ifois = 1;
2877  }
2878 
2879  // Start from the vector of all found CLCTs and select those within
2880  // the CLCT*L1A coincidence window.
2881  int bx_readout = -1;
2882  std::vector<CSCCLCTDigi> all_lcts = getCLCTs();
2883  for (std::vector <CSCCLCTDigi>::const_iterator plct = all_lcts.begin();
2884  plct != all_lcts.end(); plct++) {
2885  if (!plct->isValid()) continue;
2886 
2887  int bx = (*plct).getBX();
2888  // Skip CLCTs found too early relative to L1Accept.
2889  if (bx <= early_tbins) {
2890  if (infoV > 1) LogDebug("CSCCathodeLCTProcessor")
2891  << " Do not report CLCT on key halfstrip " << plct->getKeyStrip()
2892  << ": found at bx " << bx << ", whereas the earliest allowed bx is "
2893  << early_tbins+1;
2894  continue;
2895  }
2896 
2897  // Skip CLCTs found too late relative to L1Accept.
2898  if (bx > late_tbins) {
2899  if (infoV > 1) LogDebug("CSCCathodeLCTProcessor")
2900  << " Do not report CLCT on key halfstrip " << plct->getKeyStrip()
2901  << ": found at bx " << bx << ", whereas the latest allowed bx is "
2902  << late_tbins;
2903  continue;
2904  }
2905 
2906  // If (readout_earliest_2) take only CLCTs in the earliest bx in the read-out window:
2907  // in digi->raw step, LCTs have to be packed into the TMB header, and
2908  // currently there is room just for two.
2909  if (readout_earliest_2) {
2910  if (bx_readout == -1 || bx == bx_readout) {
2911  tmpV.push_back(*plct);
2912  if (bx_readout == -1) bx_readout = bx;
2913  }
2914  }
2915  else tmpV.push_back(*plct);
2916  }
2917  return tmpV;
2918 }
2919 
2920 // Returns vector of all found CLCTs, if any. Used for ALCT-CLCT matching.
2921 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::getCLCTs() {
2922  std::vector<CSCCLCTDigi> tmpV;
2923  for (int bx = 0; bx < MAX_CLCT_BINS; bx++) {
2924  if (bestCLCT[bx].isValid()) tmpV.push_back(bestCLCT[bx]);
2925  if (secondCLCT[bx].isValid()) tmpV.push_back(secondCLCT[bx]);
2926  }
2927  return tmpV;
2928 }
2929 
2930 
2931 // --------------------------------------------------------------------------
2932 // Test routines. Mostly for older versions of the algorithm and outdated.
2933 // --------------------------------------------------------------------------
2935  // Author: Jason Mumford (mumford@physics.ucla.edu)
2936  // This routine tests the distripStagger routine.
2937  // @@
2938  bool debug = true;
2939  int test_triad[CSCConstants::NUM_DI_STRIPS], test_time[CSCConstants::NUM_DI_STRIPS];
2940  int test_digi[CSCConstants::NUM_DI_STRIPS];
2941  int distrip = 0;
2942  test_triad[distrip] = 3; //After routine, I expect 4
2943  test_triad[distrip+1] = 3; // 4
2944  test_triad[distrip+2] = 3; // 4
2945  test_triad[distrip+3] = 3; // 4
2946  test_triad[distrip+4] = 3; // 4
2947  test_triad[distrip+5] = 3; // 4
2948  test_triad[distrip+6] = 3; // 4
2949  test_triad[distrip+7] = 3; // 4
2950  test_triad[distrip+8] = 3; // 4
2951  test_triad[distrip+9] = 3; // 4
2952  test_triad[distrip+10] = 2; // 2
2953 
2954  test_time[distrip] = 4; // "" "" 0
2955  test_time[distrip+1] = 10; // 4
2956  test_time[distrip+2] = 2; // 10
2957  test_time[distrip+3] = 0; // 2
2958  test_time[distrip+4] = 6; // 2
2959  test_time[distrip+5] = 8; // 2
2960  test_time[distrip+6] = 10; // 2
2961  test_time[distrip+7] = 1; // 2
2962  test_time[distrip+8] = 8; // 2
2963  test_time[distrip+9] = 5; // 2
2964  test_time[distrip+10] = 6; // 2
2965 
2966  std::cout << "\n ------------------------------------------------- \n";
2967  std::cout << "!!!!!!Testing distripStagger routine!!!!!!" << std::endl;
2968  std::cout << "Values before distripStagger routine:" << std::endl;
2969  for (int i=distrip; i<distrip+11; i++){
2970  test_digi[i] = 999;
2971  std::cout << "test_triad[" << i << "] = " << test_triad[i];
2972  std::cout << " test_time[" << i << "] = " << test_time[i] << std::endl;
2973  }
2974  distripStagger(test_triad, test_time, test_digi, distrip, debug);
2975  std::cout << "Values after distripStagger routine:" << std::endl;
2976  for (int i=distrip; i<distrip+11; i++){
2977  std::cout << "test_triad[" << i << "] = " << test_triad[i];
2978  std::cout << " test_time[" << i << "] = " << test_time[i] << std::endl;
2979  }
2980  std::cout << "\n ------------------------------------------------- \n \n";
2981 }
2982 
2984  // test to make sure what goes into an LCT is what comes out.
2985  for (int ptn = 0; ptn < 8; ptn++) {
2986  for (int bend = 0; bend < 2; bend++) {
2987  for (int cfeb = 0; cfeb < MAX_CFEBS; cfeb++) {
2988  for (int key_strip = 0; key_strip < 32; key_strip++) {
2989  for (int bx = 0; bx < 7; bx++) {
2990  for (int stripType = 0; stripType < 2; stripType++) {
2991  for (int quality = 3; quality < 6; quality++) {
2992  CSCCLCTDigi thisLCT(1, quality, ptn, stripType, bend,
2993  key_strip, cfeb, bx);
2994  if (ptn != thisLCT.getPattern())
2995  LogTrace("CSCCathodeLCTProcessor")
2996  << "pattern mismatch: " << ptn << " "
2997  << thisLCT.getPattern();
2998  if (bend != thisLCT.getBend())
2999  LogTrace("CSCCathodeLCTProcessor")
3000  << "bend mismatch: " << bend << " " << thisLCT.getBend();
3001  if (cfeb != thisLCT.getCFEB())
3002  LogTrace("CSCCathodeLCTProcessor")
3003  << "cfeb mismatch: " << cfeb << " " << thisLCT.getCFEB();
3004  if (key_strip != thisLCT.getKeyStrip())
3005  LogTrace("CSCCathodeLCTProcessor")
3006  << "strip mismatch: " << key_strip << " "
3007  << thisLCT.getKeyStrip();
3008  if (bx != thisLCT.getBX())
3009  LogTrace("CSCCathodeLCTProcessor")
3010  << "bx mismatch: " << bx << " " << thisLCT.getBX();
3011  if (stripType != thisLCT.getStripType())
3012  LogTrace("CSCCathodeLCTProcessor")
3013  << "Strip Type mismatch: " << stripType << " "
3014  << thisLCT.getStripType();
3015  if (quality != thisLCT.getQuality())
3016  LogTrace("CSCCathodeLCTProcessor")
3017  << "quality mismatch: " << quality << " "
3018  << thisLCT.getQuality();
3019  }
3020  }
3021  }
3022  }
3023  }
3024  }
3025  }
3026 }
3027 
3029  // @@
3030  std::cout<<" Printing patterns for Cathode LCT"<<std::endl;
3031  std::cout<<" ";
3032  for (int patternNum = 0; patternNum < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; patternNum++) {
3033  std::cout<<" Pattern "<<patternNum<<" ";
3034  }
3035  std::cout<<std::endl;
3036  std::cout<<" Layer ";
3037  for (int patternNum = 0; patternNum < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; patternNum++) {
3038  std::cout<<" Bend "<<(pattern[patternNum][NUM_PATTERN_STRIPS]==0 ? "L": "R")<<" ";
3039  }
3040  std::cout<<std::endl;
3041  for (int layer = 0; layer < CSCConstants::NUM_LAYERS; layer++) {
3042  for (int patternNum = 0; patternNum < CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07; patternNum++) {
3043  if (patternNum == 0) std::cout<<" "<<layer<<" ";
3044  if ((isTMB07 && layer != CSCConstants::KEY_CLCT_LAYER-1) ||
3045  (!isTMB07 && layer != CSCConstants::KEY_CLCT_LAYER_PRE_TMB07-1)) {//that old counting from 1 vs 0 thing.
3046  int minStrip =0;
3047  if ((isTMB07 && layer < CSCConstants::KEY_CLCT_LAYER-1) ||
3049  minStrip = 3*layer;
3050  } else {
3051  minStrip = 3*layer - 2;// since on the key layer we only have 1 strip
3052  }
3053  for (int strip = minStrip; strip < minStrip + 3; strip++) {
3054  if (layer == pattern[patternNum][strip]) {
3055  std::cout<<"X";
3056  } else {
3057  std::cout<<"_";
3058  }
3059  }
3060  } else {// on the key layer we always have a hit, right?
3061  std::cout<<" X ";
3062  }
3063  std::cout<<" ";
3064  }
3065  std::cout<<std::endl;
3066  }
3067 }
3068 
3070 //generate all possible combinations of hits in a given area and see what we find.
3071 // Benn Tannenbaum 21 June 2001
3072 
3073  //there are 16 strips in our uber-pattern, each of which can be on or off.
3074  // 2^16 = 65536
3075  for (int possibleHits = 0; possibleHits < 65536; possibleHits++) {
3077  //assign one bit to each strip in an array. I'll start centered around strip 10.
3078  stripsHit[0][ 9].push_back(( possibleHits & 1 ) != 0); // 2^0
3079  stripsHit[0][10].push_back(( possibleHits & 2 ) != 0); // 2^1
3080  stripsHit[0][11].push_back(( possibleHits & 4 ) != 0); // 2^2
3081  stripsHit[1][ 9].push_back(( possibleHits & 8 ) != 0); // 2^3
3082  stripsHit[1][10].push_back(( possibleHits & 16 ) != 0); // 2^4
3083  stripsHit[1][11].push_back(( possibleHits & 32 ) != 0); // 2^5
3084  stripsHit[2][ 9].push_back(( possibleHits & 64 ) != 0); // 2^6
3085  stripsHit[2][10].push_back(( possibleHits & 128 ) != 0); // 2^7
3086  stripsHit[2][11].push_back(( possibleHits & 256 ) != 0); // 2^8
3087  stripsHit[3][10].push_back(( possibleHits & 512 ) != 0); // 2^9
3088  stripsHit[4][ 9].push_back(( possibleHits & 1024 ) != 0); // 2^10
3089  stripsHit[4][10].push_back(( possibleHits & 2048 ) != 0); // 2^11
3090  stripsHit[4][11].push_back(( possibleHits & 4096 ) != 0); // 2^12
3091  stripsHit[5][ 9].push_back(( possibleHits & 8192 ) != 0); // 2^13
3092  stripsHit[5][10].push_back(( possibleHits & 16384 ) != 0); // 2^14
3093  stripsHit[5][11].push_back(( possibleHits & 32768 ) != 0); // 2^15
3094  int numLayersHit = findNumLayersHit(stripsHit);
3095  std::vector <CSCCLCTDigi> results = findLCTs(stripsHit, 1);
3096 // print out whatever we find-- but only ones where 4 or more layers are hit
3097 // OR ones where we find something
3098 // key: X a hit there and was used to find pattern
3099 // x a hit not involved in pattern
3100 // _ empty strip
3101 // o a hit was there, but no pattern was found
3102  if (numLayersHit > 3 || results.size() > 0) {
3103  std::cout<<"Input "<<possibleHits<<"/"<< 65536 <<" # Found Patterns "<<results.size()<<std::endl<<" ";
3104  for (int layer = 0; layer < CSCConstants::NUM_LAYERS; layer++) {
3105  if ((isTMB07 && layer != CSCConstants::KEY_CLCT_LAYER - 1) ||
3106  (!isTMB07 && layer != CSCConstants::KEY_CLCT_LAYER_PRE_TMB07 - 1)) {
3107  for (int strip = 9; strip < 12; strip++) {
3108  if (!stripsHit[layer][strip].empty()) {
3109  if (results.size() > 0) {
3110  int thePatternStrip = strip - (results[0].getKeyStrip() - 2) + 3*layer;
3111  if ((isTMB07 && layer>=CSCConstants::KEY_CLCT_LAYER) ||
3113  thePatternStrip -= 2;
3114 
3115  if (pattern[results[0].getPattern()][thePatternStrip] == layer)
3116  {
3117  std::cout<<"X";
3118  } else {
3119  std::cout<<"x";
3120  }
3121  } else {
3122  std::cout<<"o";
3123  }
3124  } else {
3125  std::cout<<"_";
3126  }
3127  }
3128  std::cout<<" ";
3129  for (unsigned int output = 0; output < results.size(); output++) {
3130  int minStrip;
3131  if ((isTMB07 && layer < CSCConstants::KEY_CLCT_LAYER-1) ||
3133  minStrip = 3*layer;
3134  } else {
3135  minStrip = 3*layer - 2;// since on the key layer we only have 1 strip
3136  }
3137  for (int strip = minStrip; strip < minStrip + 3; strip++) {
3138  if (layer == pattern[results[output].getPattern()][strip]) {
3139  std::cout<<"X";
3140  } else {
3141  std::cout<<"_";
3142  }
3143  }
3144  std::cout<<" ";
3145  }
3146  } else {
3147  if (!stripsHit[layer][10].empty()) {
3148  std::cout<<" X ";
3149  } else {
3150  std::cout<<" _ ";
3151  }
3152  for (unsigned int output = 0; output < results.size(); output++)
3153  std::cout<<" X ";
3154  }
3155  if (layer < static_cast<int>(results.size()) ) {
3156  std::cout<<results[layer];
3157  std::cout<<" ";
3158  } else {
3159  std::cout<<" "<<std::endl<<" ";
3160  }
3161  }
3162  }
3163  }
3164 }
3165 
3168  int number = 0;
3169  for (int layer = 0; layer < CSCConstants::NUM_LAYERS; layer++) {
3170  if ((!stripsHit[layer][ 9].empty()) ||
3171  (!stripsHit[layer][10].empty()) ||
3172  (!stripsHit[layer][11].empty()) ) number++;
3173  }
3174  return number;
3175 }
3176 
3177 // LocalWords: CMSSW pretrig
#define LogDebug(id)
int getQuality() const
return quality of a pattern (number of layers hit!)
Definition: CSCCLCTDigi.h:33
void getPattern(int pattern_num, int strip_value[NUM_PATTERN_STRIPS], int bx_time, int &quality, int &bend)
static const unsigned int def_drift_delay
CSCCLCTDigi secondCLCT[MAX_CLCT_BINS]
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
std::vector< CSCCLCTDigi > readoutCLCTs()
static const unsigned int def_fifo_tbins
static void distripStagger(int stag_triad[CSCConstants::MAX_NUM_STRIPS_7CFEBS], int stag_time[CSCConstants::MAX_NUM_STRIPS_7CFEBS], int stag_digi[CSCConstants::MAX_NUM_STRIPS_7CFEBS], int i_distrip, bool debug=false)
int getStrip() const
Get the strip number.
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...
bool ispretrig[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
static const int cfeb_strips[2]
unsigned int clctHitPersist() const
int first_bx_corrected[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
unsigned int clctNplanesHitPattern() const
static const unsigned int def_min_separation
int numberOfStrips() const
CSCCLCTDigi bestCLCT[MAX_CLCT_BINS]
unsigned int clctMinSeparation() const
int getComparator() const
Get Comparator readings.
unsigned int clctNplanesHitPretrig() const
static const unsigned int def_nplanes_hit_pretrig
int getTimeBin() const
Return bin number of first time bin which is ON. Counts from 0.
static int ringFromTriggerLabels(int station, int triggerCSCID)
int getStripType() const
return striptype
Definition: CSCCLCTDigi.h:39
unsigned int clctDriftDelay() const
int getBend() const
return bend
Definition: CSCCLCTDigi.h:42
static const unsigned int def_pid_thresh_pretrig
unsigned int best_pid[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
bool preTrigLookUp(const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int stripType, const int nStrips, const unsigned int bx_time)
void markBusyKeys(const int best_hstrip, const int best_patid, int quality[CSCConstants::NUM_HALF_STRIPS_7CFEBS])
void latchLCTs(const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], int keyStrip[MAX_CFEBS], unsigned int nhits[MAX_CFEBS], const int stripType, const int nStrips, const int bx_time)
static CSCTriggerGeomManager * get()
unsigned int clctPidThreshPretrig() const
void dumpDigis(const std::vector< int > strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int stripType, const int nStrips) const
int getCFEB() const
return Key CFEB ID
Definition: CSCCLCTDigi.h:48
static const int pattern2007[CSCConstants::NUM_CLCT_PATTERNS][NUM_PATTERN_HALFSTRIPS+2]
static const unsigned int def_tmb_l1a_window_size
int getBX() const
return BX
Definition: CSCCLCTDigi.h:51
static const int pattern[CSCConstants::NUM_CLCT_PATTERNS_PRE_TMB07][NUM_PATTERN_STRIPS+1]
bool getDigis(const CSCComparatorDigiCollection *compdc)
static const unsigned int def_nplanes_hit_pattern
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
int j
Definition: DBlmapReader.cc:9
const CSCLayer * layer(CSCDetId id) const
Return the layer corresponding to the given id.
Definition: CSCChamber.cc:39
unsigned int clctFifoPretrig() const
bool preTrigger(const std::vector< int > strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int stripType, const int nStrips, int &first_bx)
#define LogTrace(id)
tuple conf
Definition: dbtoconf.py:185
bool ptnFinding(const unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int nStrips, const unsigned int bx_time)
void priorityEncode(const int h_keyStrip[MAX_CFEBS], const unsigned int h_nhits[MAX_CFEBS], const int d_keyStrip[MAX_CFEBS], const unsigned int d_nhits[MAX_CFEBS], int keystrip_data[2][7])
int stagger() const
#define debug
Definition: HDRShower.cc:19
static const unsigned int def_fifo_pretrig
int getPattern() const
return pattern
Definition: CSCCLCTDigi.h:36
std::vector< int > thePreTriggerBXs
tuple pid
Definition: sysUtil.py:22
static const unsigned int def_hit_persist
std::vector< CSCCLCTDigi > findLCTs(const std::vector< int > strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], int stripType)
int stagger[CSCConstants::NUM_LAYERS]
std::vector< CSCComparatorDigi >::const_iterator const_iterator
void setFullBX(const uint16_t fullbx)
Set 12-bit full BX.
Definition: CSCCLCTDigi.h:77
unsigned int nhits[CSCConstants::NUM_HALF_STRIPS_7CFEBS]
std::vector< CSCCLCTDigi > run(const CSCComparatorDigiCollection *compdc)
unsigned int clctFifoTbins() const
#define begin
Definition: vmac.h:30
static const int pattern2007_offset[NUM_PATTERN_HALFSTRIPS]
int findNumLayersHit(std::vector< int > stripsHit[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
bool hitIsGood(int hitTime, int BX)
void clear()
clear this CLCT
Definition: CSCCLCTDigi.cc:58
std::vector< CSCComparatorDigi > digiV[CSCConstants::NUM_LAYERS]
tuple cout
Definition: gather_cfg.py:121
std::pair< const_iterator, const_iterator > Range
void readComparatorDigis(std::vector< int >halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], std::vector< int > distrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
static const int pre_hit_pattern[2][NUM_PATTERN_STRIPS]
void pulseExtension(const std::vector< int > time[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], const int nStrips, unsigned int pulse[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
int getKeyStrip() const
Definition: CSCCLCTDigi.h:65
void getKeyStripData(const std::vector< int > strip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS], int keystrip_data[CSCConstants::NUM_HALF_STRIPS_7CFEBS][7], int nStrips, int first_bx, int &best_strip, int stripType)
std::vector< CSCCLCTDigi > findLCTsSLHC(const std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::NUM_HALF_STRIPS_7CFEBS])
const CSCLayerGeometry * geometry() const
Definition: CSCLayer.h:47
tuple size
Write out results.
static int chamberFromTriggerLabels(int TriggerSector, int TriggerSubSector, int station, int TriggerCSCID)
std::vector< CSCCLCTDigi > getCLCTs()
void setConfigParameters(const CSCDBL1TPParameters *conf)
void setTrknmb(const uint16_t number)
Set track number (1,2) after sorting CLCTs.
Definition: CSCCLCTDigi.h:71