CMS 3D CMS Logo

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