Belle II Software  release-06-01-15
EventInfoSetterModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <framework/modules/core/EventInfoSetterModule.h>
10 
11 #include <framework/core/Environment.h>
12 #include <framework/utilities/Utils.h>
13 
14 #include <chrono>
15 #include <set>
16 
17 using namespace std;
18 using namespace Belle2;
19 
20 //-----------------------------------------------------------------
21 // Register the Module
22 //-----------------------------------------------------------------
23 REG_MODULE(EventInfoSetter)
24 
25 //-----------------------------------------------------------------
26 // Implementation
27 //-----------------------------------------------------------------
28 
30 {
31  if (getenv("BELLE2_PRODUCTION"))
32  m_production = stoi(getenv("BELLE2_PRODUCTION"));
33 
34  //Set module properties
35  setDescription(
36  "Sets the event meta data information (exp, run, evt). You must use this "
37  "module to tell basf2 about the number of events you want to generate, "
38  "unless you have an input module that already does so. Note that all "
39  "experiment/run combinations specified must be unique."
40  );
41 
42  //Parameter definition
43  addParam("expList", m_expList, "List of experiment numbers. Can be overridden via --experiment argument to basf2.", m_expList);
44  addParam("runList", m_runList, "List of run numbers. Can be overridden via --run argument to basf2.", m_runList);
45  addParam("evtNumList", m_evtNumList, "List of the number of events which "
46  "should be processed. Can be overridden via -n argument to basf2.",
47  m_evtNumList);
48  addParam("skipNEvents", m_eventsToSkip, "Skip this number of events before "
49  "starting. Equivalent to running over this many events without performing "
50  "any action, to allow starting at higher event numbers.", m_eventsToSkip);
51  addParam("skipToEvent", m_skipToEvent, "Skip events until the event with "
52  "the specified (experiment, run, event number) occurs. This parameter "
53  "is useful for debugging to start with a specific event.", m_skipToEvent);
54 }
55 
56 EventInfoSetterModule::~EventInfoSetterModule() = default;
57 
58 void EventInfoSetterModule::initialize()
59 {
60  //Register the EventMetaData in the data store
61  m_eventMetaDataPtr.registerInDataStore(DataStore::c_ErrorIfAlreadyRegistered);
62 
63  //steering file content overwritten via command line arguments?
64  unsigned int numEventsArgument = Environment::Instance().getNumberEventsOverride();
65  int runOverride = Environment::Instance().getRunOverride();
66  int expOverride = Environment::Instance().getExperimentOverride();
67  if (numEventsArgument > 0 or runOverride >= 0 or expOverride >= 0) {
68  if (m_evtNumList.size() > 1) {
69  B2ERROR("The -n/--events, --run, and --experiment options cannot be used when multiple runs are specified for EventInfoSetter!");
70  }
71  m_evtNumList[0] = numEventsArgument;
72  if (runOverride >= 0)
73  m_runList[0] = runOverride;
74  if (expOverride >= 0)
75  m_expList[0] = expOverride;
76  }
77 
78  unsigned int skipNEventsOverride = Environment::Instance().getSkipEventsOverride();
79  if (skipNEventsOverride != 0)
80  m_eventsToSkip = skipNEventsOverride;
81 
82  //Make sure all lists have the same size
83  unsigned int defListSize = m_expList.size();
84  if ((m_runList.size() != defListSize) || (m_evtNumList.size() != defListSize)) {
85  B2ERROR("Parameters are inconsistent. The exp, run and evt lists must have the same number of entries.");
86  } else if (defListSize == 0) {
87  B2ERROR("There are no events to be processed!");
88  } else {
89  set<pair<int, int>> expRunSet;
90  for (unsigned int i = 0; i < defListSize; i++) {
91  auto ret = expRunSet.insert(make_pair(m_expList[i], m_runList[i]));
92  if (!ret.second) {
93  B2ERROR("Exp " << ret.first->first << ", run " << ret.first->second <<
94  " used more than once! Please make sure all experiment/run combinations are unique.");
95  }
96  if (m_expList[i] < 0 or m_expList[i] > 1023)
97  B2ERROR("Experiment " << m_expList[i] << " is out of range, should be in [0, 1023]!");
98  if (m_runList[i] < 0)
99  B2ERROR("Run " << m_runList[i] << " is out of range, should be >= 0!");
100  unsigned int nevents = m_evtNumList[i];
101  if (nevents == std::numeric_limits<unsigned int>::max()) {
102  B2ERROR("Invalid number of events (valid range: 0.." << std::numeric_limits<unsigned int>::max() - 1 << ")!");
103  }
104  }
105  }
106 
107  if (!m_skipToEvent.empty()) {
108  // make sure the number of entries is exactly 3
109  if (m_skipToEvent.size() != 3) {
110  B2ERROR("skipToEvent must be a list of three values: experiment, run, event number");
111  // ignore the value
112  m_skipToEvent.clear();
113  }
114  if (m_eventsToSkip > 0) {
115  B2ERROR("You cannot supply a number of events to skip (skipNEvents) and an "
116  "event to skip to (skipToEvent) at the same time, ignoring skipNEvents");
117  //force the number of skipped events to be zero
118  m_eventsToSkip = 0;
119  }
120  }
121 
122  m_evtNumber = 1;
123  m_colIndex = 0; //adjusted in event() if mismatched
124 
125  //determine number of events we will process
126  unsigned int totalevents = 0;
127  Belle2::EventInfoSetterModule copy(*this);
128  while (copy.advanceEventCounter()) {
129  copy.m_evtNumber++;
130  totalevents++;
131  }
132  B2DEBUG(100, "EventInfoSetter: will process " << totalevents << " events in total.");
133  if (totalevents == 0) {
134  B2FATAL("Total processed number of events is 0, please check your inputs, -n and --skip-events arguments!");
135  }
136  Environment::Instance().setNumberOfMCEvents(totalevents);
137 }
138 
139 
140 bool EventInfoSetterModule::advanceEventCounter()
141 {
142  // optimized for the assumed normal case of few runs with lots of events
143  // and no skipping.
144  // In the case of 1e9 events, the branch prediction hints give the following
145  // improvements:
146  // clang: -18% real time
147  // gcc (opt): -52% real time
148  while (true) {
149  if (branch_unlikely(m_evtNumber > m_evtNumList[m_colIndex])) {
150 
151  //Search for a column where the event number is greater than 0.
152  do {
153  m_colIndex++;
154  } while ((m_colIndex < static_cast<int>(m_expList.size())) &&
155  (m_evtNumList[m_colIndex] == 0));
156 
157  if (m_colIndex < static_cast<int>(m_expList.size())) {
158  m_evtNumber = 1;
159  } else { //no experiment/run with non-zero number of events found
160  return false;
161  }
162  }
163 
164  // check if we want to skip to a specific event
165  if (branch_unlikely(!m_skipToEvent.empty())) {
166  // if current experiment and run number is different to what we're looking for
167  if (m_skipToEvent[0] != m_expList[m_colIndex] || m_skipToEvent[1] != m_runList[m_colIndex]) {
168  // then we set the m_evtNumber to the max+1
169  m_evtNumber = m_evtNumList[m_colIndex] + 1;
170  } else {
171  // otherwise we start at the event number we want to skip to
172  m_evtNumber = m_skipToEvent[2];
173  // and reset the variable as skipping is done
174  m_skipToEvent.clear();
175  }
176  // and check again if the event number is in the range we want to generate
177  } else if (branch_unlikely(m_eventsToSkip != 0)) { //are we still skipping?
178  unsigned int nskip = 1;
179  const unsigned int eventsInList = m_evtNumList[m_colIndex];
180  if (m_evtNumber <= eventsInList) //skip to end of current run?
181  nskip = eventsInList - m_evtNumber + 1;
182  if (nskip > m_eventsToSkip)
183  nskip = m_eventsToSkip;
184 
185  m_eventsToSkip -= nskip;
186  m_evtNumber += nskip;
187  } else {
188  break;
189  }
190  }
191  return true;
192 }
193 
194 void EventInfoSetterModule::event()
195 {
196  if (!advanceEventCounter())
197  return;
198 
199  m_eventMetaDataPtr.create();
200  m_eventMetaDataPtr->setProduction(m_production);
201  m_eventMetaDataPtr->setExperiment(m_expList[m_colIndex]);
202  m_eventMetaDataPtr->setRun(m_runList[m_colIndex]);
203  m_eventMetaDataPtr->setEvent(m_evtNumber);
204  auto time = std::chrono::high_resolution_clock::now().time_since_epoch();
205  m_eventMetaDataPtr->setTime(std::chrono::duration_cast<std::chrono::nanoseconds>(time).count());
206 
207  m_evtNumber++;
208 }
Module to set event, run, experiment numbers.
Base class for Modules.
Definition: Module.h:72
#define branch_unlikely(x)
A macro to tell the compiler that the argument x will be very likely be false.
Definition: Utils.h:134
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.