Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 /**
0002  * \class L1GtCaloCondition
0003  *
0004  *
0005  * Description: evaluation of a CondCalo 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/L1GtCaloCondition.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/L1GtCaloTemplate.h"
0029 #include "L1Trigger/GlobalTrigger/interface/L1GtConditionEvaluation.h"
0030 
0031 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutSetupFwd.h"
0032 
0033 #include "DataFormats/L1GlobalCaloTrigger/interface/L1GctCand.h"
0034 #include "DataFormats/L1GlobalCaloTrigger/interface/L1GctEmCand.h"
0035 #include "DataFormats/L1GlobalCaloTrigger/interface/L1GctJetCand.h"
0036 
0037 #include "CondFormats/DataRecord/interface/L1GtStableParametersRcd.h"
0038 #include "CondFormats/L1TObjects/interface/L1GtStableParameters.h"
0039 
0040 #include "L1Trigger/GlobalTrigger/interface/L1GlobalTriggerFunctions.h"
0041 #include "L1Trigger/GlobalTrigger/interface/L1GlobalTriggerPSB.h"
0042 
0043 #include "FWCore/MessageLogger/interface/MessageDrop.h"
0044 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0045 
0046 // constructors
0047 //     default
0048 L1GtCaloCondition::L1GtCaloCondition() : L1GtConditionEvaluation() {
0049   m_ifCaloEtaNumberBits = -1;
0050   m_corrParDeltaPhiNrBins = 0;
0051 }
0052 
0053 //     from base template condition (from event setup usually)
0054 L1GtCaloCondition::L1GtCaloCondition(const L1GtCondition *caloTemplate,
0055                                      const L1GlobalTriggerPSB *ptrPSB,
0056                                      const int nrL1NoIsoEG,
0057                                      const int nrL1IsoEG,
0058                                      const int nrL1CenJet,
0059                                      const int nrL1ForJet,
0060                                      const int nrL1TauJet,
0061                                      const int ifCaloEtaNumberBits)
0062     : L1GtConditionEvaluation(),
0063       m_gtCaloTemplate(static_cast<const L1GtCaloTemplate *>(caloTemplate)),
0064       m_gtPSB(ptrPSB),
0065       m_ifCaloEtaNumberBits(ifCaloEtaNumberBits) {
0066   m_corrParDeltaPhiNrBins = 0;
0067 
0068   // maximum number of objects received for the evaluation of the condition
0069   // retrieved before from event setup
0070   // for a CondCalo, all objects ar of same type, hence it is enough to get the
0071   // type for the first object
0072 
0073   switch ((m_gtCaloTemplate->objectType())[0]) {
0074     case NoIsoEG:
0075       m_condMaxNumberObjects = nrL1NoIsoEG;
0076       break;
0077     case IsoEG:
0078       m_condMaxNumberObjects = nrL1IsoEG;
0079       break;
0080     case CenJet:
0081       m_condMaxNumberObjects = nrL1CenJet;
0082       break;
0083     case ForJet:
0084       m_condMaxNumberObjects = nrL1ForJet;
0085       break;
0086     case TauJet:
0087       m_condMaxNumberObjects = nrL1TauJet;
0088       break;
0089     default:
0090       m_condMaxNumberObjects = 0;
0091       break;
0092   }
0093 }
0094 
0095 // copy constructor
0096 void L1GtCaloCondition::copy(const L1GtCaloCondition &cp) {
0097   m_gtCaloTemplate = cp.gtCaloTemplate();
0098   m_gtPSB = cp.gtPSB();
0099 
0100   m_ifCaloEtaNumberBits = cp.gtIfCaloEtaNumberBits();
0101   m_corrParDeltaPhiNrBins = cp.m_corrParDeltaPhiNrBins;
0102 
0103   m_condMaxNumberObjects = cp.condMaxNumberObjects();
0104   m_condLastResult = cp.condLastResult();
0105   m_combinationsInCond = cp.getCombinationsInCond();
0106 
0107   m_verbosity = cp.m_verbosity;
0108 }
0109 
0110 L1GtCaloCondition::L1GtCaloCondition(const L1GtCaloCondition &cp) : L1GtConditionEvaluation() { copy(cp); }
0111 
0112 // destructor
0113 L1GtCaloCondition::~L1GtCaloCondition() {
0114   // empty
0115 }
0116 
0117 // equal operator
0118 L1GtCaloCondition &L1GtCaloCondition::operator=(const L1GtCaloCondition &cp) {
0119   copy(cp);
0120   return *this;
0121 }
0122 
0123 // methods
0124 void L1GtCaloCondition::setGtCaloTemplate(const L1GtCaloTemplate *caloTempl) { m_gtCaloTemplate = caloTempl; }
0125 
0126 ///   set the pointer to PSB
0127 void L1GtCaloCondition::setGtPSB(const L1GlobalTriggerPSB *ptrPSB) { m_gtPSB = ptrPSB; }
0128 
0129 //   set the number of bits for eta of calorimeter objects
0130 void L1GtCaloCondition::setGtIfCaloEtaNumberBits(const int &ifCaloEtaNumberBitsValue) {
0131   m_ifCaloEtaNumberBits = ifCaloEtaNumberBitsValue;
0132 }
0133 
0134 //   set the maximum number of bins for the delta phi scales
0135 void L1GtCaloCondition::setGtCorrParDeltaPhiNrBins(const int &corrParDeltaPhiNrBins) {
0136   m_corrParDeltaPhiNrBins = corrParDeltaPhiNrBins;
0137 }
0138 
0139 // try all object permutations and check spatial correlations, if required
0140 const bool L1GtCaloCondition::evaluateCondition() const {
0141   // number of trigger objects in the condition
0142   int nObjInCond = m_gtCaloTemplate->nrObjects();
0143   // LogTrace("L1GlobalTrigger") << "  nObjInCond: " << nObjInCond
0144   //    << std::endl;
0145 
0146   // the candidates
0147 
0148   // objectType() gives the type for nrObjects() only,
0149   // but in a CondCalo all objects have the same type
0150   // take type from the type of the first object
0151 
0152   const std::vector<const L1GctCand *> *candVec;
0153 
0154   switch ((m_gtCaloTemplate->objectType())[0]) {
0155     case NoIsoEG:
0156       candVec = m_gtPSB->getCandL1NoIsoEG();
0157       break;
0158     case IsoEG:
0159       candVec = m_gtPSB->getCandL1IsoEG();
0160       break;
0161     case CenJet:
0162       candVec = m_gtPSB->getCandL1CenJet();
0163       break;
0164     case ForJet:
0165       candVec = m_gtPSB->getCandL1ForJet();
0166       break;
0167     case TauJet:
0168       candVec = m_gtPSB->getCandL1TauJet();
0169       break;
0170     default:
0171       return false;
0172       break;
0173   }
0174 
0175   int numberObjects = candVec->size();
0176   // LogTrace("L1GlobalTrigger") << "  numberObjects: " << numberObjects
0177   //    << std::endl;
0178   if (numberObjects < nObjInCond) {
0179     return false;
0180   }
0181 
0182   std::vector<int> index(numberObjects);
0183 
0184   for (int i = 0; i < numberObjects; ++i) {
0185     index[i] = i;
0186   }
0187 
0188   int jumpIndex = 1;
0189   int jump = factorial(numberObjects - nObjInCond);
0190 
0191   int totalLoops = 0;
0192   int passLoops = 0;
0193 
0194   // condition result condResult set to true if at least one permutation
0195   //     passes all requirements
0196   // all possible permutations are checked
0197   bool condResult = false;
0198 
0199   // store the indices of the calorimeter objects
0200   // from the combination evaluated in the condition
0201   SingleCombInCond objectsInComb;
0202   objectsInComb.reserve(nObjInCond);
0203 
0204   // clear the m_combinationsInCond vector
0205   combinationsInCond().clear();
0206 
0207   do {
0208     if (--jumpIndex)
0209       continue;
0210 
0211     jumpIndex = jump;
0212     totalLoops++;
0213 
0214     // clear the indices in the combination
0215     objectsInComb.clear();
0216 
0217     bool tmpResult = true;
0218 
0219     // check if there is a permutation that matches object-parameter
0220     // requirements
0221     for (int i = 0; i < nObjInCond; i++) {
0222       tmpResult &= checkObjectParameter(i, *(*candVec)[index[i]]);
0223       objectsInComb.push_back(index[i]);
0224     }
0225 
0226     // if permutation does not match particle conditions
0227     // skip spatial correlations
0228     if (!tmpResult) {
0229       continue;
0230     }
0231 
0232     if (m_gtCaloTemplate->wsc()) {
0233       // wsc requirements have always nObjInCond = 2
0234       // one can use directly index[0] and index[1] to compute
0235       // eta and phi differences
0236       const int ObjInWscComb = 2;
0237       if (nObjInCond != ObjInWscComb) {
0238         if (m_verbosity) {
0239           edm::LogError("L1GlobalTrigger")
0240               << "\n  Error: "
0241               << "number of particles in condition with spatial correlation = " << nObjInCond
0242               << "\n  it must be = " << ObjInWscComb << std::endl;
0243         }
0244 
0245         continue;
0246       }
0247 
0248       L1GtCaloTemplate::CorrelationParameter corrPar = *(m_gtCaloTemplate->correlationParameter());
0249 
0250       unsigned int candDeltaEta;
0251       unsigned int candDeltaPhi;
0252 
0253       // check candDeltaEta
0254 
0255       // get eta index and the sign bit of the eta index (MSB is the sign)
0256       //   signedEta[i] is the signed eta index of candVec[index[i]]
0257       int signedEta[ObjInWscComb];
0258       int signBit[ObjInWscComb] = {0, 0};
0259 
0260       int scaleEta = 1 << (m_ifCaloEtaNumberBits - 1);
0261 
0262       for (int i = 0; i < ObjInWscComb; ++i) {
0263         signBit[i] = ((*candVec)[index[i]]->etaIndex() & scaleEta) >> (m_ifCaloEtaNumberBits - 1);
0264         signedEta[i] = ((*candVec)[index[i]]->etaIndex()) % scaleEta;
0265 
0266         if (signBit[i] == 1) {
0267           signedEta[i] = (-1) * signedEta[i];
0268         }
0269       }
0270 
0271       // compute candDeltaEta - add 1 if signs are different (due to +0/-0
0272       // indices)
0273       candDeltaEta =
0274           static_cast<int>(std::abs(signedEta[1] - signedEta[0])) + static_cast<int>(signBit[1] ^ signBit[0]);
0275 
0276       if (!checkBit(corrPar.deltaEtaRange, candDeltaEta)) {
0277         continue;
0278       }
0279 
0280       // check candDeltaPhi
0281 
0282       // calculate absolute value of candDeltaPhi
0283       if ((*candVec)[index[0]]->phiIndex() > (*candVec)[index[1]]->phiIndex()) {
0284         candDeltaPhi = (*candVec)[index[0]]->phiIndex() - (*candVec)[index[1]]->phiIndex();
0285       } else {
0286         candDeltaPhi = (*candVec)[index[1]]->phiIndex() - (*candVec)[index[0]]->phiIndex();
0287       }
0288 
0289       // check if candDeltaPhi > 180 (via delta_phi_maxbits)
0290       // delta_phi contains bits for 0..180 (0 and 180 included)
0291       // protect also against infinite loop...
0292 
0293       int nMaxLoop = 10;
0294       int iLoop = 0;
0295 
0296       while (candDeltaPhi >= m_corrParDeltaPhiNrBins) {
0297         unsigned int candDeltaPhiInitial = candDeltaPhi;
0298 
0299         // candDeltaPhi > 180 ==> take 360 - candDeltaPhi
0300         candDeltaPhi = (m_corrParDeltaPhiNrBins - 1) * 2 - candDeltaPhi;
0301         if (m_verbosity) {
0302           LogTrace("L1GlobalTrigger") << "    Initial candDeltaPhi = " << candDeltaPhiInitial
0303                                       << " > m_corrParDeltaPhiNrBins = " << m_corrParDeltaPhiNrBins
0304                                       << "  ==> candDeltaPhi rescaled to: " << candDeltaPhi << " [ loop index " << iLoop
0305                                       << "; breaks after " << nMaxLoop << " loops ]\n"
0306                                       << std::endl;
0307         }
0308 
0309         iLoop++;
0310         if (iLoop > nMaxLoop) {
0311           return false;
0312         }
0313       }
0314 
0315       if (!checkBit(corrPar.deltaPhiRange, candDeltaPhi)) {
0316         continue;
0317       }
0318 
0319     }  // end wsc check
0320 
0321     // if we get here all checks were successful for this combination
0322     // set the general result for evaluateCondition to "true"
0323 
0324     condResult = true;
0325     passLoops++;
0326     combinationsInCond().push_back(objectsInComb);
0327 
0328     //    } while ( std::next_permutation(index, index + nObj) );
0329   } while (std::next_permutation(index.begin(), index.end()));
0330 
0331   // LogTrace("L1GlobalTrigger")
0332   //    << "\n  L1GtCaloCondition: total number of permutations found: " <<
0333   //    totalLoops
0334   //    << "\n  L1GtCaloCondition: number of permutations passing requirements:
0335   //    " << passLoops
0336   //    << "\n" << std::endl;
0337 
0338   return condResult;
0339 }
0340 
0341 // load calo candidates
0342 const L1GctCand *L1GtCaloCondition::getCandidate(const int indexCand) const {
0343   // objectType() gives the type for nrObjects() only,
0344   // but in a CondCalo all objects have the same type
0345   // take type from the type of the first object
0346   switch ((m_gtCaloTemplate->objectType())[0]) {
0347     case NoIsoEG:
0348       return (*(m_gtPSB->getCandL1NoIsoEG()))[indexCand];
0349       break;
0350     case IsoEG:
0351       return (*(m_gtPSB->getCandL1IsoEG()))[indexCand];
0352       break;
0353     case CenJet:
0354       return (*(m_gtPSB->getCandL1CenJet()))[indexCand];
0355       break;
0356     case ForJet:
0357       return (*(m_gtPSB->getCandL1ForJet()))[indexCand];
0358       break;
0359     case TauJet:
0360       return (*(m_gtPSB->getCandL1TauJet()))[indexCand];
0361       break;
0362     default:
0363       return nullptr;
0364       break;
0365   }
0366 
0367   return nullptr;
0368 }
0369 
0370 /**
0371  * checkObjectParameter - Compare a single particle with a numbered condition.
0372  *
0373  * @param iCondition The number of the condition.
0374  * @param cand The candidate to compare.
0375  *
0376  * @return The result of the comparison (false if a condition does not exist).
0377  */
0378 
0379 const bool L1GtCaloCondition::checkObjectParameter(const int iCondition, const L1GctCand &cand) const {
0380   // number of objects in condition
0381   int nObjInCond = m_gtCaloTemplate->nrObjects();
0382 
0383   if (iCondition >= nObjInCond || iCondition < 0) {
0384     return false;
0385   }
0386 
0387   // empty candidates can not be compared
0388   if (cand.empty()) {
0389     return false;
0390   }
0391 
0392   const L1GtCaloTemplate::ObjectParameter objPar = (*(m_gtCaloTemplate->objectParameter()))[iCondition];
0393 
0394   // check energy threshold
0395   if (!checkThreshold(objPar.etThreshold, cand.rank(), m_gtCaloTemplate->condGEq())) {
0396     return false;
0397   }
0398 
0399   // check eta
0400   if (!checkBit(objPar.etaRange, cand.etaIndex())) {
0401     return false;
0402   }
0403 
0404   // check phi
0405 
0406   if (!checkBit(objPar.phiRange, cand.phiIndex())) {
0407     return false;
0408   }
0409 
0410   // particle matches if we get here
0411   // LogTrace("L1GlobalTrigger")
0412   //    << "  checkObjectParameter: calorimeter object OK, passes all
0413   //    requirements\n"
0414   //    << std::endl;
0415 
0416   return true;
0417 }
0418 
0419 void L1GtCaloCondition::print(std::ostream &myCout) const {
0420   m_gtCaloTemplate->print(myCout);
0421 
0422   myCout << "    Number of bits for eta of calorimeter objects = " << m_ifCaloEtaNumberBits << std::endl;
0423   myCout << "    Maximum number of bins for the delta phi scales = " << m_corrParDeltaPhiNrBins << "\n " << std::endl;
0424 
0425   L1GtConditionEvaluation::print(myCout);
0426 }