Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:20:00

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   // condition result condResult set to true if at least one permutation
0192   //     passes all requirements
0193   // all possible permutations are checked
0194   bool condResult = false;
0195 
0196   // store the indices of the calorimeter objects
0197   // from the combination evaluated in the condition
0198   SingleCombInCond objectsInComb;
0199   objectsInComb.reserve(nObjInCond);
0200 
0201   // clear the m_combinationsInCond vector
0202   combinationsInCond().clear();
0203 
0204   do {
0205     if (--jumpIndex)
0206       continue;
0207 
0208     jumpIndex = jump;
0209 
0210     // clear the indices in the combination
0211     objectsInComb.clear();
0212 
0213     bool tmpResult = true;
0214 
0215     // check if there is a permutation that matches object-parameter
0216     // requirements
0217     for (int i = 0; i < nObjInCond; i++) {
0218       tmpResult &= checkObjectParameter(i, *(*candVec)[index[i]]);
0219       objectsInComb.push_back(index[i]);
0220     }
0221 
0222     // if permutation does not match particle conditions
0223     // skip spatial correlations
0224     if (!tmpResult) {
0225       continue;
0226     }
0227 
0228     if (m_gtCaloTemplate->wsc()) {
0229       // wsc requirements have always nObjInCond = 2
0230       // one can use directly index[0] and index[1] to compute
0231       // eta and phi differences
0232       const int ObjInWscComb = 2;
0233       if (nObjInCond != ObjInWscComb) {
0234         if (m_verbosity) {
0235           edm::LogError("L1GlobalTrigger")
0236               << "\n  Error: "
0237               << "number of particles in condition with spatial correlation = " << nObjInCond
0238               << "\n  it must be = " << ObjInWscComb << std::endl;
0239         }
0240 
0241         continue;
0242       }
0243 
0244       L1GtCaloTemplate::CorrelationParameter corrPar = *(m_gtCaloTemplate->correlationParameter());
0245 
0246       unsigned int candDeltaEta;
0247       unsigned int candDeltaPhi;
0248 
0249       // check candDeltaEta
0250 
0251       // get eta index and the sign bit of the eta index (MSB is the sign)
0252       //   signedEta[i] is the signed eta index of candVec[index[i]]
0253       int signedEta[ObjInWscComb];
0254       int signBit[ObjInWscComb] = {0, 0};
0255 
0256       int scaleEta = 1 << (m_ifCaloEtaNumberBits - 1);
0257 
0258       for (int i = 0; i < ObjInWscComb; ++i) {
0259         signBit[i] = ((*candVec)[index[i]]->etaIndex() & scaleEta) >> (m_ifCaloEtaNumberBits - 1);
0260         signedEta[i] = ((*candVec)[index[i]]->etaIndex()) % scaleEta;
0261 
0262         if (signBit[i] == 1) {
0263           signedEta[i] = (-1) * signedEta[i];
0264         }
0265       }
0266 
0267       // compute candDeltaEta - add 1 if signs are different (due to +0/-0
0268       // indices)
0269       candDeltaEta =
0270           static_cast<int>(std::abs(signedEta[1] - signedEta[0])) + static_cast<int>(signBit[1] ^ signBit[0]);
0271 
0272       if (!checkBit(corrPar.deltaEtaRange, candDeltaEta)) {
0273         continue;
0274       }
0275 
0276       // check candDeltaPhi
0277 
0278       // calculate absolute value of candDeltaPhi
0279       if ((*candVec)[index[0]]->phiIndex() > (*candVec)[index[1]]->phiIndex()) {
0280         candDeltaPhi = (*candVec)[index[0]]->phiIndex() - (*candVec)[index[1]]->phiIndex();
0281       } else {
0282         candDeltaPhi = (*candVec)[index[1]]->phiIndex() - (*candVec)[index[0]]->phiIndex();
0283       }
0284 
0285       // check if candDeltaPhi > 180 (via delta_phi_maxbits)
0286       // delta_phi contains bits for 0..180 (0 and 180 included)
0287       // protect also against infinite loop...
0288 
0289       int nMaxLoop = 10;
0290       int iLoop = 0;
0291 
0292       while (candDeltaPhi >= m_corrParDeltaPhiNrBins) {
0293         unsigned int candDeltaPhiInitial = candDeltaPhi;
0294 
0295         // candDeltaPhi > 180 ==> take 360 - candDeltaPhi
0296         candDeltaPhi = (m_corrParDeltaPhiNrBins - 1) * 2 - candDeltaPhi;
0297         if (m_verbosity) {
0298           LogTrace("L1GlobalTrigger") << "    Initial candDeltaPhi = " << candDeltaPhiInitial
0299                                       << " > m_corrParDeltaPhiNrBins = " << m_corrParDeltaPhiNrBins
0300                                       << "  ==> candDeltaPhi rescaled to: " << candDeltaPhi << " [ loop index " << iLoop
0301                                       << "; breaks after " << nMaxLoop << " loops ]\n"
0302                                       << std::endl;
0303         }
0304 
0305         iLoop++;
0306         if (iLoop > nMaxLoop) {
0307           return false;
0308         }
0309       }
0310 
0311       if (!checkBit(corrPar.deltaPhiRange, candDeltaPhi)) {
0312         continue;
0313       }
0314 
0315     }  // end wsc check
0316 
0317     // if we get here all checks were successful for this combination
0318     // set the general result for evaluateCondition to "true"
0319 
0320     condResult = true;
0321     combinationsInCond().push_back(objectsInComb);
0322 
0323     //    } while ( std::next_permutation(index, index + nObj) );
0324   } while (std::next_permutation(index.begin(), index.end()));
0325 
0326   return condResult;
0327 }
0328 
0329 // load calo candidates
0330 const L1GctCand *L1GtCaloCondition::getCandidate(const int indexCand) const {
0331   // objectType() gives the type for nrObjects() only,
0332   // but in a CondCalo all objects have the same type
0333   // take type from the type of the first object
0334   switch ((m_gtCaloTemplate->objectType())[0]) {
0335     case NoIsoEG:
0336       return (*(m_gtPSB->getCandL1NoIsoEG()))[indexCand];
0337       break;
0338     case IsoEG:
0339       return (*(m_gtPSB->getCandL1IsoEG()))[indexCand];
0340       break;
0341     case CenJet:
0342       return (*(m_gtPSB->getCandL1CenJet()))[indexCand];
0343       break;
0344     case ForJet:
0345       return (*(m_gtPSB->getCandL1ForJet()))[indexCand];
0346       break;
0347     case TauJet:
0348       return (*(m_gtPSB->getCandL1TauJet()))[indexCand];
0349       break;
0350     default:
0351       return nullptr;
0352       break;
0353   }
0354 
0355   return nullptr;
0356 }
0357 
0358 /**
0359  * checkObjectParameter - Compare a single particle with a numbered condition.
0360  *
0361  * @param iCondition The number of the condition.
0362  * @param cand The candidate to compare.
0363  *
0364  * @return The result of the comparison (false if a condition does not exist).
0365  */
0366 
0367 const bool L1GtCaloCondition::checkObjectParameter(const int iCondition, const L1GctCand &cand) const {
0368   // number of objects in condition
0369   int nObjInCond = m_gtCaloTemplate->nrObjects();
0370 
0371   if (iCondition >= nObjInCond || iCondition < 0) {
0372     return false;
0373   }
0374 
0375   // empty candidates can not be compared
0376   if (cand.empty()) {
0377     return false;
0378   }
0379 
0380   const L1GtCaloTemplate::ObjectParameter objPar = (*(m_gtCaloTemplate->objectParameter()))[iCondition];
0381 
0382   // check energy threshold
0383   if (!checkThreshold(objPar.etThreshold, cand.rank(), m_gtCaloTemplate->condGEq())) {
0384     return false;
0385   }
0386 
0387   // check eta
0388   if (!checkBit(objPar.etaRange, cand.etaIndex())) {
0389     return false;
0390   }
0391 
0392   // check phi
0393 
0394   if (!checkBit(objPar.phiRange, cand.phiIndex())) {
0395     return false;
0396   }
0397 
0398   // particle matches if we get here
0399   // LogTrace("L1GlobalTrigger")
0400   //    << "  checkObjectParameter: calorimeter object OK, passes all
0401   //    requirements\n"
0402   //    << std::endl;
0403 
0404   return true;
0405 }
0406 
0407 void L1GtCaloCondition::print(std::ostream &myCout) const {
0408   m_gtCaloTemplate->print(myCout);
0409 
0410   myCout << "    Number of bits for eta of calorimeter objects = " << m_ifCaloEtaNumberBits << std::endl;
0411   myCout << "    Maximum number of bins for the delta phi scales = " << m_corrParDeltaPhiNrBins << "\n " << std::endl;
0412 
0413   L1GtConditionEvaluation::print(myCout);
0414 }