CMS 3D CMS Logo

CSCUpgradeCathodeLCTProcessor.cc
Go to the documentation of this file.
2 
3 #include <iomanip>
4 
6  unsigned station,
7  unsigned sector,
8  unsigned subsector,
9  unsigned chamber,
12  if (!runPhase2_)
13  edm::LogError("CSCUpgradeCathodeLCTProcessor|ConfigError")
14  << "+++ Upgrade CSCUpgradeCathodeLCTProcessor constructed while runPhase2_ is not set! +++\n";
15 
16  // use of localized dead-time zones
17  use_dead_time_zoning_ = conf.clctParams().getParameter<bool>("useDeadTimeZoning");
18  clct_state_machine_zone_ = conf.clctParams().getParameter<unsigned int>("clctStateMachineZone");
19 
20  // how far away may trigger happen from pretrigger
21  pretrig_trig_zone_ = conf.clctParams().getParameter<unsigned int>("clctPretriggerTriggerZone");
22 }
23 
24 // --------------------------------------------------------------------------
25 // The code below is for Phase2 studies of the CLCT algorithm
26 // --------------------------------------------------------------------------
27 
28 // Phase2 version, add the feature of localized dead time zone for pretrigger
29 bool CSCUpgradeCathodeLCTProcessor::preTrigger(const int start_bx, int& first_bx) {
31  return CSCCathodeLCTProcessor::preTrigger(start_bx, first_bx);
32  }
33 
34  if (infoV > 1)
35  LogTrace("CSCUpgradeCathodeLCTProcessor")
36  << "....................PreTrigger, Phase2 version with localized dead time zone...........................";
37 
38  int nPreTriggers = 0;
39 
40  bool pre_trig = false;
41 
42  // Now do a loop over bx times to see (if/when) track goes over threshold
43  for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
44  // For any given bunch-crossing, start at the lowest keystrip and look for
45  // the number of separate layers in the pattern for that keystrip that have
46  // pulses at that bunch-crossing time. Do the same for the next keystrip,
47  // etc. Then do the entire process again for the next bunch-crossing, etc
48  // until you find a pre-trigger.
49  std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer> > hits_in_patterns;
50  hits_in_patterns.clear();
51 
52  bool hits_in_time = patternFinding(bx_time, hits_in_patterns);
53  if (hits_in_time) {
54  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
55  if (infoV > 1) {
56  if (nhits[hstrip] > 0) {
57  LogTrace("CSCUpgradeCathodeLCTProcessor")
58  << " bx = " << std::setw(2) << bx_time << " --->"
59  << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
60  << " nhits = " << nhits[hstrip];
61  }
62  }
63  // note that ispretrig_ is initialized in findLCT function
64  if (nhits[hstrip] >= nplanes_hit_pretrig && best_pid[hstrip] >= pid_thresh_pretrig &&
65  !busyMap_[hstrip][bx_time]) {
66  pre_trig = true;
67  ispretrig_[hstrip] = true;
68 
69  // write each pre-trigger to output
70  nPreTriggers++;
71  thePreTriggerDigis.push_back(constructPreCLCT(bx_time, hstrip, nPreTriggers));
72  }
73  // busy zone, keep pretriggering, ignore this
74  else if (nhits[hstrip] >= nplanes_hit_pretrig && best_pid[hstrip] >= pid_thresh_pretrig) {
75  ispretrig_[hstrip] = true;
76  if (infoV > 1)
77  LogTrace("CSCUpgradeCathodeLCTProcessor")
78  << " halfstrip " << std::setw(3) << hstrip << " in dead zone and is pretriggerred";
79  }
80  // no pretrigger on this halfstrip, release dead zone
81  else if (nhits[hstrip] < nplanes_hit_pretrig || best_pid[hstrip] < pid_thresh_pretrig) {
82  ispretrig_[hstrip] = false;
83  }
84  } // find all pretriggers
85 
86  // update dead zone
87  markBusyZone(bx_time);
88 
89  if (pre_trig) {
90  first_bx = bx_time; // bx at time of pretrigger
91  return true;
92  }
93  } else {
94  // no pattern found, remove all dead zone
96  }
97  } // end loop over bx times
98 
99  if (infoV > 1)
100  LogTrace("CSCUpgradeCathodeLCTProcessor") << "no pretrigger, returning \n";
101  first_bx = fifo_tbins;
102  return false;
103 } // preTrigger -- Phase2 version.
104 
105 // Phase2 version.
108  const CSCL1TPLookupTableCCLUT* lookupTable) {
109  // run the original algorithm in case we do not use dead time zoning
111  return CSCCathodeLCTProcessor::findLCTs(halfstrip, lookupTable);
112  }
113 
114  std::vector<CSCCLCTDigi> lctList;
115 
116  // initialize the ispretrig_ before doing pretriggering
118 
119  if (infoV > 1)
120  dumpDigis(halfstrip);
121 
122  // keeps dead-time zones around key halfstrips of triggered CLCTs
124  for (int j = 0; j < CSCConstants::MAX_CLCT_TBINS; j++) {
125  busyMap_[i][j] = false;
126  }
127  }
128 
129  // Fire half-strip one-shots for hit_persist bx's (4 bx's by default).
130  pulseExtension(halfstrip);
131 
132  unsigned int start_bx = start_bx_shift;
133  // Stop drift_delay bx's short of fifo_tbins since at later bx's we will
134  // not have a full set of hits to start pattern search anyway.
135  unsigned int stop_bx = fifo_tbins - drift_delay;
136 
137  // Allow for more than one pass over the hits in the time window.
138  // Do search in every BX
139  while (start_bx < stop_bx) {
140  // temp CLCT objects
141  CSCCLCTDigi tempBestCLCT;
142  CSCCLCTDigi tempSecondCLCT;
143 
144  // All half-strip pattern envelopes are evaluated simultaneously, on every clock cycle.
145  int first_bx = 999;
146 
147  // Check for a pre-trigger. If so, find the first BX when the pre-trigger occurred
148  bool pre_trig = CSCUpgradeCathodeLCTProcessor::preTrigger(start_bx, first_bx);
149 
150  // If any of half-strip envelopes has enough layers hit in it, TMB
151  // will pre-trigger.
152  if (pre_trig) {
153  if (infoV > 1)
154  LogTrace("CSCUpgradeCathodeLCTProcessor")
155  << "..... pretrigger at bx = " << first_bx << "; waiting drift delay .....";
156 
157  // TMB latches LCTs drift_delay clocks after pretrigger.
158  int latch_bx = first_bx + drift_delay;
159 
160  // temporary container to keep track of the hits in the CLCT
161  std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer> > hits_in_patterns;
162  hits_in_patterns.clear();
163 
164  // We check if there is at least one key half strip for which at least
165  // one pattern id has at least the minimum number of hits
166  bool hits_in_time = patternFinding(latch_bx, hits_in_patterns);
167  if (infoV > 1) {
168  if (hits_in_time) {
169  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
170  if (nhits[hstrip] > 0) {
171  LogTrace("CSCUpgradeCathodeLCTProcessor")
172  << " bx = " << std::setw(2) << latch_bx << " --->"
173  << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
174  << " nhits = " << nhits[hstrip];
175  }
176  }
177  }
178  }
179 
180  // Quality for sorting.
183  for (int ilct = 0; ilct < CSCConstants::MAX_CLCTS_PER_PROCESSOR; ilct++) {
184  best_halfstrip[ilct] = -1;
185  best_quality[ilct] = 0;
186  }
187 
189 
190  // Calculate quality from pattern id and number of hits, and
191  // simultaneously select best-quality CLCT.
192  if (hits_in_time) {
193  // first, mark half-strip zones around pretriggers
194  // that happened at the current first_bx
195  markPreTriggerZone(pretrig_zone);
196 
197  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
198  /* The bend-direction bit pid[0] is ignored (left and right bends have equal quality).
199  This works both for the Run-2 patterns
200  - PID 2,3: 2 & 14 == 2, 3 & 14 == 2
201  - PID 4,5: 4 & 14 == 4, 3 & 14 == 4
202  - PID 6,7: 6 & 14 == 6, 3 & 14 == 6
203  - PID 8,9: 8 & 14 == 8, 3 & 14 == 8
204  - PID 10: 10 & 14 == 10
205  It also works for the Run-3 patterns:
206  - PID 0,1: 0 & 14 == 0, 1 & 14 == 0
207  - PID 2,3: 2 & 14 == 2, 3 & 14 == 2
208  - PID 4: 4 & 14 == 4
209  */
210  quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
211  // do not consider halfstrips:
212  // - out of pretrigger-trigger zones
213  // - in busy zones from previous trigger
214  if (quality[hstrip] > best_quality[0] && pretrig_zone[hstrip] && !busyMap_[hstrip][first_bx]) {
215  best_halfstrip[0] = hstrip;
216  best_quality[0] = quality[hstrip];
217  // temporary alias
218  const int best_hs(best_halfstrip[0]);
219  const int best_pat(best_pid[best_hs]);
220  // construct a CLCT if the trigger condition has been met
221  if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
222  // overwrite the current best CLCT
223  tempBestCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pat], lookupTable);
224  }
225  }
226  }
227  }
228 
229  // If 1st best CLCT is found, look for the 2nd best.
230  if (best_halfstrip[0] >= 0) {
231  // Get the half-strip of the best CLCT in this BX that was put into the list.
232  // You do need to re-add the any stagger, because the busy keys are based on
233  // the pulse array which takes into account strip stagger!!!
234  const unsigned halfStripBestCLCT(tempBestCLCT.getKeyStrip() + stagger[CSCConstants::KEY_CLCT_LAYER - 1]);
235 
236  // Mark keys near best CLCT as busy by setting their quality to
237  // zero, and repeat the search.
238  //markBusyKeys(best_halfstrip[0], best_pid[best_halfstrip[0]], quality);
239  markBusyKeys(halfStripBestCLCT, best_pid[halfStripBestCLCT], quality);
240 
241  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
242  // we don't have to recalculate the quality for each half-strip
243  if (quality[hstrip] > best_quality[1] && pretrig_zone[hstrip] && !busyMap_[hstrip][first_bx]) {
244  best_halfstrip[1] = hstrip;
245  best_quality[1] = quality[hstrip];
246  // temporary alias
247  const int best_hs(best_halfstrip[1]);
248  const int best_pat(best_pid[best_hs]);
249  // construct a CLCT if the trigger condition has been met
250  if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
251  // overwrite the current second best CLCT
252  tempSecondCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pat], lookupTable);
253  }
254  }
255  }
256 
257  // Sort bestCLCT and secondALCT by quality
258  // if qualities are the same, sort by run-2 or run-3 pattern
259  // if qualities and patterns are the same, sort by half strip number
260  bool changeOrder = false;
261 
262  unsigned qualityBest = 0, qualitySecond = 0;
263  unsigned patternBest = 0, patternSecond = 0;
264  unsigned halfStripBest = 0, halfStripSecond = 0;
265 
266  if (tempBestCLCT.isValid() and tempSecondCLCT.isValid()) {
267  qualityBest = tempBestCLCT.getQuality();
268  qualitySecond = tempSecondCLCT.getQuality();
269  if (!run3_) {
270  patternBest = tempBestCLCT.getPattern();
271  patternSecond = tempSecondCLCT.getPattern();
272  } else {
273  patternBest = tempBestCLCT.getRun3Pattern();
274  patternSecond = tempSecondCLCT.getRun3Pattern();
275  }
276  halfStripBest = tempBestCLCT.getKeyStrip();
277  halfStripSecond = tempSecondCLCT.getKeyStrip();
278 
279  if (qualitySecond > qualityBest)
280  changeOrder = true;
281  else if ((qualitySecond == qualityBest) and (int(patternSecond / 2) > int(patternBest / 2)))
282  changeOrder = true;
283  else if ((qualitySecond == qualityBest) and (int(patternSecond / 2) == int(patternBest / 2)) and
284  (halfStripSecond < halfStripBest))
285  changeOrder = true;
286  }
287 
288  CSCCLCTDigi tempCLCT;
289  if (changeOrder) {
290  tempCLCT = tempBestCLCT;
291  tempBestCLCT = tempSecondCLCT;
292  tempSecondCLCT = tempCLCT;
293  }
294 
295  // add the CLCTs to the collection
296  if (tempBestCLCT.isValid()) {
297  lctList.push_back(tempBestCLCT);
298  }
299  if (tempSecondCLCT.isValid()) {
300  lctList.push_back(tempSecondCLCT);
301  }
302  } //find CLCT, end of best_halfstrip[0] >= 0
303  } //pre_trig
304  // The pattern finder runs continuously, so another pre-trigger
305  // could occur already at the next bx.
306  start_bx = first_bx + 1;
307  }
308  return lctList;
309 } // findLCTs -- Phase2 version.
310 
312  bool pretrig_zone[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) const {
313  // first reset the pretrigger zone (no pretriggers anywhere in this BX
314  for (int hstrip = 0; hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; hstrip++) {
315  pretrig_zone[hstrip] = false;
316  }
317  // then set the pretrigger zone according to the ispretrig_ array
318  for (int hstrip = 0; hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; hstrip++) {
319  if (ispretrig_[hstrip]) {
320  int min_hs = hstrip - pretrig_trig_zone_;
321  int max_hs = hstrip + pretrig_trig_zone_;
322  // set the minimum strip
323  if (min_hs < 0)
324  min_hs = 0;
325  // set the maximum strip
328  // mark the pre-trigger zone
329  for (int hs = min_hs; hs <= max_hs; hs++)
330  pretrig_zone[hs] = true;
331  if (infoV > 1)
332  LogTrace("CSCUpgradeCathodeLCTProcessor")
333  << " marked pretrigger halfstrip zone [" << min_hs << "," << max_hs << "]";
334  }
335  }
336 }
337 
339  for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
340  // check if this halfstrip has a pretrigger
341  if (ispretrig_[hstrip]) {
342  // only fixed localized dead time zone is implemented in firmware
343  int min_hstrip = hstrip - clct_state_machine_zone_;
344  int max_hstrip = hstrip + clct_state_machine_zone_;
345  // set the minimum strip
346  if (min_hstrip < stagger[CSCConstants::KEY_CLCT_LAYER - 1])
347  min_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1];
348  // set the maximum strip
349  if (max_hstrip >= numHalfStrips_)
350  max_hstrip = numHalfStrips_ - 1;
351  // mask the busy half-strips for 1 BX after the pretrigger
352  for (int hs = min_hstrip; hs <= max_hstrip; hs++)
353  busyMap_[hs][bx + 1] = true;
354  if (infoV > 1)
355  LogTrace("CSCUpgradeCathodeLCTProcessor")
356  << " marked zone around pretriggerred halfstrip " << hstrip << " as dead zone for pretriggering at bx"
357  << bx + 1 << " halfstrip: [" << min_hstrip << "," << max_hstrip << "]";
358  }
359  }
360 }
T getParameter(std::string const &) const
Definition: ParameterSet.h:307
uint16_t getQuality() const
return quality of a pattern (number of layers hit!)
Definition: CSCCLCTDigi.h:56
void pulseExtension(const std::vector< int > time[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER])
uint16_t getKeyStrip(const uint16_t n=2) const
Definition: CSCCLCTDigi.cc:107
bool patternFinding(const unsigned int bx_time, std::map< int, std::map< int, CSCCLCTDigi::ComparatorContainer > > &hits_in_patterns)
virtual std::vector< CSCCLCTDigi > findLCTs(const std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER], const CSCL1TPLookupTableCCLUT *lookupTable)
Log< level::Error, false > LogError
void markPreTriggerZone(bool pretrig_zone[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) const
CSCUpgradeCathodeLCTProcessor(unsigned endcap, unsigned station, unsigned sector, unsigned subsector, unsigned chamber, CSCBaseboard::Parameters &conf)
#define LogTrace(id)
edm::ParameterSet const & clctParams() const
Definition: CSCBaseboard.h:24
string quality
unsigned int nhits[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]
CSCCLCTPreTriggerDigi constructPreCLCT(const int bx, const unsigned halfstrip, const unsigned index) const
CSCCLCTDigi constructCLCT(const int bx, const unsigned halfstrip_withstagger, const CSCCLCTDigi::ComparatorContainer &hits, const CSCL1TPLookupTableCCLUT *lookupTable)
std::vector< CSCCLCTDigi > findLCTs(const std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER], const CSCL1TPLookupTableCCLUT *lookupTable) override
bool isValid() const
check CLCT validity (1 - valid CLCT)
Definition: CSCCLCTDigi.h:50
std::vector< CSCCLCTPreTriggerDigi > thePreTriggerDigis
void markBusyKeys(const int best_hstrip, const int best_patid, int quality[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER])
bool busyMap_[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER][CSCConstants::MAX_CLCT_TBINS]
void dumpDigis(const std::vector< int > halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) const
int stagger[CSCConstants::NUM_LAYERS]
uint16_t getPattern() const
return pattern
Definition: CSCCLCTDigi.h:62
virtual bool preTrigger(const int start_bx, int &first_bx)
uint16_t getRun3Pattern() const
return pattern
Definition: CSCCLCTDigi.h:68
bool preTrigger(const int start_bx, int &first_bx) override
bool ispretrig_[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]
unsigned int best_pid[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]