CMS 3D CMS Logo

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

Generated on Tue Jun 9 17:40:14 2009 for CMSSW by  doxygen 1.5.4