Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-14 23:16:58

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