Belle II Software  release-05-01-25
__init__.py
1 import basf2
2 from collections import namedtuple
3 import json
4 import subprocess
5 
6 prompt_script_package = "prompt.calibrations."
7 prompt_script_dir = "calibration/scripts/prompt/calibrations"
8 
9 prompt_validation_script_package = "prompt.validations."
10 prompt_validation_script_dir = "calibration/scripts/prompt/validations"
11 
12 
13 class CalibrationSettings(namedtuple('CalSet_Factory', ["name", "expert_username", "description",
14  "input_data_formats", "input_data_names", "depends_on", "expert_config"])):
15  """
16  Simple class to hold and display required information for a prompt calibration script (process).
17 
18  Parameters:
19  name (str): The unique calibration name, not longer than 64 characters.
20 
21  expert_username (str): The JIRA username of the expert to contact about this script.
22  This username will be used to assign the default responsible person for submitting and checking prompt
23  calibration jobs.
24 
25  description (str): Long form description of the calibration and what it does. Feel free to make this as long as you need.
26 
27  input_data_formats (frozenset(str)): The data formats {'raw', 'cdst', 'mdst', 'udst'} of the input files
28  that should be used as input to the process. Used to figure out if this calibration should occur
29  before the relevant data production e.g. before cDST files are created.
30 
31  input_data_names (frozenset(str)): The names that you will use when accessing the input data given to the
32  prompt calibration process i.e. Use these in the ``get_calibrations`` function to access the correct input
33  data files.
34 
35  depends_on list(CalibrationSettings): The settings variables of the other prompt calibrations that you want
36  want to depend on. This will allow the external automatic system to understand the overall ordering of
37  scripts to run. If you encounter an import error when trying to run your prompt calibration script, it is
38  likely that you have introduced a circular dependency.
39 
40  expert_config (dict): Default expert configuration for this calibration script. This is an optional dictionary
41  (which must be JSON compliant) of configuration options for your get_calibrations(...) function.
42  This is supposed to be used as a catch-all place to send in options for your calibration setup. For example,
43  you may want to have an optional list of IoV boundaries so that your prompt script knows that it should split the
44  input data between different IoV ranges. Or you might want to send if options like the maximum events per
45  input file to process. The value in your settings object will be the *default*, but you can override the value via
46  the caf_config.json sent into ``b2caf-prompt-run``.
47  """
48 
49 
52  allowed_data_formats = frozenset({"raw", "cdst", "mdst", "udst"})
53 
54  def __new__(cls, name, expert_username, description,
55  input_data_formats=None, input_data_names=None, depends_on=None, expert_config=None):
56  """
57  The special method to create the tuple instance. Returning the instance
58  calls the __init__ method
59  """
60  if len(name) > 64:
61  raise ValueError("name cannot be longer than 64 characters!")
62  if not input_data_formats:
63  raise ValueError("You must specify at least one input data format")
64  input_data_formats = frozenset(map(lambda x: x.lower(), input_data_formats))
65  if input_data_formats.difference(cls.allowed_data_formats):
66  raise ValueError("There was a data format that is not in the allowed_data_formats attribute.")
67  if not input_data_names:
68  raise ValueError("You must specify at least one input data name")
69  input_data_names = frozenset(input_data_names)
70 
71  if expert_config:
72  # Check that it's a dictionary and not some other valid JSON object
73  if not isinstance(expert_config, dict):
74  raise TypeError("expert_config must be a dictionary")
75  # Check if it is JSONable since people might put objects in there by mistake
76  try:
77  json.dumps(expert_config)
78  except TypeError as e:
79  basf2.B2ERROR("expert_config could not be serialised to JSON. "
80  "Most likely you used a non-supported type e.g. datetime.")
81  raise e
82  else:
83  expert_config = {}
84 
85  if depends_on:
86  for calibration_settings in depends_on:
87  if not isinstance(calibration_settings, cls):
88  raise TypeError(f"A list of {str(cls)} object is required when setting the 'depends_on' keyword.")
89  else:
90  depends_on = []
91 
92  return super().__new__(cls, name, expert_username, description,
93  input_data_formats, input_data_names, depends_on, expert_config)
94 
95  def json_dumps(self):
96  """
97  Returns:
98  str: A valid JSON format string of the attributes.
99  """
100  depends_on_names = [calibration_settings.name for calibration_settings in self.depends_on]
101  return json.dumps({"name": self.name,
102  "expert_username": self.expert_username,
103  "input_data_formats": list(self.input_data_formats),
104  "input_data_names": list(self.input_data_names),
105  "depends_on": list(depends_on_names),
106  "description": self.description,
107  "expert_config": self.expert_config
108  })
109 
110  def __str__(self):
111  depends_on_names = [calibration_settings.name for calibration_settings in self.depends_on]
112  output_str = str(self.__class__.__name__) + f"(name='{self.name}'):\n"
113  output_str += f" expert_username='{self.expert_username}'\n"
114  output_str += f" input_data_formats={list(self.input_data_formats)}\n"
115  output_str += f" input_data_names={list(self.input_data_names)}\n"
116  output_str += f" depends_on={list(depends_on_names)}\n"
117  output_str += f" description='{self.description}'\n"
118  output_str += f" expert_config={self.expert_config}"
119  return output_str
120 
121 
122 class ValidationSettings(namedtuple('ValSet_Factory', ["name", "description", "download_files", "expert_config"])):
123  """
124  Simple class to hold and display required information for a validation calibration script (process).
125 
126  Parameters:
127  name (str): The unique name that must match the corresponding calibration, not longer than 64 characters.
128 
129  description (str): Long form description of the validation and what it does. Feel free to make this as long as you need.
130 
131  download_files (list): The names of the files you want downloaded, e.g. mycalibration_stdout. If multiple files of
132  the same name are found, all files are downloaded and appended with the folder they were in.
133 
134  expert_config (dict): Default expert configuration for this validation script. This is an optional dictionary
135  (which must be JSON compliant) of configuration options for validation script.
136  This is supposed to be used as a catch-all place to send in options for your calibration setup. For example,
137  you may want to have an optional list of IoV boundaries so that your validation script knows that it should split the
138  input data between different IoV ranges. Or you might want to send if options like the maximum events per
139  input file to process. The value in your settings object will be the *default*, but you can override the value via
140  the caf_config.json sent into ``b2caf-prompt-run``.
141  """
142 
143  def __new__(cls, name, description, download_files=None, expert_config=None):
144  """
145  The special method to create the tuple instance. Returning the instance
146  calls the __init__ method
147  """
148  if len(name) > 64:
149  raise ValueError("name cannot be longer than 64 characters!")
150 
151  if expert_config:
152  # Check that it's a dictionary and not some other valid JSON object
153  if not isinstance(expert_config, dict):
154  raise TypeError("expert_config must be a dictionary")
155  # Check if it is JSONable since people might put objects in there by mistake
156  try:
157  json.dumps(expert_config)
158  except TypeError as e:
159  basf2.B2ERROR("expert_config could not be serialised to JSON. "
160  "Most likely you used a non-supported type e.g. datetime.")
161  raise e
162  else:
163  expert_config = {}
164 
165  return super().__new__(cls, name, description, download_files, expert_config)
166 
167  def json_dumps(self):
168  """
169  Returns:
170  str: A valid JSON format string of the attributes.
171  """
172  return json.dumps({"name": self.name,
173  "description": self.description,
174  "download_files": self.download_files,
175  "expert_config": self.expert_config
176  })
177 
178  def __str__(self):
179  output_str = str(self.__class__.__name__) + f"(name='{self.name}'):\n"
180  output_str += f" description='{self.description}'\n"
181  output_str += f" download_files='{self.download_files}'\n"
182  output_str += f" expert_config={self.expert_config}"
183  return output_str
prompt.CalibrationSettings.allowed_data_formats
allowed_data_formats
Allowed data file formats.
Definition: __init__.py:52
prompt.CalibrationSettings.__new__
def __new__(cls, name, expert_username, description, input_data_formats=None, input_data_names=None, depends_on=None, expert_config=None)
Definition: __init__.py:54
prompt.ValidationSettings.__new__
def __new__(cls, name, description, download_files=None, expert_config=None)
Definition: __init__.py:143
prompt.ValidationSettings.json_dumps
def json_dumps(self)
Definition: __init__.py:167
prompt.ValidationSettings
Definition: __init__.py:122
prompt.CalibrationSettings.json_dumps
def json_dumps(self)
Definition: __init__.py:95