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)
7 import libpbeastpy; pbeast = libpbeastpy.ServerProxy(pbeastServer)
8 import logging; log = logging.getLogger(
"DCSCalculator2.variable")
10 from itertools
import chain, combinations
12 from DQUtils.events
import process_iovs
13 from DQUtils.general
import timer
14 from DQUtils.sugar
import IOVSet, RANGEIOV_VAL, RunLumi, TimestampType, define_iov_type, make_iov_type
16 from DCSCalculator2
import config
17 from DCSCalculator2.consts
import RED, YELLOW
18 from DCSCalculator2.libcore
import map_channels
19 from DCSCalculator2.subdetector
import DCSC_DefectTranslate_Subdetector
20 from DCSCalculator2.variable
import DefectIOV, GoodIOV, DCSC_Variable
23 def __init__(self, folder, evaluator, *, mapping=None, **kwargs):
24 super().
__init__(folder, evaluator, **kwargs)
27 def read(self, query_range, folder_base, folder_name):
28 result = super().
read(query_range, folder_base, folder_name)
34 def __init__(self, folders, evaluator, *, mapping={}, **kwargs):
35 folder_merge =
','.
join(folders)
37 super().
__init__(folder_merge, evaluator, **kwargs)
42 for var
in self.variables:
43 if var.folder_name == name:
45 raise RuntimeError(
"Folder '%s' not found" % name)
47 def read(self, query_range, folder_base, folder_names):
49 folders = folder_names.split(
',')
51 for folder
in folders:
52 iovs = super().
read(query_range, folder_base, folder)
59 if config.opts.check_input_time:
60 self.print_time_info(iovs)
62 if log.isEnabledFor(logging.INFO):
63 input_hash =
hash(iovs)
64 self.input_hashes.
append(input_hash)
70 type_bases = [iovs.iov_type
for iovs
in inputs]
71 base_names = [base.__name__[:-4]
for base
in type_bases]
72 attributes = [base.lower()
for base
in base_names]
73 clazz =
make_iov_type(
'MERGER_OF_' +
'_AND_'.
join(base_names), tuple([
'channel'] + attributes))
75 inputs_by_channel = [iovs.by_channel
for iovs
in inputs]
76 all_channels =
sorted(
set(y
for x
in inputs_by_channel
for y
in x.keys()))
79 for channel
in all_channels:
80 c_inputs = [x[channel]
for x
in inputs_by_channel]
81 result.extend(iov
for iov
in self.
merge_inputs(clazz, channel, *c_inputs))
83 return IOVSet(result, iov_type=clazz, origin=self.
folder_names)
86 result = [clazz(since, until, channel, *states)
for since, until, states
in process_iovs(*inputs)]
87 return IOVSet(result, iov_type=clazz, origin=self.
folder_names)
91 "Stores the value of an object's attribute queried from pBeast"
93 class TDAQC_Variable(DCSC_Variable):
95 A variable which reads data from pBeast.
101 return int(timestamp/TDAQC_Variable.TIME_RATIO)
105 return TimestampType(timestamp*TDAQC_Variable.TIME_RATIO)
107 def __init__(self, query, evaluator, *, regex=False, mapping=dict(), force_mapping=
False, empty_value=
None):
114 self.partition, self.className, self.attribute, self.
path = query.split(
'.', 3)
118 return f
"<TDAQCVariable {self.query}>"
120 def read(self, query_range, query, *, regex=False):
122 Read the relevant data from pBeast for this variable, and convert them to COOL-like format
124 partition, className, attribute, path = query.split(
'.', 3)
126 log.info(f
"Querying pBeast object{'s using regex' if regex else ''} {query}")
128 since, until = query_range
129 since, until = TDAQC_Variable.timeCOOL2PBeast(since), TDAQC_Variable.timeCOOL2PBeast(until)
131 query_data = pbeast.get_data(partition, className, attribute, path, regex, since, until)
134 data.update(query_data[0].data)
136 def instantiate(since, until, channel, value):
137 if isinstance(value, list):
139 return PBeastIOV(TDAQC_Variable.timePBeast2COOL(since), TDAQC_Variable.timePBeast2COOL(until), channel, value)
142 for channel, entries
in data.items():
149 for point
in entries:
150 if point.value == value:
152 iovs.append(instantiate(since, point.ts, channel, value))
156 iovs.append(instantiate(since, last.ts, channel, value))
157 iovs = IOVSet(iovs, iov_type=PBeastIOV, origin=query)
159 if log.isEnabledFor(logging.INFO):
160 input_hash =
hash(iovs)
162 log.info(
" -> Input hash: % 09x (len=%i)", input_hash, len(iovs))
168 Calculate LB-wise "good" states
173 since, until = lbtime.first, lbtime.last
174 if self.timewise_folder:
178 RunLumi(until.Run, until.LumiBlock))
183 iovs = self.make_good_iovs(iovs)
185 iovs = self.map_input_channels(iovs)
187 if self.timewise_folder
and not config.opts.timewise:
189 with timer(
"Quantize %s (%i iovs over %i lbs)" %
190 (self.
query, len(iovs), len(lbtime))):
192 iovs = self.quantize(lbtime, iovs)
199 Determine if one input iov is good.
201 giov =
GoodIOV(iov.since, iov.until, self.
mapping.
get(iov.channel, iov.channel), self.evaluator(iov))
208 Determine if channels in one input iov are good.
211 for channel, goodness
in self.evaluator(iov):
212 current =
GoodIOV(iov.since, iov.until, channel, goodness)
213 current._orig_iov = iov
219 Determine whether each iov signifies a good or bad state.
224 return IOVSet(
sum(zip(*results), ()))
229 Determine if channels in one input iov are good.
233 iov_value = (((iov.value >> bit) & 1) == 1)
if iov.value
is not None else None
234 test_iov =
PBeastIOV(iov.since, iov.until, channel, iov_value)
235 current =
GoodIOV(iov.since, iov.until, channel, self.evaluator(test_iov))
236 current._orig_iov = iov
243 Determine if channels in one input iov are good.
247 iov_value = iov.value[index]
if iov.value
is not None else None
248 test_iov =
PBeastIOV(iov.since, iov.until, channel, iov_value)
249 current =
GoodIOV(iov.since, iov.until, channel, self.evaluator(test_iov))
250 current._orig_iov = iov
255 A_FAR_GARAGE, A_NEAR_GARAGE, C_FAR_GARAGE, C_NEAR_GARAGE = 101, 105, 109, 113
256 A_FAR_SIT_HV, A_NEAR_SIT_HV, C_FAR_SIT_HV, C_NEAR_SIT_HV = 1, 5, 9, 13
257 A_FAR_SIT_LV, A_NEAR_SIT_LV, C_FAR_SIT_LV, C_NEAR_SIT_LV = 21, 25, 29, 33
258 A_FAR_TOF_HV, C_FAR_TOF_HV = 51, 59
259 A_FAR_TOF_LV, C_FAR_TOF_LV = 71, 79
263 STOPLESSLY_REMOVED = 5000
265 A_FAR_SIT_DISABLED, A_NEAR_SIT_DISABLED, C_FAR_SIT_DISABLED, C_NEAR_SIT_DISABLED = 1001, 1005, 1009, 1013
266 A_FAR_TOF_DISABLED, C_FAR_TOF_DISABLED = 1051, 1059
269 GARAGE = [A_FAR_GARAGE, A_NEAR_GARAGE, C_FAR_GARAGE, C_NEAR_GARAGE]
270 SIT_HV = [A_FAR_SIT_HV, A_NEAR_SIT_HV, C_FAR_SIT_HV, C_NEAR_SIT_HV]
271 SIT_LV = [A_FAR_SIT_LV, A_NEAR_SIT_LV, C_FAR_SIT_LV, C_NEAR_SIT_LV]
272 TOF_HV = [A_FAR_TOF_HV, C_FAR_TOF_HV]
273 TOF_LV = [A_FAR_TOF_LV, C_FAR_TOF_LV]
275 SIT_DISABLED = [A_FAR_SIT_DISABLED, A_NEAR_SIT_DISABLED, C_FAR_SIT_DISABLED, C_NEAR_SIT_DISABLED]
276 TOF_DISABLED = [A_FAR_TOF_DISABLED, C_FAR_TOF_DISABLED]
279 SIT_HV_DEAD_BAND = 0.05
280 TOF_HV_DEAD_BAND = 0.90
282 SIT_LV_CURRENT_LOW, SIT_LV_CURRENT_HIGH = 0.4, 0.6
283 TOF_HV_CURRENT_LOW = 600
284 TOF_LV_CURRENT_LOW = 1
287 return dict(
chain(*[zip(channels,
range(defectChannel, defectChannel + len(channels)))
for channels, defectChannel
in mapseqArgs]))
290 return {channel:
range(channel, channel + count)
for count, channels
in countMap.items()
for channel
in channels}
293 return value
if value
is not None else default
295 class AFP(DCSC_DefectTranslate_Subdetector):
296 folder_base =
'/AFP/DCS'
305 lambda iov: iov.inphysics
is True,
306 mapping = {1: C_FAR_GARAGE, 2: C_NEAR_GARAGE, 3: A_FAR_GARAGE, 4: A_NEAR_GARAGE}
312 lambda iov: SIT_LV_CURRENT_LOW <=
remove_None(iov.current, 0) <= SIT_LV_CURRENT_HIGH,
314 ([ 9, 10, 11, 12], A_FAR_SIT_LV ),
315 ([13, 14, 15, 16], A_NEAR_SIT_LV),
316 ([ 1, 2, 3, 4], C_FAR_SIT_LV ),
317 ([ 5, 6, 7, 8], C_NEAR_SIT_LV)
323 [
'SIT/HV',
'SIT/HV_VOLTAGE_SET'],
324 lambda iov: -
remove_None(iov.hv.voltage, 0) > iov.hv_voltage_set.voltageSet - SIT_HV_DEAD_BAND,
327 ([ 6, 7, 1, 2], A_FAR_SIT_HV ),
328 ([ 8, 3, 4, 9], A_NEAR_SIT_HV),
329 ([10, 11, 12, 5], C_FAR_SIT_HV ),
330 ([13, 14, 15, 16], C_NEAR_SIT_HV)),
332 ([ 1, 2, 3, 4], A_FAR_SIT_HV ),
333 ([ 5, 6, 7, 8], A_NEAR_SIT_HV),
334 ([ 9, 10, 11, 12], C_FAR_SIT_HV ),
335 ([13, 14, 15, 16], C_NEAR_SIT_HV))
342 lambda iov: TOF_LV_CURRENT_LOW <=
remove_None(iov.hptdc1_current, 0)
and TOF_LV_CURRENT_LOW <=
remove_None(iov.hptdc2_current, 0),
343 mapping = {1: A_FAR_TOF_LV, 2: C_FAR_TOF_LV}
348 [
'TOF',
'TOF_PMT_VOLTAGE_SET'],
349 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,
351 'TOF': {1: A_FAR_TOF_HV, 2: C_FAR_TOF_HV},
352 'TOF_PMT_VOLTAGE_SET': {1: A_FAR_TOF_HV, 2: C_FAR_TOF_HV},
362 'ATLAS.RCStateInfo.state.RunCtrl.AFP',
363 lambda iov: iov.value ==
'RUNNING',
364 mapping = {
'RunCtrl.AFP': TTC_RESTART}
369 'ATLAS.RODBusyIS.BusyEnabled.Monitoring.afp_rodBusy-VLDB/RODBusy',
370 lambda iov: iov.value
is not False,
371 mapping = {
'Monitoring.afp_rodBusy-VLDB/RODBusy': {6: STOPLESSLY_REMOVED}}
376 'ATLAS.RceMonitoring.DisabledPerm.Monitoring.RceMonitoring_RCE[34]',
377 lambda iov: iov.value
is not True,
380 '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)),
381 '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)),
386 equality_breaker = 0.0001
388 dead_fraction_caution = 0 + equality_breaker
389 dead_fraction_bad = 0.25 + equality_breaker
392 1: [*GARAGE, TTC_RESTART, STOPLESSLY_REMOVED, *TOF_LV, *TOF_HV],
394 4: [*SIT_DISABLED, *SIT_LV, *SIT_HV],
399 Merge input channel states across variables, taking the worst.
401 Ignore configuration variables and variables without channel.
405 states = [state
for state
in states
if state
and state.channel
is not None]
408 return min(state.good
for state
in states)
if len(states) > 0
else None
412 def translator_core(iovs):
413 return [
DefectIOV(iov.since, iov.until, defect_name,
True,
415 for iov
in iovs
if iov.channel == channel
416 and iov.Code == color]
417 return translator_core
421 def combinator_core(iovs):
423 channel_diffs = [channels[0] - channel
for channel
in channels]
424 channel_iovs = iovs.by_channel
425 defect_iovs = [channel_iovs.get(channel)
for channel
in channels]
427 matched = [state
for state
in states
if state.Code == code]
428 if len(matched) < 2:
continue
429 matched_diffs = [diff
for state,diff
in zip(states, channel_diffs)
if state.Code == code]
430 bad_channels = [{iov.channel + diff
for iov
in state._orig_iovs
if not iov.good}
for state,diff
in zip(matched,matched_diffs)]
431 if all(a.issubset(b)
or a.issuperset(b)
for a,b
in combinations(bad_channels, 2)):
continue
432 result.append(
DefectIOV(since, until, defect_name,
True, comment=
comment()))
434 return combinator_core
437 super(AFP, self).
__init__(*args, **kwargs)
439 AFP.color_to_defect_translator(*cdcc)
444 (A_FAR_GARAGE,
'AFP_A_FAR_IN_GARAGE', RED, AFP.comment_GARAGE),
445 (A_NEAR_GARAGE,
'AFP_A_NEAR_IN_GARAGE', RED, AFP.comment_GARAGE),
446 (C_FAR_GARAGE,
'AFP_C_FAR_IN_GARAGE', RED, AFP.comment_GARAGE),
447 (C_NEAR_GARAGE,
'AFP_C_NEAR_IN_GARAGE', RED, AFP.comment_GARAGE),
449 (A_FAR_SIT_HV,
'AFP_A_FAR_SIT_PARTIALLY_OPERATIONAL_HV', YELLOW, AFP.comment_SIT_HV),
450 (A_FAR_SIT_HV,
'AFP_A_FAR_SIT_NOT_OPERATIONAL_HV', RED, AFP.comment_SIT_HV),
451 (A_NEAR_SIT_HV,
'AFP_A_NEAR_SIT_PARTIALLY_OPERATIONAL_HV', YELLOW, AFP.comment_SIT_HV),
452 (A_NEAR_SIT_HV,
'AFP_A_NEAR_SIT_NOT_OPERATIONAL_HV', RED, AFP.comment_SIT_HV),
453 (C_FAR_SIT_HV,
'AFP_C_FAR_SIT_PARTIALLY_OPERATIONAL_HV', YELLOW, AFP.comment_SIT_HV),
454 (C_FAR_SIT_HV,
'AFP_C_FAR_SIT_NOT_OPERATIONAL_HV', RED, AFP.comment_SIT_HV),
455 (C_NEAR_SIT_HV,
'AFP_C_NEAR_SIT_PARTIALLY_OPERATIONAL_HV', YELLOW, AFP.comment_SIT_HV),
456 (C_NEAR_SIT_HV,
'AFP_C_NEAR_SIT_NOT_OPERATIONAL_HV', RED, AFP.comment_SIT_HV),
458 (A_FAR_SIT_LV,
'AFP_A_FAR_SIT_PARTIALLY_OPERATIONAL_LV', YELLOW, AFP.comment_SIT_LV),
459 (A_FAR_SIT_LV,
'AFP_A_FAR_SIT_NOT_OPERATIONAL_LV', RED, AFP.comment_SIT_LV),
460 (A_NEAR_SIT_LV,
'AFP_A_NEAR_SIT_PARTIALLY_OPERATIONAL_LV', YELLOW, AFP.comment_SIT_LV),
461 (A_NEAR_SIT_LV,
'AFP_A_NEAR_SIT_NOT_OPERATIONAL_LV', RED, AFP.comment_SIT_LV),
462 (C_FAR_SIT_LV,
'AFP_C_FAR_SIT_PARTIALLY_OPERATIONAL_LV', YELLOW, AFP.comment_SIT_LV),
463 (C_FAR_SIT_LV,
'AFP_C_FAR_SIT_NOT_OPERATIONAL_LV', RED, AFP.comment_SIT_LV),
464 (C_NEAR_SIT_LV,
'AFP_C_NEAR_SIT_PARTIALLY_OPERATIONAL_LV', YELLOW, AFP.comment_SIT_LV),
465 (C_NEAR_SIT_LV,
'AFP_C_NEAR_SIT_NOT_OPERATIONAL_LV', RED, AFP.comment_SIT_LV),
467 (A_FAR_TOF_LV,
'AFP_A_FAR_TOF_NOT_OPERATIONAL_LV', RED, AFP.comment_TOF_LV),
468 (C_FAR_TOF_LV,
'AFP_C_FAR_TOF_NOT_OPERATIONAL_LV', RED, AFP.comment_TOF_LV),
470 (A_FAR_TOF_HV,
'AFP_A_FAR_TOF_NOT_OPERATIONAL_HV', RED, AFP.comment_TOF_HV),
471 (C_FAR_TOF_HV,
'AFP_C_FAR_TOF_NOT_OPERATIONAL_HV', RED, AFP.comment_TOF_HV),
476 (TTC_RESTART,
'AFP_TTC_RESTART', RED, AFP.comment_TTC_RESTART),
477 (STOPLESSLY_REMOVED,
'AFP_STOPLESSLY_REMOVED', RED, AFP.comment_STOPLESSLY_REMOVED),
479 (A_FAR_SIT_DISABLED,
'AFP_A_FAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', YELLOW, AFP.comment_SIT_DISABLED),
480 (A_FAR_SIT_DISABLED,
'AFP_A_FAR_SIT_NOT_OPERATIONAL_TDAQ', RED, AFP.comment_SIT_DISABLED),
481 (A_NEAR_SIT_DISABLED,
'AFP_A_NEAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', YELLOW, AFP.comment_SIT_DISABLED),
482 (A_NEAR_SIT_DISABLED,
'AFP_A_NEAR_SIT_NOT_OPERATIONAL_TDAQ', RED, AFP.comment_SIT_DISABLED),
483 (C_FAR_SIT_DISABLED,
'AFP_C_FAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', YELLOW, AFP.comment_SIT_DISABLED),
484 (C_FAR_SIT_DISABLED,
'AFP_C_FAR_SIT_NOT_OPERATIONAL_TDAQ', RED, AFP.comment_SIT_DISABLED),
485 (C_NEAR_SIT_DISABLED,
'AFP_C_NEAR_SIT_PARTIALLY_OPERATIONAL_TDAQ', YELLOW, AFP.comment_SIT_DISABLED),
486 (C_NEAR_SIT_DISABLED,
'AFP_C_NEAR_SIT_NOT_OPERATIONAL_TDAQ', RED, AFP.comment_SIT_DISABLED),
488 (A_FAR_TOF_DISABLED,
'AFP_A_FAR_TOF_NOT_OPERATIONAL_TDAQ', RED, AFP.comment_TOF_DISABLED),
489 (C_FAR_TOF_DISABLED,
'AFP_C_FAR_TOF_NOT_OPERATIONAL_TDAQ', RED, AFP.comment_TOF_DISABLED),
492 AFP.defect_combinator(*cdcc)
494 ([A_FAR_SIT_LV, A_FAR_SIT_DISABLED],
'AFP_A_FAR_SIT_NOT_OPERATIONAL', YELLOW, AFP.comment_SIT_COMBINATION),
495 ([A_NEAR_SIT_LV, A_NEAR_SIT_DISABLED],
'AFP_A_NEAR_SIT_NOT_OPERATIONAL', YELLOW, AFP.comment_SIT_COMBINATION),
496 ([C_FAR_SIT_LV, C_FAR_SIT_DISABLED],
'AFP_C_FAR_SIT_NOT_OPERATIONAL', YELLOW, AFP.comment_SIT_COMBINATION),
497 ([C_NEAR_SIT_LV, C_NEAR_SIT_DISABLED],
'AFP_C_NEAR_SIT_NOT_OPERATIONAL', YELLOW, AFP.comment_SIT_COMBINATION),
507 return 'Station not in physics'
511 return AFP.comment_planes(iov,
'with too low current')
515 return AFP.comment_planes(iov,
'out of nominal voltage')
519 return 'ToF TDC with too low current'
523 return 'ToF PMT out of nominal voltage'
531 return 'AFP not in the RUNNING state'
535 return 'AFP stoplessly removed from the run'
539 return AFP.comment_planes(iov,
'removed from readout')
543 return AFP.comment_device(iov,
'ToF TDC',
'removed from readout')
551 return "Combination of 'partially operational' defects"
559 return AFP.comment_device(iov,
'SiT plane', message)
563 count = iov.NConfig - iov.NWorking
566 return f
"{count} {device} {message}"