CMS 3D CMS Logo

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