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