Belle II Software development
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
15using 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
19REG_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
33SteerRootInputModule::~SteerRootInputModule() = default;
34
35void 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)
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.");
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:64
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)
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
Abstract base class for different kinds of events.