Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:20:57

0001 #include "L1Trigger/L1TMuonEndCap/interface/PrimitiveConversion.h"
0002 #include "DataFormats/L1TMuon/interface/L1TMuonSubsystems.h"
0003 #include "L1Trigger/L1TMuonEndCap/interface/SectorProcessorLUT.h"
0004 
0005 #include "Geometry/RPCGeometry/interface/RPCGeometry.h"  // for special treatments for iRPC
0006 
0007 void PrimitiveConversion::configure(const GeometryTranslator* tp_geom,
0008                                     const SectorProcessorLUT* pc_lut,
0009                                     int verbose,
0010                                     int endcap,
0011                                     int sector,
0012                                     int bx,
0013                                     int bxShiftCSC,
0014                                     int bxShiftRPC,
0015                                     int bxShiftGEM,
0016                                     int bxShiftME0,
0017                                     const std::vector<int>& zoneBoundaries,
0018                                     int zoneOverlap,
0019                                     bool duplicateTheta,
0020                                     bool fixZonePhi,
0021                                     bool useNewZones,
0022                                     bool fixME11Edges,
0023                                     bool bugME11Dupes,
0024                                     bool useRun3CCLUT_OTMB,
0025                                     bool useRun3CCLUT_TMB) {
0026   emtf_assert(tp_geom != nullptr);
0027   emtf_assert(pc_lut != nullptr);
0028 
0029   tp_geom_ = tp_geom;
0030   pc_lut_ = pc_lut;
0031 
0032   verbose_ = verbose;
0033   endcap_ = endcap;  // 1 for ME+, 2 for ME-
0034   sector_ = sector;
0035   bx_ = bx;
0036 
0037   bxShiftCSC_ = bxShiftCSC;
0038   bxShiftRPC_ = bxShiftRPC;
0039   bxShiftGEM_ = bxShiftGEM;
0040   bxShiftME0_ = bxShiftME0;
0041 
0042   zoneBoundaries_ = zoneBoundaries;
0043   zoneOverlap_ = zoneOverlap;
0044   duplicateTheta_ = duplicateTheta;
0045   fixZonePhi_ = fixZonePhi;
0046   useNewZones_ = useNewZones;
0047   fixME11Edges_ = fixME11Edges;
0048   bugME11Dupes_ = bugME11Dupes;
0049 
0050   // Run 3 CCLUT algorithm
0051   useRun3CCLUT_OTMB_ = useRun3CCLUT_OTMB;
0052   useRun3CCLUT_TMB_ = useRun3CCLUT_TMB;
0053 }
0054 
0055 void PrimitiveConversion::process(const std::map<int, TriggerPrimitiveCollection>& selected_prim_map,
0056                                   EMTFHitCollection& conv_hits) const {
0057   std::map<int, TriggerPrimitiveCollection>::const_iterator map_tp_it = selected_prim_map.begin();
0058   std::map<int, TriggerPrimitiveCollection>::const_iterator map_tp_end = selected_prim_map.end();
0059 
0060   for (; map_tp_it != map_tp_end; ++map_tp_it) {
0061     // Unique chamber ID in FW, {0, 53} as defined in get_index_csc in src/PrimitiveSelection.cc
0062     int selected = map_tp_it->first;
0063     // "Primitive Conversion" sector/station/chamber ID scheme used in FW
0064     int pc_sector = sector_;
0065     int pc_station = selected / 9;  // {0, 5} = {ME1 sub 1, ME1 sub 2, ME2, ME3, ME4, neighbor}
0066     int pc_chamber = selected % 9;  // Equals CSC ID - 1 for all except neighbor chambers
0067     int pc_segment = 0;             // Counts hits in a single chamber
0068 
0069     TriggerPrimitiveCollection::const_iterator tp_it = map_tp_it->second.begin();
0070     TriggerPrimitiveCollection::const_iterator tp_end = map_tp_it->second.end();
0071 
0072     for (; tp_it != tp_end; ++tp_it) {
0073       EMTFHit conv_hit;
0074       if (tp_it->subsystem() == L1TMuon::kCSC) {
0075         convert_csc(pc_sector, pc_station, pc_chamber, pc_segment, *tp_it, conv_hit);
0076       } else if (tp_it->subsystem() == L1TMuon::kRPC) {
0077         convert_rpc(pc_sector, pc_station, pc_chamber, pc_segment, *tp_it, conv_hit);
0078       } else if (tp_it->subsystem() == L1TMuon::kGEM) {
0079         convert_gem(pc_sector, 0, selected, pc_segment, *tp_it, conv_hit);  // pc_station and pc_chamber are meaningless
0080       } else if (tp_it->subsystem() == L1TMuon::kME0) {
0081         convert_me0(pc_sector, 0, selected, pc_segment, *tp_it, conv_hit);  // pc_station and pc_chamber are meaningless
0082       } else if (tp_it->subsystem() == L1TMuon::kDT) {
0083         convert_dt(pc_sector, 0, selected, pc_segment, *tp_it, conv_hit);  // pc_station and pc_chamber are meaningless
0084       } else {
0085         emtf_assert(false && "Incorrect subsystem type");
0086       }
0087       conv_hits.push_back(conv_hit);
0088       pc_segment += 1;
0089     }
0090   }
0091 }
0092 
0093 // _____________________________________________________________________________
0094 // CSC functions
0095 void PrimitiveConversion::convert_csc(int pc_sector,
0096                                       int pc_station,
0097                                       int pc_chamber,
0098                                       int pc_segment,
0099                                       const TriggerPrimitive& muon_primitive,
0100                                       EMTFHit& conv_hit) const {
0101   const CSCDetId& tp_detId = muon_primitive.detId<CSCDetId>();
0102   const CSCData& tp_data = muon_primitive.getCSCData();
0103 
0104   int tp_endcap = tp_detId.endcap();
0105   int tp_sector = tp_detId.triggerSector();
0106   int tp_station = tp_detId.station();
0107   int tp_ring = tp_detId.ring();
0108   int tp_chamber = tp_detId.chamber();
0109 
0110   int tp_bx = tp_data.bx;
0111   int tp_csc_ID = tp_data.cscID;
0112 
0113   // station 1 --> subsector 1 or 2
0114   // station 2,3,4 --> subsector 0
0115   int tp_subsector = (tp_station != 1) ? 0 : ((tp_chamber % 6 > 2) ? 1 : 2);
0116 
0117   const bool is_neighbor = (pc_station == 5);
0118 
0119   int csc_nID = tp_csc_ID;  // modify csc_ID if coming from neighbor sector
0120   if (is_neighbor) {
0121     // station 1 has 3 neighbor chambers: 13,14,15 in rings 1,2,3
0122     // (where are chambers 10,11,12 in station 1? they were used to label ME1/1a, but not anymore)
0123     // station 2,3,4 have 2 neighbor chambers: 10,11 in rings 1,2
0124     csc_nID = (pc_chamber < 3) ? (pc_chamber + 12) : (((pc_chamber - 1) % 2) + 9);
0125     csc_nID += 1;
0126 
0127     if (tp_station == 1) {  // neighbor ME1
0128       emtf_assert(tp_subsector == 2);
0129     }
0130   }
0131 
0132   // Set properties
0133   conv_hit.SetCSCDetId(tp_detId);
0134 
0135   conv_hit.set_bx(tp_bx + bxShiftCSC_);
0136   conv_hit.set_subsystem(L1TMuon::kCSC);
0137   conv_hit.set_endcap((tp_endcap == 2) ? -1 : tp_endcap);
0138   conv_hit.set_station(tp_station);
0139   conv_hit.set_ring(tp_ring);
0140   //conv_hit.set_roll          ( tp_roll );
0141   conv_hit.set_chamber(tp_chamber);
0142   conv_hit.set_sector(tp_sector);
0143   conv_hit.set_subsector(tp_subsector);
0144   conv_hit.set_csc_ID(tp_csc_ID);
0145   conv_hit.set_csc_nID(csc_nID);
0146   conv_hit.set_track_num(tp_data.trknmb);
0147   conv_hit.set_sync_err(tp_data.syncErr);
0148   //conv_hit.set_sector_RPC    ( tp_sector );
0149   //conv_hit.set_subsector_RPC ( tp_subsector );
0150 
0151   conv_hit.set_pc_sector(pc_sector);
0152   conv_hit.set_pc_station(pc_station);
0153   conv_hit.set_pc_chamber(pc_chamber);
0154   conv_hit.set_pc_segment(pc_segment);
0155 
0156   conv_hit.set_valid(tp_data.valid);
0157   conv_hit.set_strip(tp_data.strip);
0158   //conv_hit.set_strip_low     ( tp_data.strip_low );
0159   //conv_hit.set_strip_hi      ( tp_data.strip_hi );
0160   conv_hit.set_wire(tp_data.keywire);
0161   conv_hit.set_quality(tp_data.quality);
0162 
0163   // Calculate Pattern
0164   unsigned pattern = tp_data.pattern;
0165   const auto& detid(conv_hit.CreateCSCDetId());
0166   const bool isOTMB(detid.isME11() or detid.isME21() or detid.isME31() or detid.isME41());
0167   const bool isTMB((detid.isME12() or detid.isME22() or detid.isME32() or detid.isME42()) or (detid.isME13()));
0168 
0169   // check if CCLUT is on for this CSC TP
0170   const bool useRun3CCLUT((useRun3CCLUT_OTMB_ and isOTMB) or (useRun3CCLUT_TMB_ and isTMB));
0171   if (useRun3CCLUT) {
0172     // convert slope to Run-2 pattern for CSC TPs coming from MEX/1 chambers
0173     // where the CCLUT algorithm is enabled
0174     const unsigned slopeList[32] = {10, 10, 10, 8, 8, 8, 6, 6, 6, 4, 4, 4, 2, 2, 2, 2,
0175                                     10, 10, 10, 9, 9, 9, 7, 7, 7, 5, 5, 5, 3, 3, 3, 3};
0176 
0177     // this LUT follows the same convention as in CSCPatternBank.cc
0178     unsigned slope_and_sign(tp_data.slope);
0179     if (tp_data.bend == 1) {
0180       slope_and_sign += 16;
0181     }
0182     unsigned run2_converted_PID = slopeList[slope_and_sign];
0183     pattern = run2_converted_PID;
0184   }
0185 
0186   conv_hit.set_pattern(pattern);
0187   conv_hit.set_bend(tp_data.bend);
0188   conv_hit.set_time(0.);  // No fine resolution timing
0189   conv_hit.set_alct_quality(tp_data.alct_quality);
0190   conv_hit.set_clct_quality(tp_data.clct_quality);
0191   // Run-3
0192   conv_hit.set_strip_quart(tp_data.strip_quart);
0193   conv_hit.set_strip_eighth(tp_data.strip_eighth);
0194   conv_hit.set_strip_quart_bit(tp_data.strip_quart_bit);
0195   conv_hit.set_strip_eighth_bit(tp_data.strip_eighth_bit);
0196   conv_hit.set_pattern_run3(tp_data.pattern_run3);
0197   conv_hit.set_slope(tp_data.slope);
0198 
0199   conv_hit.set_neighbor(is_neighbor);
0200   conv_hit.set_sector_idx((endcap_ == 1) ? sector_ - 1 : sector_ + 5);
0201 
0202   convert_csc_details(conv_hit);
0203 
0204   // Add coordinates from fullsim
0205   {
0206     const GlobalPoint& gp = tp_geom_->getGlobalPoint(muon_primitive);
0207     double glob_phi = emtf::rad_to_deg(gp.phi().value());
0208     double glob_theta = emtf::rad_to_deg(gp.theta());
0209     double glob_eta = gp.eta();
0210     double glob_rho = gp.perp();
0211     double glob_z = gp.z();
0212 
0213     conv_hit.set_phi_sim(glob_phi);
0214     conv_hit.set_theta_sim(glob_theta);
0215     conv_hit.set_eta_sim(glob_eta);
0216     conv_hit.set_rho_sim(glob_rho);
0217     conv_hit.set_z_sim(glob_z);
0218   }
0219 }
0220 
0221 void PrimitiveConversion::convert_csc_details(EMTFHit& conv_hit) const {
0222   const bool is_neighbor = conv_hit.Neighbor();
0223 
0224   // Defined as in firmware
0225   // endcap : 0-1 for ME+,ME-
0226   // sector : 0-5
0227   // station: 0-4 for st1 sub1 or st1 sub2 from neighbor, st1 sub2, st2, st3, st4
0228   // cscid  : 0-14 (excluding 11), including neighbors
0229   const int fw_endcap = (endcap_ - 1);
0230   const int fw_sector = (sector_ - 1);
0231   const int fw_station =
0232       (conv_hit.Station() == 1) ? (is_neighbor ? 0 : (conv_hit.Subsector() - 1)) : conv_hit.Station();
0233   const int fw_cscid = (conv_hit.CSC_nID() - 1);
0234   const int fw_strip = conv_hit.Strip();  // it is half-strip, despite the name
0235   const int fw_wire = conv_hit.Wire();    // it is wiregroup, despite the name
0236 
0237   // Primitive converter unit
0238   // station: 0-5 for st1 sub1, st1 sub2, st2, st3, st4, neigh all st*
0239   // chamber: 0-8
0240   const int pc_station = conv_hit.PC_station();
0241   const int pc_chamber = conv_hit.PC_chamber();
0242   const int pc_segment = conv_hit.PC_segment();
0243 
0244   const bool is_me11a = (conv_hit.Station() == 1 && conv_hit.Ring() == 4);
0245   const bool is_me11b = (conv_hit.Station() == 1 && conv_hit.Ring() == 1);
0246   const bool is_me13 = (conv_hit.Station() == 1 && conv_hit.Ring() == 3);
0247 
0248   // Is this chamber mounted in reverse direction?
0249   // (i.e., phi vs. strip number is reversed)
0250   bool ph_reverse = false;
0251   if ((fw_endcap == 0 && fw_station >= 3) || (fw_endcap == 1 && fw_station < 3))  // ME+3, ME+4, ME-1, ME-2
0252     ph_reverse = true;
0253 
0254   // Chamber coverage if phi_reverse = true
0255   int ph_coverage = 0;  // Offset for coordinate conversion
0256   if (ph_reverse) {
0257     if (fw_station <= 1 && ((fw_cscid >= 6 && fw_cscid <= 8) || fw_cscid == 14))  // ME1/3
0258       ph_coverage = 15;
0259     else if (fw_station >= 2 && (fw_cscid <= 2 || fw_cscid == 9))  // ME2,3,4/1
0260       ph_coverage = 40;
0261     else  // all others
0262       ph_coverage = 20;
0263   }
0264 
0265   // Is this 10-deg or 20-deg chamber?
0266   bool is_10degree = false;
0267   if ((fw_station <= 1) ||                                                       // ME1
0268       (fw_station >= 2 && ((fw_cscid >= 3 && fw_cscid <= 8) || fw_cscid == 10))  // ME2,3,4/2
0269   ) {
0270     is_10degree = true;
0271   }
0272 
0273   // LUT index
0274   // There are 54 CSC chambers including the neighbors in a sector, but 61 LUT indices
0275   // This comes from dividing the 6 chambers + 1 neighbor in ME1/1 into ME1/1a and ME1/1b
0276   int pc_lut_id = pc_chamber;
0277   if (pc_station == 0) {  // ME1 sub 1: 0 - 11
0278     pc_lut_id = is_me11a ? pc_lut_id + 9 : pc_lut_id;
0279   } else if (pc_station == 1) {  // ME1 sub 2: 16 - 27
0280     pc_lut_id += 16;
0281     pc_lut_id = is_me11a ? pc_lut_id + 9 : pc_lut_id;
0282   } else if (pc_station == 2) {  // ME2: 28 - 36
0283     pc_lut_id += 28;
0284   } else if (pc_station == 3) {  // ME3: 39 - 47
0285     pc_lut_id += 39;
0286   } else if (pc_station == 4) {  // ME4 : 50 - 58
0287     pc_lut_id += 50;
0288   } else if (pc_station == 5 && pc_chamber < 3) {  // neighbor ME1: 12 - 15
0289     pc_lut_id = is_me11a ? pc_lut_id + 15 : pc_lut_id + 12;
0290   } else if (pc_station == 5 && pc_chamber < 5) {  // neighbor ME2: 37 - 38
0291     pc_lut_id += 28 + 9 - 3;
0292   } else if (pc_station == 5 && pc_chamber < 7) {  // neighbor ME3: 48 - 49
0293     pc_lut_id += 39 + 9 - 5;
0294   } else if (pc_station == 5 && pc_chamber < 9) {  // neighbor ME4: 59 - 60
0295     pc_lut_id += 50 + 9 - 7;
0296   }
0297   emtf_assert(pc_lut_id < 61);
0298 
0299   if (verbose_ > 1) {  // debug
0300     std::cout << "pc_station: " << pc_station << " pc_chamber: " << pc_chamber << " fw_station: " << fw_station
0301               << " fw_cscid: " << fw_cscid << " lut_id: " << pc_lut_id
0302               << " ph_init: " << pc_lut().get_ph_init(fw_endcap, fw_sector, pc_lut_id)
0303               << " ph_disp: " << pc_lut().get_ph_disp(fw_endcap, fw_sector, pc_lut_id)
0304               << " th_init: " << pc_lut().get_th_init(fw_endcap, fw_sector, pc_lut_id)
0305               << " th_disp: " << pc_lut().get_th_disp(fw_endcap, fw_sector, pc_lut_id)
0306               << " ph_init_hard: " << pc_lut().get_ph_init_hard(fw_station, fw_cscid) << std::endl;
0307   }
0308 
0309   // ___________________________________________________________________________
0310   // phi conversion
0311 
0312   // Convert half-strip into 1/8-strip
0313   int eighth_strip = 0;
0314 
0315   // Apply phi correction from CLCT pattern number (from src/SectorProcessorLUT.cc)
0316   int clct_pat_corr = pc_lut().get_ph_patt_corr(conv_hit.Pattern());
0317   int clct_pat_corr_sign = (pc_lut().get_ph_patt_corr_sign(conv_hit.Pattern()) == 0) ? 1 : -1;
0318 
0319   // At strip number 0, protect against negative correction
0320   bool bugStrip0BeforeFW48200 = false;
0321   if (bugStrip0BeforeFW48200 == false && fw_strip == 0 && clct_pat_corr_sign == -1)
0322     clct_pat_corr = 0;
0323 
0324   // check if the CCLUT algorithm is on in this chamber
0325   const auto& detid(conv_hit.CreateCSCDetId());
0326   const bool isOTMB(detid.isME11() or detid.isME21() or detid.isME31() or detid.isME41());
0327   const bool isTMB((detid.isME12() or detid.isME22() or detid.isME32() or detid.isME42()) or (detid.isME13()));
0328 
0329   const bool useRun3CCLUT((useRun3CCLUT_OTMB_ and isOTMB) or (useRun3CCLUT_TMB_ and isTMB));
0330 
0331   if (is_10degree) {
0332     eighth_strip = fw_strip << 2;  // full precision, uses only 2 bits of pattern correction
0333     if (useRun3CCLUT) {
0334       eighth_strip += (conv_hit.Strip_quart_bit() << 1 | conv_hit.Strip_eighth_bit() << 0);  // Run 3 CCLUT variables
0335     } else {
0336       eighth_strip += clct_pat_corr_sign * (clct_pat_corr >> 1);
0337     }
0338   } else {
0339     eighth_strip = fw_strip << 3;  // multiply by 2, uses all 3 bits of pattern correction
0340     if (useRun3CCLUT) {
0341       eighth_strip += (conv_hit.Strip_quart_bit() << 2 | conv_hit.Strip_eighth_bit() << 1);  // Run 3 CCLUT variables
0342     } else {
0343       eighth_strip += clct_pat_corr_sign * (clct_pat_corr >> 0);
0344     }
0345   }
0346   emtf_assert(bugStrip0BeforeFW48200 == true || eighth_strip >= 0);
0347 
0348   // Multiplicative factor for eighth_strip
0349   // +----------------------------+-------------+------------------+
0350   // | Chamber type               | Strip angle | Mult factor      |
0351   // |                            | (deg)       |                  |
0352   // +----------------------------+-------------+------------------+
0353   // | ME1/2, ME2/2, ME3/2, ME4/2 | 0.1333      | 1/2 (remove LSB) |
0354   // | ME2/1, ME3/1, ME4/1        | 0.2666      | 1 (no op)        |
0355   // | ME1/1a                     | 0.2222      | 0.8335           |
0356   // | ME1/1b                     | 0.1695      | 0.636            |
0357   // | ME1/3                      | 0.1233      | 0.4625           |
0358   // +----------------------------+-------------+------------------+
0359 
0360   int factor = 1024;
0361   if (is_me11a)
0362     factor = 1707;  // ME1/1a
0363   else if (is_me11b)
0364     factor = 1301;  // ME1/1b
0365   else if (is_me13)
0366     factor = 947;  // ME1/3
0367 
0368   // ph_tmp is full-precision phi, but local to chamber (counted from strip 0)
0369   // full phi precision: ( 1/60) deg (1/8-strip)
0370   // zone phi precision: (32/60) deg (4-strip, 32 times coarser than full phi precision)
0371   int ph_tmp = (eighth_strip * factor) >> 10;
0372   int ph_tmp_sign = (ph_reverse == 0) ? 1 : -1;
0373 
0374   int fph = pc_lut().get_ph_init(fw_endcap, fw_sector, pc_lut_id);
0375   fph = fph + ph_tmp_sign * ph_tmp;
0376 
0377   int ph_hit = pc_lut().get_ph_disp(fw_endcap, fw_sector, pc_lut_id);
0378   ph_hit = (ph_hit >> 1) + ph_tmp_sign * (ph_tmp >> 5) + ph_coverage;
0379 
0380   // Full phi +16 to put the rounded value into the middle of error range
0381   // Divide full phi by 32, subtract chamber start
0382   int ph_hit_fixed = -1 * pc_lut().get_ph_init_hard(fw_station, fw_cscid);
0383   ph_hit_fixed = ph_hit_fixed + ((fph + (1 << 4)) >> 5);
0384 
0385   if (fixZonePhi_)
0386     ph_hit = ph_hit_fixed;
0387 
0388   // Zone phi
0389   int zone_hit = pc_lut().get_ph_zone_offset(pc_station, pc_chamber);
0390   zone_hit += ph_hit;
0391 
0392   int zone_hit_fixed = pc_lut().get_ph_init_hard(fw_station, fw_cscid);
0393   zone_hit_fixed += ph_hit_fixed;
0394   // Since ph_hit_fixed = ((fph + (1<<4)) >> 5) - pc_lut().get_ph_init_hard(), the following is equivalent:
0395   //zone_hit_fixed = ((fph + (1<<4)) >> 5);
0396 
0397   if (fixZonePhi_)
0398     zone_hit = zone_hit_fixed;
0399 
0400   emtf_assert(0 <= fph && fph < 5000);
0401   emtf_assert(0 <= zone_hit && zone_hit < 192);
0402 
0403   // ___________________________________________________________________________
0404   // theta conversion
0405 
0406   // th_tmp is theta local to chamber
0407   int pc_wire_id = (fw_wire & 0x7f);  // 7-bit
0408   int th_tmp = pc_lut().get_th_lut(fw_endcap, fw_sector, pc_lut_id, pc_wire_id);
0409 
0410   // For ME1/1 with tilted wires, add theta correction as a function of (wire,strip) index
0411   if (!fixME11Edges_ && (is_me11a || is_me11b)) {
0412     int pc_wire_strip_id =
0413         (((fw_wire >> 4) & 0x3) << 5) | ((eighth_strip >> 4) & 0x1f);  // 2-bit from wire, 5-bit from 2-strip
0414 
0415     // Only affect runs before FW changeset 47114 is applied
0416     // e.g. Run 281707 and earlier
0417     if (bugME11Dupes_) {
0418       bool bugME11DupesBeforeFW47114 = false;
0419       if (bugME11DupesBeforeFW47114) {
0420         if (pc_segment == 1) {
0421           pc_wire_strip_id = (((fw_wire >> 4) & 0x3) << 5) | (0);  // 2-bit from wire, 5-bit from 2-strip
0422         }
0423       }
0424     }
0425 
0426     int th_corr = pc_lut().get_th_corr_lut(fw_endcap, fw_sector, pc_lut_id, pc_wire_strip_id);
0427     int th_corr_sign = (ph_reverse == 0) ? 1 : -1;
0428 
0429     th_tmp = th_tmp + th_corr_sign * th_corr;
0430 
0431     // Check that correction did not make invalid value outside chamber coverage
0432     const int th_negative = 50;
0433     const int th_coverage = 45;
0434     if (th_tmp > th_negative || th_tmp < 0 || fw_wire == 0)
0435       th_tmp = 0;  // limit at the bottom
0436     if (th_tmp > th_coverage)
0437       th_tmp = th_coverage;  // limit at the top
0438 
0439   } else if (fixME11Edges_ && (is_me11a || is_me11b)) {
0440     int pc_wire_strip_id =
0441         (((fw_wire >> 4) & 0x3) << 5) | ((eighth_strip >> 4) & 0x1f);  // 2-bit from wire, 5-bit from 2-strip
0442     if (is_me11a)
0443       pc_wire_strip_id = (((fw_wire >> 4) & 0x3) << 5) | ((((eighth_strip * 341) >> 8) >> 4) &
0444                                                           0x1f);  // correct for ME1/1a strip number (341/256 =~ 1.333)
0445     int th_corr = pc_lut().get_th_corr_lut(fw_endcap, fw_sector, pc_lut_id, pc_wire_strip_id);
0446 
0447     th_tmp = th_tmp + th_corr;
0448 
0449     // Check that correction did not make invalid value outside chamber coverage
0450     const int th_coverage = 46;  // max coverage for front chamber is 47, max coverage for rear chamber is 45
0451     if (fw_wire == 0)
0452       th_tmp = 0;  // limit at the bottom
0453     if (th_tmp > th_coverage)
0454       th_tmp = th_coverage;  // limit at the top
0455   }
0456 
0457   // theta precision: (36.5/128) deg
0458   // theta starts at 8.5 deg: {1, 127} <--> {8.785, 44.715}
0459   int th = pc_lut().get_th_init(fw_endcap, fw_sector, pc_lut_id);
0460   th = th + th_tmp;
0461 
0462   emtf_assert(0 <= th && th < 128);
0463   th = (th == 0) ? 1 : th;  // protect against invalid value
0464 
0465   // ___________________________________________________________________________
0466   // Zone codes and other segment IDs
0467 
0468   //int zone_hit     = ((fph + (1<<4)) >> 5);
0469   int zone_code = get_zone_code(conv_hit, th);
0470   //int phzvl        = get_phzvl(conv_hit, zone_code);
0471 
0472   int fs_zone_code = get_fs_zone_code(conv_hit);
0473   int fs_segment = get_fs_segment(conv_hit, fw_station, fw_cscid, pc_segment);
0474 
0475   int bt_station = get_bt_station(conv_hit, fw_station, fw_cscid, pc_segment);
0476   int bt_segment = get_bt_segment(conv_hit, fw_station, fw_cscid, pc_segment);
0477 
0478   // ___________________________________________________________________________
0479   // Output
0480 
0481   conv_hit.set_phi_fp(fph);   // Full-precision integer phi
0482   conv_hit.set_theta_fp(th);  // Full-precision integer theta
0483   //conv_hit.set_phzvl      ( phzvl );      // Local zone word: (1*low) + (2*mid) + (4*low) - used in FW debugging
0484   //conv_hit.set_ph_hit     ( ph_hit );     // Intermediate quantity in phi calculation - used in FW debugging
0485   conv_hit.set_zone_hit(zone_hit);    // Phi value for building patterns (0.53333 deg precision)
0486   conv_hit.set_zone_code(zone_code);  // Full zone word: 1*(zone 0) + 2*(zone 1) + 4*(zone 2) + 8*(zone 3)
0487 
0488   conv_hit.set_fs_segment(fs_segment);      // Segment number used in primitive matching
0489   conv_hit.set_fs_zone_code(fs_zone_code);  // Zone word used in primitive matching
0490 
0491   conv_hit.set_bt_station(bt_station);
0492   conv_hit.set_bt_segment(bt_segment);
0493 
0494   conv_hit.set_phi_loc(emtf::calc_phi_loc_deg(fph));
0495   conv_hit.set_phi_glob(emtf::calc_phi_glob_deg(conv_hit.Phi_loc(), conv_hit.PC_sector()));
0496   conv_hit.set_theta(emtf::calc_theta_deg_from_int(th));
0497   conv_hit.set_eta(emtf::calc_eta_from_theta_deg(conv_hit.Theta(), conv_hit.Endcap()));
0498 }
0499 
0500 // _____________________________________________________________________________
0501 // RPC functions
0502 void PrimitiveConversion::convert_rpc(int pc_sector,
0503                                       int pc_station,
0504                                       int pc_chamber,
0505                                       int pc_segment,
0506                                       const TriggerPrimitive& muon_primitive,
0507                                       EMTFHit& conv_hit) const {
0508   const RPCDetId& tp_detId = muon_primitive.detId<RPCDetId>();
0509   const RPCData& tp_data = muon_primitive.getRPCData();
0510 
0511   int tp_region = tp_detId.region();  // 0 for Barrel, +/-1 for +/- Endcap
0512   int tp_endcap = (tp_region == -1) ? 2 : tp_region;
0513   int tp_sector = tp_detId.sector();        // 1 - 6 (60 degrees in phi, sector 1 begins at -5 deg)
0514   int tp_subsector = tp_detId.subsector();  // 1 - 6 (10 degrees in phi; staggered in z)
0515   int tp_station = tp_detId.station();      // 1 - 4
0516   int tp_ring = tp_detId.ring();            // 2 - 3 (increasing theta)
0517   int tp_roll = tp_detId.roll();  // 1 - 3 (decreasing theta; aka A - C; space between rolls is 9 - 15 in theta_fp)
0518   //int tp_layer     = tp_detId.layer();      // Always 1 in the Endcap, 1 or 2 in the Barrel
0519 
0520   int tp_bx = tp_data.bx;
0521   int tp_strip = ((tp_data.strip_low + tp_data.strip_hi) / 2);  // in full-strip unit
0522 
0523   const bool is_neighbor = (pc_station == 5);
0524 
0525   // CSC-like sector, subsector and chamber numbers
0526   int csc_tp_chamber = (tp_sector - 1) * 6 + tp_subsector;
0527   int csc_tp_sector = (tp_subsector > 2) ? tp_sector : ((tp_sector + 4) % 6) + 1;  // Rotate by 20 deg
0528   int csc_tp_subsector = (tp_station != 1) ? 0 : ((csc_tp_chamber % 6 > 2) ? 1 : 2);
0529 
0530   const bool is_irpc = (tp_station == 3 || tp_station == 4) && (tp_ring == 1);
0531   if (is_irpc) {
0532     csc_tp_chamber = (tp_sector - 1) * 3 + tp_subsector;
0533     csc_tp_sector = (tp_subsector > 1) ? tp_sector : ((tp_sector + 4) % 6) + 1;  // Rotate by 20 deg
0534     csc_tp_subsector = (tp_station != 1) ? 0 : ((csc_tp_chamber % 6 > 2) ? 1 : 2);
0535   }
0536   int tp_csc_ID = emtf::get_trigger_csc_ID(tp_ring, tp_station, csc_tp_chamber);
0537 
0538   int csc_nID = tp_csc_ID;  // modify csc_ID if coming from neighbor sector
0539   if (is_neighbor) {
0540     // station 1 has 3 neighbor chambers: 13,14,15 in rings 1,2,3
0541     // (where are chambers 10,11,12 in station 1? they were used to label ME1/1a, but not anymore)
0542     // station 2,3,4 have 2 neighbor chambers: 10,11 in rings 1,2
0543     csc_nID = (pc_chamber < 3) ? (pc_chamber + 12) : (((pc_chamber - 1) % 2) + 9);
0544     csc_nID += 1;
0545   }
0546 
0547   // Use cluster width as 'quality'
0548   int tp_quality = (tp_data.strip_hi - tp_data.strip_low + 1);
0549   if (!is_irpc) {
0550     tp_quality *= 3;  // old RPC strip pitch is 1.5 times the new iRPC
0551     tp_quality /= 2;
0552   }
0553 
0554   // Set properties
0555   conv_hit.SetRPCDetId(tp_detId);
0556 
0557   conv_hit.set_bx(tp_bx + bxShiftRPC_);
0558   conv_hit.set_subsystem(L1TMuon::kRPC);
0559   conv_hit.set_endcap((tp_endcap == 2) ? -1 : tp_endcap);
0560   conv_hit.set_station(tp_station);
0561   conv_hit.set_ring(tp_ring);
0562   conv_hit.set_roll(tp_roll);
0563   conv_hit.set_chamber(csc_tp_chamber);
0564   conv_hit.set_sector(csc_tp_sector);
0565   conv_hit.set_subsector(csc_tp_subsector);
0566   conv_hit.set_csc_ID(tp_csc_ID);
0567   conv_hit.set_csc_nID(csc_nID);
0568   //conv_hit.set_track_num     ( tp_data.trknmb );
0569   //conv_hit.set_sync_err      ( tp_data.syncErr );
0570   conv_hit.set_sector_RPC(tp_sector);  // In RPC convention in CMSSW (RPCDetId.h), sector 1 starts at -5 deg
0571   conv_hit.set_subsector_RPC(tp_subsector);
0572 
0573   conv_hit.set_pc_sector(pc_sector);
0574   conv_hit.set_pc_station(pc_station);
0575   conv_hit.set_pc_chamber(pc_chamber);
0576   conv_hit.set_pc_segment(pc_segment);
0577 
0578   conv_hit.set_valid(tp_data.valid);
0579   conv_hit.set_strip(tp_strip);
0580   conv_hit.set_strip_low(tp_data.strip_low);
0581   conv_hit.set_strip_hi(tp_data.strip_hi);
0582   //conv_hit.set_wire          ( tp_data.keywire );
0583   conv_hit.set_quality(tp_quality);
0584   conv_hit.set_pattern(0);  // In firmware, this marks RPC stub
0585   //conv_hit.set_bend          ( tp_data.bend );
0586   conv_hit.set_time(tp_data.time);
0587   //conv_hit.set_alct_quality  ( tp_data.alct_quality );
0588   //conv_hit.set_clct_quality  ( tp_data.clct_quality );
0589 
0590   conv_hit.set_neighbor(is_neighbor);
0591   conv_hit.set_sector_idx((endcap_ == 1) ? sector_ - 1 : sector_ + 5);
0592 
0593   // Get coordinates from fullsim
0594   bool use_fullsim_coords = true;
0595 
0596   if (tp_data.isCPPF) {                            // CPPF digis from EMTF unpacker or CPPF emulator
0597     conv_hit.set_phi_fp(tp_data.phi_int * 4);      // Full-precision integer phi
0598     conv_hit.set_theta_fp(tp_data.theta_int * 4);  // Full-precision integer theta
0599   } else if (use_fullsim_coords) {
0600     const GlobalPoint& gp = tp_geom_->getGlobalPoint(muon_primitive);
0601     double glob_phi = emtf::rad_to_deg(gp.phi().value());
0602     double glob_theta = emtf::rad_to_deg(gp.theta());
0603     double glob_eta = gp.eta();
0604     double glob_rho = gp.perp();
0605     double glob_z = gp.z();
0606 
0607     // Use RPC-specific convention in docs/CPPF-EMTF-format_2016_11_01.docx
0608     // Phi precision is 1/15 degrees (11 bits), 4x larger than CSC precision of 1/60 degrees (13 bits)
0609     // Theta precision is 36.5/32 degrees (5 bits), 4x larger than CSC precision of 36.5/128 degrees (7 bits)
0610     //
0611     // NOTE: fph and th are recalculated using CPPF LUTs in the convert_rpc_details() function,
0612     //       this part is still kept because it is needed for Phase 2 iRPC hits.
0613     //
0614     int fph = emtf::calc_phi_loc_int_rpc(glob_phi, conv_hit.PC_sector());
0615     int th = emtf::calc_theta_int_rpc(glob_theta, conv_hit.Endcap());
0616 
0617     //emtf_assert(0 <= fph && fph < 1024);
0618     emtf_assert(0 <= fph && fph < 1250);
0619     emtf_assert(0 <= th && th < 32);
0620     emtf_assert(th != 0b11111);  // RPC hit valid when data is not all ones
0621     fph <<= 2;                   // upgrade to full CSC precision by adding 2 zeros
0622     th <<= 2;                    // upgrade to full CSC precision by adding 2 zeros
0623     th = (th == 0) ? 1 : th;     // protect against invalid value
0624 
0625     if (is_irpc) {
0626       const RPCRoll* roll = dynamic_cast<const RPCRoll*>(tp_geom_->getRPCGeometry().roll(tp_detId));
0627       emtf_assert(roll != nullptr);  // failed to get RPC roll
0628       const GlobalPoint& new_gp = roll->surface().toGlobal(LocalPoint(tp_data.x, tp_data.y, 0));
0629       glob_phi = emtf::rad_to_deg(gp.phi().value());  // using 'gp' instead of 'new_gp' for phi
0630       glob_theta = emtf::rad_to_deg(new_gp.theta());
0631       glob_eta = new_gp.eta();
0632       glob_rho = new_gp.perp();
0633       glob_z = new_gp.z();
0634 
0635       fph = emtf::calc_phi_loc_int(glob_phi, conv_hit.PC_sector());
0636       th = emtf::calc_theta_int(glob_theta, conv_hit.Endcap());
0637 
0638       emtf_assert(0 <= fph && fph < 5000);
0639       emtf_assert(0 <= th && th < 128);
0640       th = (th == 0) ? 1 : th;  // protect against invalid value
0641     }
0642 
0643     // _________________________________________________________________________
0644     // Output
0645 
0646     conv_hit.set_phi_sim(glob_phi);
0647     conv_hit.set_theta_sim(glob_theta);
0648     conv_hit.set_eta_sim(glob_eta);
0649     conv_hit.set_rho_sim(glob_rho);
0650     conv_hit.set_z_sim(glob_z);
0651 
0652     conv_hit.set_phi_fp(fph);   // Full-precision integer phi
0653     conv_hit.set_theta_fp(th);  // Full-precision integer theta
0654   }
0655 
0656   convert_rpc_details(conv_hit, tp_data.isCPPF);
0657 }
0658 
0659 void PrimitiveConversion::convert_rpc_details(EMTFHit& conv_hit, bool isCPPF) const {
0660   const bool is_neighbor = conv_hit.Neighbor();
0661 
0662   const int pc_station = conv_hit.PC_station();
0663   const int pc_chamber = conv_hit.PC_chamber();
0664   const int pc_segment = conv_hit.PC_segment();
0665 
0666   //const int fw_endcap  = (endcap_-1);
0667   //const int fw_sector  = (sector_-1);
0668   const int fw_station = (conv_hit.Station() == 1) ? (is_neighbor ? 0 : pc_station) : conv_hit.Station();
0669   const int fw_cscid = (conv_hit.CSC_nID() - 1);
0670 
0671   int fph = conv_hit.Phi_fp();
0672   int th = conv_hit.Theta_fp();
0673 
0674   // Do coordinate conversion using the CPPF LUTs. Not needed if the received digis are CPPF digis.
0675   bool use_cppf_lut = !isCPPF;
0676 
0677   if (use_cppf_lut) {
0678     int halfstrip = (conv_hit.Strip_low() + conv_hit.Strip_hi() - 1);
0679     emtf_assert(1 <= halfstrip && halfstrip <= 64);
0680 
0681     int fph2 = pc_lut().get_cppf_ph_lut(conv_hit.Endcap(),
0682                                         conv_hit.Sector_RPC(),
0683                                         conv_hit.Station(),
0684                                         conv_hit.Ring(),
0685                                         conv_hit.Subsector_RPC(),
0686                                         conv_hit.Roll(),
0687                                         halfstrip,
0688                                         is_neighbor);
0689     int th2 = pc_lut().get_cppf_th_lut(conv_hit.Endcap(),
0690                                        conv_hit.Sector_RPC(),
0691                                        conv_hit.Station(),
0692                                        conv_hit.Ring(),
0693                                        conv_hit.Subsector_RPC(),
0694                                        conv_hit.Roll());
0695     //emtf_assert(abs((fph>>2) - fph2) <= 4); // arbitrary tolerance
0696     //emtf_assert(abs((th>>2) - th2) <= 1);   // arbitrary tolerance
0697     fph = fph2;
0698     th = th2;
0699 
0700     //emtf_assert(0 <= fph && fph < 1024);
0701     emtf_assert(0 <= fph && fph < 1250);
0702     emtf_assert(0 <= th && th < 32);
0703     emtf_assert(th != 0b11111);  // RPC hit valid when data is not all ones
0704     fph <<= 2;                   // upgrade to full CSC precision by adding 2 zeros
0705     th <<= 2;                    // upgrade to full CSC precision by adding 2 zeros
0706     th = (th == 0) ? 1 : th;     // protect against invalid value
0707   }
0708 
0709   if (verbose_ > 1) {  // debug
0710     std::cout << "RPC hit pc_station: " << pc_station << " pc_chamber: " << pc_chamber << " fw_station: " << fw_station
0711               << " fw_cscid: " << fw_cscid << " tp_station: " << conv_hit.Station() << " tp_ring: " << conv_hit.Ring()
0712               << " tp_sector: " << conv_hit.Sector_RPC() << " tp_subsector: " << conv_hit.Subsector_RPC()
0713               << " fph: " << fph << " th: " << th << std::endl;
0714   }
0715 
0716   // ___________________________________________________________________________
0717   // Zone codes and other segment IDs
0718 
0719   int zone_hit = ((fph + (1 << 4)) >> 5);
0720   int zone_code = get_zone_code(conv_hit, th);
0721   //int phzvl        = get_phzvl(conv_hit, zone_code);
0722 
0723   int fs_zone_code = get_fs_zone_code(conv_hit);
0724   int fs_segment = get_fs_segment(conv_hit, fw_station, fw_cscid, pc_segment);
0725 
0726   int bt_station = get_bt_station(conv_hit, fw_station, fw_cscid, pc_segment);
0727   int bt_segment = get_bt_segment(conv_hit, fw_station, fw_cscid, pc_segment);
0728 
0729   // ___________________________________________________________________________
0730   // Output
0731 
0732   conv_hit.set_phi_fp(fph);   // Full-precision integer phi
0733   conv_hit.set_theta_fp(th);  // Full-precision integer theta
0734   //conv_hit.set_phzvl      ( phzvl );      // Local zone word: (1*low) + (2*mid) + (4*low) - used in FW debugging
0735   //conv_hit.set_ph_hit     ( ph_hit );     // Intermediate quantity in phi calculation - used in FW debugging
0736   conv_hit.set_zone_hit(zone_hit);    // Phi value for building patterns (0.53333 deg precision)
0737   conv_hit.set_zone_code(zone_code);  // Full zone word: 1*(zone 0) + 2*(zone 1) + 4*(zone 2) + 8*(zone 3)
0738 
0739   conv_hit.set_fs_segment(fs_segment);      // Segment number used in primitive matching
0740   conv_hit.set_fs_zone_code(fs_zone_code);  // Zone word used in primitive matching
0741 
0742   conv_hit.set_bt_station(bt_station);
0743   conv_hit.set_bt_segment(bt_segment);
0744 
0745   conv_hit.set_phi_loc(emtf::calc_phi_loc_deg(fph));
0746   conv_hit.set_phi_glob(emtf::calc_phi_glob_deg(conv_hit.Phi_loc(), conv_hit.PC_sector()));
0747   conv_hit.set_theta(emtf::calc_theta_deg_from_int(th));
0748   conv_hit.set_eta(emtf::calc_eta_from_theta_deg(conv_hit.Theta(), conv_hit.Endcap()));
0749 }
0750 
0751 // _____________________________________________________________________________
0752 // GEM functions
0753 void PrimitiveConversion::convert_gem(int pc_sector,
0754                                       int pc_station,
0755                                       int pc_chamber,
0756                                       int pc_segment,
0757                                       const TriggerPrimitive& muon_primitive,
0758                                       EMTFHit& conv_hit) const {
0759   const GEMDetId& tp_detId = muon_primitive.detId<GEMDetId>();
0760   const GEMData& tp_data = muon_primitive.getGEMData();
0761 
0762   int tp_region = tp_detId.region();  // 0 for Barrel, +/-1 for +/- Endcap
0763   int tp_endcap = (tp_region == -1) ? 2 : tp_region;
0764   int tp_station = tp_detId.station();
0765   int tp_ring = tp_detId.ring();
0766   int tp_roll = tp_detId.roll();
0767   //int tp_layer     = tp_detId.layer();
0768   int tp_chamber = tp_detId.chamber();
0769 
0770   int tp_bx = tp_data.bx;
0771   int tp_pad = ((tp_data.pad_low + tp_data.pad_hi) / 2);
0772 
0773   int tp_sector = emtf::get_trigger_sector(tp_ring, tp_station, tp_chamber);
0774   int tp_csc_ID = emtf::get_trigger_csc_ID(tp_ring, tp_station, tp_chamber);
0775 
0776   // station 1 --> subsector 1 or 2
0777   // station 2,3,4 --> subsector 0
0778   int tp_subsector = (tp_station != 1) ? 0 : ((tp_chamber % 6 > 2) ? 1 : 2);
0779 
0780   const bool is_neighbor = (pc_chamber == 12 || pc_chamber == 13);
0781 
0782   int csc_nID = tp_csc_ID;  // modify csc_ID if coming from neighbor sector
0783   if (is_neighbor) {
0784     // station 1 has 3 neighbor chambers: 13,14,15 in rings 1,2,3
0785     // (where are chambers 10,11,12 in station 1? they were used to label ME1/1a, but not anymore)
0786     // station 2,3,4 have 2 neighbor chambers: 10,11 in rings 1,2
0787     if (tp_station == 1) {
0788       csc_nID = 13;
0789     } else {
0790       csc_nID = 10;
0791     }
0792   }
0793 
0794   // Use cluster width as 'quality'
0795   int tp_quality = (tp_data.pad_hi - tp_data.pad_low + 1);
0796 
0797   // Set properties
0798   conv_hit.SetGEMDetId(tp_detId);
0799 
0800   conv_hit.set_bx(tp_bx + bxShiftGEM_);
0801   conv_hit.set_subsystem(L1TMuon::kGEM);
0802   conv_hit.set_endcap((tp_endcap == 2) ? -1 : tp_endcap);
0803   conv_hit.set_station(tp_station);
0804   conv_hit.set_ring(tp_ring);
0805   conv_hit.set_roll(tp_roll);
0806   conv_hit.set_chamber(tp_chamber);
0807   conv_hit.set_sector(tp_sector);
0808   conv_hit.set_subsector(tp_subsector);
0809   conv_hit.set_csc_ID(tp_csc_ID);
0810   conv_hit.set_csc_nID(csc_nID);
0811   //conv_hit.set_track_num     ( tp_data.trknmb );
0812   //conv_hit.set_sync_err      ( tp_data.syncErr );
0813   //conv_hit.set_sector_RPC    ( tp_sector );
0814   //conv_hit.set_subsector_RPC ( tp_subsector );
0815 
0816   conv_hit.set_pc_sector(pc_sector);
0817   conv_hit.set_pc_station(pc_station);
0818   conv_hit.set_pc_chamber(pc_chamber);
0819   conv_hit.set_pc_segment(pc_segment);
0820 
0821   conv_hit.set_valid(true);
0822   conv_hit.set_strip(tp_pad);
0823   conv_hit.set_strip_low(tp_data.pad_low);
0824   conv_hit.set_strip_hi(tp_data.pad_hi);
0825   //conv_hit.set_wire          ( tp_data.keywire );
0826   conv_hit.set_quality(tp_quality);
0827   conv_hit.set_pattern(0);  // arbitrary
0828   //conv_hit.set_bend          ( tp_data.bend );
0829   conv_hit.set_time(0.);  // No fine resolution timing
0830   //conv_hit.set_alct_quality  ( tp_data.alct_quality );
0831   //conv_hit.set_clct_quality  ( tp_data.clct_quality );
0832 
0833   conv_hit.set_neighbor(is_neighbor);
0834   conv_hit.set_sector_idx((endcap_ == 1) ? sector_ - 1 : sector_ + 5);
0835 
0836   // Get coordinates from fullsim since LUTs do not exist yet
0837   bool use_fullsim_coords = true;
0838   if (use_fullsim_coords) {
0839     const GlobalPoint& gp = tp_geom_->getGlobalPoint(muon_primitive);
0840     double glob_phi = emtf::rad_to_deg(gp.phi().value());
0841     double glob_theta = emtf::rad_to_deg(gp.theta());
0842     double glob_eta = gp.eta();
0843     double glob_rho = gp.perp();
0844     double glob_z = gp.z();
0845 
0846     // Use the CSC precision (unconfirmed!)
0847     int fph = emtf::calc_phi_loc_int(glob_phi, conv_hit.PC_sector());
0848     int th = emtf::calc_theta_int(glob_theta, conv_hit.Endcap());
0849 
0850     emtf_assert(0 <= fph && fph < 5000);
0851     emtf_assert(0 <= th && th < 128);
0852     th = (th == 0) ? 1 : th;  // protect against invalid value
0853 
0854     // _________________________________________________________________________
0855     // Output
0856 
0857     conv_hit.set_phi_sim(glob_phi);
0858     conv_hit.set_theta_sim(glob_theta);
0859     conv_hit.set_eta_sim(glob_eta);
0860     conv_hit.set_rho_sim(glob_rho);
0861     conv_hit.set_z_sim(glob_z);
0862 
0863     conv_hit.set_phi_fp(fph);   // Full-precision integer phi
0864     conv_hit.set_theta_fp(th);  // Full-precision integer theta
0865   }
0866 
0867   convert_other_details(conv_hit);
0868 }
0869 
0870 void PrimitiveConversion::convert_other_details(EMTFHit& conv_hit) const {
0871   const bool is_neighbor = conv_hit.Neighbor();
0872 
0873   const int pc_station = conv_hit.PC_station();
0874   const int pc_chamber = conv_hit.PC_chamber();
0875   const int pc_segment = conv_hit.PC_segment();
0876 
0877   //const int fw_endcap  = (endcap_-1);
0878   //const int fw_sector  = (sector_-1);
0879   const int fw_station =
0880       (conv_hit.Station() == 1) ? (is_neighbor ? 0 : (conv_hit.Subsector() - 1)) : conv_hit.Station();
0881   const int fw_cscid = (conv_hit.CSC_nID() - 1);
0882 
0883   int fph = conv_hit.Phi_fp();
0884   int th = conv_hit.Theta_fp();
0885 
0886   if (verbose_ > 1) {  // debug
0887     std::cout << "GEM hit pc_station: " << pc_station << " pc_chamber: " << pc_chamber << " fw_station: " << fw_station
0888               << " fw_cscid: " << fw_cscid << " tp_station: " << conv_hit.Station() << " tp_ring: " << conv_hit.Ring()
0889               << " tp_sector: " << conv_hit.Sector() << " tp_subsector: " << conv_hit.Subsector() << " fph: " << fph
0890               << " th: " << th << std::endl;
0891   }
0892 
0893   // ___________________________________________________________________________
0894   // Zone codes and other segment IDs
0895 
0896   int zone_hit = ((fph + (1 << 4)) >> 5);
0897   int zone_code = get_zone_code(conv_hit, th);
0898   //int phzvl        = get_phzvl(conv_hit, zone_code);
0899 
0900   int fs_zone_code = get_fs_zone_code(conv_hit);
0901   int fs_segment = get_fs_segment(conv_hit, fw_station, fw_cscid, pc_segment);
0902 
0903   int bt_station = get_bt_station(conv_hit, fw_station, fw_cscid, pc_segment);
0904   int bt_segment = get_bt_segment(conv_hit, fw_station, fw_cscid, pc_segment);
0905 
0906   // ___________________________________________________________________________
0907   // Output
0908 
0909   conv_hit.set_phi_fp(fph);   // Full-precision integer phi
0910   conv_hit.set_theta_fp(th);  // Full-precision integer theta
0911   //conv_hit.set_phzvl      ( phzvl );      // Local zone word: (1*low) + (2*mid) + (4*low) - used in FW debugging
0912   //conv_hit.set_ph_hit     ( ph_hit );     // Intermediate quantity in phi calculation - used in FW debugging
0913   conv_hit.set_zone_hit(zone_hit);    // Phi value for building patterns (0.53333 deg precision)
0914   conv_hit.set_zone_code(zone_code);  // Full zone word: 1*(zone 0) + 2*(zone 1) + 4*(zone 2) + 8*(zone 3)
0915 
0916   conv_hit.set_fs_segment(fs_segment);      // Segment number used in primitive matching
0917   conv_hit.set_fs_zone_code(fs_zone_code);  // Zone word used in primitive matching
0918 
0919   conv_hit.set_bt_station(bt_station);
0920   conv_hit.set_bt_segment(bt_segment);
0921 
0922   conv_hit.set_phi_loc(emtf::calc_phi_loc_deg(fph));
0923   conv_hit.set_phi_glob(emtf::calc_phi_glob_deg(conv_hit.Phi_loc(), conv_hit.PC_sector()));
0924   conv_hit.set_theta(emtf::calc_theta_deg_from_int(th));
0925   conv_hit.set_eta(emtf::calc_eta_from_theta_deg(conv_hit.Theta(), conv_hit.Endcap()));
0926 }
0927 
0928 // _____________________________________________________________________________
0929 // ME0 functions
0930 void PrimitiveConversion::convert_me0(int pc_sector,
0931                                       int pc_station,
0932                                       int pc_chamber,
0933                                       int pc_segment,
0934                                       const TriggerPrimitive& muon_primitive,
0935                                       EMTFHit& conv_hit) const {
0936   const ME0DetId& tp_detId = muon_primitive.detId<ME0DetId>();
0937   const ME0Data& tp_data = muon_primitive.getME0Data();
0938 
0939   int tp_region = tp_detId.region();  // 0 for Barrel, +/-1 for +/- Endcap
0940   int tp_endcap = (tp_region == -1) ? 2 : tp_region;
0941   int tp_station = tp_detId.station();
0942   int tp_ring = 1;  // tp_detId.ring() does not exist
0943   //int tp_roll      = tp_detId.roll();
0944   //int tp_layer     = tp_detId.layer();
0945   int tp_chamber = tp_detId.chamber();
0946 
0947   int tp_bx = tp_data.bx;
0948   int tp_pad = tp_data.phiposition;
0949   int tp_partition = tp_data.partition;
0950 
0951   // The ME0 geometry is similar to ME2/1, so I use tp_station = 2, tp_ring = 1
0952   // when calling get_trigger_sector() and get_trigger_csc_ID()
0953   int tp_sector = emtf::get_trigger_sector(1, 2, tp_chamber);
0954   int tp_csc_ID = emtf::get_trigger_csc_ID(1, 2, tp_chamber);
0955   int tp_subsector = 0;
0956 
0957   const bool is_neighbor = (pc_chamber == 14);
0958 
0959   int csc_nID = tp_csc_ID;  // modify csc_ID if coming from neighbor sector
0960   if (is_neighbor) {
0961     // station 1 has 3 neighbor chambers: 13,14,15 in rings 1,2,3
0962     // (where are chambers 10,11,12 in station 1? they were used to label ME1/1a, but not anymore)
0963     // station 2,3,4 have 2 neighbor chambers: 10,11 in rings 1,2
0964     csc_nID = 10;
0965   }
0966 
0967   // Set properties
0968   conv_hit.SetME0DetId(tp_detId);
0969 
0970   conv_hit.set_bx(tp_bx + bxShiftME0_);
0971   conv_hit.set_subsystem(L1TMuon::kME0);
0972   conv_hit.set_endcap((tp_endcap == 2) ? -1 : tp_endcap);
0973   conv_hit.set_station(tp_station);
0974   conv_hit.set_ring(tp_ring);
0975   conv_hit.set_roll(tp_partition);
0976   conv_hit.set_chamber(tp_chamber);
0977   conv_hit.set_sector(tp_sector);
0978   conv_hit.set_subsector(tp_subsector);
0979   conv_hit.set_csc_ID(tp_csc_ID);
0980   conv_hit.set_csc_nID(csc_nID);
0981   //conv_hit.set_track_num     ( tp_data.trknmb );
0982   //conv_hit.set_sync_err      ( tp_data.syncErr );
0983   //conv_hit.set_sector_RPC    ( tp_sector );
0984   //conv_hit.set_subsector_RPC ( tp_subsector );
0985 
0986   conv_hit.set_pc_sector(pc_sector);
0987   conv_hit.set_pc_station(pc_station);
0988   conv_hit.set_pc_chamber(pc_chamber);
0989   conv_hit.set_pc_segment(pc_segment);
0990 
0991   conv_hit.set_valid(true);
0992   conv_hit.set_strip(tp_pad);
0993   //conv_hit.set_strip_low     ( tp_strip );
0994   //conv_hit.set_strip_hi      ( tp_strip );
0995   //conv_hit.set_wire          ( tp_data.keywire );
0996   conv_hit.set_quality(tp_data.quality);
0997   conv_hit.set_pattern(0);  // arbitrary
0998   conv_hit.set_bend(tp_data.deltaphi * (tp_data.bend == 0 ? 1 : -1));
0999   conv_hit.set_time(0.);  // No fine resolution timing
1000   //conv_hit.set_alct_quality  ( tp_data.alct_quality );
1001   //conv_hit.set_clct_quality  ( tp_data.clct_quality );
1002 
1003   conv_hit.set_neighbor(is_neighbor);
1004   conv_hit.set_sector_idx((endcap_ == 1) ? sector_ - 1 : sector_ + 5);
1005 
1006   // Get coordinates from fullsim since LUTs do not exist yet
1007   bool use_fullsim_coords = true;
1008   if (use_fullsim_coords) {
1009     const GlobalPoint& gp = tp_geom_->getGlobalPoint(muon_primitive);
1010     double glob_phi = emtf::rad_to_deg(gp.phi().value());
1011     double glob_theta = emtf::rad_to_deg(gp.theta());
1012     double glob_eta = gp.eta();
1013     double glob_rho = gp.perp();
1014     double glob_z = gp.z();
1015 
1016     // Use the CSC precision (unconfirmed!)
1017     int fph = emtf::calc_phi_loc_int(glob_phi, conv_hit.PC_sector());
1018     int th = emtf::calc_theta_int(glob_theta, conv_hit.Endcap());
1019 
1020     bool fix_me0_theta_edge = true;
1021     if (fix_me0_theta_edge) {
1022       // The ME0 extends to eta of 2.8 or theta of 7.0 deg. But integer theta
1023       // only starts at theta of 8.5 deg.
1024       if (th < 0)
1025         th = 0;
1026     }
1027 
1028     emtf_assert(0 <= fph && fph < 5000);
1029     emtf_assert(0 <= th && th < 128);
1030     th = (th == 0) ? 1 : th;  // protect against invalid value
1031 
1032     // _________________________________________________________________________
1033     // Output
1034 
1035     conv_hit.set_phi_sim(glob_phi);
1036     conv_hit.set_theta_sim(glob_theta);
1037     conv_hit.set_eta_sim(glob_eta);
1038     conv_hit.set_rho_sim(glob_rho);
1039     conv_hit.set_z_sim(glob_z);
1040 
1041     conv_hit.set_phi_fp(fph);   // Full-precision integer phi
1042     conv_hit.set_theta_fp(th);  // Full-precision integer theta
1043   }
1044 
1045   convert_other_details(conv_hit);
1046 }
1047 
1048 // _____________________________________________________________________________
1049 // DT functions
1050 void PrimitiveConversion::convert_dt(int pc_sector,
1051                                      int pc_station,
1052                                      int pc_chamber,
1053                                      int pc_segment,
1054                                      const TriggerPrimitive& muon_primitive,
1055                                      EMTFHit& conv_hit) const {
1056   const DTChamberId& tp_detId = muon_primitive.detId<DTChamberId>();
1057   const DTData& tp_data = muon_primitive.getDTData();
1058 
1059   int tp_wheel = tp_detId.wheel();
1060   int tp_station = tp_detId.station();
1061   int tp_sector = tp_detId.sector();  // sectors are 1-12, starting at phi=0 and increasing with phi
1062 
1063   // In station 4, where the top and bottom setcors are made of two chambers,
1064   // two additional sector numbers are used, 13 (after sector 4, top)
1065   // and 14 (after sector 10, bottom).
1066   if (tp_station == 4) {
1067     if (tp_sector == 13)
1068       tp_sector = 4;
1069     else if (tp_sector == 14)
1070       tp_sector = 10;
1071   }
1072 
1073   int tp_bx = tp_data.bx;
1074   int tp_phi = tp_data.radialAngle;
1075   int tp_phiB = tp_data.bendingAngle;
1076 
1077   // Mimic 10 deg CSC chamber. I use tp_station = 2, tp_ring = 2
1078   // when calling get_trigger_sector() and get_trigger_csc_ID()
1079   int tp_chamber =
1080       tp_sector * 3 - 1;  // DT chambers are 30 deg. Multiply sector number by 3 to mimic 10 deg CSC chamber number
1081   int tp_endcap = (tp_wheel > 0) ? +1 : ((tp_wheel < 0) ? 2 : 0);
1082   int csc_tp_sector = emtf::get_trigger_sector(2, 2, tp_chamber);
1083   int tp_csc_ID = emtf::get_trigger_csc_ID(2, 2, tp_chamber);
1084   int tp_subsector = 0;
1085 
1086   const bool is_neighbor = (pc_chamber >= 8);
1087 
1088   int csc_nID = tp_csc_ID;  // modify csc_ID if coming from neighbor sector
1089   if (is_neighbor) {
1090     // station 1 has 3 neighbor chambers: 13,14,15 in rings 1,2,3
1091     // (where are chambers 10,11,12 in station 1? they were used to label ME1/1a, but not anymore)
1092     // station 2,3,4 have 2 neighbor chambers: 10,11 in rings 1,2
1093     csc_nID = 10;
1094   }
1095 
1096   // Set properties
1097   conv_hit.SetDTDetId(tp_detId);
1098 
1099   conv_hit.set_bx(tp_bx);
1100   conv_hit.set_subsystem(L1TMuon::kDT);
1101   conv_hit.set_endcap((tp_endcap == 2) ? -1 : tp_endcap);
1102   conv_hit.set_station(tp_station);
1103   conv_hit.set_ring(1);         // set to ring 1?
1104   conv_hit.set_roll(tp_wheel);  // used as wheel
1105   conv_hit.set_chamber(tp_chamber);
1106   conv_hit.set_sector(csc_tp_sector);
1107   conv_hit.set_subsector(tp_subsector);
1108   conv_hit.set_csc_ID(tp_csc_ID);
1109   conv_hit.set_csc_nID(csc_nID);
1110   conv_hit.set_track_num(tp_data.segment_number);
1111   conv_hit.set_sync_err(tp_data.RpcBit);  // hacked to store rpc bit
1112   //conv_hit.set_sector_RPC    ( tp_sector );
1113   //conv_hit.set_subsector_RPC ( tp_subsector );
1114 
1115   conv_hit.set_pc_sector(pc_sector);
1116   conv_hit.set_pc_station(pc_station);
1117   conv_hit.set_pc_chamber(pc_chamber);
1118   conv_hit.set_pc_segment(pc_segment);
1119 
1120   conv_hit.set_valid(true);
1121   conv_hit.set_strip(tp_phi);
1122   //conv_hit.set_strip_low     ( tp_data.strip_low );
1123   //conv_hit.set_strip_hi      ( tp_data.strip_hi );
1124   conv_hit.set_wire(tp_data.theta_bti_group);
1125   conv_hit.set_quality(tp_data.qualityCode);
1126   conv_hit.set_pattern(0);  // arbitrary
1127   conv_hit.set_bend(tp_phiB);
1128   conv_hit.set_time(0.);  // No fine resolution timing
1129   //conv_hit.set_alct_quality  ( tp_data.alct_quality );
1130   //conv_hit.set_clct_quality  ( tp_data.clct_quality );
1131 
1132   conv_hit.set_neighbor(is_neighbor);
1133   conv_hit.set_sector_idx((endcap_ == 1) ? sector_ - 1 : sector_ + 5);
1134 
1135   // Get coordinates from fullsim since LUTs do not exist yet
1136   bool use_fullsim_coords = true;
1137   if (use_fullsim_coords) {
1138     const GlobalPoint& gp = tp_geom_->getGlobalPoint(muon_primitive);
1139     double glob_phi = emtf::rad_to_deg(gp.phi().value());
1140     double glob_theta = emtf::rad_to_deg(gp.theta());
1141     double glob_eta = gp.eta();
1142     double glob_rho = gp.perp();
1143     double glob_z = gp.z();
1144 
1145     // Use the CSC precision (unconfirmed!)
1146     int fph = emtf::calc_phi_loc_int(glob_phi, conv_hit.PC_sector());
1147     int th = emtf::calc_theta_int(glob_theta, conv_hit.Endcap());
1148 
1149     bool fix_dt_phi_edge = true;
1150     if (fix_dt_phi_edge) {
1151       // The DT chamber edges are not always aligned at 0,30,60,etc. The local
1152       // phi 0 is set to the CSC chamber edge minus 22 deg. But it is possible
1153       // for the DT neighbor chamber to go as far as the CSC chamber edge minus
1154       // 32 deg.
1155       double loc = emtf::calc_phi_loc_deg_from_glob(glob_phi, conv_hit.PC_sector());
1156       if ((loc + 22.) < 0. && (loc + 32.) > 0.)
1157         fph = 0;
1158       else if ((loc + 360. + 22.) < 0. && (loc + 360. + 32.) > 0.)
1159         fph = 0;
1160     }
1161 
1162     emtf_assert(0 <= fph && fph < 5400);
1163     emtf_assert(0 <= th && th < 180);  // Note: eta = 0.73 -> theta_int = 150
1164     th = (th == 0) ? 1 : th;           // protect against invalid value
1165 
1166     // _________________________________________________________________________
1167     // Output
1168 
1169     conv_hit.set_phi_sim(glob_phi);
1170     conv_hit.set_theta_sim(glob_theta);
1171     conv_hit.set_eta_sim(glob_eta);
1172     conv_hit.set_rho_sim(glob_rho);
1173     conv_hit.set_z_sim(glob_z);
1174 
1175     conv_hit.set_phi_fp(fph);   // Full-precision integer phi
1176     conv_hit.set_theta_fp(th);  // Full-precision integer theta
1177   }
1178 
1179   convert_other_details(conv_hit);
1180 }
1181 
1182 // _____________________________________________________________________________
1183 // Aux functions
1184 int PrimitiveConversion::get_zone_code(const EMTFHit& conv_hit, int th) const {
1185   // ph zone boundaries for chambers that cover more than one zone
1186   // bnd1 is the lower boundary, bnd2 the upper boundary
1187   int zone_code = 0;
1188 
1189   bool is_csc = (conv_hit.Subsystem() == L1TMuon::kCSC);
1190   bool is_me13 = (is_csc && conv_hit.Station() == 1 && conv_hit.Ring() == 3);
1191 
1192   if (th >= 127)
1193     th = 127;
1194 
1195   for (int izone = 0; izone < emtf::NUM_ZONES; ++izone) {
1196     int zone_code_tmp = get_fs_zone_code(conv_hit);
1197     if (zone_code_tmp & (1 << izone)) {
1198       bool no_use_bnd1 =
1199           ((izone == 0) || ((zone_code_tmp & (1 << (izone - 1))) == 0) || is_me13);  // first possible zone for this hit
1200       bool no_use_bnd2 = (((zone_code_tmp & (1 << (izone + 1))) == 0) || is_me13);   // last possible zone for this hit
1201 
1202       int ph_zone_bnd1 = no_use_bnd1 ? zoneBoundaries_.at(0) : zoneBoundaries_.at(izone);
1203       int ph_zone_bnd2 = no_use_bnd2 ? zoneBoundaries_.at(emtf::NUM_ZONES) : zoneBoundaries_.at(izone + 1);
1204 
1205       if ((th > (ph_zone_bnd1 - zoneOverlap_)) && (th <= (ph_zone_bnd2 + zoneOverlap_))) {
1206         zone_code |= (1 << izone);
1207       }
1208     }
1209   }
1210   emtf_assert(zone_code > 0);
1211   return zone_code;
1212 }
1213 
1214 int PrimitiveConversion::get_phzvl(const EMTFHit& conv_hit, int zone_code) const {
1215   // For backward compatibility, no longer needed (only explicitly used in FW)
1216   // phzvl: each chamber overlaps with at most 3 zones, so this "local" zone word says
1217   // which of the possible zones contain the hit: 1 for lower, 2 for middle, 4 for upper
1218   int phzvl = 0;
1219   if (conv_hit.Ring() == 1 || conv_hit.Ring() == 4) {
1220     phzvl = (zone_code >> 0);
1221   } else if (conv_hit.Ring() == 2) {
1222     if (conv_hit.Station() == 3 || conv_hit.Station() == 4) {
1223       phzvl = (zone_code >> 1);
1224     } else if (conv_hit.Station() == 1 || conv_hit.Station() == 2) {
1225       phzvl = (zone_code >> 2);
1226     }
1227   } else if (conv_hit.Ring() == 3) {
1228     phzvl = (zone_code >> 3);
1229   }
1230   return phzvl;
1231 }
1232 
1233 int PrimitiveConversion::get_fs_zone_code(const EMTFHit& conv_hit) const {
1234   static const unsigned int zone_code_table[4][3] = {
1235       // map (station,ring) to zone_code
1236       {0b0011, 0b0100, 0b1000},  // st1 r1: [z0,z1], r2: [z2],       r3: [z3]
1237       {0b0011, 0b1100, 0b1100},  // st2 r1: [z0,z1], r2: [z2,z3],    r3 = r2
1238       {0b0001, 0b1110, 0b1110},  // st3 r1: [z0],    r2: [z1,z2,z3], r3 = r2
1239       {0b0001, 0b0110, 0b0110}   // st4 r1: [z0],    r2: [z1,z2],    r3 = r2
1240   };
1241 
1242   static const unsigned int zone_code_table_new[4][3] = {
1243       // map (station,ring) to zone_code
1244       {0b0011, 0b0110, 0b1000},  // st1 r1: [z0,z1], r2: [z1,z2],    r3: [z3]
1245       {0b0011, 0b1110, 0b1110},  // st2 r1: [z0,z1], r2: [z1,z2,z3], r3 = r2
1246       {0b0011, 0b1110, 0b1110},  // st3 r1: [z0,z1], r2: [z1,z2,z3], r3 = r2
1247       {0b0001, 0b0110, 0b0110}   // st4 r1: [z0],    r2: [z1,z2],    r3 = r2
1248   };
1249 
1250   unsigned int istation = (conv_hit.Station() - 1);
1251   unsigned int iring = (conv_hit.Ring() == 4) ? 0 : (conv_hit.Ring() - 1);
1252   emtf_assert(istation < 4 && iring < 3);
1253   unsigned int zone_code = useNewZones_ ? zone_code_table_new[istation][iring] : zone_code_table[istation][iring];
1254   return zone_code;
1255 }
1256 
1257 int PrimitiveConversion::get_fs_segment(const EMTFHit& conv_hit, int fw_station, int fw_cscid, int pc_segment) const {
1258   // For later use in primitive matching
1259   // (in the firmware, this happens in the find_segment module)
1260   int fs_history = 0;               // history id: not set here, to be set in primitive matching
1261   int fs_chamber = -1;              // chamber id
1262   int fs_segment = pc_segment % 2;  // segment id
1263 
1264   // For ME1
1265   //   j = 0 is neighbor sector chamber
1266   //   j = 1,2,3 are native subsector 1 chambers
1267   //   j = 4,5,6 are native subsector 2 chambers
1268   // For ME2,3,4:
1269   //   j = 0 is neighbor sector chamber
1270   //   j = 1,2,3,4,5,6 are native sector chambers
1271   const bool is_neighbor = conv_hit.Neighbor();
1272   if (fw_station <= 1) {  // ME1
1273     int n = fw_cscid % 3;
1274     fs_chamber = is_neighbor ? 0 : ((fw_station == 0) ? 1 + n : 4 + n);
1275   } else {  // ME2,3,4
1276     int n = (conv_hit.Ring() == 1) ? fw_cscid : (fw_cscid - 3);
1277     fs_chamber = is_neighbor ? 0 : 1 + n;
1278   }
1279 
1280   emtf_assert(fs_history == 0 && (0 <= fs_chamber && fs_chamber < 7) && (0 <= fs_segment && fs_segment < 2));
1281   // fs_segment is a 6-bit word, HHCCCS, encoding the segment number S in the chamber (1 or 2),
1282   // the chamber number CCC ("j" above: uniquely identifies chamber within station and ring),
1283   // and the history HH (0 for current BX, 1 for previous BX, 2 for BX before that)
1284   fs_segment = ((fs_history & 0x3) << 4) | ((fs_chamber & 0x7) << 1) | (fs_segment & 0x1);
1285   return fs_segment;
1286 }
1287 
1288 int PrimitiveConversion::get_bt_station(const EMTFHit& conv_hit, int fw_station, int fw_cscid, int pc_segment) const {
1289   int bt_station = fw_station;
1290   return bt_station;
1291 }
1292 
1293 int PrimitiveConversion::get_bt_segment(const EMTFHit& conv_hit, int fw_station, int fw_cscid, int pc_segment) const {
1294   // For later use in angle calculation and best track selection
1295   // (in the firmware, this happens in the best_tracks module)
1296   int bt_history = 0;               // history id: not set here, to be set in primitive matching
1297   int bt_chamber = -1;              // chamber id
1298   int bt_segment = pc_segment % 2;  // segment id
1299 
1300   // For ME1
1301   //   j = 0 is No valid LCT
1302   //   j = 1 .. 9 are native sector chambers
1303   //   j = 10 .. 12 are neighbor sector chambers
1304   // For ME2,3,4
1305   //   j = 0 is No valid LCT
1306   //   j = 1 .. 9 are native sector chambers
1307   //   j = 10 .. 11 are neighbor sector chambers
1308   bt_chamber = fw_cscid + 1;
1309   if (fw_station == 0 && bt_chamber >= 13)  // ME1 neighbor chambers 13,14,15 -> 10,11,12
1310     bt_chamber -= 3;
1311 
1312   emtf_assert(bt_history == 0 && (0 <= bt_chamber && bt_chamber < 13) && (0 <= bt_segment && bt_segment < 2));
1313   // bt_segment is a 7-bit word, HHCCCCS, encoding the segment number S in the chamber (1 or 2),
1314   // the chamber number CCCC ("j" above: uniquely identifies chamber within station and ring),
1315   // and the history HH (0 for current BX, 1 for previous BX, 2 for BX before that)
1316   bt_segment = ((bt_history & 0x3) << 5) | ((bt_chamber & 0xf) << 1) | (bt_segment & 0x1);
1317   return bt_segment;
1318 }
1319 
1320 bool PrimitiveConversion::is_valid_for_run2(const EMTFHit& conv_hit) const {
1321   bool is_csc = conv_hit.Is_CSC();
1322   bool is_rpc = conv_hit.Is_RPC();
1323   bool is_irpc = conv_hit.Is_RPC() && ((conv_hit.Station() == 3 || conv_hit.Station() == 4) && (conv_hit.Ring() == 1));
1324   bool is_omtf = conv_hit.Is_RPC() && ((conv_hit.Station() == 1 || conv_hit.Station() == 2) &&
1325                                        (conv_hit.Ring() == 3));  // RPC in the overlap region
1326   return (is_csc || (is_rpc && !is_irpc && !is_omtf));
1327 }