Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-04-21 01:53:29

0001 #ifndef L1Trigger_L1TGlobal_ConditionEvaluation_h
0002 #define L1Trigger_L1TGlobal_ConditionEvaluation_h
0003 
0004 /**
0005  * \class ConditionEvaluation
0006  *
0007  *
0008  * Description: Base class for evaluation of the L1 Global Trigger object templates.
0009  *
0010  * Implementation:
0011  *    <TODO: enter implementation details>
0012  *
0013  * \author: Vasile Mihai Ghete   - HEPHY Vienna
0014  *
0015  * \new features: Vladimir Rekovic                                                          
0016  *                - extend for indexing
0017  * \new features: Bernhard Arnold, Elisa Fontanesi                                                          
0018  *                - extended for muon track finder index feature (used for Run 3 muon monitoring seeds)             
0019  *                - checkRangeEta function allows to use up to five eta cuts in L1 algorithms 
0020  *
0021  */
0022 
0023 // system include files
0024 #include <iostream>
0025 
0026 #include <string>
0027 #include <vector>
0028 
0029 // user include files
0030 
0031 //   base class
0032 
0033 //
0034 #include "DataFormats/L1TGlobal/interface/GlobalObjectMapFwd.h"
0035 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0036 #include <cstdint>
0037 
0038 // forward declarations
0039 
0040 namespace l1t {
0041 
0042   // class interface
0043   class ConditionEvaluation {
0044   public:
0045     /// constructor
0046     ConditionEvaluation() : m_condMaxNumberObjects(0), m_condLastResult(false), m_verbosity(0) {}
0047 
0048     /// destructor
0049     virtual ~ConditionEvaluation() {}
0050 
0051   public:
0052     /// get / set the maximum number of objects received for the
0053     /// evaluation of the condition
0054     inline int condMaxNumberObjects() const { return m_condMaxNumberObjects; }
0055 
0056     inline void setCondMaxNumberObjects(int condMaxNumberObjectsValue) {
0057       m_condMaxNumberObjects = condMaxNumberObjectsValue;
0058     }
0059 
0060     /// get the latest result for the condition
0061     inline bool condLastResult() const { return m_condLastResult; }
0062 
0063     /// call evaluateCondition and save last result
0064     inline void evaluateConditionStoreResult(const int bxEval) { m_condLastResult = evaluateCondition(bxEval); }
0065 
0066     /// the core function to check if the condition matches
0067     virtual const bool evaluateCondition(const int bxEval) const = 0;
0068 
0069     /// get numeric expression
0070     virtual std::string getNumericExpression() const {
0071       if (m_condLastResult) {
0072         return "1";
0073       } else {
0074         return "0";
0075       }
0076     }
0077 
0078     /// get all the object combinations evaluated to true in the condition
0079     inline CombinationsInCond const& getCombinationsInCond() const { return m_combinationsInCond; }
0080 
0081     /// print condition
0082     virtual void print(std::ostream& myCout) const;
0083 
0084     inline void setVerbosity(const int verbosity) { m_verbosity = verbosity; }
0085 
0086   protected:
0087     /// get all the object combinations (to fill it...)
0088     inline CombinationsInCond& combinationsInCond() const { return m_combinationsInCond; }
0089 
0090     /// check if a value is greater than a threshold or
0091     /// greater-or-equal depending on the value of the condGEqValue flag
0092     template <class Type1, class Type2>
0093     const bool checkThreshold(const Type1& thresholdL,
0094                               const Type1& thresholdH,
0095                               const Type2& value,
0096                               bool condGEqValue) const;
0097 
0098     /// check if a value is greater than a threshold or
0099     /// greater-or-equal depending on the value of the condGEqValue flag
0100     /// Added for Displaced Muons:
0101     ///       Above checkThreshold fails when value overflows or threshold window is invalid
0102     ///       Below checkUnconstrainedPt allows value to overflow and only evaluates cut if threshold window is valid
0103     template <class Type1, class Type2>
0104     const bool checkUnconstrainedPt(const Type1& thresholdL,
0105                                     const Type1& thresholdH,
0106                                     const Type2& value,
0107                                     bool condGEqValue) const;
0108 
0109     /// check if a index is in a given range
0110     template <class Type1>
0111     const bool checkIndex(const Type1& indexLo, const Type1& indexHi, const unsigned int index) const;
0112 
0113     /// check if a bit with a given number is set in a mask
0114     template <class Type1>
0115     const bool checkBit(const Type1& mask, const unsigned int bitNumber) const;
0116 
0117     /// check if a value is in a given eta range and outside of a veto range
0118     ///        Up to five eta cuts are allowed in L1 algorithms.
0119     ///        Three eta cuts are used for the DoubleMu seeds with upt requirement implemented for Run 3 (2023)
0120     template <class Type1>
0121     const bool checkRangeEta(const unsigned int bitNumber,
0122                              const std::vector<Type1>& windows,
0123                              const unsigned int nEtaBits) const;
0124 
0125     /// check if a value is in a given phi range and outside of a veto range
0126     template <class Type1>
0127     const bool checkRangePhi(const unsigned int bitNumber,
0128                              const Type1& W1beginR,
0129                              const Type1& W1endR,
0130                              const Type1& W2beginR,
0131                              const Type1& W2endR) const;
0132 
0133     /// check if a value is in a given deltaEta range
0134     template <class Type1>
0135     const bool checkRangeDeltaEta(const unsigned int obj1Eta,
0136                                   const unsigned int obj2Eta,
0137                                   const Type1& lowerR,
0138                                   const Type1& upperR,
0139                                   const unsigned int nEtaBits) const;
0140 
0141     /// check if a value is in a given deltaPhi range
0142     template <class Type1>
0143     const bool checkRangeDeltaPhi(const unsigned int obj1Phi,
0144                                   const unsigned int obj2Phi,
0145                                   const Type1& lowerR,
0146                                   const Type1& upperR) const;
0147 
0148     /// check if a value is in a given muon track finder index range
0149     template <class Type1>
0150     const bool checkRangeTfMuonIndex(const unsigned int bitNumber, const std::vector<Type1>& windows) const;
0151 
0152   protected:
0153     /// maximum number of objects received for the evaluation of the condition
0154     /// usually retrieved from event setup
0155     int m_condMaxNumberObjects;
0156 
0157     /// the last result of evaluateCondition()
0158     bool m_condLastResult;
0159 
0160     /// store all the object combinations evaluated to true in the condition
0161     mutable CombinationsInCond m_combinationsInCond;
0162 
0163     /// verbosity level
0164     int m_verbosity;
0165   };
0166 
0167   // define templated methods
0168 
0169   // check if a value is greater than a threshold or
0170   // greater-or-equal depending on the value of the condGEqValue flag
0171   template <class Type1, class Type2>
0172   const bool ConditionEvaluation::checkThreshold(const Type1& thresholdL,
0173                                                  const Type1& thresholdH,
0174                                                  const Type2& value,
0175                                                  const bool condGEqValue) const {
0176     if (value > 0) {
0177       LogTrace("L1GlobalTrigger") << "  checkThreshold check for condGEqValue = " << condGEqValue
0178                                   << "\n    hex: " << std::hex << "threshold = " << thresholdL << " - " << thresholdH
0179                                   << " value = " << value << "\n    dec: " << std::dec << "threshold = " << thresholdL
0180                                   << " - " << thresholdH << " value = " << value << std::endl;
0181     }
0182 
0183     if (condGEqValue) {
0184       if (value >= (Type2)thresholdL && (Type1)value < thresholdH) {
0185         //LogTrace("L1GlobalTrigger") << "    condGEqValue: value >= threshold"
0186         //    << std::endl;
0187 
0188         return true;
0189       }
0190 
0191       return false;
0192 
0193     } else {
0194       if (value == (Type2)thresholdL) {
0195         //LogTrace("L1GlobalTrigger") << "    condGEqValue: value = threshold"
0196         //    << std::endl;
0197 
0198         return true;
0199       }
0200 
0201       return false;
0202     }
0203   }
0204 
0205   // check if a value is greater than a threshold or
0206   // greater-or-equal depending on the value of the condGEqValue flag
0207   /// Added for Displaced Muons:
0208   ///       Above checkThreshold fails when value overflows or threshold window is invalid
0209   ///       Below checkUnconstrainedPt allows value to overflow and only evaluates cut if threshold window is valid
0210   template <class Type1, class Type2>
0211   const bool ConditionEvaluation::checkUnconstrainedPt(const Type1& thresholdL,
0212                                                        const Type1& thresholdH,
0213                                                        const Type2& value,
0214                                                        const bool condGEqValue) const {
0215     if (value > 0) {
0216       LogTrace("L1GlobalTrigger") << "  checkUnconstrainedPt check for condGEqValue = " << condGEqValue
0217                                   << "\n    hex: " << std::hex << "threshold = " << thresholdL << " - " << thresholdH
0218                                   << " value = " << value << "\n    dec: " << std::dec << "threshold = " << thresholdL
0219                                   << " - " << thresholdH << " value = " << value << std::endl;
0220     }
0221     if (thresholdH > 0)  // Only evaluate cut if threshold window is valid
0222     {
0223       if (condGEqValue) {
0224         if (value >= (Type2)thresholdL && (Type1)value <= thresholdH) {
0225           return true;
0226         }
0227         return false;
0228       } else {
0229         if (value == (Type2)thresholdL) {
0230           return true;
0231         }
0232         return false;
0233       }
0234     } else  // If invalid threshold window, do not evaluate cut (ie. pass through)
0235       return true;
0236   }
0237 
0238   // check if a index in a given index range
0239   template <class Type1>
0240   const bool ConditionEvaluation::checkIndex(const Type1& indexLo,
0241                                              const Type1& indexHi,
0242                                              const unsigned int index) const {
0243     LogDebug("l1t|Global") << "\n l1t::ConditionEvaluation"
0244                            << "\n\t indexLo = " << indexLo << "\n\t indexHi = " << indexHi << "\n\t index = " << index
0245                            << std::endl;
0246 
0247     // set condition to false if indexLo > indexHi
0248     if (indexLo > indexHi) {
0249       return false;
0250     }
0251     if (index >= indexLo && index <= indexHi) {
0252       return true;
0253     }
0254 
0255     return false;
0256   }
0257 
0258   // check if a bit with a given number is set in a mask
0259   template <class Type1>
0260   const bool ConditionEvaluation::checkBit(const Type1& mask, const unsigned int bitNumber) const {
0261     uint64_t oneBit = 1ULL;
0262 
0263     if (bitNumber >= (sizeof(oneBit) * 8)) {
0264       if (m_verbosity) {
0265         LogTrace("L1GlobalTrigger") << "    checkBit "
0266                                     << "\n     Bit number = " << bitNumber << " larger than maximum allowed "
0267                                     << sizeof(oneBit) * 8 << std::endl;
0268       }
0269 
0270       return false;
0271     }
0272 
0273     oneBit <<= bitNumber;
0274 
0275     //LogTrace("L1GlobalTrigger") << "    checkBit " << "\n     mask address = " << &mask
0276     //    << std::dec << "\n     dec: " << "mask = " << mask << " oneBit = " << oneBit
0277     //    << " bitNumber = " << bitNumber << std::hex << "\n     hex: " << "mask = " << mask
0278     //    << " oneBit = " << oneBit << " bitNumber = " << bitNumber << std::dec
0279     //    << "\n     mask & oneBit result = " << bool ( mask & oneBit ) << std::endl;
0280 
0281     return (mask & oneBit);
0282   }
0283 
0284   /// check if a value is in a given eta range and outside of a veto range
0285   ///        Up to five eta cuts are allowed in L1 algorithms.
0286   ///        Three eta cuts are used for the DoubleMu seeds with upt requirement implemented for Run 3 (2023)
0287   template <class Type1>
0288   const bool ConditionEvaluation::checkRangeEta(const unsigned int bitNumber,
0289                                                 const std::vector<Type1>& windows,
0290                                                 const unsigned int nEtaBits) const {
0291     if (windows.empty()) {
0292       return true;
0293     }
0294 
0295     for (const auto& window : windows) {
0296       const unsigned int diff1 = window.upper - window.lower;
0297       const unsigned int diff2 = bitNumber - window.lower;
0298       const unsigned int diff3 = window.upper - bitNumber;
0299 
0300       const bool cond1 = ((diff1 >> nEtaBits) & 1) ? false : true;
0301       const bool cond2 = ((diff2 >> nEtaBits) & 1) ? false : true;
0302       const bool cond3 = ((diff3 >> nEtaBits) & 1) ? false : true;
0303 
0304       // check if value is in range
0305       // for begin <= end takes [begin, end]
0306       // for begin >= end takes [begin, end] over zero angle!
0307       bool passWindow = false;
0308       if (cond1 && (cond2 && cond3))
0309         passWindow = true;
0310       else if (!cond1 && (cond2 || cond3))
0311         passWindow = true;
0312       else
0313         passWindow = false;
0314 
0315       LogDebug("l1t|Global") << "\n l1t::ConditionEvaluation"
0316                              << "\n\t bitNumber = " << bitNumber << "\n\t window.lower = " << window.lower
0317                              << "\n\t window.upper = " << window.upper << "\n\t diff1 = " << diff1
0318                              << "\n\t cond1 = " << cond1 << "\n\t diff2 = " << diff2 << "\n\t cond2 = " << cond2
0319                              << "\n\t diff3 = " << diff3 << "\n\t cond3 = " << cond3
0320                              << "\n\t passWindow = " << passWindow << std::endl;
0321 
0322       if (passWindow) {
0323         return true;
0324       }
0325     }
0326 
0327     return false;
0328   }
0329 
0330   /// check if a value is in a given phi range and outside of a veto range
0331   template <class Type1>
0332   const bool ConditionEvaluation::checkRangePhi(const unsigned int bitNumber,
0333                                                 const Type1& W1beginR,
0334                                                 const Type1& W1endR,
0335                                                 const Type1& W2beginR,
0336                                                 const Type1& W2endR) const {
0337     // set condition to true if beginR==endR = default -1
0338     if (W1beginR == W1endR && W1beginR == (Type1)-1) {
0339       return true;
0340     }
0341 
0342     int W1diff1 = W1endR - W1beginR;
0343     int W1diff2 = bitNumber - W1beginR;
0344     int W1diff3 = W1endR - bitNumber;
0345 
0346     bool W1cond1 = (W1diff1 < 0) ? false : true;
0347     bool W1cond2 = (W1diff2 < 0) ? false : true;
0348     bool W1cond3 = (W1diff3 < 0) ? false : true;
0349 
0350     // check if value is in range
0351     // for begin <= end takes [begin, end]
0352     // for begin >= end takes [begin, end] over zero angle!
0353     bool passWindow1 = false;
0354     if (W1cond1 && (W1cond2 && W1cond3))
0355       passWindow1 = true;
0356     else if (!W1cond1 && (W1cond2 || W1cond3))
0357       passWindow1 = true;
0358     else {
0359       passWindow1 = false;
0360     }
0361 
0362     LogDebug("l1t|Global") << "\n l1t::ConditionEvaluation"
0363                            << "\n\t bitNumber = " << bitNumber << "\n\t W1beginR = " << W1beginR
0364                            << "\n\t W1endR   = " << W1endR << "\n\t W1diff1 = " << W1diff1
0365                            << "\n\t W1cond1 = " << W1cond1 << "\n\t W1diff2 = " << W1diff2
0366                            << "\n\t W1cond2 = " << W1cond2 << "\n\t W1diff3 = " << W1diff3
0367                            << "\n\t W1cond3 = " << W1cond3 << std::endl;
0368 
0369     if (W2beginR == W2endR && W2beginR == (Type1)-1) {
0370       return passWindow1;
0371     }
0372 
0373     int W2diff1 = W2endR - W2beginR;
0374     int W2diff2 = bitNumber - W2beginR;
0375     int W2diff3 = W2endR - bitNumber;
0376 
0377     bool W2cond1 = (W2diff1 < 0) ? false : true;
0378     bool W2cond2 = (W2diff2 < 0) ? false : true;
0379     bool W2cond3 = (W2diff3 < 0) ? false : true;
0380 
0381     // check if value is in range
0382     // for begin <= end takes [begin, end]
0383     // for begin >= end takes [begin, end] over zero angle!
0384     bool passWindow2 = false;
0385     if (W2cond1 && (W2cond2 && W2cond3))
0386       passWindow2 = true;
0387     else if (!W2cond1 && (W2cond2 || W2cond3))
0388       passWindow2 = true;
0389     else {
0390       passWindow2 = false;
0391     }
0392 
0393     if (passWindow1 || passWindow2) {
0394       return true;
0395     } else {
0396       return false;
0397     }
0398   }
0399 
0400   template <class Type1>
0401   const bool ConditionEvaluation::checkRangeDeltaEta(const unsigned int obj1Eta,
0402                                                      const unsigned int obj2Eta,
0403                                                      const Type1& lowerR,
0404                                                      const Type1& upperR,
0405                                                      const unsigned int nEtaBits) const {
0406     /*   // set condition to true if beginR==endR = default -1 */
0407     /*   if( beginR==endR && beginR==-1 ){ */
0408     /*     return true; */
0409     /*   } */
0410 
0411     unsigned int compare = obj1Eta - obj2Eta;
0412     bool cond = ((compare >> nEtaBits) & 1) ? false : true;
0413 
0414     unsigned int larger, smaller;
0415     if (cond) {
0416       larger = obj1Eta;
0417       smaller = obj2Eta;
0418     } else {
0419       larger = obj2Eta;
0420       smaller = obj1Eta;
0421     }
0422 
0423     unsigned int diff = ((larger + ((~smaller + 1) & 255)) & 255);
0424 
0425     unsigned int diff1 = upperR - lowerR;
0426     unsigned int diff2 = diff - lowerR;
0427     unsigned int diff3 = upperR - diff;
0428 
0429     bool cond1 = ((diff1 >> nEtaBits) & 1) ? false : true;
0430     bool cond2 = ((diff2 >> nEtaBits) & 1) ? false : true;
0431     bool cond3 = ((diff3 >> nEtaBits) & 1) ? false : true;
0432 
0433     LogDebug("l1t|Global") << "\n l1t::ConditionEvaluation"
0434                            << "\n\t obj1Eta = " << obj1Eta << "\n\t obj2Eta = " << obj2Eta << "\n\t lowerR = " << lowerR
0435                            << "\n\t upperR = " << upperR << "\n\t compare = " << compare << "\n\t cond = " << cond
0436                            << "\n\t diff = " << diff << "\n\t diff1 = " << diff1 << "\n\t cond1 = " << cond1
0437                            << "\n\t diff2 = " << diff2 << "\n\t cond2 = " << cond2 << "\n\t diff3 = " << diff3
0438                            << "\n\t cond3 = " << cond3 << std::endl;
0439 
0440     if (cond1 && (cond2 && cond3))
0441       return true;
0442     else if (!cond1 && (cond2 || cond3))
0443       return true;
0444     else {
0445       return false;
0446     }
0447   }
0448 
0449   template <class Type1>
0450   const bool ConditionEvaluation::checkRangeDeltaPhi(const unsigned int obj1Phi,
0451                                                      const unsigned int obj2Phi,
0452                                                      const Type1& lowerR,
0453                                                      const Type1& upperR) const {
0454     int deltaPhi = abs(int(obj1Phi) - int(obj2Phi));
0455     if (deltaPhi > 71)
0456       deltaPhi = 143 - deltaPhi + 1;  // Add +1 if the calculation is over 0
0457 
0458     int diff1 = upperR - lowerR;
0459     int diff2 = deltaPhi - lowerR;
0460     int diff3 = upperR - deltaPhi;
0461 
0462     bool cond1 = (diff1 < 0) ? false : true;
0463     bool cond2 = (diff2 < 0) ? false : true;
0464     bool cond3 = (diff3 < 0) ? false : true;
0465 
0466     LogDebug("l1t|Global") << "\n l1t::ConditionEvaluation"
0467                            << "\n\t obj1Phi = " << obj1Phi << "\n\t obj2Phi = " << obj2Phi
0468                            << "\n\t deltaPhi = " << deltaPhi << "\n\t lowerR = " << lowerR << "\n\t upperR = " << upperR
0469                            << "\n\t diff1 = " << diff1 << "\n\t cond1 = " << cond1 << "\n\t diff2 = " << diff2
0470                            << "\n\t cond2 = " << cond2 << "\n\t diff3 = " << diff3 << "\n\t cond3 = " << cond3
0471                            << std::endl;
0472 
0473     // check if value is in range
0474     // for begin <= end takes [begin, end]
0475     // for begin >= end takes [begin, end] over zero angle!
0476     if (cond1 && (cond2 && cond3))
0477       return true;
0478     else if (!cond1 && (cond2 || cond3))
0479       return true;
0480     else {
0481       return false;
0482     }
0483   }
0484 
0485   template <class Type1>
0486   const bool ConditionEvaluation::checkRangeTfMuonIndex(const unsigned int value,
0487                                                         const std::vector<Type1>& windows) const {
0488     if (windows.empty()) {
0489       return true;
0490     }
0491 
0492     for (const auto& window : windows) {
0493       if ((window.lower <= value) and (value <= window.upper)) {
0494         return true;
0495         LogDebug("l1t|Global") << "\n l1t::ConditionEvaluation"
0496                                << "\n\t window.lower = " << window.lower << "\n\t window.upper = " << window.upper
0497                                << "Passed TfMuonIndex window" << std::endl;
0498       }
0499     }
0500 
0501     return false;
0502   }
0503 
0504 }  // namespace l1t
0505 #endif