Belle II Software  release-08-01-10
SteerRootInputModule.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/core/SteerRootInputModule.h>
10 
11 #include <framework/core/Environment.h>
12 #include <framework/core/InputController.h>
13 
14 
15 using namespace Belle2;
16 
17 //REG_MODLUE needed for --execute-path functionality
18 //Note: should not appear in module list since we're not in the right directory
19 REG_MODULE(SteerRootInput);
20 
22 {
23  setDescription("Internal module used by Path.add_independent_merge_path(). This shouldn't appear in 'basf2 -m' output. If it does, check REG_MODULE() handling.");
24 
25  // ATTENTION! This module is NOT SAFE for parallel processing (do not set flag c_ParallelProcessingCertified)
26 
27  addParam("eventMixing", m_eventMixing, "merge each event of main path with each event of independent path", false);
28  // I have to set this parameter explicitly (cannot use InputController::getCurrentFileName() as we're dealing with TChains and might be at different files)
29  addParam("mergeSameFile", m_mergeSameFile, "if you want to merge a file with itself, mixing evts (1,3) is the same as (3,1)",
30  false);
31 }
32 
33 SteerRootInputModule::~SteerRootInputModule() = default;
34 
35 void SteerRootInputModule::init(bool eventMixing, bool mergeSameFile)
36 {
37  m_eventMixing = eventMixing;
38  m_mergeSameFile = mergeSameFile;
39 }
40 
42 {
43  m_eventMetaData_main.isRequired();
44  m_eventMetaData_indep.isRequired();
45 
46  if (!m_mergedEventConsistency.isOptional()) {
47  B2ERROR("Object MergedEventConsistency not found. This is not expected.");
48  }
49 
50  std::pair<long, long> numEntries = { InputController::numEntries(false), InputController::numEntries(true)};
51  std::pair<long, long> skippedEntries = { InputController::getSkippedEntries(false), InputController::getSkippedEntries(true)};
52 
53  if (m_mergeSameFile) {
54  if (!m_eventMixing) {
55  B2ERROR("It does not make sense to merge a file with itself if you're not doing event mixing.");
56  } else {
57  // quick check if you're really trying to mix a file with itself
58  if (numEntries.first != numEntries.second) {
59  B2ERROR("Are you sure you are mixing a file with itself? Inconsistent number of events found.");
60  }
61  // if merging a file with itself, it is only possible if you're skipping the same number of events in both of them
62  if (skippedEntries.first != skippedEntries.second) {
63  B2ERROR("Cannot mix file with itself if you're skipping a different number of events in both RootInputModules");
64  }
65  }
66  }
67 
70  B2ERROR("Event mixing not possible if you want to skip to a certain exp/run/evt with the RootInputModule."
71  " Please skip to a certain entry in the File instead (use parameter 'skipNEvents').");
72  }
73 
74  // Tell the InputController that we are controlling it
76  // Tell the InputController/Environment how many events we want to process
77  // These are UPPER thresholds. We use EventMetaData::setEndOfData() to end processing early if we're done
78  // We don't know how many events will have to be skipped (inconsistent charge) so there is not much more we can do here
79  long evtsToProcess = -1;
80  if (m_eventMixing) {
81  // we want to be able to process each event of first path along with each event of second path
82  evtsToProcess = (numEntries.first - skippedEntries.first) * (numEntries.second - skippedEntries.second);
83  } else {
84  // we want to end processing if both paths are done (may skip events in one path because of unphysical combinations)
85  evtsToProcess = std::max((numEntries.first - skippedEntries.first), (numEntries.second - skippedEntries.second));
86  }
87  if (Environment::Instance().getNumberEventsOverride() == 0 || evtsToProcess < Environment::Instance().getNumberEventsOverride()) {
89  }
90 }
91 
93 {
94  // We expect that both RootInputModules called InputController::eventLoaded(...) so
95  // both indices should be -1 (otherwise something bad happened)
96  if (InputController::getNextEntry(false) != -1 && InputController::getNextEntry(true) != -1) {
97  B2FATAL("This should not happen. Expected that both paths were processed at this point.");
98  }
99 
100  // Were the previous events the last one to be processed?
101  // (see below for explanation why we have to do that)
102  if (m_processedLastEvent) {
103  m_eventMetaData_main->setEndOfData();
104  setReturnValue(false);
105  return;
106  }
107 
108  // We want to do a few checks if the combination of events make sense
109  // But the module has to be run in any case to set events, which should be processed next
110  bool goodMerge = true;
111  // And this will be set to the events to be processed next
112  std::pair <long, long> nextEntries;
113 
114  std::pair<long, long> numEntries = { InputController::numEntries(false), InputController::numEntries(true)};
115  std::pair <long, long> currEntries = { InputController::getCurrentEntry(false), InputController::getCurrentEntry(true)};
116 
117  // Make sure charge is consistent (if this option is enabled)
118  if (m_mergedEventConsistency.isValid()) {
119  goodMerge = m_mergedEventConsistency->getConsistent();
120  }
121 
122  // Make sure an event is not merged with itself (not physical)
123  if (goodMerge) {
124  goodMerge = (m_eventMetaData_main->getEvent() != m_eventMetaData_indep->getEvent() ||
125  m_eventMetaData_main->getRun() != m_eventMetaData_indep->getRun() ||
126  m_eventMetaData_main->getExperiment() != m_eventMetaData_indep->getExperiment());
127  }
128 
129  if (m_eventMixing) {
130  // Process events in order (0,0), (0,1), ..., (0,n), (1,0), (1,1), ...
131  // If merging file with itself (1,0) is the same as (0,1)
132  // This module is executed AFTER the RootInputModules
133  // So set indices for next call of event()
134  // First pair of events (0,0) already processed when this method is called for the first time
135  nextEntries = std::make_pair(currEntries.first, currEntries.second + 1);
136  // if end of second file reached, load next event in first files
137  if (nextEntries.second == numEntries.second) {
138  ++nextEntries.first;
139  if (!m_mergeSameFile) {
140  nextEntries.second = InputController::getSkippedEntries(true);
141  } else {
142  // we made sure that the same number of events is skipped in both RootInputModules
143  nextEntries.second = nextEntries.first + 1;
144  }
145  }
146  } else {
147  // only advance to next event in first file if we don't have to skip this combination of events
148  if (goodMerge) {
149  nextEntries = std::make_pair(currEntries.first + 1, currEntries.second + 1);
150  } else {
151  nextEntries = std::make_pair(currEntries.first, currEntries.second + 1);
152  }
153  }
154 
155  // Finally, check if we're actually done with everything
156  // Well, using EventMetaData::setEndOfData() is not perfect since it will also skip the current events..
157  // So we have to process one more event and set flag m_processedLastEvent (but path will be ended)
158  if (nextEntries.first >= numEntries.first || nextEntries.second >= numEntries.second) {
159  // Let's make this a warning since the EventProcessor also drops a warning that processing is stopped
160  // but of course this behavior is expected in our case :)
161  B2INFO("Reached end of file(s), so we're done. End processing.");
162  m_processedLastEvent = true;
163  // we need to set them to a valid number (doesn't matter what exactly it is)
164  nextEntries = currEntries;
165  }
166 
167  // set the events to be processed next
168  InputController::setNextEntry(nextEntries.first, false);
169  InputController::setNextEntry(nextEntries.second, true);
170  // and set the return value (should this combination of events be further processed)
171  setReturnValue(goodMerge);
172 }
void setNumberEventsOverride(unsigned int nevents)
Override the number of events in run 1 for EventInfoSetter module.
Definition: Environment.h:63
static Environment & Instance()
Static method to get a reference to the Environment instance.
Definition: Environment.cc:28
static long getNextRun()
Return run number set via setNextEntry().
static long getSkippedEntries(bool independentPath=false)
returns the number of entries skipped by the RootInputModule.
static void setNextEntry(long entry, bool independentPath=false)
Set the file entry to be loaded the next time event() is called.
static long getNextExperiment()
Return experiment number set via setNextEntry().
static long getCurrentEntry(bool independentPath=false)
returns the entry number currently loaded.
static long numEntries(bool independentPath=false)
Returns total number of entries in the event tree.
static long getNextEntry(bool independentPath=false)
Return entry number set via setNextEntry().
static void enableEventMerging(Module *steerRootInputModule)
Set that we are merging events from two paths.
static long getNextEvent()
Return event number set via setNextEntry().
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 setReturnValue(int value)
Sets the return value for this module as integer.
Definition: Module.cc:220
StoreObjPtr< EventMetaData > m_eventMetaData_main
We want to use the EventMetaData for some basic checks.
bool m_processedLastEvent
set if current event is the last one to be processed
StoreObjPtr< MergedEventConsistency > m_mergedEventConsistency
Check if charge of both events is consistent (otherwise skip)
virtual void initialize() override
Initialize the Module.
bool m_eventMixing
do event mixing (merge each event of main path with each event of independent path)
virtual void event() override
This method is the core of the module.
void init(bool eventMixing, bool mergeSameFile)
setter for Path.
StoreObjPtr< EventMetaData > m_eventMetaData_indep
We want to use the EventMetaData for some basic checks.
bool m_mergeSameFile
if you want to merge a file with itself, mixing evts (1,3) is the same as (3,1)
REG_MODULE(arichBtest)
Register the Module.
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
Abstract base class for different kinds of events.