CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DQM/TrackerCommon/src/TriggerHelper.cc

Go to the documentation of this file.
00001 //
00002 // $Id: TriggerHelper.cc,v 1.9 2010/03/27 12:09:12 dutta Exp $
00003 //
00004 
00005 
00006 #include "DQM/TrackerCommon/interface/TriggerHelper.h"
00007 
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 
00010 #include "FWCore/Framework/interface/ESHandle.h"
00011 #include "CondFormats/HLTObjects/interface/AlCaRecoTriggerBits.h"
00012 #include "DataFormats/L1GlobalTrigger/interface/L1GtLogicParser.h"
00013 #include <string>
00014 #include <vector>
00015 
00016 
00017 
00019 TriggerHelper::TriggerHelper( const edm::ParameterSet & config )
00020   : watchDB_( 0 )
00021   , gtDBKey_( "" )
00022   , l1DBKey_( "" )
00023   , hltDBKey_( "" )
00024   , on_( true )
00025   , onDcs_( true )
00026   , onGt_( true )
00027   , onL1_( true )
00028   , onHlt_( true )
00029   , configError_( "CONFIG_ERROR" )
00030 {
00031 
00032   // General switch(es)
00033   if ( config.exists( "andOr" ) ) {
00034     andOr_ = config.getParameter< bool >( "andOr" );
00035   } else {
00036     on_    = false;
00037     onDcs_ = false;
00038     onGt_  = false;
00039     onL1_  = false;
00040     onHlt_ = false;
00041   }
00042 
00043   if ( on_ ) {
00044     if ( config.exists( "andOrDcs" ) ) {
00045       andOrDcs_      = config.getParameter< bool >( "andOrDcs" );
00046       dcsInputTag_   = config.getParameter< edm::InputTag >( "dcsInputTag" );
00047       dcsPartitions_ = config.getParameter< std::vector< int > >( "dcsPartitions" );
00048       errorReplyDcs_ = config.getParameter< bool >( "errorReplyDcs" );
00049     } else {
00050       onDcs_ = false;
00051     }
00052     if ( config.exists( "andOrGt" ) ) {
00053       andOrGt_              = config.getParameter< bool >( "andOrGt" );
00054       gtInputTag_           = config.getParameter< edm::InputTag >( "gtInputTag" );
00055       gtLogicalExpressions_ = config.getParameter< std::vector< std::string > >( "gtStatusBits" );
00056       errorReplyGt_         = config.getParameter< bool >( "errorReplyGt" );
00057       if ( config.exists( "gtDBKey" ) ) gtDBKey_ = config.getParameter< std::string >( "gtDBKey" );
00058     } else {
00059       onGt_ = false;
00060     }
00061     if ( config.exists( "andOrL1" ) ) {
00062       andOrL1_              = config.getParameter< bool >( "andOrL1" );
00063       l1LogicalExpressions_ = config.getParameter< std::vector< std::string > >( "l1Algorithms" );
00064       errorReplyL1_         = config.getParameter< bool >( "errorReplyL1" );
00065       if ( config.exists( "l1DBKey" ) ) l1DBKey_ = config.getParameter< std::string >( "l1DBKey" );
00066     } else {
00067       onL1_ = false;
00068     }
00069     if ( config.exists( "andOrHlt" ) ) {
00070       andOrHlt_              = config.getParameter< bool >( "andOrHlt" );
00071       hltInputTag_           = config.getParameter< edm::InputTag >( "hltInputTag" );
00072       hltLogicalExpressions_ = config.getParameter< std::vector< std::string > >( "hltPaths" );
00073       errorReplyHlt_         = config.getParameter< bool >( "errorReplyHlt" );
00074       if ( config.exists( "hltDBKey" ) ) hltDBKey_ = config.getParameter< std::string >( "hltDBKey" );
00075     } else {
00076       onHlt_ = false;
00077     }
00078     if ( ! onDcs_ && ! onGt_ && ! onL1_ && ! onHlt_ ) on_      = false;
00079     else                                              watchDB_ = new edm::ESWatcher< AlCaRecoTriggerBitsRcd> ;
00080   }
00081 
00082 }
00083 
00084 
00086 TriggerHelper::~TriggerHelper()
00087 {
00088 
00089   if ( on_ ) delete watchDB_;
00090 
00091 }
00092 
00093 
00095 void TriggerHelper::initRun( const edm::Run & run, const edm::EventSetup & setup )
00096 {
00097 
00098   // FIXME Can this stay safely in the run loop, or does it need to go to the event loop?
00099   // Means: Are the event setups identical?
00100   if ( watchDB_->check( setup ) ) {
00101     if ( onGt_ && gtDBKey_.size() > 0 ) {
00102       const std::vector< std::string > exprs( expressionsFromDB( gtDBKey_, setup ) );
00103       if ( exprs.empty() || exprs.at( 0 ) != configError_ ) gtLogicalExpressions_ = exprs;
00104     }
00105     if ( onL1_ && l1DBKey_.size() > 0 ) {
00106       const std::vector< std::string > exprs( expressionsFromDB( l1DBKey_, setup ) );
00107       if ( exprs.empty() || exprs.at( 0 ) != configError_ ) l1LogicalExpressions_ = exprs;
00108     }
00109     if ( onHlt_ && hltDBKey_.size() > 0 ) {
00110       const std::vector< std::string > exprs( expressionsFromDB( hltDBKey_, setup ) );
00111       if ( exprs.empty() || exprs.at( 0 ) != configError_ ) hltLogicalExpressions_ = exprs;
00112     }
00113   }
00114 
00115   hltConfigInit_ = false;
00116   if ( onHlt_ ) {
00117     if ( hltInputTag_.process().size() == 0 ) {
00118       edm::LogError( "TriggerHelper" ) << "HLT TriggerResults InputTag \"" << hltInputTag_.encode() << "\" specifies no process";
00119     } else {
00120       bool hltChanged( false );
00121       if ( ! hltConfig_.init( run, setup, hltInputTag_.process(), hltChanged ) ) {
00122         edm::LogError( "TriggerHelper" ) << "HLT config initialization error with process name \"" << hltInputTag_.process() << "\"";
00123       } else if ( hltConfig_.size() <= 0 ) {
00124         edm::LogError( "TriggerHelper" ) << "HLT config size error";
00125       } else hltConfigInit_ = true;
00126     }
00127   }
00128 
00129 }
00130 
00131 
00133 bool TriggerHelper::accept( const edm::Event & event, const edm::EventSetup & setup )
00134 {
00135 
00136   if ( ! on_ ) return true;
00137 
00138   // Determine decision
00139   if ( andOr_ ) return ( acceptDcs( event ) || acceptGt( event ) || acceptL1( event, setup ) || acceptHlt( event ) );
00140   return ( acceptDcs( event ) && acceptGt( event ) && acceptL1( event, setup ) && acceptHlt( event ) );
00141 
00142 }
00143 
00144 
00145 bool TriggerHelper::acceptDcs( const edm::Event & event )
00146 {
00147 
00148   // An empty DCS partitions list acts as switch.
00149   if ( ! onDcs_ || dcsPartitions_.empty() ) return ( ! andOr_ ); // logically neutral, depending on base logical connective
00150 
00151   // Accessing the DcsStatusCollection
00152   edm::Handle< DcsStatusCollection > dcsStatus;
00153   event.getByLabel( dcsInputTag_, dcsStatus );
00154   if ( ! dcsStatus.isValid() ) {
00155     edm::LogError( "TriggerHelper" ) << "DcsStatusCollection product with InputTag \"" << dcsInputTag_.encode() << "\" not in event ==> decision: " << errorReplyDcs_;
00156     return errorReplyDcs_;
00157   }
00158 
00159   // Determine decision of DCS partition combination and return
00160   if ( andOrDcs_ ) { // OR combination
00161     for ( std::vector< int >::const_iterator partitionNumber = dcsPartitions_.begin(); partitionNumber != dcsPartitions_.end(); ++partitionNumber ) {
00162       if ( acceptDcsPartition( dcsStatus, *partitionNumber ) ) return true;
00163     }
00164     return false;
00165   }
00166   for ( std::vector< int >::const_iterator partitionNumber = dcsPartitions_.begin(); partitionNumber != dcsPartitions_.end(); ++partitionNumber ) {
00167     if ( ! acceptDcsPartition( dcsStatus, *partitionNumber ) ) return false;
00168   }
00169   return true;
00170 
00171 }
00172 
00173 
00174 bool TriggerHelper::acceptDcsPartition( const edm::Handle< DcsStatusCollection > & dcsStatus, int dcsPartition ) const
00175 {
00176 
00177   // Error checks
00178   switch( dcsPartition ) {
00179     case DcsStatus::EBp   :
00180     case DcsStatus::EBm   :
00181     case DcsStatus::EEp   :
00182     case DcsStatus::EEm   :
00183     case DcsStatus::HBHEa :
00184     case DcsStatus::HBHEb :
00185     case DcsStatus::HBHEc :
00186     case DcsStatus::HF    :
00187     case DcsStatus::HO    :
00188     case DcsStatus::RPC   :
00189     case DcsStatus::DT0   :
00190     case DcsStatus::DTp   :
00191     case DcsStatus::DTm   :
00192     case DcsStatus::CSCp  :
00193     case DcsStatus::CSCm  :
00194     case DcsStatus::CASTOR:
00195     case DcsStatus::TIBTID:
00196     case DcsStatus::TOB   :
00197     case DcsStatus::TECp  :
00198     case DcsStatus::TECm  :
00199     case DcsStatus::BPIX  :
00200     case DcsStatus::FPIX  :
00201     case DcsStatus::ESp   :
00202     case DcsStatus::ESm   :
00203       break;
00204     default:
00205       edm::LogError( "TriggerHelper" ) << "DCS partition number \"" << dcsPartition << "\" does not exist ==> decision: " << errorReplyDcs_;
00206       return errorReplyDcs_;
00207   }
00208 
00209   // Determine decision
00210   return dcsStatus->at( 0 ).ready( dcsPartition );
00211 
00212 }
00213 
00214 
00216 bool TriggerHelper::acceptGt( const edm::Event & event )
00217 {
00218 
00219   // An empty GT status bits logical expressions list acts as switch.
00220   if ( ! onGt_ || gtLogicalExpressions_.empty() ) return ( ! andOr_ ); // logically neutral, depending on base logical connective
00221 
00222   // Accessing the L1GlobalTriggerReadoutRecord
00223   edm::Handle< L1GlobalTriggerReadoutRecord > gtReadoutRecord;
00224   event.getByLabel( gtInputTag_, gtReadoutRecord );
00225   if ( ! gtReadoutRecord.isValid() ) {
00226     edm::LogError( "TriggerHelper" ) << "L1GlobalTriggerReadoutRecord product with InputTag \"" << gtInputTag_.encode() << "\" not in event ==> decision: " << errorReplyGt_;
00227     return errorReplyGt_;
00228   }
00229 
00230   // Determine decision of GT status bits logical expression combination and return
00231   if ( andOrGt_ ) { // OR combination
00232     for ( std::vector< std::string >::const_iterator gtLogicalExpression = gtLogicalExpressions_.begin(); gtLogicalExpression != gtLogicalExpressions_.end(); ++gtLogicalExpression ) {
00233       if ( acceptGtLogicalExpression( gtReadoutRecord, *gtLogicalExpression ) ) return true;
00234     }
00235     return false;
00236   }
00237   for ( std::vector< std::string >::const_iterator gtLogicalExpression = gtLogicalExpressions_.begin(); gtLogicalExpression != gtLogicalExpressions_.end(); ++gtLogicalExpression ) {
00238     if ( ! acceptGtLogicalExpression( gtReadoutRecord, *gtLogicalExpression ) ) return false;
00239   }
00240   return true;
00241 
00242 }
00243 
00244 
00246 bool TriggerHelper::acceptGtLogicalExpression( const edm::Handle< L1GlobalTriggerReadoutRecord > & gtReadoutRecord, std::string gtLogicalExpression )
00247 {
00248 
00249   // Check empty std::strings
00250   if ( gtLogicalExpression.empty() ) {
00251     edm::LogError( "TriggerHelper" ) << "Empty logical expression ==> decision: " << errorReplyGt_;
00252     return errorReplyGt_;
00253   }
00254 
00255   // Negated paths
00256   bool negExpr( negate( gtLogicalExpression ) );
00257   if ( negExpr && gtLogicalExpression.empty() ) {
00258     edm::LogError( "TriggerHelper" ) << "Empty (negated) logical expression ==> decision: " << errorReplyGt_;
00259     return errorReplyGt_;
00260   }
00261 
00262   // Parse logical expression and determine GT status bit decision
00263   L1GtLogicParser gtAlgoLogicParser( gtLogicalExpression );
00264   // Loop over status bits
00265   for ( size_t iStatusBit = 0; iStatusBit < gtAlgoLogicParser.operandTokenVector().size(); ++iStatusBit ) {
00266     const std::string gtStatusBit( gtAlgoLogicParser.operandTokenVector().at( iStatusBit ).tokenName );
00267     // Manipulate status bit decision as stored in the parser
00268     bool decision;
00269     // Hard-coded status bits!!!
00270     if ( gtStatusBit == "PhysDecl" || gtStatusBit == "PhysicsDeclared" ) {
00271       decision = ( gtReadoutRecord->gtFdlWord().physicsDeclared() == 1 );
00272     } else {
00273       edm::LogError( "TriggerHelper" ) << "GT status bit \"" << gtStatusBit << "\" is not defined ==> decision: " << errorReplyGt_;
00274       decision = errorReplyDcs_;
00275     }
00276     gtAlgoLogicParser.operandTokenVector().at( iStatusBit ).tokenResult = decision;
00277   }
00278 
00279   // Determine decision
00280   const bool gtDecision( gtAlgoLogicParser.expressionResult() );
00281   return negExpr ? ( ! gtDecision ) : gtDecision;
00282 
00283 }
00284 
00285 
00287 bool TriggerHelper::acceptL1( const edm::Event & event, const edm::EventSetup & setup )
00288 {
00289 
00290   // An empty L1 logical expressions list acts as switch.
00291   if ( ! onL1_ || l1LogicalExpressions_.empty() ) return ( ! andOr_ ); // logically neutral, depending on base logical connective
00292 
00293   // Getting the L1 event setup
00294   l1Gt_.retrieveL1EventSetup( setup ); // FIXME This can possibly go to initRun()
00295 
00296   // Determine decision of L1 logical expression combination and return
00297   if ( andOrL1_ ) { // OR combination
00298     for ( std::vector< std::string >::const_iterator l1LogicalExpression = l1LogicalExpressions_.begin(); l1LogicalExpression != l1LogicalExpressions_.end(); ++l1LogicalExpression ) {
00299       if ( acceptL1LogicalExpression( event, *l1LogicalExpression ) ) return true;
00300     }
00301     return false;
00302   }
00303   for ( std::vector< std::string >::const_iterator l1LogicalExpression = l1LogicalExpressions_.begin(); l1LogicalExpression != l1LogicalExpressions_.end(); ++l1LogicalExpression ) {
00304     if ( ! acceptL1LogicalExpression( event, *l1LogicalExpression ) ) return false;
00305   }
00306   return true;
00307 
00308 }
00309 
00310 
00312 bool TriggerHelper::acceptL1LogicalExpression( const edm::Event & event, std::string l1LogicalExpression )
00313 {
00314 
00315   // Check empty std::strings
00316   if ( l1LogicalExpression.empty() ) {
00317     edm::LogError( "TriggerHelper" ) << "Empty logical expression ==> decision: " << errorReplyL1_;
00318     return errorReplyL1_;
00319   }
00320 
00321   // Negated logical expression
00322   bool negExpr( negate( l1LogicalExpression ) );
00323   if ( negExpr && l1LogicalExpression.empty() ) {
00324     edm::LogError( "TriggerHelper" ) << "Empty (negated) logical expression ==> decision: " << errorReplyL1_;
00325     return errorReplyL1_;
00326   }
00327 
00328   // Parse logical expression and determine L1 decision
00329   L1GtLogicParser l1AlgoLogicParser( l1LogicalExpression );
00330   // Loop over algorithms
00331   for ( size_t iAlgorithm = 0; iAlgorithm < l1AlgoLogicParser.operandTokenVector().size(); ++iAlgorithm ) {
00332     const std::string l1AlgoName( l1AlgoLogicParser.operandTokenVector().at( iAlgorithm ).tokenName );
00333     int error( -1 );
00334     const bool decision( l1Gt_.decision( event, l1AlgoName, error ) );
00335     // Error checks
00336     if ( error != 0 ) {
00337       if ( error == 1 ) edm::LogError( "TriggerHelper" ) << "L1 algorithm \"" << l1AlgoName << "\" does not exist in the L1 menu ==> decision: "                                          << errorReplyL1_;
00338       else              edm::LogError( "TriggerHelper" )  << "L1 algorithm \"" << l1AlgoName << "\" received error code " << error << " from L1GtUtils::decisionBeforeMask ==> decision: " << errorReplyL1_;
00339       l1AlgoLogicParser.operandTokenVector().at( iAlgorithm ).tokenResult = errorReplyL1_;
00340       continue;
00341     }
00342     // Manipulate algo decision as stored in the parser
00343     l1AlgoLogicParser.operandTokenVector().at( iAlgorithm ).tokenResult = decision;
00344   }
00345 
00346   // Return decision
00347   const bool l1Decision( l1AlgoLogicParser.expressionResult() );
00348   return negExpr ? ( ! l1Decision ) : l1Decision;
00349 
00350 }
00351 
00352 
00354 bool TriggerHelper::acceptHlt( const edm::Event & event )
00355 {
00356 
00357   // An empty HLT logical expressions list acts as switch.
00358   if ( ! onHlt_ || hltLogicalExpressions_.empty() ) return ( ! andOr_ ); // logically neutral, depending on base logical connective
00359 
00360   // Checking the HLT configuration,
00361   if ( ! hltConfigInit_ ) {
00362     edm::LogError( "TriggerHelper" ) << "HLT config error ==> decision: " << errorReplyHlt_;
00363     return errorReplyHlt_;
00364   }
00365 
00366   // Accessing the TriggerResults
00367   edm::Handle< edm::TriggerResults > hltTriggerResults;
00368   event.getByLabel( hltInputTag_, hltTriggerResults );
00369   if ( ! hltTriggerResults.isValid() ) {
00370     edm::LogError( "TriggerHelper" ) << "TriggerResults product with InputTag \"" << hltInputTag_.encode() << "\" not in event ==> decision: " << errorReplyHlt_;
00371     return errorReplyHlt_;
00372   }
00373 
00374   // Determine decision of HLT logical expression combination and return
00375   if ( andOrHlt_ ) { // OR combination
00376     for ( std::vector< std::string >::const_iterator hltLogicalExpression = hltLogicalExpressions_.begin(); hltLogicalExpression != hltLogicalExpressions_.end(); ++hltLogicalExpression ) {
00377       if ( acceptHltLogicalExpression( hltTriggerResults, *hltLogicalExpression ) ) return true;
00378     }
00379     return false;
00380   }
00381   for ( std::vector< std::string >::const_iterator hltLogicalExpression = hltLogicalExpressions_.begin(); hltLogicalExpression != hltLogicalExpressions_.end(); ++hltLogicalExpression ) {
00382     if ( ! acceptHltLogicalExpression( hltTriggerResults, *hltLogicalExpression ) ) return false;
00383   }
00384   return true;
00385 
00386 }
00387 
00388 
00390 bool TriggerHelper::acceptHltLogicalExpression( const edm::Handle< edm::TriggerResults > & hltTriggerResults, std::string hltLogicalExpression ) const
00391 {
00392 
00393   // Check empty std::strings
00394   if ( hltLogicalExpression.empty() ) {
00395     edm::LogError( "TriggerHelper" ) << "Empty logical expression ==> decision: " << errorReplyHlt_;
00396     return errorReplyHlt_;
00397   }
00398 
00399   // Negated paths
00400   bool negExpr( negate( hltLogicalExpression ) );
00401   if ( negExpr && hltLogicalExpression.empty() ) {
00402     edm::LogError( "TriggerHelper" ) << "Empty (negated) logical expression ==> decision: " << errorReplyHlt_;
00403     return errorReplyHlt_;
00404   }
00405 
00406   // Parse logical expression and determine HLT decision
00407   L1GtLogicParser hltAlgoLogicParser( hltLogicalExpression );
00408   // Loop over paths
00409   for ( size_t iPath = 0; iPath < hltAlgoLogicParser.operandTokenVector().size(); ++iPath ) {
00410     const std::string hltPathName( hltAlgoLogicParser.operandTokenVector().at( iPath ).tokenName );
00411     const unsigned indexPath( hltConfig_.triggerIndex( hltPathName ) );
00412     // Further error checks
00413     if ( indexPath == hltConfig_.size() ) {
00414       edm::LogError( "TriggerHelper" ) << "HLT path \"" << hltPathName << "\" is not found in process " << hltInputTag_.process() << " ==> decision: " << errorReplyHlt_;
00415       hltAlgoLogicParser.operandTokenVector().at( iPath ).tokenResult = errorReplyHlt_;
00416       continue;
00417     }
00418     if ( hltTriggerResults->error( indexPath ) ) {
00419       edm::LogError( "TriggerHelper" ) << "HLT path \"" << hltPathName << "\" in error ==> decision: " << errorReplyHlt_;
00420       hltAlgoLogicParser.operandTokenVector().at( iPath ).tokenResult = errorReplyHlt_;
00421       continue;
00422     }
00423     // Manipulate algo decision as stored in the parser
00424     const bool decision( hltTriggerResults->accept( indexPath ) );
00425     hltAlgoLogicParser.operandTokenVector().at( iPath ).tokenResult = decision;
00426   }
00427 
00428   // Determine decision
00429   const bool hltDecision( hltAlgoLogicParser.expressionResult() );
00430   return negExpr ? ( ! hltDecision ) : hltDecision;
00431 
00432 }
00433 
00434 
00435 
00437 std::vector< std::string > TriggerHelper::expressionsFromDB( const std::string & key, const edm::EventSetup & setup )
00438 {
00439 
00440   edm::ESHandle< AlCaRecoTriggerBits > logicalExpressions;
00441   setup.get< AlCaRecoTriggerBitsRcd >().get( logicalExpressions );
00442   const std::map< std::string, std::string > & expressionMap = logicalExpressions->m_alcarecoToTrig;
00443   std::map< std::string, std::string >::const_iterator listIter = expressionMap.find( key );
00444   if ( listIter == expressionMap.end() ) {
00445     edm::LogError( "TriggerHelper" ) << "No logical expressions found under key " << key << " in 'AlCaRecoTriggerBitsRcd'";
00446     return std::vector< std::string >( 1, configError_ );
00447   }
00448   return logicalExpressions->decompose( listIter->second );
00449 
00450 }
00451 
00452 
00453 
00455 bool TriggerHelper::negate( std::string & word ) const
00456 {
00457 
00458   bool negate( false );
00459   if ( word.at( 0 ) == '~' ) {
00460     negate = true;
00461     word.erase( 0, 1 );
00462   }
00463   return negate;
00464 
00465 }