Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-04-08 04:01:56

0001 /**
0002  * \class MuCondition
0003  *
0004  *
0005  * Description: evaluation of a CondMuon condition.
0006  *
0007  * Implementation:
0008  *    <TODO: enter implementation details>
0009  *
0010  * \author: Vasile Mihai Ghete   - HEPHY Vienna
0011  *          Vladimir Rekovic - extend for indexing
0012  *          Rick Cavanaugh - include displaced muons
0013  *
0014  */
0015 
0016 // this class header
0017 #include "L1Trigger/L1TGlobal/interface/MuCondition.h"
0018 
0019 // system include files
0020 #include <iostream>
0021 #include <iomanip>
0022 
0023 #include <string>
0024 #include <vector>
0025 #include <algorithm>
0026 
0027 // user include files
0028 //   base classes
0029 #include "L1Trigger/L1TGlobal/interface/MuonTemplate.h"
0030 #include "L1Trigger/L1TGlobal/interface/ConditionEvaluation.h"
0031 
0032 #include "DataFormats/L1Trigger/interface/Muon.h"
0033 
0034 #include "L1Trigger/L1TGlobal/interface/GlobalBoard.h"
0035 
0036 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0037 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0038 
0039 // constructors
0040 //     default
0041 l1t::MuCondition::MuCondition() : ConditionEvaluation() {
0042   // empty
0043 }
0044 
0045 //     from base template condition (from event setup usually)
0046 l1t::MuCondition::MuCondition(const GlobalCondition* muonTemplate,
0047                               const GlobalBoard* ptrGTL,
0048                               const int nrL1Mu,
0049                               const int ifMuEtaNumberBits)
0050     : ConditionEvaluation(),
0051       m_gtMuonTemplate(static_cast<const MuonTemplate*>(muonTemplate)),
0052       m_gtGTL(ptrGTL),
0053       m_ifMuEtaNumberBits(ifMuEtaNumberBits) {
0054   m_corrParDeltaPhiNrBins = 0;
0055   m_condMaxNumberObjects = nrL1Mu;
0056 }
0057 
0058 // copy constructor
0059 void l1t::MuCondition::copy(const l1t::MuCondition& cp) {
0060   m_gtMuonTemplate = cp.gtMuonTemplate();
0061   m_gtGTL = cp.gtGTL();
0062 
0063   m_ifMuEtaNumberBits = cp.gtIfMuEtaNumberBits();
0064   m_corrParDeltaPhiNrBins = cp.m_corrParDeltaPhiNrBins;
0065 
0066   m_condMaxNumberObjects = cp.condMaxNumberObjects();
0067   m_condLastResult = cp.condLastResult();
0068   m_combinationsInCond = cp.getCombinationsInCond();
0069 
0070   m_verbosity = cp.m_verbosity;
0071 }
0072 
0073 l1t::MuCondition::MuCondition(const l1t::MuCondition& cp) : ConditionEvaluation() { copy(cp); }
0074 
0075 // destructor
0076 l1t::MuCondition::~MuCondition() {
0077   // empty
0078 }
0079 
0080 // equal operator
0081 l1t::MuCondition& l1t::MuCondition::operator=(const l1t::MuCondition& cp) {
0082   copy(cp);
0083   return *this;
0084 }
0085 
0086 // methods
0087 void l1t::MuCondition::setGtMuonTemplate(const MuonTemplate* muonTempl) { m_gtMuonTemplate = muonTempl; }
0088 
0089 ///   set the pointer to GTL
0090 void l1t::MuCondition::setGtGTL(const GlobalBoard* ptrGTL) { m_gtGTL = ptrGTL; }
0091 
0092 //   set the number of bits for eta of muon objects
0093 void l1t::MuCondition::setGtIfMuEtaNumberBits(const int& ifMuEtaNumberBitsValue) {
0094   m_ifMuEtaNumberBits = ifMuEtaNumberBitsValue;
0095 }
0096 
0097 //   set the maximum number of bins for the delta phi scales
0098 void l1t::MuCondition::setGtCorrParDeltaPhiNrBins(const int& corrParDeltaPhiNrBins) {
0099   m_corrParDeltaPhiNrBins = corrParDeltaPhiNrBins;
0100 }
0101 
0102 // try all object permutations and check spatial correlations, if required
0103 const bool l1t::MuCondition::evaluateCondition(const int bxEval) const {
0104   // BLW Need to pass this as an argument
0105   //const int bxEval=0;   //BLW Change for BXVector
0106 
0107   // number of trigger objects in the condition
0108   int nObjInCond = m_gtMuonTemplate->nrObjects();
0109 
0110   // the candidates
0111   const BXVector<const l1t::Muon*>* candVec = m_gtGTL->getCandL1Mu();  //BLW Change for BXVector
0112 
0113   // Look at objects in bx = bx + relativeBx
0114   int useBx = bxEval + m_gtMuonTemplate->condRelativeBx();
0115 
0116   // Fail condition if attempting to get Bx outside of range
0117   if ((useBx < candVec->getFirstBX()) || (useBx > candVec->getLastBX())) {
0118     return false;
0119   }
0120 
0121   int numberObjects = candVec->size(useBx);  //BLW Change for BXVector
0122   //LogTrace("L1TGlobal") << "  numberObjects: " << numberObjects
0123   //    << std::endl;
0124   if (numberObjects < nObjInCond) {
0125     return false;
0126   }
0127 
0128   std::vector<int> index(numberObjects);
0129 
0130   for (int i = 0; i < numberObjects; ++i) {
0131     index[i] = i;
0132   }
0133 
0134   int numberForFactorial = numberObjects - nObjInCond;
0135 
0136   // TEMPORARY FIX UNTIL IMPLEMENT NEW MUON CONDITIONS
0137   int myfactorial = 1;
0138   for (int i = numberForFactorial; i > 0; i--)
0139     myfactorial *= i;
0140 
0141   int jumpIndex = 1;
0142   int jump = myfactorial;  //factorial(numberObjects - nObjInCond);
0143 
0144   int totalLoops = 0;
0145   int passLoops = 0;
0146 
0147   // condition result condResult set to true if at least one permutation
0148   //     passes all requirements
0149   // all possible permutations are checked
0150   bool condResult = false;
0151 
0152   // store the indices of the muon objects
0153   // from the combination evaluated in the condition
0154   SingleCombInCond objectsInComb;
0155   objectsInComb.reserve(nObjInCond);
0156 
0157   // clear the m_combinationsInCond vector
0158   combinationsInCond().clear();
0159 
0160   do {
0161     if (--jumpIndex)
0162       continue;
0163 
0164     jumpIndex = jump;
0165     totalLoops++;
0166 
0167     // clear the indices in the combination
0168     objectsInComb.clear();
0169 
0170     bool tmpResult = true;
0171 
0172     bool passCondition = false;
0173     // check if there is a permutation that matches object-parameter requirements
0174     for (int i = 0; i < nObjInCond; i++) {
0175       passCondition = checkObjectParameter(i, *(candVec->at(useBx, index[i])), index[i]);  //BLW Change for BXVector
0176       tmpResult &= passCondition;
0177       if (passCondition)
0178         LogDebug("L1TGlobal") << "===> MuCondition::evaluateCondition, CONGRATS!! This muon passed the condition."
0179                               << std::endl;
0180       else
0181         LogDebug("L1TGlobal") << "===> MuCondition::evaluateCondition, FAIL!! This muon failed the condition."
0182                               << std::endl;
0183       objectsInComb.push_back(index[i]);
0184     }
0185 
0186     // if permutation does not match particle conditions
0187     // skip charge correlation and spatial correlations
0188     if (!tmpResult) {
0189       continue;
0190     }
0191 
0192     // get the correlation parameters (chargeCorrelation included here also)
0193     MuonTemplate::CorrelationParameter corrPar = *(m_gtMuonTemplate->correlationParameter());
0194 
0195     // charge_correlation consists of 3 relevant bits (D2, D1, D0)
0196     unsigned int chargeCorr = corrPar.chargeCorrelation;
0197 
0198     // charge ignore bit (D0) not set?
0199     if ((chargeCorr & 1) == 0) {
0200       LogDebug("L1TGlobal") << "===> MuCondition:: Checking Charge Correlation" << std::endl;
0201 
0202       for (int i = 0; i < nObjInCond; i++) {
0203         // check valid charge - skip if invalid charge
0204         int chargeValid = (candVec->at(useBx, index[i]))->hwChargeValid();  //BLW Change for BXVector
0205         tmpResult &= chargeValid;
0206 
0207         if (chargeValid == 0) {  //BLW type change for New Muon Class
0208           continue;
0209         }
0210       }
0211 
0212       if (!tmpResult) {
0213         LogDebug("L1TGlobal") << "===> MuCondition:: Charge Correlation Failed...No Valid Charges" << std::endl;
0214         continue;
0215       }
0216 
0217       if (nObjInCond > 1) {  // more objects condition
0218 
0219         // find out if signs are equal
0220         bool equalSigns = true;
0221         for (int i = 0; i < nObjInCond - 1; i++) {
0222           if ((candVec->at(useBx, index[i]))->hwCharge() !=
0223               (candVec->at(useBx, index[i + 1]))->hwCharge()) {  //BLW Change for BXVector
0224             equalSigns = false;
0225             break;
0226           }
0227         }
0228 
0229         LogDebug("L1TGlobal") << "===> MuCondition:: Checking Charge Correlation equalSigns = " << equalSigns
0230                               << std::endl;
0231 
0232         // two or three particle condition
0233         if (nObjInCond == 2 || nObjInCond == 3) {
0234           if (!(((chargeCorr & 2) != 0 && equalSigns) || ((chargeCorr & 4) != 0 && !equalSigns))) {
0235             LogDebug("L1TGlobal") << "===> MuCondition:: 2/3 Muon Fail Charge Correlation Condition =" << chargeCorr
0236                                   << std::endl;
0237             continue;
0238           }
0239         } else if (nObjInCond == 4) {
0240           //counter to count positive charges to determine if there are pairs
0241           unsigned int posCount = 0;
0242 
0243           for (int i = 0; i < nObjInCond; i++) {
0244             if ((candVec->at(useBx, index[i]))->hwCharge() > 0) {  //BLW Change for BXVector
0245               posCount++;
0246             }
0247           }
0248 
0249           // Original OS 4 muon condition (disagreement with firmware):
0250           //    if (!(((chargeCorr & 2) != 0 && equalSigns) || ((chargeCorr & 4) != 0 && posCount == 2))) {
0251           // Fix by R. Cavanaugh:
0252           //       Note that negative charge => hwCharge = 0
0253           //                 positive charge => hwCharge = 1
0254           //       Hence:  (0,0,0,0) => (posCount = 0) => 4 SS muons
0255           //               (1,0,0,0) => (posCount = 1) => 1 OS muon pair, 1 SS muon pair
0256           //               (1,1,0,0) => (posCount = 2) => 2 OS muon pairs
0257           //               (1,0,1,0) => (posCount = 2) => 2 OS muon pairs
0258           //               (0,0,1,1) => (posCount = 2) => 2 OS muon pairs
0259           //               (1,1,1,0) => (posCount = 3) => 1 SS muon pair, 1 OS muon pair
0260           //               (1,1,1,1) => (posCount = 4) => 4 SS muons
0261           //       A requirement (posCount == 2) implies there must be exactly 2 OS pairs of muons
0262           //       A requirement of at least 1 pair of OS muons implies condition should be (posCount > 0 && posCount < 4)
0263           if (!(((chargeCorr & 2) != 0 && equalSigns) || ((chargeCorr & 4) != 0 && (posCount > 0 && posCount < 4)))) {
0264             LogDebug("L1TGlobal") << "===> MuCondition:: 4 Muon Fail Charge Correlation Condition = " << chargeCorr
0265                                   << " posCnt " << posCount << std::endl;
0266             continue;
0267           }
0268         }
0269       }  // end require nObjInCond > 1
0270     }    // end signchecks
0271 
0272     if (m_gtMuonTemplate->wsc()) {
0273       // wsc requirements have always nObjInCond = 2
0274       // one can use directly index[0] and index[1] to compute
0275       // eta and phi differences
0276       const int ObjInWscComb = 2;
0277       if (nObjInCond != ObjInWscComb) {
0278         edm::LogError("L1TGlobal") << "\n  Error: "
0279                                    << "number of particles in condition with spatial correlation = " << nObjInCond
0280                                    << "\n  it must be = " << ObjInWscComb << std::endl;
0281         // TODO Perhaps I should throw here an exception,
0282         // since something is really wrong if nObjInCond != ObjInWscComb (=2)
0283         continue;
0284       }
0285 
0286       // check delta eta
0287       if (!checkRangeDeltaEta((candVec->at(useBx, 0))->hwEtaAtVtx(),
0288                               (candVec->at(useBx, 1))->hwEtaAtVtx(),
0289                               corrPar.deltaEtaRangeLower,
0290                               corrPar.deltaEtaRangeUpper,
0291                               8)) {
0292         LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRangeDeltaEta" << std::endl;
0293         continue;
0294       }
0295 
0296       // check delta phi
0297       if (!checkRangeDeltaPhi((candVec->at(useBx, 0))->hwPhiAtVtx(),
0298                               (candVec->at(useBx, 1))->hwPhiAtVtx(),
0299                               corrPar.deltaPhiRangeLower,
0300                               corrPar.deltaPhiRangeUpper)) {
0301         LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRangeDeltaPhi" << std::endl;
0302         continue;
0303       }
0304 
0305     }  // end wsc check
0306 
0307     // if we get here all checks were successfull for this combination
0308     // set the general result for evaluateCondition to "true"
0309 
0310     condResult = true;
0311     passLoops++;
0312     (combinationsInCond()).push_back(objectsInComb);
0313 
0314   } while (std::next_permutation(index.begin(), index.end()));
0315 
0316   //LogTrace("L1TGlobal")
0317   //    << "\n  MuCondition: total number of permutations found:          " << totalLoops
0318   //    << "\n  MuCondition: number of permutations passing requirements: " << passLoops
0319   //    << "\n" << std::endl;
0320 
0321   return condResult;
0322 }
0323 
0324 // load muon candidates
0325 const l1t::Muon* l1t::MuCondition::getCandidate(const int bx, const int indexCand) const {
0326   return (m_gtGTL->getCandL1Mu())->at(bx, indexCand);  //BLW Change for BXVector
0327 }
0328 
0329 /**
0330  * checkObjectParameter - Compare a single particle with a numbered condition.
0331  *
0332  * @param iCondition The number of the condition.
0333  * @param cand The candidate to compare.
0334  *
0335  * @return The result of the comparison (false if a condition does not exist).
0336  */
0337 
0338 const bool l1t::MuCondition::checkObjectParameter(const int iCondition,
0339                                                   const l1t::Muon& cand,
0340                                                   const unsigned int index) const {
0341   // number of objects in condition
0342   int nObjInCond = m_gtMuonTemplate->nrObjects();
0343 
0344   if (iCondition >= nObjInCond || iCondition < 0) {
0345     return false;
0346   }
0347 
0348   //     // empty candidates can not be compared
0349   //     if (cand.empty()) {
0350   //         return false;
0351   //     }
0352 
0353   const MuonTemplate::ObjectParameter objPar = (*(m_gtMuonTemplate->objectParameter()))[iCondition];
0354 
0355   // using the logic table from GTL-9U-module.pdf
0356   // "Truth table for Isolation bit"
0357 
0358   // check thresholds:
0359 
0360   //   value < low pt threshold
0361   //       fail trigger
0362 
0363   //   low pt threshold <= value < high pt threshold & non-isolated muon:
0364   //       requestIso true:                    fail trigger
0365   //       requestIso false, enableIso true:   fail trigger
0366   //       requestIso false, enableIso false:  OK,  trigger
0367 
0368   //   low pt threshold <= value < high pt threshold & isolated muon:
0369   //       requestIso true:                    OK,  trigger
0370   //       requestIso false, enableIso true:   OK,  trigger
0371   //       requestIso false, enableIso false:  OK,  trigger
0372 
0373   //   value >= high pt threshold & non-isolated muon:
0374   //       requestIso true:  fail trigger
0375   //       requestIso false: OK,  trigger
0376 
0377   //   value >= high pt threshold & isolated muon:
0378   //       OK, trigger
0379 
0380   LogDebug("L1TGlobal") << "\n MuonTemplate::ObjectParameter : " << std::hex << "\n\t ptHighThreshold = 0x "
0381                         << objPar.ptHighThreshold << "\n\t ptLowThreshold  = 0x " << objPar.ptLowThreshold
0382                         << "\n\t indexHigh       = 0x " << objPar.indexHigh << "\n\t indexLow        = 0x "
0383                         << objPar.indexLow << "\n\t requestIso      = 0x " << objPar.requestIso
0384                         << "\n\t enableIso       = 0x " << objPar.enableIso << "\n\t etaRange        = 0x "
0385                         << objPar.etaRange << "\n\t phiLow          = 0x " << objPar.phiLow
0386                         << "\n\t phiHigh         = 0x " << objPar.phiHigh << "\n\t phiWindow1Lower = 0x "
0387                         << objPar.phiWindow1Lower << "\n\t phiWindow1Upper = 0x " << objPar.phiWindow1Upper
0388                         << "\n\t phiWindow2Lower = 0x " << objPar.phiWindow2Lower << "\n\t phiWindow2Lower = 0x "
0389                         << objPar.phiWindow2Lower << "\n\t charge          = 0x " << objPar.charge
0390                         << "\n\t qualityLUT      = 0x " << objPar.qualityLUT << "\n\t isolationLUT    = 0x "
0391                         << objPar.isolationLUT << "\n\t enableMip       = 0x " << objPar.enableMip << std::endl;
0392 
0393   LogDebug("L1TGlobal") << "\n l1t::Muon : "
0394                         << "\n\t hwPt       = 0x " << cand.hwPt() << "\n\t hwEtaAtVtx = 0x " << cand.hwEtaAtVtx()
0395                         << "\n\t hwPhiAtVtx = 0x " << cand.hwPhiAtVtx() << "\n\t hwCharge   = 0x " << cand.hwCharge()
0396                         << "\n\t hwQual     = 0x " << cand.hwQual() << "\n\t hwIso      = 0x " << cand.hwIso()
0397                         << std::dec << std::endl;
0398 
0399   if (objPar.unconstrainedPtHigh > 0)  // Rick Cavanaugh:  Check if unconstrained pT cut-window is valid
0400   {
0401     if (!checkUnconstrainedPt(objPar.unconstrainedPtLow,
0402                               objPar.unconstrainedPtHigh,
0403                               cand.hwPtUnconstrained(),
0404                               m_gtMuonTemplate->condGEq())) {
0405       LogDebug("L1TGlobal") << "\t\t Muon Failed unconstrainedPt checkThreshold; iCondition = " << iCondition
0406                             << std::endl;
0407       return false;
0408     }
0409   }
0410   if (objPar.impactParameterLUT !=
0411       0)  // Rick Cavanaugh:  Check if impact parameter LUT is valid.  0xF is default; 0x0 is invalid
0412   {
0413     // check impact parameter ( bit check ) with impact parameter LUT
0414     // sanity check on candidate impact parameter
0415     if (cand.hwDXY() > 3) {
0416       LogDebug("L1TGlobal") << "\t\t l1t::Candidate has out of range hwDXY = " << cand.hwDXY() << std::endl;
0417       return false;
0418     }
0419     bool passImpactParameterLUT = ((objPar.impactParameterLUT >> cand.hwDXY()) & 1);
0420     if (!passImpactParameterLUT) {
0421       LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed impact parameter requirement" << std::endl;
0422       return false;
0423     }
0424   }
0425 
0426   if (!checkThreshold(objPar.ptLowThreshold, objPar.ptHighThreshold, cand.hwPt(), m_gtMuonTemplate->condGEq())) {
0427     LogDebug("L1TGlobal") << "\t\t Muon Failed checkThreshold " << std::endl;
0428     return false;
0429   }
0430 
0431   // check index
0432   if (!checkIndex(objPar.indexLow, objPar.indexHigh, index)) {
0433     LogDebug("L1TGlobal") << "\t\t Muon Failed checkIndex " << std::endl;
0434     return false;
0435   }
0436 
0437   // check eta
0438   if (!checkRangeEta(cand.hwEtaAtVtx(),
0439                      objPar.etaWindow1Lower,
0440                      objPar.etaWindow1Upper,
0441                      objPar.etaWindow2Lower,
0442                      objPar.etaWindow2Upper,
0443                      8)) {
0444     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRange(eta)" << std::endl;
0445     return false;
0446   }
0447 
0448   // check phi
0449   if (!checkRangePhi(cand.hwPhiAtVtx(),
0450                      objPar.phiWindow1Lower,
0451                      objPar.phiWindow1Upper,
0452                      objPar.phiWindow2Lower,
0453                      objPar.phiWindow2Upper)) {
0454     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRange(phi)" << std::endl;
0455     return false;
0456   }
0457 
0458   // check charge
0459   if (objPar.charge >= 0) {
0460     if (cand.hwCharge() != objPar.charge) {
0461       LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed charge requirement" << std::endl;
0462       return false;
0463     }
0464   }
0465 
0466   // check quality ( bit check ) with quality LUT
0467   // sanity check on candidate quality
0468   if (cand.hwQual() > 16) {
0469     LogDebug("L1TGlobal") << "\t\t l1t::Candidate has out of range hwQual = " << cand.hwQual() << std::endl;
0470     return false;
0471   }
0472   bool passQualLUT = ((objPar.qualityLUT >> cand.hwQual()) & 1);
0473   if (!passQualLUT) {
0474     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed quality requirement" << std::endl;
0475     return false;
0476   }
0477 
0478   // check isolation ( bit check ) with isolation LUT
0479   // sanity check on candidate isolation
0480   if (cand.hwIso() > 4) {
0481     LogDebug("L1TGlobal") << "\t\t l1t::Candidate has out of range hwIso = " << cand.hwIso() << std::endl;
0482     return false;
0483   }
0484   bool passIsoLUT = ((objPar.isolationLUT >> cand.hwIso()) & 1);
0485   if (!passIsoLUT) {
0486     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed isolation requirement" << std::endl;
0487     return false;
0488   }
0489 
0490   // A number of values is required to trigger (at least one).
0491   // "Don't care" means that all values are allowed.
0492   // Qual = 000 means then NO MUON (GTL module)
0493 
0494   // if (cand.hwQual() == 0) {
0495   //    LogDebug("L1TGlobal") << "\t\t Muon Failed hwQual() == 0" << std::endl;
0496   //     return false;
0497   // }
0498 
0499   // if (objPar.qualityRange == 0) {
0500   //    LogDebug("L1TGlobal") << "\t\t Muon Failed qualityRange == 0" << std::endl;
0501   //     return false;
0502   // }
0503   // else {
0504   //   if (!checkBit(objPar.qualityRange, cand.hwQual())) {
0505   //    LogDebug("L1TGlobal") << "\t\t Muon Failed checkBit(qualityRange) " << std::endl;
0506   //         return false;
0507   //     }
0508   // }
0509 
0510   // check mip
0511   if (objPar.enableMip) {
0512     //      if (!cand.hwMip()) {
0513     // LogDebug("L1TGlobal") << "\t\t Muon Failed enableMip" << std::endl;
0514     //          return false;
0515     //      }
0516   }
0517 
0518   // particle matches if we get here
0519   //LogTrace("L1TGlobal")
0520   //    << "  checkObjectParameter: muon object OK, passes all requirements\n" << std::endl;
0521 
0522   return true;
0523 }
0524 
0525 void l1t::MuCondition::print(std::ostream& myCout) const {
0526   m_gtMuonTemplate->print(myCout);
0527 
0528   myCout << "    Number of bits for eta of muon objects = " << m_ifMuEtaNumberBits << std::endl;
0529   myCout << "    Maximum number of bins for the delta phi scales = " << m_corrParDeltaPhiNrBins << "\n " << std::endl;
0530 
0531   ConditionEvaluation::print(myCout);
0532 }