Back to home page

Project CMSSW displayed by LXR

 
 

    


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