Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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   // condition result condResult set to true if at least one permutation
0145   //     passes all requirements
0146   // all possible permutations are checked
0147   bool condResult = false;
0148 
0149   // store the indices of the muon objects
0150   // from the combination evaluated in the condition
0151   SingleCombInCond objectsInComb;
0152   objectsInComb.reserve(nObjInCond);
0153 
0154   // clear the m_combinationsInCond vector
0155   combinationsInCond().clear();
0156 
0157   do {
0158     if (--jumpIndex)
0159       continue;
0160 
0161     jumpIndex = jump;
0162 
0163     // clear the indices in the combination
0164     objectsInComb.clear();
0165 
0166     bool tmpResult = true;
0167 
0168     bool passCondition = false;
0169     // check if there is a permutation that matches object-parameter requirements
0170     for (int i = 0; i < nObjInCond; i++) {
0171       passCondition = checkObjectParameter(i, *(candVec->at(useBx, index[i])), index[i]);  //BLW Change for BXVector
0172       tmpResult &= passCondition;
0173       if (passCondition)
0174         LogDebug("L1TGlobal") << "===> MuCondition::evaluateCondition, CONGRATS!! This muon passed the condition."
0175                               << std::endl;
0176       else
0177         LogDebug("L1TGlobal") << "===> MuCondition::evaluateCondition, FAIL!! This muon failed the condition."
0178                               << std::endl;
0179       objectsInComb.push_back(index[i]);
0180     }
0181 
0182     // if permutation does not match particle conditions
0183     // skip charge correlation and spatial correlations
0184     if (!tmpResult) {
0185       continue;
0186     }
0187 
0188     // get the correlation parameters (chargeCorrelation included here also)
0189     MuonTemplate::CorrelationParameter corrPar = *(m_gtMuonTemplate->correlationParameter());
0190 
0191     // charge_correlation consists of 3 relevant bits (D2, D1, D0)
0192     unsigned int chargeCorr = corrPar.chargeCorrelation;
0193 
0194     // charge ignore bit (D0) not set?
0195     if ((chargeCorr & 1) == 0) {
0196       LogDebug("L1TGlobal") << "===> MuCondition:: Checking Charge Correlation" << std::endl;
0197 
0198       for (int i = 0; i < nObjInCond; i++) {
0199         // check valid charge - skip if invalid charge
0200         int chargeValid = (candVec->at(useBx, index[i]))->hwChargeValid();  //BLW Change for BXVector
0201         tmpResult &= chargeValid;
0202 
0203         if (chargeValid == 0) {  //BLW type change for New Muon Class
0204           continue;
0205         }
0206       }
0207 
0208       if (!tmpResult) {
0209         LogDebug("L1TGlobal") << "===> MuCondition:: Charge Correlation Failed...No Valid Charges" << std::endl;
0210         continue;
0211       }
0212 
0213       if (nObjInCond > 1) {  // more objects condition
0214 
0215         // find out if signs are equal
0216         bool equalSigns = true;
0217         for (int i = 0; i < nObjInCond - 1; i++) {
0218           if ((candVec->at(useBx, index[i]))->hwCharge() !=
0219               (candVec->at(useBx, index[i + 1]))->hwCharge()) {  //BLW Change for BXVector
0220             equalSigns = false;
0221             break;
0222           }
0223         }
0224 
0225         LogDebug("L1TGlobal") << "===> MuCondition:: Checking Charge Correlation equalSigns = " << equalSigns
0226                               << std::endl;
0227 
0228         // two or three particle condition
0229         if (nObjInCond == 2 || nObjInCond == 3) {
0230           if (!(((chargeCorr & 2) != 0 && equalSigns) || ((chargeCorr & 4) != 0 && !equalSigns))) {
0231             LogDebug("L1TGlobal") << "===> MuCondition:: 2/3 Muon Fail Charge Correlation Condition =" << chargeCorr
0232                                   << std::endl;
0233             continue;
0234           }
0235         } else if (nObjInCond == 4) {
0236           //counter to count positive charges to determine if there are pairs
0237           unsigned int posCount = 0;
0238 
0239           for (int i = 0; i < nObjInCond; i++) {
0240             if ((candVec->at(useBx, index[i]))->hwCharge() > 0) {  //BLW Change for BXVector
0241               posCount++;
0242             }
0243           }
0244 
0245           // Original OS 4 muon condition (disagreement with firmware):
0246           //    if (!(((chargeCorr & 2) != 0 && equalSigns) || ((chargeCorr & 4) != 0 && posCount == 2))) {
0247           // Fix by R. Cavanaugh:
0248           //       Note that negative charge => hwCharge = 0
0249           //                 positive charge => hwCharge = 1
0250           //       Hence:  (0,0,0,0) => (posCount = 0) => 4 SS muons
0251           //               (1,0,0,0) => (posCount = 1) => 1 OS muon pair, 1 SS muon pair
0252           //               (1,1,0,0) => (posCount = 2) => 2 OS muon pairs
0253           //               (1,0,1,0) => (posCount = 2) => 2 OS muon pairs
0254           //               (0,0,1,1) => (posCount = 2) => 2 OS muon pairs
0255           //               (1,1,1,0) => (posCount = 3) => 1 SS muon pair, 1 OS muon pair
0256           //               (1,1,1,1) => (posCount = 4) => 4 SS muons
0257           //       A requirement (posCount == 2) implies there must be exactly 2 OS pairs of muons
0258           //       A requirement of at least 1 pair of OS muons implies condition should be (posCount > 0 && posCount < 4)
0259           if (!(((chargeCorr & 2) != 0 && equalSigns) || ((chargeCorr & 4) != 0 && (posCount > 0 && posCount < 4)))) {
0260             LogDebug("L1TGlobal") << "===> MuCondition:: 4 Muon Fail Charge Correlation Condition = " << chargeCorr
0261                                   << " posCnt " << posCount << std::endl;
0262             continue;
0263           }
0264         }
0265       }  // end require nObjInCond > 1
0266     }    // end signchecks
0267 
0268     if (m_gtMuonTemplate->wsc()) {
0269       // wsc requirements have always nObjInCond = 2
0270       // one can use directly index[0] and index[1] to compute
0271       // eta and phi differences
0272       const int ObjInWscComb = 2;
0273       if (nObjInCond != ObjInWscComb) {
0274         edm::LogError("L1TGlobal") << "\n  Error: "
0275                                    << "number of particles in condition with spatial correlation = " << nObjInCond
0276                                    << "\n  it must be = " << ObjInWscComb << std::endl;
0277         // TODO Perhaps I should throw here an exception,
0278         // since something is really wrong if nObjInCond != ObjInWscComb (=2)
0279         continue;
0280       }
0281 
0282       // check delta eta
0283       if (!checkRangeDeltaEta((candVec->at(useBx, 0))->hwEtaAtVtx(),
0284                               (candVec->at(useBx, 1))->hwEtaAtVtx(),
0285                               corrPar.deltaEtaRangeLower,
0286                               corrPar.deltaEtaRangeUpper,
0287                               8)) {
0288         LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRangeDeltaEta" << std::endl;
0289         continue;
0290       }
0291 
0292       // check delta phi
0293       if (!checkRangeDeltaPhi((candVec->at(useBx, 0))->hwPhiAtVtx(),
0294                               (candVec->at(useBx, 1))->hwPhiAtVtx(),
0295                               corrPar.deltaPhiRangeLower,
0296                               corrPar.deltaPhiRangeUpper)) {
0297         LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRangeDeltaPhi" << std::endl;
0298         continue;
0299       }
0300 
0301     }  // end wsc check
0302 
0303     // if we get here all checks were successfull for this combination
0304     // set the general result for evaluateCondition to "true"
0305 
0306     condResult = true;
0307     (combinationsInCond()).push_back(objectsInComb);
0308 
0309   } while (std::next_permutation(index.begin(), index.end()));
0310 
0311   return condResult;
0312 }
0313 
0314 // load muon candidates
0315 const l1t::Muon* l1t::MuCondition::getCandidate(const int bx, const int indexCand) const {
0316   return (m_gtGTL->getCandL1Mu())->at(bx, indexCand);  //BLW Change for BXVector
0317 }
0318 
0319 /**
0320  * checkObjectParameter - Compare a single particle with a numbered condition.
0321  *
0322  * @param iCondition The number of the condition.
0323  * @param cand The candidate to compare.
0324  *
0325  * @return The result of the comparison (false if a condition does not exist).
0326  */
0327 
0328 const bool l1t::MuCondition::checkObjectParameter(const int iCondition,
0329                                                   const l1t::Muon& cand,
0330                                                   const unsigned int index) const {
0331   // number of objects in condition
0332   int nObjInCond = m_gtMuonTemplate->nrObjects();
0333 
0334   if (iCondition >= nObjInCond || iCondition < 0) {
0335     return false;
0336   }
0337 
0338   //     // empty candidates can not be compared
0339   //     if (cand.empty()) {
0340   //         return false;
0341   //     }
0342 
0343   const MuonTemplate::ObjectParameter objPar = (*(m_gtMuonTemplate->objectParameter()))[iCondition];
0344 
0345   // using the logic table from GTL-9U-module.pdf
0346   // "Truth table for Isolation bit"
0347 
0348   // check thresholds:
0349 
0350   //   value < low pt threshold
0351   //       fail trigger
0352 
0353   //   low pt threshold <= value < high pt threshold & non-isolated muon:
0354   //       requestIso true:                    fail trigger
0355   //       requestIso false, enableIso true:   fail trigger
0356   //       requestIso false, enableIso false:  OK,  trigger
0357 
0358   //   low pt threshold <= value < high pt threshold & isolated muon:
0359   //       requestIso true:                    OK,  trigger
0360   //       requestIso false, enableIso true:   OK,  trigger
0361   //       requestIso false, enableIso false:  OK,  trigger
0362 
0363   //   value >= high pt threshold & non-isolated muon:
0364   //       requestIso true:  fail trigger
0365   //       requestIso false: OK,  trigger
0366 
0367   //   value >= high pt threshold & isolated muon:
0368   //       OK, trigger
0369 
0370   LogDebug("L1TGlobal") << "\n MuonTemplate::ObjectParameter : " << std::hex << "\n\t ptHighThreshold = 0x "
0371                         << objPar.ptHighThreshold << "\n\t ptLowThreshold  = 0x " << objPar.ptLowThreshold
0372                         << "\n\t indexHigh       = 0x " << objPar.indexHigh << "\n\t indexLow        = 0x "
0373                         << objPar.indexLow << "\n\t requestIso      = 0x " << objPar.requestIso
0374                         << "\n\t enableIso       = 0x " << objPar.enableIso << "\n\t etaRange        = 0x "
0375                         << objPar.etaRange << "\n\t phiLow          = 0x " << objPar.phiLow
0376                         << "\n\t phiHigh         = 0x " << objPar.phiHigh << "\n\t phiWindow1Lower = 0x "
0377                         << objPar.phiWindow1Lower << "\n\t phiWindow1Upper = 0x " << objPar.phiWindow1Upper
0378                         << "\n\t phiWindow2Lower = 0x " << objPar.phiWindow2Lower << "\n\t phiWindow2Lower = 0x "
0379                         << objPar.phiWindow2Lower << "\n\t charge          = 0x " << objPar.charge
0380                         << "\n\t qualityLUT      = 0x " << objPar.qualityLUT << "\n\t isolationLUT    = 0x "
0381                         << objPar.isolationLUT << "\n\t enableMip       = 0x " << objPar.enableMip << std::endl;
0382 
0383   LogDebug("L1TGlobal") << "\n l1t::Muon : "
0384                         << "\n\t hwPt       = 0x " << cand.hwPt() << "\n\t hwEtaAtVtx = 0x " << cand.hwEtaAtVtx()
0385                         << "\n\t hwPhiAtVtx = 0x " << cand.hwPhiAtVtx() << "\n\t hwCharge   = 0x " << cand.hwCharge()
0386                         << "\n\t hwQual     = 0x " << cand.hwQual() << "\n\t hwIso      = 0x " << cand.hwIso()
0387                         << std::dec << std::endl;
0388 
0389   if (objPar.unconstrainedPtHigh > 0)  // Rick Cavanaugh:  Check if unconstrained pT cut-window is valid
0390   {
0391     if (!checkUnconstrainedPt(objPar.unconstrainedPtLow,
0392                               objPar.unconstrainedPtHigh,
0393                               cand.hwPtUnconstrained(),
0394                               m_gtMuonTemplate->condGEq())) {
0395       LogDebug("L1TGlobal") << "\t\t Muon Failed unconstrainedPt checkThreshold; iCondition = " << iCondition
0396                             << std::endl;
0397       return false;
0398     }
0399   }
0400   if (objPar.impactParameterLUT !=
0401       0)  // Rick Cavanaugh:  Check if impact parameter LUT is valid.  0xF is default; 0x0 is invalid
0402   {
0403     // check impact parameter ( bit check ) with impact parameter LUT
0404     // sanity check on candidate impact parameter
0405     if (cand.hwDXY() > 3) {
0406       LogDebug("L1TGlobal") << "\t\t l1t::Candidate has out of range hwDXY = " << cand.hwDXY() << std::endl;
0407       return false;
0408     }
0409     bool passImpactParameterLUT = ((objPar.impactParameterLUT >> cand.hwDXY()) & 1);
0410     if (!passImpactParameterLUT) {
0411       LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed impact parameter requirement" << std::endl;
0412       return false;
0413     }
0414   }
0415 
0416   if (!checkThreshold(objPar.ptLowThreshold, objPar.ptHighThreshold, cand.hwPt(), m_gtMuonTemplate->condGEq())) {
0417     LogDebug("L1TGlobal") << "\t\t Muon Failed checkThreshold " << std::endl;
0418     return false;
0419   }
0420 
0421   // check index
0422   if (!checkIndex(objPar.indexLow, objPar.indexHigh, index)) {
0423     LogDebug("L1TGlobal") << "\t\t Muon Failed checkIndex " << std::endl;
0424     return false;
0425   }
0426 
0427   // check eta
0428   if (!checkRangeEta(cand.hwEtaAtVtx(), objPar.etaWindows, 8)) {
0429     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRangeEta" << std::endl;
0430     return false;
0431   }
0432 
0433   // check phi
0434   if (!checkRangePhi(cand.hwPhiAtVtx(),
0435                      objPar.phiWindow1Lower,
0436                      objPar.phiWindow1Upper,
0437                      objPar.phiWindow2Lower,
0438                      objPar.phiWindow2Upper)) {
0439     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRange(phi)" << std::endl;
0440     return false;
0441   }
0442 
0443   // check charge
0444   if (objPar.charge >= 0) {
0445     if (cand.hwCharge() != objPar.charge) {
0446       LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed charge requirement" << std::endl;
0447       return false;
0448     }
0449   }
0450 
0451   // check quality ( bit check ) with quality LUT
0452   // sanity check on candidate quality
0453   if (cand.hwQual() > 16) {
0454     LogDebug("L1TGlobal") << "\t\t l1t::Candidate has out of range hwQual = " << cand.hwQual() << std::endl;
0455     return false;
0456   }
0457   bool passQualLUT = ((objPar.qualityLUT >> cand.hwQual()) & 1);
0458   if (!passQualLUT) {
0459     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed quality requirement" << std::endl;
0460     return false;
0461   }
0462 
0463   // check isolation ( bit check ) with isolation LUT
0464   // sanity check on candidate isolation
0465   if (cand.hwIso() > 4) {
0466     LogDebug("L1TGlobal") << "\t\t l1t::Candidate has out of range hwIso = " << cand.hwIso() << std::endl;
0467     return false;
0468   }
0469   bool passIsoLUT = ((objPar.isolationLUT >> cand.hwIso()) & 1);
0470   if (!passIsoLUT) {
0471     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed isolation requirement" << std::endl;
0472     return false;
0473   }
0474 
0475   // check muon TF index
0476   if (!checkRangeTfMuonIndex(cand.tfMuonIndex(), objPar.tfMuonIndexWindows)) {
0477     LogDebug("L1TGlobal") << "\t\t l1t::Candidate failed checkRangeTfMuonIndex" << std::endl;
0478     return false;
0479   }
0480 
0481   // A number of values is required to trigger (at least one).
0482   // "Don't care" means that all values are allowed.
0483   // Qual = 000 means then NO MUON (GTL module)
0484 
0485   // if (cand.hwQual() == 0) {
0486   //    LogDebug("L1TGlobal") << "\t\t Muon Failed hwQual() == 0" << std::endl;
0487   //     return false;
0488   // }
0489 
0490   // if (objPar.qualityRange == 0) {
0491   //    LogDebug("L1TGlobal") << "\t\t Muon Failed qualityRange == 0" << std::endl;
0492   //     return false;
0493   // }
0494   // else {
0495   //   if (!checkBit(objPar.qualityRange, cand.hwQual())) {
0496   //    LogDebug("L1TGlobal") << "\t\t Muon Failed checkBit(qualityRange) " << std::endl;
0497   //         return false;
0498   //     }
0499   // }
0500 
0501   // check mip
0502   if (objPar.enableMip) {
0503     //      if (!cand.hwMip()) {
0504     // LogDebug("L1TGlobal") << "\t\t Muon Failed enableMip" << std::endl;
0505     //          return false;
0506     //      }
0507   }
0508 
0509   // particle matches if we get here
0510   //LogTrace("L1TGlobal")
0511   //    << "  checkObjectParameter: muon object OK, passes all requirements\n" << std::endl;
0512 
0513   return true;
0514 }
0515 
0516 void l1t::MuCondition::print(std::ostream& myCout) const {
0517   m_gtMuonTemplate->print(myCout);
0518 
0519   myCout << "    Number of bits for eta of muon objects = " << m_ifMuEtaNumberBits << std::endl;
0520   myCout << "    Maximum number of bins for the delta phi scales = " << m_corrParDeltaPhiNrBins << "\n " << std::endl;
0521 
0522   ConditionEvaluation::print(myCout);
0523 }