File indexing completed on 2021-12-03 23:52:10
0001 #include "L1Trigger/CSCTriggerPrimitives/interface/CSCCathodeLCTProcessor.h"
0002
0003 #include <iomanip>
0004 #include <memory>
0005
0006
0007 const unsigned int CSCCathodeLCTProcessor::def_fifo_tbins = 12;
0008 const unsigned int CSCCathodeLCTProcessor::def_fifo_pretrig = 7;
0009 const unsigned int CSCCathodeLCTProcessor::def_hit_persist = 6;
0010 const unsigned int CSCCathodeLCTProcessor::def_drift_delay = 2;
0011 const unsigned int CSCCathodeLCTProcessor::def_nplanes_hit_pretrig = 2;
0012 const unsigned int CSCCathodeLCTProcessor::def_nplanes_hit_pattern = 4;
0013 const unsigned int CSCCathodeLCTProcessor::def_pid_thresh_pretrig = 2;
0014 const unsigned int CSCCathodeLCTProcessor::def_min_separation = 10;
0015 const unsigned int CSCCathodeLCTProcessor::def_tmb_l1a_window_size = 7;
0016
0017
0018
0019
0020
0021 CSCCathodeLCTProcessor::CSCCathodeLCTProcessor(unsigned endcap,
0022 unsigned station,
0023 unsigned sector,
0024 unsigned subsector,
0025 unsigned chamber,
0026 const edm::ParameterSet& conf)
0027 : CSCBaseboard(endcap, station, sector, subsector, chamber, conf) {
0028 static std::atomic<bool> config_dumped{false};
0029
0030
0031 fifo_tbins = clctParams_.getParameter<unsigned int>("clctFifoTbins");
0032 hit_persist = clctParams_.getParameter<unsigned int>("clctHitPersist");
0033 drift_delay = clctParams_.getParameter<unsigned int>("clctDriftDelay");
0034 nplanes_hit_pretrig = clctParams_.getParameter<unsigned int>("clctNplanesHitPretrig");
0035 nplanes_hit_pattern = clctParams_.getParameter<unsigned int>("clctNplanesHitPattern");
0036
0037
0038 fifo_pretrig = clctParams_.getParameter<unsigned int>("clctFifoPretrig");
0039
0040 pid_thresh_pretrig = clctParams_.getParameter<unsigned int>("clctPidThreshPretrig");
0041 min_separation = clctParams_.getParameter<unsigned int>("clctMinSeparation");
0042
0043 start_bx_shift = clctParams_.getParameter<int>("clctStartBxShift");
0044
0045
0046 tmb_l1a_window_size =
0047 tmbParams_.getParameter<unsigned int>("tmbL1aWindowSize");
0048
0049
0050
0051
0052
0053
0054
0055 early_tbins = tmbParams_.getParameter<int>("tmbEarlyTbins");
0056 if (early_tbins < 0)
0057 early_tbins = fifo_pretrig - CSCConstants::CLCT_EMUL_TIME_OFFSET;
0058
0059
0060 readout_earliest_2 = tmbParams_.getParameter<bool>("tmbReadoutEarliest2");
0061
0062
0063 infoV = clctParams_.getParameter<int>("verbosity");
0064
0065
0066
0067 if (runCCLUT_) {
0068 pid_thresh_pretrig = 0;
0069 }
0070
0071
0072 checkConfigParameters();
0073 if ((infoV > 0) && !config_dumped) {
0074 dumpConfigParams();
0075 config_dumped = true;
0076 }
0077
0078 numStrips_ = 0;
0079
0080 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0081 if ((i_layer + 1) % 2 == 0)
0082 stagger[i_layer] = 0;
0083 else
0084 stagger[i_layer] = 1;
0085 }
0086
0087
0088 if (runCCLUT_) {
0089 clct_pattern_ = CSCPatternBank::clct_pattern_run3_;
0090
0091 cclut_ = std::make_unique<ComparatorCodeLUT>(conf);
0092 } else {
0093 clct_pattern_ = CSCPatternBank::clct_pattern_legacy_;
0094 }
0095
0096 const auto& shower = showerParams_.getParameterSet("cathodeShower");
0097 thresholds_ = shower.getParameter<std::vector<unsigned>>("showerThresholds");
0098 showerMinInTBin_ = shower.getParameter<unsigned>("showerMinInTBin");
0099 showerMaxInTBin_ = shower.getParameter<unsigned>("showerMaxInTBin");
0100 showerMinOutTBin_ = shower.getParameter<unsigned>("showerMinOutTBin");
0101 showerMaxOutTBin_ = shower.getParameter<unsigned>("showerMaxOutTBin");
0102 minLayersCentralTBin_ = shower.getParameter<unsigned>("minLayersCentralTBin");
0103 thePreTriggerDigis.clear();
0104
0105
0106 qualityControl_ = std::make_unique<LCTQualityControl>(endcap, station, sector, subsector, chamber, conf);
0107 }
0108
0109 void CSCCathodeLCTProcessor::setDefaultConfigParameters() {
0110
0111 fifo_tbins = def_fifo_tbins;
0112 fifo_pretrig = def_fifo_pretrig;
0113 hit_persist = def_hit_persist;
0114 drift_delay = def_drift_delay;
0115 nplanes_hit_pretrig = def_nplanes_hit_pretrig;
0116 nplanes_hit_pattern = def_nplanes_hit_pattern;
0117 pid_thresh_pretrig = def_pid_thresh_pretrig;
0118 min_separation = def_min_separation;
0119 tmb_l1a_window_size = def_tmb_l1a_window_size;
0120 }
0121
0122
0123 void CSCCathodeLCTProcessor::setConfigParameters(const CSCDBL1TPParameters* conf) {
0124 static std::atomic<bool> config_dumped{false};
0125
0126 fifo_tbins = conf->clctFifoTbins();
0127 fifo_pretrig = conf->clctFifoPretrig();
0128 hit_persist = conf->clctHitPersist();
0129 drift_delay = conf->clctDriftDelay();
0130 nplanes_hit_pretrig = conf->clctNplanesHitPretrig();
0131 nplanes_hit_pattern = conf->clctNplanesHitPattern();
0132 pid_thresh_pretrig = conf->clctPidThreshPretrig();
0133 min_separation = conf->clctMinSeparation();
0134
0135
0136 checkConfigParameters();
0137 if (!config_dumped) {
0138 dumpConfigParams();
0139 config_dumped = true;
0140 }
0141 }
0142
0143 void CSCCathodeLCTProcessor::setESLookupTables(const CSCL1TPLookupTableCCLUT* conf) { cclut_->setESLookupTables(conf); }
0144
0145 void CSCCathodeLCTProcessor::checkConfigParameters() {
0146
0147
0148
0149 static const unsigned int max_fifo_tbins = 1 << 5;
0150 static const unsigned int max_fifo_pretrig = 1 << 5;
0151 static const unsigned int max_hit_persist = 1 << 4;
0152 static const unsigned int max_drift_delay = 1 << 2;
0153 static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
0154 static const unsigned int max_nplanes_hit_pattern = 1 << 3;
0155 static const unsigned int max_pid_thresh_pretrig = 1 << 4;
0156 static const unsigned int max_min_separation = CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER;
0157 static const unsigned int max_tmb_l1a_window_size = 1 << 4;
0158
0159
0160 CSCBaseboard::checkConfigParameters(fifo_tbins, max_fifo_tbins, def_fifo_tbins, "fifo_tbins");
0161 CSCBaseboard::checkConfigParameters(fifo_pretrig, max_fifo_pretrig, def_fifo_pretrig, "fifo_pretrig");
0162 CSCBaseboard::checkConfigParameters(hit_persist, max_hit_persist, def_hit_persist, "hit_persist");
0163 CSCBaseboard::checkConfigParameters(drift_delay, max_drift_delay, def_drift_delay, "drift_delay");
0164 CSCBaseboard::checkConfigParameters(
0165 nplanes_hit_pretrig, max_nplanes_hit_pretrig, def_nplanes_hit_pretrig, "nplanes_hit_pretrig");
0166 CSCBaseboard::checkConfigParameters(
0167 nplanes_hit_pattern, max_nplanes_hit_pattern, def_nplanes_hit_pattern, "nplanes_hit_pattern");
0168 CSCBaseboard::checkConfigParameters(
0169 pid_thresh_pretrig, max_pid_thresh_pretrig, def_pid_thresh_pretrig, "pid_thresh_pretrig");
0170 CSCBaseboard::checkConfigParameters(min_separation, max_min_separation, def_min_separation, "min_separation");
0171 CSCBaseboard::checkConfigParameters(
0172 tmb_l1a_window_size, max_tmb_l1a_window_size, def_tmb_l1a_window_size, "tmb_l1a_window_size");
0173 }
0174
0175 void CSCCathodeLCTProcessor::clear() {
0176 thePreTriggerDigis.clear();
0177 thePreTriggerBXs.clear();
0178 for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
0179 bestCLCT[bx].clear();
0180 secondCLCT[bx].clear();
0181 }
0182 inTimeHMT_ = 0;
0183 }
0184
0185 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::run(const CSCComparatorDigiCollection* compdc) {
0186
0187
0188
0189
0190 static std::atomic<bool> config_dumped{false};
0191 if ((infoV > 0) && !config_dumped) {
0192 dumpConfigParams();
0193 config_dumped = true;
0194 }
0195
0196
0197
0198 if (numStrips_ <= 0 or numStrips_ > CSCConstants::MAX_NUM_STRIPS_RUN2) {
0199 if (cscChamber_) {
0200 numStrips_ = cscChamber_->layer(1)->geometry()->numberOfStrips();
0201
0202
0203
0204
0205
0206
0207
0208 if (isME11_) {
0209 if (theRing == 4) {
0210 edm::LogError("CSCCathodeLCTProcessor|SetupError")
0211 << "+++ Invalid ring number for this processor " << theRing << " was set in the config."
0212 << " +++\n"
0213 << "+++ CSC geometry looks garbled; no emulation possible +++\n";
0214 }
0215 if (!disableME1a_ && theRing == 1 && !gangedME1a_)
0216 numStrips_ = CSCConstants::MAX_NUM_STRIPS_RUN2;
0217 if (!disableME1a_ && theRing == 1 && gangedME1a_)
0218 numStrips_ = CSCConstants::MAX_NUM_STRIPS_RUN1;
0219 if (disableME1a_ && theRing == 1)
0220 numStrips_ = CSCConstants::NUM_STRIPS_ME1B;
0221 }
0222
0223 numHalfStrips_ = 2 * numStrips_ + 1;
0224 numCFEBs_ = numStrips_ / CSCConstants::NUM_STRIPS_PER_CFEB;
0225
0226 if (numStrips_ > CSCConstants::MAX_NUM_STRIPS_RUN2) {
0227 edm::LogError("CSCCathodeLCTProcessor|SetupError")
0228 << "+++ Number of strips, " << numStrips_ << " found in " << theCSCName_ << " (sector " << theSector
0229 << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
0230 << " exceeds max expected, " << CSCConstants::MAX_NUM_STRIPS_RUN2 << " +++\n"
0231 << "+++ CSC geometry looks garbled; no emulation possible +++\n";
0232 numStrips_ = -1;
0233 numHalfStrips_ = -1;
0234 numCFEBs_ = -1;
0235 }
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0250 stagger[i_layer] = (cscChamber_->layer(i_layer + 1)->geometry()->stagger() + 1) / 2;
0251 }
0252 } else {
0253 edm::LogError("CSCCathodeLCTProcessor|ConfigError")
0254 << " " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
0255 << theTrigChamber << ")"
0256 << " is not defined in current geometry! +++\n"
0257 << "+++ CSC geometry looks garbled; no emulation possible +++\n";
0258 numStrips_ = -1;
0259 numHalfStrips_ = -1;
0260 numCFEBs_ = -1;
0261 }
0262 }
0263
0264 if (numStrips_ <= 0 or 2 * (unsigned)numStrips_ > qualityControl_->get_csc_max_halfstrip(theStation, theRing)) {
0265 edm::LogError("CSCCathodeLCTProcessor|ConfigError")
0266 << " " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
0267 << theTrigChamber << "):"
0268 << " numStrips_ = " << numStrips_ << "; CLCT emulation skipped! +++";
0269 std::vector<CSCCLCTDigi> emptyV;
0270 return emptyV;
0271 }
0272
0273
0274 bool hasDigis = getDigis(compdc);
0275
0276 if (hasDigis) {
0277
0278 std::vector<int> halfStripTimes[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER];
0279 readComparatorDigis(halfStripTimes);
0280
0281
0282
0283
0284
0285
0286
0287 unsigned int layersHit = 0;
0288 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0289 for (int i_hstrip = 0; i_hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; i_hstrip++) {
0290 if (!halfStripTimes[i_layer][i_hstrip].empty()) {
0291 layersHit++;
0292 break;
0293 }
0294 }
0295 }
0296
0297
0298
0299 if (layersHit >= nplanes_hit_pretrig)
0300 run(halfStripTimes);
0301
0302
0303 encodeHighMultiplicityBits(halfStripTimes);
0304 }
0305
0306
0307 std::vector<CSCCLCTDigi> tmpV = getCLCTs();
0308
0309
0310
0311
0312
0313
0314
0315
0316 for (auto& p : tmpV) {
0317 p.setBX(p.getBX() + CSCConstants::ALCT_CLCT_OFFSET);
0318 }
0319
0320 return tmpV;
0321 }
0322
0323 void CSCCathodeLCTProcessor::run(
0324 const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) {
0325
0326
0327
0328
0329
0330
0331
0332
0333 pulse_.initialize(numHalfStrips_ + 1);
0334
0335 std::vector<CSCCLCTDigi> CLCTlist = findLCTs(halfstrip);
0336
0337
0338 if (CLCTlist.size() > 1)
0339 sort(CLCTlist.begin(), CLCTlist.end(), std::greater<CSCCLCTDigi>());
0340
0341 for (const auto& p : CLCTlist) {
0342 const int bx = p.getBX();
0343 if (bx >= CSCConstants::MAX_CLCT_TBINS) {
0344 if (infoV > 0)
0345 edm::LogWarning("L1CSCTPEmulatorOutOfTimeCLCT")
0346 << "+++ Bx of CLCT candidate, " << bx << ", exceeds max allowed, " << CSCConstants::MAX_CLCT_TBINS - 1
0347 << "; skipping it... +++\n";
0348 continue;
0349 }
0350
0351 if (!bestCLCT[bx].isValid()) {
0352 bestCLCT[bx] = p;
0353 } else if (!secondCLCT[bx].isValid()) {
0354 secondCLCT[bx] = p;
0355 }
0356 }
0357
0358 for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
0359 if (bestCLCT[bx].isValid()) {
0360 bestCLCT[bx].setTrknmb(1);
0361
0362
0363 qualityControl_->checkValid(bestCLCT[bx]);
0364
0365 if (infoV > 0)
0366 LogDebug("CSCCathodeLCTProcessor")
0367 << bestCLCT[bx] << " found in " << CSCDetId::chamberName(theEndcap, theStation, theRing, theChamber)
0368 << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
0369 << "\n";
0370 }
0371 if (secondCLCT[bx].isValid()) {
0372 secondCLCT[bx].setTrknmb(2);
0373
0374
0375 qualityControl_->checkValid(secondCLCT[bx]);
0376
0377 if (infoV > 0)
0378 LogDebug("CSCCathodeLCTProcessor")
0379 << secondCLCT[bx] << " found in " << CSCDetId::chamberName(theEndcap, theStation, theRing, theChamber)
0380 << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
0381 << "\n";
0382 }
0383 }
0384
0385
0386 }
0387
0388 bool CSCCathodeLCTProcessor::getDigis(const CSCComparatorDigiCollection* compdc) {
0389 bool hasDigis = false;
0390
0391
0392 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0393 digiV[i_layer].clear();
0394
0395 CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer + 1);
0396 getDigis(compdc, detid);
0397
0398 if (isME11_ && !disableME1a_) {
0399 CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer + 1);
0400 getDigis(compdc, detid_me1a);
0401 }
0402
0403 if (!digiV[i_layer].empty()) {
0404 hasDigis = true;
0405 if (infoV > 1) {
0406 LogTrace("CSCCathodeLCTProcessor") << "found " << digiV[i_layer].size() << " comparator digi(s) in layer "
0407 << i_layer << " of " << detid.chamberName() << " (trig. sector " << theSector
0408 << " subsector " << theSubsector << " id " << theTrigChamber << ")";
0409 }
0410 }
0411 }
0412
0413 return hasDigis;
0414 }
0415
0416 void CSCCathodeLCTProcessor::getDigis(const CSCComparatorDigiCollection* compdc, const CSCDetId& id) {
0417 const bool me1a = (id.station() == 1) && (id.ring() == 4);
0418 const CSCComparatorDigiCollection::Range rcompd = compdc->get(id);
0419 for (CSCComparatorDigiCollection::const_iterator digiIt = rcompd.first; digiIt != rcompd.second; ++digiIt) {
0420 const unsigned int origStrip = digiIt->getStrip();
0421 const unsigned int maxStripsME1a =
0422 gangedME1a_ ? CSCConstants::NUM_STRIPS_ME1A_GANGED : CSCConstants::NUM_STRIPS_ME1A_UNGANGED;
0423
0424
0425 if (me1a && origStrip <= maxStripsME1a && !disableME1a_) {
0426
0427
0428 CSCComparatorDigi digi_corr(
0429 origStrip + CSCConstants::NUM_STRIPS_ME1B, digiIt->getComparator(), digiIt->getTimeBinWord());
0430 digiV[id.layer() - 1].push_back(digi_corr);
0431 } else {
0432 digiV[id.layer() - 1].push_back(*digiIt);
0433 }
0434 }
0435 }
0436
0437 void CSCCathodeLCTProcessor::readComparatorDigis(
0438 std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) {
0439 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0440 int i_digi = 0;
0441 for (std::vector<CSCComparatorDigi>::iterator pld = digiV[i_layer].begin(); pld != digiV[i_layer].end();
0442 pld++, i_digi++) {
0443
0444 if (infoV > 1) {
0445 std::ostringstream strstrm;
0446 strstrm << "Comparator digi: comparator = " << pld->getComparator() << " strip #" << pld->getStrip()
0447 << " time bins on:";
0448 std::vector<int> bx_times = pld->getTimeBinsOn();
0449 for (unsigned int tbin = 0; tbin < bx_times.size(); tbin++)
0450 strstrm << " " << bx_times[tbin];
0451 LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
0452 }
0453
0454
0455
0456 int thisComparator = pld->getComparator();
0457 if (thisComparator != 0 && thisComparator != 1) {
0458 if (infoV >= 0)
0459 edm::LogWarning("L1CSCTPEmulatorWrongInput")
0460 << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
0461 << " Found comparator digi with wrong comparator value = " << thisComparator << "; skipping it... +++\n";
0462 continue;
0463 }
0464
0465
0466 int thisStrip = pld->getStrip() - 1;
0467 if (thisStrip < 0 || thisStrip >= numStrips_) {
0468 if (infoV >= 0)
0469 edm::LogWarning("L1CSCTPEmulatorWrongInput")
0470 << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
0471 << " Found comparator digi with wrong strip number = " << thisStrip << " (max strips = " << numStrips_
0472 << "); skipping it... +++\n";
0473 continue;
0474 }
0475
0476
0477
0478 int thisHalfstrip = 2 * thisStrip + thisComparator + stagger[i_layer];
0479 if (thisHalfstrip >= numHalfStrips_) {
0480 if (infoV >= 0)
0481 edm::LogWarning("L1CSCTPEmulatorWrongInput")
0482 << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
0483 << " Found wrong halfstrip number = " << thisHalfstrip << "; skipping this digi... +++\n";
0484 continue;
0485 }
0486
0487
0488 std::vector<int> bx_times = pld->getTimeBinsOn();
0489 for (unsigned int i = 0; i < bx_times.size(); i++) {
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499 if (bx_times[i] > 1 && bx_times[i] < static_cast<int>(fifo_tbins)) {
0500 if (i == 0 || (i > 0 && bx_times[i] - bx_times[i - 1] >= static_cast<int>(hit_persist))) {
0501
0502
0503
0504 if (infoV > 1)
0505 LogTrace("CSCCathodeLCTProcessor")
0506 << "Comp digi: layer " << i_layer + 1 << " digi #" << i_digi + 1 << " strip " << thisStrip
0507 << " halfstrip " << thisHalfstrip << " time " << bx_times[i] << " comparator " << thisComparator
0508 << " stagger " << stagger[i_layer];
0509 halfstrip[i_layer][thisHalfstrip].push_back(bx_times[i]);
0510 } else if (i > 0) {
0511 if (infoV > 1)
0512 LogTrace("CSCCathodeLCTProcessor")
0513 << "+++ station " << theStation << " ring " << theRing << " chamber " << theChamber
0514 << " Skipping comparator digi: strip = " << thisStrip << ", layer = " << i_layer + 1
0515 << ", bx = " << bx_times[i] << ", bx of previous hit = " << bx_times[i - 1];
0516 }
0517 } else {
0518 if (infoV > 1)
0519 LogTrace("CSCCathodeLCTProcessor") << "+++ station " << theStation << " ring " << theRing << " chamber "
0520 << theChamber << "+++ Skipping comparator digi: strip = " << thisStrip
0521 << ", layer = " << i_layer + 1 << ", bx = " << bx_times[i] << " +++";
0522 }
0523 }
0524 }
0525 }
0526 }
0527
0528
0529 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::findLCTs(
0530 const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) {
0531 std::vector<CSCCLCTDigi> lctList;
0532
0533 if (infoV > 1)
0534 dumpDigis(halfstrip);
0535
0536
0537 pulseExtension(halfstrip);
0538
0539 unsigned int start_bx = start_bx_shift;
0540
0541
0542 unsigned int stop_bx = fifo_tbins - drift_delay;
0543
0544 while (start_bx < stop_bx) {
0545
0546 CSCCLCTDigi tempBestCLCT;
0547 CSCCLCTDigi tempSecondCLCT;
0548
0549
0550
0551 int first_bx = 999;
0552 bool pre_trig = preTrigger(start_bx, first_bx);
0553
0554
0555
0556 if (pre_trig) {
0557 thePreTriggerBXs.push_back(first_bx);
0558 if (infoV > 1)
0559 LogTrace("CSCCathodeLCTProcessor") << "..... pretrigger at bx = " << first_bx << "; waiting drift delay .....";
0560
0561
0562
0563
0564
0565
0566 int latch_bx = first_bx + drift_delay;
0567
0568
0569
0570 std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer>> hits_in_patterns;
0571 hits_in_patterns.clear();
0572
0573
0574
0575 bool hits_in_time = patternFinding(latch_bx, hits_in_patterns);
0576 if (infoV > 1) {
0577 if (hits_in_time) {
0578 for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0579 if (nhits[hstrip] > 0) {
0580 LogTrace("CSCCathodeLCTProcessor")
0581 << " bx = " << std::setw(2) << latch_bx << " --->"
0582 << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
0583 << " nhits = " << nhits[hstrip];
0584 }
0585 }
0586 }
0587 }
0588
0589
0590
0591
0592
0593
0594
0595
0596 int quality[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER];
0597 int best_halfstrip[CSCConstants::MAX_CLCTS_PER_PROCESSOR];
0598 int best_quality[CSCConstants::MAX_CLCTS_PER_PROCESSOR];
0599
0600 for (int ilct = 0; ilct < CSCConstants::MAX_CLCTS_PER_PROCESSOR; ilct++) {
0601 best_halfstrip[ilct] = -1;
0602 best_quality[ilct] = 0;
0603 }
0604
0605
0606
0607 if (hits_in_time) {
0608 for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0609
0610
0611 quality[hstrip] = (best_pid[hstrip] & 14) | (nhits[hstrip] << 5);
0612 if (quality[hstrip] > best_quality[0]) {
0613 best_halfstrip[0] = hstrip;
0614 best_quality[0] = quality[hstrip];
0615 }
0616
0617 const int best_hs(best_halfstrip[0]);
0618
0619 if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
0620
0621 tempBestCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pid[best_hs]]);
0622 }
0623 }
0624 }
0625
0626
0627 if (best_halfstrip[0] >= 0) {
0628
0629
0630
0631 const unsigned halfStripBestCLCT(tempBestCLCT.getKeyStrip() + stagger[CSCConstants::KEY_CLCT_LAYER - 1]);
0632
0633
0634
0635 markBusyKeys(halfStripBestCLCT, best_pid[halfStripBestCLCT], quality);
0636
0637 for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0638 if (quality[hstrip] > best_quality[1]) {
0639 best_halfstrip[1] = hstrip;
0640 best_quality[1] = quality[hstrip];
0641 }
0642
0643 const int best_hs(best_halfstrip[1]);
0644
0645 if (best_hs >= 0 && nhits[best_hs] >= nplanes_hit_pattern) {
0646
0647 tempSecondCLCT = constructCLCT(first_bx, best_hs, hits_in_patterns[best_hs][best_pid[best_hs]]);
0648 }
0649 }
0650
0651 if (tempBestCLCT.isValid()) {
0652 lctList.push_back(tempBestCLCT);
0653 }
0654 if (tempSecondCLCT.isValid()) {
0655 lctList.push_back(tempSecondCLCT);
0656 }
0657 }
0658
0659
0660
0661
0662
0663
0664 start_bx = fifo_tbins;
0665
0666
0667
0668 unsigned int stop_time = fifo_tbins - drift_delay;
0669 for (unsigned int bx = latch_bx + 1; bx < stop_time; bx++) {
0670 bool return_to_idle = true;
0671 bool hits_in_time = patternFinding(bx, hits_in_patterns);
0672 if (hits_in_time) {
0673 for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0674
0675 if (nhits[hstrip] >= nplanes_hit_pretrig) {
0676 if (infoV > 1)
0677 LogTrace("CSCCathodeLCTProcessor") << " State machine busy at bx = " << bx;
0678 return_to_idle = false;
0679 break;
0680 }
0681 }
0682 }
0683 if (return_to_idle) {
0684 if (infoV > 1)
0685 LogTrace("CSCCathodeLCTProcessor") << " State machine returns to idle state at bx = " << bx;
0686 start_bx = bx;
0687 break;
0688 }
0689 }
0690 }
0691 else {
0692 start_bx = first_bx + 1;
0693 }
0694 }
0695
0696 return lctList;
0697 }
0698
0699
0700 void CSCCathodeLCTProcessor::pulseExtension(
0701 const std::vector<int> time[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) {
0702 const unsigned bits_in_pulse = pulse_.bitsInPulse();
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712 pulse_.clear();
0713
0714
0715 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0716 for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
0717
0718
0719 if (!time[i_layer][i_strip].empty()) {
0720 std::vector<int> bx_times = time[i_layer][i_strip];
0721 for (unsigned int i = 0; i < bx_times.size(); i++) {
0722
0723 if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
0724 if (infoV > 0)
0725 edm::LogWarning("L1CSCTPEmulatorOutOfTimeDigi")
0726 << "+++ BX time of comparator digi (halfstrip = " << i_strip << " layer = " << i_layer
0727 << ") bx = " << bx_times[i] << " is not within the range (0-" << bits_in_pulse
0728 << "] allowed for pulse extension. Skip this digi! +++\n";
0729 continue;
0730 }
0731 if (bx_times[i] >= start_bx_shift) {
0732 pulse_.extend(i_layer, i_strip, bx_times[i], hit_persist);
0733 }
0734 }
0735 }
0736 }
0737 }
0738 }
0739
0740
0741 bool CSCCathodeLCTProcessor::preTrigger(const int start_bx, int& first_bx) {
0742 if (infoV > 1)
0743 LogTrace("CSCCathodeLCTProcessor") << "....................PreTrigger...........................";
0744
0745 int nPreTriggers = 0;
0746
0747 bool pre_trig = false;
0748
0749 for (unsigned int bx_time = start_bx; bx_time < fifo_tbins; bx_time++) {
0750
0751
0752
0753
0754
0755
0756 std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer>> hits_in_patterns;
0757 hits_in_patterns.clear();
0758
0759 bool hits_in_time = patternFinding(bx_time, hits_in_patterns);
0760 if (hits_in_time) {
0761
0762 clearPreTriggers();
0763
0764 for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0765
0766 if (infoV > 1) {
0767 if (nhits[hstrip] > 0) {
0768 LogTrace("CSCCathodeLCTProcessor")
0769 << " bx = " << std::setw(2) << bx_time << " --->"
0770 << " halfstrip = " << std::setw(3) << hstrip << " best pid = " << std::setw(2) << best_pid[hstrip]
0771 << " nhits = " << nhits[hstrip];
0772 }
0773 }
0774
0775 if (nhits[hstrip] >= nplanes_hit_pretrig && best_pid[hstrip] >= pid_thresh_pretrig) {
0776 pre_trig = true;
0777 ispretrig_[hstrip] = true;
0778
0779
0780 nPreTriggers++;
0781 thePreTriggerDigis.push_back(constructPreCLCT(bx_time, hstrip, nPreTriggers));
0782 }
0783 }
0784
0785
0786 if (pre_trig) {
0787 first_bx = bx_time;
0788 return true;
0789 }
0790 }
0791 }
0792
0793 if (infoV > 1)
0794 LogTrace("CSCCathodeLCTProcessor") << "no pretrigger, returning \n";
0795 first_bx = fifo_tbins;
0796 return false;
0797 }
0798
0799
0800 bool CSCCathodeLCTProcessor::patternFinding(
0801 const unsigned int bx_time, std::map<int, std::map<int, CSCCLCTDigi::ComparatorContainer>>& hits_in_patterns) {
0802 if (bx_time >= fifo_tbins)
0803 return false;
0804
0805 unsigned layers_hit = pulse_.numberOfLayersAtBX(bx_time);
0806 if (layers_hit < nplanes_hit_pretrig)
0807 return false;
0808
0809 for (int key_hstrip = 0; key_hstrip < numHalfStrips_; key_hstrip++) {
0810 best_pid[key_hstrip] = 0;
0811 nhits[key_hstrip] = 0;
0812 }
0813
0814 bool hit_layer[CSCConstants::NUM_LAYERS];
0815
0816
0817 for (int key_hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; key_hstrip < numHalfStrips_; key_hstrip++) {
0818
0819 for (unsigned int pid = clct_pattern_.size() - 1; pid >= pid_thresh_pretrig and pid < clct_pattern_.size(); pid--) {
0820 layers_hit = 0;
0821
0822 for (int ilayer = 0; ilayer < CSCConstants::NUM_LAYERS; ilayer++) {
0823 hit_layer[ilayer] = false;
0824 }
0825
0826
0827 CSCCLCTDigi::ComparatorContainer hits_single_pattern;
0828 hits_single_pattern.resize(6);
0829 for (auto& p : hits_single_pattern) {
0830 p.resize(CSCConstants::CLCT_PATTERN_WIDTH, CSCConstants::INVALID_HALF_STRIP);
0831 }
0832
0833
0834 double num_pattern_hits = 0., times_sum = 0.;
0835 std::multiset<int> mset_for_median;
0836 mset_for_median.clear();
0837
0838
0839
0840 for (int this_layer = 0; this_layer < CSCConstants::NUM_LAYERS; this_layer++) {
0841 for (int strip_num = 0; strip_num < CSCConstants::CLCT_PATTERN_WIDTH; strip_num++) {
0842
0843 if (clct_pattern_[pid][this_layer][strip_num] == 0)
0844 continue;
0845
0846
0847 int this_strip = CSCPatternBank::clct_pattern_offset_[strip_num] + key_hstrip;
0848
0849
0850 if (this_strip >= 0 && this_strip < numHalfStrips_) {
0851 if (infoV > 3) {
0852 LogTrace("CSCCathodeLCTProcessor") << " In patternFinding: key_strip = " << key_hstrip << " pid = " << pid
0853 << " layer = " << this_layer << " strip = " << this_strip << std::endl;
0854 }
0855
0856 if (pulse_.isOneShotHighAtBX(this_layer, this_strip, bx_time)) {
0857 if (hit_layer[this_layer] == false) {
0858 hit_layer[this_layer] = true;
0859 layers_hit++;
0860
0861 hits_single_pattern[this_layer][strip_num] = this_strip - stagger[this_layer];
0862 }
0863
0864
0865
0866 int first_bx_layer = bx_time;
0867 for (unsigned int dbx = 0; dbx < hit_persist; dbx++) {
0868 if (pulse_.isOneShotHighAtBX(this_layer, this_strip, first_bx_layer - 1))
0869 first_bx_layer--;
0870 else
0871 break;
0872 }
0873 times_sum += (double)first_bx_layer;
0874 num_pattern_hits += 1.;
0875 mset_for_median.insert(first_bx_layer);
0876 if (infoV > 2)
0877 LogTrace("CSCCathodeLCTProcessor") << " 1st bx in layer: " << first_bx_layer << " sum bx: " << times_sum
0878 << " #pat. hits: " << num_pattern_hits;
0879 }
0880 }
0881 }
0882 }
0883
0884
0885 if (layers_hit >= nplanes_hit_pattern) {
0886 hits_in_patterns[key_hstrip][pid] = hits_single_pattern;
0887 }
0888
0889
0890 if (layers_hit > nhits[key_hstrip]) {
0891 best_pid[key_hstrip] = pid;
0892 nhits[key_hstrip] = layers_hit;
0893
0894
0895 if (nhits[key_hstrip] == CSCConstants::NUM_LAYERS)
0896 break;
0897 }
0898 }
0899 }
0900
0901
0902
0903 return true;
0904 }
0905
0906
0907 void CSCCathodeLCTProcessor::markBusyKeys(const int best_hstrip,
0908 const int best_patid,
0909 int quality[CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) {
0910 int nspan = min_separation;
0911 int pspan = min_separation;
0912
0913 for (int hstrip = best_hstrip - nspan; hstrip <= best_hstrip + pspan; hstrip++) {
0914 if (hstrip >= 0 && hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER) {
0915 quality[hstrip] = 0;
0916 }
0917 }
0918 }
0919
0920 CSCCLCTDigi CSCCathodeLCTProcessor::constructCLCT(const int bx,
0921 const unsigned halfstrip_withstagger,
0922 const CSCCLCTDigi::ComparatorContainer& hits) {
0923
0924 const unsigned quality = nhits[halfstrip_withstagger];
0925 const unsigned pattern = best_pid[halfstrip_withstagger];
0926 const unsigned bend = CSCPatternBank::getPatternBend(clct_pattern_[pattern]);
0927 const unsigned keyhalfstrip = halfstrip_withstagger - stagger[CSCConstants::KEY_CLCT_LAYER - 1];
0928 const unsigned cfeb = keyhalfstrip / CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
0929 const unsigned halfstrip = keyhalfstrip % CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
0930
0931
0932 CSCCLCTDigi clct(1,
0933 quality,
0934 pattern,
0935
0936 1,
0937 bend,
0938 halfstrip,
0939 cfeb,
0940 bx,
0941 0,
0942 0,
0943 -1,
0944 CSCCLCTDigi::Version::Legacy);
0945
0946
0947 clct.setHits(hits);
0948
0949
0950 if (runCCLUT_) {
0951 cclut_->run(clct, numCFEBs_);
0952 }
0953
0954
0955 cleanComparatorContainer(clct);
0956
0957 if (infoV > 1) {
0958 LogTrace("CSCCathodeLCTProcessor") << "Produce CLCT " << clct << std::endl;
0959 }
0960
0961 return clct;
0962 }
0963
0964 CSCCLCTPreTriggerDigi CSCCathodeLCTProcessor::constructPreCLCT(const int bx_time,
0965 const unsigned hstrip,
0966 const unsigned nPreTriggers) const {
0967 const int bend = clct_pattern_[best_pid[hstrip]][CSCConstants::NUM_LAYERS - 1][CSCConstants::CLCT_PATTERN_WIDTH];
0968 const int halfstrip = hstrip % CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
0969 const int cfeb = hstrip / CSCConstants::NUM_HALF_STRIPS_PER_CFEB;
0970 return CSCCLCTPreTriggerDigi(1, nhits[hstrip], best_pid[hstrip], 1, bend, halfstrip, cfeb, bx_time, nPreTriggers, 0);
0971 }
0972
0973 void CSCCathodeLCTProcessor::clearPreTriggers() {
0974 for (int hstrip = stagger[CSCConstants::KEY_CLCT_LAYER - 1]; hstrip < numHalfStrips_; hstrip++) {
0975 ispretrig_[hstrip] = false;
0976 }
0977 }
0978
0979 void CSCCathodeLCTProcessor::cleanComparatorContainer(CSCCLCTDigi& clct) const {
0980 CSCCLCTDigi::ComparatorContainer newHits = clct.getHits();
0981 for (auto& p : newHits) {
0982 p.erase(
0983 std::remove_if(p.begin(), p.end(), [](unsigned i) -> bool { return i == CSCConstants::INVALID_HALF_STRIP; }),
0984 p.end());
0985 }
0986 clct.setHits(newHits);
0987 }
0988
0989
0990
0991
0992
0993 void CSCCathodeLCTProcessor::dumpConfigParams() const {
0994 std::ostringstream strm;
0995 strm << "\n";
0996 strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
0997 strm << "+ CLCT configuration parameters: +\n";
0998 strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
0999 strm << " fifo_tbins [total number of time bins in DAQ readout] = " << fifo_tbins << "\n";
1000 strm << " fifo_pretrig [start time of cathode raw hits in DAQ readout] = " << fifo_pretrig << "\n";
1001 strm << " hit_persist [duration of signal pulse, in 25 ns bins] = " << hit_persist << "\n";
1002 strm << " drift_delay [time after pre-trigger before TMB latches LCTs] = " << drift_delay << "\n";
1003 strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = " << nplanes_hit_pretrig << "\n";
1004 strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = " << nplanes_hit_pattern << "\n";
1005 strm << " pid_thresh_pretrig [lower threshold on pattern id] = " << pid_thresh_pretrig << "\n";
1006 strm << " min_separation [region of busy key strips] = " << min_separation << "\n";
1007 strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1008 LogDebug("CSCCathodeLCTProcessor") << strm.str();
1009 }
1010
1011
1012 void CSCCathodeLCTProcessor::dumpDigis(
1013 const std::vector<int> strip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) const {
1014 LogDebug("CSCCathodeLCTProcessor") << theCSCName_ << " strip type: half-strip, numHalfStrips " << numHalfStrips_;
1015
1016 std::ostringstream strstrm;
1017 for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
1018 if (i_strip % 10 == 0) {
1019 if (i_strip < 100)
1020 strstrm << i_strip / 10;
1021 else
1022 strstrm << (i_strip - 100) / 10;
1023 } else
1024 strstrm << " ";
1025 if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1026 strstrm << " ";
1027 }
1028 strstrm << "\n";
1029 for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
1030 strstrm << i_strip % 10;
1031 if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1032 strstrm << " ";
1033 }
1034 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1035 strstrm << "\n";
1036 for (int i_strip = 0; i_strip < numHalfStrips_; i_strip++) {
1037 if (!strip[i_layer][i_strip].empty()) {
1038 std::vector<int> bx_times = strip[i_layer][i_strip];
1039
1040 strstrm << std::hex << bx_times[0] << std::dec;
1041 } else {
1042 strstrm << "-";
1043 }
1044 if ((i_strip + 1) % CSCConstants::NUM_HALF_STRIPS_PER_CFEB == 0)
1045 strstrm << " ";
1046 }
1047 }
1048 LogTrace("CSCCathodeLCTProcessor") << strstrm.str();
1049 }
1050
1051
1052
1053 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::readoutCLCTs() const {
1054
1055 std::vector<CSCCLCTDigi> tmpV;
1056
1057
1058
1059
1060
1061
1062
1063
1064 const unsigned delta_tbin = tmb_l1a_window_size / 2;
1065 int early_tbin = CSCConstants::CLCT_CENTRAL_BX - delta_tbin;
1066 int late_tbin = CSCConstants::CLCT_CENTRAL_BX + delta_tbin;
1067
1068
1069
1070
1071 if (tmb_l1a_window_size % 2 == 0)
1072 late_tbin = CSCConstants::CLCT_CENTRAL_BX + delta_tbin - 1;
1073 const int max_late_tbin = CSCConstants::MAX_CLCT_TBINS - 1;
1074
1075
1076 if (early_tbin < 0) {
1077 edm::LogWarning("CSCCathodeLCTProcessor|SuspiciousParameters")
1078 << "Early time bin (early_tbin) smaller than minimum allowed, which is 0. set early_tbin to 0.";
1079 early_tbin = 0;
1080 }
1081 if (late_tbin > max_late_tbin) {
1082 edm::LogWarning("CSCCathodeLCTProcessor|SuspiciousParameters")
1083 << "Late time bin (late_tbin) larger than maximum allowed, which is " << max_late_tbin
1084 << ". set early_tbin to max allowed";
1085 late_tbin = CSCConstants::MAX_CLCT_TBINS - 1;
1086 }
1087
1088
1089 const auto& all_clcts = getCLCTs();
1090
1091
1092
1093 int bx_readout = -1;
1094 for (const auto& clct : all_clcts) {
1095
1096 if (!clct.isValid())
1097 continue;
1098
1099 const int bx = clct.getBX();
1100
1101 if (bx < early_tbin) {
1102 if (infoV > 1)
1103 LogDebug("CSCCathodeLCTProcessor")
1104 << " Do not report correlated CLCT on key halfstrip " << clct.getStrip() << ": found at bx " << bx
1105 << ", whereas the earliest allowed bx is " << early_tbin;
1106 continue;
1107 }
1108
1109
1110 if (bx > late_tbin) {
1111 if (infoV > 1)
1112 LogDebug("CSCCathodeLCTProcessor")
1113 << " Do not report correlated CLCT on key halfstrip " << clct.getStrip() << ": found at bx " << bx
1114 << ", whereas the latest allowed bx is " << late_tbin;
1115 continue;
1116 }
1117
1118
1119 if (readout_earliest_2) {
1120
1121
1122 if (bx_readout == -1 || bx == bx_readout) {
1123 tmpV.push_back(clct);
1124 if (bx_readout == -1)
1125 bx_readout = bx;
1126 }
1127 } else
1128 tmpV.push_back(clct);
1129 }
1130
1131
1132 qualityControl_->checkMultiplicityBX(tmpV);
1133 for (const auto& clct : tmpV) {
1134 qualityControl_->checkValid(clct);
1135 }
1136
1137 return tmpV;
1138 }
1139
1140
1141 std::vector<CSCCLCTDigi> CSCCathodeLCTProcessor::getCLCTs() const {
1142 std::vector<CSCCLCTDigi> tmpV;
1143 for (int bx = 0; bx < CSCConstants::MAX_CLCT_TBINS; bx++) {
1144 if (bestCLCT[bx].isValid())
1145 tmpV.push_back(bestCLCT[bx]);
1146 if (secondCLCT[bx].isValid())
1147 tmpV.push_back(secondCLCT[bx]);
1148 }
1149 return tmpV;
1150 }
1151
1152
1153
1154
1155
1156
1157 CSCCLCTDigi CSCCathodeLCTProcessor::getBestCLCT(int bx) const {
1158 CSCCLCTDigi lct = bestCLCT[bx];
1159 lct.setBX(lct.getBX() + CSCConstants::ALCT_CLCT_OFFSET);
1160 return lct;
1161 }
1162
1163 CSCCLCTDigi CSCCathodeLCTProcessor::getSecondCLCT(int bx) const {
1164 CSCCLCTDigi lct = secondCLCT[bx];
1165 lct.setBX(lct.getBX() + CSCConstants::ALCT_CLCT_OFFSET);
1166 return lct;
1167 }
1168
1169
1170 CSCShowerDigi CSCCathodeLCTProcessor::readoutShower() const { return shower_; }
1171
1172 void CSCCathodeLCTProcessor::encodeHighMultiplicityBits(
1173 const std::vector<int> halfstrip[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER]) {
1174 inTimeHMT_ = 0;
1175
1176 auto layerTime = [=](unsigned time) { return time == CSCConstants::CLCT_CENTRAL_BX; };
1177
1178 unsigned nLayersWithHits = 0;
1179 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1180 bool atLeastOneWGHit = false;
1181 for (int i_hstrip = 0; i_hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; i_hstrip++) {
1182
1183 if (!halfstrip[i_layer][i_hstrip].empty()) {
1184 auto times = halfstrip[i_layer][i_hstrip];
1185 int nLayerTime = std::count_if(times.begin(), times.end(), layerTime);
1186
1187 if (nLayerTime > 0) {
1188 atLeastOneWGHit = true;
1189 break;
1190 }
1191 }
1192 }
1193
1194 if (atLeastOneWGHit) {
1195 nLayersWithHits++;
1196 }
1197 }
1198
1199
1200
1201 if (nLayersWithHits < minLayersCentralTBin_)
1202 return;
1203
1204
1205 auto inTime = [=](unsigned time) { return time >= showerMinInTBin_ and time <= showerMaxInTBin_; };
1206
1207
1208 unsigned hitsInTime = 0;
1209 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1210 for (int i_hstrip = 0; i_hstrip < CSCConstants::MAX_NUM_HALF_STRIPS_RUN2_TRIGGER; i_hstrip++) {
1211 auto times = halfstrip[i_layer][i_hstrip];
1212 hitsInTime += std::count_if(times.begin(), times.end(), inTime);
1213 }
1214 }
1215
1216
1217
1218 unsigned csc_idx = CSCDetId::iChamberType(theStation, theRing) - 2;
1219
1220
1221 std::vector<unsigned> station_thresholds = {
1222 thresholds_[csc_idx * 3], thresholds_[csc_idx * 3 + 1], thresholds_[csc_idx * 3 + 2]};
1223
1224
1225 for (unsigned i = 0; i < station_thresholds.size(); i++) {
1226 if (hitsInTime >= station_thresholds[i]) {
1227 inTimeHMT_ = i + 1;
1228 }
1229 }
1230
1231
1232 shower_ = CSCShowerDigi(inTimeHMT_, false, theTrigChamber);
1233 }