Belle II Software development
TriggerSkimModule.cc
1
2/**************************************************************************
3 * basf2 (Belle II Analysis Software Framework) *
4 * Author: The Belle II Collaboration *
5 * *
6 * See git log for contributors and copyright holders. *
7 * This file is licensed under LGPL-3.0, see LICENSE.md. *
8 **************************************************************************/
9
10#include <calibration/modules/TriggerSkim/TriggerSkimModule.h>
11#include <hlt/softwaretrigger/core/utilities.h>
12#include <framework/core/ModuleParam.templateDetails.h>
13#include <framework/utilities/Utils.h>
14
15#include <algorithm>
16#include <stdexcept>
17
18using namespace Belle2;
19
20REG_MODULE(TriggerSkim);
21
23{
24 // Set module properties
25 setDescription(R"DOC(Trigger Skim Module
26
27Module will return an overall result (True/False) based on whether or not ANY or
28ALL (depending on ``logicMode``) of the specified triggers returned the given
29value (``expectedResult``) from the SoftwareTriggerResult.
30
31Optionally it can apply prescales on each trigger line. In that case ``logicMode='and'``
32might not be very meaningful as the return value will only be true if all trigger
33lines were accepted after their own prescale.
34)DOC");
36
37 // Parameter definitions
38 addParam("triggerLines", m_triggerLines,
39 "Trigger lines to skim on. This can either be just a list of names or "
40 "each item can also optionally be a tuple with name and prescale factor. "
41 "So either ``['hadron', 'cosmic']`` or ``[('hadron', 1), ('cosmic', 20)]`` "
42 "or a mix of both");
43 addParam("expectedResult", m_expectedResult,
44 "The SoftwareTriggerResult value that each trigger line in the ``triggerLines`` "
45 "parameter will be tested for.", int(1));
46 addParam("logicMode", m_logicMode,
47 "Each trigger line in ``triggerLines`` will be tested against the ``expectedResult`` parameter. "
48 "The logic mode controls whether we test using 'and' or 'or' logic to get a return value. "
49 "'and' means that all trigger lines must have ``results == expectedResult``, 'or' means that only "
50 "one of the trigger lines must match the expectedResult value.", m_logicMode);
51 addParam("useRandomNumbersForPreScale", m_useRandomNumbersForPreScale, "Flag to use random numbers (True) "
52 "or a counter (False) for applying the prescale. In the latter case, the module will retain exactly "
53 "one event every N processed, where N (the counter value) is set for each line via the "
54 "``triggerLines`` option. By default, random numbers are used.", m_useRandomNumbersForPreScale);
55 addParam("resultOnMissing", m_resultOnMissing, "Value to return if hlt trigger result is not available or incomplete. "
56 "If this is set to None a FATAL error will be raised if the results are missing. Otherwise the value "
57 "given will be set as return value of the module", m_resultOnMissing);
58 addParam("skipFirstEvent", m_firstEvent, "Boolean to skip the first event or not. "
59 "If the module is used inside the hbasf2, like HLT storage, the first event need to be skipped.", m_firstEvent);
60}
61
63{
65 m_trigResults.isRequired();
66 } else {
67 m_trigResults.isOptional();
68 }
69 if (m_logicMode != "and" and m_logicMode != "or") {
70 B2FATAL("You have entered an invalid parameter for logicMode. "
71 "Valid strings are any of ['or', 'and']");
72 }
73 if(m_expectedResult < -1 or m_expectedResult > 1) {
74 B2FATAL("Expected trigger result needs to be -1, 0 or 1");
75 }
76
77 // check if and how many prescales we have
78 int havePrescales{0};
79 for(const auto& triggerLine: m_triggerLines){
80 boost::apply_visitor(Utils::VisitOverload{
81 [&havePrescales](const std::tuple<std::string, unsigned int>& line) {
82 const auto& [name, prescale] = line;
83 if(prescale < 1) {
84 B2ERROR("Prescale is not positive, needs to be at least 1"
85 << LogVar("trigger line", name) << LogVar("prescale", prescale));
86 }
87 ++havePrescales;
88 B2DEBUG(20, "Prescale of " << prescale << " to be applied to " << name);
89 },
90 [](const std::string& name) {
91 // nothing to do without prescales
92 B2DEBUG(20, "No prescales to be applied to " << name);
93 },
94 }, triggerLine);
95 }
96 // and reserve counters if we need them
97 if(havePrescales > 0 and not m_useRandomNumbersForPreScale) {
98 m_prescaleCounters.clear();
99 m_prescaleCounters.assign(havePrescales, 0);
100 }
101}
102
103bool TriggerSkimModule::checkTrigger(const std::string& name, unsigned int prescale, uint32_t* counter) const {
104 try {
105 bool accepted = m_trigResults->getResult(name) == static_cast<SoftwareTriggerCutResult>(m_expectedResult);
106 if(accepted and prescale != 1) {
107 accepted &= SoftwareTrigger::makePreScale(prescale, counter);
108 }
109 return accepted;
110 } catch(std::out_of_range &e) {
111 // typo? change in lines? In any case we nope out of here but let's try to give a helpful message
112 std::string available_lines = "";
113 // cppcheck-suppress unassignedVariable
114 for(auto&& [line, result]: m_trigResults->getResults()) {
115 available_lines += line + "(" + std::to_string((int)result) + ") ";
116 }
118 B2WARNING("Software trigger line not found" << LogVar("requested", name)
119 << LogVar("available", available_lines)
120 << LogVar("errorFlag", m_eventMetaDataPtr->getErrorFlag())
121 << LogVar("experiment", m_eventMetaDataPtr->getExperiment())
122 << LogVar("run", m_eventMetaDataPtr->getRun())
123 << LogVar("event", m_eventMetaDataPtr->getEvent()));
124 return *m_resultOnMissing;
125 }
126 else {
127 B2FATAL("Software trigger line not found (if this is expected, please use the `resultOnMissing` parameter)"
128 << LogVar("requested", name)
129 << LogVar("available", available_lines)
130 << LogVar("errorFlag", m_eventMetaDataPtr->getErrorFlag())
131 << LogVar("experiment", m_eventMetaDataPtr->getExperiment())
132 << LogVar("run", m_eventMetaDataPtr->getRun())
133 << LogVar("event", m_eventMetaDataPtr->getEvent()));
134 return false;
135 }
136 }
137}
138
140{
141 if(m_firstEvent) {
142 m_firstEvent = false;
143 setReturnValue(true);
144 return;
145 }
146 if(!m_trigResults) {
149 return;
150 }
151 B2FATAL("No HLT Trigger result available (if this is expected to be possible "
152 "please use the `resultOnMissing` parameter");
153 }
154 // count accepted triggers
155 size_t numAccepted(0);
156 // Now check all lines, index is the prescale counter if needed
157 size_t counterIndex{0};
158 for(const auto& triggerLine: m_triggerLines) {
159 const bool accept = boost::apply_visitor(Utils::VisitOverload{
160 // check in prescale case
161 [this, &counterIndex](const std::tuple<std::string, unsigned int>& line) {
162 const auto& [name, prescale] = line;
163 uint32_t* prescaleCounter = m_useRandomNumbersForPreScale ? nullptr : &m_prescaleCounters[counterIndex++];
164 return checkTrigger(name, prescale, prescaleCounter);
165 },
166 // check without prescale
167 [this](const std::string& name) {
168 return checkTrigger(name);
169 },
170 }, triggerLine);
171 if(accept)
172 ++numAccepted;
173 }
174
175 // Apply our logic on the test results
176 if (m_logicMode == "and") {
177 setReturnValue(numAccepted == m_triggerLines.size());
178 }
179 if (m_logicMode == "or") {
180 setReturnValue(numAccepted > 0);
181 }
182}
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
void setReturnValue(int value)
Sets the return value for this module as integer.
Definition: Module.cc:220
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
bool m_firstEvent
Check event is the first event for hbasf2 usage, especiaaly for HLT storage.
std::string m_logicMode
do we want each or any trigger line?
virtual void initialize() override
Initialize.
std::optional< int > m_resultOnMissing
value to return if there's no SoftwareTriggerResult
virtual void event() override
Event function.
int m_expectedResult
Result we want for each or any trigger line.
std::vector< boost::variant< std::string, std::tuple< std::string, unsigned int > > > m_triggerLines
List of triggerlines we're interested in.
std::vector< uint32_t > m_prescaleCounters
if we don't use random prescale we need counters
bool m_useRandomNumbersForPreScale
and do we want random prescale or counters ?
StoreObjPtr< SoftwareTriggerResult > m_trigResults
Required input for trigger results.
StoreObjPtr< EventMetaData > m_eventMetaDataPtr
EventMetaData is used to report warning/error messages.
bool checkTrigger(const std::string &name, unsigned int prescale=1, uint32_t *counter=nullptr) const
Check a single trigger line for the expected result.
TriggerSkimModule()
Constructor: Sets the description, the properties and the parameters of the module.
Class to store variables with their name which were sent to the logging service.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
SoftwareTriggerCutResult
Enumeration with all possible results of the SoftwareTriggerCut.
Abstract base class for different kinds of events.
Helper struct for the C++17 std::visit overload pattern to allow simple use of variants.
Definition: Utils.h:26