 |
Belle II Software
release-05-02-19
|
11 #include <boost/python/register_ptr_to_python.hpp>
12 #include <boost/python/class.hpp>
13 #include <boost/python/list.hpp>
14 #include <boost/python/dict.hpp>
15 #include <boost/python/copy_const_reference.hpp>
16 #include <boost/python/overloads.hpp>
17 #include <boost/python/enum.hpp>
18 #include <boost/python/docstring_options.hpp>
21 #include <framework/core/Module.h>
22 #include <framework/core/ModuleCondition.h>
23 #include <framework/core/PyModule.h>
24 #include <framework/core/ModuleManager.h>
25 #include <framework/core/Path.h>
27 #include <framework/logging/Logger.h>
30 using namespace boost::python;
35 m_description(
"Not set by the author"),
38 m_hasReturnValue(false),
46 B2FATAL(
"Module type not set for " <<
getName());
53 B2FATAL(
"Trying to change module type from " <<
m_type <<
" is not allowed, the value is assumed to be fixed.");
83 m_conditions.emplace_back(expression, path, afterConditionPath);
89 if_value(
"<1", path, afterConditionPath);
94 if_value(
">=1", path, afterConditionPath);
104 B2FATAL(
"A condition was set for '" <<
getName() <<
"', but the module did not set a return value!");
122 B2FATAL(
"A condition was set for '" <<
getName() <<
"', but the module did not set a return value!");
127 return condition.getPath();
141 B2FATAL(
"A condition was set for '" <<
getName() <<
"', but the module did not set a return value!");
146 return condition.getAfterConditionPath();
154 std::vector<std::shared_ptr<Path>> allConditionPaths;
156 allConditionPaths.push_back(condition.getPath());
159 return allConditionPaths;
171 std::string allMissing =
"";
172 for (
const auto& s : missing)
173 allMissing += s +
" ";
174 if (!missing.empty())
175 B2ERROR(
"The following required parameters of Module '" <<
getName() <<
"' were not specified: " << allMissing <<
176 "\nPlease add them to your steering file.");
177 return !missing.empty();
184 newModule->m_moduleParamList.setParameters(
getParamList());
197 std::string output =
getName();
200 output += condition.getString();
242 }
catch (std::runtime_error& e) {
243 throw std::runtime_error(
"Cannot set parameter '" + name +
"' for module '"
244 +
m_name +
"': " + e.what());
257 boost::python::list dictKeys = dictionary.keys();
258 int nKey = boost::python::len(dictKeys);
261 for (
int iKey = 0; iKey < nKey; ++iKey) {
262 boost::python::object currKey = dictKeys[iKey];
263 boost::python::extract<std::string> keyProxy(currKey);
265 if (keyProxy.check()) {
266 const boost::python::object& currValue = dictionary[currKey];
269 B2ERROR(
"Setting the module parameters from a python dictionary: invalid key in dictionary!");
288 boost::python::list _getParamInfoListPython(
const Module* m)
290 return *(m->getParamInfoListPython().get());
292 boost::python::list _getAllConditionPathsPython(
const Module* m)
294 boost::python::list allConditionPaths;
295 for (
const auto& conditionPath : m->getAllConditionPaths()) {
296 allConditionPaths.append(boost::python::object(conditionPath));
299 return allConditionPaths;
301 boost::python::list _getAllConditionsPython(
const Module* m)
303 boost::python::list allConditions;
304 for (
const auto& condition : m->getAllConditions()) {
305 allConditions.append(boost::python::object(boost::ref(condition)));
308 return allConditions;
312 #if !defined(__GNUG__) || defined(__ICC)
314 #pragma GCC diagnostic push
315 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
318 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(if_value_overloads, if_value, 2, 3)
319 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(if_false_overloads, if_false, 1, 2)
320 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(if_true_overloads, if_true, 1, 2)
321 #if !defined(__GNUG__) || defined(__ICC)
323 #pragma GCC diagnostic pop
330 namespace bp = boost::python;
332 docstring_options options(
true,
true,
false);
336 enum_<Module::EAfterConditionPath>(
"AfterConditionPath",
337 R
"(Determines execution behaviour after a conditional path has been executed:
341 End processing of this path after the conditional path. (this is the default for if_value() etc.)
343 .. attribute:: CONTINUE
345 After the conditional path, resume execution after this module.)")
351 enum_<Belle2::ModuleCondition::EConditionOperators>(
"ConditionOperator")
352 .value(
">", Belle2::ModuleCondition::EConditionOperators::c_GT)
353 .value(
"<", Belle2::ModuleCondition::EConditionOperators::c_ST)
354 .value(
">=", Belle2::ModuleCondition::EConditionOperators::c_GE)
355 .value(
"<=", Belle2::ModuleCondition::EConditionOperators::c_SE)
356 .value(
"==", Belle2::ModuleCondition::EConditionOperators::c_EQ)
357 .value(
"!=", Belle2::ModuleCondition::EConditionOperators::c_NE)
360 enum_<Module::EModulePropFlags>(
"ModulePropFlags",
361 R
"(Flags to indicate certain low-level features of modules, see :func:`Module.set_property_flags()`, :func:`Module.has_properties()`. Most useful flags are:
363 .. attribute:: PARALLELPROCESSINGCERTIFIED
365 This module can be run in parallel processing mode safely (All I/O must be done through the data store, in particular, the module must not write any files.)
367 .. attribute:: HISTOGRAMMANAGER
369 This module is used to manage histograms accumulated by other modules
371 .. attribute:: TERMINATEINALLPROCESSES
373 When using parallel processing, call this module's terminate() function in all processes. This will also ensure that there is exactly one process (single-core if no parallel modules found) or at least one input, one main and one output process.
375 .value("INPUT", Module::EModulePropFlags::c_Input)
376 .value(
"OUTPUT", Module::EModulePropFlags::c_Output)
377 .value(
"PARALLELPROCESSINGCERTIFIED", Module::EModulePropFlags::c_ParallelProcessingCertified)
378 .value(
"HISTOGRAMMANAGER", Module::EModulePropFlags::c_HistogramManager)
379 .value(
"INTERNALSERIALIZER", Module::EModulePropFlags::c_InternalSerializer)
380 .value(
"TERMINATEINALLPROCESSES", Module::EModulePropFlags::c_TerminateInAllProcesses)
384 class_<Module, PyModule> module(
"Module", R
"(
385 Base class for Modules.
387 A module is the smallest building block of the framework.
388 A typical event processing chain consists of a Path containing
389 modules. By inheriting from this base class, various types of
390 modules can be created. To use a module, please refer to
391 :func:`Path.add_module()`. A list of modules is available by running
392 ``basf2 -m`` or ``basf2 -m package``, detailed information on parameters is
393 given by e.g. ``basf2 -m RootInput``.
395 The 'Module Development' section in the manual provides detailed information
396 on how to create modules, setting parameters, or using return values/conditions:
397 https://confluence.desy.de/display/BI/Software+Basf2manual#Module_Development
402 .def(
"name", &
Module::getName, return_value_policy<copy_const_reference>(),
403 "Returns the name of the module. Can be changed via :func:`set_name() <Module.set_name()>`, use :func:`type() <Module.type()>` for identifying a particular module class.")
404 .def(
"type", &
Module::getType, return_value_policy<copy_const_reference>(),
405 "Returns the type of the module (i.e. class name minus 'Module')")
407 Set custom name, e.g. to distinguish multiple modules of the same type.
409 >>> path.add_module('EventInfoSetter')
410 >>> ro = path.add_module('RootOutput', branchNames=['EventMetaData'])
411 >>> ro.set_name('RootOutput_metadata_only')
413 [EventInfoSetter -> RootOutput_metadata_only]
417 "Returns the description of this module.")
419 "Returns the package this module belongs to.")
420 .def(
"available_params", &_getParamInfoListPython,
421 "Return list of all module parameters as `ModuleParamInfo` instances")
423 R
"DOCSTRING(Allows to check if the module has the given properties out of `ModulePropFlags` set.
425 >>> if module.has_properties(ModulePropFlags.PARALLELPROCESSINGCERTIFIED):
429 properties (int): bitmask of `ModulePropFlags` to check for.
432 "Set module properties in the form of an OR combination of `ModulePropFlags`.");
435 docstring_options subOptions(
true,
false,
false);
439 R
"DOCSTRING(if_value(expression, condition_path, after_condition_path=AfterConditionPath.END)
441 Sets a conditional sub path which will be executed after this
442 module if the return value set in the module passes the given ``expression``.
444 Modules can define a return value (int or bool) using ``setReturnValue()``,
445 which can be used in the steering file to split the Path based on this value, for example
447 >>> module_with_condition.if_value("<1", another_path)
449 In case the return value of the ``module_with_condition`` for a given event is
450 less than 1, the execution will be diverted into ``another_path`` for this event.
452 You could for example set a special return value if an error occurs, and divert
453 the execution into a path containing :b2:mod:`RootOutput` if it is found;
454 saving only the data producing/produced by the error.
456 After a conditional path has executed, basf2 will by default stop processing
457 the path for this event. This behaviour can be changed by setting the
458 ``after_condition_path`` argument.
461 expression (str): Expression to determine if the conditional path should be executed.
462 This should be one of the comparison operators ``<``, ``>``, ``<=``,
463 ``>=``, ``==``, or ``!=`` followed by a numerical value for the return value
464 condition_path (Path): path to execute in case the expression is fulfilled
465 after_condition_path (AfterConditionPath): What to do once the ``condition_path`` has been executed.
469 R
"DOC(if_false(condition_path, after_condition_path=AfterConditionPath.END)
471 Sets a conditional sub path which will be executed after this module if
472 the return value of the module evaluates to False. This is equivalent to
473 calling `if_value` with ``expression=\"<1\"``)DOC")
476 R
"DOC(if_true(condition_path, after_condition_path=AfterConditionPath.END)
478 Sets a conditional sub path which will be executed after this module if
479 the return value of the module evaluates to True. It is equivalent to
480 calling `if_value` with ``expression=\">=1\"``)DOC");
484 "Return true if a conditional path has been set for this module "
485 "using `if_value`, `if_true` or `if_false`")
486 .def(
"get_all_condition_paths", &_getAllConditionPathsPython,
487 "Return a list of all conditional paths set for this module using "
488 "`if_value`, `if_true` or `if_false`")
489 .def(
"get_all_conditions", &_getAllConditionsPython,
490 "Return a list of all conditional path expressions set for this module using "
491 "`if_value`, `if_true` or `if_false`")
492 .add_property(
"logging", make_function(&
Module::getLogConfig, return_value_policy<reference_existing_object>()),
494 .def(
"return_value", setReturnValueInt, bp::arg(
"value"), \
495 "Set a return value. Can be used by custom modules to set the return value "
496 "used to determine if conditional paths are executed")
498 "Set the log level for this module. Messages below that level will be suppressed\n\n"
499 "Parameters:\n log_level (LogLevel): Minimum level for messages to be displayed")
501 "Set the debug level for this module. Debug messages with a higher level will "
502 "be suppressed. This function has no visible effect if the log level is "
503 "not set to `DEBUG <LogLevel.DEBUG>`\n\n"
504 "Parameters:\n debug_level (int): Maximum debug level for messages to be displayed.")
506 "Set the log level which will cause processing to be aborted. Usually "
507 "processing is only aborted for `FATAL <LogLevel.FATAL>` messages "
508 "but with this function it's possible to set this to a lower value\n\n"
509 "Parameters:\n abort_level (LogLevel): log level which will cause processing to be aborted.")
511 "Set a `LogInfo` configuration object for this module to determine how log messages should be formatted")
514 "This function is called by the processing just once before processing any data "
515 "is processed. Modules can override this method to perform some actions at "
516 "startup once all parameters are set")
518 "This function is called by the processing just before a new run of data "
519 "is processed. Modules can override this method to perform actions which "
522 "This function is called by the processing once for each event."
523 "Modules should override this method to perform actions during event processing")
525 "This function is called by the processing just after a new run of data "
526 "is processed. Modules can override this method to perform actions which "
529 "This function is called by the processing once after all data "
530 "is processed. Modules can override this method to perform some cleanup at "
531 "shutdown. The terminate functions of all modules are called in reverse "
532 "order of the `initialize` calls.")
537 docstring_options param_options(
true,
false,
false);
541 This method can be used to set module parameters. There are two ways of
542 calling this function:
544 1. With two arguments where the first is the name of the parameter and the second is the value.
546 >>> module.param("parameterName", "parameterValue")
548 2. Or with just one parameter which is a dictionary mapping multiple parameter names to their values
550 >>> module.param({"parameter1": "value1", "parameter2": True})
555 register_ptr_to_python<ModulePtr>();
563 m_package(std::move(package))
Module::EAfterConditionPath getAfterConditionPath() const
What to do after the conditional path is finished.
std::shared_ptr< Path > getConditionPath() const
Returns the path of the last true condition (if there is at least one, else reaturn a null pointer).
void if_false(const std::shared_ptr< Path > &path, EAfterConditionPath afterConditionPath=EAfterConditionPath::c_End)
A simplified version to add a condition to the module.
void setLogLevel(int logLevel)
Configure the log level.
void setParamPython(const std::string &name, const boost::python::object &pyObj)
Implements a method for setting boost::python objects.
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.
void if_true(const std::shared_ptr< Path > &path, EAfterConditionPath afterConditionPath=EAfterConditionPath::c_End)
A simplified version to set the condition of the module.
void setDescription(const std::string &description)
Sets the description of the module.
static ModuleManager & Instance()
Exception is thrown if the requested module could not be created by the ModuleManager.
std::shared_ptr< boost::python::list > getParamInfoListPython() const
Returns a python list of all parameters.
int m_returnValue
The return value.
bool hasCondition() const
Returns true if at least one condition was set for the module.
LogConfig m_logConfig
The log system configuration of the module.
void setLogLevel(ELogLevel logLevel)
Configure the log level.
virtual void def_initialize()
Wrappers to make the methods without "def_" prefix callable from Python.
@ c_End
End current event after the conditional path.
std::string m_package
Package this module is found in (may be empty).
static void exposePythonAPI()
Exposes methods of the Module class to Python.
const std::string & getType() const
Returns the type of the module (i.e.
void setAbortLevel(ELogLevel abortLevel)
Configure the abort level.
ModuleProxyBase(std::string moduleType, std::string package)
The constructor of the ModuleProxyBase class.
ELogLevel
Definition of the supported log levels.
void if_value(const std::string &expression, const std::shared_ptr< Path > &path, EAfterConditionPath afterConditionPath=EAfterConditionPath::c_End)
Add a condition to the module.
void registerModuleProxy(ModuleProxyBase *moduleProxy)
Registers a module proxy.
const std::string & getPackage() const
Returns the package this module is in.
void setAbortLevel(int abortLevel)
Configure the abort log level.
void setDebugLevel(int debugLevel)
Configure the debug messaging level.
bool hasUnsetForcedParams() const
Returns true and prints error message if the module has unset parameters which the user has to set in...
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
const std::string & getDescription() const
Returns the description of the module.
std::shared_ptr< PathElement > clone() const override
Create an independent copy of this module.
std::vector< std::string > getUnsetForcedParams() const
Returns list of unset parameters (if they are required to have a value.
@ c_Continue
After the conditional path, resume execution after this module.
Abstract base class for different kinds of events.
Class for logging debug, info and error messages.
void setType(const std::string &type)
Set the module type.
std::shared_ptr< Path > PathPtr
Defines a pointer to a path object as a boost shared pointer.
bool m_hasReturnValue
True, if the return value is set.
std::shared_ptr< Module > ModulePtr
Defines a pointer to a module object as a boost shared pointer.
ModuleParamList m_moduleParamList
List storing and managing all parameter of the module.
std::string m_name
The name of the module, saved as a string (user-modifiable)
void setReturnValue(int value)
Sets the return value for this module as integer.
void updateModule(const LogConfig *moduleLogConfig=nullptr, const std::string &moduleName="")
Sets the log configuration to the given module log configuration and sets the module name This method...
virtual void def_endRun()
This method can receive that the current run ends as a call from the Python side.
std::string m_type
The type of the module, saved as a string.
void setLogInfo(int logLevel, unsigned int logInfo)
Configure the printed log information for the given level.
std::vector< ModuleCondition > m_conditions
Module condition, only non-null if set.
void setParamPython(const std::string &name, const PythonObject &pyObj)
Implements a method for setting boost::python objects.
static LogSystem & Instance()
Static method to get a reference to the LogSystem instance.
void setLogInfo(ELogLevel logLevel, unsigned int logInfo)
Configure the printed log information for the given level.
const ModuleParamList & getParamList() const
Return module param list.
EAfterConditionPath
Different options for behaviour after a conditional path was executed.
virtual void def_terminate()
Wrapper method for the virtual function terminate() that has the implementation to be used in a call ...
virtual void def_beginRun()
Wrapper method for the virtual function beginRun() that has the implementation to be used in a call f...
unsigned int m_propertyFlags
The properties of the module as bitwise or (with |) of EModulePropFlags.
virtual void def_event()
Wrapper method for the virtual function event() that has the implementation to be used in a call from...
std::string m_description
The description of the module.
const std::string & getName() const
Returns the name of the module.
void setName(const std::string &name)
Set the name of the module.
LogConfig & getLogConfig()
Returns the log system configuration.
bool evalCondition() const
If at least one condition was set, it is evaluated and true returned if at least one condition return...
std::shared_ptr< boost::python::list > getParamInfoListPython() const
Returns a python list of all parameters.
void setParamPythonDict(const boost::python::dict &dictionary)
Implements a method for reading the parameter values from a boost::python dictionary.
std::string getPathString() const override
return the module name.
std::vector< std::shared_ptr< Path > > getAllConditionPaths() const
Return all condition paths currently set (no matter if the condition is true or not).
void setLogConfig(const LogConfig &logConfig)
Set the log system configuration.
void setDebugLevel(int debugLevel)
Configure the debug messaging level.
bool hasProperties(unsigned int propertyFlags) const
Returns true if all specified property flags are available in this module.