9#include <framework/pybasf2/Framework.h>
11#include <framework/core/PyObjConvUtils.h>
12#include <framework/core/Environment.h>
13#include <framework/core/RandomNumbers.h>
14#include <framework/core/EventProcessor.h>
15#include <framework/core/ModuleManager.h>
16#include <framework/datastore/DataStore.h>
17#include <framework/database/DBStore.h>
18#include <framework/database/Database.h>
19#include <framework/pcore/pEventProcessor.h>
20#include <framework/pcore/ZMQEventProcessor.h>
21#include <framework/pcore/zmq/utils/ZMQAddressUtils.h>
22#include <framework/utilities/FileSystem.h>
23#include <framework/database/Configuration.h>
25#include <framework/logging/Logger.h>
26#include <framework/logging/LogSystem.h>
28#include <boost/algorithm/string.hpp>
29#include <boost/algorithm/string/join.hpp>
30#include <boost/python.hpp>
35using namespace boost::python;
95 static bool already_executed =
false;
96 static std::set<const Module*> previously_run_modules;
97 static int errors_from_previous_run = 0;
99 if (already_executed) {
100 B2WARNING(
"Calling process() more than once per steering file is still experimental, please check results carefully! Python modules especially should reinitialise their state in initialise() to avoid problems");
102 B2FATAL(
"Your path contains the same module instance in multiple places. Calling process() multiple times is not implemented for this case.");
106 for (
const auto& m : moduleListUnique) {
107 if (previously_run_modules.count(m.get()) > 0) {
109 startPath = std::static_pointer_cast<Path>(startPath->
clone());
114 for (
const auto& m : moduleListUnique) {
115 previously_run_modules.insert(m.get());
119 if (numLogError != errors_from_previous_run) {
120 B2FATAL(numLogError <<
" ERROR(S) occurred! The processing of events will not be started.");
130 already_executed =
true;
131 if (environment.getNumberProcesses() == 0) {
134 processor.
process(startPath, maxEvent);
136 if (environment.getUseZMQ()) {
138 if (environment.getZMQSocketAddress().empty()) {
142 processor.
process(startPath, maxEvent);
145 processor.
process(startPath, maxEvent);
155 }
catch (std::exception& e) {
156 B2ERROR(
"Uncaught exception encountered: " << e.what());
160 B2ERROR(
"Uncaught exception encountered!");
200 std::vector<std::string> realms;
203 realms.push_back(thisRealm);
204 if (boost::iequals(realm, thisRealm)) {
210 B2ERROR(
"Invalid realm! Needs to be one of " << boost::join(realms,
", "));
233 B2WARNING(
"basf2 will write the simulation steps of each event into output csv files. "
234 "This is fine if you are producing events for the Belle II Virtual Reality application, "
235 "otherwise this function should not be used since the execution time will significantly increase.");
248 if (!ignore_errors and result.empty()) {
253 PyErr_SetFromErrnoWithFilename(PyExc_FileNotFoundError, filename.c_str());
254 boost::python::throw_error_already_set();
265 boost::python::list returnList;
268 returnList.append(boost::python::object(path));
275 boost::python::dict returnDict;
277 returnDict[boost::python::object(modulePair.first)] = boost::python::object(modulePair.second);
284 boost::python::list returnList;
287 returnList.append(boost::python::object(mod));
292#if !defined(__GNUG__) || defined(__ICC)
294#pragma GCC diagnostic push
295#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
299#if !defined(__GNUG__) || defined(__ICC)
301#pragma GCC diagnostic pop
305 PyObject* PyExc_ModuleNotCreatedError{
nullptr};
308 void moduleNotCreatedTranslator(
const ModuleManager::ModuleNotCreatedError& e)
310 PyErr_SetString(PyExc_ModuleNotCreatedError, e.what());
316 PyExc_ModuleNotCreatedError = PyErr_NewExceptionWithDoc(
"basf2.ModuleNotCreatedError",
317 "This exception is raised when a basf2 module could not be created for any reason",
318 PyExc_RuntimeError,
nullptr);
319 scope().attr(
"ModuleNotCreatedError") = handle<>(borrowed(PyExc_ModuleNotCreatedError));
320 register_exception_translator<ModuleManager::ModuleNotCreatedError>(moduleNotCreatedTranslator);
326 docstring_options options(
true,
true,
false);
329 class_<Framework, std::shared_ptr<Framework>, boost::noncopyable>(
"Framework",
"Initialize and Cleanup functions", no_init);
330 std::shared_ptr<Framework> initguard{
new Framework()};
331 scope().attr(
"__framework") = initguard;
334Add a directory in which to search for compiled basf2 C++ `Modules <Module>`.
336This directory needs to contain the shared libraries containing the compiled
337modules as well as companion files ending in ``.b2modmap`` which contain a list
338of the module names contained in each library.
341 The newly added path will not override existing modules
344 path (str): directory containing the modules.
345)DOCSTRING", args("path"));
347Set the path to the externals to be used.
350 This will not change the library and executable paths but will just change
351 the directory where to look for certain data files like the Evtgen particle
352 definition file. Don't use this unless you really know what you are doing.
355 path (str): new top level directory for the externals
356)DOCSTRING", args("path"));
358Return a python list containing all the directories included in the module
362 `add_module_search_path`
365Return a dictionary containing the names of all known modules
366as keys and the name of the shared library containing these modules as values.
369Return a list with pointers to all previously created module instances by calling `register_module()`
372Return the filename where the pickled path is or should be stored
375Set the filename where the pickled path should be stored or retrieved from
376)DOCSTRING", args("path"));
378Sets number of worker processes for parallel processing.
380Can be overridden using the ``-p`` argument to basf2.
383 Setting this to 1 will have one parallel worker job which is almost always
384 slower than just running without parallel processing but is still provided to
385 allow debugging of parallel execution.
388 nproc (int): number of worker processes. 0 to disable parallel processing.
391Gets number of worker processes for parallel processing. 0 disables parallel processing
394Set the names of all DataStore objects which should be sent between the
395parallel processes. This can be used to improve parallel processing performance
396by removing objects not required.
401 docstring_options param_options(
true,
false,
false);
402 def(
"_register_module", registerModule1);
403 def(
"_register_module", registerModule2, R
"DOCSTRING(register_module(name, library=None)
404Register a new Module.
406This function will try to create a new instance of a module with the given name. If no library is given it will try to find the module by itself from the module search path. Optionally one can specify the name of a shared library containing the module code then this library will be loaded
409 `list_module_search_paths()`, `add_module_search_path()`
412 name (str): Type of the module to create
413 library (str): Optional, name of a shared library containing the module
416 An instance of the module if successful.
419 will raise a `ModuleNotCreatedError` if there is any problem creating the module.
422Set the basf2 execution realm.
424The severity of log messages sometimes depends on where basf2 runs. This is controlled by the execution realm.
426Usually the realm does not have to be set explicitly. On the HLT or express reco it should be set to 'online' and for official productions to 'production'.
427)DOCSTRING", args("realm"));
429Set that the run is for cosmics data
432Set that the run is for beam data
435Allow basf2 to write the simulation steps of each event into csv files.
437This function should not be used in production jobs because the execution time will significantly increase.
439 def("_process", &
Framework::process, process_overloads(R
"DOCSTRING(process(path, num_events=0)
440Processes up to max_events events by starting with the first module in the specified path.
442 This method starts processing events only if there is a module in the path
443 which is capable of specifying the end of the data flow.
446 path (Path): The processing starts with the first module of this path.
447 max_events (int): The maximum number of events that will be processed.
448 If the number is smaller than 1, all events will be processed (default).
453 def("find_file", &
Framework::findFile, (arg(
"filename"), arg(
"data_type") =
"", arg(
"silent") =
false), R
"DOC(
454 Try to find a file and return its full path
456 If ``data_type`` is empty this function will try to find the file
458 1. in ``$BELLE2_LOCAL_DIR``,
459 2. in ``$BELLE2_RELEASE_DIR``
460 3. relative to the current working directory.
462 Other known ``data_type`` values are
465 Example data for examples and tutorials. Will try to find the file
467 1. in ``$BELLE2_EXAMPLES_DATA_DIR``
468 2. relative to the current working directory
471 Data for validation purposes. Will try to find the file in
473 1. in ``$BELLE2_VALIDATION_DATA_DIR``
474 2. relative to the current working directory
477 Data for starterkit purposes. Will try to find the file in
479 1. in ``$BELLE2_STARTERKIT_DATA_DIR``
480 2. relative to the current working directory
482 .. versionadded:: release-03-00-00
485 filename (str): relative filename to look for, either in a central place or
486 in the current working directory
487 data_type (str): case insensitive data type to find. Either empty string or
488 one of ``"examples"``, ``"validation"`` or "``starterkit``".
489 silent (bool): If True don't print any errors and just return an empty
490 string if the file cannot be found
static Configuration & getInstance()
Get a reference to the instance which will be used when the Database is initialized.
void reset()
Reset to default values.
ERunType
Enum for identifying run type (beam or cosmic)
static DataStore & Instance()
Instance of singleton Store.
void setInitializeActive(bool active)
Setter for m_initializeActive.
static bool s_DoCleanup
Global flag to to decide if we can do normal cleanup.
void reset(EDurability durability)
Frees memory occupied by data store items and removes all objects from the map.
void setNumberProcesses(int number)
Sets the number of processes which should be used for the parallel processing.
void setRealm(LogConfig::ELogRealm realm)
Set the basf2 execution realm.
void setJobInformation(const std::shared_ptr< Path > &path)
Set info from path executed by the framework.
void setRunType(Const::ERunType runType)
Set the run type (beam or cosmic).
int getNumberProcesses() const
Returns the number of worker processes which should be used for the parallel processing.
void setExternalsPath(const std::string &externalsPath)
Sets the path which points to the externals directory of the framework.
void setStreamingObjects(const std::vector< std::string > &strobjs)
Set list of streaming objects.
void setWriteSimSteps(const bool writeSimSteps)
Set the flag for writing the simulation steps into an output csv file.
const std::string & getPicklePath() const
Returns the path to the file where the pickled path is stored.
static Environment & Instance()
Static method to get a reference to the Environment instance.
void setPicklePath(const std::string &path)
Sets the path to the file where the pickled path is stored.
provides the core event processing loop.
void setProfileModuleName(const std::string &name)
Set the name of the module we want to profile.
void process(const PathPtr &startPath, long maxEvent=0)
Processes the full module chain, starting with the first module in the given path.
static std::string findFile(const std::string &path, bool silent=false)
Search for given file or directory in local or central release directory, and return absolute path if...
static boost::python::list getRegisteredModulesPython()
Returns a list of all registered modules.
static void writeSimulationSteps()
Function for writing the simulation steps of each event into csv files.
static std::string findFile(const std::string &filename, const std::string &type, bool ignore_errors=false)
Find a file.
static void setRunType(const Const::ERunType runType)
Function to set the run type (beam or cosmic)
static void setBeamRun()
Function to set that the script is running on beam data (by default it runs on beam data,...
static boost::python::list getModuleSearchPathsPython()
Returns a list of all module search paths known to the framework.
static void setNumberProcesses(int numProcesses)
Function to set number of worker processes for parallel processing.
static void exposePythonAPI()
Exposes methods of the Framework class to Python.
static void setCosmicRun()
Function to set that the script is running on cosmics data (by default it runs on beam data)
static void setRealm(const std::string &realm)
Function to set the execution realm.
static boost::python::dict getAvailableModulesPython()
Returns a dictionary containing the found modules and the filenames of the shared libraries in which ...
static void setStreamingObjects(const boost::python::list &streamingObjects)
Function to set streaming objects for Tx module.
static std::string getPicklePath()
Function to get the path to the file where the pickled path is stored.
static ModulePtr registerModule(const std::string &moduleName)
Registers a new module to the framework and returns a shared pointer.
static void setPicklePath(const std::string &path)
Function to set the path to the file where the pickled path is stored.
static void setExternalsPath(const std::string &path)
Sets the path in which the externals of the framework are located.
virtual ~Framework()
Destructor.
static int getNumberProcesses()
Function to get number of worker processes for parallel processing.
static void addModuleSearchPath(const std::string &path)
Adds a new filepath to the list of filepaths which are searched for modules.
static void process(PathPtr startPath, long maxEvent=0)
Processes up to maxEvent events by starting with the first module in the specified path.
static const char * logRealmToString(ELogRealm realm)
Converts a log realm type to a string.
@ c_Error
Error: for things that went wrong and have to be fixed.
ELogRealm
Definition of the supported execution realms.
@ c_None
No specific realm.
@ c_Production
Data production jobs.
void resetMessageCounter()
Resets the message counter and error log by setting all message counts to 0.
void enableErrorSummary(bool on)
enable/disable error/warning summary after successful execution and B2FATAL.
int getMessageCounter(LogConfig::ELogLevel logLevel) const
Returns the number of logging calls per log level.
static LogSystem & Instance()
Static method to get a reference to the LogSystem instance.
std::shared_ptr< Module > registerModule(const std::string &moduleName, std::string sharedLibPath="") noexcept(false)
Creates an instance of a module and registers it to the ModuleManager.
static ModuleManager & Instance()
Exception is thrown if the requested module could not be created by the ModuleManager.
void reset()
Delete all created modules.
void addModuleSearchPath(const std::string &path)
Adds a new filepath to the list of filepaths which are searched for a requested module.
std::list< std::shared_ptr< Module > > buildModulePathList(bool unique=true) const
Builds a list of all modules which could be executed during the data processing.
std::shared_ptr< PathElement > clone() const override
Create an independent copy of this path, recreating all contained modules with the same parameters.
static bool isInitialized()
Truth that the random number generator has been initialized.
static void initialize()
Initialize the random number generator with a unique random seed;.
static std::string randomSocketName(const std::string &hostname)
Generate a random socket name in the form tcp://hostname:port.
This class provides the core event processing loop for parallel processing with ZMQ.
void process(const PathPtr &spath, long maxEvent)
Processes the full module chain using parallel processing, starting with the first module in the give...
This class provides the core event processing loop for parallel processing.
void process(const PathPtr &spath, long maxEvent)
Processes the full module chain, starting with the first module in the given path.
void reset(bool keepEntries=false)
Invalidate all payloads.
std::shared_ptr< Path > PathPtr
Defines a pointer to a path object as a boost shared pointer.
static Database & Instance()
Instance of a singleton Database.
static DBStore & Instance()
Instance of a singleton DBStore.
std::shared_ptr< Module > ModulePtr
Defines a pointer to a module object as a boost shared pointer.
static void reset(bool keepConfig=false)
Reset the database instance.
Scalar convertPythonObject(const boost::python::object &pyObject, Scalar)
Convert from Python to given type.
Abstract base class for different kinds of events.