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