CMS 3D CMS Logo

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