Belle II Software  release-05-02-19
TriggerSkimModule.cc
1 
2 /**************************************************************************
3  * BASF2 (Belle Analysis Framework 2) *
4  * Copyright(C) 2016 - Belle II Collaboration *
5  * *
6  * Author: The Belle II Collaboration *
7  * Contributors: David Dossett *
8  * *
9  * This software is provided "as is" without any warranty. *
10  **************************************************************************/
11 
12 #include <calibration/modules/TriggerSkim/TriggerSkimModule.h>
13 #include <hlt/softwaretrigger/core/utilities.h>
14 #include <framework/core/ModuleParam.templateDetails.h>
15 #include <framework/utilities/Utils.h>
16 
17 #include <algorithm>
18 #include <stdexcept>
19 
20 using namespace Belle2;
21 
22 REG_MODULE(TriggerSkim)
23 
25 {
26  // Set module properties
27  setDescription(R"DOC(Trigger Skim Module
28 
29 Module will return an overall result (True/False) based on whether or not ANY or
30 ALL (depending on ``logicMode``) of the specified triggers returned the given
31 value (``expectedResult``) from the SoftwareTriggerResult.
32 
33 Optionally it can apply prescales on each trigger line. In that case ``logicMode='and'``
34 might not be very meaningful as the return value will only be true if all trigger
35 lines were accepted after their own prescale.
36 )DOC");
37  setPropertyFlags(c_ParallelProcessingCertified);
38 
39  // Parameter definitions
40  addParam("triggerLines", m_triggerLines,
41  "Trigger lines to skim on. This can either be just a list of names or "
42  "each item can also optionally be a tuple with name and prescale factor. "
43  "So either ``['hadron', 'cosmic']`` or ``[('hadron', 1), ('cosmic', 20)]`` "
44  "or a mix of both");
45  addParam("expectedResult", m_expectedResult,
46  "The SoftwareTriggerResult value that each trigger line in the ``triggerLines`` "
47  "parameter will be tested for.", int(1));
48  addParam("logicMode", m_logicMode,
49  "Each trigger line in ``triggerLines`` will be tested against the ``expectedResult`` parameter. "
50  "The logic mode controls whether we test using 'and' or 'or' logic to get a return value. "
51  "'and' means that all trigger lines must have ``results == expectedResult``, 'or' means that only "
52  "one of the trigger lines must match the expectedResult value.", m_logicMode);
53  addParam("useRandomNumbersForPreScale", m_useRandomNumbersForPreScale, "Flag to use random numbers (True) "
54  "or a counter (False) for applying the prescale. In the latter case, the module will retain exactly "
55  "one event every N processed, where N (the counter value) is set for each line via the "
56  "``triggerLines`` option. By default, random numbers are used.", m_useRandomNumbersForPreScale);
57  addParam("resultOnMissing", m_resultOnMissing, "Value to return if hlt trigger result is not available or incomplete. "
58  "If this is set to None a FATAL error will be raised if the results are missing. Otherwise the value "
59  "given will be set as return value of the module", m_resultOnMissing);
60 }
61 
63 {
64  if(!m_resultOnMissing) {
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 
103 bool 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  for(auto&& [line, result]: m_trigResults->getResults()) {
114  available_lines += line + "(" + std::to_string((int)result) + ") ";
115  }
116  if(m_resultOnMissing) {
117  B2WARNING("Software trigger line not found" << LogVar("requested", name)
118  << LogVar("available", available_lines)
119  << LogVar("errorFlag", m_eventMetaDataPtr->getErrorFlag())
120  << LogVar("experiment", m_eventMetaDataPtr->getExperiment())
121  << LogVar("run", m_eventMetaDataPtr->getRun())
122  << LogVar("event", m_eventMetaDataPtr->getEvent()));
123  return *m_resultOnMissing;
124  }
125  else {
126  B2FATAL("Software trigger line not found (if this is expected, please use the `resultOnMissing` parameter)"
127  << LogVar("requested", name)
128  << LogVar("available", available_lines)
129  << LogVar("errorFlag", m_eventMetaDataPtr->getErrorFlag())
130  << LogVar("experiment", m_eventMetaDataPtr->getExperiment())
131  << LogVar("run", m_eventMetaDataPtr->getRun())
132  << LogVar("event", m_eventMetaDataPtr->getEvent()));
133  return false;
134  }
135  }
136 }
137 
139 {
140  if(!m_trigResults) {
141  if(m_resultOnMissing) {
143  return;
144  }
145  B2FATAL("No HLT Trigger result available (if this is expected to be possible "
146  "please use the `resultOnMissing` parameter");
147  }
148  // count accepted triggers
149  size_t numAccepted(0);
150  // Now check all lines, index is the prescale counter if needed
151  size_t counterIndex{0};
152  for(const auto& triggerLine: m_triggerLines) {
153  const bool accept = boost::apply_visitor(Utils::VisitOverload{
154  // check in prescale case
155  [this, &counterIndex](const std::tuple<std::string, unsigned int>& line) {
156  const auto& [name, prescale] = line;
157  uint32_t* prescaleCounter = m_useRandomNumbersForPreScale ? nullptr : &m_prescaleCounters[counterIndex++];
158  return checkTrigger(name, prescale, prescaleCounter);
159  },
160  // check without prescale
161  [this](const std::string& name) {
162  return checkTrigger(name);
163  },
164  }, triggerLine);
165  if(accept)
166  ++numAccepted;
167  }
168 
169  // Apply our logic on the test results
170  if (m_logicMode == "and") {
171  setReturnValue(numAccepted == m_triggerLines.size());
172  }
173  if (m_logicMode == "or") {
174  setReturnValue(numAccepted > 0);
175  }
176 }
Belle2::TriggerSkimModule
Returns the calibration result from SoftwareTriigerResult for skimming out calibration flagged events...
Definition: TriggerSkimModule.h:39
Belle2::Utils::VisitOverload
Helper struct for the C++17 std::visit overload pattern to allow simple use of variants.
Definition: Utils.h:19
Belle2::TriggerSkimModule::m_logicMode
std::string m_logicMode
do we want each or any trigger line?
Definition: TriggerSkimModule.h:60
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::TriggerSkimModule::event
virtual void event() override
Event function.
Definition: TriggerSkimModule.cc:138
Belle2::TriggerSkimModule::m_prescaleCounters
std::vector< uint32_t > m_prescaleCounters
if we don't use random prescale we need counters
Definition: TriggerSkimModule.h:66
Belle2::TriggerSkimModule::initialize
virtual void initialize() override
Initialize.
Definition: TriggerSkimModule.cc:62
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
LogVar
Class to store variables with their name which were sent to the logging service.
Definition: LogVariableStream.h:24
Belle2::Module::setReturnValue
void setReturnValue(int value)
Sets the return value for this module as integer.
Definition: Module.cc:222
Belle2::TriggerSkimModule::m_expectedResult
int m_expectedResult
Result we want for each or any trigger line.
Definition: TriggerSkimModule.h:58
Belle2::TriggerSkimModule::checkTrigger
bool checkTrigger(const std::string &name, unsigned int prescale=1, uint32_t *counter=nullptr) const
Check a single trigger line for the expected result.
Definition: TriggerSkimModule.cc:103
Belle2::TriggerSkimModule::m_resultOnMissing
boost::optional< int > m_resultOnMissing
value to return if there's no SoftwareTriggerResult
Definition: TriggerSkimModule.h:64
Belle2::TriggerSkimModule::m_trigResults
StoreObjPtr< SoftwareTriggerResult > m_trigResults
Required input for trigger results.
Definition: TriggerSkimModule.h:54
Belle2::TriggerSkimModule::m_triggerLines
std::vector< boost::variant< std::string, std::tuple< std::string, unsigned int > > > m_triggerLines
List of triggerlines we're interested in.
Definition: TriggerSkimModule.h:56
Belle2::TriggerSkimModule::m_eventMetaDataPtr
StoreObjPtr< EventMetaData > m_eventMetaDataPtr
EventMetaData is used to report warning/error messages.
Definition: TriggerSkimModule.h:68
Belle2::SoftwareTriggerCutResult
SoftwareTriggerCutResult
Enumeration with all possible results of the SoftwareTriggerCut.
Definition: SoftwareTriggerResult.h:31
Belle2::TriggerSkimModule::m_useRandomNumbersForPreScale
bool m_useRandomNumbersForPreScale
and do we want random prescale or counters ?
Definition: TriggerSkimModule.h:62