1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
|
/** \class TriggerResultsFilter
*
* See header file for documentation
*
*
* Authors: Martin Grunewald, Andrea Bocci
*
*/
#include <iomanip>
#include <iostream>
#include <sstream>
#include <algorithm>
#include "DataFormats/Common/interface/TriggerResults.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/Utilities/interface/Exception.h"
#include "FWCore/Utilities/interface/InputTag.h"
#include "FWCore/Utilities/interface/RegexMatch.h"
#include "FWCore/Utilities/interface/transform.h"
#include "HLTrigger/HLTcore/interface/TriggerExpressionEvaluator.h"
#include "HLTrigger/HLTcore/interface/TriggerExpressionParser.h"
#include "TriggerResultsFilter.h"
//
// constructors and destructor
//
TriggerResultsFilter::TriggerResultsFilter(const edm::ParameterSet& config)
: m_expression(nullptr), m_eventCache(config, consumesCollector()) {
std::vector<std::string> const& expressions = config.getParameter<std::vector<std::string>>("triggerConditions");
parse(expressions);
if (m_expression and m_eventCache.usePathStatus()) {
// if the expression was successfully parsed, store the list of patterns,
// each in both std::string and std::regex format
// and with a flag for having valid matches
hltPathStatusPatterns_ = edm::vector_transform(m_expression->patterns(), [](std::string const& pattern) {
return PatternData(pattern, std::regex(edm::glob2reg(pattern), std::regex::extended));
});
if (hltPathStatusPatterns_.empty()) {
return;
}
// consume all matching paths
callWhenNewProductsRegistered([this](edm::ProductDescription const& branch) {
if (branch.branchType() == edm::InEvent and branch.className() == "edm::HLTPathStatus") {
bool consumeBranch = true;
for (auto& pattern : hltPathStatusPatterns_) {
if (std::regex_match(branch.moduleLabel(), pattern.regex)) {
pattern.matched = true;
if (consumeBranch) {
consumeBranch = false;
m_eventCache.setPathStatusToken(branch, consumesCollector());
}
}
}
}
});
}
}
void TriggerResultsFilter::beginStream(edm::StreamID) {
// if throw=True, check if any of the input patterns had zero matches (and if so, throw an exception)
if (not hltPathStatusPatterns_.empty() and m_eventCache.shouldThrow()) {
auto unmatchedPatternsExist = std::any_of(
hltPathStatusPatterns_.cbegin(), hltPathStatusPatterns_.cend(), [](auto foo) { return (not foo.matched); });
if (unmatchedPatternsExist) {
cms::Exception excpt("UnmatchedPatterns");
excpt << "the parameter \"triggerConditions\" contains patterns with zero matches"
<< " for the available edm::HLTPathStatus collections - invalid patterns are:";
for (auto const& pattern : hltPathStatusPatterns_)
if (not pattern.matched)
excpt << "\n\t" << pattern.str;
throw excpt;
}
}
}
void TriggerResultsFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
// # use HLTPathStatus results
desc.add<bool>("usePathStatus", false)
->setComment("Read the HLT results from the TriggerResults (false) or from the current job's PathStatus (true).");
// # HLT results - set to empty to ignore HLT
desc.add<edm::InputTag>("hltResults", edm::InputTag("TriggerResults", "", "@skipCurrentProcess"))
->setComment("HLT TriggerResults. Leave empty to ignore the HLT results. Ignored when usePathStatus is true.");
// # L1 uGT results - set to empty to ignore L1T
desc.add<edm::InputTag>("l1tResults", edm::InputTag("hltGtStage2Digis"))
->setComment("uGT digi collection. Leave empty to ignore the L1T results.");
// # use initial L1 decision, before masks and prescales
desc.add<bool>("l1tIgnoreMaskAndPrescale", false);
// # OBSOLETE - these parameters are ignored, they are left only not to break old configurations
// they will not be printed in the generated cfi.py file
desc.addOptionalNode(edm::ParameterDescription<bool>("l1tIgnoreMask", false, true), false)
->setComment("This parameter is obsolete and will be ignored.");
desc.addOptionalNode(edm::ParameterDescription<bool>("l1techIgnorePrescales", false, true), false)
->setComment("This parameter is obsolete and will be ignored.");
desc.addOptionalNode(edm::ParameterDescription<unsigned int>("daqPartitions", 0x01, true), false)
->setComment("This parameter is obsolete and will be ignored.");
// # throw exception on unknown trigger names
desc.add<bool>("throw", true);
// # trigger conditions
std::vector<std::string> triggerConditions(1, "HLT_*");
desc.add<std::vector<std::string>>("triggerConditions", triggerConditions);
descriptions.add("triggerResultsFilter", desc);
}
void TriggerResultsFilter::parse(const std::vector<std::string>& expressions) {
// parse the logical expressions into functionals
if (expressions.empty()) {
edm::LogWarning("Configuration") << "Empty trigger results expression";
} else if (expressions.size() == 1) {
parse(expressions[0]);
} else {
std::stringstream expression;
expression << "(" << expressions[0] << ")";
for (unsigned int i = 1; i < expressions.size(); ++i)
expression << " OR (" << expressions[i] << ")";
parse(expression.str());
}
}
void TriggerResultsFilter::parse(const std::string& expression) {
// parse the logical expressions into functionals
m_expression.reset(triggerExpression::parse(expression));
// check if the expressions were parsed correctly
if (not m_expression) {
if (m_eventCache.shouldThrow()) {
throw cms::Exception("Configuration") << "Couldn't parse trigger-results expression \"" << expression << "\"";
} else {
edm::LogWarning("Configuration") << "Couldn't parse trigger-results expression \"" << expression << "\"";
}
}
}
bool TriggerResultsFilter::filter(edm::Event& event, const edm::EventSetup& setup) {
if (not m_expression)
// no valid expression has been parsed
return false;
if (not m_eventCache.setEvent(event, setup))
// couldn't properly access all information from the Event
return false;
// if the L1 or HLT configurations have changed, (re)initialize the filters (including during the first event)
if (m_eventCache.configurationUpdated()) {
m_expression->init(m_eventCache);
// log the expanded configuration
edm::LogInfo("Configuration") << "TriggerResultsFilter configuration updated: " << *m_expression;
}
// run the trigger results filter
return (*m_expression)(m_eventCache);
}
// register as framework plugin
#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(TriggerResultsFilter);
|