3 """Small module containing helper functions to set the metadata on objects
4 created for the validation correctly """
7 from typing
import Optional, Union, List, Tuple
12 from ROOT
import Belle2
15 ROOT.gInterpreter.Declare(
"#include <framework/utilities/MakeROOTCompatible.h>")
21 def file_description_set(rootfile: Union[ROOT.TFile, str, pathlib.PurePath],
22 description: str) ->
None:
24 Add file description validation metdata to a ROOT file.
27 rootfile (TFile, str or pathlib.PurePath): Name of the root file
28 to open or an already open TFile instance
29 description (str): Common description/information of/about all plots
30 in this ROOT file (will be displayed above the plots)
36 if not isinstance(rootfile, ROOT.TFile):
37 if isinstance(rootfile, pathlib.PurePath):
38 rootfile = str(rootfile)
39 rootfile = ROOT.TFile(rootfile,
"UPDATE")
41 if not rootfile.IsOpen()
or not rootfile.IsWritable():
43 f
"ROOT file {rootfile.GetName()} is not open for writing"
48 directory_guard = ROOT.TDirectory.TContext(rootfile)
49 desc = ROOT.TNamed(
"Description", description)
55 def validation_metadata_set(obj: ROOT.TObject, title: str, contact: str,
56 description: str, check: str,
57 xlabel: Optional[str] =
None,
58 ylabel: Optional[str] =
None,
59 metaoptions=
"") ->
None:
61 Set the validation metadata for a given object by setting the necessary
62 values. This function can be used on any object supported by the
63 Validation (histograms, profiles, ntuples)
66 obj: Instance of the object which should get the metadata
67 title (str): Title to use for the object
68 contact (str): Contact person, usually in the form "Name <email>"
69 description (str): Text description what can be seen in the plot
70 check (str): Text description what to look for in the validation for
71 shifters to easily see if the distribution looks ok
72 xlabel (str): If given try to set this as the label for the x axis
73 ylabel (str): If given try to set this as the label for the y axis
74 metaoptions (str): Metaoptions (additional options to influence the
75 comparison between revisions, styling of the plot, etc.)
79 Different ways to specify LaTeX for different arguments:
80 see `create_validation_histograms`
85 obj.SetAlias(
"Contact", contact)
86 obj.SetAlias(
"Description", description)
87 obj.SetAlias(
"Check", check)
88 obj.SetAlias(
"MetaOptions", metaoptions)
89 except AttributeError:
93 function_list = obj.GetListOfFunctions()
94 function_list.Add(ROOT.TNamed(
"Contact", contact))
95 function_list.Add(ROOT.TNamed(
"Description", description))
96 function_list.Add(ROOT.TNamed(
"Check", check))
97 function_list.Add(ROOT.TNamed(
"MetaOptions", metaoptions))
98 except AttributeError:
102 if xlabel
is not None:
104 obj.GetXaxis().SetTitle(xlabel)
105 except AttributeError:
108 if ylabel
is not None:
110 obj.GetYaxis().SetTitle(ylabel)
111 except AttributeError:
116 def validation_metadata_update(
117 rootfile: Union[str, ROOT.TFile, pathlib.PurePath],
118 name: str, *args, **argk) ->
None:
120 This is a convenience helper for `validation_metadata_set` in case the
121 objects have already been saved in a ROOT file before: It will open the
122 file (or use an existing TFile), extract the object, add the metadata and
123 save the new version to the file
126 rootfile (str, ROOT.TFile or pathlib.PurePath): Name of the root file
127 to open or an already open TFile instance
128 name (str): Name of the object in the file
129 title (str): Title to use for the object
130 contact (str): Contact person, usually in the form "Name <email>"
131 description (str): Text description what can be seen in the plot
132 check (str): Text description what to look for in the validation for
133 shifters to easily see if the distribution looks ok
134 xlabel (str): If given try to set this as the label for the x axis
135 ylabel (str): If given try to set this as the label for the y axis
136 metaoptions (str): Metaoptions (additional options to influence the
137 comparison between revisions, styling of the plot, etc.)
141 Different ways to specify LaTeX for different arguments:
142 see `create_validation_histograms`
146 if not isinstance(rootfile, ROOT.TFile):
147 if isinstance(rootfile, pathlib.PurePath):
148 rootfile = str(rootfile)
149 rootfile = ROOT.TFile(rootfile,
"UPDATE")
151 if not rootfile.IsOpen()
or not rootfile.IsWritable():
153 f
"ROOT file {rootfile.GetName()} is not open for writing"
155 obj = rootfile.Get(name)
158 f
"Cannot find object named {name} in {rootfile.GetName()}"
160 validation_metadata_set(obj, *args, **argk)
164 directory_guard = ROOT.TDirectory.TContext(rootfile)
165 obj.Write(
"", ROOT.TObject.kOverwrite)
170 class ValidationMetadataSetter(basf2.Module):
172 Simple module to set the valdiation metadata for a given list of objects
173 automatically at the end of event processing
175 Just add this module **before** any
176 VariablesToNtuple/VariablesToHistogram modules and it will set the
177 correct validation metadata at the end of processing
180 The module needs to be before the modules creating the objects
181 as terminate() functions are executed in reverse order from last to
182 first module. If this module is after the creation modules the metadata
183 might not be set correctly
186 def __init__(self, variables: List[Tuple[str]],
187 rootfile: Union[str, pathlib.PurePath], description=
""):
189 Initialize ValidationMetadataSetter
192 variables (list(tuple(str))): List of objects to set the metadata
193 for. Each entry should be the name of an object followed by the
194 metadata values which will be forwarded to
195 `validation_metadata_set`:
196 ``(name, title, contact, description, check, xlabel, ylabel,
198 where ``xlabel``, ``ylabel`` and ``metaoptions`` are optional
199 rootfile (str or pathlib.PurePath): The name of the ROOT file where
200 the objects can be found
201 description (str): Common description/information of/about all plots
202 in this ROOT file (will be displayed above the plots)
206 self._variables = variables
207 if isinstance(rootfile, pathlib.PurePath):
208 rootfile = str(rootfile)
210 self._rootfile = rootfile
213 self._description = description
218 def initialize(self):
219 """Make sure we keep the file open"""
224 """And update the metadata at the end"""
225 for name, *metadata
in self._variables:
227 validation_metadata_update(self._tfile, name, *metadata)
228 if self._description:
229 file_description_set(self._tfile, self._description)
233 def create_validation_histograms(
234 path: basf2.Path, rootfile: Union[str, pathlib.PurePath],
236 variables_1d: Optional[List[Tuple]] =
None,
237 variables_2d: Optional[List[Tuple]] =
None,
241 Create histograms for all the variables and also label them to be useful
242 in validation plots in one go. This is similar to the
243 `modularAnalysis.variablesToHistogram` function but also sets the
244 metadata correctly to be used by the validation
247 path (basf2.Path): Path where to put the modules
248 rootfile (str or pathlib.PurePath): Name of the output root file
249 particlelist (str): Name of the particle list, can be empty for event
251 variables_1d: List of 1D histogram definitions of the form
252 ``var, bins, min, max, title, contact, description, check_for
253 [, xlabel [, ylabel [, metaoptions]]]``
254 variables_2d: List of 2D histogram definitions of the form
255 ``var1, bins1, min1, max1, var2, bins2, min2, max2, title, contact,
256 description, check_for [, xlabel [, ylabel [, metaoptions]]]``
257 description: Common description/information of/about all plots in this
258 ROOT file (will be displayed above the plots)
262 Sadly, there are two different ways to specify latex formulas.
264 1. The ROOT-style using ``#``:
265 ``"Einstein-Pythagoras a^{2} + b^{2} = #frac{E}{m}"``
267 This style should be used for histogram title and labels, that is the
268 ``title``, ``xlabel`` and ``ylabel`` arguments
270 2. The normal Latex style (with escaped backslashes or raw
272 ``"Einstein-Pythagoras $a^2 + b^2 = \\\\frac{E}{m}$"``.
274 This style should be used for all other fields like ``description``,
277 You can use the normal Latex style also for histogram title and descriptions
278 but the PDF version of the plots will still be buggy and not show all
281 if isinstance(rootfile, pathlib.PurePath):
282 rootfile = str(rootfile)
286 if variables_1d
is not None:
287 for var, nbins, vmin, vmax, *data
in variables_1d:
288 histograms_1d.append((var, nbins, vmin, vmax))
289 metadata.append([var] + data)
291 if variables_2d
is not None:
292 for row
in variables_2d:
295 histograms_2d.append(row[:8])
296 metadata.append([var1 + var2] + list(row[8:]))
299 ValidationMetadataSetter(metadata, rootfile, description=description)
302 "VariablesToHistogram",
303 particleList=particlelist,
304 variables=histograms_1d,
305 variables_2d=histograms_2d,