CMS 3D CMS Logo

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