Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:55:30

0001 #include "L1Trigger/L1TMuonEndCap/interface/PrimitiveSelection.h"
0002 #include "DataFormats/L1TMuon/interface/L1TMuonSubsystems.h"
0003 
0004 #include "helper.h"  // merge_map_into_map
0005 
0006 // 18 in ME1; 9x3 in ME2,3,4; 9 from neighbor sector.
0007 // Arranged in FW as 6 stations, 9 chambers per station.
0008 #define NUM_CSC_CHAMBERS 6 * 9
0009 // 6x2 in RE1,2; 12x2 in RE3,4; 6 from neighbor sector.
0010 // Arranged in FW as 7 stations, 6 chambers per station.
0011 // For Phase 2, add RE1/3, RE2/3, RE3/1, RE4/1 -> 10 chambers per station
0012 #define NUM_RPC_CHAMBERS 7 * 10
0013 // 6 in GE1/1; 3 in GE2/1; 3 in ME0; 3 from neighbor sector. (unconfirmed!)
0014 #define NUM_GEM_CHAMBERS 15
0015 // 2x4 in MB1,2,3,4; 4 from neighbor sector. (unconfirmed!)
0016 #define NUM_DT_CHAMBERS 3 * 4
0017 
0018 void PrimitiveSelection::configure(int verbose,
0019                                    int endcap,
0020                                    int sector,
0021                                    int bx,
0022                                    int bxShiftCSC,
0023                                    int bxShiftRPC,
0024                                    int bxShiftGEM,
0025                                    int bxShiftME0,
0026                                    bool includeNeighbor,
0027                                    bool duplicateTheta,
0028                                    bool bugME11Dupes,
0029                                    bool useRun3CCLUT_OTMB,
0030                                    bool useRun3CCLUT_TMB) {
0031   verbose_ = verbose;
0032   endcap_ = endcap;
0033   sector_ = sector;
0034   bx_ = bx;
0035 
0036   bxShiftCSC_ = bxShiftCSC;
0037   bxShiftRPC_ = bxShiftRPC;
0038   bxShiftGEM_ = bxShiftGEM;
0039   bxShiftME0_ = bxShiftME0;
0040 
0041   includeNeighbor_ = includeNeighbor;
0042   duplicateTheta_ = duplicateTheta;
0043   bugME11Dupes_ = bugME11Dupes;
0044 
0045   // Run 3 CCLUT algorithm
0046   useRun3CCLUT_OTMB_ = useRun3CCLUT_OTMB;
0047   useRun3CCLUT_TMB_ = useRun3CCLUT_TMB;
0048 }
0049 
0050 // _____________________________________________________________________________
0051 // Specialized process() for CSC
0052 template <>
0053 void PrimitiveSelection::process(emtf::CSCTag tag,
0054                                  const TriggerPrimitiveCollection& muon_primitives,
0055                                  std::map<int, TriggerPrimitiveCollection>& selected_csc_map) const {
0056   TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
0057   TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
0058 
0059   for (; tp_it != tp_end; ++tp_it) {
0060     int selected_csc = select_csc(*tp_it);  // Returns CSC "link" index (0 - 53)
0061 
0062     if (selected_csc >= 0) {
0063       emtf_assert(selected_csc < NUM_CSC_CHAMBERS);
0064 
0065       //FIXME
0066       if (selected_csc_map[selected_csc].size() < 2) {
0067         selected_csc_map[selected_csc].push_back(*tp_it);
0068       } else {
0069         edm::LogWarning("L1T") << "\n******************* EMTF EMULATOR: SUPER-BIZZARE CASE *******************";
0070         edm::LogWarning("L1T") << "Found 3 CSC trigger primitives in the same chamber";
0071         for (int ii = 0; ii < 3; ii++) {
0072           TriggerPrimitive tp_err = (ii < 2 ? selected_csc_map[selected_csc].at(ii) : *tp_it);
0073           edm::LogWarning("L1T") << "LCT #" << ii + 1 << ": BX " << tp_err.getBX() << ", endcap "
0074                                  << tp_err.detId<CSCDetId>().endcap() << ", sector "
0075                                  << tp_err.detId<CSCDetId>().triggerSector() << ", station "
0076                                  << tp_err.detId<CSCDetId>().station() << ", ring " << tp_err.detId<CSCDetId>().ring()
0077                                  << ", chamber " << tp_err.detId<CSCDetId>().chamber() << ", CSC ID "
0078                                  << tp_err.getCSCData().cscID << ": strip " << tp_err.getStrip() << ", wire "
0079                                  << tp_err.getWire();
0080         }
0081         edm::LogWarning("L1T") << "************************* ONLY KEEP FIRST TWO *************************\n\n";
0082       }
0083 
0084     }  // End conditional: if (selected_csc >= 0)
0085   }    // End loop: for (; tp_it != tp_end; ++tp_it)
0086 
0087   // Duplicate CSC muon primitives
0088   // If there are 2 LCTs in the same chamber with (strip, wire) = (s1, w1) and (s2, w2)
0089   // make all combinations with (s1, w1), (s2, w1), (s1, w2), (s2, w2)
0090   if (duplicateTheta_) {
0091     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_csc_map.begin();
0092     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_csc_map.end();
0093 
0094     for (; map_tp_it != map_tp_end; ++map_tp_it) {
0095       int selected = map_tp_it->first;
0096       TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second;  // pass by reference
0097 
0098       if (tmp_primitives.size() >= 4) {
0099         edm::LogWarning("L1T") << "EMTF found 4 or more CSC LCTs in one chamber: keeping only two";
0100         tmp_primitives.erase(tmp_primitives.begin() + 4, tmp_primitives.end());  // erase 5th element++
0101         tmp_primitives.erase(tmp_primitives.begin() + 2);                        // erase 3rd element
0102         tmp_primitives.erase(tmp_primitives.begin() + 1);                        // erase 2nd element
0103       } else if (tmp_primitives.size() == 3) {
0104         edm::LogWarning("L1T") << "EMTF found 3 CSC LCTs in one chamber: keeping only two";
0105         tmp_primitives.erase(tmp_primitives.begin() + 2);  // erase 3rd element
0106       }
0107       emtf_assert(tmp_primitives.size() <= 2);  // at most 2 hits
0108 
0109       if (tmp_primitives.size() == 2) {
0110         if ((tmp_primitives.at(0).getStrip() != tmp_primitives.at(1).getStrip()) &&
0111             (tmp_primitives.at(0).getWire() != tmp_primitives.at(1).getWire())) {
0112           // Swap wire numbers
0113           TriggerPrimitive tp0 = tmp_primitives.at(0);  // (s1,w1)
0114           TriggerPrimitive tp1 = tmp_primitives.at(1);  // (s2,w2)
0115           uint16_t tmp_keywire = tp0.accessCSCData().keywire;
0116           tp0.accessCSCData().keywire = tp1.accessCSCData().keywire;  // (s1,w2)
0117           tp1.accessCSCData().keywire = tmp_keywire;                  // (s2,w1)
0118 
0119           tmp_primitives.insert(tmp_primitives.begin() + 1, tp1);  // (s2,w1) at 2nd pos
0120           tmp_primitives.insert(tmp_primitives.begin() + 2, tp0);  // (s1,w2) at 3rd pos
0121         }
0122 
0123         const bool is_csc_me11 = (0 <= selected && selected <= 2) || (9 <= selected && selected <= 11) ||
0124                                  (selected == 45);  // ME1/1 sub 1 or ME1/1 sub 2 or ME1/1 from neighbor
0125 
0126         if (bugME11Dupes_ && is_csc_me11) {
0127           // For ME1/1, always make 4 LCTs without checking strip & wire combination
0128           if (tmp_primitives.size() == 2) {
0129             // Swap wire numbers
0130             TriggerPrimitive tp0 = tmp_primitives.at(0);  // (s1,w1)
0131             TriggerPrimitive tp1 = tmp_primitives.at(1);  // (s2,w2)
0132             uint16_t tmp_keywire = tp0.accessCSCData().keywire;
0133             tp0.accessCSCData().keywire = tp1.accessCSCData().keywire;  // (s1,w2)
0134             tp1.accessCSCData().keywire = tmp_keywire;                  // (s2,w1)
0135 
0136             tmp_primitives.insert(tmp_primitives.begin() + 1, tp1);  // (s2,w1) at 2nd pos
0137             tmp_primitives.insert(tmp_primitives.begin() + 2, tp0);  // (s1,w2) at 3rd pos
0138           }
0139           emtf_assert(tmp_primitives.size() == 1 || tmp_primitives.size() == 4);
0140         }
0141 
0142       }  // end if tmp_primitives.size() == 2
0143     }    // end loop over selected_csc_map
0144   }      // end if duplicate theta
0145 }
0146 
0147 // _____________________________________________________________________________
0148 // Specialized process() for RPC
0149 template <>
0150 void PrimitiveSelection::process(emtf::RPCTag tag,
0151                                  const TriggerPrimitiveCollection& muon_primitives,
0152                                  std::map<int, TriggerPrimitiveCollection>& selected_rpc_map) const {
0153   TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
0154   TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
0155 
0156   for (; tp_it != tp_end; ++tp_it) {
0157     int selected_rpc = select_rpc(*tp_it);  // Returns RPC "link" index
0158 
0159     if (selected_rpc >= 0) {
0160       emtf_assert(selected_rpc < NUM_RPC_CHAMBERS);
0161       selected_rpc_map[selected_rpc].push_back(*tp_it);
0162     }
0163   }
0164 
0165   // Apply truncation as in firmware: keep first 2 clusters, max cluster
0166   // size = 3 strips.
0167   // According to Karol Bunkowski, for one chamber (so 3 eta rolls) only up
0168   // to 2 hits (cluster centres) are produced. First two 'first' clusters are
0169   // chosen, and only after the cut on the cluster size is applied. So if
0170   // there are 1 large cluster and 2 small clusters, it is possible that
0171   // one of the two small clusters is discarded first, and the large cluster
0172   // then is removed by the cluster size cut, leaving only one cluster.
0173   // Note: this needs to be modified for Phase 2 with additional iRPC chambers.
0174   bool apply_truncation = true;
0175   if (apply_truncation) {
0176     struct {
0177       typedef TriggerPrimitive value_type;
0178       bool operator()(const value_type& x) const {
0179         // Skip cluster size cut if primitives are from CPPF emulator or EMTF unpacker (already clustered)
0180         if (x.getRPCData().isCPPF)
0181           return false;
0182 
0183         int sz = x.getRPCData().strip_hi - x.getRPCData().strip_low + 1;
0184 
0185         const RPCDetId& tp_detId = x.detId<RPCDetId>();
0186         int tp_station = tp_detId.station();
0187         int tp_ring = tp_detId.ring();
0188         const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
0189         if (is_irpc)
0190           return sz > 6;  // iRPC strip pitch is 1.5 times smaller than traditional RPC
0191         return sz > 3;
0192       }
0193     } cluster_size_cut;
0194 
0195     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_rpc_map.begin();
0196     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_rpc_map.end();
0197 
0198     for (; map_tp_it != map_tp_end; ++map_tp_it) {
0199       int selected = map_tp_it->first;
0200       TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second;  // pass by reference
0201 
0202       //FIXME
0203       // Check to see if unpacked CPPF digis have <= 2 digis per chamber, as expected
0204       if (tmp_primitives.size() > 2 && tmp_primitives.at(0).getRPCData().isCPPF) {
0205         edm::LogWarning("L1T") << "\n******************* EMTF EMULATOR: SUPER-BIZZARE CASE *******************";
0206         edm::LogWarning("L1T") << "Found " << tmp_primitives.size() << " CPPF digis in the same chamber";
0207         for (const auto& tp : tmp_primitives)
0208           tp.print(std::cout);
0209         edm::LogWarning("L1T") << "************************* ONLY KEEP FIRST TWO *************************\n\n";
0210       }
0211 
0212       if ((selected % 10) == 8 || (selected % 10) == 9) {  // RE3/1 or RE4/1 (iRPC)
0213         // Keep the first 4 clusters
0214         if (tmp_primitives.size() > 4)
0215           tmp_primitives.erase(tmp_primitives.begin() + 4, tmp_primitives.end());
0216       } else {
0217         // Keep the first 2 clusters
0218         if (tmp_primitives.size() > 2)
0219           tmp_primitives.erase(tmp_primitives.begin() + 2, tmp_primitives.end());
0220       }
0221 
0222       // Apply cluster size cut
0223       tmp_primitives.erase(std::remove_if(tmp_primitives.begin(), tmp_primitives.end(), cluster_size_cut),
0224                            tmp_primitives.end());
0225     }
0226   }  // end if apply_truncation
0227 
0228   // Map RPC subsector and chamber to CSC chambers
0229   // Note: RE3/2 & RE3/3 are considered as one chamber; RE4/2 & RE4/3 too.
0230   bool map_rpc_to_csc = true;
0231   if (map_rpc_to_csc) {
0232     std::map<int, TriggerPrimitiveCollection> tmp_selected_rpc_map;
0233 
0234     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_rpc_map.begin();
0235     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_rpc_map.end();
0236 
0237     for (; map_tp_it != map_tp_end; ++map_tp_it) {
0238       int selected = map_tp_it->first;
0239       TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second;  // pass by reference
0240 
0241       int rpc_sub = selected / 10;
0242       int rpc_chm = selected % 10;
0243 
0244       int pc_station = -1;
0245       int pc_chamber = -1;
0246 
0247       if (rpc_sub != 6) {    // native
0248         if (rpc_chm == 0) {  // RE1/2: 3-5, 12-14
0249           if (0 <= rpc_sub && rpc_sub < 3) {
0250             pc_station = 0;
0251             pc_chamber = 3 + rpc_sub;
0252           } else if (3 <= rpc_sub && rpc_sub < 6) {
0253             pc_station = 1;
0254             pc_chamber = 3 + (rpc_sub - 3);
0255           }
0256         } else if (rpc_chm == 6) {  // RE1/3: 6-8, 15-17
0257           if (0 <= rpc_sub && rpc_sub < 3) {
0258             pc_station = 0;
0259             pc_chamber = 6 + rpc_sub;
0260           } else if (3 <= rpc_sub && rpc_sub < 6) {
0261             pc_station = 1;
0262             pc_chamber = 6 + (rpc_sub - 3);
0263           }
0264         } else if (rpc_chm == 1 || rpc_chm == 7) {  // RE2/2, RE2/3: 21-26
0265           pc_station = 2;
0266           pc_chamber = 3 + rpc_sub;
0267         } else if (2 <= rpc_chm && rpc_chm <= 3) {  // RE3/2, RE3/3: 30-35
0268           pc_station = 3;
0269           pc_chamber = 3 + rpc_sub;
0270         } else if (4 <= rpc_chm && rpc_chm <= 5) {  // RE4/2, RE4/3: 39-44
0271           pc_station = 4;
0272           pc_chamber = 3 + rpc_sub;
0273         } else if (rpc_chm == 8) {  // RE3/1: 27-29
0274           pc_station = 3;
0275           pc_chamber = rpc_sub;
0276         } else if (rpc_chm == 9) {  // RE4/1: 36-38
0277           pc_station = 4;
0278           pc_chamber = rpc_sub;
0279         }
0280 
0281       } else {  // neighbor
0282         pc_station = 5;
0283         if (rpc_chm == 0) {  // RE1/2: 46
0284           pc_chamber = 1;
0285         } else if (rpc_chm == 6) {  // RE1/3: 47
0286           pc_chamber = 2;
0287         } else if (rpc_chm == 1 || rpc_chm == 7) {  // RE2/2, RE2/3: 49
0288           pc_chamber = 4;
0289         } else if (2 <= rpc_chm && rpc_chm <= 3) {  // RE3/2, RE3/3: 51
0290           pc_chamber = 6;
0291         } else if (4 <= rpc_chm && rpc_chm <= 5) {  // RE4/2, RE4/3: 53
0292           pc_chamber = 8;
0293         } else if (rpc_chm == 8) {  // RE3/1: 50
0294           pc_chamber = 5;
0295         } else if (rpc_chm == 9) {  // RE4/1: 52
0296           pc_chamber = 7;
0297         }
0298       }
0299       emtf_assert(pc_station != -1 && pc_chamber != -1);
0300       emtf_assert(pc_station < 6 && pc_chamber < 9);
0301 
0302       selected = (pc_station * 9) + pc_chamber;
0303 
0304       bool ignore_this_rpc_chm = false;
0305       if (rpc_chm == 3 || rpc_chm == 5) {  // special case of RE3,4/2 and RE3,4/3 chambers
0306         // if RE3,4/2 exists, ignore RE3,4/3. In C++, this assumes that the loop
0307         // over selected_rpc_map will always find RE3,4/2 before RE3,4/3
0308         if (tmp_selected_rpc_map.find(selected) != tmp_selected_rpc_map.end())
0309           ignore_this_rpc_chm = true;
0310       }
0311 
0312       if (rpc_chm == 6 || rpc_chm == 7) {  // RE1/3 and RE2/3 chambers are not part of EMTF
0313         ignore_this_rpc_chm = true;
0314       }
0315 
0316       if (rpc_chm == 8 || rpc_chm == 9) {  // RE3/1 and RE4/1 chambers are not available until Phase-2
0317         ignore_this_rpc_chm = true;
0318       }
0319 
0320       if (ignore_this_rpc_chm) {
0321         // Set RPC stubs as invalid, but we keep them
0322         for (auto&& tp : tmp_primitives) {
0323           tp.accessRPCData().valid = 0;
0324         }
0325       }
0326 
0327       // Keep the stubs in the temporary map
0328       if (tmp_selected_rpc_map.find(selected) == tmp_selected_rpc_map.end()) {
0329         tmp_selected_rpc_map[selected] = tmp_primitives;
0330       } else {
0331         tmp_selected_rpc_map[selected].insert(
0332             tmp_selected_rpc_map[selected].end(), tmp_primitives.begin(), tmp_primitives.end());
0333       }
0334     }  // end loop over selected_rpc_map
0335 
0336     std::swap(selected_rpc_map, tmp_selected_rpc_map);  // replace the original map
0337   }                                                     // end if map_rpc_to_csc
0338 }
0339 
0340 // _____________________________________________________________________________
0341 // Specialized process() for GEM
0342 template <>
0343 void PrimitiveSelection::process(emtf::GEMTag tag,
0344                                  const TriggerPrimitiveCollection& muon_primitives,
0345                                  std::map<int, TriggerPrimitiveCollection>& selected_gem_map) const {
0346   TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
0347   TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
0348 
0349   for (; tp_it != tp_end; ++tp_it) {
0350     int selected_gem = select_gem(*tp_it);  // Returns GEM "link" index
0351 
0352     if (selected_gem >= 0) {
0353       emtf_assert(selected_gem < NUM_GEM_CHAMBERS);
0354       selected_gem_map[selected_gem].push_back(*tp_it);
0355     }
0356   }
0357 
0358   // Apply truncation: max cluster size = 8 pads, keep first 8 clusters.
0359   bool apply_truncation = true;
0360   if (apply_truncation) {
0361     struct {
0362       typedef TriggerPrimitive value_type;
0363       bool operator()(const value_type& x) const {
0364         int sz = x.getGEMData().pad_hi - x.getGEMData().pad_low + 1;
0365         return sz > 8;
0366       }
0367     } cluster_size_cut;
0368 
0369     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_gem_map.begin();
0370     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_gem_map.end();
0371 
0372     for (; map_tp_it != map_tp_end; ++map_tp_it) {
0373       //int selected = map_tp_it->first;
0374       TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second;  // pass by reference
0375 
0376       // Apply cluster size cut
0377       tmp_primitives.erase(std::remove_if(tmp_primitives.begin(), tmp_primitives.end(), cluster_size_cut),
0378                            tmp_primitives.end());
0379 
0380       // Keep the first 8 clusters
0381       if (tmp_primitives.size() > 8)
0382         tmp_primitives.erase(tmp_primitives.begin() + 8, tmp_primitives.end());
0383     }
0384   }  // end if apply_truncation
0385 }
0386 
0387 // _____________________________________________________________________________
0388 // Specialized process() for ME0
0389 template <>
0390 void PrimitiveSelection::process(emtf::ME0Tag tag,
0391                                  const TriggerPrimitiveCollection& muon_primitives,
0392                                  std::map<int, TriggerPrimitiveCollection>& selected_me0_map) const {
0393   TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
0394   TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
0395 
0396   for (; tp_it != tp_end; ++tp_it) {
0397     int selected_me0 = select_me0(*tp_it);  // Returns ME0 "link" index
0398 
0399     if (selected_me0 >= 0) {
0400       emtf_assert(selected_me0 < NUM_GEM_CHAMBERS);
0401       selected_me0_map[selected_me0].push_back(*tp_it);
0402     }
0403   }
0404 
0405   // Apply truncation
0406   bool apply_truncation = true;
0407   if (apply_truncation) {
0408     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_me0_map.begin();
0409     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_me0_map.end();
0410 
0411     for (; map_tp_it != map_tp_end; ++map_tp_it) {
0412       //int selected = map_tp_it->first;
0413       TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second;  // pass by reference
0414 
0415       // Keep the first 20 clusters
0416       if (tmp_primitives.size() > 20)
0417         tmp_primitives.erase(tmp_primitives.begin() + 20, tmp_primitives.end());
0418     }
0419   }
0420 }
0421 
0422 // _____________________________________________________________________________
0423 // Specialized process() for DT
0424 template <>
0425 void PrimitiveSelection::process(emtf::DTTag tag,
0426                                  const TriggerPrimitiveCollection& muon_primitives,
0427                                  std::map<int, TriggerPrimitiveCollection>& selected_dt_map) const {
0428   TriggerPrimitiveCollection::const_iterator tp_it = muon_primitives.begin();
0429   TriggerPrimitiveCollection::const_iterator tp_end = muon_primitives.end();
0430 
0431   for (; tp_it != tp_end; ++tp_it) {
0432     int selected_dt = select_dt(*tp_it);  // Returns DT "link" index
0433 
0434     if (selected_dt >= 0) {
0435       emtf_assert(selected_dt < NUM_DT_CHAMBERS);
0436       selected_dt_map[selected_dt].push_back(*tp_it);
0437     }
0438   }
0439 
0440   // Duplicate DT muon primitives
0441   if (duplicateTheta_) {
0442     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_it = selected_dt_map.begin();
0443     std::map<int, TriggerPrimitiveCollection>::iterator map_tp_end = selected_dt_map.end();
0444 
0445     for (; map_tp_it != map_tp_end; ++map_tp_it) {
0446       //int selected = map_tp_it->first;
0447       TriggerPrimitiveCollection& tmp_primitives = map_tp_it->second;  // pass by reference
0448 
0449       emtf_assert(tmp_primitives.size() <= 2);  // at most 2 hits
0450 
0451       if (tmp_primitives.size() == 2) {
0452         if ((tmp_primitives.at(0).getStrip() != tmp_primitives.at(1).getStrip()) &&
0453             (tmp_primitives.at(0).getWire() != tmp_primitives.at(1).getWire())) {
0454           // Swap wire numbers
0455           TriggerPrimitive tp0 = tmp_primitives.at(0);  // (s1,w1)
0456           TriggerPrimitive tp1 = tmp_primitives.at(1);  // (s2,w2)
0457           uint16_t tmp_keywire = tp0.accessDTData().theta_bti_group;
0458           tp0.accessDTData().theta_bti_group = tp1.accessDTData().theta_bti_group;  // (s1,w2)
0459           tp1.accessDTData().theta_bti_group = tmp_keywire;                         // (s2,w1)
0460 
0461           tmp_primitives.insert(tmp_primitives.begin() + 1, tp1);  // (s2,w1) at 2nd pos
0462           tmp_primitives.insert(tmp_primitives.begin() + 2, tp0);  // (s1,w2) at 3rd pos
0463         }
0464       }  // end if tmp_primitives.size() == 2
0465     }    // end loop over selected_dt_map
0466   }      // end if duplicate theta
0467 }
0468 
0469 // _____________________________________________________________________________
0470 // Put the hits from DT, CSC, RPC, GEM, ME0 together in one collection
0471 
0472 // Notes from Alex (2017-03-28):
0473 //
0474 //     The RPC inclusion logic is very simple currently:
0475 //     - each CSC is analyzed for having track stubs in each BX
0476 //     - IF a CSC chamber is missing at least one track stub,
0477 //         AND there is an RPC overlapping with it in phi and theta,
0478 //         AND that RPC has hits,
0479 //       THEN RPC hit is inserted instead of missing CSC stub.
0480 //
0481 //     This is done at the output of coord_delay module, so such
0482 // inserted RPC hits can be matched to patterns by match_ph_segments
0483 // module, just like any CSC stubs. Note that substitution of missing
0484 // CSC stubs with RPC hits happens regardless of what's going on in
0485 // other chambers, regardless of whether a pattern has been detected
0486 // or not, basically regardless of anything. RPCs are treated as a
0487 // supplemental source of stubs for CSCs.
0488 
0489 void PrimitiveSelection::merge(const std::map<int, TriggerPrimitiveCollection>& selected_dt_map,
0490                                const std::map<int, TriggerPrimitiveCollection>& selected_csc_map,
0491                                const std::map<int, TriggerPrimitiveCollection>& selected_rpc_map,
0492                                const std::map<int, TriggerPrimitiveCollection>& selected_gem_map,
0493                                const std::map<int, TriggerPrimitiveCollection>& selected_me0_map,
0494                                std::map<int, TriggerPrimitiveCollection>& selected_prim_map) const {
0495   // First, put CSC hits
0496   std::map<int, TriggerPrimitiveCollection>::const_iterator map_tp_it = selected_csc_map.begin();
0497   std::map<int, TriggerPrimitiveCollection>::const_iterator map_tp_end = selected_csc_map.end();
0498 
0499   for (; map_tp_it != map_tp_end; ++map_tp_it) {
0500     int selected_csc = map_tp_it->first;
0501     const TriggerPrimitiveCollection& csc_primitives = map_tp_it->second;
0502     emtf_assert(csc_primitives.size() <= 4);  // at most 4 hits, including duplicated hits
0503 
0504     // Insert all CSC hits
0505     selected_prim_map[selected_csc] = csc_primitives;
0506   }
0507 
0508   // Second, insert GEM stubs if there is no CSC hits
0509   map_tp_it = selected_gem_map.begin();
0510   map_tp_end = selected_gem_map.end();
0511 
0512   for (; map_tp_it != map_tp_end; ++map_tp_it) {
0513     int selected_gem = map_tp_it->first;
0514     const TriggerPrimitiveCollection& gem_primitives = map_tp_it->second;
0515     if (gem_primitives.empty())
0516       continue;
0517     emtf_assert(gem_primitives.size() <= 8);  // at most 8 hits
0518 
0519     bool found = (selected_prim_map.find(selected_gem) != selected_prim_map.end());
0520     if (!found) {
0521       // No CSC hits, insert all GEM hits
0522       selected_prim_map[selected_gem] = gem_primitives;
0523 
0524     } else {
0525       // Do nothing
0526     }
0527   }
0528 
0529   // Third, insert RPC stubs if there is no CSC/GEM hits
0530   map_tp_it = selected_rpc_map.begin();
0531   map_tp_end = selected_rpc_map.end();
0532 
0533   for (; map_tp_it != map_tp_end; ++map_tp_it) {
0534     int selected_rpc = map_tp_it->first;
0535     const TriggerPrimitiveCollection& rpc_primitives = map_tp_it->second;
0536     if (rpc_primitives.empty())
0537       continue;
0538     emtf_assert(rpc_primitives.size() <= 4);  // at most 4 hits
0539 
0540     bool found = (selected_prim_map.find(selected_rpc) != selected_prim_map.end());
0541     if (!found) {
0542       // No CSC/GEM hits, insert all RPC hits
0543       //selected_prim_map[selected_rpc] = rpc_primitives;
0544 
0545       // No CSC/GEM hits, insert the valid RPC hits
0546       TriggerPrimitiveCollection tmp_rpc_primitives;
0547       for (const auto& tp : rpc_primitives) {
0548         if (tp.getRPCData().valid != 0) {
0549           tmp_rpc_primitives.push_back(tp);
0550         }
0551       }
0552       emtf_assert(tmp_rpc_primitives.size() <= 2);  // at most 2 hits
0553 
0554       selected_prim_map[selected_rpc] = tmp_rpc_primitives;
0555 
0556     } else {
0557       // Initial FW in 2017; was disabled on June 7.
0558       // If only one CSC/GEM hit, insert the first RPC hit
0559       //TriggerPrimitiveCollection& tmp_primitives = selected_prim_map[selected_rpc];  // pass by reference
0560 
0561       //if (tmp_primitives.size() < 2) {
0562       //  tmp_primitives.push_back(rpc_primitives.front());
0563       //}
0564     }
0565   }
0566 }
0567 
0568 void PrimitiveSelection::merge_no_truncate(const std::map<int, TriggerPrimitiveCollection>& selected_dt_map,
0569                                            const std::map<int, TriggerPrimitiveCollection>& selected_csc_map,
0570                                            const std::map<int, TriggerPrimitiveCollection>& selected_rpc_map,
0571                                            const std::map<int, TriggerPrimitiveCollection>& selected_gem_map,
0572                                            const std::map<int, TriggerPrimitiveCollection>& selected_me0_map,
0573                                            std::map<int, TriggerPrimitiveCollection>& selected_prim_map) const {
0574   // First, put CSC hits
0575   merge_map_into_map(selected_csc_map, selected_prim_map);
0576 
0577   // Second, insert ME0 hits
0578   merge_map_into_map(selected_me0_map, selected_prim_map);
0579 
0580   // Third, insert GEM hits
0581   merge_map_into_map(selected_gem_map, selected_prim_map);
0582 
0583   // Fourth, insert RPC hits
0584   merge_map_into_map(selected_rpc_map, selected_prim_map);
0585 
0586   // Fifth, insert DT hits
0587   merge_map_into_map(selected_dt_map, selected_prim_map);
0588 }
0589 
0590 // _____________________________________________________________________________
0591 // CSC functions
0592 int PrimitiveSelection::select_csc(const TriggerPrimitive& muon_primitive) const {
0593   int selected = -1;
0594 
0595   if (muon_primitive.subsystem() == L1TMuon::kCSC) {
0596     const CSCDetId& tp_detId = muon_primitive.detId<CSCDetId>();
0597     const CSCData& tp_data = muon_primitive.getCSCData();
0598 
0599     int tp_endcap = tp_detId.endcap();
0600     int tp_sector = tp_detId.triggerSector();
0601     int tp_station = tp_detId.station();
0602     int tp_ring = tp_detId.ring();
0603     int tp_chamber = tp_detId.chamber();
0604 
0605     int tp_bx = tp_data.bx;
0606     int tp_csc_ID = tp_data.cscID;
0607 
0608     const auto& [max_strip, max_wire] = emtf::get_csc_max_strip_and_wire(tp_station, tp_ring);
0609     const auto& [max_pattern, max_quality] = emtf::get_csc_max_pattern_and_quality(tp_station, tp_ring);
0610     const auto max_slope = emtf::get_csc_max_slope(tp_station, tp_ring, useRun3CCLUT_OTMB_, useRun3CCLUT_TMB_);
0611 
0612     if (endcap_ == 1 && sector_ == 1 && bx_ == -3) {  // do assertion checks only once
0613       emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
0614       emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
0615       emtf_assert(1 <= tp_station && tp_station <= 4);
0616       emtf_assert(1 <= tp_csc_ID && tp_csc_ID <= 9);
0617       emtf_assert(tp_data.strip < max_strip);
0618       emtf_assert(tp_data.keywire < max_wire);
0619       emtf_assert(tp_data.valid == true);
0620       emtf_assert(tp_data.pattern < max_pattern);
0621       emtf_assert(0 < tp_data.quality && tp_data.quality < max_quality);
0622     }
0623 
0624     // Check for corrupted LCT data. Data corruption could occur due to software or hardware issues, If corrupted, reject the LCT.
0625     // Note that the checks are performed in every sector processor for every BX. As a result, the same LCT may be reported multiple times by all 12 sector processors from BX=-3 to BX=+3.
0626     {
0627       if (!(tp_data.strip < max_strip)) {
0628         edm::LogWarning("L1T") << "Found error in LCT strip: " << tp_data.strip << " (allowed range: 0-"
0629                                << max_strip - 1 << ").";
0630         edm::LogWarning("L1T")
0631             << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
0632             << tp_ring << ", cscid " << tp_csc_ID
0633             << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
0634         return selected;
0635       }
0636 
0637       if (!(tp_data.keywire < max_wire)) {
0638         edm::LogWarning("L1T") << "Found error in LCT wire: " << tp_data.keywire << " (allowed range: 0-"
0639                                << max_wire - 1 << ").";
0640         edm::LogWarning("L1T")
0641             << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
0642             << tp_ring << ", cscid " << tp_csc_ID
0643             << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
0644         return selected;
0645       }
0646 
0647       if (!(tp_data.valid == true)) {
0648         edm::LogWarning("L1T") << "Found error in LCT valid: " << tp_data.valid << " (allowed value: 1).";
0649         edm::LogWarning("L1T")
0650             << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
0651             << tp_ring << ", cscid " << tp_csc_ID
0652             << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
0653         return selected;
0654       }
0655 
0656       if (!(tp_data.pattern < max_pattern)) {
0657         edm::LogWarning("L1T") << "Found error in LCT pattern: " << tp_data.pattern << " (allowed range: 0-"
0658                                << max_pattern - 1 << ").";
0659         edm::LogWarning("L1T")
0660             << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
0661             << tp_ring << ", cscid " << tp_csc_ID
0662             << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
0663         return selected;
0664       }
0665 
0666       if (!(0 < tp_data.quality && tp_data.quality < max_quality)) {
0667         edm::LogWarning("L1T") << "Found error in LCT quality: " << tp_data.quality << " (allowed range: 1-"
0668                                << max_quality - 1 << ").";
0669         edm::LogWarning("L1T")
0670             << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
0671             << tp_ring << ", cscid " << tp_csc_ID
0672             << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
0673         return selected;
0674       }
0675 
0676       if (!(tp_data.slope < max_slope)) {
0677         edm::LogWarning("L1T") << "Found error in LCT slope: " << tp_data.slope << " (allowed range: 0-"
0678                                << max_slope - 1 << ").";
0679         edm::LogWarning("L1T")
0680             << "From endcap " << tp_endcap << ", sector " << tp_sector << ", station " << tp_station << ", ring "
0681             << tp_ring << ", cscid " << tp_csc_ID
0682             << ". (Note that this LCT may be reported multiple times. See source code for explanations.)";
0683         return selected;
0684       }
0685     }  // end check for corrupted LCT data
0686 
0687     // station 1 --> subsector 1 or 2
0688     // station 2,3,4 --> subsector 0
0689     int tp_subsector = (tp_station != 1) ? 0 : ((tp_chamber % 6 > 2) ? 1 : 2);
0690 
0691     // Check if the chamber belongs to this sector processor at this BX.
0692     selected = get_index_csc(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_bx);
0693   }
0694   return selected;
0695 }
0696 
0697 bool PrimitiveSelection::is_in_sector_csc(int tp_endcap, int tp_sector) const {
0698   return ((endcap_ == tp_endcap) && (sector_ == tp_sector));
0699 }
0700 
0701 bool PrimitiveSelection::is_in_neighbor_sector_csc(
0702     int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID) const {
0703   auto get_neighbor = [](int sector) { return (sector == 1) ? 6 : sector - 1; };
0704 
0705   if (includeNeighbor_) {
0706     if ((endcap_ == tp_endcap) && (get_neighbor(sector_) == tp_sector)) {
0707       if (tp_station == 1) {
0708         if ((tp_subsector == 2) && (tp_csc_ID == 3 || tp_csc_ID == 6 || tp_csc_ID == 9))
0709           return true;
0710 
0711       } else {
0712         if (tp_csc_ID == 3 || tp_csc_ID == 9)
0713           return true;
0714       }
0715     }
0716   }
0717   return false;
0718 }
0719 
0720 bool PrimitiveSelection::is_in_bx_csc(int tp_bx) const {
0721   tp_bx += bxShiftCSC_;
0722   return (bx_ == tp_bx);
0723 }
0724 
0725 // Returns CSC input "link".  Index used by FW for unique chamber identification.
0726 int PrimitiveSelection::get_index_csc(
0727     int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const {
0728   int selected = -1;
0729 
0730   bool is_native = false;
0731   bool is_neighbor = false;
0732   if (is_in_bx_csc(tp_bx)) {
0733     if (is_in_sector_csc(tp_endcap, tp_sector)) {
0734       is_native = true;
0735     } else if (is_in_neighbor_sector_csc(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID)) {
0736       is_neighbor = true;
0737     }
0738   }
0739   if (!is_native && !is_neighbor)
0740     return selected;
0741 
0742   if (!is_neighbor) {
0743     if (tp_station == 1) {  // ME1: 0 - 8, 9 - 17
0744       selected = (tp_subsector - 1) * 9 + (tp_csc_ID - 1);
0745     } else {  // ME2,3,4: 18 - 26, 27 - 35, 36 - 44
0746       selected = (tp_station)*9 + (tp_csc_ID - 1);
0747     }
0748 
0749   } else {
0750     if (tp_station == 1) {  // ME1n: 45 - 47
0751       selected = (5) * 9 + (tp_csc_ID - 1) / 3;
0752     } else {  // ME2n,3n,4n: 48 - 53
0753       selected = (5) * 9 + (tp_station)*2 - 1 + (tp_csc_ID - 1 < 3 ? 0 : 1);
0754     }
0755   }
0756   emtf_assert(selected != -1);
0757   return selected;
0758 }
0759 
0760 // _____________________________________________________________________________
0761 // RPC functions
0762 int PrimitiveSelection::select_rpc(const TriggerPrimitive& muon_primitive) const {
0763   int selected = -1;
0764 
0765   if (muon_primitive.subsystem() == L1TMuon::kRPC) {
0766     const RPCDetId& tp_detId = muon_primitive.detId<RPCDetId>();
0767     const RPCData& tp_data = muon_primitive.getRPCData();
0768 
0769     int tp_region = tp_detId.region();  // 0 for Barrel, +/-1 for +/- Endcap
0770     int tp_endcap = (tp_region == -1) ? 2 : tp_region;
0771     int tp_sector = tp_detId.sector();        // 1 - 6 (60 degrees in phi, sector 1 begins at -5 deg)
0772     int tp_subsector = tp_detId.subsector();  // 1 - 6 (10 degrees in phi; staggered in z)
0773     int tp_station = tp_detId.station();      // 1 - 4
0774     int tp_ring = tp_detId.ring();            // 2 - 3 (increasing theta)
0775     int tp_roll = tp_detId.roll();  // 1 - 3 (decreasing theta; aka A - C; space between rolls is 9 - 15 in theta_fp)
0776     //int tp_layer     = tp_detId.layer();
0777 
0778     int tp_bx = tp_data.bx;
0779     int tp_strip = tp_data.strip;
0780     int tp_emtf_sect = tp_data.emtf_sector;
0781     bool tp_CPPF = tp_data.isCPPF;
0782 
0783     // In neighbor chambers, have two separate CPPFDigis for the two EMTF sectors
0784     if (tp_CPPF && (tp_emtf_sect != sector_))
0785       return selected;
0786 
0787     const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
0788 
0789     if (endcap_ == 1 && sector_ == 1 && bx_ == -3) {  // do assertion checks only once
0790       emtf_assert(tp_region != 0);
0791       emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
0792       emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
0793       emtf_assert(1 <= tp_subsector && tp_subsector <= 6);
0794       emtf_assert(1 <= tp_station && tp_station <= 4);
0795       emtf_assert((!is_irpc && 2 <= tp_ring && tp_ring <= 3) || (is_irpc && tp_ring == 1));
0796       emtf_assert((!is_irpc && 1 <= tp_roll && tp_roll <= 3) || (is_irpc && 1 <= tp_roll && tp_roll <= 5));
0797       //emtf_assert((!is_irpc && (tp_CPPF || (1 <= tp_strip && tp_strip <= 32))) || (is_irpc && 1 <= tp_strip && tp_strip <= 96));
0798       emtf_assert((!is_irpc && (tp_CPPF || (1 <= tp_strip && tp_strip <= 32))) ||
0799                   (is_irpc && 1 <= tp_strip && tp_strip <= 96 * 2));  // in CMSSW, the iRPC chamber has 192 strips
0800       //emtf_assert(tp_station > 2 || tp_ring != 3);  // stations 1 and 2 do not receive RPCs from ring 3
0801       emtf_assert(tp_data.valid == true);
0802     }
0803 
0804     // Check if the chamber belongs to this sector processor at this BX.
0805     selected = get_index_rpc(tp_endcap, tp_station, tp_ring, tp_sector, tp_subsector, tp_bx);
0806   }
0807   return selected;
0808 }
0809 
0810 bool PrimitiveSelection::is_in_sector_rpc(
0811     int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector) const {
0812   // RPC sector X, subsectors 1-2 correspond to CSC sector X-1
0813   // RPC sector X, subsectors 3-6 correspond to CSC sector X
0814   // iRPC sector X, subsectors 1   correspond to CSC sector X-1
0815   // iRPC sector X, subsectors 2-3 correspind to CSC sector X
0816   auto get_csc_sector = [](int tp_station, int tp_ring, int tp_sector, int tp_subsector) {
0817     const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
0818     if (is_irpc) {
0819       // 20 degree chamber
0820       int corr = (tp_subsector < 2) ? (tp_sector == 1 ? +5 : -1) : 0;
0821       return tp_sector + corr;
0822     } else {
0823       // 10 degree chamber
0824       int corr = (tp_subsector < 3) ? (tp_sector == 1 ? +5 : -1) : 0;
0825       return tp_sector + corr;
0826     }
0827   };
0828   return ((endcap_ == tp_endcap) && (sector_ == get_csc_sector(tp_station, tp_ring, tp_sector, tp_subsector)));
0829 }
0830 
0831 bool PrimitiveSelection::is_in_neighbor_sector_rpc(
0832     int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector) const {
0833   auto get_neighbor_subsector = [](int tp_station, int tp_ring) {
0834     const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
0835     if (is_irpc) {
0836       // 20 degree chamber
0837       return 1;
0838     } else {
0839       // 10 degree chamber
0840       return 2;
0841     }
0842   };
0843   return (includeNeighbor_ && (endcap_ == tp_endcap) && (sector_ == tp_sector) &&
0844           (tp_subsector == get_neighbor_subsector(tp_station, tp_ring)));
0845 }
0846 
0847 bool PrimitiveSelection::is_in_bx_rpc(int tp_bx) const {
0848   tp_bx += bxShiftRPC_;
0849   return (bx_ == tp_bx);
0850 }
0851 
0852 int PrimitiveSelection::get_index_rpc(
0853     int tp_endcap, int tp_station, int tp_ring, int tp_sector, int tp_subsector, int tp_bx) const {
0854   int selected = -1;
0855 
0856   bool is_native = false;
0857   bool is_neighbor = false;
0858   if (is_in_bx_rpc(tp_bx)) {
0859     if (is_in_sector_rpc(tp_endcap, tp_station, tp_ring, tp_sector, tp_subsector)) {
0860       is_native = true;
0861     } else if (is_in_neighbor_sector_rpc(tp_endcap, tp_station, tp_ring, tp_sector, tp_subsector)) {
0862       is_neighbor = true;
0863     }
0864   }
0865   if (!is_native && !is_neighbor)
0866     return selected;
0867 
0868   // CPPF RX data come in 3 frames x 64 bits, for 7 links. Each 64-bit data
0869   // carry 2 words of 32 bits. Each word carries phi (11 bits) and theta (5 bits)
0870   // of 2 segments (x2).
0871   //
0872   // Firmware uses 'rpc_sub' as RPC subsector index and 'rpc_chm' as RPC chamber index
0873   // rpc_sub [0,6] = RPC subsector 3, 4, 5, 6, 1 from neighbor, 2 from neighbor, 2. They correspond to
0874   //                 CSC sector phi 0-10 deg, 10-20, 20-30, 30-40, 40-50, 50-60, 50-60 from neighbor
0875   // rpc_chm [0,5] = RPC chamber RE1/2, RE2/2, RE3/2, RE3/3, RE4/2, RE4/3
0876   //                 For Phase 2, add RE1/3, RE2/3, RE3/1, RE4/1 -> rpc_chm [0,9]
0877   //
0878   int rpc_sub = -1;
0879   int rpc_chm = -1;
0880 
0881   const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
0882 
0883   if (!is_neighbor) {
0884     if (!is_irpc) {
0885       rpc_sub = ((tp_subsector + 3) % 6);
0886     } else {
0887       rpc_sub = ((tp_subsector + 1) % 3);
0888     }
0889   } else {
0890     rpc_sub = 6;
0891   }
0892 
0893   if (tp_station <= 2 && tp_ring == 2) {  // RE1/2, RE2/2
0894     rpc_chm = (tp_station - 1);
0895   } else if (tp_station >= 3 && tp_ring >= 2) {  // RE3/2, RE3/3, RE4/2, RE4/3
0896     rpc_chm = 2 + (tp_station - 3) * 2 + (tp_ring - 2);
0897   } else if (tp_station <= 2 && tp_ring == 3) {  // RE1/3, RE2/3
0898     rpc_chm = 6 + (tp_station - 1);
0899   } else if (tp_station >= 3 && tp_ring == 1) {  // RE3/1, RE4/1
0900     rpc_chm = 8 + (tp_station - 3);
0901   }
0902 
0903   selected = (rpc_sub * 10) + rpc_chm;
0904   emtf_assert(selected != -1);
0905   return selected;
0906 }
0907 
0908 // _____________________________________________________________________________
0909 // GEM functions
0910 //
0911 // According to what I know at the moment
0912 // - GE1/1: 10 degree chamber, 8 rolls, 384 strips = 192 pads
0913 // - GE2/1: 20 degree chamber, 8 rolls, 768 strips = 384 pads
0914 int PrimitiveSelection::select_gem(const TriggerPrimitive& muon_primitive) const {
0915   int selected = -1;
0916 
0917   if (muon_primitive.subsystem() == L1TMuon::kGEM) {
0918     const GEMDetId& tp_detId = muon_primitive.detId<GEMDetId>();
0919     const GEMData& tp_data = muon_primitive.getGEMData();
0920 
0921     int tp_region = tp_detId.region();  // 0 for Barrel, +/-1 for +/- Endcap
0922     int tp_endcap = (tp_region == -1) ? 2 : tp_region;
0923     int tp_station = tp_detId.station();
0924     int tp_ring = tp_detId.ring();
0925     int tp_roll = tp_detId.roll();
0926     int tp_layer = tp_detId.layer();
0927     int tp_chamber = tp_detId.chamber();
0928 
0929     int tp_bx = tp_data.bx;
0930     int tp_pad = ((tp_data.pad_low + tp_data.pad_hi) / 2);
0931 
0932     int tp_sector = emtf::get_trigger_sector(tp_ring, tp_station, tp_chamber);
0933     int tp_csc_ID = emtf::get_trigger_csc_ID(tp_ring, tp_station, tp_chamber);
0934 
0935     // station 1 --> subsector 1 or 2
0936     // station 2,3,4 --> subsector 0
0937     int tp_subsector = (tp_station != 1) ? 0 : ((tp_chamber % 6 > 2) ? 1 : 2);
0938 
0939     if (endcap_ == 1 && sector_ == 1 && bx_ == -3) {  // do assertion checks only once
0940       emtf_assert(tp_region != 0);
0941       emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
0942       emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
0943       emtf_assert(1 <= tp_station && tp_station <= 2);
0944       emtf_assert(tp_ring == 1);
0945       emtf_assert(1 <= tp_roll && tp_roll <= 8);
0946       emtf_assert(1 <= tp_layer && tp_layer <= 2);
0947       emtf_assert(1 <= tp_csc_ID && tp_csc_ID <= 3);
0948       emtf_assert((tp_station == 1 && 0 <= tp_pad && tp_pad <= 191) || (tp_station != 1));
0949       emtf_assert((tp_station == 2 && 0 <= tp_pad && tp_pad <= 383) || (tp_station != 2));
0950     }
0951 
0952     // Check if the chamber belongs to this sector processor at this BX.
0953     selected = get_index_gem(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_bx);
0954   }
0955   return selected;
0956 }
0957 
0958 bool PrimitiveSelection::is_in_sector_gem(int tp_endcap, int tp_sector) const {
0959   // Identical to the corresponding CSC function
0960   return is_in_sector_csc(tp_endcap, tp_sector);
0961 }
0962 
0963 bool PrimitiveSelection::is_in_neighbor_sector_gem(
0964     int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID) const {
0965   // Identical to the corresponding CSC function
0966   return is_in_neighbor_sector_csc(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID);
0967 }
0968 
0969 bool PrimitiveSelection::is_in_bx_gem(int tp_bx) const {
0970   tp_bx += bxShiftGEM_;
0971   return (bx_ == tp_bx);
0972 }
0973 
0974 int PrimitiveSelection::get_index_gem(
0975     int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const {
0976   int selected = -1;
0977 
0978   bool is_native = false;
0979   bool is_neighbor = false;
0980   if (is_in_bx_gem(tp_bx)) {
0981     if (is_in_sector_gem(tp_endcap, tp_sector)) {
0982       is_native = true;
0983     } else if (is_in_neighbor_sector_gem(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID)) {
0984       is_neighbor = true;
0985     }
0986   }
0987   if (!is_native && !is_neighbor)
0988     return selected;
0989 
0990   if (!is_neighbor) {
0991     if (tp_station == 1) {  // GE1/1: 0 - 5
0992       selected = (tp_subsector - 1) * 3 + (tp_csc_ID - 1);
0993     } else {  // GE2/1: 6 - 8
0994       selected = 6 + (tp_csc_ID - 1);
0995     }
0996 
0997   } else {
0998     if (tp_station == 1) {  // GE1/1n: 12
0999       selected = 12;
1000     } else {  // GE2/1n: 13
1001       selected = 13;
1002     }
1003   }
1004   emtf_assert(selected != -1);
1005   return selected;
1006 }
1007 
1008 // _____________________________________________________________________________
1009 // ME0 functions
1010 //
1011 // According to what I know at the moment
1012 // - ME0: 20 degree chamber, 8 rolls, 384 strips = 192 pads
1013 int PrimitiveSelection::select_me0(const TriggerPrimitive& muon_primitive) const {
1014   int selected = -1;
1015 
1016   if (muon_primitive.subsystem() == L1TMuon::kME0) {
1017     const ME0DetId& tp_detId = muon_primitive.detId<ME0DetId>();
1018     const ME0Data& tp_data = muon_primitive.getME0Data();
1019 
1020     int tp_region = tp_detId.region();  // 0 for Barrel, +/-1 for +/- Endcap
1021     int tp_endcap = (tp_region == -1) ? 2 : tp_region;
1022     int tp_station = tp_detId.station();
1023     int tp_ring = 1;  // tp_detId.ring() does not exist
1024     //int tp_roll      = tp_detId.roll();
1025     //int tp_layer     = tp_detId.layer();
1026     int tp_chamber = tp_detId.chamber();
1027 
1028     int tp_bx = tp_data.bx;
1029     int tp_pad = tp_data.phiposition;
1030     int tp_partition = tp_data.partition;
1031 
1032     // The ME0 geometry is similar to ME2/1, so I use tp_station = 2, tp_ring = 1
1033     // when calling get_trigger_sector() and get_trigger_csc_ID()
1034     int tp_sector = emtf::get_trigger_sector(1, 2, tp_chamber);
1035     int tp_csc_ID = emtf::get_trigger_csc_ID(1, 2, tp_chamber);
1036     int tp_subsector = 0;
1037 
1038     if (endcap_ == 1 && sector_ == 1 && bx_ == -3) {  // do assertion checks only once
1039       emtf_assert(tp_region != 0);
1040       emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
1041       emtf_assert(emtf::MIN_TRIGSECTOR <= tp_sector && tp_sector <= emtf::MAX_TRIGSECTOR);
1042       emtf_assert(tp_station == 1);
1043       emtf_assert(tp_ring == 1);
1044       //emtf_assert(1 <= tp_roll && tp_roll <= 8);    // not set
1045       //emtf_assert(1 <= tp_layer && tp_layer <= 6);  // not set
1046       emtf_assert(1 <= tp_csc_ID && tp_csc_ID <= 3);
1047       emtf_assert(0 <= tp_pad && tp_pad <= 767);
1048       emtf_assert(0 <= tp_partition && tp_partition <= 15);
1049     }
1050 
1051     // Check if the chamber belongs to this sector processor at this BX.
1052     selected = get_index_me0(tp_endcap, tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_pad, tp_bx);
1053   }
1054   return selected;
1055 }
1056 
1057 bool PrimitiveSelection::is_in_sector_me0(int tp_endcap, int tp_sector, int tp_csc_ID, int tp_pad) const {
1058   // Similar to the corresponding CSC function, but requires a 5 deg shift
1059   // because the CSC chamber 1 starts at -5 deg, but the ME0 chamber 1 starts
1060   // at -10 deg.
1061   // This means that in sector 1, CSC chambers cover 15 to 75 deg, but ME0
1062   // chambers cover 10 to 70 deg. 5 deg (1/4 of chamber) needs to be added
1063   // to cover 70 to 75 deg, and 5 deg needs to be subtracted from 10 to 15 deg.
1064   auto get_other_neighbor = [](int sector) { return (sector == 6) ? 1 : sector + 1; };
1065 
1066   bool add5deg = false;
1067   bool sub5deg = false;
1068   if (includeNeighbor_) {
1069     if ((endcap_ == tp_endcap) && (get_other_neighbor(sector_) == tp_sector)) {
1070       if (tp_csc_ID == 1 && tp_endcap == 1 && tp_pad >= (767 - 192)) {  // higher 1/4 of chamber
1071         add5deg = true;
1072       } else if (tp_csc_ID == 1 && tp_endcap == 2 && tp_pad <= 191) {  // lower 1/4 of chamber
1073         add5deg = true;
1074       }
1075     }
1076     if ((endcap_ == tp_endcap) && (sector_ == tp_sector)) {
1077       if (tp_csc_ID == 1 && tp_endcap == 1 && tp_pad >= (767 - 192)) {  // higher 1/4 of chamber
1078         sub5deg = true;
1079       } else if (tp_csc_ID == 1 && tp_endcap == 2 && tp_pad <= 191) {  // lower 1/4 of chamber
1080         sub5deg = true;
1081       }
1082     }
1083   }
1084   return (is_in_sector_csc(tp_endcap, tp_sector) && !sub5deg) || add5deg;
1085 }
1086 
1087 bool PrimitiveSelection::is_in_neighbor_sector_me0(int tp_endcap, int tp_sector, int tp_csc_ID, int tp_pad) const {
1088   // Similar to the corresponding CSC function, but requires a 5 deg shift
1089   // because the CSC chamber 1 starts at -5 deg, but the ME0 chamber 1 starts
1090   // at -10 deg.
1091   // This means that in sector 1, CSC chamber from the neighbor sector
1092   // covers -5 to 15 deg, but ME0 chamber from the neighbor sector covers
1093   // -10 to 10 deg. 5 deg (1/4 of chamber) needs to be subtracted from
1094   // -10 to -5 deg, and 5 deg needs to be added to cover 10 to 15 deg.
1095   auto get_neighbor = [](int sector) { return (sector == 1) ? 6 : sector - 1; };
1096 
1097   bool add5deg = false;
1098   bool sub5deg = false;
1099   if (includeNeighbor_) {
1100     if ((endcap_ == tp_endcap) && (get_neighbor(sector_) == tp_sector)) {
1101       if (tp_csc_ID == 3 && tp_endcap == 1 && tp_pad >= (767 - 192)) {  // higher 1/4 of chamber
1102         sub5deg = true;
1103       } else if (tp_csc_ID == 3 && tp_endcap == 2 && tp_pad <= 191) {  // lower 1/4 of chamber
1104         sub5deg = true;
1105       }
1106     }
1107     if ((endcap_ == tp_endcap) && (sector_ == tp_sector)) {
1108       if (tp_csc_ID == 1 && tp_endcap == 1 && tp_pad >= (767 - 192)) {  // higher 1/4 of chamber
1109         add5deg = true;
1110       } else if (tp_csc_ID == 1 && tp_endcap == 2 && tp_pad <= 191) {  // lower 1/4 of chamber
1111         add5deg = true;
1112       }
1113     }
1114   }
1115   // (Note: use tp_subsector = 0, tp_station = 2)
1116   return (is_in_neighbor_sector_csc(tp_endcap, tp_sector, 0, 2, tp_csc_ID) && !sub5deg) || add5deg;
1117 }
1118 
1119 bool PrimitiveSelection::is_in_bx_me0(int tp_bx) const {
1120   tp_bx += bxShiftME0_;
1121   return (bx_ == tp_bx);
1122 }
1123 
1124 int PrimitiveSelection::get_index_me0(
1125     int tp_endcap, int tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_pad, int tp_bx) const {
1126   int selected = -1;
1127 
1128   bool is_native = false;
1129   bool is_neighbor = false;
1130   if (is_in_bx_me0(tp_bx)) {
1131     if (is_in_sector_me0(tp_endcap, tp_sector, tp_csc_ID, tp_pad)) {
1132       is_native = true;
1133     } else if (is_in_neighbor_sector_me0(tp_endcap, tp_sector, tp_csc_ID, tp_pad)) {
1134       is_neighbor = true;
1135     }
1136   }
1137   if (!is_native && !is_neighbor)
1138     return selected;
1139 
1140   if (!is_neighbor) {  // ME0: 9 - 11
1141     selected = 9 + (tp_csc_ID - 1);
1142   } else {  // ME0n: 14
1143     selected = 14;
1144   }
1145   emtf_assert(selected != -1);
1146   return selected;
1147 }
1148 
1149 // _____________________________________________________________________________
1150 // DT functions
1151 int PrimitiveSelection::select_dt(const TriggerPrimitive& muon_primitive) const {
1152   int selected = -1;
1153 
1154   if (muon_primitive.subsystem() == L1TMuon::kDT) {
1155     const DTChamberId& tp_detId = muon_primitive.detId<DTChamberId>();
1156     const DTData& tp_data = muon_primitive.getDTData();
1157 
1158     int tp_wheel = tp_detId.wheel();
1159     int tp_station = tp_detId.station();
1160     int tp_sector = tp_detId.sector();  // sectors are 1-12, starting at phi=0 and increasing with phi
1161 
1162     // In station 4, where the top and bottom sectors are made of two chambers,
1163     // two additional sector numbers are used, 13 (after sector 4, top)
1164     // and 14 (after sector 10, bottom).
1165     if (tp_station == 4) {
1166       if (tp_sector == 13)
1167         tp_sector = 4;
1168       else if (tp_sector == 14)
1169         tp_sector = 10;
1170     }
1171 
1172     int tp_bx = tp_data.bx;
1173     int tp_phi = tp_data.radialAngle;
1174     //int tp_phiB      = tp_data.bendingAngle;
1175 
1176     // Mimic 10 deg CSC chamber. I use tp_station = 2, tp_ring = 2
1177     // when calling get_trigger_sector() and get_trigger_csc_ID()
1178     int tp_chamber =
1179         tp_sector * 3 - 1;  // DT chambers are 30 deg. Multiply sector number by 3 to mimic 10 deg CSC chamber number
1180     int tp_endcap = (tp_wheel > 0) ? 1 : ((tp_wheel < 0) ? 2 : 0);
1181     int csc_tp_sector = emtf::get_trigger_sector(2, 2, tp_chamber);
1182     int tp_csc_ID = emtf::get_trigger_csc_ID(2, 2, tp_chamber);
1183     int tp_subsector = 0;
1184 
1185     if (endcap_ == 1 && sector_ == 1 && bx_ == -3) {  // do assertion checks only once
1186       //emtf_assert(-2 <= tp_wheel && tp_wheel <= +2);
1187       emtf_assert(tp_wheel == -2 || tp_wheel == +2);  // do not include wheels -1, 0, +1
1188       //emtf_assert(1 <= tp_station && tp_station <= 4);
1189       emtf_assert(1 <= tp_station && tp_station <= 3);  // do not include MB4
1190       emtf_assert(1 <= tp_sector && tp_sector <= 12);
1191       emtf_assert(emtf::MIN_ENDCAP <= tp_endcap && tp_endcap <= emtf::MAX_ENDCAP);
1192       emtf_assert(emtf::MIN_TRIGSECTOR <= csc_tp_sector && csc_tp_sector <= emtf::MAX_TRIGSECTOR);
1193       //emtf_assert(4 <= tp_csc_ID && tp_csc_ID <= 9);
1194       emtf_assert(tp_csc_ID == 6 || tp_csc_ID == 9);
1195       emtf_assert(-2048 <= tp_phi && tp_phi <= 2047);  // 12-bit
1196       //emtf_assert(-512 <= tp_phiB && tp_phiB <= 511);  // 10-bit
1197     }
1198 
1199     // Check if the chamber belongs to this sector processor at this BX.
1200     selected = get_index_dt(tp_endcap, csc_tp_sector, tp_subsector, tp_station, tp_csc_ID, tp_bx);
1201   }
1202   return selected;
1203 }
1204 
1205 bool PrimitiveSelection::is_in_sector_dt(int tp_endcap, int tp_sector) const {
1206   // Identical to the corresponding CSC function
1207   return is_in_sector_csc(tp_endcap, tp_sector);
1208 }
1209 
1210 bool PrimitiveSelection::is_in_neighbor_sector_dt(int tp_endcap, int tp_sector, int tp_csc_ID) const {
1211   // Identical to the corresponding CSC function
1212   // (Note: use tp_subsector = 0, tp_station = 2)
1213   return is_in_neighbor_sector_csc(tp_endcap, tp_sector, 0, 2, tp_csc_ID);
1214 }
1215 
1216 bool PrimitiveSelection::is_in_bx_dt(int tp_bx) const {
1217   //tp_bx += bxShiftDT_;
1218   return (bx_ == tp_bx);
1219 }
1220 
1221 int PrimitiveSelection::get_index_dt(
1222     int tp_endcap, int csc_tp_sector, int tp_subsector, int tp_station, int tp_csc_ID, int tp_bx) const {
1223   int selected = -1;
1224 
1225   bool is_native = false;
1226   bool is_neighbor = false;
1227   if (is_in_bx_dt(tp_bx)) {
1228     if (is_in_sector_dt(tp_endcap, csc_tp_sector)) {
1229       is_native = true;
1230     } else if (is_in_neighbor_sector_dt(tp_endcap, csc_tp_sector, tp_csc_ID)) {
1231       is_neighbor = true;
1232     }
1233   }
1234   if (!is_native && !is_neighbor)
1235     return selected;
1236 
1237   if (!is_neighbor) {                                       // MB1,2,3,4: 0-7
1238     selected = (tp_station - 1) * 2 + (tp_csc_ID - 6) / 3;  // tp_csc_ID should be either 6 or 9
1239   } else {                                                  // ME1,2,3,4n: 8-11
1240     selected = 8 + (tp_station - 1);
1241   }
1242   emtf_assert(selected != -1);
1243   return selected;
1244 }