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