Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
afp.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 import os
4 pbeastDefaultServer = 'https://pc-atlas-www.cern.ch' if os.getenv('PBEAST_SERVER_HTTPS_PROXY', '').startswith('atlasgw') else 'https://atlasop.cern.ch'
5 pbeastServer = os.getenv('PBEAST_SERVER', pbeastDefaultServer)
6 
7 import libpbeastpy; pbeast = libpbeastpy.ServerProxy(pbeastServer)
8 import logging; log = logging.getLogger("DCSCalculator2.variable")
9 
10 from bisect import bisect
11 from collections.abc import Collection, Iterable, Mapping
12 import functools
13 from itertools import chain
14 
15 from DQUtils.events import process_iovs
16 from DQUtils.general import timer
17 from DQUtils.sugar import IOVSet, RANGEIOV_VAL, RunLumi, TimestampType, define_iov_type, make_iov_type
18 
19 from DCSCalculator2 import config
20 from DCSCalculator2.consts import RED, YELLOW, GREEN, GREY, GOOD, BAD, EMPTY
21 from DCSCalculator2.libcore import map_channels
22 from DCSCalculator2.subdetector import DCSC_DefectTranslate_Subdetector
23 from DCSCalculator2.variable import DefectIOV, GoodIOV, DCSC_Variable
24 
25 class DCSC_Variable_With_Mapping(DCSC_Variable):
26  def __init__(self, folder, evaluator, *, mapping=None, **kwargs):
27  super().__init__(folder, evaluator, **kwargs)
28  self.mapping = mapping
29 
30  def read(self, query_range, folder_base, folder_name):
31  result = super().read(query_range, folder_base, folder_name)
32  if self.mapping is not None:
33  result = map_channels(result, self.mapping, folder_name)
34  return result
35 
37  def make_good_iov(self, iov):
38  giov = []
39  for channel, goodness in self.evaluator(iov):
40  current = GoodIOV(iov.since, iov.until, channel, goodness)
41  current._orig_iov = iov
42  giov.append(current)
43  return giov
44 
45  def make_good_iovs(self, iovs):
46  results = []
47  for iov in iovs:
48  results.append(self.make_good_iov(iov))
49  return IOVSet(sum(zip(*results), ())) # Sort by channel first
50 
51 class DCSC_Merged_Variable(DCSC_Variable):
52  def __init__(self, folders, evaluator, *, mapping={}, **kwargs):
53  folder_merge = ','.join(folders)
54 
55  super().__init__(folder_merge, evaluator, **kwargs)
56  self.folder_names = folders
57  self.mapping = mapping
58 
59  def read(self, query_range, folder_base, folder_names):
60  var_iovs = []
61  folders = folder_names.split(',')
62 
63  for folder in folders:
64  iovs = super().read(query_range, folder_base, folder)
65  if folder in self.mapping:
66  iovs = map_channels(iovs, self.mapping[folder], folder)
67  var_iovs.append(iovs)
68 
69  iovs = self.merge_input_variables(*var_iovs)
70 
71  if config.opts.check_input_time:
72  self.print_time_info(iovs)
73 
74  if log.isEnabledFor(logging.INFO):
75  input_hash = hash(iovs)
76  self.input_hashes.append(input_hash)
77  #log.info(" -> Input hash: % 09x (len=%i)", input_hash, len(iovs))
78 
79  return iovs
80 
81  def merge_input_variables(self, *inputs):
82  type_bases = [iovs.iov_type for iovs in inputs]
83  base_names = [base.__name__[:-4] for base in type_bases]
84  attributes = [base.lower() for base in base_names]
85  clazz = make_iov_type('MERGER_OF_' + '_AND_'.join(base_names), tuple(['channel'] + attributes))
86 
87  inputs_by_channel = [iovs.by_channel for iovs in inputs]
88  all_channels = sorted(set(y for x in inputs_by_channel for y in x.keys()))
89 
90  result = []
91  for channel in all_channels:
92  c_inputs = [x[channel] for x in inputs_by_channel]
93  result.extend(iov for iov in self.merge_inputs(clazz, channel, *c_inputs))
94 
95  return IOVSet(result, iov_type=clazz, origin=self.folder_names)
96 
97  def merge_inputs(self, clazz, channel, *inputs):
98  result = [clazz(since, until, channel, *states) for since, until, states in process_iovs(*inputs)]
99  return IOVSet(result, iov_type=clazz, origin=self.folder_names)
100 
101 @define_iov_type
102 def PBeastIOV(channel, value):
103  "Stores the value of an object's attribute queried from pBeast"
104 
105 class TDAQC_Variable(DCSC_Variable):
106  """
107  A variable which reads data from pBeast.
108  """
109  TIME_RATIO = 1e3
110 
111  @staticmethod
112  def timeCOOL2PBeast(timestamp):
113  return int(timestamp/TDAQC_Variable.TIME_RATIO)
114 
115  @staticmethod
116  def timePBeast2COOL(timestamp):
117  return TimestampType(timestamp*TDAQC_Variable.TIME_RATIO)
118 
119  def __init__(self, query, evaluator, *, regex=False, mapping=dict(), force_mapping=False, empty_value=None):
120  super().__init__(query, evaluator)
121  self.regex = regex
122  self.mapping = mapping
123  self.force_mapping = force_mapping
124  self.empty_value = empty_value
125  self.query = query
126  self.partition, self.className, self.attribute, self.path = query.split('.', 3)
127  self.input_hashes = []
128 
129  def __repr__(self):
130  return f"<TDAQCVariable {self.query}>"
131 
132  def read(self, query_range, query, *, regex=False):
133  """
134  Read the relevant data from pBeast for this variable, and convert them to COOL-like format
135  """
136  partition, className, attribute, path = query.split('.', 3)
137 
138  log.info(f"Querying pBeast object{'s using regex' if regex else ''} {query}")
139 
140  since, until = query_range
141  since, until = TDAQC_Variable.timeCOOL2PBeast(since), TDAQC_Variable.timeCOOL2PBeast(until)
142 
143  query_data = pbeast.get_data(partition, className, attribute, path, regex, since, until)
144  data = dict.fromkeys(self.mapping.keys()) if self.force_mapping else dict()
145  if query_data:
146  data.update(query_data[0].data)
147 
148  def instantiate(since, until, channel, value):
149  if isinstance(value, list):
150  value = tuple(value)
151  return PBeastIOV(TDAQC_Variable.timePBeast2COOL(since), TDAQC_Variable.timePBeast2COOL(until), channel, value)
152 
153  iovs = []
154  for channel, entries in data.items():
155  if not entries:
156  iovs.append(PBeastIOV(*query_range, channel, self.empty_value))
157  continue
158  first = entries[0]
159  since = first.ts
160  value = first.value
161  for point in entries:
162  if point.value == value:
163  continue
164  iovs.append(instantiate(since, point.ts, channel, value))
165  since = point.ts
166  value = point.value
167  last = entries[-1]
168  iovs.append(instantiate(since, last.ts, channel, value))
169  iovs = IOVSet(iovs, iov_type=PBeastIOV, origin=query)
170 
171  if log.isEnabledFor(logging.INFO):
172  input_hash = hash(iovs)
173  self.input_hashes.append(input_hash)
174  log.info(" -> Input hash: % 09x (len=%i)", input_hash, len(iovs))
175 
176  return iovs
177 
178  def calculate_good_iovs(self, lbtime, subdetector):
179  """
180  Calculate LB-wise "good" states
181  """
182 
183  self.subdetector = subdetector
184 
185  since, until = lbtime.first, lbtime.last
186  if self.timewise_folder:
187  query_range = RANGEIOV_VAL(since.since, until.until)
188  else:
189  query_range = RANGEIOV_VAL(RunLumi(since.Run, since.LumiBlock),
190  RunLumi(until.Run, until.LumiBlock))
191 
192  # Read the database
193  iovs = self.read(query_range, self.query, regex=self.regex)
194  # Decide the states of the input iovs
195  iovs = self.make_good_iovs(iovs)
196  # Apply a mapping for input channels if necessary
197  iovs = self.map_input_channels(iovs)
198 
199  if self.timewise_folder and not config.opts.timewise:
200  # we might already know the defect mapping
201  with timer("Quantize %s (%i iovs over %i lbs)" %
202  (self.query, len(iovs), len(lbtime))):
203  # Quantize to luminosity block
204  iovs = self.quantize(lbtime, iovs)
205 
206  self.iovs = iovs
207  return self
208 
209  def make_good_iov(self, iov):
210  """
211  Determine if one input iov is good.
212  """
213  giov = GoodIOV(iov.since, iov.until, self.mapping.get(iov.channel, iov.channel), self.evaluator(iov))
214  giov._orig_iov = iov
215  return giov
216 
218  def make_good_iov(self, iov):
219  """
220  Determine if channels in one input iov are good.
221  """
222  giov = []
223  for channel, goodness in self.evaluator(iov):
224  current = GoodIOV(iov.since, iov.until, channel, goodness)
225  current._orig_iov = iov
226  giov.append(current)
227  return giov
228 
229  def make_good_iovs(self, iovs):
230  """
231  Determine whether each iov signifies a good or bad state.
232  """
233  results = []
234  for iov in iovs:
235  results.append(self.make_good_iov(iov))
236  return IOVSet(sum(zip(*results), ())) # Sort by channel first
237 
239  def make_good_iov(self, iov):
240  """
241  Determine if channels in one input iov are good.
242  """
243  giov = []
244  for bit, channel in self.mapping.get(iov.channel, dict()).items():
245  iov_value = (((iov.value >> bit) & 1) == 1) if iov.value is not None else None
246  test_iov = PBeastIOV(iov.since, iov.until, channel, iov_value)
247  current = GoodIOV(iov.since, iov.until, channel, self.evaluator(test_iov))
248  current._orig_iov = iov
249  giov.append(current)
250  return giov
251 
253  def make_good_iov(self, iov):
254  """
255  Determine if channels in one input iov are good.
256  """
257  giov = []
258  for index, channel in self.mapping.get(iov.channel, dict()).items():
259  iov_value = iov.value[index] if iov.value is not None else None
260  test_iov = PBeastIOV(iov.since, iov.until, channel, iov_value)
261  current = GoodIOV(iov.since, iov.until, channel, self.evaluator(test_iov))
262  current._orig_iov = iov
263  giov.append(current)
264  return giov
265 
266 def load_current(filename:str, n_modules:int) -> tuple[list[float],list[tuple[float,...]]]:
267  from datetime import datetime, timezone
268  from pkg_resources import resource_string
269  data = resource_string('DCSCalculator2.subdetectors.data', filename).decode().strip().split('\n')
270  result = {}
271  for line in data:
272  line = line.strip()
273  if not line or line[0] == '#': continue
274  line = line.split()
275  current = tuple(float(x) for x in line[1:])
276  if len(current) != n_modules:
277  log.warning(f"Wrong number of modules ({len(current)}) in resource '{filename}' from {line[0]}. Setting thresholds to 0...")
278  current = (0.,) * n_modules
279  time = datetime.fromisoformat(line[0])
280  if time.tzinfo is None: time = time.replace(tzinfo=timezone.utc)
281  time = time.timestamp()
282  result[time] = current
283  keys, values = zip(*sorted(result.items()))
284  if not values: keys, values = [0.], [(0.,) * n_modules]
285  return (list(keys), list(values))
286 
287 def get_current(data: tuple[list[float],list[tuple[float,...]]], timestamp:float) -> tuple[float, ...]:
288  timestamp = timestamp / 1e9
289  keys, values = data
290  index = max(bisect(keys, timestamp) - 1, 0)
291  return values[index]
292 
293 get_sit_current = functools.partial(get_current, load_current('afp_sit_current.dat', 16))
294 get_tdc_current = functools.partial(get_current, load_current('afp_tdc_current.dat', 4))
295 
296 # DCS channels
297 A_FAR_GARAGE, A_NEAR_GARAGE, C_FAR_GARAGE, C_NEAR_GARAGE = 101, 105, 109, 113
298 A_FAR_SIT_HV, A_NEAR_SIT_HV, C_FAR_SIT_HV, C_NEAR_SIT_HV = 1, 5, 9, 13
299 A_FAR_SIT_LV, A_NEAR_SIT_LV, C_FAR_SIT_LV, C_NEAR_SIT_LV = 21, 25, 29, 33
300 A_FAR_TOF_HV, C_FAR_TOF_HV = 17, 19
301 A_FAR_TOF_LV, C_FAR_TOF_LV = 37, 39
302 
303 # TDAQ channels
304 TTC_RESTART = 1000
305 STOPLESSLY_REMOVED = 5000
306 
307 A_FAR_SIT_DISABLED, A_NEAR_SIT_DISABLED, C_FAR_SIT_DISABLED, C_NEAR_SIT_DISABLED = 1001, 1005, 1009, 1013
308 A_FAR_TOF_DISABLED, C_FAR_TOF_DISABLED = 1017, 1019
309 
310 # Channel names
311 NAMING = ['FSA0', 'FSA1', 'FSA2', 'FSA3',
312  'NSA0', 'NSA1', 'NSA2', 'NSA3',
313  'FSC0', 'FSC1', 'FSC2', 'FSC3',
314  'NSC0', 'NSC1', 'NSC2', 'NSC3',
315  'TDC-A-1', 'TDC-A-2',
316  'TDC-C-1', 'TDC-C-2']
317 
318 # Channel groups
319 GARAGE = [A_FAR_GARAGE, A_NEAR_GARAGE, C_FAR_GARAGE, C_NEAR_GARAGE]
320 SIT_HV = [A_FAR_SIT_HV, A_NEAR_SIT_HV, C_FAR_SIT_HV, C_NEAR_SIT_HV]
321 SIT_LV = [A_FAR_SIT_LV, A_NEAR_SIT_LV, C_FAR_SIT_LV, C_NEAR_SIT_LV]
322 TOF_HV = [A_FAR_TOF_HV, C_FAR_TOF_HV]
323 TOF_LV = [A_FAR_TOF_LV, C_FAR_TOF_LV]
324 
325 SIT_DISABLED = [A_FAR_SIT_DISABLED, A_NEAR_SIT_DISABLED, C_FAR_SIT_DISABLED, C_NEAR_SIT_DISABLED]
326 TOF_DISABLED = [A_FAR_TOF_DISABLED, C_FAR_TOF_DISABLED]
327 
328 # Thresholds
329 SIT_HV_DEAD_BAND = 0.05
330 TOF_HV_DEAD_BAND = 0.90
331 
332 SIT_LV_CURRENT_HIGH = 0.8
333 TOF_HV_CURRENT_LOW = 600
334 
335 def mapChannels(*mapseqArgs: tuple[Collection[int], int]) -> dict[int, int]:
336  return dict(chain(*[zip(channels, range(defectChannel, defectChannel + len(channels))) for channels, defectChannel in mapseqArgs]))
337 
338 def mapTranslatorCounts(countMap:Mapping[int,Iterable[int]]) -> dict[int, range]:
339  return {channel: range(channel, channel + count) for count, channels in countMap.items() for channel in channels}
340 
341 def remove_None(value, default):
342  return value if value is not None else default
343 
344 class AFP(DCSC_DefectTranslate_Subdetector):
345  folder_base = '/AFP/DCS'
346  variables = [
347 
350 
351  # AFP_(A|C)_(FAR|NEAR)_IN_GARAGE
353  'STATION',
354  lambda iov: iov.inphysics is True,
355  mapping = {1: C_FAR_GARAGE, 2: C_NEAR_GARAGE, 3: A_FAR_GARAGE, 4: A_NEAR_GARAGE}
356  ),
357 
358  # AFP_(A|C)_(FAR|NEAR)_SIT_(PARTIALLY|NOT)_OPERATIONAL_LV
360  'SIT/LV',
361  #lambda iov: SIT_LV_CURRENT_LOW <= remove_None(iov.current, 0) <= SIT_LV_CURRENT_HIGH,
362  #lambda iov: SIT_LV_CURRENT_LOW[iov.channel - SIT_LV[0]] <= remove_None(iov.current, 0) <= SIT_LV_CURRENT_HIGH,
363  lambda iov: get_sit_current(iov.since)[iov.channel - SIT_LV[0]] <= remove_None(iov.current, 0) <= SIT_LV_CURRENT_HIGH,
364  mapping = mapChannels(
365  ([ 9, 10, 11, 12], A_FAR_SIT_LV ),
366  ([13, 14, 15, 16], A_NEAR_SIT_LV),
367  ([ 1, 2, 3, 4], C_FAR_SIT_LV ),
368  ([ 5, 6, 7, 8], C_NEAR_SIT_LV)
369  )
370  ),
371 
372  # AFP_(A|C)_(FAR|NEAR)_SIT_(PARTIALLY|NOT)_OPERATIONAL_HV
374  ['SIT/HV', 'SIT/HV_VOLTAGE_SET'],
375  lambda iov: -remove_None(iov.hv.voltage, 0) > iov.hv_voltage_set.voltageSet - SIT_HV_DEAD_BAND,
376  mapping = {
377  'SIT/HV': mapChannels(
378  ([ 6, 7, 1, 2], A_FAR_SIT_HV ),
379  ([ 8, 3, 4, 9], A_NEAR_SIT_HV),
380  ([10, 11, 12, 5], C_FAR_SIT_HV ),
381  ([13, 14, 15, 16], C_NEAR_SIT_HV)),
382  'SIT/HV_VOLTAGE_SET': mapChannels(
383  ([ 1, 2, 3, 4], A_FAR_SIT_HV ),
384  ([ 5, 6, 7, 8], A_NEAR_SIT_HV),
385  ([ 9, 10, 11, 12], C_FAR_SIT_HV ),
386  ([13, 14, 15, 16], C_NEAR_SIT_HV))
387  }
388  ),
389 
390  # AFP_(A|C)_FAR_TOF_NOT_OPERATIONAL_LV
392  'TOF_TDC_CURRENT',
393  lambda iov: [(iov.channel, get_tdc_current(iov.since)[iov.channel - TOF_LV[0]] <= remove_None(iov.hptdc1_current, 0)),
394  (iov.channel + 1, get_tdc_current(iov.since)[iov.channel + 1 - TOF_LV[0]] <= remove_None(iov.hptdc2_current, 0))],
395  mapping = {1: A_FAR_TOF_LV, 2: C_FAR_TOF_LV}
396  ),
397 
398  # AFP_(A|C)_FAR_TOF_NOT_OPERATIONAL_HV
400  ['TOF', 'TOF_PMT_VOLTAGE_SET'],
401  lambda iov: -remove_None(iov.tof.pmt_voltage, 0) > iov.tof_pmt_voltage_set.pmt_voltageSet - TOF_HV_DEAD_BAND and -remove_None(iov.tof.pmt_current, 0) > TOF_HV_CURRENT_LOW,
402  mapping = {
403  'TOF': {1: A_FAR_TOF_HV, 2: C_FAR_TOF_HV},
404  'TOF_PMT_VOLTAGE_SET': {1: A_FAR_TOF_HV, 2: C_FAR_TOF_HV},
405  }
406  ),
407 
408 
411 
412  # AFP_TTC_RESTART
414  'ATLAS.RCStateInfo.state.RunCtrl.AFP',
415  lambda iov: iov.value == 'RUNNING',
416  mapping = {'RunCtrl.AFP': TTC_RESTART}
417  ),
418 
419  # AFP_STOPLESSLY_REMOVED
421  'ATLAS.RODBusyIS.BusyEnabled.Monitoring.afp_rodBusy-VLDB/RODBusy',
422  lambda iov: iov.value is not False,
423  mapping = {'Monitoring.afp_rodBusy-VLDB/RODBusy': {6: STOPLESSLY_REMOVED}}
424  ),
425 
426  # AFP_(A|C)_(FAR|NEAR)_(PARTIALLY|NOT)_OPERATIONAL_TDAQ
428  'ATLAS.RceMonitoring.DisabledPerm.Monitoring.RceMonitoring_RCE[34]',
429  lambda iov: iov.value is not True,
430  regex = True,
431  mapping = {
432  'Monitoring.RceMonitoring_RCE3': mapChannels(([0, 2, 4, 6], A_NEAR_SIT_DISABLED), ([8, 10, 12, 14], A_FAR_SIT_DISABLED), ([9, 11], A_FAR_TOF_DISABLED)),
433  'Monitoring.RceMonitoring_RCE4': mapChannels(([0, 2, 4, 6], C_NEAR_SIT_DISABLED), ([8, 10, 12, 14], C_FAR_SIT_DISABLED), ([9, 11], C_FAR_TOF_DISABLED)),
434  }
435  ),
436  ]
437 
438  equality_breaker = 0.0001
439 
440  dead_fraction_caution = 0 + equality_breaker
441  dead_fraction_bad = 0.25 + equality_breaker
442 
444  1: [*GARAGE, TTC_RESTART, STOPLESSLY_REMOVED, *TOF_HV],
445  2: [*TOF_DISABLED, *TOF_LV],
446  4: [*SIT_DISABLED, *SIT_LV, *SIT_HV],
447  })
448 
449  def merge_variable_states(self, states):
450  """
451  Merge input channel states across variables, taking the worst.
452 
453  Ignore configuration variables and variables without channel.
454  """
455 
456  # Remove variables without channel
457  states = [state for state in states if state and state.channel is not None]
458 
459  # More simplistic way of doing the above, but cannot handle config vars:
460  return min(state.good for state in states) if len(states) > 0 else None
461 
462  def calculate_dead_fraction(self, since, until, output_channel, states, state_iovs):
463  """
464  Calculate the dead fraction and the resulting traffic light code.
465  """
466 
467  n_total = len(states)
468  n_working = states.count(GOOD)
469  n_bad = states.count(BAD)
470  n_unfilled = states.count(EMPTY)
471 
472  assert n_total == len(self.mapping[output_channel])
473  assert n_total - n_working - n_bad - n_unfilled == 0
474 
475  n_config = n_total - n_unfilled
476  dead_fraction = 1. - n_working / n_total
477 
478  code = GREEN
479  if dead_fraction > self.dead_fraction_caution:
480  code = YELLOW
481  if dead_fraction > self.dead_fraction_bad:
482  code = RED
483 
484  if n_unfilled / n_total > self.dead_fraction_caution:
485  code = GREY
486  if n_unfilled and config.opts.mark_unfilled_grey:
487  code = GREY
488 
489  return code, dead_fraction, 0., n_config, n_working
490 
491  @staticmethod
492  def defect_translator(channel, defect_name, selector, comment):
493  def translator_core(iovs):
494  return [DefectIOV(iov.since, iov.until, defect_name, True, comment=comment(iov))
495  for iov in iovs if iov.channel == channel and not iov._is_empty and selector(iov)]
496  return translator_core
497 
498  @staticmethod
499  def defect_combinator(channels, defect_name, selector, naffected, comment):
500  def combinator_core(iovs):
501  result = []
502  channel_iovs = iovs.by_channel
503  defect_iovs = [channel_iovs.get(channel) for channel in channels]
504  for since, until, states in process_iovs(*defect_iovs):
505  matched = [(state, group) for state,group in zip(states,channels) if not state._is_empty and selector(state)]
506  if len(matched) < 2: continue # We need at least two defects
507  bad_channels = {iov.channel - group for state,group in matched for iov in state._orig_iovs if not iov.good}
508  if len(bad_channels) < naffected: continue
509  result.append(DefectIOV(since, until, defect_name, True, comment=comment()))
510  return result
511  return combinator_core
512 
513  @staticmethod
514  def color_selector(color):
515  def selector_core(iov):
516  return iov.Code == color
517  return selector_core
518 
519  @staticmethod
520  def nbad_selector(nbad):
521  if isinstance(nbad, int): nbad = [nbad]
522  def selector_core(iov):
523  return iov.NConfig - iov.NWorking in nbad
524  return selector_core
525 
526  def __init__(self, *args, **kwargs):
527  super(AFP, self).__init__(*args, **kwargs)
528  self.translators = [
529  AFP.defect_translator(*cdsc)
530  for cdsc in [
531 
534  (A_FAR_GARAGE, 'AFP_A_FAR_IN_GARAGE', AFP.color_selector(RED), AFP.comment_GARAGE),
535  (A_NEAR_GARAGE, 'AFP_A_NEAR_IN_GARAGE', AFP.color_selector(RED), AFP.comment_GARAGE),
536  (C_FAR_GARAGE, 'AFP_C_FAR_IN_GARAGE', AFP.color_selector(RED), AFP.comment_GARAGE),
537  (C_NEAR_GARAGE, 'AFP_C_NEAR_IN_GARAGE', AFP.color_selector(RED), AFP.comment_GARAGE),
538 
539  (A_FAR_SIT_HV, 'AFP_A_FAR_SIT_PARTIALLY_OPERATIONAL_HV', AFP.nbad_selector([1]), AFP.comment_SIT_HV),
540  (A_NEAR_SIT_HV, 'AFP_A_NEAR_SIT_PARTIALLY_OPERATIONAL_HV', AFP.nbad_selector([1]), AFP.comment_SIT_HV),
541  (C_FAR_SIT_HV, 'AFP_C_FAR_SIT_PARTIALLY_OPERATIONAL_HV', AFP.nbad_selector([1]), AFP.comment_SIT_HV),
542  (C_NEAR_SIT_HV, 'AFP_C_NEAR_SIT_PARTIALLY_OPERATIONAL_HV', AFP.nbad_selector([1]), AFP.comment_SIT_HV),
543  (A_FAR_SIT_HV, 'AFP_A_FAR_SIT_NOT_OPERATIONAL_HV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_HV),
544  (A_NEAR_SIT_HV, 'AFP_A_NEAR_SIT_NOT_OPERATIONAL_HV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_HV),
545  (C_FAR_SIT_HV, 'AFP_C_FAR_SIT_NOT_OPERATIONAL_HV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_HV),
546  (C_NEAR_SIT_HV, 'AFP_C_NEAR_SIT_NOT_OPERATIONAL_HV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_HV),
547 
548  (A_FAR_SIT_LV, 'AFP_A_FAR_SIT_PARTIALLY_OPERATIONAL_LV', AFP.nbad_selector([1]), AFP.comment_SIT_LV),
549  (A_NEAR_SIT_LV, 'AFP_A_NEAR_SIT_PARTIALLY_OPERATIONAL_LV', AFP.nbad_selector([1]), AFP.comment_SIT_LV),
550  (C_FAR_SIT_LV, 'AFP_C_FAR_SIT_PARTIALLY_OPERATIONAL_LV', AFP.nbad_selector([1]), AFP.comment_SIT_LV),
551  (C_NEAR_SIT_LV, 'AFP_C_NEAR_SIT_PARTIALLY_OPERATIONAL_LV', AFP.nbad_selector([1]), AFP.comment_SIT_LV),
552  (A_FAR_SIT_LV, 'AFP_A_FAR_SIT_NOT_OPERATIONAL_LV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_LV),
553  (A_NEAR_SIT_LV, 'AFP_A_NEAR_SIT_NOT_OPERATIONAL_LV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_LV),
554  (C_FAR_SIT_LV, 'AFP_C_FAR_SIT_NOT_OPERATIONAL_LV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_LV),
555  (C_NEAR_SIT_LV, 'AFP_C_NEAR_SIT_NOT_OPERATIONAL_LV', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_LV),
556  (A_FAR_SIT_LV, 'AFP_A_FAR_SIT_NOT_OPERATIONAL_LV_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_LV),
557  (A_NEAR_SIT_LV, 'AFP_A_NEAR_SIT_NOT_OPERATIONAL_LV_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_LV),
558  (C_FAR_SIT_LV, 'AFP_C_FAR_SIT_NOT_OPERATIONAL_LV_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_LV),
559  (C_NEAR_SIT_LV, 'AFP_C_NEAR_SIT_NOT_OPERATIONAL_LV_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_LV),
560 
561  (A_FAR_TOF_LV, 'AFP_A_FAR_TOF_NOT_OPERATIONAL_LV', AFP.color_selector(RED), AFP.comment_TOF_LV),
562  (C_FAR_TOF_LV, 'AFP_C_FAR_TOF_NOT_OPERATIONAL_LV', AFP.color_selector(RED), AFP.comment_TOF_LV),
563 
564  (A_FAR_TOF_HV, 'AFP_A_FAR_TOF_NOT_OPERATIONAL_HV', AFP.color_selector(RED), AFP.comment_TOF_HV),
565  (C_FAR_TOF_HV, 'AFP_C_FAR_TOF_NOT_OPERATIONAL_HV', AFP.color_selector(RED), AFP.comment_TOF_HV),
566 
567 
570  (TTC_RESTART, 'AFP_TTC_RESTART', AFP.color_selector(RED), AFP.comment_TTC_RESTART),
571  (STOPLESSLY_REMOVED, 'AFP_STOPLESSLY_REMOVED', AFP.color_selector(RED), AFP.comment_STOPLESSLY_REMOVED),
572 
573  (A_FAR_SIT_DISABLED, 'AFP_A_FAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', AFP.nbad_selector([1]), AFP.comment_SIT_DISABLED),
574  (A_NEAR_SIT_DISABLED, 'AFP_A_NEAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', AFP.nbad_selector([1]), AFP.comment_SIT_DISABLED),
575  (C_FAR_SIT_DISABLED, 'AFP_C_FAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', AFP.nbad_selector([1]), AFP.comment_SIT_DISABLED),
576  (C_NEAR_SIT_DISABLED, 'AFP_C_NEAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', AFP.nbad_selector([1]), AFP.comment_SIT_DISABLED),
577  (A_FAR_SIT_DISABLED, 'AFP_A_FAR_SIT_NOT_OPERATIONAL_TDAQ', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_DISABLED),
578  (A_NEAR_SIT_DISABLED, 'AFP_A_NEAR_SIT_NOT_OPERATIONAL_TDAQ', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_DISABLED),
579  (C_FAR_SIT_DISABLED, 'AFP_C_FAR_SIT_NOT_OPERATIONAL_TDAQ', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_DISABLED),
580  (C_NEAR_SIT_DISABLED, 'AFP_C_NEAR_SIT_NOT_OPERATIONAL_TDAQ', AFP.nbad_selector([2, 3, 4]), AFP.comment_SIT_DISABLED),
581  (A_FAR_SIT_DISABLED, 'AFP_A_FAR_SIT_NOT_OPERATIONAL_TDAQ_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_DISABLED),
582  (A_NEAR_SIT_DISABLED, 'AFP_A_NEAR_SIT_NOT_OPERATIONAL_TDAQ_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_DISABLED),
583  (C_FAR_SIT_DISABLED, 'AFP_C_FAR_SIT_NOT_OPERATIONAL_TDAQ_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_DISABLED),
584  (C_NEAR_SIT_DISABLED, 'AFP_C_NEAR_SIT_NOT_OPERATIONAL_TDAQ_3PLANES', AFP.nbad_selector([3, 4]), AFP.comment_SIT_DISABLED),
585 
586  (A_FAR_TOF_DISABLED, 'AFP_A_FAR_TOF_NOT_OPERATIONAL_TDAQ', AFP.color_selector(RED), AFP.comment_TOF_DISABLED),
587  (C_FAR_TOF_DISABLED, 'AFP_C_FAR_TOF_NOT_OPERATIONAL_TDAQ', AFP.color_selector(RED), AFP.comment_TOF_DISABLED),
588  ]
589  ] + [
590  AFP.defect_combinator(*cdsac)
591  for cdsac in [
592  ([A_FAR_SIT_LV, A_FAR_SIT_DISABLED], 'AFP_A_FAR_SIT_NOT_OPERATIONAL', AFP.nbad_selector([1]), 2, AFP.comment_SIT_COMBINATION),
593  ([A_NEAR_SIT_LV, A_NEAR_SIT_DISABLED], 'AFP_A_NEAR_SIT_NOT_OPERATIONAL', AFP.nbad_selector([1]), 2, AFP.comment_SIT_COMBINATION),
594  ([C_FAR_SIT_LV, C_FAR_SIT_DISABLED], 'AFP_C_FAR_SIT_NOT_OPERATIONAL', AFP.nbad_selector([1]), 2, AFP.comment_SIT_COMBINATION),
595  ([C_NEAR_SIT_LV, C_NEAR_SIT_DISABLED], 'AFP_C_NEAR_SIT_NOT_OPERATIONAL', AFP.nbad_selector([1]), 2, AFP.comment_SIT_COMBINATION),
596  ([A_FAR_SIT_LV, A_FAR_SIT_DISABLED], 'AFP_A_FAR_SIT_NOT_OPERATIONAL_3PLANES', AFP.nbad_selector([1, 2]), 3, AFP.comment_SIT_COMBINATION),
597  ([A_NEAR_SIT_LV, A_NEAR_SIT_DISABLED], 'AFP_A_NEAR_SIT_NOT_OPERATIONAL_3PLANES', AFP.nbad_selector([1, 2]), 3, AFP.comment_SIT_COMBINATION),
598  ([C_FAR_SIT_LV, C_FAR_SIT_DISABLED], 'AFP_C_FAR_SIT_NOT_OPERATIONAL_3PLANES', AFP.nbad_selector([1, 2]), 3, AFP.comment_SIT_COMBINATION),
599  ([C_NEAR_SIT_LV, C_NEAR_SIT_DISABLED], 'AFP_C_NEAR_SIT_NOT_OPERATIONAL_3PLANES', AFP.nbad_selector([1, 2]), 3, AFP.comment_SIT_COMBINATION),
600  ]
601  ]
602 
603 
606 
607  @staticmethod
608  def comment_GARAGE(iov):
609  return 'Station not in physics'
610 
611  @staticmethod
612  def comment_SIT_LV(iov):
613  return AFP.comment_planes(iov, 'out of nominal current', SIT_LV[0])
614 
615  @staticmethod
616  def comment_SIT_HV(iov):
617  return AFP.comment_planes(iov, 'out of nominal voltage', SIT_HV[0])
618 
619  @staticmethod
620  def comment_TOF_LV(iov):
621  return AFP.comment_tof_tdc(iov, 'with too low current', TOF_LV[0])
622 
623  @staticmethod
624  def comment_TOF_HV(iov):
625  return 'ToF PMT out of nominal voltage'
626 
627 
630 
631  @staticmethod
633  return 'AFP not in the RUNNING state'
634 
635  @staticmethod
637  return 'AFP stoplessly removed from the run'
638 
639  @staticmethod
641  return AFP.comment_planes(iov, 'removed from readout', SIT_DISABLED[0])
642 
643  @staticmethod
645  return AFP.comment_tof_tdc(iov, 'removed from readout', TOF_DISABLED[0])
646 
647 
650 
651  @staticmethod
653  return "Combination of 'partially operational' defects"
654 
655 
658 
659  @staticmethod
660  def comment_planes(iov, message, defect_offset=None, module_tagger=None):
661  return AFP.comment_device(iov, 'SiT plane', message, defect_offset, module_tagger)
662 
663  @staticmethod
664  def comment_tof_tdc(iov, message, defect_offset=None, module_tagger=None):
665  if defect_offset is not None: defect_offset -= 16
666  return AFP.comment_device(iov, 'ToF TDC', message, defect_offset, module_tagger)
667 
668  @staticmethod
669  def comment_device(iov, device, message, defect_offset=None, module_tagger=None):
670  count = iov.NConfig - iov.NWorking
671  if count != 1:
672  device += 's'
673  comment = f"{count} {device} {message}"
674  if defect_offset is None:
675  return comment
676  iovs = sorted([orig for orig in iov._orig_iovs if orig.good is False], key=lambda x: x.channel)
677  list = [NAMING[orig.channel - defect_offset] for orig in iovs]
678  if module_tagger is not None:
679  list = [f"{module} {module_tagger(orig)}" for module,orig in zip(list,iovs)]
680  return comment + f" ({', '.join(list)})"
python.subdetectors.afp.AFP
Definition: afp.py:344
python.libcore.map_channels
def map_channels(iovs, mapping, folder)
Definition: libcore.py:39
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
AtlasMcWeight::decode
double decode(number_type binnedWeight)
Convert weight from unsigned to double.
Definition: AtlasMcWeight.cxx:32
python.subdetectors.afp.AFP.calculate_dead_fraction
def calculate_dead_fraction(self, since, until, output_channel, states, state_iovs)
Definition: afp.py:462
python.subdetectors.afp.TDAQC_Variable.calculate_good_iovs
def calculate_good_iovs(self, lbtime, subdetector)
Definition: afp.py:178
python.subdetectors.afp.DCSC_Merged_Variable
Definition: afp.py:51
runLayerRecalibration.chain
chain
Definition: runLayerRecalibration.py:175
python.subdetectors.afp.AFP.comment_SIT_HV
def comment_SIT_HV(iov)
Definition: afp.py:616
python.subdetectors.afp.AFP.comment_STOPLESSLY_REMOVED
def comment_STOPLESSLY_REMOVED(iov)
Definition: afp.py:636
python.subdetectors.afp.AFP.comment_TTC_RESTART
def comment_TTC_RESTART(iov)
TDAQ defects.
Definition: afp.py:632
python.subdetectors.afp.mapChannels
dict[int, int] mapChannels(*tuple[Collection[int], int] mapseqArgs)
Definition: afp.py:335
python.subdetectors.afp.TDAQC_Array_Variable.make_good_iov
def make_good_iov(self, iov)
Definition: afp.py:253
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
python.subdetectors.afp.DCSC_Multi_Channel_Variable
Definition: afp.py:36
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
python.sugar.iovtype.RANGEIOV_VAL
def RANGEIOV_VAL()
Definition: iovtype.py:153
python.subdetectors.afp.DCSC_Merged_Variable.merge_input_variables
def merge_input_variables(self, *inputs)
Definition: afp.py:81
python.subdetectors.afp.TDAQC_Variable.iovs
iovs
Definition: afp.py:206
python.subdetectors.afp.TDAQC_Variable
Definition: afp.py:105
python.subdetectors.afp.AFP.mapping
mapping
Definition: afp.py:443
python.subdetectors.afp.TDAQC_Variable.path
path
Definition: afp.py:126
python.subdetectors.afp.TDAQC_Variable.input_hashes
input_hashes
Definition: afp.py:127
python.variable.DefectIOV
def DefectIOV(channel, present, comment)
Definition: variable.py:26
python.subdetectors.afp.AFP.translators
translators
Definition: afp.py:528
python.subdetectors.afp.TDAQC_Variable.read
def read(self, query_range, query, *regex=False)
Definition: afp.py:132
python.subdetectors.afp.AFP.comment_TOF_LV
def comment_TOF_LV(iov)
Definition: afp.py:620
python.subdetectors.afp.TDAQC_Variable.timePBeast2COOL
def timePBeast2COOL(timestamp)
Definition: afp.py:116
python.subdetectors.afp.TDAQC_Variable.empty_value
empty_value
Definition: afp.py:124
python.subdetectors.afp.get_sit_current
get_sit_current
Definition: afp.py:293
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.subdetectors.afp.AFP.comment_tof_tdc
def comment_tof_tdc(iov, message, defect_offset=None, module_tagger=None)
Definition: afp.py:664
python.subdetectors.afp.TDAQC_Multi_Channel_Variable
Definition: afp.py:217
python.utils.AtlRunQueryTimer.timer
def timer(name, disabled=False)
Definition: AtlRunQueryTimer.py:86
python.subdetectors.afp.TDAQC_Array_Variable
Definition: afp.py:252
python.variable.GoodIOV
def GoodIOV(channel, good)
Definition: variable.py:18
python.subdetectors.afp.load_current
tuple[list[float], list[tuple[float,...]]] load_current(str filename, int n_modules)
Definition: afp.py:266
python.sugar.runlumi.RunLumi
RunLumi
Definition: runlumi.py:131
python.subdetectors.afp.DCSC_Merged_Variable.__init__
def __init__(self, folders, evaluator, *mapping={}, **kwargs)
Definition: afp.py:52
python.subdetectors.afp.TDAQC_Variable.__init__
def __init__(self, query, evaluator, *regex=False, mapping=dict(), force_mapping=False, empty_value=None)
Definition: afp.py:119
python.subdetectors.afp.TDAQC_Variable.make_good_iov
def make_good_iov(self, iov)
Definition: afp.py:209
python.subdetectors.afp.TDAQC_Multi_Channel_Variable.make_good_iovs
def make_good_iovs(self, iovs)
Definition: afp.py:229
python.subdetectors.afp.DCSC_Multi_Channel_Variable.make_good_iov
def make_good_iov(self, iov)
Definition: afp.py:37
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
python.subdetectors.afp.DCSC_Merged_Variable.folder_names
folder_names
Definition: afp.py:56
python.subdetectors.afp.AFP.color_selector
def color_selector(color)
Definition: afp.py:514
python.subdetectors.afp.AFP.comment_TOF_DISABLED
def comment_TOF_DISABLED(iov)
Definition: afp.py:644
python.subdetectors.afp.AFP.comment_planes
def comment_planes(iov, message, defect_offset=None, module_tagger=None)
Comment templates.
Definition: afp.py:660
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
python.subdetectors.afp.DCSC_Merged_Variable.read
def read(self, query_range, folder_base, folder_names)
Definition: afp.py:59
python.subdetectors.afp.AFP.dead_fraction_caution
int dead_fraction_caution
Definition: afp.py:440
python.subdetectors.afp.TDAQC_Variable.subdetector
subdetector
Definition: afp.py:183
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.subdetectors.afp.AFP.__init__
def __init__(self, *args, **kwargs)
Definition: afp.py:526
python.subdetectors.afp.AFP.defect_translator
def defect_translator(channel, defect_name, selector, comment)
Definition: afp.py:492
python.subdetectors.afp.TDAQC_Variable.__repr__
def __repr__(self)
Definition: afp.py:129
python.subdetectors.afp.PBeastIOV
def PBeastIOV(channel, value)
Definition: afp.py:102
python.events.process_iovs
def process_iovs(*iovsets)
Definition: events.py:30
python.subdetectors.afp.AFP.comment_SIT_DISABLED
def comment_SIT_DISABLED(iov)
Definition: afp.py:640
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
CaloCondBlobAlgs_fillNoiseFromASCII.comment
string comment
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:27
python.subdetectors.afp.AFP.comment_SIT_COMBINATION
def comment_SIT_COMBINATION()
Combination defects.
Definition: afp.py:652
python.subdetectors.afp.TDAQC_Variable.query
query
Definition: afp.py:125
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.subdetectors.afp.DCSC_Multi_Channel_Variable.make_good_iovs
def make_good_iovs(self, iovs)
Definition: afp.py:45
python.subdetectors.afp.AFP.comment_TOF_HV
def comment_TOF_HV(iov)
Definition: afp.py:624
python.subdetectors.afp.DCSC_Merged_Variable.mapping
mapping
Definition: afp.py:57
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.subdetectors.afp.DCSC_Variable_With_Mapping.mapping
mapping
Definition: afp.py:28
python.subdetectors.afp.DCSC_Variable_With_Mapping
Definition: afp.py:25
python.subdetectors.afp.TDAQC_Variable.mapping
mapping
Definition: afp.py:122
python.subdetectors.afp.TDAQC_Variable.timeCOOL2PBeast
def timeCOOL2PBeast(timestamp)
Definition: afp.py:112
python.subdetectors.afp.AFP.comment_SIT_LV
def comment_SIT_LV(iov)
Definition: afp.py:612
python.subdetectors.afp.DCSC_Variable_With_Mapping.__init__
def __init__(self, folder, evaluator, *mapping=None, **kwargs)
Definition: afp.py:26
python.subdetectors.afp.mapTranslatorCounts
dict[int, range] mapTranslatorCounts(Mapping[int, Iterable[int]] countMap)
Definition: afp.py:338
python.selector.AtlRunQuerySelectorLhcOlc.selector
selector
Definition: AtlRunQuerySelectorLhcOlc.py:611
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
python.subdetectors.afp.AFP.dead_fraction_bad
float dead_fraction_bad
Definition: afp.py:441
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
python.subdetectors.afp.AFP.nbad_selector
def nbad_selector(nbad)
Definition: afp.py:520
python.subdetectors.afp.get_current
tuple[float,...] get_current(tuple[list[float], list[tuple[float,...]]] data, float timestamp)
Definition: afp.py:287
python.subdetectors.afp.get_tdc_current
get_tdc_current
Definition: afp.py:294
python.subdetectors.afp.AFP.defect_combinator
def defect_combinator(channels, defect_name, selector, naffected, comment)
Definition: afp.py:499
python.subdetectors.afp.DCSC_Variable_With_Mapping.read
def read(self, query_range, folder_base, folder_name)
Definition: afp.py:30
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.subdetectors.afp.TDAQC_Bit_Flag_Variable
Definition: afp.py:238
python.sugar.iovtype.make_iov_type
def make_iov_type(name, variables, bases=(IOVType,), _memoized={})
Definition: iovtype.py:114
python.subdetectors.afp.TDAQC_Multi_Channel_Variable.make_good_iov
def make_good_iov(self, iov)
Definition: afp.py:218
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:798
python.subdetectors.afp.TDAQC_Variable.force_mapping
force_mapping
Definition: afp.py:123
python.subdetectors.afp.AFP.comment_GARAGE
def comment_GARAGE(iov)
DCS defects.
Definition: afp.py:608
python.subdetectors.afp.TDAQC_Variable.regex
regex
Definition: afp.py:121
python.subdetectors.afp.remove_None
def remove_None(value, default)
Definition: afp.py:341
python.subdetectors.afp.TDAQC_Bit_Flag_Variable.make_good_iov
def make_good_iov(self, iov)
Definition: afp.py:239
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.subdetectors.afp.AFP.comment_device
def comment_device(iov, device, message, defect_offset=None, module_tagger=None)
Definition: afp.py:669
python.subdetectors.afp.DCSC_Merged_Variable.merge_inputs
def merge_inputs(self, clazz, channel, *inputs)
Definition: afp.py:97
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65
python.subdetectors.afp.AFP.merge_variable_states
def merge_variable_states(self, states)
Definition: afp.py:449