12 The core module of the Belle II Analysis Software Framework.
16 import signal
as _signal
19 if _sys.version_info[0] < 3:
20 print(
"basf2 requires python3. Please run the steering files using basf2 "
21 "(or python3), not python")
25 from basf2
import _override_print
33 from basf2
import _constwrapper
37 basf2label =
'basf2 (Belle II Analysis Software Framework)'
39 basf2copyright =
'Copyright(C) 2010-2021 Members of the Belle II Collaboration'
41 basf2license =
'(See "basf2 --license" for more information.)'
50 _signal.signal(_signal.SIGINT, _signal.SIG_DFL)
53 def register_module(name_or_module, shared_lib_path=None, logLevel=None, debugLevel=None, **kwargs):
55 Register the module 'name' and return it (e.g. for adding to a path). This
56 function is intended to instantiate existing modules. To find out which
57 modules exist you can run :program:`basf2 -m` and to get details about the
58 parameters for each module you can use :program:`basf2 -m {modulename}`
60 Parameters can be passed directly to the module as keyword parameters or can
61 be set later using `Module.param`
63 >>> module = basf2.register_module('EventInfoSetter', evtNumList=100, logLevel=LogLevel.ERROR)
64 >>> module.param("evtNumList", 100)
67 name_or_module: The name of the module type, may also be an existing
68 `Module` instance for which parameters should be set
69 shared_lib_path (str): An optional path to a shared library from which the
70 module should be loaded
71 logLevel (LogLevel): indicates the minimum severity of log messages
72 to be shown from this module. See `Module.set_log_level`
73 debugLevel (int): Number indicating the detail of debug messages, the
74 default level is 100. See `Module.set_debug_level`
75 kwargs: Additional parameters to be passed to the module.
78 You can also use `Path.add_module()` directly,
79 which accepts the same name, logging and module parameter arguments. There
80 is no need to register the module by hand if you will add it to the path in
84 if isinstance(name_or_module, pybasf2.Module):
85 module = name_or_module
87 module_name = name_or_module
88 if shared_lib_path
is not None:
89 module = pybasf2._register_module(module_name, shared_lib_path)
91 module = pybasf2._register_module(module_name)
95 if logLevel
is not None:
96 module.set_log_level(logLevel)
97 if debugLevel
is not None:
98 module.set_debug_level(debugLevel)
103 def set_module_parameters(path, name=None, type=None, recursive=False, **kwargs):
104 """Set the given set of parameters for all `modules <Module>` in a path which
105 have the given ``name`` (see `Module.set_name`)
107 Usage is similar to `register_module()` but this function will not create
108 new modules but just adjust parameters for modules already in a `Path`
110 >>> set_module_parameters(path, "Geometry", components=["PXD"], logLevel=LogLevel.WARNING)
113 path (basf2.Path): The path to search for the modules
114 name (str): Then name of the module to set parameters for
115 type (str): The type of the module to set parameters for.
116 recursive (bool): if True also look in paths connected by conditions or `Path.for_each()`
117 kwargs: Named parameters to be set for the module, see `register_module()`
120 if name
is None and type
is None:
121 raise ValueError(
"At least one of name or type has to be given")
124 raise ValueError(
"no module parameters given")
127 for module
in path.modules():
128 if (name
is None or module.name() == name)
and (type
is None or module.type() == type):
131 register_module(module, **kwargs)
135 if module.has_condition():
136 for condition_path
in module.get_all_condition_paths():
137 set_module_parameters(condition_path, name, type, recursive, **kwargs)
138 if module.type() ==
"SubEvent":
139 for subpath
in [p.values
for p
in module.available_params()
if p.name ==
"path"]:
140 set_module_parameters(subpath, name, type, recursive, **kwargs)
143 raise KeyError(
"No module with given name found anywhere in the path")
146 def remove_module(old_path, name=None):
147 """Provides a new path with all modules that were in the ``old_path`` \
148 except the one with the given ``name`` (see `Module.set_name`)
150 Usage is very simple, in this example we remove Geometry the path:
152 >>> main = remove_module(main, "Geometry")
155 old_path (basf2.Path): The path to search for the module
156 name (str): Then name of the module you want to remove
160 raise ValueError(
"You should provide the module name")
162 new_path = create_path()
164 for module
in old_path.modules():
165 if name != module.name():
166 new_path.add_module(module)
173 Creates a new path and returns it. You can also instantiate `basf2.Path` directly.
175 return pybasf2.Path()
178 def process(path, max_event=0):
180 Start processing events using the modules in the given `basf2.Path` object.
182 Can be called multiple times in one steering file (some restrictions apply:
183 modules need to perform proper cleanup & reinitialisation, if Geometry is
184 involved this might be difficult to achieve.)
186 When used in a Jupyter notebook this function will automatically print a
187 nice progress bar and display the log messages in an advanced way once the
188 processing is complete.
191 This also means that in a Jupyter Notebook, modifications to class members
192 or global variables will not be visible after processing is complete as
193 the processing is performed in a subprocess.
195 To restore the old behavior you can use ``basf2.core.process()`` which
196 will behave exactly identical in Jupyter notebooks as it does in normal
199 from basf2 import core
204 path: The path with which the processing starts
205 max_event: The maximal number of events which will be processed,
208 .. versionchanged:: release-03-00-00
209 automatic Jupyter integration
215 ipython = get_ipython()
216 history =
"\n".join(e[2]
for e
in ipython.history_manager.get_range())
217 from ROOT
import Belle2
223 if pybasf2.get_pickle_path() !=
"":
225 path = check_pickle_path(path)
231 pybasf2.B2INFO(
"Starting event processing, random seed is set to '" + pybasf2.get_random_seed() +
"'")
234 pybasf2._process(path, max_event)
236 pybasf2._process(path)
239 def set_log_level(level):
241 Sets the global log level which specifies up to which level the
242 logging messages will be shown
245 level (basf2.LogLevel): minimum severity of messages to be logged
248 logging.log_level = level
251 def set_debug_level(level):
253 Sets the global debug level which specifies up to which level the
254 debug messages should be shown
257 level (int): The debug level. The default value is 100
260 logging.debug_level = level
263 def log_to_console(color=False):
265 Adds the standard output stream to the list of logging destinations.
266 The shell logging destination is
267 added to the list by the framework by default.
270 logging.add_console(color)
273 def log_to_file(filename, append=False):
275 Adds a text file to the list of logging destinations.
278 filename: The path and filename of the text file
279 append: Should the logging system append the messages to the end of the
280 file (True) or create a new file for each event processing session (False).
284 logging.add_file(filename, append)
289 Resets the logging by removing all logging destinations
295 def _add_module(self, module, logLevel=None, debugLevel=None, **kwargs):
297 Add given module (either object or name) at the end of this path.
298 All unknown arguments are passed as module parameters.
300 >>> path = create_path()
301 >>> path.add_module('EventInfoSetter', evtNumList=100, logLevel=LogLevel.ERROR)
302 <pybasf2.Module at 0x1e356e0>
304 >>> path = create_path()
305 >>> eventinfosetter = register_module('EventInfoSetter')
306 >>> path.add_module(eventinfosetter)
307 <pybasf2.Module at 0x2289de8>
309 module = register_module(module, logLevel=logLevel, debugLevel=debugLevel, **kwargs)
310 self._add_module_object(module)
314 def _add_independent_path(self, skim_path, ds_ID='', merge_back_event=None):
316 Add given path at the end of this path and ensure all modules there
317 do not influence the main DataStore. You can thus use modules in
318 skim_path to clean up e.g. the list of particles, save a skimmed uDST file,
319 and continue working with the unmodified DataStore contents outside of
323 ds_ID: can be specified to give a defined ID to the temporary DataStore,
324 otherwise, a random name will be generated.
325 merge_back_event: is a list of object/array names (of event durability)
326 that will be merged back into the main path.
328 if merge_back_event
is None:
329 merge_back_event = []
330 self._add_independent_path(skim_path, ds_ID, merge_back_event)
333 pybasf2.Path.add_module = _add_module
334 pybasf2.Path.add_independent_path = _add_independent_path
337 def get_default_global_tags():
339 Return the list of default globaltags in one string separated with comma
341 .. deprecated:: release-04-00-00
342 Please use `basf2.conditions.default_globaltags <ConditionsConfiguration.default_globaltags>` instead
344 B2WARNING(
"basf2.get_default_global_tags() is deprecated, please use basf2.conditions.default_globaltags")
345 return ",".join(conditions.default_globaltags)
348 def set_central_database_networkparams(**argk):
350 Set some expert database connection details
352 .. deprecated:: release-04-00-00
353 Please use `basf2.conditions.expert_settings <ConditionsConfiguration.expert_settings>` instead
355 B2WARNING(
"basf2.set_central_database_networkparams() is deprecated, please use basf2.conditions.expert_settings()")
356 return conditions.expert_settings(**argk)
359 def set_central_serverlist(serverlist):
361 Set the list of database servers
363 .. deprecated:: release-04-00-00
364 Please use `basf2.conditions.metadata_providers <ConditionsConfiguration.metadata_providers>` instead
366 B2WARNING(
"basf2.set_central_serverlist() is deprecated, please use basf2.conditions.metadata_providers instead")
367 conditions.metadata_providers = serverlist + [e
for e
in conditions.metadata_providers
if not e.startswith(
"http")]
static Environment & Instance()
Static method to get a reference to the Environment instance.