File indexing completed on 2021-11-04 03:24:52
0001 #include "L1Trigger/CSCTriggerPrimitives/interface/CSCAnodeLCTProcessor.h"
0002 #include <set>
0003
0004
0005 const unsigned int CSCAnodeLCTProcessor::def_fifo_tbins = 16;
0006 const unsigned int CSCAnodeLCTProcessor::def_fifo_pretrig = 10;
0007 const unsigned int CSCAnodeLCTProcessor::def_drift_delay = 2;
0008 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pretrig = 2;
0009 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_pattern = 4;
0010 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_accel_pretrig = 2;
0011 const unsigned int CSCAnodeLCTProcessor::def_nplanes_hit_accel_pattern = 4;
0012 const unsigned int CSCAnodeLCTProcessor::def_trig_mode = 2;
0013 const unsigned int CSCAnodeLCTProcessor::def_accel_mode = 0;
0014 const unsigned int CSCAnodeLCTProcessor::def_l1a_window_width = 7;
0015
0016
0017
0018
0019
0020 CSCAnodeLCTProcessor::CSCAnodeLCTProcessor(unsigned endcap,
0021 unsigned station,
0022 unsigned sector,
0023 unsigned subsector,
0024 unsigned chamber,
0025 const edm::ParameterSet& conf)
0026 : CSCBaseboard(endcap, station, sector, subsector, chamber, conf) {
0027 static std::atomic<bool> config_dumped{false};
0028
0029
0030 fifo_tbins = alctParams_.getParameter<unsigned int>("alctFifoTbins");
0031 fifo_pretrig = alctParams_.getParameter<unsigned int>("alctFifoPretrig");
0032 drift_delay = alctParams_.getParameter<unsigned int>("alctDriftDelay");
0033 nplanes_hit_pretrig = alctParams_.getParameter<unsigned int>("alctNplanesHitPretrig");
0034 nplanes_hit_pattern = alctParams_.getParameter<unsigned int>("alctNplanesHitPattern");
0035 nplanes_hit_accel_pretrig = alctParams_.getParameter<unsigned int>("alctNplanesHitAccelPretrig");
0036 nplanes_hit_accel_pattern = alctParams_.getParameter<unsigned int>("alctNplanesHitAccelPattern");
0037 trig_mode = alctParams_.getParameter<unsigned int>("alctTrigMode");
0038 accel_mode = alctParams_.getParameter<unsigned int>("alctAccelMode");
0039 l1a_window_width = alctParams_.getParameter<unsigned int>("alctL1aWindowWidth");
0040
0041 hit_persist = alctParams_.getParameter<unsigned int>("alctHitPersist");
0042
0043
0044 infoV = alctParams_.getParameter<int>("verbosity");
0045
0046
0047 early_tbins = alctParams_.getParameter<int>("alctEarlyTbins");
0048 if (early_tbins < 0)
0049 early_tbins = fifo_pretrig - CSCConstants::ALCT_EMUL_TIME_OFFSET;
0050
0051
0052 ghost_cancellation_bx_depth = alctParams_.getParameter<int>("alctGhostCancellationBxDepth");
0053
0054
0055 ghost_cancellation_side_quality = alctParams_.getParameter<bool>("alctGhostCancellationSideQuality");
0056
0057
0058 pretrig_extra_deadtime = alctParams_.getParameter<unsigned int>("alctPretrigDeadtime");
0059
0060
0061 narrow_mask_r1 = alctParams_.getParameter<bool>("alctNarrowMaskForR1");
0062
0063
0064 checkConfigParameters();
0065 if ((infoV > 0 || (runPhase2_)) && !config_dumped) {
0066 dumpConfigParams();
0067 config_dumped = true;
0068 }
0069
0070 numWireGroups = 0;
0071 MESelection = (theStation < 3) ? 0 : 1;
0072
0073
0074 use_corrected_bx = false;
0075 if (runPhase2_) {
0076 use_corrected_bx = alctParams_.getParameter<bool>("alctUseCorrectedBx");
0077 }
0078
0079
0080 loadPatternMask();
0081
0082
0083 qualityControl_ = std::make_unique<LCTQualityControl>(endcap, station, sector, subsector, chamber, conf);
0084
0085 const auto& shower = showerParams_.getParameterSet("anodeShower");
0086 thresholds_ = shower.getParameter<std::vector<unsigned>>("showerThresholds");
0087 showerMinInTBin_ = shower.getParameter<unsigned>("showerMinInTBin");
0088 showerMaxInTBin_ = shower.getParameter<unsigned>("showerMaxInTBin");
0089 showerMinOutTBin_ = shower.getParameter<unsigned>("showerMinOutTBin");
0090 showerMaxOutTBin_ = shower.getParameter<unsigned>("showerMaxOutTBin");
0091 minLayersCentralTBin_ = shower.getParameter<unsigned>("minLayersCentralTBin");
0092 }
0093
0094 void CSCAnodeLCTProcessor::loadPatternMask() {
0095
0096 if (narrow_mask_r1 && (theRing == 1 || theRing == 4)) {
0097 alct_pattern_ = CSCPatternBank::alct_pattern_r1_;
0098 } else {
0099 alct_pattern_ = CSCPatternBank::alct_pattern_legacy_;
0100 }
0101 }
0102
0103 void CSCAnodeLCTProcessor::setDefaultConfigParameters() {
0104
0105 fifo_tbins = def_fifo_tbins;
0106 fifo_pretrig = def_fifo_pretrig;
0107 drift_delay = def_drift_delay;
0108 nplanes_hit_pretrig = def_nplanes_hit_pretrig;
0109 nplanes_hit_pattern = def_nplanes_hit_pattern;
0110 nplanes_hit_accel_pretrig = def_nplanes_hit_accel_pretrig;
0111 nplanes_hit_accel_pattern = def_nplanes_hit_accel_pattern;
0112 trig_mode = def_trig_mode;
0113 accel_mode = def_accel_mode;
0114 l1a_window_width = def_l1a_window_width;
0115 }
0116
0117
0118 void CSCAnodeLCTProcessor::setConfigParameters(const CSCDBL1TPParameters* conf) {
0119 static std::atomic<bool> config_dumped{false};
0120
0121 fifo_tbins = conf->alctFifoTbins();
0122 fifo_pretrig = conf->alctFifoPretrig();
0123 drift_delay = conf->alctDriftDelay();
0124 nplanes_hit_pretrig = conf->alctNplanesHitPretrig();
0125 nplanes_hit_pattern = conf->alctNplanesHitPattern();
0126 nplanes_hit_accel_pretrig = conf->alctNplanesHitAccelPretrig();
0127 nplanes_hit_accel_pattern = conf->alctNplanesHitAccelPattern();
0128 trig_mode = conf->alctTrigMode();
0129 accel_mode = conf->alctAccelMode();
0130 l1a_window_width = conf->alctL1aWindowWidth();
0131
0132
0133 checkConfigParameters();
0134 if (!config_dumped) {
0135 dumpConfigParams();
0136 config_dumped = true;
0137 }
0138 }
0139
0140 void CSCAnodeLCTProcessor::checkConfigParameters() {
0141
0142
0143
0144 static const unsigned int max_fifo_tbins = 1 << 5;
0145 static const unsigned int max_fifo_pretrig = 1 << 5;
0146 static const unsigned int max_drift_delay = 1 << 2;
0147 static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
0148 static const unsigned int max_nplanes_hit_pattern = 1 << 3;
0149 static const unsigned int max_nplanes_hit_accel_pretrig = 1 << 3;
0150 static const unsigned int max_nplanes_hit_accel_pattern = 1 << 3;
0151 static const unsigned int max_trig_mode = 1 << 2;
0152 static const unsigned int max_accel_mode = 1 << 2;
0153 static const unsigned int max_l1a_window_width = CSCConstants::MAX_ALCT_TBINS;
0154
0155
0156 CSCBaseboard::checkConfigParameters(fifo_tbins, max_fifo_tbins, def_fifo_tbins, "fifo_tbins");
0157 CSCBaseboard::checkConfigParameters(fifo_pretrig, max_fifo_pretrig, def_fifo_pretrig, "fifo_pretrig");
0158 CSCBaseboard::checkConfigParameters(drift_delay, max_drift_delay, def_drift_delay, "drift_delay");
0159 CSCBaseboard::checkConfigParameters(
0160 nplanes_hit_pretrig, max_nplanes_hit_pretrig, def_nplanes_hit_pretrig, "nplanes_hit_pretrig");
0161 CSCBaseboard::checkConfigParameters(
0162 nplanes_hit_pattern, max_nplanes_hit_pattern, def_nplanes_hit_pattern, "nplanes_hit_pattern");
0163 CSCBaseboard::checkConfigParameters(nplanes_hit_accel_pretrig,
0164 max_nplanes_hit_accel_pretrig,
0165 def_nplanes_hit_accel_pretrig,
0166 "nplanes_hit_accel_pretrig");
0167 CSCBaseboard::checkConfigParameters(nplanes_hit_accel_pattern,
0168 max_nplanes_hit_accel_pattern,
0169 def_nplanes_hit_accel_pattern,
0170 "nplanes_hit_accel_pattern");
0171 CSCBaseboard::checkConfigParameters(trig_mode, max_trig_mode, def_trig_mode, "trig_mode");
0172 CSCBaseboard::checkConfigParameters(accel_mode, max_accel_mode, def_accel_mode, "accel_mode");
0173 CSCBaseboard::checkConfigParameters(l1a_window_width, max_l1a_window_width, def_l1a_window_width, "l1a_window_width");
0174 }
0175
0176 void CSCAnodeLCTProcessor::clear() {
0177 for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
0178 bestALCT[bx].clear();
0179 secondALCT[bx].clear();
0180 }
0181 lct_list.clear();
0182 inTimeHMT_ = 0;
0183 }
0184
0185 void CSCAnodeLCTProcessor::clear(const int wire, const int pattern) {
0186
0187 if (pattern == CSCConstants::ALCT_ACCELERATOR_PATTERN)
0188 quality[wire][CSCConstants::ALCT_ACCELERATOR_PATTERN] = -999;
0189 else {
0190 quality[wire][CSCConstants::ALCT_COLLISIONA_PATTERN] = -999;
0191 quality[wire][CSCConstants::ALCT_COLLISIONB_PATTERN] = -999;
0192 }
0193 }
0194
0195 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::run(const CSCWireDigiCollection* wiredc) {
0196 static std::atomic<bool> config_dumped{false};
0197 if ((infoV > 0 || (runPhase2_)) && !config_dumped) {
0198 dumpConfigParams();
0199 config_dumped = true;
0200 }
0201
0202
0203
0204 if (numWireGroups <= 0 or numWireGroups > CSCConstants::MAX_NUM_WIREGROUPS) {
0205 if (cscChamber_) {
0206 numWireGroups = cscChamber_->layer(1)->geometry()->numberOfWireGroups();
0207 if (numWireGroups > CSCConstants::MAX_NUM_WIREGROUPS) {
0208 edm::LogError("CSCAnodeLCTProcessor|SetupError")
0209 << "+++ Number of wire groups, " << numWireGroups << " found in " << theCSCName_ << " (sector " << theSector
0210 << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
0211 << " exceeds max expected, " << CSCConstants::MAX_NUM_WIREGROUPS << " +++\n"
0212 << "+++ CSC geometry looks garbled; no emulation possible +++\n";
0213 numWireGroups = -1;
0214 }
0215 } else {
0216 edm::LogError("CSCAnodeLCTProcessor|SetupError")
0217 << "+++ " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
0218 << theTrigChamber << ")"
0219 << " is not defined in current geometry! +++\n"
0220 << "+++ CSC geometry looks garbled; no emulation possible +++\n";
0221 numWireGroups = -1;
0222 }
0223 }
0224
0225 if (numWireGroups <= 0 or (unsigned) numWireGroups > qualityControl_->get_csc_max_wiregroup(theStation, theRing)) {
0226 edm::LogError("CSCAnodeLCTProcessor|SetupError")
0227 << "+++ " << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector << " trig id. "
0228 << theTrigChamber << "):"
0229 << " numWireGroups = " << numWireGroups << "; ALCT emulation skipped! +++";
0230 std::vector<CSCALCTDigi> emptyV;
0231 return emptyV;
0232 }
0233
0234
0235 bool hasDigis = getDigis(wiredc);
0236
0237 if (hasDigis) {
0238
0239 std::vector<int> wireGroupTimes[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIREGROUPS];
0240 readWireDigis(wireGroupTimes);
0241
0242
0243
0244
0245 const unsigned int min_layers =
0246 (nplanes_hit_accel_pattern == 0)
0247 ? nplanes_hit_pattern
0248 : ((nplanes_hit_pattern <= nplanes_hit_accel_pattern) ? nplanes_hit_pattern : nplanes_hit_accel_pattern);
0249
0250 unsigned int layersHit = 0;
0251 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0252 for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
0253 if (!wireGroupTimes[i_layer][i_wire].empty()) {
0254 layersHit++;
0255 break;
0256 }
0257 }
0258 }
0259 if (layersHit >= min_layers)
0260 run(wireGroupTimes);
0261
0262 encodeHighMultiplicityBits(wireGroupTimes);
0263 }
0264
0265
0266 return getALCTs();
0267 }
0268
0269 void CSCAnodeLCTProcessor::run(const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIREGROUPS]) {
0270 bool trigger = false;
0271
0272
0273 pulse_.initialize(numWireGroups);
0274
0275
0276 bool chamber_empty = pulseExtension(wire);
0277
0278
0279
0280 std::map<int, std::map<int, CSCALCTDigi::WireContainer>> hits_in_patterns;
0281 hits_in_patterns.clear();
0282
0283
0284
0285
0286 unsigned int stop_bx = fifo_tbins - drift_delay;
0287 if (!chamber_empty) {
0288 for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
0289
0290 const unsigned max_wire = qualityControl_->get_csc_max_wiregroup(theStation, theRing);
0291 if (unsigned(i_wire) >= max_wire)
0292 continue;
0293
0294 unsigned int start_bx = 0;
0295
0296 while (start_bx < stop_bx) {
0297 if (preTrigger(i_wire, start_bx)) {
0298 if (infoV > 2)
0299 showPatterns(i_wire);
0300 if (patternDetection(i_wire, hits_in_patterns)) {
0301 trigger = true;
0302 int ghost_cleared[2] = {0, 0};
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315 ghostCancellationLogicOneWire(i_wire, ghost_cleared);
0316
0317 int bx = (use_corrected_bx) ? first_bx_corrected[i_wire] : first_bx[i_wire];
0318 if (bx >= CSCConstants::MAX_ALCT_TBINS)
0319 edm::LogError("CSCAnodeLCTProcessor")
0320 << " bx of valid trigger : " << bx << " > max allowed value " << CSCConstants::MAX_ALCT_TBINS;
0321
0322
0323 if (quality[i_wire][0] > 0 and bx < CSCConstants::MAX_ALCT_TBINS) {
0324 int valid = (ghost_cleared[0] == 0) ? 1 : 0;
0325 CSCALCTDigi newALCT(valid, quality[i_wire][0], 1, 0, i_wire, bx);
0326
0327
0328 setWireContainer(newALCT, hits_in_patterns[i_wire][0]);
0329
0330 lct_list.emplace_back(newALCT);
0331 if (infoV > 1)
0332 LogTrace("CSCAnodeLCTProcessor") << "Add one ALCT to list " << lct_list.back();
0333 }
0334
0335
0336 if (quality[i_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] > 0 and bx < CSCConstants::MAX_ALCT_TBINS) {
0337 int valid = (ghost_cleared[CSCConstants::ALCT_COLLISIONA_PATTERN] == 0)
0338 ? 1
0339 : 0;
0340
0341 CSCALCTDigi newALCT(valid,
0342 quality[i_wire][CSCConstants::ALCT_COLLISIONA_PATTERN],
0343 0,
0344 quality[i_wire][CSCConstants::ALCT_COLLISIONB_PATTERN],
0345 i_wire,
0346 bx);
0347
0348
0349 setWireContainer(newALCT, hits_in_patterns[i_wire][CSCConstants::ALCT_COLLISIONA_PATTERN]);
0350
0351 lct_list.emplace_back(newALCT);
0352 if (infoV > 1)
0353 LogTrace("CSCAnodeLCTProcessor") << "Add one ALCT to list " << lct_list.back();
0354 }
0355
0356
0357
0358
0359
0360 start_bx = first_bx[i_wire] + drift_delay + pretrig_extra_deadtime;
0361 } else {
0362
0363 start_bx = first_bx[i_wire] + 1;
0364 }
0365 } else {
0366 break;
0367 }
0368 }
0369 }
0370 }
0371
0372
0373 if (trigger) {
0374
0375
0376
0377
0378
0379
0380
0381 lctSearch();
0382 }
0383 }
0384
0385 bool CSCAnodeLCTProcessor::getDigis(const CSCWireDigiCollection* wiredc) {
0386
0387 bool hasDigis = false;
0388
0389
0390 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0391 digiV[i_layer].clear();
0392
0393 CSCDetId detid(theEndcap, theStation, theRing, theChamber, i_layer + 1);
0394 getDigis(wiredc, detid);
0395
0396
0397 if (isME11_ && !disableME1a_) {
0398 CSCDetId detid_me1a(theEndcap, theStation, 4, theChamber, i_layer + 1);
0399 getDigis(wiredc, detid_me1a);
0400 }
0401
0402 if (!digiV[i_layer].empty()) {
0403 hasDigis = true;
0404 if (infoV > 1) {
0405 LogTrace("CSCAnodeLCTProcessor") << "found " << digiV[i_layer].size() << " wire digi(s) in layer " << i_layer
0406 << " of " << theCSCName_ << " (trig. sector " << theSector << " subsector "
0407 << theSubsector << " id " << theTrigChamber << ")";
0408 for (const auto& wd : digiV[i_layer]) {
0409 LogTrace("CSCAnodeLCTProcessor") << " " << wd;
0410 }
0411 }
0412 }
0413 }
0414
0415 return hasDigis;
0416 }
0417
0418 void CSCAnodeLCTProcessor::getDigis(const CSCWireDigiCollection* wiredc, const CSCDetId& id) {
0419 CSCWireDigiCollection::Range rwired = wiredc->get(id);
0420 for (CSCWireDigiCollection::const_iterator digiIt = rwired.first; digiIt != rwired.second; ++digiIt) {
0421 digiV[id.layer() - 1].push_back(*digiIt);
0422 }
0423 }
0424
0425 void CSCAnodeLCTProcessor::readWireDigis(
0426 std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIREGROUPS]) {
0427
0428 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0429
0430
0431 for (const auto& wd : digiV[i_layer]) {
0432 int i_wire = wd.getWireGroup() - 1;
0433 std::vector<int> bx_times = wd.getTimeBinsOn();
0434
0435
0436 if (i_wire < 0 || i_wire >= numWireGroups) {
0437 if (infoV >= 0)
0438 edm::LogWarning("CSCAnodeLCTProcessor|WrongInput")
0439 << "+++ Found wire digi with wrong wire number = " << i_wire << " (max wires = " << numWireGroups
0440 << "); skipping it... +++\n";
0441 continue;
0442 }
0443
0444
0445
0446
0447
0448
0449
0450 int last_time = -999;
0451 if (bx_times.size() == fifo_tbins) {
0452 wire[i_layer][i_wire].push_back(0);
0453 wire[i_layer][i_wire].push_back(6);
0454 } else {
0455 for (unsigned int i = 0; i < bx_times.size(); i++) {
0456
0457 if (i > 0 && bx_times[i] == (bx_times[i - 1] + 1))
0458 continue;
0459 if (bx_times[i] < static_cast<int>(fifo_tbins)) {
0460 if (infoV > 2)
0461 LogTrace("CSCAnodeLCTProcessor")
0462 << "Digi on layer " << i_layer << " wire " << i_wire << " at time " << bx_times[i];
0463
0464
0465
0466
0467 if (last_time < 0 || ((bx_times[i] - last_time) >= 6)) {
0468 wire[i_layer][i_wire].push_back(bx_times[i]);
0469 last_time = bx_times[i];
0470 }
0471 } else {
0472 if (infoV > 1)
0473 LogTrace("CSCAnodeLCTProcessor") << "+++ Skipping wire digi: wire = " << i_wire << " layer = " << i_layer
0474 << ", bx = " << bx_times[i] << " +++";
0475 }
0476 }
0477 }
0478 }
0479 }
0480 }
0481
0482 bool CSCAnodeLCTProcessor::pulseExtension(
0483 const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIREGROUPS]) {
0484 bool chamber_empty = true;
0485 int i_wire, i_layer, digi_num;
0486
0487 const unsigned bits_in_pulse = pulse_.bitsInPulse();
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497 pulse_.clear();
0498
0499 for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
0500 first_bx[i_wire] = -999;
0501 first_bx_corrected[i_wire] = -999;
0502 for (int j = 0; j < 3; j++)
0503 quality[i_wire][j] = -999;
0504 }
0505
0506 for (i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0507 digi_num = 0;
0508 for (i_wire = 0; i_wire < numWireGroups; i_wire++) {
0509 if (!wire[i_layer][i_wire].empty()) {
0510 std::vector<int> bx_times = wire[i_layer][i_wire];
0511 for (unsigned int i = 0; i < bx_times.size(); i++) {
0512
0513 if (bx_times[i] < 0 || bx_times[i] + hit_persist >= bits_in_pulse) {
0514 if (infoV > 0)
0515 edm::LogWarning("CSCAnodeLCTProcessor|OutOfTimeDigi")
0516 << "+++ BX time of wire digi (wire = " << i_wire << " layer = " << i_layer << ") bx = " << bx_times[i]
0517 << " is not within the range (0-" << bits_in_pulse
0518 << "] allowed for pulse extension. Skip this digi! +++\n";
0519 continue;
0520 }
0521
0522
0523 if (chamber_empty)
0524 chamber_empty = false;
0525
0526
0527 pulse_.extend(i_layer, i_wire, bx_times[i], hit_persist);
0528
0529
0530 if (infoV > 1) {
0531 LogTrace("CSCAnodeLCTProcessor") << "Wire digi: layer " << i_layer << " digi #" << ++digi_num
0532 << " wire group " << i_wire << " time " << bx_times[i];
0533 if (infoV > 2) {
0534 std::ostringstream strstrm;
0535 for (int i = 1; i <= 32; i++) {
0536 strstrm << pulse_.oneShotAtBX(i_layer, i_wire, 32 - i);
0537 }
0538 LogTrace("CSCAnodeLCTProcessor") << " Pulse: " << strstrm.str();
0539 }
0540 }
0541 }
0542 }
0543 }
0544 }
0545
0546 if (infoV > 1 && !chamber_empty) {
0547 dumpDigis(wire);
0548 }
0549
0550 return chamber_empty;
0551 }
0552
0553 bool CSCAnodeLCTProcessor::preTrigger(const int key_wire, const int start_bx) {
0554 int nPreTriggers = 0;
0555
0556 unsigned int layers_hit;
0557 bool hit_layer[CSCConstants::NUM_LAYERS];
0558 int this_wire;
0559
0560
0561 const unsigned int nplanes_hit_pretrig_acc =
0562 (nplanes_hit_accel_pretrig != 0) ? nplanes_hit_accel_pretrig : nplanes_hit_pretrig;
0563 const unsigned int pretrig_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
0564 nplanes_hit_pretrig_acc, nplanes_hit_pretrig, nplanes_hit_pretrig};
0565
0566
0567
0568
0569
0570 unsigned int stop_bx = fifo_tbins - drift_delay;
0571 for (unsigned int bx_time = start_bx; bx_time < stop_bx; bx_time++) {
0572 for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
0573
0574 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
0575 hit_layer[i_layer] = false;
0576 layers_hit = 0;
0577
0578
0579 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0580 for (int i_wire = 0; i_wire < CSCConstants::ALCT_PATTERN_WIDTH; i_wire++) {
0581
0582 if (alct_pattern_[i_pattern][i_layer][i_wire]) {
0583 this_wire = CSCPatternBank::alct_keywire_offset_[MESelection][i_wire] + key_wire;
0584 if ((this_wire >= 0) && (this_wire < numWireGroups)) {
0585
0586 if (pulse_.isOneShotHighAtBX(i_layer, this_wire, bx_time)) {
0587
0588 if (!hit_layer[i_layer]) {
0589 hit_layer[i_layer] = true;
0590 layers_hit++;
0591 }
0592
0593
0594
0595 if (layers_hit >= pretrig_thresh[i_pattern]) {
0596 first_bx[key_wire] = bx_time;
0597 if (infoV > 1) {
0598 LogTrace("CSCAnodeLCTProcessor") << "Pretrigger was satisfied for wire: " << key_wire
0599 << " pattern: " << i_pattern << " bx_time: " << bx_time;
0600 }
0601
0602 nPreTriggers++;
0603
0604
0605 thePreTriggerDigis.emplace_back(
0606 CSCALCTPreTriggerDigi(1, layers_hit - 3, 0, 0, this_wire, bx_time, nPreTriggers));
0607 return true;
0608 }
0609 }
0610 }
0611 }
0612 }
0613 }
0614 }
0615 }
0616
0617 return false;
0618 }
0619
0620 bool CSCAnodeLCTProcessor::patternDetection(
0621 const int key_wire, std::map<int, std::map<int, CSCALCTDigi::WireContainer>>& hits_in_patterns) {
0622 bool trigger = false;
0623 bool hit_layer[CSCConstants::NUM_LAYERS];
0624 unsigned int temp_quality;
0625 int this_wire, delta_wire;
0626
0627
0628 const unsigned int nplanes_hit_pattern_acc =
0629 (nplanes_hit_accel_pattern != 0) ? nplanes_hit_accel_pattern : nplanes_hit_pattern;
0630 const unsigned int pattern_thresh[CSCConstants::NUM_ALCT_PATTERNS] = {
0631 nplanes_hit_pattern_acc, nplanes_hit_pattern, nplanes_hit_pattern};
0632 const std::string ptn_label[] = {"Accelerator", "CollisionA", "CollisionB"};
0633
0634 for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
0635 temp_quality = 0;
0636
0637
0638 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++)
0639 hit_layer[i_layer] = false;
0640
0641
0642 CSCALCTDigi::WireContainer hits_single_pattern;
0643 hits_single_pattern.clear();
0644 hits_single_pattern.resize(CSCConstants::NUM_LAYERS);
0645 for (auto& p : hits_single_pattern) {
0646 p.resize(CSCConstants::ALCT_PATTERN_WIDTH, CSCConstants::INVALID_WIREGROUP);
0647 }
0648
0649 double num_pattern_hits = 0., times_sum = 0.;
0650 std::multiset<int> mset_for_median;
0651 mset_for_median.clear();
0652
0653 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
0654 for (int i_wire = 0; i_wire < CSCConstants::ALCT_PATTERN_WIDTH; i_wire++) {
0655
0656 if (alct_pattern_[i_pattern][i_layer][i_wire]) {
0657 delta_wire = CSCPatternBank::alct_keywire_offset_[MESelection][i_wire];
0658 this_wire = delta_wire + key_wire;
0659 if ((this_wire >= 0) && (this_wire < numWireGroups)) {
0660
0661
0662 if (pulse_.isOneShotHighAtBX(i_layer, this_wire, first_bx[key_wire] + drift_delay)) {
0663
0664 hits_single_pattern[i_layer][i_wire] = this_wire;
0665
0666
0667
0668 if (!hit_layer[i_layer]) {
0669 temp_quality++;
0670
0671 hit_layer[i_layer] = true;
0672 if (infoV > 1)
0673 LogTrace("CSCAnodeLCTProcessor")
0674 << "bx_time: " << first_bx[key_wire] << " pattern: " << i_pattern << " keywire: " << key_wire
0675 << " layer: " << i_layer << " quality: " << temp_quality;
0676 }
0677
0678
0679 if (abs(delta_wire) < 2) {
0680
0681
0682 int first_bx_layer = first_bx[key_wire] + drift_delay;
0683 for (unsigned int dbx = 0; dbx < hit_persist; dbx++) {
0684 if (pulse_.isOneShotHighAtBX(i_layer, this_wire, first_bx_layer - 1)) {
0685 first_bx_layer--;
0686 } else
0687 break;
0688 }
0689 times_sum += (double)first_bx_layer;
0690 num_pattern_hits += 1.;
0691 mset_for_median.insert(first_bx_layer);
0692 if (infoV > 2)
0693 LogTrace("CSCAnodeLCTProcessor") << " 1st bx in layer: " << first_bx_layer << " sum bx: " << times_sum
0694 << " #pat. hits: " << num_pattern_hits;
0695 }
0696 }
0697 }
0698 }
0699 }
0700 }
0701
0702
0703 const int sz = mset_for_median.size();
0704 if (sz > 0) {
0705 std::multiset<int>::iterator im = mset_for_median.begin();
0706 if (sz > 1)
0707 std::advance(im, sz / 2 - 1);
0708 if (sz == 1)
0709 first_bx_corrected[key_wire] = *im;
0710 else if ((sz % 2) == 1)
0711 first_bx_corrected[key_wire] = *(++im);
0712 else
0713 first_bx_corrected[key_wire] = ((*im) + (*(++im))) / 2;
0714
0715 #if defined(EDM_ML_DEBUG)
0716 if (infoV > 1) {
0717 auto lt = LogTrace("CSCAnodeLCTProcessor")
0718 << "bx=" << first_bx[key_wire] << " bx_cor=" << first_bx_corrected[key_wire] << " bxset=";
0719 for (im = mset_for_median.begin(); im != mset_for_median.end(); im++) {
0720 lt << " " << *im;
0721 }
0722 }
0723 #endif
0724 }
0725
0726
0727 if (temp_quality >= pattern_thresh[i_pattern]) {
0728 trigger = true;
0729 hits_in_patterns[key_wire][i_pattern] = hits_single_pattern;
0730
0731
0732
0733 temp_quality = getTempALCTQuality(temp_quality);
0734
0735 if (i_pattern == CSCConstants::ALCT_ACCELERATOR_PATTERN) {
0736
0737 quality[key_wire][CSCConstants::ALCT_ACCELERATOR_PATTERN] = temp_quality;
0738 } else {
0739
0740 if (static_cast<int>(temp_quality) > quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN]) {
0741 quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] = temp_quality;
0742 quality[key_wire][CSCConstants::ALCT_COLLISIONB_PATTERN] = i_pattern - 1;
0743 }
0744 }
0745 if (infoV > 1) {
0746 LogTrace("CSCAnodeLCTProcessor") << "Pattern found; keywire: " << key_wire << " type: " << ptn_label[i_pattern]
0747 << " quality: " << temp_quality << "\n";
0748 }
0749 }
0750 }
0751 if (infoV > 1 && quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] > 0) {
0752 if (quality[key_wire][CSCConstants::ALCT_COLLISIONB_PATTERN] == 0)
0753 LogTrace("CSCAnodeLCTProcessor") << "Collision Pattern A is chosen"
0754 << "\n";
0755 else if (quality[key_wire][CSCConstants::ALCT_COLLISIONB_PATTERN] == 1)
0756 LogTrace("CSCAnodeLCTProcessor") << "Collision Pattern B is chosen"
0757 << "\n";
0758 }
0759
0760 trigMode(key_wire);
0761
0762 return trigger;
0763 }
0764
0765 void CSCAnodeLCTProcessor::ghostCancellationLogicOneWire(const int key_wire, int* ghost_cleared) {
0766 for (int i_pattern = 0; i_pattern < 2; i_pattern++) {
0767 ghost_cleared[i_pattern] = 0;
0768 if (key_wire == 0)
0769 continue;
0770
0771
0772 int qual_this = quality[key_wire][i_pattern];
0773 if (qual_this > 0) {
0774
0775
0776
0777 for (auto& p : lct_list) {
0778
0779
0780
0781 if (not(p.getKeyWG() == key_wire - 1 and 1 - p.getAccelerator() == i_pattern))
0782 continue;
0783
0784 bool ghost_cleared_prev = false;
0785 int qual_prev = p.getQuality();
0786 int first_bx_prev = p.getBX();
0787 if (infoV > 1)
0788 LogTrace("CSCAnodeLCTProcessor")
0789 << "ghost concellation logic "
0790 << ((i_pattern == CSCConstants::ALCT_ACCELERATOR_PATTERN) ? "Accelerator" : "Collision") << " key_wire "
0791 << key_wire << " quality " << qual_this << " bx " << first_bx[key_wire] << " previous key_wire "
0792 << key_wire - 1 << " quality " << qual_prev << " bx " << first_bx[key_wire - 1];
0793
0794
0795 int dt = first_bx[key_wire] - first_bx_prev;
0796
0797
0798
0799
0800
0801
0802 if (dt == 0) {
0803 if (qual_prev >= qual_this)
0804 ghost_cleared[i_pattern] = 1;
0805 else if (qual_prev < qual_this)
0806 ghost_cleared_prev = true;
0807 } else if (dt > 0 && dt <= ghost_cancellation_bx_depth) {
0808 if ((!ghost_cancellation_side_quality) || (qual_prev > qual_this))
0809 ghost_cleared[i_pattern] = 1;
0810 } else if (dt < 0 && dt * (-1) <= ghost_cancellation_bx_depth) {
0811 if ((!ghost_cancellation_side_quality) || (qual_prev < qual_this))
0812 ghost_cleared_prev = true;
0813 }
0814
0815 if (ghost_cleared[i_pattern] == 1) {
0816 if (infoV > 1)
0817 LogTrace("CSCAnodeLCTProcessor")
0818 << ((i_pattern == CSCConstants::ALCT_ACCELERATOR_PATTERN) ? "Accelerator" : "Collision")
0819 << " pattern ghost cancelled on key_wire " << key_wire << " q=" << qual_this << " by wire "
0820 << key_wire - 1 << " q=" << qual_prev;
0821
0822 }
0823
0824 if (ghost_cleared_prev) {
0825 if (infoV > 1)
0826 LogTrace("CSCAnodeLCTProcessor")
0827 << ((i_pattern == CSCConstants::ALCT_ACCELERATOR_PATTERN) ? "Accelerator" : "Collision")
0828 << " pattern ghost cancelled on key_wire " << key_wire - 1 << " q=" << qual_prev << " by wire "
0829 << key_wire << " q=" << qual_this;
0830 p.setValid(0);
0831 }
0832 }
0833
0834 }
0835 }
0836 }
0837
0838 void CSCAnodeLCTProcessor::lctSearch() {
0839
0840
0841 const std::vector<CSCALCTDigi>& fourBest = bestTrackSelector(lct_list);
0842
0843 if (infoV > 0) {
0844 int n_alct_all = 0, n_alct = 0;
0845 for (const auto& p : lct_list) {
0846 if (p.isValid() && p.getBX() == CSCConstants::LCT_CENTRAL_BX)
0847 n_alct_all++;
0848 }
0849 for (const auto& p : fourBest) {
0850 if (p.isValid() && p.getBX() == CSCConstants::LCT_CENTRAL_BX)
0851 n_alct++;
0852 }
0853
0854 LogTrace("CSCAnodeLCTProcessor") << "alct_count E:" << theEndcap << "S:" << theStation << "R:" << theRing
0855 << "C:" << theChamber << " all " << n_alct_all << " found " << n_alct;
0856 }
0857
0858
0859
0860 for (const auto& p : fourBest) {
0861 const int bx = p.getBX();
0862 if (bx >= CSCConstants::MAX_ALCT_TBINS) {
0863 if (infoV > 0)
0864 edm::LogWarning("CSCAnodeLCTProcessor|OutOfTimeALCT")
0865 << "+++ Bx of ALCT candidate, " << bx << ", exceeds max allowed, " << CSCConstants::MAX_ALCT_TBINS - 1
0866 << "; skipping it... +++\n";
0867 continue;
0868 }
0869
0870 if (isBetterALCT(p, bestALCT[bx])) {
0871 if (isBetterALCT(bestALCT[bx], secondALCT[bx])) {
0872 secondALCT[bx] = bestALCT[bx];
0873 }
0874 bestALCT[bx] = p;
0875 } else if (isBetterALCT(p, secondALCT[bx])) {
0876 secondALCT[bx] = p;
0877 }
0878 }
0879
0880 for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
0881 if (bestALCT[bx].isValid()) {
0882 bestALCT[bx].setTrknmb(1);
0883
0884
0885 qualityControl_->checkValidReadout(bestALCT[bx]);
0886
0887 if (infoV > 0) {
0888 LogDebug("CSCAnodeLCTProcessor") << bestALCT[bx] << " fullBX = " << bestALCT[bx].getFullBX() << " found in "
0889 << theCSCName_ << " (sector " << theSector << " subsector " << theSubsector
0890 << " trig id. " << theTrigChamber << ")"
0891 << "\n";
0892 }
0893 if (secondALCT[bx].isValid()) {
0894 secondALCT[bx].setTrknmb(2);
0895
0896
0897 qualityControl_->checkValidReadout(secondALCT[bx]);
0898
0899 if (infoV > 0) {
0900 LogDebug("CSCAnodeLCTProcessor")
0901 << secondALCT[bx] << " fullBX = " << secondALCT[bx].getFullBX() << " found in " << theCSCName_
0902 << " (sector " << theSector << " subsector " << theSubsector << " trig id. " << theTrigChamber << ")"
0903 << "\n";
0904 }
0905 }
0906 }
0907 }
0908 }
0909
0910 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::bestTrackSelector(const std::vector<CSCALCTDigi>& all_alcts) {
0911 CSCALCTDigi bestALCTs[CSCConstants::MAX_ALCT_TBINS][CSCConstants::MAX_ALCTS_PER_PROCESSOR];
0912 CSCALCTDigi secondALCTs[CSCConstants::MAX_ALCT_TBINS][CSCConstants::MAX_ALCTS_PER_PROCESSOR];
0913
0914 if (infoV > 1) {
0915 LogTrace("CSCAnodeLCTProcessor") << all_alcts.size() << " ALCTs at the input of best-track selector: ";
0916 for (const auto& p : all_alcts) {
0917 if (!p.isValid())
0918 continue;
0919 LogTrace("CSCAnodeLCTProcessor") << p;
0920 }
0921 }
0922
0923 CSCALCTDigi tA[CSCConstants::MAX_ALCT_TBINS][CSCConstants::MAX_ALCTS_PER_PROCESSOR];
0924 CSCALCTDigi tB[CSCConstants::MAX_ALCT_TBINS][CSCConstants::MAX_ALCTS_PER_PROCESSOR];
0925 for (const auto& p : all_alcts) {
0926 if (!p.isValid())
0927 continue;
0928
0929
0930
0931
0932
0933
0934
0935
0936 int bx = p.getBX();
0937 int accel = p.getAccelerator();
0938 int qual = p.getQuality();
0939 int wire = p.getKeyWG();
0940 bool vA = tA[bx][accel].isValid();
0941 bool vB = tB[bx][accel].isValid();
0942 int qA = tA[bx][accel].getQuality();
0943 int qB = tB[bx][accel].getQuality();
0944 int wA = tA[bx][accel].getKeyWG();
0945 int wB = tB[bx][accel].getKeyWG();
0946 if (!vA || qual > qA || (qual == qA && wire > wA)) {
0947 tA[bx][accel] = p;
0948 }
0949 if (!vB || qual > qB || (qual == qB && wire < wB)) {
0950 tB[bx][accel] = p;
0951 }
0952 }
0953
0954 for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
0955 for (int accel = 0; accel <= 1; accel++) {
0956
0957 if (tA[bx][accel].isValid()) {
0958 if (infoV > 2) {
0959 LogTrace("CSCAnodeLCTProcessor") << "tA: " << tA[bx][accel];
0960 LogTrace("CSCAnodeLCTProcessor") << "tB: " << tB[bx][accel];
0961 }
0962 bestALCTs[bx][accel] = tA[bx][accel];
0963
0964
0965 if (tA[bx][accel] != tB[bx][accel] && tA[bx][accel].getQuality() == tB[bx][accel].getQuality()) {
0966 secondALCTs[bx][accel] = tB[bx][accel];
0967 } else {
0968
0969
0970
0971
0972 for (const auto& p : all_alcts) {
0973 if (p.isValid() && p.getAccelerator() == accel && p.getBX() == bx &&
0974 p.getQuality() < bestALCTs[bx][accel].getQuality() &&
0975 p.getQuality() >= secondALCTs[bx][accel].getQuality() &&
0976 p.getKeyWG() >= secondALCTs[bx][accel].getKeyWG()) {
0977 secondALCTs[bx][accel] = p;
0978 }
0979 }
0980 }
0981 }
0982 }
0983 }
0984
0985
0986 std::vector<CSCALCTDigi> fourBest;
0987 for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
0988 for (int i = 0; i < CSCConstants::MAX_ALCTS_PER_PROCESSOR; i++) {
0989 if (bestALCTs[bx][i].isValid()) {
0990 fourBest.push_back(bestALCTs[bx][i]);
0991 }
0992 }
0993 for (int i = 0; i < CSCConstants::MAX_ALCTS_PER_PROCESSOR; i++) {
0994 if (secondALCTs[bx][i].isValid()) {
0995 fourBest.push_back(secondALCTs[bx][i]);
0996 }
0997 }
0998 }
0999
1000 if (infoV > 1) {
1001 LogTrace("CSCAnodeLCTProcessor") << fourBest.size() << " ALCTs selected: ";
1002 for (const auto& p : fourBest) {
1003 LogTrace("CSCAnodeLCTProcessor") << p;
1004 }
1005 }
1006
1007 return fourBest;
1008 }
1009
1010 bool CSCAnodeLCTProcessor::isBetterALCT(const CSCALCTDigi& lhsALCT, const CSCALCTDigi& rhsALCT) const {
1011 bool returnValue = false;
1012
1013 if (lhsALCT.isValid() && !rhsALCT.isValid()) {
1014 return true;
1015 }
1016
1017
1018
1019 if (lhsALCT.getBX() < rhsALCT.getBX()) {
1020 returnValue = true;
1021 }
1022 if (lhsALCT.getBX() != rhsALCT.getBX()) {
1023 return returnValue;
1024 }
1025
1026
1027 const int qual1 = lhsALCT.getQuality();
1028 const int qual2 = rhsALCT.getQuality();
1029 if (qual1 > qual2) {
1030 returnValue = true;
1031 }
1032
1033
1034
1035
1036
1037
1038
1039
1040 else if (qual1 == qual2 && lhsALCT.getAccelerator() != rhsALCT.getAccelerator()) {
1041 if ((accel_mode == 0 || accel_mode == 1) && rhsALCT.getAccelerator() == 0)
1042 returnValue = true;
1043 if ((accel_mode == 2 || accel_mode == 3) && lhsALCT.getAccelerator() == 0)
1044 returnValue = true;
1045 }
1046
1047 return returnValue;
1048 }
1049
1050 void CSCAnodeLCTProcessor::trigMode(const int key_wire) {
1051 switch (trig_mode) {
1052 default:
1053 case 0:
1054
1055 break;
1056 case 1:
1057
1058 if (quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] > 0) {
1059 quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] = 0;
1060 if (infoV > 1)
1061 LogTrace("CSCAnodeLCTProcessor") << "trigMode(): collision track " << key_wire << " disabled"
1062 << "\n";
1063 }
1064 break;
1065 case 2:
1066
1067 if (quality[key_wire][CSCConstants::ALCT_ACCELERATOR_PATTERN] > 0) {
1068 quality[key_wire][CSCConstants::ALCT_ACCELERATOR_PATTERN] = 0;
1069 if (infoV > 1)
1070 LogTrace("CSCAnodeLCTProcessor") << "trigMode(): accelerator track " << key_wire << " disabled"
1071 << "\n";
1072 }
1073 break;
1074 case 3:
1075
1076
1077 if (quality[key_wire][0] > 0 && quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] > 0) {
1078 quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] = 0;
1079 if (infoV > 1)
1080 LogTrace("CSCAnodeLCTProcessor") << "trigMode(): collision track " << key_wire << " disabled"
1081 << "\n";
1082 }
1083 break;
1084 }
1085 }
1086
1087 void CSCAnodeLCTProcessor::accelMode(const int key_wire) {
1088 int promotionBit = 1 << 2;
1089
1090 switch (accel_mode) {
1091 default:
1092 case 0:
1093
1094 if (quality[key_wire][0] > 0) {
1095 quality[key_wire][0] = 0;
1096 if (infoV > 1)
1097 LogTrace("CSCAnodeLCTProcessor") << "alctMode(): accelerator track " << key_wire << " ignored"
1098 << "\n";
1099 }
1100 break;
1101 case 1:
1102
1103 if (quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] > 0) {
1104 quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] += promotionBit;
1105 if (infoV > 1)
1106 LogTrace("CSCAnodeLCTProcessor") << "alctMode(): collision track " << key_wire << " promoted"
1107 << "\n";
1108 }
1109 break;
1110 case 2:
1111
1112 if (quality[key_wire][CSCConstants::ALCT_ACCELERATOR_PATTERN] > 0) {
1113 quality[key_wire][CSCConstants::ALCT_ACCELERATOR_PATTERN] += promotionBit;
1114 if (infoV > 1)
1115 LogTrace("CSCAnodeLCTProcessor") << "alctMode(): accelerator track " << key_wire << " promoted"
1116 << "\n";
1117 }
1118 break;
1119 case 3:
1120
1121 if (quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] > 0) {
1122 quality[key_wire][CSCConstants::ALCT_COLLISIONA_PATTERN] = 0;
1123 if (infoV > 1)
1124 LogTrace("CSCAnodeLCTProcessor") << "alctMode(): collision track " << key_wire << " ignored"
1125 << "\n";
1126 }
1127 break;
1128 }
1129 }
1130
1131
1132 void CSCAnodeLCTProcessor::dumpConfigParams() const {
1133 std::ostringstream strm;
1134 strm << "\n";
1135 strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1136 strm << "+ ALCT configuration parameters: +\n";
1137 strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1138 strm << " fifo_tbins [total number of time bins in DAQ readout] = " << fifo_tbins << "\n";
1139 strm << " fifo_pretrig [start time of anode raw hits in DAQ readout] = " << fifo_pretrig << "\n";
1140 strm << " drift_delay [drift delay after pre-trigger, in 25 ns bins] = " << drift_delay << "\n";
1141 strm << " nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = " << nplanes_hit_pretrig << "\n";
1142 strm << " nplanes_hit_pattern [min. number of layers hit for trigger] = " << nplanes_hit_pattern << "\n";
1143 strm << " nplanes_hit_accel_pretrig [min. number of layers hit for accel."
1144 << " pre-trig.] = " << nplanes_hit_accel_pretrig << "\n";
1145 strm << " nplanes_hit_accel_pattern [min. number of layers hit for accel."
1146 << " trigger] = " << nplanes_hit_accel_pattern << "\n";
1147 strm << " trig_mode [enabling/disabling collision/accelerator tracks] = " << trig_mode << "\n";
1148 strm << " accel_mode [preference to collision/accelerator tracks] = " << accel_mode << "\n";
1149 strm << " l1a_window_width [L1Accept window width, in 25 ns bins] = " << l1a_window_width << "\n";
1150 strm << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1151 LogDebug("CSCAnodeLCTProcessor") << strm.str();
1152 }
1153
1154
1155 void CSCAnodeLCTProcessor::dumpDigis(
1156 const std::vector<int> wire[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIREGROUPS]) const {
1157 LogDebug("CSCAnodeLCTProcessor") << theCSCName_ << " nWiregroups " << numWireGroups;
1158
1159 std::ostringstream strstrm;
1160 for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1161 if (i_wire % 10 == 0) {
1162 if (i_wire < 100)
1163 strstrm << i_wire / 10;
1164 else
1165 strstrm << (i_wire - 100) / 10;
1166 } else
1167 strstrm << " ";
1168 }
1169 strstrm << "\n";
1170 for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1171 strstrm << i_wire % 10;
1172 }
1173 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1174 strstrm << "\n";
1175 for (int i_wire = 0; i_wire < numWireGroups; i_wire++) {
1176 if (!wire[i_layer][i_wire].empty()) {
1177 std::vector<int> bx_times = wire[i_layer][i_wire];
1178 strstrm << std::hex << bx_times[0] << std::dec;
1179 } else {
1180 strstrm << ".";
1181 }
1182 }
1183 }
1184 LogTrace("CSCAnodeLCTProcessor") << strstrm.str();
1185 }
1186
1187
1188
1189 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::readoutALCTs() const {
1190 std::vector<CSCALCTDigi> tmpV;
1191
1192
1193
1194
1195 const int lct_bins = l1a_window_width;
1196 static std::atomic<int> late_tbins{early_tbins + lct_bins};
1197
1198 static std::atomic<int> ifois{0};
1199 if (ifois == 0) {
1200 if (infoV >= 0 && early_tbins < 0) {
1201 edm::LogWarning("CSCAnodeLCTProcessor|SuspiciousParameters")
1202 << "+++ fifo_pretrig = " << fifo_pretrig << "; in-time ALCTs are not getting read-out!!! +++"
1203 << "\n";
1204 }
1205
1206 if (late_tbins > CSCConstants::MAX_ALCT_TBINS - 1) {
1207 if (infoV >= 0)
1208 edm::LogWarning("CSCAnodeLCTProcessor|SuspiciousParameters")
1209 << "+++ Allowed range of time bins, [0-" << late_tbins << "] exceeds max allowed, "
1210 << CSCConstants::MAX_ALCT_TBINS - 1 << " +++\n"
1211 << "+++ Set late_tbins to max allowed +++\n";
1212 late_tbins = CSCConstants::MAX_ALCT_TBINS - 1;
1213 }
1214 ifois = 1;
1215 }
1216
1217
1218
1219 const std::vector<CSCALCTDigi>& all_alcts = getALCTs();
1220 for (const auto& p : all_alcts) {
1221 if (!p.isValid())
1222 continue;
1223
1224 int bx = p.getBX();
1225
1226 if (bx <= early_tbins) {
1227 if (infoV > 1)
1228 LogDebug("CSCAnodeLCTProcessor") << " Do not report ALCT on keywire " << p.getKeyWG() << ": found at bx " << bx
1229 << ", whereas the earliest allowed bx is " << early_tbins + 1;
1230 continue;
1231 }
1232
1233
1234 if (bx > late_tbins) {
1235 if (infoV > 1)
1236 LogDebug("CSCAnodeLCTProcessor") << " Do not report ALCT on keywire " << p.getKeyWG() << ": found at bx " << bx
1237 << ", whereas the latest allowed bx is " << late_tbins;
1238 continue;
1239 }
1240
1241 tmpV.push_back(p);
1242 }
1243
1244
1245
1246
1247
1248
1249
1250 for (auto& p : tmpV) {
1251 p.setBX(p.getBX() - (CSCConstants::LCT_CENTRAL_BX - l1a_window_width / 2));
1252 }
1253
1254
1255 qualityControl_->checkMultiplicityBX(tmpV);
1256 for (const auto& alct : tmpV) {
1257 qualityControl_->checkValid(alct);
1258 }
1259
1260 return tmpV;
1261 }
1262
1263
1264 std::vector<CSCALCTDigi> CSCAnodeLCTProcessor::getALCTs() const {
1265 std::vector<CSCALCTDigi> tmpV;
1266 for (int bx = 0; bx < CSCConstants::MAX_ALCT_TBINS; bx++) {
1267 if (bestALCT[bx].isValid())
1268 tmpV.push_back(bestALCT[bx]);
1269 if (secondALCT[bx].isValid())
1270 tmpV.push_back(secondALCT[bx]);
1271 }
1272 return tmpV;
1273 }
1274
1275 CSCALCTDigi CSCAnodeLCTProcessor::getBestALCT(int bx) const { return bestALCT[bx]; }
1276
1277 CSCALCTDigi CSCAnodeLCTProcessor::getSecondALCT(int bx) const { return secondALCT[bx]; }
1278
1279
1280 CSCShowerDigi CSCAnodeLCTProcessor::readoutShower() const { return shower_; }
1281
1282
1283
1284
1285 void CSCAnodeLCTProcessor::showPatterns(const int key_wire) {
1286
1287 for (int i_pattern = 0; i_pattern < CSCConstants::NUM_ALCT_PATTERNS; i_pattern++) {
1288 std::ostringstream strstrm_header;
1289 LogTrace("CSCAnodeLCTProcessor") << "\n"
1290 << "Pattern: " << i_pattern << " Key wire: " << key_wire;
1291 for (int i = 1; i <= 32; i++) {
1292 strstrm_header << ((32 - i) % 10);
1293 }
1294 LogTrace("CSCAnodeLCTProcessor") << strstrm_header.str();
1295 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1296 for (int i_wire = 0; i_wire < CSCConstants::ALCT_PATTERN_WIDTH; i_wire++) {
1297
1298 if (alct_pattern_[i_pattern][i_layer][i_wire]) {
1299 std::ostringstream strstrm_pulse;
1300 int this_wire = CSCPatternBank::alct_keywire_offset_[MESelection][i_wire] + key_wire;
1301 if (this_wire >= 0 && this_wire < numWireGroups) {
1302 for (int i = 1; i <= 32; i++) {
1303 strstrm_pulse << pulse_.oneShotAtBX(i_layer, this_wire, 32 - i);
1304 }
1305 LogTrace("CSCAnodeLCTProcessor") << strstrm_pulse.str() << " on layer " << i_layer << " wire " << this_wire;
1306 }
1307 }
1308 }
1309 }
1310 LogTrace("CSCAnodeLCTProcessor") << "-------------------------------------------";
1311 }
1312 }
1313
1314 int CSCAnodeLCTProcessor::getTempALCTQuality(int temp_quality) const {
1315 int Q;
1316 if (temp_quality > 3)
1317 Q = temp_quality - 3;
1318 else
1319 Q = 0;
1320
1321 return Q;
1322 }
1323
1324 void CSCAnodeLCTProcessor::cleanWireContainer(CSCALCTDigi::WireContainer& wireHits) const {
1325 for (auto& p : wireHits) {
1326 p.erase(std::remove_if(p.begin(), p.end(), [](unsigned i) -> bool { return i == CSCConstants::INVALID_WIREGROUP; }),
1327 p.end());
1328 }
1329 }
1330
1331 void CSCAnodeLCTProcessor::setWireContainer(CSCALCTDigi& alct, CSCALCTDigi::WireContainer& wireHits) const {
1332
1333 cleanWireContainer(wireHits);
1334
1335
1336 alct.setHits(wireHits);
1337 }
1338
1339 void CSCAnodeLCTProcessor::encodeHighMultiplicityBits(
1340 const std::vector<int> wires[CSCConstants::NUM_LAYERS][CSCConstants::MAX_NUM_WIREGROUPS]) {
1341 inTimeHMT_ = 0;
1342
1343 auto layerTime = [=](unsigned time) { return time == CSCConstants::LCT_CENTRAL_BX; };
1344
1345
1346 unsigned nLayersWithHits = 0;
1347 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1348 bool atLeastOneWGHit = false;
1349 for (int i_wire = 0; i_wire < CSCConstants::MAX_NUM_WIREGROUPS; i_wire++) {
1350
1351 if (!wires[i_layer][i_wire].empty()) {
1352 auto times = wires[i_layer][i_wire];
1353 int nLayerTime = std::count_if(times.begin(), times.end(), layerTime);
1354
1355 if (nLayerTime > 0) {
1356 atLeastOneWGHit = true;
1357 break;
1358 }
1359 }
1360 }
1361
1362 if (atLeastOneWGHit) {
1363 nLayersWithHits++;
1364 }
1365 }
1366
1367
1368
1369 if (nLayersWithHits < minLayersCentralTBin_)
1370 return;
1371
1372
1373 auto inTime = [=](unsigned time) { return time >= showerMinInTBin_ and time <= showerMaxInTBin_; };
1374
1375
1376 unsigned hitsInTime = 0;
1377 for (int i_layer = 0; i_layer < CSCConstants::NUM_LAYERS; i_layer++) {
1378 for (int i_wire = 0; i_wire < CSCConstants::MAX_NUM_WIREGROUPS; i_wire++) {
1379 auto times = wires[i_layer][i_wire];
1380 hitsInTime += std::count_if(times.begin(), times.end(), inTime);
1381 }
1382 }
1383
1384
1385
1386 unsigned csc_idx = CSCDetId::iChamberType(theStation, theRing) - 2;
1387
1388
1389 std::vector<unsigned> station_thresholds = {
1390 thresholds_[csc_idx * 3], thresholds_[csc_idx * 3 + 1], thresholds_[csc_idx * 3 + 2]};
1391
1392
1393 for (unsigned i = 0; i < station_thresholds.size(); i++) {
1394 if (hitsInTime >= station_thresholds[i]) {
1395 inTimeHMT_ = i + 1;
1396 }
1397 }
1398
1399
1400 shower_ = CSCShowerDigi(inTimeHMT_, false, theTrigChamber);
1401 }