CMS 3D CMS Logo

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