Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:09:27

0001 /** \class HLTHighLevel
0002  *
0003  * See header file for documentation
0004  *
0005  *
0006  *  \author Martin Grunewald
0007  *
0008  */
0009 
0010 #include <vector>
0011 #include <string>
0012 #include <iostream>
0013 #include <iomanip>
0014 
0015 #include "DataFormats/Common/interface/Handle.h"
0016 #include "DataFormats/Common/interface/TriggerResults.h"
0017 #include "DataFormats/Provenance/interface/ModuleDescription.h"
0018 #include "FWCore/Common/interface/TriggerNames.h"
0019 #include "FWCore/Utilities/interface/Exception.h"
0020 #include "FWCore/Utilities/interface/RegexMatch.h"
0021 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0022 #include "FWCore/ServiceRegistry/interface/PathContext.h"
0023 #include "FWCore/ServiceRegistry/interface/PlaceInPathContext.h"
0024 #include "FWCore/ServiceRegistry/interface/ModuleCallingContext.h"
0025 
0026 // needed for trigger bits from EventSetup as in ALCARECO paths
0027 #include "CondFormats/HLTObjects/interface/AlCaRecoTriggerBits.h"
0028 #include "CondFormats/DataRecord/interface/AlCaRecoTriggerBitsRcd.h"
0029 
0030 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0031 #include "HLTHighLevel.h"
0032 
0033 //
0034 // constructors and destructor
0035 //
0036 HLTHighLevel::HLTHighLevel(const edm::ParameterSet& iConfig)
0037     : inputTag_(iConfig.getParameter<edm::InputTag>("TriggerResultsTag")),
0038       inputToken_(consumes<edm::TriggerResults>(inputTag_)),
0039       triggerNamesID_(),
0040       andOr_(iConfig.getParameter<bool>("andOr")),
0041       throw_(iConfig.getParameter<bool>("throw")),
0042       eventSetupPathsKey_(iConfig.getParameter<std::string>("eventSetupPathsKey")),
0043       HLTPatterns_(iConfig.getParameter<std::vector<std::string> >("HLTPaths")),
0044       HLTPathsByName_(),
0045       HLTPathsByIndex_() {
0046   // names and slot numbers are computed during the event loop,
0047   // as they need to access the TriggerNames object via the TriggerResults
0048 
0049   if (!eventSetupPathsKey_.empty()) {
0050     // If paths come from eventsetup, we must watch for IOV changes.
0051     if (!HLTPatterns_.empty()) {
0052       // We do not want double trigger path setting, so throw!
0053       throw cms::Exception("Configuration")
0054           << " HLTHighLevel instance: " << iConfig.getParameter<std::string>("@module_label") << "\n configured with "
0055           << HLTPatterns_.size() << " HLTPaths and\n"
0056           << " eventSetupPathsKey " << eventSetupPathsKey_ << ", choose either of them.";
0057     }
0058     alcaRecotriggerBitsToken_ = esConsumes<AlCaRecoTriggerBits, AlCaRecoTriggerBitsRcd>();
0059     watchAlCaRecoTriggerBitsRcd_.emplace();
0060   }
0061 }
0062 
0063 //
0064 // member functions
0065 //
0066 
0067 void HLTHighLevel::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0068   edm::ParameterSetDescription desc;
0069   desc.add<edm::InputTag>("TriggerResultsTag", edm::InputTag("TriggerResults", "", "HLT"));
0070   std::vector<std::string> hltPaths(0);
0071   // # provide list of HLT paths (or patterns) you want
0072   desc.add<std::vector<std::string> >("HLTPaths", hltPaths);
0073   // # not empty => use read paths from AlCaRecoTriggerBitsRcd via this key
0074   desc.add<std::string>("eventSetupPathsKey", "");
0075   // # how to deal with multiple triggers: True (OR) accept if ANY is true, False (AND) accept if ALL are true
0076   desc.add<bool>("andOr", true);
0077   // # throw exception on unknown path names
0078   desc.add<bool>("throw", true);
0079   descriptions.add("hltHighLevel", desc);
0080 }
0081 
0082 // Initialize the internal trigger path representation (names and indices) from the
0083 // patterns specified in the configuration.
0084 // This needs to be called once at startup, whenever the trigger table has changed
0085 // or in case of paths from eventsetup and IOV changed
0086 void HLTHighLevel::init(const edm::TriggerResults& result,
0087                         const edm::Event& event,
0088                         const edm::EventSetup& iSetup,
0089                         const edm::TriggerNames& triggerNames) {
0090   unsigned int n;
0091 
0092   // clean up old data
0093   HLTPathsByName_.clear();
0094   HLTPathsByIndex_.clear();
0095 
0096   // Overwrite paths from EventSetup via AlCaRecoTriggerBitsRcd if configured:
0097   if (!eventSetupPathsKey_.empty()) {
0098     HLTPatterns_ = this->pathsFromSetup(eventSetupPathsKey_, event, iSetup);
0099   }
0100 
0101   if (HLTPatterns_.empty()) {
0102     // for empty input vector, default to all HLT trigger paths
0103     n = result.size();
0104     HLTPathsByName_.resize(n);
0105     HLTPathsByIndex_.resize(n);
0106     for (unsigned int i = 0; i < n; ++i) {
0107       HLTPathsByName_[i] = triggerNames.triggerName(i);
0108       HLTPathsByIndex_[i] = i;
0109     }
0110   } else {
0111     // otherwise, expand wildcards in trigger names...
0112     for (auto const& pattern : HLTPatterns_) {
0113       if (edm::is_glob(pattern)) {
0114         // found a glob pattern, expand it
0115         std::vector<std::vector<std::string>::const_iterator> matches =
0116             edm::regexMatch(triggerNames.triggerNames(), pattern);
0117         if (matches.empty()) {
0118           // pattern does not match any trigger paths
0119           if (throw_)
0120             throw cms::Exception("Configuration")
0121                 << "requested pattern \"" << pattern << "\" does not match any HLT paths";
0122           else
0123             edm::LogInfo("Configuration") << "requested pattern \"" << pattern << "\" does not match any HLT paths";
0124         } else {
0125           // store the matching patterns
0126           for (auto const& match : matches)
0127             HLTPathsByName_.push_back(*match);
0128         }
0129       } else {
0130         // found a trigger name, just copy it
0131         HLTPathsByName_.push_back(pattern);
0132       }
0133     }
0134     n = HLTPathsByName_.size();
0135 
0136     // ...and get hold of trigger indices
0137     bool valid = false;
0138     HLTPathsByIndex_.resize(n);
0139     for (unsigned int i = 0; i < HLTPathsByName_.size(); i++) {
0140       HLTPathsByIndex_[i] = triggerNames.triggerIndex(HLTPathsByName_[i]);
0141       if (HLTPathsByIndex_[i] < result.size()) {
0142         valid = true;
0143       } else {
0144         // trigger path not found
0145         HLTPathsByIndex_[i] = (unsigned int)-1;
0146         if (throw_)
0147           throw cms::Exception("Configuration") << "requested HLT path \"" << HLTPathsByName_[i] << "\" does not exist";
0148         else
0149           edm::LogInfo("Configuration") << "requested HLT path \"" << HLTPathsByName_[i] << "\" does not exist";
0150       }
0151     }
0152 
0153     if (not valid) {
0154       // no point in throwing - if requested, it should have already happened
0155       edm::LogWarning("Configuration")
0156           << "none of the requested paths and pattern match any HLT path - no events will be selected";
0157     }
0158   }
0159 
0160   // report on what is finally used
0161   LogDebug("HLTHighLevel") << "HLT trigger paths: " + inputTag_.encode() << " - Number of paths: " << n
0162                            << " - andOr mode: " << andOr_ << " - throw mode: " << throw_;
0163 
0164   LogTrace("HLTHighLevel") << "The HLT trigger paths (# index name):";
0165   for (unsigned int i = 0; i < n; ++i)
0166     if (HLTPathsByIndex_[i] == (unsigned int)-1)
0167       LogTrace("HLTHighLevel") << "    n/a   " << HLTPathsByName_[i];
0168     else
0169       LogTrace("HLTHighLevel") << "    " << std::setw(4) << HLTPathsByIndex_[i] << "  " << HLTPathsByName_[i];
0170 }
0171 
0172 // ------------ getting paths from EventSetup  ------------
0173 std::vector<std::string> HLTHighLevel::pathsFromSetup(const std::string& key,
0174                                                       const edm::Event& event,
0175                                                       const edm::EventSetup& iSetup) const {
0176   // Get map of strings to concatenated list of names of HLT paths from EventSetup:
0177   const auto& triggerBits = iSetup.getData(alcaRecotriggerBitsToken_);
0178   typedef std::map<std::string, std::string> TriggerMap;
0179   const TriggerMap& triggerMap = triggerBits.m_alcarecoToTrig;
0180 
0181   auto listIter = triggerMap.find(key);
0182   if (listIter == triggerMap.end()) {
0183     throw cms::Exception("Configuration")
0184         << " HLTHighLevel [instance: " << moduleLabel() << " - path: " << pathName(event)
0185         << "]: No triggerList with key " << key << " in AlCaRecoTriggerBitsRcd";
0186   }
0187 
0188   // We must avoid a map<string,vector<string> > in DB for performance reason,
0189   // so the paths are mapped into one string that we have to decompose:
0190   return triggerBits.decompose(listIter->second);
0191 }
0192 
0193 // ------------ method called to produce the data  ------------
0194 bool HLTHighLevel::filter(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0195   using namespace std;
0196   using namespace edm;
0197 
0198   // get hold of TriggerResults Object
0199   Handle<TriggerResults> trh;
0200   iEvent.getByToken(inputToken_, trh);
0201   if (trh.isValid()) {
0202     LogDebug("HLTHighLevel") << "TriggerResults found, number of HLT paths: " << trh->size();
0203   } else {
0204     LogError("HLTHighLevel") << "TriggerResults product " << inputTag_.encode()
0205                              << " not found - returning result=false!";
0206     return false;
0207   }
0208 
0209   // init the TriggerNames with the TriggerResults
0210   const edm::TriggerNames& triggerNames = iEvent.triggerNames(*trh);
0211   bool config_changed = false;
0212   if (triggerNamesID_ != triggerNames.parameterSetID()) {
0213     triggerNamesID_ = triggerNames.parameterSetID();
0214     config_changed = true;
0215   }
0216 
0217   // (re)run the initialization stuff if
0218   // - this is the first event
0219   // - or the HLT table has changed
0220   // - or selected trigger bits come from AlCaRecoTriggerBitsRcd and these changed
0221   if (config_changed or (watchAlCaRecoTriggerBitsRcd_ and watchAlCaRecoTriggerBitsRcd_->check(iSetup))) {
0222     this->init(*trh, iEvent, iSetup, triggerNames);
0223   }
0224   unsigned int n = HLTPathsByName_.size();
0225   unsigned int nbad = 0;
0226   unsigned int fired = 0;
0227 
0228   // count invalid and fired triggers
0229   for (unsigned int i = 0; i < n; i++)
0230     if (HLTPathsByIndex_[i] == (unsigned int)-1)
0231       ++nbad;
0232     else if (trh->accept(HLTPathsByIndex_[i]))
0233       ++fired;
0234 
0235   if ((nbad > 0) and (config_changed or throw_)) {
0236     // only generate the error message if it's actually going to be used
0237     std::string message;
0238 
0239     for (unsigned int i = 0; i < n; i++)
0240       if (HLTPathsByIndex_[i] == (unsigned int)-1)
0241         message += HLTPathsByName_[i] + " ";
0242 
0243     if (config_changed) {
0244       LogTrace("HLTHighLevel") << " HLTHighLevel [instance: " << moduleLabel() << " - path: " << pathName(iEvent)
0245                                << "] configured with " << nbad << "/" << n << " unknown HLT path names: " << message;
0246     }
0247 
0248     if (throw_) {
0249       throw cms::Exception("Configuration")
0250           << " HLTHighLevel [instance: " << moduleLabel() << " - path: " << pathName(iEvent) << "] configured with "
0251           << nbad << "/" << n << " unknown HLT path names: " << message;
0252     }
0253   }
0254 
0255   // Boolean filter result (always at least one trigger)
0256   const bool accept((fired > 0) and (andOr_ or (fired == n - nbad)));
0257   LogDebug("HLTHighLevel") << "Accept = " << std::boolalpha << accept;
0258 
0259   return accept;
0260 }
0261 
0262 std::string const& HLTHighLevel::pathName(const edm::Event& event) const {
0263   return event.moduleCallingContext()->placeInPathContext()->pathContext()->pathName();
0264 }
0265 
0266 std::string const& HLTHighLevel::moduleLabel() const { return moduleDescription().moduleLabel(); }