12from collections
import namedtuple
15prompt_script_package =
"prompt.calibrations."
16prompt_script_dir =
"calibration/scripts/prompt/calibrations"
18prompt_validation_script_package =
"prompt.validations."
19prompt_validation_script_dir =
"calibration/scripts/prompt/validations"
21INPUT_DATA_FILTERS = {
"Magnet": {
"On":
"On",
24 "Beam Energy": {
"No Beam":
"No Beam",
26 "Continuum":
"Continuum",
29 "Run Type": {
"beam":
"beam",
31 "debug":
"debug",
"null":
"null",
32 "physics":
"physics"},
33 "Data Tag": {
"hlt_skim":
"hlt_skim",
34 "bhabha_all_calib":
"bhabha_all_calib",
35 "cosmic_calib":
"cosmic_calib",
36 "gamma_gamma_calib":
"gamma_gamma_calib",
37 "hadron_calib":
"hadron_calib",
38 "btocharm_calib":
"btocharm_calib",
39 "mumu_tight_or_highm_calib":
"mumu_tight_or_highm_calib",
40 "offip_calib":
"offip_calib",
41 "radmumu_calib":
"radmumu_calib",
42 "random_calib":
"random_calib",
43 "delayedbhabha_calib":
"delayedbhabha_calib",
44 "single_gamma_mc":
"single_gamma_mc"},
45 "Data Quality Tag": {
">=30 Minute Run":
">=30 Minute Run",
46 "Bad For Alignment":
"Bad For Alignment",
48 "Good Shifter":
"Good Shifter",
49 "Good For PXD":
"Good For PXD",
50 "Good Or Recoverable":
"Good Or Recoverable",
51 "Good Or Recoverable Shifter":
"Good Or Recoverable Shifter"}
55class CalibrationSettings(namedtuple(
'CalSet_Factory', [
"name",
64 Simple class to hold and
display required information for a
prompt calibration script (process).
67 name (str): The unique calibration name,
not longer than 64 characters.
69 expert_username (str): The GitLab username of the expert to contact about this script.
70 This username will be used to assign the default responsible person
for submitting
and checking prompt
73 description (str): Long form description of the calibration
and what it does. Feel free to make this
as long
as you need.
75 input_data_formats (frozenset(str)): The data formats {
'raw',
'cdst',
'mdst',
'udst'} of the input files
76 that should be used
as input to the process. Used to figure out
if this calibration should occur
77 before the relevant data production e.g. before cDST files are created.
79 input_data_names (frozenset(str)): The names that you will use when accessing the input data given to the
80 prompt calibration process i.e. Use these
in the ``get_calibrations`` function to access the correct input
81 data files. e.g. input_data_names=[
"all_events",
"offres_photon_events"]
83 input_data_filters (dict): The data selection
for the data input names, used
for automated calibration.
84 The keys should correspond to one of the ``input_data_names``
with the values being a list of the various data
85 filters, e.g. Data Tag, Beam Energy, Run Type, Run Quality Tag
and Magnet. All available filters can be found
in the
86 input_data_filters dictionary e.g.
from prompt
import input_data_filters
with details about data tags
and run quality
87 tags found at: https://calibration.belle2.org/belle2/data_tags/list/.
88 To exclude specific filters, pre-append
with *NOT* e.g.
89 {
"all_events": [
"mumu_tight_or_highm_calib",
"hadron_calib",
"Good",
"On"],
90 "offres_photon_events": [
"gamma_gamma_calib",
"Good",
"NOT On"]}.
91 Not selecting a specific filters (e.g. Magnet)
is equivalent to
not having any requirements, e.g. (Either)
93 depends_on (list(CalibrationSettings)): The settings variables of the other prompt calibrations that you want
94 want to depend on. This will allow the external automatic system to understand the overall ordering of
95 scripts to run. If you encounter an
import error when trying to run your prompt calibration script, it
is
96 likely that you have introduced a circular dependency.
98 expert_config (dict): Default expert configuration
for this calibration script. This
is an optional dictionary
99 (which must be JSON compliant) of configuration options
for your get_calibrations(...) function.
100 This
is supposed to be used
as a catch-all place to send
in options
for your calibration setup. For example,
101 you may want to have an optional list of IoV boundaries so that your prompt script knows that it should split the
102 input data between different IoV ranges. Or you might want to send
if options like the maximum events per
103 input file to process. The value
in your settings object will be the *default*, but you can override the value via
104 the caf_config.json sent into ``b2caf-prompt-run``.
110 allowed_data_formats = frozenset({"raw",
"cdst",
"mdst",
"udst"})
112 def __new__(cls, name, expert_username, description,
113 input_data_formats=None, input_data_names=None, input_data_filters=None, depends_on=None, expert_config=None):
115 The special method to create the tuple instance. Returning the instance
116 calls the __init__ method
119 raise ValueError(
"name cannot be longer than 64 characters!")
120 if not input_data_formats:
121 raise ValueError(
"You must specify at least one input data format")
122 input_data_formats = frozenset(map(
lambda x: x.lower(), input_data_formats))
123 if input_data_formats.difference(cls.allowed_data_formats):
124 raise ValueError(
"There was a data format that is not in the allowed_data_formats attribute.")
125 if not input_data_names:
126 raise ValueError(
"You must specify at least one input data name")
127 input_data_names = frozenset(input_data_names)
130 if input_data_filters:
131 if set(input_data_filters.keys()) != input_data_names:
132 raise ValueError(
"The 'input_data_filters' keys don't match the 'input_data_names'!")
134 allowed_filters = {filter_name
for category
in INPUT_DATA_FILTERS.values()
for filter_name
in category}
135 requested_filters = {filter_name.replace(
"NOT",
"", 1).lstrip()
for filters
in input_data_filters.values()
136 for filter_name
in filters}
137 if not allowed_filters.issuperset(requested_filters):
138 raise ValueError(
"The 'input_data_filters' contains unknown filter names:"
139 f
"{requested_filters.difference(allowed_filters)}")
141 input_data_filters = {}
145 if not isinstance(expert_config, dict):
146 raise TypeError(
"expert_config must be a dictionary")
149 json.dumps(expert_config)
150 except TypeError
as e:
151 basf2.B2ERROR(
"expert_config could not be serialised to JSON. "
152 "Most likely you used a non-supported type e.g. datetime.")
158 for calibration_settings
in depends_on:
159 if not isinstance(calibration_settings, cls):
160 raise TypeError(f
"A list of {str(cls)} object is required when setting the 'depends_on' keyword.")
164 return super().__new__(cls, name, expert_username, description,
165 input_data_formats, input_data_names, input_data_filters, depends_on, expert_config)
167 def json_dumps(self):
170 str: A valid JSON format string of the attributes.
172 depends_on_names = [calibration_settings.name for calibration_settings
in self.depends_on]
173 return json.dumps({
"name": self.name,
174 "expert_username": self.expert_username,
175 "input_data_formats": list(self.input_data_formats),
176 "input_data_names": list(self.input_data_names),
177 "input_data_filters": self.input_data_filters,
178 "depends_on": list(depends_on_names),
179 "description": self.description,
180 "expert_config": self.expert_config
184 depends_on_names = [calibration_settings.name
for calibration_settings
in self.depends_on]
185 output_str = str(self.__class__.__name__) + f
"(name='{self.name}'):\n"
186 output_str += f
" expert_username='{self.expert_username}'\n"
187 output_str += f
" input_data_formats={list(self.input_data_formats)}\n"
188 output_str += f
" input_data_names={list(self.input_data_names)}\n"
189 output_str += f
" input_data_filters={list(self.input_data_filters)}\n"
190 output_str += f
" depends_on={list(depends_on_names)}\n"
191 output_str += f
" description='{self.description}'\n"
192 output_str += f
" expert_config={self.expert_config}"
196class ValidationSettings(namedtuple(
'ValSet_Factory', [
"name",
"description",
"download_files",
"expert_config"])):
198 Simple class to hold and
display required information for a
validation calibration script (process).
201 name (str): The unique name that must match the corresponding calibration,
not longer than 64 characters.
203 description (str): Long form description of the validation
and what it does. Feel free to make this
as long
as you need.
205 download_files (list): The names of the files you want downloaded, e.g. mycalibration_stdout. If multiple files of
206 the same name are found, all files are downloaded
and appended
with the folder they were
in.
208 expert_config (dict): Default expert configuration
for this validation script. This
is an optional dictionary
209 (which must be JSON compliant) of configuration options
for validation script.
210 This
is supposed to be used
as a catch-all place to send
in options
for your calibration setup. For example,
211 you may want to have an optional list of IoV boundaries so that your validation script knows that it should split the
212 input data between different IoV ranges. Or you might want to send
if options like the maximum events per
213 input file to process. The value
in your settings object will be the *default*, but you can override the value via
214 the caf_config.json sent into ``b2caf-prompt-run``.
217 def __new__(cls, name, description, download_files=None, expert_config=None):
219 The special method to create the tuple instance. Returning the instance
220 calls the __init__ method
223 raise ValueError(
"name cannot be longer than 64 characters!")
227 if not isinstance(expert_config, dict):
228 raise TypeError(
"expert_config must be a dictionary")
231 json.dumps(expert_config)
232 except TypeError
as e:
233 basf2.B2ERROR(
"expert_config could not be serialised to JSON. "
234 "Most likely you used a non-supported type e.g. datetime.")
239 return super().__new__(cls, name, description, download_files, expert_config)
241 def json_dumps(self):
244 str: A valid JSON format string of the attributes.
246 return json.dumps({
"name": self.name,
247 "description": self.description,
248 "download_files": self.download_files,
249 "expert_config": self.expert_config
253 output_str = str(self.__class__.__name__) + f
"(name='{self.name}'):\n"
254 output_str += f
" description='{self.description}'\n"
255 output_str += f
" download_files='{self.download_files}'\n"
256 output_str += f
" expert_config={self.expert_config}"