CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/L1Trigger/GlobalTrigger/src/L1GtMuonCondition.cc

Go to the documentation of this file.
00001 
00017 // this class header
00018 #include "L1Trigger/GlobalTrigger/interface/L1GtMuonCondition.h"
00019 
00020 // system include files
00021 #include <iostream>
00022 #include <iomanip>
00023 
00024 #include <string>
00025 #include <vector>
00026 #include <algorithm>
00027 
00028 // user include files
00029 //   base classes
00030 #include "CondFormats/L1TObjects/interface/L1GtMuonTemplate.h"
00031 #include "L1Trigger/GlobalTrigger/interface/L1GtConditionEvaluation.h"
00032 
00033 #include "DataFormats/L1GlobalTrigger/interface/L1GlobalTriggerReadoutSetupFwd.h"
00034 
00035 #include "DataFormats/L1GlobalMuonTrigger/interface/L1MuGMTCand.h"
00036 
00037 #include "L1Trigger/GlobalTrigger/interface/L1GlobalTriggerFunctions.h"
00038 #include "L1Trigger/GlobalTrigger/interface/L1GlobalTriggerGTL.h"
00039 
00040 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00041 #include "FWCore/MessageLogger/interface/MessageDrop.h"
00042 
00043 // constructors
00044 //     default
00045 L1GtMuonCondition::L1GtMuonCondition() :
00046     L1GtConditionEvaluation() {
00047 
00048     // empty
00049 
00050 }
00051 
00052 //     from base template condition (from event setup usually)
00053 L1GtMuonCondition::L1GtMuonCondition(const L1GtCondition* muonTemplate,
00054         const L1GlobalTriggerGTL* ptrGTL, const int nrL1Mu,
00055         const int ifMuEtaNumberBits) :
00056     L1GtConditionEvaluation(),
00057     m_gtMuonTemplate(static_cast<const L1GtMuonTemplate*>(muonTemplate)),
00058     m_gtGTL(ptrGTL),
00059     m_ifMuEtaNumberBits(ifMuEtaNumberBits)
00060 {
00061     m_corrParDeltaPhiNrBins = 0;
00062     m_condMaxNumberObjects = nrL1Mu;
00063 }
00064 
00065 // copy constructor
00066 void L1GtMuonCondition::copy(const L1GtMuonCondition &cp) {
00067 
00068     m_gtMuonTemplate = cp.gtMuonTemplate();
00069     m_gtGTL = cp.gtGTL();
00070 
00071     m_ifMuEtaNumberBits = cp.gtIfMuEtaNumberBits();
00072     m_corrParDeltaPhiNrBins = cp.m_corrParDeltaPhiNrBins;
00073 
00074     m_condMaxNumberObjects = cp.condMaxNumberObjects();
00075     m_condLastResult = cp.condLastResult();
00076     m_combinationsInCond = cp.getCombinationsInCond();
00077 
00078     m_verbosity = cp.m_verbosity;
00079 
00080 }
00081 
00082 L1GtMuonCondition::L1GtMuonCondition(const L1GtMuonCondition& cp) :
00083     L1GtConditionEvaluation() {
00084     copy(cp);
00085 }
00086 
00087 // destructor
00088 L1GtMuonCondition::~L1GtMuonCondition() {
00089 
00090     // empty
00091 
00092 }
00093 
00094 // equal operator
00095 L1GtMuonCondition& L1GtMuonCondition::operator= (const L1GtMuonCondition& cp)
00096 {
00097     copy(cp);
00098     return *this;
00099 }
00100 
00101 // methods
00102 void L1GtMuonCondition::setGtMuonTemplate(const L1GtMuonTemplate* muonTempl) {
00103 
00104     m_gtMuonTemplate = muonTempl;
00105 
00106 }
00107 
00109 void L1GtMuonCondition::setGtGTL(const L1GlobalTriggerGTL* ptrGTL) {
00110 
00111     m_gtGTL = ptrGTL;
00112 
00113 }
00114 
00115 
00116 //   set the number of bits for eta of muon objects
00117 void L1GtMuonCondition::setGtIfMuEtaNumberBits(
00118         const int& ifMuEtaNumberBitsValue) {
00119 
00120     m_ifMuEtaNumberBits = ifMuEtaNumberBitsValue;
00121 
00122 }
00123 
00124 //   set the maximum number of bins for the delta phi scales
00125 void L1GtMuonCondition::setGtCorrParDeltaPhiNrBins(
00126         const int& corrParDeltaPhiNrBins) {
00127 
00128     m_corrParDeltaPhiNrBins = corrParDeltaPhiNrBins;
00129 
00130 }
00131 
00132 
00133 // try all object permutations and check spatial correlations, if required
00134 const bool L1GtMuonCondition::evaluateCondition() const {
00135 
00136     // number of trigger objects in the condition
00137     int nObjInCond = m_gtMuonTemplate->nrObjects();
00138 
00139     // the candidates
00140     const std::vector<const L1MuGMTCand*>* candVec = m_gtGTL->getCandL1Mu();
00141 
00142     int numberObjects = candVec->size();
00143     //LogTrace("L1GlobalTrigger") << "  numberObjects: " << numberObjects
00144     //    << std::endl;
00145     if (numberObjects < nObjInCond) {
00146         return false;
00147     }
00148 
00149     std::vector<int> index(numberObjects);
00150 
00151     for (int i = 0; i < numberObjects; ++i) {
00152         index[i] = i;
00153     }
00154 
00155     int jumpIndex = 1;
00156     int jump = factorial(numberObjects - nObjInCond);
00157 
00158     int totalLoops = 0;
00159     int passLoops = 0;
00160 
00161     // condition result condResult set to true if at least one permutation
00162     //     passes all requirements
00163     // all possible permutations are checked
00164     bool condResult = false;
00165 
00166     // store the indices of the muon objects
00167     // from the combination evaluated in the condition
00168     SingleCombInCond objectsInComb;
00169     objectsInComb.reserve(nObjInCond);
00170 
00171     // clear the m_combinationsInCond vector
00172     (combinationsInCond()).clear();
00173 
00174     do {
00175 
00176         if (--jumpIndex)
00177             continue;
00178 
00179         jumpIndex = jump;
00180         totalLoops++;
00181 
00182         // clear the indices in the combination
00183         objectsInComb.clear();
00184 
00185         bool tmpResult = true;
00186 
00187         // check if there is a permutation that matches object-parameter requirements
00188         for (int i = 0; i < nObjInCond; i++) {
00189 
00190             tmpResult &= checkObjectParameter(i, *(*candVec)[index[i]]);
00191             objectsInComb.push_back(index[i]);
00192 
00193         }
00194 
00195         // if permutation does not match particle conditions
00196         // skip charge correlation and spatial correlations
00197         if ( !tmpResult) {
00198 
00199             continue;
00200 
00201         }
00202 
00203         // get the correlation parameters (chargeCorrelation included here also)
00204         L1GtMuonTemplate::CorrelationParameter corrPar =
00205             *(m_gtMuonTemplate->correlationParameter());
00206 
00207         // charge_correlation consists of 3 relevant bits (D2, D1, D0)
00208         unsigned int chargeCorr = corrPar.chargeCorrelation;
00209 
00210         // charge ignore bit (D0) not set?
00211         if ((chargeCorr & 1) == 0) {
00212 
00213             for (int i = 0; i < nObjInCond; i++) {
00214                 // check valid charge - skip if invalid charge
00215                 bool chargeValid = (*candVec)[index[i]]->charge_valid();
00216                 tmpResult &= chargeValid;
00217 
00218                 if ( !chargeValid) {
00219                     continue;
00220                 }
00221             }
00222 
00223             if ( !tmpResult) {
00224                 continue;
00225             }
00226 
00227             if (nObjInCond == 1) { // one object condition
00228 
00229                 // D2..enable pos, D1..enable neg
00230                 if ( ! ( ( (chargeCorr & 4) != 0 && (*candVec)[index[0]]->charge()> 0 )
00231                     || ( (chargeCorr & 2) != 0 && (*candVec)[index[0]]->charge() < 0 ) )) {
00232 
00233                     continue;
00234                 }
00235 
00236             }
00237             else { // more objects condition
00238 
00239                 // find out if signs are equal
00240                 bool equalSigns = true;
00241                 for (int i = 0; i < nObjInCond-1; i++) {
00242                     if ((*candVec)[index[i]]->charge() != (*candVec)[index[i+1]]->charge()) {
00243                         equalSigns = false;
00244                         break;
00245                     }
00246                 }
00247 
00248                 // two or three particle condition
00249                 if (nObjInCond == 2 || nObjInCond == 3) {
00250                     // D2..enable equal, D1..enable not equal
00251                     if ( ! ( ( (chargeCorr & 4) != 0 && equalSigns ) || ( (chargeCorr & 2) != 0
00252                         && !equalSigns ) )) {
00253 
00254                         continue;
00255                     }
00256                 }
00257 
00258                 // four particle condition
00259                 if (nObjInCond == 4) {
00260                     //counter to count positive charges to determine if there are pairs
00261                     unsigned int posCount = 0;
00262 
00263                     for (int i = 0; i < nObjInCond; i++) {
00264                         if ((*candVec)[index[i]]->charge()> 0) {
00265                             posCount++;
00266                         }
00267                     }
00268 
00269                     // D2..enable equal, D1..enable pairs
00270                     if ( ! ( ( (chargeCorr & 4) != 0 && equalSigns ) || ( (chargeCorr & 2) != 0
00271                         && posCount == 2 ) )) {
00272 
00273                         continue;
00274                     }
00275                 }
00276             }
00277         } // end signchecks
00278 
00279 
00280         if (m_gtMuonTemplate->wsc()) {
00281 
00282             // wsc requirements have always nObjInCond = 2
00283             // one can use directly index[0] and index[1] to compute
00284             // eta and phi differences
00285             const int ObjInWscComb = 2;
00286             if (nObjInCond != ObjInWscComb) {
00287 
00288                 edm::LogError("L1GlobalTrigger") << "\n  Error: "
00289                     << "number of particles in condition with spatial correlation = " << nObjInCond
00290                     << "\n  it must be = " << ObjInWscComb << std::endl;
00291                 // TODO Perhaps I should throw here an exception,
00292                 // since something is really wrong if nObjInCond != ObjInWscComb (=2)
00293                 continue;
00294             }
00295 
00296             unsigned int candDeltaEta;
00297             unsigned int candDeltaPhi;
00298 
00299             // check candDeltaEta
00300 
00301             // get eta index and the sign bit of the eta index (MSB is the sign)
00302             //   signedEta[i] is the signed eta index of (*candVec)[index[i]]
00303             int signedEta[ObjInWscComb];
00304             int signBit[ObjInWscComb] = { 0, 0 };
00305 
00306             int scaleEta = 1 << (m_ifMuEtaNumberBits - 1);
00307 
00308             for (int i = 0; i < ObjInWscComb; ++i) {
00309                 signBit[i] = ((*candVec)[index[i]]->etaIndex() & scaleEta)>>(m_ifMuEtaNumberBits - 1);
00310                 signedEta[i] = ((*candVec)[index[i]]->etaIndex() )%scaleEta;
00311 
00312                 if (signBit[i] == 1) {
00313                     signedEta[i] = (-1)*signedEta[i];
00314                 }
00315 
00316             }
00317 
00318             // compute candDeltaEta - add 1 if signs are different (due to +0/-0 indices)
00319             candDeltaEta = static_cast<int> (std::abs(signedEta[1] - signedEta[0]))
00320                 + static_cast<int> (signBit[1]^signBit[0]);
00321 
00322             if ( !checkBit(corrPar.deltaEtaRange, candDeltaEta) ) {
00323                 continue;
00324             }
00325 
00326             // check candDeltaPhi
00327 
00328             // calculate absolute value of candDeltaPhi
00329             if ((*candVec)[index[0]]->phiIndex()> (*candVec)[index[1]]->phiIndex()) {
00330                 candDeltaPhi = (*candVec)[index[0]]->phiIndex() - (*candVec)[index[1]]->phiIndex();
00331             }
00332             else {
00333                 candDeltaPhi = (*candVec)[index[1]]->phiIndex() - (*candVec)[index[0]]->phiIndex();
00334             }
00335 
00336             // check if candDeltaPhi > 180 (via delta_phi_maxbits)
00337             // delta_phi contains bits for 0..180 (0 and 180 included)
00338             // protect also against infinite loop...
00339 
00340             int nMaxLoop = 10;
00341             int iLoop = 0;
00342 
00343             while (candDeltaPhi >= m_corrParDeltaPhiNrBins) {
00344 
00345                 unsigned int candDeltaPhiInitial = candDeltaPhi;
00346 
00347                 // candDeltaPhi > 180 ==> take 360 - candDeltaPhi
00348                 candDeltaPhi = (m_corrParDeltaPhiNrBins - 1) * 2 - candDeltaPhi;
00349                 if (m_verbosity) {
00350                     LogTrace("L1GlobalTrigger")
00351                             << "    Initial candDeltaPhi = "
00352                             << candDeltaPhiInitial
00353                             << " > m_corrParDeltaPhiNrBins = "
00354                             << m_corrParDeltaPhiNrBins
00355                             << "  ==> candDeltaPhi rescaled to: "
00356                             << candDeltaPhi << " [ loop index " << iLoop
00357                             << "; breaks after " << nMaxLoop << " loops ]\n"
00358                             << std::endl;
00359                 }
00360 
00361                 iLoop++;
00362                 if (iLoop > nMaxLoop) {
00363                     return false;
00364                 }
00365             }
00366 
00367             // delta_phi bitmask is saved in two boost::uint64_t words
00368             if (candDeltaPhi < 64) {
00369                 if (!checkBit(corrPar.deltaPhiRange0Word, candDeltaPhi) ) {
00370                     continue;
00371                 }
00372             }
00373             else {
00374                 if (!checkBit(corrPar.deltaPhiRange1Word, (candDeltaPhi - 64))) {
00375                     continue;
00376                 }
00377             }
00378 
00379         } // end wsc check
00380 
00381         // if we get here all checks were successfull for this combination
00382         // set the general result for evaluateCondition to "true"
00383 
00384         condResult = true;
00385         passLoops++;
00386         (combinationsInCond()).push_back(objectsInComb);
00387 
00388     } while (std::next_permutation(index.begin(), index.end()) );
00389 
00390     //LogTrace("L1GlobalTrigger")
00391     //    << "\n  L1GtMuonCondition: total number of permutations found:          " << totalLoops
00392     //    << "\n  L1GtMuonCondition: number of permutations passing requirements: " << passLoops
00393     //    << "\n" << std::endl;
00394 
00395     return condResult;
00396 
00397 }
00398 
00399 // load muon candidates
00400 const L1MuGMTCand* L1GtMuonCondition::getCandidate(const int indexCand) const {
00401 
00402     return (*(m_gtGTL->getCandL1Mu()))[indexCand];
00403 }
00404 
00414 const bool L1GtMuonCondition::checkObjectParameter(const int iCondition, const L1MuGMTCand& cand) const {
00415 
00416     // number of objects in condition
00417     int nObjInCond = m_gtMuonTemplate->nrObjects();
00418 
00419     if (iCondition >= nObjInCond || iCondition < 0) {
00420         return false;
00421     }
00422 
00423     // empty candidates can not be compared
00424     if (cand.empty()) {
00425         return false;
00426     }
00427 
00428     const L1GtMuonTemplate::ObjectParameter objPar =
00429         ( *(m_gtMuonTemplate->objectParameter()) )[iCondition];
00430 
00431     // using the logic table from GTL-9U-module.pdf
00432     // "Truth table for Isolation bit"
00433 
00434     // check thresholds:
00435 
00436     //   value < low pt threshold
00437     //       fail trigger
00438 
00439     //   low pt threshold <= value < high pt threshold & non-isolated muon:
00440     //       requestIso true:                    fail trigger
00441     //       requestIso false, enableIso true:   fail trigger
00442     //       requestIso false, enableIso false:  OK,  trigger
00443 
00444     //   low pt threshold <= value < high pt threshold & isolated muon:
00445     //       requestIso true:                    OK,  trigger
00446     //       requestIso false, enableIso true:   OK,  trigger
00447     //       requestIso false, enableIso false:  OK,  trigger
00448 
00449     //   value >= high pt threshold & non-isolated muon:
00450     //       requestIso true:  fail trigger
00451     //       requestIso false: OK,  trigger
00452 
00453     //   value >= high pt threshold & isolated muon:
00454     //       OK, trigger
00455 
00456 
00457     if ( !checkThreshold(objPar.ptHighThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq()) ) {
00458 
00459         if ( !checkThreshold(objPar.ptLowThreshold, cand.ptIndex(), m_gtMuonTemplate->condGEq()) ) {
00460 
00461             return false;
00462         }
00463         else {
00464 
00465             // check isolation
00466             if ( !cand.isol() ) {
00467                 if (objPar.requestIso || objPar.enableIso) {
00468 
00469                     return false;
00470                 }
00471             }
00472 
00473         }
00474 
00475     }
00476     else {
00477 
00478         if ( !cand.isol() ) {
00479             if (objPar.requestIso) {
00480 
00481                 return false;
00482             }
00483         }
00484 
00485     }
00486 
00487     // check eta
00488 
00489     if (!checkBit(objPar.etaRange, cand.etaIndex())) {
00490         return false;
00491     }
00492 
00493     // check phi  - in the requested range (no LUT used - LUT too big for hw chip)
00494     // for phiLow <= phiHigh takes [phiLow, phiHigh]
00495     // for phiLow >= phiHigh takes [phiLow, phiHigh] over zero angle!
00496 
00497     if (objPar.phiHigh >= objPar.phiLow) {
00498 
00499         if (! ( (objPar.phiLow <= cand.phiIndex()) && (cand.phiIndex() <= objPar.phiHigh ) )) {
00500 
00501             return false;
00502         }
00503 
00504     }
00505     else { // go over zero angle!!
00506         if (! ( (objPar.phiLow <= cand.phiIndex()) || (cand.phiIndex() <= objPar.phiHigh ) )) {
00507 
00508             return false;
00509         }
00510     }
00511 
00512     // check quality ( bit check )
00513 
00514     // A number of values is required to trigger (at least one).
00515     // "Don’t care" means that all values are allowed.
00516     // Qual = 000 means then NO MUON (GTL module)
00517 
00518     if (cand.quality() == 0) {
00519         return false;
00520     }
00521 
00522     if (objPar.qualityRange == 0) {
00523         return false;
00524     }
00525     else {
00526         if (!checkBit(objPar.qualityRange, cand.quality())) {
00527             return false;
00528         }
00529     }
00530 
00531     // check mip
00532     if (objPar.enableMip) {
00533         if (!cand.mip()) {
00534 
00535             return false;
00536         }
00537     }
00538 
00539     // particle matches if we get here
00540     //LogTrace("L1GlobalTrigger")
00541     //    << "  checkObjectParameter: muon object OK, passes all requirements\n" << std::endl;
00542 
00543     return true;
00544 }
00545 
00546 void L1GtMuonCondition::print(std::ostream& myCout) const {
00547 
00548     m_gtMuonTemplate->print(myCout);
00549 
00550     myCout << "    Number of bits for eta of muon objects = "
00551             << m_ifMuEtaNumberBits << std::endl;
00552     myCout << "    Maximum number of bins for the delta phi scales = "
00553             << m_corrParDeltaPhiNrBins << "\n " << std::endl;
00554 
00555     L1GtConditionEvaluation::print(myCout);
00556 
00557 }
00558