File indexing completed on 2024-09-07 04:36:58
0001 #include "L1Trigger/L1TMuonEndCap/interface/PatternRecognition.h"
0002 #include "DataFormats/L1TMuon/interface/L1TMuonSubsystems.h"
0003
0004 #include "helper.h" // to_hex, to_binary
0005
0006 namespace {
0007 const int padding_w_st1 = 15;
0008 const int padding_w_st3 = 7;
0009 const int padding_extra_w_st1 = padding_w_st1 - padding_w_st3;
0010 }
0011
0012 void PatternRecognition::configure(int verbose,
0013 int endcap,
0014 int sector,
0015 int bx,
0016 int bxWindow,
0017 const std::vector<std::string>& pattDefinitions,
0018 const std::vector<std::string>& symPattDefinitions,
0019 bool useSymPatterns,
0020 int maxRoadsPerZone,
0021 bool useSecondEarliest) {
0022 verbose_ = verbose;
0023 endcap_ = endcap;
0024 sector_ = sector;
0025 bx_ = bx;
0026
0027 bxWindow_ = bxWindow;
0028 pattDefinitions_ = pattDefinitions;
0029 symPattDefinitions_ = symPattDefinitions;
0030 useSymPatterns_ = useSymPatterns;
0031 maxRoadsPerZone_ = maxRoadsPerZone;
0032 useSecondEarliest_ = useSecondEarliest;
0033
0034 configure_details();
0035 }
0036
0037 void PatternRecognition::configure_details() {
0038 emtf_assert(1 <= bxWindow_ && bxWindow_ <= 3);
0039
0040 patterns_.clear();
0041
0042
0043 if (!useSymPatterns_) {
0044
0045 for (const auto& s : pattDefinitions_) {
0046 const std::vector<std::string>& tokens = split_string(s, ',', ':');
0047 emtf_assert(tokens.size() == 9);
0048
0049 std::vector<std::string>::const_iterator tokens_it = tokens.begin();
0050
0051
0052
0053 int straightness = std::stoi(*tokens_it++);
0054 int st1_max = std::stoi(*tokens_it++);
0055 int st1_min = std::stoi(*tokens_it++);
0056 int st2_max = std::stoi(*tokens_it++);
0057 int st2_min = std::stoi(*tokens_it++);
0058 int st3_max = std::stoi(*tokens_it++);
0059 int st3_min = std::stoi(*tokens_it++);
0060 int st4_max = std::stoi(*tokens_it++);
0061 int st4_min = std::stoi(*tokens_it++);
0062
0063
0064
0065 emtf_assert(st2_max == padding_w_st3 && st2_min == padding_w_st3);
0066
0067
0068
0069 st2_max += padding_extra_w_st1;
0070 st2_min += padding_extra_w_st1;
0071 st3_max += padding_extra_w_st1;
0072 st3_min += padding_extra_w_st1;
0073 st4_max += padding_extra_w_st1;
0074 st4_min += padding_extra_w_st1;
0075
0076
0077 PhiMemoryImage pattern;
0078 pattern.set_straightness(straightness);
0079 int i = 0;
0080
0081 for (i = st1_min; i <= st1_max; i++)
0082 pattern.set_bit(0, i);
0083 for (i = st2_min; i <= st2_max; i++)
0084 pattern.set_bit(1, i);
0085 for (i = st3_min; i <= st3_max; i++)
0086 pattern.set_bit(2, i);
0087 for (i = st4_min; i <= st4_max; i++)
0088 pattern.set_bit(3, i);
0089
0090
0091 pattern.rotr(padding_extra_w_st1);
0092 patterns_.push_back(pattern);
0093 }
0094 emtf_assert(patterns_.size() == pattDefinitions_.size());
0095
0096 } else {
0097
0098 for (const auto& s : symPattDefinitions_) {
0099 const std::vector<std::string>& tokens = split_string(s, ',', ':');
0100 emtf_assert(tokens.size() == 17);
0101
0102 std::vector<std::string>::const_iterator tokens_it = tokens.begin();
0103
0104
0105
0106 int straightness = std::stoi(*tokens_it++);
0107 int st1_max1 = std::stoi(*tokens_it++);
0108 int st1_min1 = std::stoi(*tokens_it++);
0109 int st1_max2 = std::stoi(*tokens_it++);
0110 int st1_min2 = std::stoi(*tokens_it++);
0111 int st2_max1 = std::stoi(*tokens_it++);
0112 int st2_min1 = std::stoi(*tokens_it++);
0113 int st2_max2 = std::stoi(*tokens_it++);
0114 int st2_min2 = std::stoi(*tokens_it++);
0115 int st3_max1 = std::stoi(*tokens_it++);
0116 int st3_min1 = std::stoi(*tokens_it++);
0117 int st3_max2 = std::stoi(*tokens_it++);
0118 int st3_min2 = std::stoi(*tokens_it++);
0119 int st4_max1 = std::stoi(*tokens_it++);
0120 int st4_min1 = std::stoi(*tokens_it++);
0121 int st4_max2 = std::stoi(*tokens_it++);
0122 int st4_min2 = std::stoi(*tokens_it++);
0123
0124
0125
0126 emtf_assert(st2_max1 == padding_w_st3 && st2_min1 == padding_w_st3);
0127 emtf_assert(st2_max2 == padding_w_st3 && st2_min2 == padding_w_st3);
0128
0129
0130
0131 st2_max1 += padding_extra_w_st1;
0132 st2_min1 += padding_extra_w_st1;
0133 st2_max2 += padding_extra_w_st1;
0134 st2_min2 += padding_extra_w_st1;
0135 st3_max1 += padding_extra_w_st1;
0136 st3_min1 += padding_extra_w_st1;
0137 st3_max2 += padding_extra_w_st1;
0138 st3_min2 += padding_extra_w_st1;
0139 st4_max1 += padding_extra_w_st1;
0140 st4_min1 += padding_extra_w_st1;
0141 st4_max2 += padding_extra_w_st1;
0142 st4_min2 += padding_extra_w_st1;
0143
0144
0145 PhiMemoryImage pattern;
0146 pattern.set_straightness(straightness);
0147 int i = 0;
0148
0149 for (i = st1_min1; i <= st1_max1; i++)
0150 pattern.set_bit(0, i);
0151 for (i = st1_min2; i <= st1_max2; i++)
0152 pattern.set_bit(0, i);
0153 for (i = st2_min1; i <= st2_max1; i++)
0154 pattern.set_bit(1, i);
0155 for (i = st2_min2; i <= st2_max2; i++)
0156 pattern.set_bit(1, i);
0157 for (i = st3_min1; i <= st3_max1; i++)
0158 pattern.set_bit(2, i);
0159 for (i = st3_min2; i <= st3_max2; i++)
0160 pattern.set_bit(2, i);
0161 for (i = st4_min1; i <= st4_max1; i++)
0162 pattern.set_bit(3, i);
0163 for (i = st4_min2; i <= st4_max2; i++)
0164 pattern.set_bit(3, i);
0165
0166
0167 pattern.rotr(padding_extra_w_st1);
0168 patterns_.push_back(pattern);
0169 }
0170 emtf_assert(patterns_.size() == symPattDefinitions_.size());
0171 }
0172
0173 if (verbose_ > 2) {
0174 for (const auto& pattern : patterns_) {
0175 std::cout << "Pattern straightness: " << pattern.get_straightness() << " image: " << std::endl;
0176 std::cout << pattern << std::endl;
0177 }
0178 }
0179 }
0180
0181 void PatternRecognition::process(const std::deque<EMTFHitCollection>& extended_conv_hits,
0182 std::map<pattern_ref_t, int>& patt_lifetime_map,
0183 emtf::zone_array<EMTFRoadCollection>& zone_roads) const {
0184
0185 int num_conv_hits = 0;
0186 for (const auto& conv_hits : extended_conv_hits)
0187 num_conv_hits += conv_hits.size();
0188 bool early_exit = (num_conv_hits == 0) && (patt_lifetime_map.empty());
0189
0190 if (early_exit)
0191 return;
0192
0193 if (verbose_ > 0) {
0194 for (const auto& conv_hits : extended_conv_hits) {
0195 for (const auto& conv_hit : conv_hits) {
0196 if (conv_hit.Subsystem() == L1TMuon::kCSC) {
0197 std::cout << "CSC hit st: " << conv_hit.PC_station() << " ch: " << conv_hit.PC_chamber()
0198 << " ph: " << conv_hit.Phi_fp() << " th: " << conv_hit.Theta_fp() << " strip: " << conv_hit.Strip()
0199 << " wire: " << conv_hit.Wire() << " cpat: " << conv_hit.Pattern()
0200 << " zone_hit: " << conv_hit.Zone_hit() << " zone_code: " << conv_hit.Zone_code()
0201 << " bx: " << conv_hit.BX() << std::endl;
0202 }
0203 }
0204 }
0205
0206 for (const auto& conv_hits : extended_conv_hits) {
0207 for (const auto& conv_hit : conv_hits) {
0208 if (conv_hit.Subsystem() == L1TMuon::kRPC) {
0209 std::cout << "RPC hit st: " << conv_hit.PC_station() << " ch: " << conv_hit.PC_chamber()
0210 << " ph>>2: " << (conv_hit.Phi_fp() >> 2) << " th>>2: " << (conv_hit.Theta_fp() >> 2)
0211 << " strip: " << conv_hit.Strip() << " roll: " << conv_hit.Roll() << " cpat: " << conv_hit.Pattern()
0212 << " bx: " << conv_hit.BX() << std::endl;
0213 }
0214 }
0215 }
0216
0217 for (const auto& conv_hits : extended_conv_hits) {
0218 for (const auto& conv_hit : conv_hits) {
0219 if (conv_hit.Subsystem() == L1TMuon::kGEM) {
0220 std::cout << "GEM hit st: " << conv_hit.PC_station() << " ch: " << conv_hit.PC_chamber()
0221 << " ph: " << conv_hit.Phi_fp() << " th: " << conv_hit.Theta_fp() << " strip: " << conv_hit.Strip()
0222 << " roll: " << conv_hit.Roll() << " cpat: " << conv_hit.Pattern() << " bx: " << conv_hit.BX()
0223 << std::endl;
0224 }
0225 }
0226 }
0227 }
0228
0229
0230 emtf::zone_array<PhiMemoryImage> zone_images;
0231
0232 for (int izone = 0; izone < emtf::NUM_ZONES; ++izone) {
0233
0234 if (is_zone_empty(izone + 1, extended_conv_hits, patt_lifetime_map))
0235 continue;
0236
0237
0238 make_zone_image(izone + 1, extended_conv_hits, zone_images.at(izone));
0239
0240
0241 process_single_zone(izone + 1, zone_images.at(izone), patt_lifetime_map, zone_roads.at(izone));
0242 }
0243
0244 if (verbose_ > 2) {
0245 for (int izone = emtf::NUM_ZONES; izone >= 1; --izone) {
0246 std::cout << "zone: " << izone << std::endl;
0247 std::cout << zone_images.at(izone - 1) << std::endl;
0248 }
0249
0250
0251
0252 }
0253
0254 if (verbose_ > 0) {
0255 for (const auto& roads : zone_roads) {
0256 for (const auto& road : reversed(roads)) {
0257 std::cout << "pattern: z: " << road.Zone() - 1 << " ph: " << road.Key_zhit()
0258 << " q: " << to_hex(road.Quality_code()) << " ly: " << to_binary(road.Layer_code(), 3)
0259 << " str: " << to_binary(road.Straightness(), 3) << " bx: " << road.BX() << std::endl;
0260 }
0261 }
0262 }
0263
0264
0265 for (int izone = 0; izone < emtf::NUM_ZONES; ++izone) {
0266 sort_single_zone(zone_roads.at(izone));
0267 }
0268 }
0269
0270 bool PatternRecognition::is_zone_empty(int zone,
0271 const std::deque<EMTFHitCollection>& extended_conv_hits,
0272 const std::map<pattern_ref_t, int>& patt_lifetime_map) const {
0273 int izone = zone - 1;
0274 int num_conv_hits = 0;
0275 int num_patts = 0;
0276
0277 std::deque<EMTFHitCollection>::const_iterator ext_conv_hits_it = extended_conv_hits.begin();
0278 std::deque<EMTFHitCollection>::const_iterator ext_conv_hits_end = extended_conv_hits.end();
0279
0280 for (; ext_conv_hits_it != ext_conv_hits_end; ++ext_conv_hits_it) {
0281 EMTFHitCollection::const_iterator conv_hits_it = ext_conv_hits_it->begin();
0282 EMTFHitCollection::const_iterator conv_hits_end = ext_conv_hits_it->end();
0283
0284 for (; conv_hits_it != conv_hits_end; ++conv_hits_it) {
0285 emtf_assert(conv_hits_it->PC_segment() <=
0286 4);
0287
0288 if (conv_hits_it->Subsystem() == L1TMuon::kRPC)
0289 continue;
0290
0291 if (conv_hits_it->Subsystem() == L1TMuon::kGEM)
0292 continue;
0293
0294 if (conv_hits_it->Zone_code() & (1 << izone)) {
0295 num_conv_hits += 1;
0296 }
0297 }
0298 }
0299
0300 std::map<pattern_ref_t, int>::const_iterator patt_lifetime_map_it = patt_lifetime_map.begin();
0301 std::map<pattern_ref_t, int>::const_iterator patt_lifetime_map_end = patt_lifetime_map.end();
0302
0303 for (; patt_lifetime_map_it != patt_lifetime_map_end; ++patt_lifetime_map_it) {
0304 if (patt_lifetime_map_it->first.at(0) == zone) {
0305 num_patts += 1;
0306 }
0307 }
0308
0309 return (num_conv_hits == 0) && (num_patts == 0);
0310 }
0311
0312 void PatternRecognition::make_zone_image(int zone,
0313 const std::deque<EMTFHitCollection>& extended_conv_hits,
0314 PhiMemoryImage& image) const {
0315 int izone = zone - 1;
0316
0317 std::deque<EMTFHitCollection>::const_iterator ext_conv_hits_it = extended_conv_hits.begin();
0318 std::deque<EMTFHitCollection>::const_iterator ext_conv_hits_end = extended_conv_hits.end();
0319
0320 for (; ext_conv_hits_it != ext_conv_hits_end; ++ext_conv_hits_it) {
0321 EMTFHitCollection::const_iterator conv_hits_it = ext_conv_hits_it->begin();
0322 EMTFHitCollection::const_iterator conv_hits_end = ext_conv_hits_it->end();
0323
0324 for (; conv_hits_it != conv_hits_end; ++conv_hits_it) {
0325 if (conv_hits_it->Subsystem() == L1TMuon::kRPC)
0326 continue;
0327
0328 if (conv_hits_it->Subsystem() == L1TMuon::kGEM)
0329 continue;
0330
0331 if (conv_hits_it->Zone_code() & (1 << izone)) {
0332 unsigned int layer = conv_hits_it->Station() - 1;
0333 unsigned int bit = conv_hits_it->Zone_hit();
0334 image.set_bit(layer, bit);
0335 }
0336 }
0337 }
0338 }
0339
0340 void PatternRecognition::process_single_zone(int zone,
0341 PhiMemoryImage cloned_image,
0342 std::map<pattern_ref_t, int>& patt_lifetime_map,
0343 EMTFRoadCollection& roads) const {
0344 roads.clear();
0345
0346 const int drift_time = bxWindow_ - 1;
0347 const int npatterns = patterns_.size();
0348
0349
0350
0351 cloned_image.rotl(padding_w_st3);
0352
0353 for (int izhit = 0; izhit < emtf::NUM_ZONE_HITS; ++izhit) {
0354
0355
0356 if (izhit > 0)
0357 cloned_image.rotr(1);
0358
0359 int max_quality_code = -1;
0360 EMTFRoad tmp_road;
0361
0362
0363 for (int ipatt = 0; ipatt < npatterns; ++ipatt) {
0364 const PhiMemoryImage& patt = patterns_.at(ipatt);
0365 const pattern_ref_t patt_ref = {{zone, izhit, ipatt}};
0366 int straightness = patt.get_straightness();
0367
0368 bool is_lifetime_up = false;
0369
0370 int layer_code = patt.op_and(cloned_image);
0371 bool more_than_one = (layer_code != 0) && (layer_code != 1) && (layer_code != 2) && (layer_code != 4);
0372 bool more_than_zero = (layer_code != 0);
0373
0374 if (more_than_zero) {
0375
0376 auto ins = patt_lifetime_map.insert({patt_ref, 0});
0377
0378 if (!useSecondEarliest_) {
0379
0380 auto patt_ins = ins.first;
0381 bool patt_exists = !ins.second;
0382
0383 if (patt_exists) {
0384 if (patt_ins->second == drift_time) {
0385 is_lifetime_up = true;
0386 }
0387 }
0388 patt_ins->second += 1;
0389
0390 } else {
0391
0392 auto patt_ins = ins.first;
0393 int bx_shifter = patt_ins->second;
0394 int bx2 = bool(bx_shifter & (1 << 2));
0395 int bx1 = bool(bx_shifter & (1 << 1));
0396 int bx0 = bool(bx_shifter & (1 << 0));
0397
0398
0399 if (drift_time == 2 && bx2 == 0 && bx1 == 1) {
0400 is_lifetime_up = true;
0401 } else if (drift_time == 1 && bx1 == 0 && bx0 == 1) {
0402 is_lifetime_up = true;
0403 } else if (drift_time == 0) {
0404 is_lifetime_up = true;
0405 }
0406
0407 bx2 = bx1;
0408 bx1 = bx0;
0409 bx0 = more_than_zero;
0410 bx_shifter = (bx2 << 2) | (bx1 << 1) | bx0;
0411 patt_ins->second = bx_shifter;
0412 }
0413
0414 } else {
0415
0416 patt_lifetime_map.erase(patt_ref);
0417 }
0418
0419
0420
0421 if (is_lifetime_up && more_than_one) {
0422
0423
0424
0425 int quality_code =
0426 ((((straightness >> 2) & 1) << 5) | (((straightness >> 1) & 1) << 3) | (((straightness >> 0) & 1) << 1) |
0427 (((layer_code >> 2) & 1) << 4) | (((layer_code >> 1) & 1) << 2) | (((layer_code >> 0) & 1) << 0));
0428
0429
0430 EMTFRoad road;
0431 road.set_endcap((endcap_ == 1) ? 1 : -1);
0432 road.set_sector(sector_);
0433 road.set_sector_idx((endcap_ == 1) ? sector_ - 1 : sector_ + 5);
0434 road.set_bx(bx_ - drift_time);
0435
0436 road.set_zone(patt_ref.at(0));
0437 road.set_key_zhit(patt_ref.at(1));
0438 road.set_pattern(patt_ref.at(2));
0439
0440 road.set_straightness(straightness);
0441 road.set_layer_code(layer_code);
0442 road.set_quality_code(quality_code);
0443
0444
0445 if (max_quality_code < quality_code) {
0446 max_quality_code = quality_code;
0447 tmp_road = road;
0448 }
0449 }
0450
0451 }
0452
0453
0454 if (max_quality_code != -1) {
0455 roads.push_back(tmp_road);
0456 }
0457
0458 }
0459
0460
0461
0462 if (!roads.empty()) {
0463 std::array<int, emtf::NUM_ZONE_HITS> quality_codes;
0464 quality_codes.fill(0);
0465
0466 EMTFRoadCollection::iterator roads_it = roads.begin();
0467 EMTFRoadCollection::iterator roads_end = roads.end();
0468
0469 for (; roads_it != roads_end; ++roads_it) {
0470 quality_codes.at(roads_it->Key_zhit()) = roads_it->Quality_code();
0471 }
0472
0473 roads_it = roads.begin();
0474 roads_end = roads.end();
0475
0476 for (; roads_it != roads_end; ++roads_it) {
0477 int izhit = roads_it->Key_zhit();
0478
0479
0480 int qc = quality_codes.at(izhit);
0481
0482
0483
0484 int ql = (izhit == emtf::NUM_ZONE_HITS - 1) ? 0 : quality_codes.at(izhit + 1);
0485 int qr = (izhit == 0) ? 0 : quality_codes.at(izhit - 1);
0486
0487
0488 if (qc <= ql || qc < qr) {
0489 roads_it->set_quality_code(0);
0490 }
0491 }
0492 }
0493
0494
0495
0496 struct {
0497 typedef EMTFRoad value_type;
0498 bool operator()(const value_type& x) const { return (x.Quality_code() == 0); }
0499 } quality_code_zero_pred;
0500
0501 roads.erase(std::remove_if(roads.begin(), roads.end(), quality_code_zero_pred), roads.end());
0502 }
0503
0504 void PatternRecognition::sort_single_zone(EMTFRoadCollection& roads) const {
0505
0506 struct {
0507 typedef EMTFRoad value_type;
0508 bool operator()(const value_type& lhs, const value_type& rhs) const { return lhs.Key_zhit() > rhs.Key_zhit(); }
0509 } greater_zhit_cmp;
0510
0511 std::sort(roads.begin(), roads.end(), greater_zhit_cmp);
0512
0513
0514 struct {
0515 typedef EMTFRoad value_type;
0516 bool operator()(const value_type& lhs, const value_type& rhs) const {
0517 return lhs.Quality_code() > rhs.Quality_code();
0518 }
0519 } greater_quality_cmp;
0520
0521 std::stable_sort(roads.begin(), roads.end(), greater_quality_cmp);
0522
0523
0524 const size_t n = maxRoadsPerZone_;
0525 if (roads.size() > n) {
0526 roads.erase(roads.begin() + n, roads.end());
0527 }
0528 emtf_assert(roads.size() <= n);
0529
0530
0531 for (unsigned iroad = 0; iroad < roads.size(); ++iroad) {
0532 roads.at(iroad).set_winner(iroad);
0533 }
0534 }