9from lxml.builder
import E
10from IPython
import get_ipython
11from .
import core
as b2core
15from ROOT
import Belle2
18_process_warning =
False
21def _create_pathhtml(path, name="Path", details=None):
22 """Create an html fragment for a given Path object"""
23 size = len(path.modules())
24 fragment = E.div(f
"{name} with {size} modules")
25 if details
is not None:
26 fragment.append(details)
28 module_list = E.ol(style=
"list-style-type:decimal; font-style:normal;")
29 for m
in path.modules():
32 tname = f
" (type \"{tname}\")" if tname != name
else ""
33 module = E.li(
"Module ", E.b(name), tname)
34 detail_list = E.ul(style=
"margin:0em 0em 0.5em 0em")
35 for p
in m.available_params():
37 detail_list.append(E.li(E.code(f
"{p.name} = {p.values}")))
38 for c
in m.get_all_conditions():
39 after = str(c.get_after_path())
40 details = E.span(
" (condition: ", E.code(f
"{c.get_operator()} {c.get_value()}"),
", afterwards:", E.code(after),
')')
41 detail_list.append(E.li(_create_pathhtml(c.get_path(),
"Conditional Path", details=details),
42 style=
"list-style-type: disclosure-closed"))
43 if len(detail_list) > 0:
44 module.append(detail_list)
46 module_list.append(module)
47 if len(module_list) > 0:
48 fragment.append(module_list)
52def print_path_html(path):
53 """Print a path (and all sub paths) as html"""
54 return etree.tostring(_create_pathhtml(path,
"basf2.Path")).decode()
57def print_module_html(module):
58 """Print a module (and its parameters) as well as the description"""
61 tname = f
" (type {tname})" if tname != name
else ""
62 module_html = E.div(
"basf2.Module ", E.b(name), tname, E.p(module.description),
63 E.style(
"table.b2module * { text-align: left !important; }"))
64 cols = [
"parameter",
"type",
"default",
"current",
"changed",
"is required"]
65 if len(module.available_params()) > 0:
67 for p
in module.available_params():
68 params.append(E.tr(E.td(p.name), E.td(E.code(str(p.type))), E.td(E.code(str(p.default))), E.td(E.code(str(p.values))),
69 E.td(E.b(
"yes")
if p.setInSteering
else "no"),
70 E.td(E.b(
"yes")
if p.forceInSteering
else "no")))
71 params.append(E.tr(E.td(), E.td(p.description, colspan=
"5")))
73 module_html.append(E.table(E.thead(E.tr(*[E.th(e)
for e
in cols])), params, **{
"class":
"b2module"}))
75 return etree.tostring(module_html).decode()
78def enable_notebooksupport():
80 Small function to enable some notebook compatibility.
81 Mostly make sure that log messages are shown correctly (they are C++ so they need some special love to show up).
85 b2core.logging.reset()
86 b2core.logging.add_console(
True)
87 b2core.logging.enable_python_logging =
True
93 html_formatter = get_ipython().display_formatter.formatters[
'text/html']
94 html_formatter.for_type(b2core.Path, print_path_html)
95 html_formatter.for_type(b2core.Module, print_module_html)
98def _child_process(pipe, path, max_events):
99 """Execute process() in a child process but send the persistent datastore objects back to the parent"""
101 b2core.process(path, max_events)
104 for name
in [
"ProcessStatistics"]:
107 if storeobj.isValid():
108 return_objects[name] = str(ROOT.TBufferJSON.ToJSON(storeobj.obj()))
109 pipe.send(return_objects)
113def process(path, max_event=0):
115 Start processing events using the modules in the given `basf2.Path` object.
117 Can be called multiple times
in one steering file.
119 This
is a convenience wrapper which will automatically call the
120 `process()` function
in a separate process to prevent FATAL errors
from killing
124 As processing
is done
in a separate process the
global state of the notebook
125 cannot be modified. For example a python modules collecting information will appear to be
126 empty after execution
and global variables will also
not be modified.
128 If you need to modify the state of the notebook during processing you need to call
132 path: The path
with which the processing starts
133 max_event: The maximal number of events which will be processed, 0
for no limit
138 global _process_warning
139 if not _process_warning:
140 _process_warning =
True
141 b2core.B2INFO(
"process() called in a Jupyter Notebook. See help(basf2.process) for caveats")
144 ctx = multiprocessing.get_context(
"fork")
145 nanny, child = ctx.Pipe()
146 process = ctx.Process(target=_child_process, args=(child, path, max_event))
149 if process.exitcode != 0:
150 raise RuntimeError(
"Event processing was not successful")
151 return_objects = nanny.recv()
153 datastore.setInitializeActive(
True)
155 for name, value
in return_objects.items():
157 if value
is not None:
158 storeobj.registerInDataStore()
160 obj = ROOT.TBufferJSON.ConvertFromJSON(value)
161 ROOT.SetOwnership(obj,
False)
162 storeobj.assign(obj,
True)
164 datastore.setInitializeActive(
False)
static DataStore & Instance()
Instance of singleton Store.
a (simplified) python wrapper for StoreObjPtr.