CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/L1Trigger/GlobalMuonTrigger/src/L1MuGMTMerger.cc

Go to the documentation of this file.
00001 //-------------------------------------------------
00002 //
00003 //   Class: L1MuGMTMerger
00004 //
00005 //   Description:  GMT Merger
00006 //
00007 //
00008 //   $Date $
00009 //   $Revision $
00010 //
00011 //   Author :
00012 //   H. Sakulin                   HEPHY Vienna
00013 //
00014 //   Migrated to CMSSW:
00015 //   I. Mikulec
00016 //
00017 //--------------------------------------------------
00018 
00019 //-----------------------
00020 // This Class's Header --
00021 //-----------------------
00022 
00023 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTMerger.h"
00024 
00025 //---------------
00026 // C++ Headers --
00027 //---------------
00028 
00029 #include <iostream>
00030 #include <vector>
00031 #include <cmath>
00032 
00033 //-------------------------------
00034 // Collaborating Class Headers --
00035 //-------------------------------
00036 
00037 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTConfig.h"
00038 #include "L1Trigger/GlobalMuonTrigger/interface/L1MuGlobalMuonTrigger.h"
00039 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTPSB.h"
00040 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTSortRankUnit.h"
00041 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTMatcher.h"
00042 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTCancelOutUnit.h"
00043 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTMipIsoAU.h"
00044 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTExtendedCand.h"
00045 
00046 
00047 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankEtaQLUT.h"
00048 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankPtQLUT.h"
00049 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankEtaPhiLUT.h"
00050 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFMergeRankCombineLUT.h"
00051 
00052 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFEtaConvLUT.h"
00053 
00054 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFPhiProEtaConvLUT.h"
00055 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFPhiProLUT.h"
00056 
00057 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTLFPtMixLUT.h"
00058 
00059 #include "CondFormats/L1TObjects/interface/L1MuTriggerScales.h"
00060 #include "CondFormats/L1TObjects/interface/L1MuTriggerPtScale.h"
00061 
00062 #include "L1Trigger/GlobalMuonTrigger/src/L1MuGMTReg.h"
00063   
00064 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00065 
00066 //---------------------------------
00067 //       class L1MuGMTMerger
00068 //---------------------------------
00069 
00070 //----------------
00071 // Constructors --
00072 //----------------
00073 L1MuGMTMerger::L1MuGMTMerger(const L1MuGlobalMuonTrigger& gmt, int id) : 
00074   m_gmt(gmt), m_id(id), dtcsc_mu(4), rpc_mu(4) {
00075 
00076   dtcsc_mu.reserve(4);
00077   rpc_mu.reserve(4);
00078    
00079 }
00080 
00081 //--------------
00082 // Destructor --
00083 //--------------
00084 L1MuGMTMerger::~L1MuGMTMerger() { 
00085   reset();  
00086 }
00087 
00088 //--------------
00089 // Operations --
00090 //--------------
00091 
00092 //
00093 // run Merger
00094 //
00095 void L1MuGMTMerger::run() {
00096   load();
00097   merge();  
00098 }
00099 
00100 
00101 //
00102 // reset Merger
00103 //
00104 void L1MuGMTMerger::reset() {
00105 
00106   for ( int i = 0; i < 4; i++ ) {  
00107     dtcsc_mu[i] = 0;
00108     rpc_mu[i] = 0;
00109   }
00110   
00111   std::vector<L1MuGMTExtendedCand*>::iterator iter;
00112   for ( iter = m_MuonCands.begin(); iter != m_MuonCands.end(); iter++ ) {
00113     if ( *iter ) delete (*iter); 
00114     *iter = 0;
00115   }
00116 
00117   m_MuonCands.clear();
00118 
00119 }
00120 
00121 
00122 //
00123 // print selection results
00124 //
00125 void L1MuGMTMerger::print() const {
00126 
00127   edm::LogVerbatim("GMT_Merger_info") << " ";
00128 
00129   std::vector<L1MuGMTExtendedCand*>::const_iterator iter;
00130   for ( iter = m_MuonCands.begin(); iter != m_MuonCands.end(); iter++ ) {
00131     if ( *iter && !(*iter)->empty() ) (*iter)->print();
00132   }
00133   
00134   edm::LogVerbatim("GMT_Merger_info") << " ";
00135 
00136 }
00137 
00138 
00139 //
00140 // load Merger (get data from PSB)
00141 //
00142 void L1MuGMTMerger::load() {
00143 
00144   // barrel Merger gets DTBX and barrel RPC muons
00145   if ( m_id == 0 ) {
00146     for ( unsigned idt = 0; idt < L1MuGMTConfig::MAXDTBX; idt++ ) {
00147       dtcsc_mu[idt] = m_gmt.Data()->DTBXMuon(idt);
00148     }
00149     for ( unsigned irpc = 0; irpc < L1MuGMTConfig::MAXRPCbarrel; irpc++ ) {
00150       rpc_mu[irpc] = m_gmt.Data()->RPCMuon(irpc);
00151     }
00152   }
00153   
00154   // endcap Merger gets CSC and endcap RPC muons
00155   if ( m_id == 1 ) {  
00156     for ( unsigned icsc = 0; icsc < L1MuGMTConfig::MAXCSC; icsc++ ) {
00157       dtcsc_mu[icsc] = m_gmt.Data()->CSCMuon(icsc);
00158     }
00159     for ( unsigned irpc = 0; irpc < L1MuGMTConfig::MAXRPCendcap; irpc++ ) {
00160       rpc_mu[irpc] = m_gmt.Data()->RPCMuon(irpc+4);
00161     }
00162   }
00163  
00164 }
00165 
00166 
00167 void L1MuGMTMerger::merge() {
00168 
00169   const L1MuGMTMatrix<bool>& pairM = m_gmt.Matcher(m_id)->pairM();
00170 
00171   // Handling of cancel-out and empty muons is different in software and hardware
00172   //
00173   // - in hardware, a candidate may be empty (pt_code == 0) and an empty bit
00174   //   is passed to the sorter in order to suppress the candidate. In the
00175   //   software no candidate is created in this case.
00176   //
00177   // - in hardware, RPC candidates are passed to the sorter even if they are 
00178   //   also used in a matched pair. They are then suppressed in the sorter. In
00179   //   software no RPC candidate is created if the muon is used in a pair.
00180   //
00181   // - in hardware, cancel-out signals from the cancel-out units in the own and   
00182   //   other Logic FPGA are passed to the sorter in order to cancel out muons.
00183   //   In software the cancel-out signals are alrady checked here in the merger 
00184   //   and no candidates are created for cancelled muons.
00185   //
00186   // There may therefore be less muons passed to the sorter in software than 
00187   // in Hardware. At the output of the first sorter stage the results should 
00188   // be comparable, again.
00189   
00190   unsigned HaloOverwritesMatched = 1;
00191   
00192   // loop over DT/CSC muons
00193   for (int i=0; i<4; i++) {
00194     if (dtcsc_mu[i] != 0) {
00195 
00196       int match_idx = pairM.rowAny(i);
00197 
00198       int csc_is_halo = (m_id==1) && (dtcsc_mu[i]->finehalo_packed() == 1);
00199 
00200       if ( (match_idx != -1) && // is it matched?
00201            (! (csc_is_halo && HaloOverwritesMatched) ) )
00202         createMergedCand(i, match_idx);         
00203       else {
00204         // check my first and the other chip's second cancel-out units
00205         if ((! m_gmt.CancelOutUnit(m_id)->cancelMyChipMuon(i) ) &&
00206             (! m_gmt.CancelOutUnit(3-m_id)->cancelOtherChipMuon(i) ) &&
00207             (! L1MuGMTSortRankUnit::isDisabled(dtcsc_mu[i]) ) )
00208           createDTCSCCand(i);
00209       }
00210     }
00211   }
00212 
00213   // additionally loop over RPC muons
00214   for (int j=0; j<4; j++) {
00215     if (rpc_mu[j] != 0) {      
00216       
00217       int match_idx = pairM.colAny(j);
00218       
00219       if (match_idx == -1) { // is it unmatched?
00220         if ((! m_gmt.CancelOutUnit(m_id+2)->cancelMyChipMuon(j) ) &&
00221             (! L1MuGMTSortRankUnit::isDisabled(rpc_mu[j]) ) )
00222           createRPCCand(j);
00223       }
00224     }
00225   }
00226 
00227   // set physical values in the GMT candidates for use in the analysis
00228   const L1MuTriggerScales* theTriggerScales = L1MuGMTConfig::getTriggerScales();
00229   const L1MuTriggerPtScale* theTriggerPtScale = L1MuGMTConfig::getTriggerPtScale();
00230   
00231   std::vector<L1MuGMTExtendedCand*>::const_iterator icand;
00232   for(icand=m_MuonCands.begin();icand!=m_MuonCands.end();icand++) {
00233     L1MuGMTExtendedCand* cand = (*icand);
00234     cand->setPhiValue( theTriggerScales->getPhiScale()->getLowEdge( cand->phiIndex() ));
00235     cand->setEtaValue( theTriggerScales->getGMTEtaScale()->getCenter( cand->etaIndex() ));
00236     cand->setPtValue( theTriggerPtScale->getPtScale()->getLowEdge( cand->ptIndex() ));
00237     // cand->setPtValue( theTriggerScales->getPtScale()->getLowEdge( cand->ptIndex() ));
00238   }
00239 
00240 }
00241 
00242 void L1MuGMTMerger::createDTCSCCand(int idx_dtcsc) {
00243   L1MuGMTExtendedCand* tmpmuon = new L1MuGMTExtendedCand();
00244    
00245   tmpmuon->setBx(dtcsc_mu[idx_dtcsc]->bx());
00246   tmpmuon->setPhiPacked( projectedPhi(dtcsc_mu[idx_dtcsc]) ); 
00247   tmpmuon->setEtaPacked( convertedEta(dtcsc_mu[idx_dtcsc]) ); 
00248   tmpmuon->setPtPacked( dtcsc_mu[idx_dtcsc]->pt_packed() ); 
00249   tmpmuon->setChargePacked( sysign(dtcsc_mu[idx_dtcsc]) ); 
00250   tmpmuon->setMIP( m_gmt.MipIsoAU(m_id)->MIP(idx_dtcsc) );    
00251   tmpmuon->setIsolation ( m_gmt.MipIsoAU(m_id)->ISO(idx_dtcsc) );    
00252   tmpmuon->setRank( L1MuGMTSortRankUnit::sort_rank(dtcsc_mu[idx_dtcsc]) );
00253 
00254   unsigned quality = 0;
00255   switch ( L1MuGMTSortRankUnit::getVeryLowQualityLevel(dtcsc_mu[idx_dtcsc]) ) {
00256   case 0: quality = 6; break; //DT/CSC
00257   case 1: quality = 2; break; //VERY LOW QUALITY LEVEL 1
00258   case 2: quality = 3; break; //VERY LOW QUALITY LEVEL 2
00259   case 3: quality = 4; break; //VERY LOW QUALITY LEVEL 3
00260   }
00261 
00262   if ( (m_id==1) && (dtcsc_mu[idx_dtcsc]->finehalo_packed() == 1) ) 
00263     quality = 1; // HALO quality
00264 
00265   tmpmuon->setQuality( quality ); // RPC
00266   tmpmuon->setDTCSCIndex(idx_dtcsc);
00267   tmpmuon->setRPCIndex(0);
00268   tmpmuon->setFwdBit( m_id );
00269   tmpmuon->setRPCBit( 0 );
00270 
00271   m_MuonCands.push_back(tmpmuon);
00272 }
00273 
00274 
00275 void L1MuGMTMerger::createRPCCand(int idx_rpc) {
00276   L1MuGMTExtendedCand* tmpmuon = new L1MuGMTExtendedCand();
00277    
00278   tmpmuon->setBx(rpc_mu[idx_rpc]->bx()); 
00279   tmpmuon->setPhiPacked( projectedPhi(rpc_mu[idx_rpc]) ); 
00280   tmpmuon->setEtaPacked( convertedEta(rpc_mu[idx_rpc]) ); 
00281   tmpmuon->setPtPacked( rpc_mu[idx_rpc]->pt_packed() ); 
00282   tmpmuon->setChargePacked( sysign( rpc_mu[idx_rpc] ) ); 
00283   tmpmuon->setMIP( m_gmt.MipIsoAU(m_id)->MIP(idx_rpc+4) );    
00284   tmpmuon->setIsolation ( m_gmt.MipIsoAU(m_id)->ISO(idx_rpc+4) );    
00285   tmpmuon->setRank( L1MuGMTSortRankUnit::sort_rank(rpc_mu[idx_rpc]) );
00286 
00287   unsigned quality = 0;
00288   switch ( L1MuGMTSortRankUnit::getVeryLowQualityLevel(rpc_mu[idx_rpc]) ) {
00289   case 0: quality = 5; break; //RPC
00290   case 1: quality = 2; break; //VERY LOW QUALITY LEVEL1
00291   case 2: quality = 3; break; //VERY LOW QUALITY LEVEL2
00292   case 3: quality = 4; break; //VERY LOW QUALITY LEVEL3
00293   }
00294 
00295   tmpmuon->setQuality( quality ); // RPC
00296   tmpmuon->setDTCSCIndex(0);
00297   tmpmuon->setRPCIndex(idx_rpc);
00298   tmpmuon->setFwdBit( m_id );
00299   tmpmuon->setRPCBit( 1 );
00300     
00301   m_MuonCands.push_back(tmpmuon);
00302 }
00303 
00304 int L1MuGMTMerger::selectDTCSC(unsigned MMconfig, int by_rank, int by_pt, int by_combi) const {
00305   return 
00306     (   (MMconfig & 32) == 32 ) ||
00307     ( ( (MMconfig &  8) ==  8 ) && by_rank ) ||
00308     ( ( (MMconfig &  4) ==  4 ) && by_pt   ) ||
00309     ( ( (MMconfig &  2) ==  2 ) && by_combi);
00310 
00311 } 
00312 
00313 int L1MuGMTMerger::doSpecialMerge(unsigned MMconfig) const {
00314   return (MMconfig & 1) == 1;
00315 }
00316 
00317 int L1MuGMTMerger::doANDMerge(unsigned MMconfig) const {
00318   return (MMconfig & 64) == 64;
00319 }
00320 
00321 unsigned L1MuGMTMerger::convertedEta(const L1MuRegionalCand* mu) const {
00322   L1MuGMTLFEtaConvLUT* etaconv_lut = L1MuGMTConfig::getLFEtaConvLUT();
00323   return etaconv_lut->SpecificLookup_eta_gmt (mu->type_idx(), mu->eta_packed() );
00324 }
00325 
00326 unsigned L1MuGMTMerger::projectedPhi(const L1MuRegionalCand* mu) const {
00327 
00328   // convert eta
00329   L1MuGMTLFPhiProEtaConvLUT* phiproetaconv_lut = L1MuGMTConfig::getLFPhiProEtaConvLUT();
00330   unsigned eta4 = phiproetaconv_lut->SpecificLookup_eta_out (mu->type_idx(), mu->eta_packed() );
00331   
00332   // look up delta-phi 9 bit signed
00333   L1MuGMTLFPhiProLUT* phipro_lut = L1MuGMTConfig::getLFPhiProLUT();
00334   unsigned dphi9 = phipro_lut->SpecificLookup_dphi (mu->type_idx(), eta4, mu->pt_packed(), mu->charge_packed());
00335   
00336   // sign extend
00337   L1MuSignedPacking<9> DPhiPacking;
00338   int dphi = DPhiPacking.idxFromPacked( dphi9 );
00339   
00340   // add modulo 144
00341   int newphi = mu->phi_packed() + dphi; 
00342   if (newphi < 0) newphi += 144;
00343   if (newphi >= 144) newphi -= 144;
00344 
00345   return (unsigned) newphi;  
00346 }
00347 
00348 
00349 unsigned L1MuGMTMerger::sysign(const L1MuRegionalCand* mu) const {
00350 
00351   unsigned sysign = mu->charge_packed();
00352 
00353   if ( mu->charge_valid_packed() == 0 )
00354     sysign = 2; // undefined charge
00355 
00356   return sysign;
00357 }
00358 
00359 void L1MuGMTMerger::createMergedCand(int idx_dtcsc, int idx_rpc) {
00360 
00361   // In the hardware matrices of select_bits are calculated for all
00362   // possible pairings. 
00363   // In ORCA we only calculate selec-bits for the actual 
00364   // pairs to save time.
00365 
00366   // look up merge ranks
00367   int merge_rank_dtcsc = merge_rank(dtcsc_mu[idx_dtcsc]);
00368   int merge_rank_rpc   = merge_rank(rpc_mu[idx_rpc]);
00369 
00370   // calculate select-bits (1: take DT/CSC, 0: take RPC)
00371   int selected_by_rank = abs(merge_rank_dtcsc) > abs(merge_rank_rpc);
00372   int selected_by_pt   = dtcsc_mu[idx_dtcsc]->pt_packed() <= rpc_mu[idx_rpc]->pt_packed();
00373 
00374   // Selection by combination of min pt and higher rank
00375   // select by rank if both flags are set, otherwise by min pt
00376   // in other words: select by minpt if one flag is not set
00377   int selected_by_combi = (merge_rank_dtcsc<0 && merge_rank_rpc<0) ? selected_by_rank : selected_by_pt;
00378 
00379   
00380   L1MuGMTExtendedCand* tmpmuon = new L1MuGMTExtendedCand();
00381    
00382   tmpmuon->setBx(dtcsc_mu[idx_dtcsc]->bx());
00383 
00384 
00385   // merge phi
00386   //  unsigned MMConfig_phi = 32; // take DT
00387   unsigned MMConfig_phi = L1MuGMTConfig::getRegMMConfigPhi()->getValue(m_id);
00388 
00389   unsigned phi = 0;
00390   
00391   if (selectDTCSC(MMConfig_phi, selected_by_rank, selected_by_pt, selected_by_combi) )
00392     phi = projectedPhi( dtcsc_mu[idx_dtcsc] );
00393   else
00394     phi = projectedPhi( rpc_mu[idx_rpc] );
00395 
00396   tmpmuon->setPhiPacked( phi );
00397    
00398   // merge eta
00399   unsigned MMConfig_eta = L1MuGMTConfig::getRegMMConfigEta()->getValue(m_id);
00400 
00401   unsigned eta = 0;
00402   
00403   if (doSpecialMerge( MMConfig_eta ) ) {
00404     if ( (m_id == 1) || dtcsc_mu[idx_dtcsc]->finehalo_packed() ) 
00405       eta = convertedEta( dtcsc_mu[idx_dtcsc] );
00406     else
00407       eta = convertedEta( rpc_mu[idx_rpc] );
00408   } 
00409   else {
00410     if ( selectDTCSC(MMConfig_eta, selected_by_rank, selected_by_pt, selected_by_combi) )
00411       eta = convertedEta( dtcsc_mu[idx_dtcsc] );
00412     else
00413       eta = convertedEta( rpc_mu[idx_rpc] );    
00414   }
00415   tmpmuon->setEtaPacked( eta );
00416 
00417   // merge pt
00418   unsigned MMConfig_pt = L1MuGMTConfig::getRegMMConfigPt()->getValue(m_id);
00419 
00420   unsigned pt = 0;
00421 
00422   if (doSpecialMerge( MMConfig_pt ) ) { // mix pt
00423     L1MuGMTLFPtMixLUT* ptmix_lut = L1MuGMTConfig::getLFPtMixLUT();
00424     pt = ptmix_lut->SpecificLookup_pt_mixed (m_id, dtcsc_mu[idx_dtcsc]->pt_packed(), 
00425                                              rpc_mu[idx_rpc]->pt_packed());    
00426   } 
00427   else {
00428     if ( selectDTCSC(MMConfig_pt, selected_by_rank, selected_by_pt, selected_by_combi) )
00429       pt = dtcsc_mu[idx_dtcsc]->pt_packed();
00430     else
00431       pt = rpc_mu[idx_rpc]->pt_packed();
00432   }
00433   tmpmuon->setPtPacked( pt );
00434 
00435   // merge charge
00436   unsigned MMConfig_charge = L1MuGMTConfig::getRegMMConfigCharge()->getValue(m_id);
00437 
00438   unsigned sy_sign = 0;
00439 
00440   if (doSpecialMerge( MMConfig_charge ) ) {
00441     // based on charge valid bits
00442     if ( rpc_mu[idx_rpc]->charge_valid_packed()==1 && dtcsc_mu[idx_dtcsc]->charge_valid_packed()==0 )
00443       sy_sign = sysign(rpc_mu[idx_rpc]);
00444     else 
00445       sy_sign = sysign(dtcsc_mu[idx_dtcsc]);
00446   } 
00447   else {
00448     if ( selectDTCSC(MMConfig_charge, selected_by_rank, selected_by_pt, selected_by_combi) )
00449       sy_sign = sysign(dtcsc_mu[idx_dtcsc]);
00450     else
00451       sy_sign = sysign(rpc_mu[idx_rpc]);
00452   }
00453   tmpmuon->setChargePacked( sy_sign );
00454    
00455   // merge quality  
00456 
00457   
00458   // merge MIP
00459   unsigned MMConfig_MIP = L1MuGMTConfig::getRegMMConfigMIP()->getValue(m_id);
00460 
00461   bool mip_bit = false;
00462 
00463   bool mip_bit_dtcsc = m_gmt.MipIsoAU(m_id)->MIP(idx_dtcsc);
00464   bool mip_bit_rpc   = m_gmt.MipIsoAU(m_id)->MIP(idx_rpc+4);
00465  
00466   if ( doSpecialMerge(MMConfig_MIP) ) {
00467     if ( doANDMerge(MMConfig_MIP) )
00468       mip_bit =  mip_bit_dtcsc && mip_bit_rpc;
00469     else
00470       mip_bit =  mip_bit_dtcsc || mip_bit_rpc;
00471   }
00472   else {
00473     if ( selectDTCSC(MMConfig_MIP, selected_by_rank, selected_by_pt, selected_by_combi) )
00474       mip_bit = mip_bit_dtcsc;
00475     else
00476       mip_bit = mip_bit_rpc;
00477   }
00478 
00479   tmpmuon->setMIP(mip_bit);
00480  
00481   // merge ISO
00482   unsigned MMConfig_ISO = L1MuGMTConfig::getRegMMConfigISO()->getValue(m_id);
00483 
00484   bool iso_bit = false;
00485 
00486   bool iso_bit_dtcsc = m_gmt.MipIsoAU(m_id)->ISO(idx_dtcsc);
00487   bool iso_bit_rpc   = m_gmt.MipIsoAU(m_id)->ISO(idx_rpc+4);
00488  
00489   if ( doSpecialMerge(MMConfig_ISO) ) {
00490     if ( doANDMerge(MMConfig_ISO) )
00491       iso_bit =  iso_bit_dtcsc && iso_bit_rpc;
00492     else
00493       iso_bit =  iso_bit_dtcsc || iso_bit_rpc;
00494   }
00495   else {
00496     if ( selectDTCSC(MMConfig_ISO, selected_by_rank, selected_by_pt, selected_by_combi) )
00497       iso_bit = iso_bit_dtcsc;
00498     else
00499       iso_bit = iso_bit_rpc;
00500   }
00501 
00502   tmpmuon->setIsolation(iso_bit);
00503 
00504   // merge sort rank
00505   unsigned MMConfig_SRK = L1MuGMTConfig::getRegMMConfigSRK()->getValue(m_id);
00506 
00507   unsigned rank_offset = L1MuGMTConfig::getRegSortRankOffset()->getValue(m_id);
00508 
00509   unsigned rank = 0;
00510   if ( selectDTCSC(MMConfig_SRK, selected_by_rank, selected_by_pt, selected_by_combi) )
00511     rank = L1MuGMTSortRankUnit::sort_rank(dtcsc_mu[idx_dtcsc]) + rank_offset; 
00512   else
00513     rank = L1MuGMTSortRankUnit::sort_rank(rpc_mu[idx_rpc])     + rank_offset;
00514 
00515   tmpmuon->setRank(rank); 
00516 
00517   // quality of merged candidate
00518   tmpmuon->setQuality( 7 ); // code for matched muons
00519 
00520   tmpmuon->setDTCSCIndex(idx_dtcsc);
00521   tmpmuon->setRPCIndex(idx_rpc);
00522   tmpmuon->setFwdBit( m_id );
00523   tmpmuon->setRPCBit( 0 );
00524    
00525   m_MuonCands.push_back(tmpmuon);
00526 }
00527 
00528 // calculate merge rank as in HW
00529 
00530 int L1MuGMTMerger::merge_rank(const L1MuRegionalCand* muon) const {
00531 
00532   if ( muon == 0 || muon->empty() ) return 0;
00533 
00534   unsigned lut_idx= muon->type_idx();
00535   
00536   // obtain inputs as coded in HW
00537   unsigned eta = muon->eta_packed();
00538   unsigned q = muon->quality_packed();
00539   unsigned pt  = muon->pt_packed();
00540   unsigned phi = muon->phi_packed();
00541 
00542   // lookup eta-q
00543   L1MuGMTLFMergeRankEtaQLUT* etaq_lut = L1MuGMTConfig::getLFMergeRankEtaQLUT();
00544   unsigned rank_etaq = etaq_lut->SpecificLookup_rank_etaq (lut_idx, eta, q);
00545   unsigned flag = etaq_lut->SpecificLookup_flag (lut_idx, eta, q);
00546    
00547   // lookup pt-q
00548   L1MuGMTLFMergeRankPtQLUT* ptq_lut = L1MuGMTConfig::getLFMergeRankPtQLUT();
00549   unsigned rank_ptq = ptq_lut->SpecificLookup_rank_ptq (lut_idx, q, pt);
00550   
00551   // lookup etaphi
00552   L1MuGMTLFMergeRankEtaPhiLUT* etaphi_lut = L1MuGMTConfig::getLFMergeRankEtaPhiLUT();
00553   unsigned rank_etaphi = etaphi_lut->SpecificLookup_rank_etaphi (lut_idx, eta, phi);
00554   
00555   // combine
00556   L1MuGMTLFMergeRankCombineLUT* combine_lut = L1MuGMTConfig::getLFMergeRankCombineLUT();
00557   unsigned rank = combine_lut->SpecificLookup_merge_rank (lut_idx, rank_etaq, rank_ptq, rank_etaphi);
00558 
00559   int rank_signed = rank;
00560 
00561   if (flag == 1) rank_signed *= -1;
00562    
00563   return rank_signed;
00564 }
00565 
00566 
00567 
00568