Belle II Software development
B2BIIMdstInputModule.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 <b2bii/modules/B2BIIMdstInput/B2BIIMdstInputModule.h>
10
11#include <framework/core/Environment.h>
12#include <framework/utilities/FileSystem.h>
13#include <framework/database/Configuration.h>
14
15// Belle tables
16#include "belle_legacy/tables/belletdf.h"
17
18// Belle II dataobjects
19#include <framework/utilities/NumberSequence.h>
20
21#include <cstdlib>
22#include <algorithm>
23
24using namespace std;
25using namespace Belle2;
26
27
28/*
29Some code for simple globing from
30http://stackoverflow.com/questions/8401777/simple-glob-in-c-on-unix-system
31In RootInput this is handled by ROOT
32*/
33#include <glob.h>
34#include <vector>
35#include <string>
36vector<string> globbing(const vector<string>& patterns)
37{
38 vector<string> ret;
39 for (const auto& pat : patterns) {
40 glob_t glob_result;
41 glob(pat.c_str(), GLOB_TILDE, NULL, &glob_result);
42 for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) {
43 ret.push_back(string(glob_result.gl_pathv[i]));
44 }
45 globfree(&glob_result);
46 }
47 return ret;
48}
49
50//-----------------------------------------------------------------
51// Register the Module
52//-----------------------------------------------------------------
53REG_MODULE(B2BIIMdstInput);
54
55//-----------------------------------------------------------------
56// Implementation
57//-----------------------------------------------------------------
58
60{
61 //Set module properties
62 setDescription("Module to read Belle MDST files.");
64
65 m_nevt = -1;
68
69 //Parameter definition
70 addParam("inputFileName", m_inputFileName, "Belle MDST input file name. "
71 "For more than one file use inputFileNames", std::string(""));
72 addParam("inputFileNames", m_inputFileNames, "Belle MDST input file names.",
74
75 std::vector<std::string> emptyvector;
76 addParam("entrySequences", m_entrySequences,
77 "The number sequences (e.g. 23:42,101) defining the entries which are processed for each inputFileName."
78 "Must be specified exactly once for each file to be opened."
79 "The first event has the number 0.", emptyvector);
80 addParam("evtgenProcessing", m_evtgenProcessing, "Flag to switch on only evtgen processing", false);
81}
82
83
87
88std::vector<std::string> B2BIIMdstInputModule::getInputFiles() const
89{
90 std::vector<std::string> inputFiles = Environment::Instance().getInputFilesOverride();
91 if (!inputFiles.empty()) {
92 return inputFiles;
93 }
94 inputFiles = m_inputFileNames;
95 if (!m_inputFileName.empty())
96 inputFiles.push_back(m_inputFileName);
97 return inputFiles;
98}
99
101{
102 m_inputFileNames = globbing(getInputFiles());
103
104 auto entrySequencesOverride = Environment::Instance().getEntrySequencesOverride();
105 if (entrySequencesOverride.size() > 0)
106 m_entrySequences = entrySequencesOverride;
107
108 //Check if there is at least one filename provided
109 if (m_inputFileNames.empty()) {
110 B2FATAL("Empty list of files supplied, cannot continue");
111 }
112
113 if (m_entrySequences.size() > 0 and m_inputFileNames.size() != m_entrySequences.size()) {
114 B2FATAL("Number of provided filenames does not match the number of given entrySequences parameters: len(inputFileNames) = "
115 << m_inputFileNames.size() << " len(entrySequences) = " << m_entrySequences.size());
116 }
117
118 //Ok we have files. Since vectors can only remove efficiently from the back
119 //we reverse the order and read the files from back to front.
120 std::reverse(m_inputFileNames.begin(), m_inputFileNames.end());
121
122 // check environment
123 const char* table_dir = getenv("PANTHER_TABLE_DIR");
124 if (!table_dir or !FileSystem::isDir(table_dir)) {
125 string fixed_table_dir = Environment::Instance().getExternalsPath() + "/share/belle_legacy/panther";
126 B2WARNING("PANTHER_TABLE_DIR environment variable not set correctly. This is a known problem with externals v00-05-09, using " <<
127 fixed_table_dir << " instead.");
128 if (!FileSystem::isDir(fixed_table_dir))
129 B2FATAL("Path " << fixed_table_dir << " does not exist, your externals setup seems broken.");
130 setenv("PANTHER_TABLE_DIR", fixed_table_dir.c_str(), 1); //overwrite existing value
131 }
132
133
134 // Initialize Panther
135 BsInit(0);
136
137 // Initialize Belle II DataStore
139
140 // open the first file
141 openNextFile();
142
143 // Also, make sure we register a filemetadata object. We don't have most information
144 // to go into it but we need it for real/MC flag
145 m_fileMetadata.registerInDataStore();
146}
147
149{
150 B2DEBUG(99, "[B2BIIMdstInputModule::initializeDataStore] initialization of DataStore started");
151
152 m_evtMetaData.registerInDataStore();
153
154 B2DEBUG(99, "[B2BIIMdstInputModule::initializeDataStore] initialization of DataStore ended");
155}
156
157
159{
160 B2DEBUG(99, "B2BIIMdstInput: beginRun called.");
161}
162
164{
165 // delete existing FileIO
166 BsClrTab(BBS_CLEAR_ALL);
167 delete m_fd;
168 m_fd = nullptr;
169
170 // check if we have more files to read
171 if (m_inputFileNames.empty()) return false;
172 // if so, get the last one from the list and remove it.
173 const std::string name = m_inputFileNames.back();
174 m_inputFileNames.pop_back();
175
176 // Open data file
177 m_fd = new Belle::Panther_FileIO(name.c_str(), BBS_READ);
178
179 // Read first record (does not contain event data)
180 if (m_fd->read() == -1) {
181 B2FATAL("Couldn't read file '" << name << "'!");
182 }
183 m_nevt++;
186
187 if (m_entrySequences.size() > 0)
188 // exclude ":" since this case is not considered in generate_number_sequence
191 }
192 return true;
193}
194
196{
197
198 do {
200 // read event
201 int rectype = -1;
202 while (rectype < 0 && rectype != -2) {
203 //clear all previous event data before reading!
204 BsClrTab(BBS_CLEAR);
205 rectype = m_fd->read();
206 if (rectype == -1) {
207 B2ERROR("Error while reading panther tables! Record skipped.");
208 }
209 }
210 if (rectype == -2) { // EoF detected
211 B2DEBUG(99, "[B2BIIMdstInputModule::Conversion] Conversion stopped at event #" << m_nevt << ". EOF detected!");
212 return false;
213 }
214
215 } while (m_entrySequences.size() > 0
218
219 return true;
220}
221
223{
224 m_nevt++;
225
226 // Fill EventMetaData
227 StoreObjPtr<EventMetaData> evtmetadata;
228
229 // Read next event: We try to read the next event from the current file
230 // if this fails, open the next file and try again
231 // if we cannot open the next file then stop processing
232 while (!readNextEvent()) {
233 if (!openNextFile()) {
234 B2DEBUG(99, "[B2BIIMdstInputModule::Conversion] Conversion stopped at event #" << m_nevt << ". No more files");
235 return;
236 }
237 }
238 evtmetadata.create();
239
240 // Convert the Belle_event -> EventMetaData
241 // Get Belle_event_Manager
242 Belle::Belle_event_Manager& evman = Belle::Belle_event_Manager::get_manager();
243 if (evman.count() == 0) {
244 if (m_evtgenProcessing) {
245 if (!m_fileMetadata) {
246 m_fileMetadata.create();
248 } else {
249 // Make sure we don't process real data and MC in the same process
250 if (m_fileMetadata->isMC() == false) {
251 B2FATAL("Information whether we process real or simulated data has changed. Refusing to continue");
252 }
253 }
254 return;
255 } else {
256 B2FATAL("No event found in the event manager, the input mdst file might be corrupted. "
257 "If you are running on evtgen's output, please set the evtgenProcessing flag to true.");
258 }
259 }
260
261 Belle::Belle_event& evt = evman[0];
262
263 // Check if RUNHEAD is available if not create one using the event.
264 // Basf did something similar in Record::convert_to_begin_run.
265 // Some files are missing the RUNHEAD for unknown reasons.
266 Belle::Belle_runhead_Manager& rhdmgr = Belle::Belle_runhead_Manager::get_manager();
267 Belle::Belle_runhead_Manager::const_iterator belleevt = rhdmgr.begin();
268
269 B2DEBUG(90, "Event number " << m_nevt);
270 if (belleevt == rhdmgr.end() || not(*belleevt)) {
271 B2WARNING("Missing RUNHEAD: Creating RUNHEAD from Event. This is as far as we know fine and handled correctly.");
272
273 Belle::Belle_runhead& bgr = rhdmgr.add();
274 bgr.ExpMC(evt.ExpMC());
275 bgr.ExpNo(evt.ExpNo());
276 bgr.RunNo(evt.RunNo());
277 bgr.Time(evt.Time());
278 bgr.Date(evt.Date());
279 bgr.Field(evt.MagFieldID());
280 bgr.MaxField(evt.BField());
281 bgr.Type(0); // basf used 0, and the debug output below of valid entries returned 0 as well
282 bgr.ELER(evt.ELER());
283 bgr.EHER(evt.EHER());
284
285 // In basf the BELLE_RUNHEAD which is created like this is not cleared anymore
286 // m_fd->non_clear("BELLE_RUNHEAD");
287 // However, I think in this case we are going to miss reinitializing the BELLE_RUNHEAD
288 // at the beginning of a new run without a BELLE_RUNHEAD, I'm not sure how this was handled
289 // in basf. I think it is safest to recreate the BELLE_RUNHEAD for each event which is missing
290 // the BELLE_RUNHEAD
291
292 } else {
293 Belle::Belle_runhead& bgr = rhdmgr[0];
294 B2DEBUG(90, "ExpMC " << bgr.ExpMC() << " " << evt.ExpMC());
295 B2DEBUG(90, "ExpNo " << bgr.ExpNo() << " " << evt.ExpNo());
296 B2DEBUG(90, "RunNo " << bgr.RunNo() << " " << evt.RunNo());
297 B2DEBUG(90, "Time " << bgr.Time() << " " << evt.Time());
298 B2DEBUG(90, "Date " << bgr.Date() << " " << evt.Date());
299 B2DEBUG(90, "Field " << bgr.Field() << " " << evt.MagFieldID());
300 B2DEBUG(90, "MaxField " << bgr.MaxField() << " " << evt.BField());
301 B2DEBUG(90, "Type " << bgr.Type());
302 B2DEBUG(90, "ELER " << bgr.ELER() << " " << evt.ELER());
303 B2DEBUG(90, "EHER " << bgr.EHER() << " " << evt.EHER());
304 }
305
306 // set exp/run/evt numbers
307 evtmetadata->setExperiment(evt.ExpNo());
308 evtmetadata->setRun(evt.RunNo());
309 evtmetadata->setEvent(evt.EvtNo() & 0x0fffffff);
310
311 // set generated weight (>0 for MC; <0 for real DATA)
312 bool realData = evt.ExpMC() != 2;
313 evtmetadata->setGeneratedWeight(realData ? -1.0 : 1.0);
314
315 // no file metadata yet? apparently first event, make sure the real/MC data flag is correct
316 if (!m_fileMetadata) {
317 m_fileMetadata.create();
318 if (realData) m_fileMetadata->declareRealData();
319 // this happens for the first event so now is a good time to tell the framework
320 // which globaltags we want to use ...
321 std::string tag = realData ? "B2BII" : "B2BII_MC";
323 } else {
324 // Make sure we don't process real data and MC in the same process
325 if (realData == m_fileMetadata->isMC()) {
326 B2FATAL("Information whether we process real or simulated data has changed. Refusing to continue");
327 }
328 }
329
330 B2DEBUG(90, "[B2BIIMdstInputModule] Convert exp/run/evt: " << evt.ExpNo() << "/" << evt.RunNo() << "/" << int(
331 evt.EvtNo() & 0x0fffffff));
332}
333
335{
336 B2INFO("B2BIIMdstInput: endRun done.");
337}
338
339
341{
342 delete m_fd;
343 B2INFO("B2BIIMdstInput: terminate called");
344}
int m_nevt
Global event counter.
virtual ~B2BIIMdstInputModule() override
Destructor.
int m_current_file_entry
Entry counter in current file.
bool readNextEvent()
Read the next event from the currently open file.
virtual void initialize() override
Initialize the module.
virtual void event() override
Called for each event.
virtual void endRun() override
Called when the current run finished.
virtual void terminate() override
Terminates the module.
std::string m_inputFileName
Input MDST file name for backwards compatibility.
Belle::Panther_FileIO * m_fd
PantherFile.
std::vector< std::string > m_inputFileNames
List of input MDST filenames.
bool openNextFile()
Open the next file from the list of files.
StoreObjPtr< EventMetaData > m_evtMetaData
event meta data Object pointer
virtual void beginRun() override
Called when a new run is started.
std::set< int64_t > m_valid_entries_in_current_file
Entries numbers which are valid for the current file.
void initializeDataStore()
Initializes Belle II DataStore.
bool m_evtgenProcessing
Flag to switch on only evtgen processing.
StoreObjPtr< FileMetaData > m_fileMetadata
File metadata to declare if we process real data or simulated data.
std::vector< std::string > getInputFiles() const
Get list of input files, taking -i command line overrides into account.
std::vector< std::string > m_entrySequences
The number sequences (e.g.
static Configuration & getInstance()
Get a reference to the instance which will be used when the Database is initialized.
void setInputGlobaltags(const std::vector< std::string > &inputTags)
To be called by input modules with the tags to be added from input files.
std::vector< std::string > getEntrySequencesOverride() const
Returns the number sequences (e.g.
Definition Environment.h:74
const std::vector< std::string > & getInputFilesOverride() const
Return overridden input file names, or empty vector if none were set.
const std::string & getExternalsPath() const
Returns the path which points to the externals directory of the framework.
Definition Environment.h:62
static Environment & Instance()
Static method to get a reference to the Environment instance.
static bool isDir(const std::string &filename)
Check if filename points to an existing directory.
Definition FileSystem.cc:51
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
Module()
Constructor.
Definition Module.cc:30
@ c_Input
This module is an input module (reads data).
Definition Module.h:78
bool create(bool replace=false)
Create a default object in the data store.
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
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:559
std::set< int64_t > generate_number_sequence(const std::string &str)
Generate a sequence of numbers defined by a string.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
Abstract base class for different kinds of events.
STL namespace.