Belle II Software  release-05-02-19
__init__.py
1 import basf2
2 from collections import namedtuple
3 import json
4 
5 prompt_script_package = "prompt.calibrations."
6 prompt_script_dir = "calibration/scripts/prompt/calibrations"
7 
8 prompt_validation_script_package = "prompt.validations."
9 prompt_validation_script_dir = "calibration/scripts/prompt/validations"
10 
11 input_data_filters = {"Magnet": {"On": "On",
12  "Off": "Off",
13  "Either": "Either"},
14  "Beam Energy": {"No Beam": "No Beam",
15  "4S": "4S",
16  "Continuum": "Continuum",
17  "Scan": "Scan"},
18  "Run Type": {"beam": "beam",
19  "cosmic": "cosmic",
20  "debug": "debug", "null": "null",
21  "physics": "physics"},
22  "Data Tag": {"hlt_skim": "hlt_skim",
23  "bhabha_all_calib": "bhabha_all_calib",
24  "cosmic_calib": "cosmic_calib",
25  "gamma_gamma_calib": "gamma_gamma_calib",
26  "hadron_calib": "hadron_calib",
27  "mumutight_calib": "mumutight_calib",
28  "offip_calib": "offip_calib",
29  "radmumu_calib": "radmumu_calib",
30  "random_calib": "random_calib"},
31  "Data Quality Tag": {">=30 Minute Run": ">=30 Minute Run",
32  "Bad For Alignment": "Bad For Alignment",
33  "Good": "Good",
34  "Good Shifter": "Good Shifter",
35  "Good For PXD": "Good For PXD",
36  "Good Or Recoverable": "Good Or Recoverable",
37  "Good Or Recoverable Shifter": "Good Or Recoverable Shifter"}
38  }
39 
40 
41 class CalibrationSettings(namedtuple('CalSet_Factory', ["name",
42  "expert_username",
43  "description",
44  "input_data_formats",
45  "input_data_names",
46  "input_data_filters",
47  "depends_on",
48  "expert_config"])):
49  """
50  Simple class to hold and display required information for a prompt calibration script (process).
51 
52  Parameters:
53  name (str): The unique calibration name, not longer than 64 characters.
54 
55  expert_username (str): The JIRA username of the expert to contact about this script.
56  This username will be used to assign the default responsible person for submitting and checking prompt
57  calibration jobs.
58 
59  description (str): Long form description of the calibration and what it does. Feel free to make this as long as you need.
60 
61  input_data_formats (frozenset(str)): The data formats {'raw', 'cdst', 'mdst', 'udst'} of the input files
62  that should be used as input to the process. Used to figure out if this calibration should occur
63  before the relevant data production e.g. before cDST files are created.
64 
65  input_data_names (frozenset(str)): The names that you will use when accessing the input data given to the
66  prompt calibration process i.e. Use these in the ``get_calibrations`` function to access the correct input
67  data files. e.g. input_data_names=["all_events", "offres_photon_events"]
68 
69  input_data_filters (dict): The data selection for the data input names, used for automated calibration.
70  The keys should correspond to one of the ``input_data_names`` with the values being a list of the various data
71  filters, e.g. Data Tag, Beam Energy, Run Type, Run Quality Tag and Magnet. All available filters can be found in the
72  input_data_filters dictionary e.g. from prompt import input_data_filters with details about data tags and run quality
73  tags found at: https://calibration.belle2.org/belle2/data_tags/list/.
74  To exclude specific filters, pre-append with *NOT* e.g.
75  {"all_events": ["mumutight_calib", "hadron_calib", "Good", "On"],
76  "offres_photon_events": ["gamma_gamma_calib", "Good", "NOT On"]}.
77  Not selecting a specfic filters (e.g. Magnet) is equivalent to not having any requirements, e.g. (Either)
78 
79  depends_on (list(CalibrationSettings)): The settings variables of the other prompt calibrations that you want
80  want to depend on. This will allow the external automatic system to understand the overall ordering of
81  scripts to run. If you encounter an import error when trying to run your prompt calibration script, it is
82  likely that you have introduced a circular dependency.
83 
84  expert_config (dict): Default expert configuration for this calibration script. This is an optional dictionary
85  (which must be JSON compliant) of configuration options for your get_calibrations(...) function.
86  This is supposed to be used as a catch-all place to send in options for your calibration setup. For example,
87  you may want to have an optional list of IoV boundaries so that your prompt script knows that it should split the
88  input data between different IoV ranges. Or you might want to send if options like the maximum events per
89  input file to process. The value in your settings object will be the *default*, but you can override the value via
90  the caf_config.json sent into ``b2caf-prompt-run``.
91  """
92 
93 
96  allowed_data_formats = frozenset({"raw", "cdst", "mdst", "udst"})
97 
98  def __new__(cls, name, expert_username, description,
99  input_data_formats=None, input_data_names=None, input_data_filters=None, depends_on=None, expert_config=None):
100  """
101  The special method to create the tuple instance. Returning the instance
102  calls the __init__ method
103  """
104  if len(name) > 64:
105  raise ValueError("name cannot be longer than 64 characters!")
106  if not input_data_formats:
107  raise ValueError("You must specify at least one input data format")
108  input_data_formats = frozenset(map(lambda x: x.lower(), input_data_formats))
109  if input_data_formats.difference(cls.allowed_data_formats):
110  raise ValueError("There was a data format that is not in the allowed_data_formats attribute.")
111  if not input_data_names:
112  raise ValueError("You must specify at least one input data name")
113  input_data_names = frozenset(input_data_names)
114 
115  if expert_config:
116  # Check that it's a dictionary and not some other valid JSON object
117  if not isinstance(expert_config, dict):
118  raise TypeError("expert_config must be a dictionary")
119  # Check if it is JSONable since people might put objects in there by mistake
120  try:
121  json.dumps(expert_config)
122  except TypeError as e:
123  basf2.B2ERROR("expert_config could not be serialised to JSON. "
124  "Most likely you used a non-supported type e.g. datetime.")
125  raise e
126  else:
127  expert_config = {}
128 
129  if depends_on:
130  for calibration_settings in depends_on:
131  if not isinstance(calibration_settings, cls):
132  raise TypeError(f"A list of {str(cls)} object is required when setting the 'depends_on' keyword.")
133  else:
134  depends_on = []
135 
136  return super().__new__(cls, name, expert_username, description,
137  input_data_formats, input_data_names, input_data_filters, depends_on, expert_config)
138 
139  def json_dumps(self):
140  """
141  Returns:
142  str: A valid JSON format string of the attributes.
143  """
144  depends_on_names = [calibration_settings.name for calibration_settings in self.depends_on]
145  return json.dumps({"name": self.name,
146  "expert_username": self.expert_username,
147  "input_data_formats": list(self.input_data_formats),
148  "input_data_names": list(self.input_data_names),
149  "input_data_filters": self.input_data_filters,
150  "depends_on": list(depends_on_names),
151  "description": self.description,
152  "expert_config": self.expert_config
153  })
154 
155  def __str__(self):
156  depends_on_names = [calibration_settings.name for calibration_settings in self.depends_on]
157  output_str = str(self.__class__.__name__) + f"(name='{self.name}'):\n"
158  output_str += f" expert_username='{self.expert_username}'\n"
159  output_str += f" input_data_formats={list(self.input_data_formats)}\n"
160  output_str += f" input_data_names={list(self.input_data_names)}\n"
161  output_str += f" input_data_filters={list(self.input_data_filters)}\n"
162  output_str += f" depends_on={list(depends_on_names)}\n"
163  output_str += f" description='{self.description}'\n"
164  output_str += f" expert_config={self.expert_config}"
165  return output_str
166 
167 
168 class ValidationSettings(namedtuple('ValSet_Factory', ["name", "description", "download_files", "expert_config"])):
169  """
170  Simple class to hold and display required information for a validation calibration script (process).
171 
172  Parameters:
173  name (str): The unique name that must match the corresponding calibration, not longer than 64 characters.
174 
175  description (str): Long form description of the validation and what it does. Feel free to make this as long as you need.
176 
177  download_files (list): The names of the files you want downloaded, e.g. mycalibration_stdout. If multiple files of
178  the same name are found, all files are downloaded and appended with the folder they were in.
179 
180  expert_config (dict): Default expert configuration for this validation script. This is an optional dictionary
181  (which must be JSON compliant) of configuration options for validation script.
182  This is supposed to be used as a catch-all place to send in options for your calibration setup. For example,
183  you may want to have an optional list of IoV boundaries so that your validation script knows that it should split the
184  input data between different IoV ranges. Or you might want to send if options like the maximum events per
185  input file to process. The value in your settings object will be the *default*, but you can override the value via
186  the caf_config.json sent into ``b2caf-prompt-run``.
187  """
188 
189  def __new__(cls, name, description, download_files=None, expert_config=None):
190  """
191  The special method to create the tuple instance. Returning the instance
192  calls the __init__ method
193  """
194  if len(name) > 64:
195  raise ValueError("name cannot be longer than 64 characters!")
196 
197  if expert_config:
198  # Check that it's a dictionary and not some other valid JSON object
199  if not isinstance(expert_config, dict):
200  raise TypeError("expert_config must be a dictionary")
201  # Check if it is JSONable since people might put objects in there by mistake
202  try:
203  json.dumps(expert_config)
204  except TypeError as e:
205  basf2.B2ERROR("expert_config could not be serialised to JSON. "
206  "Most likely you used a non-supported type e.g. datetime.")
207  raise e
208  else:
209  expert_config = {}
210 
211  return super().__new__(cls, name, description, download_files, expert_config)
212 
213  def json_dumps(self):
214  """
215  Returns:
216  str: A valid JSON format string of the attributes.
217  """
218  return json.dumps({"name": self.name,
219  "description": self.description,
220  "download_files": self.download_files,
221  "expert_config": self.expert_config
222  })
223 
224  def __str__(self):
225  output_str = str(self.__class__.__name__) + f"(name='{self.name}'):\n"
226  output_str += f" description='{self.description}'\n"
227  output_str += f" download_files='{self.download_files}'\n"
228  output_str += f" expert_config={self.expert_config}"
229  return output_str
230 
prompt.CalibrationSettings.allowed_data_formats
allowed_data_formats
Allowed data file formats.
Definition: __init__.py:97
prompt.ValidationSettings.__new__
def __new__(cls, name, description, download_files=None, expert_config=None)
Definition: __init__.py:190
prompt.ValidationSettings.json_dumps
def json_dumps(self)
Definition: __init__.py:214
prompt.ValidationSettings
Definition: __init__.py:169
prompt.CalibrationSettings.__new__
def __new__(cls, name, expert_username, description, input_data_formats=None, input_data_names=None, input_data_filters=None, depends_on=None, expert_config=None)
Definition: __init__.py:99
prompt.CalibrationSettings.json_dumps
def json_dumps(self)
Definition: __init__.py:140