Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:18:29

0001 /** \class TriggerResultsFilter
0002  *
0003  * See header file for documentation
0004  *
0005  *
0006  *  Authors: Martin Grunewald, Andrea Bocci
0007  *
0008  */
0009 
0010 #include <iomanip>
0011 #include <iostream>
0012 #include <sstream>
0013 #include <algorithm>
0014 
0015 #include "DataFormats/Common/interface/TriggerResults.h"
0016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0017 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0018 #include "FWCore/Utilities/interface/Exception.h"
0019 #include "FWCore/Utilities/interface/InputTag.h"
0020 #include "FWCore/Utilities/interface/RegexMatch.h"
0021 #include "FWCore/Utilities/interface/transform.h"
0022 #include "HLTrigger/HLTcore/interface/TriggerExpressionEvaluator.h"
0023 #include "HLTrigger/HLTcore/interface/TriggerExpressionParser.h"
0024 
0025 #include "TriggerResultsFilter.h"
0026 
0027 //
0028 // constructors and destructor
0029 //
0030 TriggerResultsFilter::TriggerResultsFilter(const edm::ParameterSet& config)
0031     : m_expression(nullptr), m_eventCache(config, consumesCollector()) {
0032   std::vector<std::string> const& expressions = config.getParameter<std::vector<std::string>>("triggerConditions");
0033   parse(expressions);
0034   if (m_expression and m_eventCache.usePathStatus()) {
0035     // if the expression was successfully parsed, store the list of patterns,
0036     // each in both std::string and std::regex format
0037     // and with a flag for having valid matches
0038     hltPathStatusPatterns_ = edm::vector_transform(m_expression->patterns(), [](std::string const& pattern) {
0039       return PatternData(pattern, std::regex(edm::glob2reg(pattern), std::regex::extended));
0040     });
0041 
0042     if (hltPathStatusPatterns_.empty()) {
0043       return;
0044     }
0045 
0046     // consume all matching paths
0047     callWhenNewProductsRegistered([this](edm::BranchDescription const& branch) {
0048       if (branch.branchType() == edm::InEvent and branch.className() == "edm::HLTPathStatus") {
0049         bool consumeBranch = true;
0050         for (auto& pattern : hltPathStatusPatterns_) {
0051           if (std::regex_match(branch.moduleLabel(), pattern.regex)) {
0052             pattern.matched = true;
0053             if (consumeBranch) {
0054               consumeBranch = false;
0055               m_eventCache.setPathStatusToken(branch, consumesCollector());
0056             }
0057           }
0058         }
0059       }
0060     });
0061   }
0062 }
0063 
0064 void TriggerResultsFilter::beginStream(edm::StreamID) {
0065   // if throw=True, check if any of the input patterns had zero matches (and if so, throw an exception)
0066   if (not hltPathStatusPatterns_.empty() and m_eventCache.shouldThrow()) {
0067     auto unmatchedPatternsExist = std::any_of(
0068         hltPathStatusPatterns_.cbegin(), hltPathStatusPatterns_.cend(), [](auto foo) { return (not foo.matched); });
0069     if (unmatchedPatternsExist) {
0070       cms::Exception excpt("UnmatchedPatterns");
0071       excpt << "the parameter \"triggerConditions\" contains patterns with zero matches"
0072             << " for the available edm::HLTPathStatus collections - invalid patterns are:";
0073       for (auto const& pattern : hltPathStatusPatterns_)
0074         if (not pattern.matched)
0075           excpt << "\n\t" << pattern.str;
0076       throw excpt;
0077     }
0078   }
0079 }
0080 
0081 void TriggerResultsFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0082   edm::ParameterSetDescription desc;
0083   // # use HLTPathStatus results
0084   desc.add<bool>("usePathStatus", false)
0085       ->setComment("Read the HLT results from the TriggerResults (false) or from the current job's PathStatus (true).");
0086   // # HLT results - set to empty to ignore HLT
0087   desc.add<edm::InputTag>("hltResults", edm::InputTag("TriggerResults", "", "@skipCurrentProcess"))
0088       ->setComment("HLT TriggerResults. Leave empty to ignore the HLT results. Ignored when usePathStatus is true.");
0089   // # L1 uGT results - set to empty to ignore L1T
0090   desc.add<edm::InputTag>("l1tResults", edm::InputTag("hltGtStage2Digis"))
0091       ->setComment("uGT digi collection. Leave empty to ignore the L1T results.");
0092   // # use initial L1 decision, before masks and prescales
0093   desc.add<bool>("l1tIgnoreMaskAndPrescale", false);
0094   // # OBSOLETE - these parameters are ignored, they are left only not to break old configurations
0095   // they will not be printed in the generated cfi.py file
0096   desc.addOptionalNode(edm::ParameterDescription<bool>("l1tIgnoreMask", false, true), false)
0097       ->setComment("This parameter is obsolete and will be ignored.");
0098   desc.addOptionalNode(edm::ParameterDescription<bool>("l1techIgnorePrescales", false, true), false)
0099       ->setComment("This parameter is obsolete and will be ignored.");
0100   desc.addOptionalNode(edm::ParameterDescription<unsigned int>("daqPartitions", 0x01, true), false)
0101       ->setComment("This parameter is obsolete and will be ignored.");
0102   // # throw exception on unknown trigger names
0103   desc.add<bool>("throw", true);
0104   // # trigger conditions
0105   std::vector<std::string> triggerConditions(1, "HLT_*");
0106   desc.add<std::vector<std::string>>("triggerConditions", triggerConditions);
0107   descriptions.add("triggerResultsFilter", desc);
0108 }
0109 
0110 void TriggerResultsFilter::parse(const std::vector<std::string>& expressions) {
0111   // parse the logical expressions into functionals
0112   if (expressions.empty()) {
0113     edm::LogWarning("Configuration") << "Empty trigger results expression";
0114   } else if (expressions.size() == 1) {
0115     parse(expressions[0]);
0116   } else {
0117     std::stringstream expression;
0118     expression << "(" << expressions[0] << ")";
0119     for (unsigned int i = 1; i < expressions.size(); ++i)
0120       expression << " OR (" << expressions[i] << ")";
0121     parse(expression.str());
0122   }
0123 }
0124 
0125 void TriggerResultsFilter::parse(const std::string& expression) {
0126   // parse the logical expressions into functionals
0127   m_expression.reset(triggerExpression::parse(expression));
0128 
0129   // check if the expressions were parsed correctly
0130   if (not m_expression) {
0131     if (m_eventCache.shouldThrow()) {
0132       throw cms::Exception("Configuration") << "Couldn't parse trigger-results expression \"" << expression << "\"";
0133     } else {
0134       edm::LogWarning("Configuration") << "Couldn't parse trigger-results expression \"" << expression << "\"";
0135     }
0136   }
0137 }
0138 
0139 bool TriggerResultsFilter::filter(edm::Event& event, const edm::EventSetup& setup) {
0140   if (not m_expression)
0141     // no valid expression has been parsed
0142     return false;
0143 
0144   if (not m_eventCache.setEvent(event, setup))
0145     // couldn't properly access all information from the Event
0146     return false;
0147 
0148   // if the L1 or HLT configurations have changed, (re)initialize the filters (including during the first event)
0149   if (m_eventCache.configurationUpdated()) {
0150     m_expression->init(m_eventCache);
0151 
0152     // log the expanded configuration
0153     edm::LogInfo("Configuration") << "TriggerResultsFilter configuration updated: " << *m_expression;
0154   }
0155 
0156   // run the trigger results filter
0157   return (*m_expression)(m_eventCache);
0158 }
0159 
0160 // register as framework plugin
0161 #include "FWCore/Framework/interface/MakerMacros.h"
0162 DEFINE_FWK_MODULE(TriggerResultsFilter);