Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 14:22:20

0001 /**
0002  * \class L1GtMuonCondition
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  *
0012  *
0013  */
0014 
0015 // this class header
0016 #include "L1Trigger/GlobalTrigger/interface/L1GtMuonCondition.h"
0017 
0018 // system include files
0019 #include <iomanip>
0020 #include <iostream>
0021 
0022 #include <algorithm>
0023 #include <string>
0024 #include <vector>
0025 
0026 // user include files
0027 //   base classes
0028 #include "CondFormats/L1TObjects/interface/L1GtMuonTemplate.h"
0029 #include "L1Trigger/GlobalTrigger/interface/L1GtConditionEvaluation.h"
0030 
0031 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutSetupFwd.h"
0032 
0033 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTCand.h"
0034 
0035 #include "L1Trigger/GlobalTrigger/interface/L1GlobalTriggerFunctions.h"
0036 #include "L1Trigger/GlobalTrigger/interface/L1GlobalTriggerGTL.h"
0037 
0038 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0039 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0040 
0041 // constructors
0042 //     default
0043 L1GtMuonCondition::L1GtMuonCondition() : L1GtConditionEvaluation() {
0044   // empty
0045 }
0046 
0047 //     from base template condition (from event setup usually)
0048 L1GtMuonCondition::L1GtMuonCondition(const L1GtCondition *muonTemplate,
0049                                      const L1GlobalTriggerGTL *ptrGTL,
0050                                      const int nrL1Mu,
0051                                      const int ifMuEtaNumberBits)
0052     : L1GtConditionEvaluation(),
0053       m_gtMuonTemplate(static_cast<const L1GtMuonTemplate *>(muonTemplate)),
0054       m_gtGTL(ptrGTL),
0055       m_ifMuEtaNumberBits(ifMuEtaNumberBits) {
0056   m_corrParDeltaPhiNrBins = 0;
0057   m_condMaxNumberObjects = nrL1Mu;
0058 }
0059 
0060 // copy constructor
0061 void L1GtMuonCondition::copy(const L1GtMuonCondition &cp) {
0062   m_gtMuonTemplate = cp.gtMuonTemplate();
0063   m_gtGTL = cp.gtGTL();
0064 
0065   m_ifMuEtaNumberBits = cp.gtIfMuEtaNumberBits();
0066   m_corrParDeltaPhiNrBins = cp.m_corrParDeltaPhiNrBins;
0067 
0068   m_condMaxNumberObjects = cp.condMaxNumberObjects();
0069   m_condLastResult = cp.condLastResult();
0070   m_combinationsInCond = cp.getCombinationsInCond();
0071 
0072   m_verbosity = cp.m_verbosity;
0073 }
0074 
0075 L1GtMuonCondition::L1GtMuonCondition(const L1GtMuonCondition &cp) : L1GtConditionEvaluation() { copy(cp); }
0076 
0077 // destructor
0078 L1GtMuonCondition::~L1GtMuonCondition() {
0079   // empty
0080 }
0081 
0082 // equal operator
0083 L1GtMuonCondition &L1GtMuonCondition::operator=(const L1GtMuonCondition &cp) {
0084   copy(cp);
0085   return *this;
0086 }
0087 
0088 // methods
0089 void L1GtMuonCondition::setGtMuonTemplate(const L1GtMuonTemplate *muonTempl) { m_gtMuonTemplate = muonTempl; }
0090 
0091 ///   set the pointer to GTL
0092 void L1GtMuonCondition::setGtGTL(const L1GlobalTriggerGTL *ptrGTL) { m_gtGTL = ptrGTL; }
0093 
0094 //   set the number of bits for eta of muon objects
0095 void L1GtMuonCondition::setGtIfMuEtaNumberBits(const int &ifMuEtaNumberBitsValue) {
0096   m_ifMuEtaNumberBits = ifMuEtaNumberBitsValue;
0097 }
0098 
0099 //   set the maximum number of bins for the delta phi scales
0100 void L1GtMuonCondition::setGtCorrParDeltaPhiNrBins(const int &corrParDeltaPhiNrBins) {
0101   m_corrParDeltaPhiNrBins = corrParDeltaPhiNrBins;
0102 }
0103 
0104 // try all object permutations and check spatial correlations, if required
0105 const bool L1GtMuonCondition::evaluateCondition() const {
0106   // number of trigger objects in the condition
0107   int nObjInCond = m_gtMuonTemplate->nrObjects();
0108 
0109   // the candidates
0110   const std::vector<const L1MuGMTCand *> *candVec = m_gtGTL->getCandL1Mu();
0111 
0112   int numberObjects = candVec->size();
0113   // LogTrace("L1GlobalTrigger") << "  numberObjects: " << numberObjects
0114   //    << std::endl;
0115   if (numberObjects < nObjInCond) {
0116     return false;
0117   }
0118 
0119   std::vector<int> index(numberObjects);
0120 
0121   for (int i = 0; i < numberObjects; ++i) {
0122     index[i] = i;
0123   }
0124 
0125   int jumpIndex = 1;
0126   int jump = factorial(numberObjects - nObjInCond);
0127 
0128   int totalLoops = 0;
0129   int passLoops = 0;
0130 
0131   // condition result condResult set to true if at least one permutation
0132   //     passes all requirements
0133   // all possible permutations are checked
0134   bool condResult = false;
0135 
0136   // store the indices of the muon objects
0137   // from the combination evaluated in the condition
0138   SingleCombInCond objectsInComb;
0139   objectsInComb.reserve(nObjInCond);
0140 
0141   // clear the m_combinationsInCond vector
0142   (combinationsInCond()).clear();
0143 
0144   do {
0145     if (--jumpIndex)
0146       continue;
0147 
0148     jumpIndex = jump;
0149     totalLoops++;
0150 
0151     // clear the indices in the combination
0152     objectsInComb.clear();
0153 
0154     bool tmpResult = true;
0155 
0156     // check if there is a permutation that matches object-parameter
0157     // requirements
0158     for (int i = 0; i < nObjInCond; i++) {
0159       tmpResult &= checkObjectParameter(i, *(*candVec)[index[i]]);
0160       objectsInComb.push_back(index[i]);
0161     }
0162 
0163     // if permutation does not match particle conditions
0164     // skip charge correlation and spatial correlations
0165     if (!tmpResult) {
0166       continue;
0167     }
0168 
0169     // get the correlation parameters (chargeCorrelation included here also)
0170     L1GtMuonTemplate::CorrelationParameter corrPar = *(m_gtMuonTemplate->correlationParameter());
0171 
0172     // charge_correlation consists of 3 relevant bits (D2, D1, D0)
0173     unsigned int chargeCorr = corrPar.chargeCorrelation;
0174 
0175     // charge ignore bit (D0) not set?
0176     if ((chargeCorr & 1) == 0) {
0177       for (int i = 0; i < nObjInCond; i++) {
0178         // check valid charge - skip if invalid charge
0179         bool chargeValid = (*candVec)[index[i]]->charge_valid();
0180         tmpResult &= chargeValid;
0181 
0182         if (!chargeValid) {
0183           continue;
0184         }
0185       }
0186 
0187       if (!tmpResult) {
0188         continue;
0189       }
0190 
0191       if (nObjInCond == 1) {  // one object condition
0192 
0193         // D2..enable pos, D1..enable neg
0194         if (!(((chargeCorr & 4) != 0 && (*candVec)[index[0]]->charge() > 0) ||
0195               ((chargeCorr & 2) != 0 && (*candVec)[index[0]]->charge() < 0))) {
0196           continue;
0197         }
0198 
0199       } else {  // more objects condition
0200 
0201         // find out if signs are equal
0202         bool equalSigns = true;
0203         for (int i = 0; i < nObjInCond - 1; i++) {
0204           if ((*candVec)[index[i]]->charge() != (*candVec)[index[i + 1]]->charge()) {
0205             equalSigns = false;
0206             break;
0207           }
0208         }
0209 
0210         // two or three particle condition
0211         if (nObjInCond == 2 || nObjInCond == 3) {
0212           // D2..enable equal, D1..enable not equal
0213           if (!(((chargeCorr & 4) != 0 && equalSigns) || ((chargeCorr & 2) != 0 && !equalSigns))) {
0214             continue;
0215           }
0216         }
0217 
0218         // four particle condition
0219         if (nObjInCond == 4) {
0220           // counter to count positive charges to determine if there are pairs
0221           unsigned int posCount = 0;
0222 
0223           for (int i = 0; i < nObjInCond; i++) {
0224             if ((*candVec)[index[i]]->charge() > 0) {
0225               posCount++;
0226             }
0227           }
0228 
0229           // D2..enable equal, D1..enable pairs
0230           if (!(((chargeCorr & 4) != 0 && equalSigns) || ((chargeCorr & 2) != 0 && posCount == 2))) {
0231             continue;
0232           }
0233         }
0234       }
0235     }  // end signchecks
0236 
0237     if (m_gtMuonTemplate->wsc()) {
0238       // wsc requirements have always nObjInCond = 2
0239       // one can use directly index[0] and index[1] to compute
0240       // eta and phi differences
0241       const int ObjInWscComb = 2;
0242       if (nObjInCond != ObjInWscComb) {
0243         edm::LogError("L1GlobalTrigger") << "\n  Error: "
0244                                          << "number of particles in condition with spatial correlation = " << nObjInCond
0245                                          << "\n  it must be = " << ObjInWscComb << std::endl;
0246         // TODO Perhaps I should throw here an exception,
0247         // since something is really wrong if nObjInCond != ObjInWscComb (=2)
0248         continue;
0249       }
0250 
0251       unsigned int candDeltaEta;
0252       unsigned int candDeltaPhi;
0253 
0254       // check candDeltaEta
0255 
0256       // get eta index and the sign bit of the eta index (MSB is the sign)
0257       //   signedEta[i] is the signed eta index of (*candVec)[index[i]]
0258       int signedEta[ObjInWscComb];
0259       int signBit[ObjInWscComb] = {0, 0};
0260 
0261       int scaleEta = 1 << (m_ifMuEtaNumberBits - 1);
0262 
0263       for (int i = 0; i < ObjInWscComb; ++i) {
0264         signBit[i] = ((*candVec)[index[i]]->etaIndex() & scaleEta) >> (m_ifMuEtaNumberBits - 1);
0265         signedEta[i] = ((*candVec)[index[i]]->etaIndex()) % scaleEta;
0266 
0267         if (signBit[i] == 1) {
0268           signedEta[i] = (-1) * signedEta[i];
0269         }
0270       }
0271 
0272       // compute candDeltaEta - add 1 if signs are different (due to +0/-0
0273       // indices)
0274       candDeltaEta =
0275           static_cast<int>(std::abs(signedEta[1] - signedEta[0])) + static_cast<int>(signBit[1] ^ signBit[0]);
0276 
0277       if (!checkBit(corrPar.deltaEtaRange, candDeltaEta)) {
0278         continue;
0279       }
0280 
0281       // check candDeltaPhi
0282 
0283       // calculate absolute value of candDeltaPhi
0284       if ((*candVec)[index[0]]->phiIndex() > (*candVec)[index[1]]->phiIndex()) {
0285         candDeltaPhi = (*candVec)[index[0]]->phiIndex() - (*candVec)[index[1]]->phiIndex();
0286       } else {
0287         candDeltaPhi = (*candVec)[index[1]]->phiIndex() - (*candVec)[index[0]]->phiIndex();
0288       }
0289 
0290       // check if candDeltaPhi > 180 (via delta_phi_maxbits)
0291       // delta_phi contains bits for 0..180 (0 and 180 included)
0292       // protect also against infinite loop...
0293 
0294       int nMaxLoop = 10;
0295       int iLoop = 0;
0296 
0297       while (candDeltaPhi >= m_corrParDeltaPhiNrBins) {
0298         unsigned int candDeltaPhiInitial = candDeltaPhi;
0299 
0300         // candDeltaPhi > 180 ==> take 360 - candDeltaPhi
0301         candDeltaPhi = (m_corrParDeltaPhiNrBins - 1) * 2 - candDeltaPhi;
0302         if (m_verbosity) {
0303           LogTrace("L1GlobalTrigger") << "    Initial candDeltaPhi = " << candDeltaPhiInitial
0304                                       << " > m_corrParDeltaPhiNrBins = " << m_corrParDeltaPhiNrBins
0305                                       << "  ==> candDeltaPhi rescaled to: " << candDeltaPhi << " [ loop index " << iLoop
0306                                       << "; breaks after " << nMaxLoop << " loops ]\n"
0307                                       << std::endl;
0308         }
0309 
0310         iLoop++;
0311         if (iLoop > nMaxLoop) {
0312           return false;
0313         }
0314       }
0315 
0316       // delta_phi bitmask is saved in two uint64_t words
0317       if (candDeltaPhi < 64) {
0318         if (!checkBit(corrPar.deltaPhiRange0Word, candDeltaPhi)) {
0319           continue;
0320         }
0321       } else {
0322         if (!checkBit(corrPar.deltaPhiRange1Word, (candDeltaPhi - 64))) {
0323           continue;
0324         }
0325       }
0326 
0327     }  // end wsc check
0328 
0329     // if we get here all checks were successfull for this combination
0330     // set the general result for evaluateCondition to "true"
0331 
0332     condResult = true;
0333     passLoops++;
0334     (combinationsInCond()).push_back(objectsInComb);
0335 
0336   } while (std::next_permutation(index.begin(), index.end()));
0337 
0338   // LogTrace("L1GlobalTrigger")
0339   //    << "\n  L1GtMuonCondition: total number of permutations found: " <<
0340   //    totalLoops
0341   //    << "\n  L1GtMuonCondition: number of permutations passing requirements:
0342   //    " << passLoops
0343   //    << "\n" << std::endl;
0344 
0345   return condResult;
0346 }
0347 
0348 // load muon candidates
0349 const L1MuGMTCand *L1GtMuonCondition::getCandidate(const int indexCand) const {
0350   return (*(m_gtGTL->getCandL1Mu()))[indexCand];
0351 }
0352 
0353 /**
0354  * checkObjectParameter - Compare a single particle with a numbered condition.
0355  *
0356  * @param iCondition The number of the condition.
0357  * @param cand The candidate to compare.
0358  *
0359  * @return The result of the comparison (false if a condition does not exist).
0360  */
0361 
0362 const bool L1GtMuonCondition::checkObjectParameter(const int iCondition, const L1MuGMTCand &cand) const {
0363   // number of objects in condition
0364   int nObjInCond = m_gtMuonTemplate->nrObjects();
0365 
0366   if (iCondition >= nObjInCond || iCondition < 0) {
0367     return false;
0368   }
0369 
0370   // empty candidates can not be compared
0371   if (cand.empty()) {
0372     return false;
0373   }
0374 
0375   const L1GtMuonTemplate::ObjectParameter objPar = (*(m_gtMuonTemplate->objectParameter()))[iCondition];
0376 
0377   // using the logic table from GTL-9U-module.pdf
0378   // "Truth table for Isolation bit"
0379 
0380   // check thresholds:
0381 
0382   //   value < low pt threshold
0383   //       fail trigger
0384 
0385   //   low pt threshold <= value < high pt threshold & non-isolated muon:
0386   //       requestIso true:                    fail trigger
0387   //       requestIso false, enableIso true:   fail trigger
0388   //       requestIso false, enableIso false:  OK,  trigger
0389 
0390   //   low pt threshold <= value < high pt threshold & isolated muon:
0391   //       requestIso true:                    OK,  trigger
0392   //       requestIso false, enableIso true:   OK,  trigger
0393   //       requestIso false, enableIso false:  OK,  trigger
0394 
0395   //   value >= high pt threshold & non-isolated muon:
0396   //       requestIso true:  fail trigger
0397   //       requestIso false: OK,  trigger
0398 
0399   //   value >= high pt threshold & isolated muon:
0400   //       OK, trigger
0401 
0402   if (!checkThreshold(objPar.ptHighThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq())) {
0403     if (!checkThreshold(objPar.ptLowThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq())) {
0404       return false;
0405     } else {
0406       // check isolation
0407       if (!cand.isol()) {
0408         if (objPar.requestIso || objPar.enableIso) {
0409           return false;
0410         }
0411       }
0412     }
0413 
0414   } else {
0415     if (!cand.isol()) {
0416       if (objPar.requestIso) {
0417         return false;
0418       }
0419     }
0420   }
0421 
0422   // check eta
0423 
0424   if (!checkBit(objPar.etaRange, cand.etaIndex())) {
0425     return false;
0426   }
0427 
0428   // check phi  - in the requested range (no LUT used - LUT too big for hw chip)
0429   // for phiLow <= phiHigh takes [phiLow, phiHigh]
0430   // for phiLow >= phiHigh takes [phiLow, phiHigh] over zero angle!
0431 
0432   if (objPar.phiHigh >= objPar.phiLow) {
0433     if (!((objPar.phiLow <= cand.phiIndex()) && (cand.phiIndex() <= objPar.phiHigh))) {
0434       return false;
0435     }
0436 
0437   } else {  // go over zero angle!!
0438     if (!((objPar.phiLow <= cand.phiIndex()) || (cand.phiIndex() <= objPar.phiHigh))) {
0439       return false;
0440     }
0441   }
0442 
0443   // check quality ( bit check )
0444 
0445   // A number of values is required to trigger (at least one).
0446   // "Don’t care" means that all values are allowed.
0447   // Qual = 000 means then NO MUON (GTL module)
0448 
0449   if (cand.quality() == 0) {
0450     return false;
0451   }
0452 
0453   if (objPar.qualityRange == 0) {
0454     return false;
0455   } else {
0456     if (!checkBit(objPar.qualityRange, cand.quality())) {
0457       return false;
0458     }
0459   }
0460 
0461   // check mip
0462   if (objPar.enableMip) {
0463     if (!cand.mip()) {
0464       return false;
0465     }
0466   }
0467 
0468   // particle matches if we get here
0469   // LogTrace("L1GlobalTrigger")
0470   //    << "  checkObjectParameter: muon object OK, passes all requirements\n"
0471   //    << std::endl;
0472 
0473   return true;
0474 }
0475 
0476 void L1GtMuonCondition::print(std::ostream &myCout) const {
0477   m_gtMuonTemplate->print(myCout);
0478 
0479   myCout << "    Number of bits for eta of muon objects = " << m_ifMuEtaNumberBits << std::endl;
0480   myCout << "    Maximum number of bins for the delta phi scales = " << m_corrParDeltaPhiNrBins << "\n " << std::endl;
0481 
0482   L1GtConditionEvaluation::print(myCout);
0483 }