Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 //-------------------------------------------------
0002 //
0003 //   Class: L1MuGMTMerger
0004 //
0005 //   Description:  GMT Merger
0006 //
0007 //
0008 //
0009 //   Author :
0010 //   H. Sakulin                   HEPHY Vienna
0011 //
0012 //   Migrated to CMSSW:
0013 //   I. Mikulec
0014 //
0015 //--------------------------------------------------
0016 
0017 //-----------------------
0018 // This Class's Header --
0019 //-----------------------
0020 
0021 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTMerger.h"
0022 
0023 //---------------
0024 // C++ Headers --
0025 //---------------
0026 
0027 #include <iostream>
0028 #include <vector>
0029 #include <cmath>
0030 
0031 //-------------------------------
0032 // Collaborating Class Headers --
0033 //-------------------------------
0034 
0035 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTConfig.h"
0036 #include "L1Trigger/GlobalMuonTrigger/interface/L1MuGlobalMuonTrigger.h"
0037 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTPSB.h"
0038 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTSortRankUnit.h"
0039 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTMatcher.h"
0040 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTCancelOutUnit.h"
0041 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTMipIsoAU.h"
0042 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTExtendedCand.h"
0043 
0044 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankEtaQLUT.h"
0045 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankPtQLUT.h"
0046 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankEtaPhiLUT.h"
0047 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankCombineLUT.h"
0048 
0049 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFEtaConvLUT.h"
0050 
0051 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFPhiProEtaConvLUT.h"
0052 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFPhiProLUT.h"
0053 
0054 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFPtMixLUT.h"
0055 
0056 #include "CondFormats/L1TObjects/interface/L1MuTriggerScales.h"
0057 #include "CondFormats/L1TObjects/interface/L1MuTriggerPtScale.h"
0058 
0059 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTReg.h"
0060 
0061 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0062 
0063 //---------------------------------
0064 //       class L1MuGMTMerger
0065 //---------------------------------
0066 
0067 //----------------
0068 // Constructors --
0069 //----------------
0070 L1MuGMTMerger::L1MuGMTMerger(const L1MuGlobalMuonTrigger& gmt, int id) : m_gmt(gmt), m_id(id), dtcsc_mu(4), rpc_mu(4) {
0071   dtcsc_mu.reserve(4);
0072   rpc_mu.reserve(4);
0073 }
0074 
0075 //--------------
0076 // Destructor --
0077 //--------------
0078 L1MuGMTMerger::~L1MuGMTMerger() { reset(); }
0079 
0080 //--------------
0081 // Operations --
0082 //--------------
0083 
0084 //
0085 // run Merger
0086 //
0087 void L1MuGMTMerger::run() {
0088   load();
0089   merge();
0090 }
0091 
0092 //
0093 // reset Merger
0094 //
0095 void L1MuGMTMerger::reset() {
0096   for (int i = 0; i < 4; i++) {
0097     dtcsc_mu[i] = nullptr;
0098     rpc_mu[i] = nullptr;
0099   }
0100 
0101   std::vector<L1MuGMTExtendedCand*>::iterator iter;
0102   for (iter = m_MuonCands.begin(); iter != m_MuonCands.end(); iter++) {
0103     if (*iter)
0104       delete (*iter);
0105     *iter = nullptr;
0106   }
0107 
0108   m_MuonCands.clear();
0109 }
0110 
0111 //
0112 // print selection results
0113 //
0114 void L1MuGMTMerger::print() const {
0115   edm::LogVerbatim("GMT_Merger_info") << " ";
0116 
0117   std::vector<L1MuGMTExtendedCand*>::const_iterator iter;
0118   for (iter = m_MuonCands.begin(); iter != m_MuonCands.end(); iter++) {
0119     if (*iter && !(*iter)->empty())
0120       (*iter)->print();
0121   }
0122 
0123   edm::LogVerbatim("GMT_Merger_info") << " ";
0124 }
0125 
0126 //
0127 // load Merger (get data from PSB)
0128 //
0129 void L1MuGMTMerger::load() {
0130   // barrel Merger gets DTBX and barrel RPC muons
0131   if (m_id == 0) {
0132     for (unsigned idt = 0; idt < L1MuGMTConfig::MAXDTBX; idt++) {
0133       dtcsc_mu[idt] = m_gmt.Data()->DTBXMuon(idt);
0134     }
0135     for (unsigned irpc = 0; irpc < L1MuGMTConfig::MAXRPCbarrel; irpc++) {
0136       rpc_mu[irpc] = m_gmt.Data()->RPCMuon(irpc);
0137     }
0138   }
0139 
0140   // endcap Merger gets CSC and endcap RPC muons
0141   if (m_id == 1) {
0142     for (unsigned icsc = 0; icsc < L1MuGMTConfig::MAXCSC; icsc++) {
0143       dtcsc_mu[icsc] = m_gmt.Data()->CSCMuon(icsc);
0144     }
0145     for (unsigned irpc = 0; irpc < L1MuGMTConfig::MAXRPCendcap; irpc++) {
0146       rpc_mu[irpc] = m_gmt.Data()->RPCMuon(irpc + 4);
0147     }
0148   }
0149 }
0150 
0151 void L1MuGMTMerger::merge() {
0152   const L1MuGMTMatrix<bool>& pairM = m_gmt.Matcher(m_id)->pairM();
0153 
0154   // Handling of cancel-out and empty muons is different in software and hardware
0155   //
0156   // - in hardware, a candidate may be empty (pt_code == 0) and an empty bit
0157   //   is passed to the sorter in order to suppress the candidate. In the
0158   //   software no candidate is created in this case.
0159   //
0160   // - in hardware, RPC candidates are passed to the sorter even if they are
0161   //   also used in a matched pair. They are then suppressed in the sorter. In
0162   //   software no RPC candidate is created if the muon is used in a pair.
0163   //
0164   // - in hardware, cancel-out signals from the cancel-out units in the own and
0165   //   other Logic FPGA are passed to the sorter in order to cancel out muons.
0166   //   In software the cancel-out signals are alrady checked here in the merger
0167   //   and no candidates are created for cancelled muons.
0168   //
0169   // There may therefore be less muons passed to the sorter in software than
0170   // in Hardware. At the output of the first sorter stage the results should
0171   // be comparable, again.
0172 
0173   unsigned HaloOverwritesMatched = 1;
0174 
0175   // loop over DT/CSC muons
0176   for (int i = 0; i < 4; i++) {
0177     if (dtcsc_mu[i] != nullptr) {
0178       int match_idx = pairM.rowAny(i);
0179 
0180       int csc_is_halo = (m_id == 1) && (dtcsc_mu[i]->finehalo_packed() == 1);
0181 
0182       if ((match_idx != -1) &&  // is it matched?
0183           (!(csc_is_halo && HaloOverwritesMatched)))
0184         createMergedCand(i, match_idx);
0185       else {
0186         // check my first and the other chip's second cancel-out units
0187         if ((!m_gmt.CancelOutUnit(m_id)->cancelMyChipMuon(i)) &&
0188             (!m_gmt.CancelOutUnit(3 - m_id)->cancelOtherChipMuon(i)) && (!L1MuGMTSortRankUnit::isDisabled(dtcsc_mu[i])))
0189           createDTCSCCand(i);
0190       }
0191     }
0192   }
0193 
0194   // additionally loop over RPC muons
0195   for (int j = 0; j < 4; j++) {
0196     if (rpc_mu[j] != nullptr) {
0197       int match_idx = pairM.colAny(j);
0198 
0199       if (match_idx == -1) {  // is it unmatched?
0200         if ((!m_gmt.CancelOutUnit(m_id + 2)->cancelMyChipMuon(j)) && (!L1MuGMTSortRankUnit::isDisabled(rpc_mu[j])))
0201           createRPCCand(j);
0202       }
0203     }
0204   }
0205 
0206   // set physical values in the GMT candidates for use in the analysis
0207   const L1MuTriggerScales* theTriggerScales = L1MuGMTConfig::getTriggerScales();
0208   const L1MuTriggerPtScale* theTriggerPtScale = L1MuGMTConfig::getTriggerPtScale();
0209 
0210   std::vector<L1MuGMTExtendedCand*>::const_iterator icand;
0211   for (icand = m_MuonCands.begin(); icand != m_MuonCands.end(); icand++) {
0212     L1MuGMTExtendedCand* cand = (*icand);
0213     cand->setPhiValue(theTriggerScales->getPhiScale()->getLowEdge(cand->phiIndex()));
0214     cand->setEtaValue(theTriggerScales->getGMTEtaScale()->getCenter(cand->etaIndex()));
0215     cand->setPtValue(theTriggerPtScale->getPtScale()->getLowEdge(cand->ptIndex()));
0216     // cand->setPtValue( theTriggerScales->getPtScale()->getLowEdge( cand->ptIndex() ));
0217   }
0218 }
0219 
0220 void L1MuGMTMerger::createDTCSCCand(int idx_dtcsc) {
0221   L1MuGMTExtendedCand* tmpmuon = new L1MuGMTExtendedCand();
0222 
0223   tmpmuon->setBx(dtcsc_mu[idx_dtcsc]->bx());
0224   tmpmuon->setPhiPacked(projectedPhi(dtcsc_mu[idx_dtcsc]));
0225   tmpmuon->setEtaPacked(convertedEta(dtcsc_mu[idx_dtcsc]));
0226   tmpmuon->setPtPacked(dtcsc_mu[idx_dtcsc]->pt_packed());
0227   tmpmuon->setChargePacked(sysign(dtcsc_mu[idx_dtcsc]));
0228   tmpmuon->setMIP(m_gmt.MipIsoAU(m_id)->MIP(idx_dtcsc));
0229   tmpmuon->setIsolation(m_gmt.MipIsoAU(m_id)->ISO(idx_dtcsc));
0230   tmpmuon->setRank(L1MuGMTSortRankUnit::sort_rank(dtcsc_mu[idx_dtcsc]));
0231 
0232   unsigned quality = 0;
0233   switch (L1MuGMTSortRankUnit::getVeryLowQualityLevel(dtcsc_mu[idx_dtcsc])) {
0234     case 0:
0235       quality = 6;
0236       break;  //DT/CSC
0237     case 1:
0238       quality = 2;
0239       break;  //VERY LOW QUALITY LEVEL 1
0240     case 2:
0241       quality = 3;
0242       break;  //VERY LOW QUALITY LEVEL 2
0243     case 3:
0244       quality = 4;
0245       break;  //VERY LOW QUALITY LEVEL 3
0246   }
0247 
0248   if ((m_id == 1) && (dtcsc_mu[idx_dtcsc]->finehalo_packed() == 1))
0249     quality = 1;  // HALO quality
0250 
0251   tmpmuon->setQuality(quality);  // RPC
0252   tmpmuon->setDTCSCIndex(idx_dtcsc);
0253   tmpmuon->setRPCIndex(0);
0254   tmpmuon->setFwdBit(m_id);
0255   tmpmuon->setRPCBit(0);
0256 
0257   m_MuonCands.push_back(tmpmuon);
0258 }
0259 
0260 void L1MuGMTMerger::createRPCCand(int idx_rpc) {
0261   L1MuGMTExtendedCand* tmpmuon = new L1MuGMTExtendedCand();
0262 
0263   tmpmuon->setBx(rpc_mu[idx_rpc]->bx());
0264   tmpmuon->setPhiPacked(projectedPhi(rpc_mu[idx_rpc]));
0265   tmpmuon->setEtaPacked(convertedEta(rpc_mu[idx_rpc]));
0266   tmpmuon->setPtPacked(rpc_mu[idx_rpc]->pt_packed());
0267   tmpmuon->setChargePacked(sysign(rpc_mu[idx_rpc]));
0268   tmpmuon->setMIP(m_gmt.MipIsoAU(m_id)->MIP(idx_rpc + 4));
0269   tmpmuon->setIsolation(m_gmt.MipIsoAU(m_id)->ISO(idx_rpc + 4));
0270   tmpmuon->setRank(L1MuGMTSortRankUnit::sort_rank(rpc_mu[idx_rpc]));
0271 
0272   unsigned quality = 0;
0273   switch (L1MuGMTSortRankUnit::getVeryLowQualityLevel(rpc_mu[idx_rpc])) {
0274     case 0:
0275       quality = 5;
0276       break;  //RPC
0277     case 1:
0278       quality = 2;
0279       break;  //VERY LOW QUALITY LEVEL1
0280     case 2:
0281       quality = 3;
0282       break;  //VERY LOW QUALITY LEVEL2
0283     case 3:
0284       quality = 4;
0285       break;  //VERY LOW QUALITY LEVEL3
0286   }
0287 
0288   tmpmuon->setQuality(quality);  // RPC
0289   tmpmuon->setDTCSCIndex(0);
0290   tmpmuon->setRPCIndex(idx_rpc);
0291   tmpmuon->setFwdBit(m_id);
0292   tmpmuon->setRPCBit(1);
0293 
0294   m_MuonCands.push_back(tmpmuon);
0295 }
0296 
0297 int L1MuGMTMerger::selectDTCSC(unsigned MMconfig, int by_rank, int by_pt, int by_combi) const {
0298   return ((MMconfig & 32) == 32) || (((MMconfig & 8) == 8) && by_rank) || (((MMconfig & 4) == 4) && by_pt) ||
0299          (((MMconfig & 2) == 2) && by_combi);
0300 }
0301 
0302 int L1MuGMTMerger::doSpecialMerge(unsigned MMconfig) const { return (MMconfig & 1) == 1; }
0303 
0304 int L1MuGMTMerger::doANDMerge(unsigned MMconfig) const { return (MMconfig & 64) == 64; }
0305 
0306 unsigned L1MuGMTMerger::convertedEta(const L1MuRegionalCand* mu) const {
0307   L1MuGMTLFEtaConvLUT* etaconv_lut = L1MuGMTConfig::getLFEtaConvLUT();
0308   return etaconv_lut->SpecificLookup_eta_gmt(mu->type_idx(), mu->eta_packed());
0309 }
0310 
0311 unsigned L1MuGMTMerger::projectedPhi(const L1MuRegionalCand* mu) const {
0312   // convert eta
0313   L1MuGMTLFPhiProEtaConvLUT* phiproetaconv_lut = L1MuGMTConfig::getLFPhiProEtaConvLUT();
0314   unsigned eta4 = phiproetaconv_lut->SpecificLookup_eta_out(mu->type_idx(), mu->eta_packed());
0315 
0316   // look up delta-phi 9 bit signed
0317   L1MuGMTLFPhiProLUT* phipro_lut = L1MuGMTConfig::getLFPhiProLUT();
0318   unsigned dphi9 = phipro_lut->SpecificLookup_dphi(mu->type_idx(), eta4, mu->pt_packed(), mu->charge_packed());
0319 
0320   // sign extend
0321   L1MuSignedPacking<9> DPhiPacking;
0322   int dphi = DPhiPacking.idxFromPacked(dphi9);
0323 
0324   // add modulo 144
0325   int newphi = mu->phi_packed() + dphi;
0326   if (newphi < 0)
0327     newphi += 144;
0328   if (newphi >= 144)
0329     newphi -= 144;
0330 
0331   return (unsigned)newphi;
0332 }
0333 
0334 unsigned L1MuGMTMerger::sysign(const L1MuRegionalCand* mu) const {
0335   unsigned sysign = mu->charge_packed();
0336 
0337   if (mu->charge_valid_packed() == 0)
0338     sysign = 2;  // undefined charge
0339 
0340   return sysign;
0341 }
0342 
0343 void L1MuGMTMerger::createMergedCand(int idx_dtcsc, int idx_rpc) {
0344   // In the hardware matrices of select_bits are calculated for all
0345   // possible pairings.
0346   // In ORCA we only calculate selec-bits for the actual
0347   // pairs to save time.
0348 
0349   // look up merge ranks
0350   int merge_rank_dtcsc = merge_rank(dtcsc_mu[idx_dtcsc]);
0351   int merge_rank_rpc = merge_rank(rpc_mu[idx_rpc]);
0352 
0353   // calculate select-bits (1: take DT/CSC, 0: take RPC)
0354   // fix: if equal prefer DT/CSC as in HW!
0355   //  int selected_by_rank = abs(merge_rank_dtcsc) > abs(merge_rank_rpc);
0356   int selected_by_rank = abs(merge_rank_dtcsc) >= abs(merge_rank_rpc);
0357   int selected_by_pt = dtcsc_mu[idx_dtcsc]->pt_packed() <= rpc_mu[idx_rpc]->pt_packed();
0358 
0359   // Selection by combination of min pt and higher rank
0360   // select by rank if both flags are set, otherwise by min pt
0361   // in other words: select by minpt if one flag is not set
0362   int selected_by_combi = (merge_rank_dtcsc < 0 && merge_rank_rpc < 0) ? selected_by_rank : selected_by_pt;
0363 
0364   L1MuGMTExtendedCand* tmpmuon = new L1MuGMTExtendedCand();
0365 
0366   tmpmuon->setBx(dtcsc_mu[idx_dtcsc]->bx());
0367 
0368   // merge phi
0369   //  unsigned MMConfig_phi = 32; // take DT
0370   unsigned MMConfig_phi = L1MuGMTConfig::getRegMMConfigPhi()->getValue(m_id);
0371 
0372   unsigned phi = 0;
0373 
0374   if (selectDTCSC(MMConfig_phi, selected_by_rank, selected_by_pt, selected_by_combi))
0375     phi = projectedPhi(dtcsc_mu[idx_dtcsc]);
0376   else
0377     phi = projectedPhi(rpc_mu[idx_rpc]);
0378 
0379   tmpmuon->setPhiPacked(phi);
0380 
0381   // merge eta
0382   unsigned MMConfig_eta = L1MuGMTConfig::getRegMMConfigEta()->getValue(m_id);
0383 
0384   unsigned eta = 0;
0385 
0386   if (doSpecialMerge(MMConfig_eta)) {
0387     if ((m_id == 1) || dtcsc_mu[idx_dtcsc]->finehalo_packed())
0388       eta = convertedEta(dtcsc_mu[idx_dtcsc]);
0389     else
0390       eta = convertedEta(rpc_mu[idx_rpc]);
0391   } else {
0392     if (selectDTCSC(MMConfig_eta, selected_by_rank, selected_by_pt, selected_by_combi))
0393       eta = convertedEta(dtcsc_mu[idx_dtcsc]);
0394     else
0395       eta = convertedEta(rpc_mu[idx_rpc]);
0396   }
0397   tmpmuon->setEtaPacked(eta);
0398 
0399   // merge pt
0400   unsigned MMConfig_pt = L1MuGMTConfig::getRegMMConfigPt()->getValue(m_id);
0401 
0402   unsigned pt = 0;
0403 
0404   if (doSpecialMerge(MMConfig_pt)) {  // mix pt
0405     L1MuGMTLFPtMixLUT* ptmix_lut = L1MuGMTConfig::getLFPtMixLUT();
0406     pt = ptmix_lut->SpecificLookup_pt_mixed(m_id, dtcsc_mu[idx_dtcsc]->pt_packed(), rpc_mu[idx_rpc]->pt_packed());
0407   } else {
0408     if (selectDTCSC(MMConfig_pt, selected_by_rank, selected_by_pt, selected_by_combi))
0409       pt = dtcsc_mu[idx_dtcsc]->pt_packed();
0410     else
0411       pt = rpc_mu[idx_rpc]->pt_packed();
0412   }
0413   tmpmuon->setPtPacked(pt);
0414 
0415   // merge charge
0416   unsigned MMConfig_charge = L1MuGMTConfig::getRegMMConfigCharge()->getValue(m_id);
0417 
0418   unsigned sy_sign = 0;
0419 
0420   if (doSpecialMerge(MMConfig_charge)) {
0421     // based on charge valid bits
0422     if (rpc_mu[idx_rpc]->charge_valid_packed() == 1 && dtcsc_mu[idx_dtcsc]->charge_valid_packed() == 0)
0423       sy_sign = sysign(rpc_mu[idx_rpc]);
0424     else
0425       sy_sign = sysign(dtcsc_mu[idx_dtcsc]);
0426   } else {
0427     if (selectDTCSC(MMConfig_charge, selected_by_rank, selected_by_pt, selected_by_combi))
0428       sy_sign = sysign(dtcsc_mu[idx_dtcsc]);
0429     else
0430       sy_sign = sysign(rpc_mu[idx_rpc]);
0431   }
0432   tmpmuon->setChargePacked(sy_sign);
0433 
0434   // merge quality
0435 
0436   // merge MIP
0437   unsigned MMConfig_MIP = L1MuGMTConfig::getRegMMConfigMIP()->getValue(m_id);
0438 
0439   bool mip_bit = false;
0440 
0441   bool mip_bit_dtcsc = m_gmt.MipIsoAU(m_id)->MIP(idx_dtcsc);
0442   bool mip_bit_rpc = m_gmt.MipIsoAU(m_id)->MIP(idx_rpc + 4);
0443 
0444   if (doSpecialMerge(MMConfig_MIP)) {
0445     if (doANDMerge(MMConfig_MIP))
0446       mip_bit = mip_bit_dtcsc && mip_bit_rpc;
0447     else
0448       mip_bit = mip_bit_dtcsc || mip_bit_rpc;
0449   } else {
0450     if (selectDTCSC(MMConfig_MIP, selected_by_rank, selected_by_pt, selected_by_combi))
0451       mip_bit = mip_bit_dtcsc;
0452     else
0453       mip_bit = mip_bit_rpc;
0454   }
0455 
0456   tmpmuon->setMIP(mip_bit);
0457 
0458   // merge ISO
0459   unsigned MMConfig_ISO = L1MuGMTConfig::getRegMMConfigISO()->getValue(m_id);
0460 
0461   bool iso_bit = false;
0462 
0463   bool iso_bit_dtcsc = m_gmt.MipIsoAU(m_id)->ISO(idx_dtcsc);
0464   bool iso_bit_rpc = m_gmt.MipIsoAU(m_id)->ISO(idx_rpc + 4);
0465 
0466   if (doSpecialMerge(MMConfig_ISO)) {
0467     if (doANDMerge(MMConfig_ISO))
0468       iso_bit = iso_bit_dtcsc && iso_bit_rpc;
0469     else
0470       iso_bit = iso_bit_dtcsc || iso_bit_rpc;
0471   } else {
0472     if (selectDTCSC(MMConfig_ISO, selected_by_rank, selected_by_pt, selected_by_combi))
0473       iso_bit = iso_bit_dtcsc;
0474     else
0475       iso_bit = iso_bit_rpc;
0476   }
0477 
0478   tmpmuon->setIsolation(iso_bit);
0479 
0480   // merge sort rank
0481   unsigned MMConfig_SRK = L1MuGMTConfig::getRegMMConfigSRK()->getValue(m_id);
0482 
0483   unsigned rank_offset = L1MuGMTConfig::getRegSortRankOffset()->getValue(m_id);
0484 
0485   unsigned rank = 0;
0486   if (selectDTCSC(MMConfig_SRK, selected_by_rank, selected_by_pt, selected_by_combi))
0487     rank = L1MuGMTSortRankUnit::sort_rank(dtcsc_mu[idx_dtcsc]) + rank_offset;
0488   else
0489     rank = L1MuGMTSortRankUnit::sort_rank(rpc_mu[idx_rpc]) + rank_offset;
0490 
0491   tmpmuon->setRank(rank);
0492 
0493   // quality of merged candidate
0494   tmpmuon->setQuality(7);  // code for matched muons
0495 
0496   tmpmuon->setDTCSCIndex(idx_dtcsc);
0497   tmpmuon->setRPCIndex(idx_rpc);
0498   tmpmuon->setFwdBit(m_id);
0499   tmpmuon->setRPCBit(0);
0500 
0501   m_MuonCands.push_back(tmpmuon);
0502 }
0503 
0504 // calculate merge rank as in HW
0505 
0506 int L1MuGMTMerger::merge_rank(const L1MuRegionalCand* muon) const {
0507   if (muon == nullptr || muon->empty())
0508     return 0;
0509 
0510   unsigned lut_idx = muon->type_idx();
0511 
0512   // obtain inputs as coded in HW
0513   unsigned eta = muon->eta_packed();
0514   unsigned q = muon->quality_packed();
0515   unsigned pt = muon->pt_packed();
0516   unsigned phi = muon->phi_packed();
0517 
0518   // lookup eta-q
0519   L1MuGMTLFMergeRankEtaQLUT* etaq_lut = L1MuGMTConfig::getLFMergeRankEtaQLUT();
0520   unsigned rank_etaq = etaq_lut->SpecificLookup_rank_etaq(lut_idx, eta, q);
0521   unsigned flag = etaq_lut->SpecificLookup_flag(lut_idx, eta, q);
0522 
0523   // lookup pt-q
0524   L1MuGMTLFMergeRankPtQLUT* ptq_lut = L1MuGMTConfig::getLFMergeRankPtQLUT();
0525   unsigned rank_ptq = ptq_lut->SpecificLookup_rank_ptq(lut_idx, q, pt);
0526 
0527   // lookup etaphi
0528   L1MuGMTLFMergeRankEtaPhiLUT* etaphi_lut = L1MuGMTConfig::getLFMergeRankEtaPhiLUT();
0529   unsigned rank_etaphi = etaphi_lut->SpecificLookup_rank_etaphi(lut_idx, eta, phi);
0530 
0531   // combine
0532   L1MuGMTLFMergeRankCombineLUT* combine_lut = L1MuGMTConfig::getLFMergeRankCombineLUT();
0533   unsigned rank = combine_lut->SpecificLookup_merge_rank(lut_idx, rank_etaq, rank_ptq, rank_etaphi);
0534 
0535   int rank_signed = rank;
0536 
0537   if (flag == 1)
0538     rank_signed *= -1;
0539 
0540   return rank_signed;
0541 }