ATLAS Offline Software
Loading...
Searching...
No Matches
tile.py
Go to the documentation of this file.
1# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3from logging import getLogger; log = getLogger("DCSCalculator2.tile")
4from ..lib import (DCSC_DefectTranslate_Subdetector, DCSC_Variable,
5 DCSC_Variable_With_Mapping, OUT_OF_CONFIG, GoodIOV)
6
7from itertools import product
8
9from TileCalibBlobObjs.Classes import (
10 TileCalibDrawerBch, TileBchDecoder, TileBchStatus, TileCalibUtils, TileBchPrbs)
11
12# Magic, needed for functioning coral Blob
13try:
14 import PyCintex as C
15except Exception:
16 import cppyy as C
17Blob = C.gbl.coral.Blob
18
19WHITE, BLACK, GREY, RED, YELLOW, GREEN = None, -1, 0, 1, 2, 3
20
21TILBA, TILBC, TIEBA, TIEBC = 232, 233, 234, 235
22N_CHANNELS_PER_MODULE = [90]*148+[64]*14+[60]+[64]*66+[60]+[64]*46
23
24def make_blob(string):
25 b = Blob()
26 b.write(string)
27 b.seek(0)
28 return b
29
30def decode_status(chan, calib_blob):
31 """
32 Given a module number `chan` and a `calib_blob` string, return the number
33 of bad, good and affected channels in this module.
34
35 It also returns a dictionary `prob` containing as keys the problem identifier
36 and values the number of channels affected by that problem.
37 """
38
39 if chan == 1000 or len(calib_blob) <= 24:
40 # chan 1000 is a comment, and calib_blobs less than 24 in length cause
41 # a crash.
42 return None
43
44 # Decode a Coral BLOB into a string
45 b = make_blob(calib_blob)
47
48 bad, good, affected = [], [], []
49
50 probs = {}
51
52 decoder = TileBchDecoder(bch.getBitPatternVersion())
53 chn_adcs = product(list(range(TileCalibUtils.max_chan())),
54 list(range(TileCalibUtils.max_gain())))
55 # Stolen from near
56 # http://alxr.usatlas.bnl.gov/lxr/source/atlas/TileCalorimeter/TileCalib/
57 # TileCalibBlobPython/python/TileBchTools.py#072
58 for chn, adc in chn_adcs:
59 adcBits, chnBits = bch.getData(chn, adc, 0), bch.getData(chn, 2, 0)
60 status = TileBchStatus(decoder.decode(chnBits, adcBits))
61 if status.isBad(): bad.append((chn, adc))
62 if status.isGood(): good.append((chn, adc))
63 if status.isAffected(): affected.append((chn, adc))
64
65 if not status.isGood():
66 prbs = status.getPrbs()
67 # Build a dictionary
68 for prb in prbs:
69 key = prb, TileBchPrbs.getDescription(prb)
70 probs[key] = probs.get(key, 0) + 1
71
72 return len(bad), len(good), len(affected), probs
73
75 """
76 Rewrite the TileCalibBlob field to contain the result of `decode_status`
77 """
78 return i._replace(TileCalibBlob=decode_status(i.channel, i.TileCalibBlob))
79
81 return iovs.empty(decode_tile_iov(i) for i in iovs)
82
84 """
85 Records modules which have all of their channels in the NoHV state.
86 """
87 input_db = "COOLOFL_TILE/CONDBR2"
88 is_config_variable = True
89 timewise_folder = False
90
91 fetch_args = dict(tag="TileOfl02StatusAdc-RUN2-HLT-UPD1-00")
92
93 def make_good_iov(self, iov):
94 return GoodIOV(iov.since, iov.until, iov.channel, OUT_OF_CONFIG)
95
96 def make_good_iovs(self, iovs):
97 iovs = decode_tile_iovs(iovs)
98
99 log.debug("Number of NHV iovs: %i", len(iovs))
100
101 def too_many_nohv(iov):
102 """
103 Read the TileCalib blob to determine what problems are present.
104 If all ADCs appear to have (2002, No HV), then count this module
105 as being OUT OF CONFIG. Number of ADCs is 45*2 for LBA/LBC partitions
106 32*2 for most of the modules in EBA/EBC partitions and 30*2 for EBA15 and EBC18
107 """
108 if not iov.TileCalibBlob: return False
109 nbad, ngood, naffected, problems = iov.TileCalibBlob
110 if problems:
111 log.debug("Tile problems %i %r", iov.channel, problems)
112 return problems.get((2002, 'No HV'), 0) >= N_CHANNELS_PER_MODULE[iov.channel]
113
114 iovs = iovs.empty(iov for iov in iovs if too_many_nohv(iov))
115
116 log.debug("Bad high voltage channels:")
117 log.debug("= [%r]", ", ".join(str(i.channel) for i in iovs))
118
119 iovs = super(Tile_NoHighVoltage, self).make_good_iovs(iovs)
120
121 return iovs
122
124 """
125 Check the TILE/DCS/STATES FORDAQ_MBHV code for modules in a good state.
126 Excludes modules which are known to be entirely bad due to No HV so that
127 shifters will notice problems with the STATE which are unrelated to this
128 known problem.
129 """
130
131 folder_base = "/TILE/DCS"
132
133 # Key: output_channel
134 # Value: input_channel
135 #mapping = {
136 # TILBA: range( 1, 64) + [65],
137 # TILBC: range( 66, 130),
138 # TIEBA: range(193, 257),
139 # TIEBC: [64] + range(130, 193),
140 #}
141
142 # New mapping, ordered so that the channels match up with
143 # The channels in the next mapping, mapping2.
144 # I'm not a big fan of the way this is done, so I should
145 # come up with a better solution. I at least need to clean it up
146 def lrange(a, b): return list(range(a,b))
147 mapping = {
148 TILBA: lrange(49, 52) + [65] + [55] + lrange(61, 64) + [16] +
149 lrange(1, 16) + lrange(17, 49) + lrange(52, 55) + lrange(56, 61),
150
151 TILBC: lrange(114, 118) + [121] + lrange(127, 130) + [81] + lrange(66, 81) +
152 lrange(82, 114) + lrange(118, 121) + lrange( 122, 127),
153
154 TIEBA: lrange(241, 245) + [248] + lrange(254, 257) + [208] + lrange(193, 208) +
155 lrange(209, 241) + lrange(245, 248) + lrange(249, 254),
156
157 TIEBC: lrange(177, 181) + [184] + lrange(190, 193) + [145] + lrange(131, 134) +
158 [64] + lrange(134, 145) + lrange(146, 163) + [130] + lrange(163, 177) +
159 lrange(181, 184) + lrange(185, 190)
160 }
161
162 mapping2 = dict( list(zip(range( 20, 84), mapping[TILBA])) +
163 list(zip(range( 84, 148), mapping[TILBC])) +
164 list(zip(range(148, 212), mapping[TIEBA])) +
165 list(zip(range(212, 276), mapping[TIEBC]))
166 )
167
168 variables = [
169 #DCSC_Variable("STATES", lambda iov: iov.FORDAQ_MBHV == 212222),
170 DCSC_Variable("STATES", lambda iov: iov.FORDAQ_MBHV in (212222, 202221)),
171 Tile_NoHighVoltage("/TILE/OFL02/STATUS/ADC", None)
172 ]
173
174 dead_fraction_caution = 0.01
175 dead_fraction_bad = 0.75
176
177
178
179#For book keeping purposes, here is a historical summary of thresholds
180#
181#24/06/10
182#Runs start of the year -
183# dead_fraction_map = {
184# TILBA: 0.048,
185# TILBC: 0.048,
186# TIEBA: dead_fraction_caution,
187# TIEBC: 0.0314
188# }
189#
190#23/07/10 - Lost EBC47
191#Runs - 160801
192# dead_fraction_map = {
193# TILBA: 0.048,
194# TILBC: 0.048,
195# TIEBA: dead_fraction_caution,
196# TIEBC: 0.048
197# }
198#
199#
200#11/08/10 - Lost LBA09 due to interface card issue. Lost LBC08
201#Runs 160878 - 177167
202# dead_fraction_map = {
203# TILBA: 0.064,
204# TILBC: 0.064,
205# TIEBA: dead_fraction_caution,
206# TIEBC: 0.048
207# }
208#
209#21/03/11 - After winter maintanence, many power supplies were repaired
210# but the frequent power cutscost us several modules
211#Runs 177167 - 178624
212# dead_fraction_map = {
213# TILBA: 0.032,
214# TILBC: 0.017,
215# TIEBA: dead_fraction_caution,
216# TIEBC: 0.017
217# }
218#
219#08/04/11 - Lost LBC07 but gained EBC37
220#Runs 178740 - 178908
221# dead_fraction_map = {
222# TILBA: 0.032,
223# TILBC: 0.032,
224# TIEBA: dead_fraction_caution,
225# TIEBC: dead_fraction_caution
226# }
227#
228#08/04/11 - Lost LBC02
229#Runs 178933 - present
230# dead_fraction_map = {
231# TILBA: 0.032,
232# TILBC: 0.048,
233# TIEBA: dead_fraction_caution,
234# TIEBC: dead_fraction_caution
235# }
236#
237#
238#27/04/11 - Lost EBC37, gained LBA24 back
239#Runs 178933 - present
240# dead_fraction_map = {
241# TILBA: 0.032,
242# TILBC: 0.048,
243# TIEBA: dead_fraction_caution,
244# TIEBC: dead_fraction_caution
245# }
246#
247#
248#27/04/11 - Lost EBC37, gained LBA24 back
249# dead_fraction_map = {
250# TILBA: 0.017, # Mask dead modules
251# TILBC: 0.048, # Mask dead modules
252# TIEBA: dead_fraction_caution,
253# TIEBC: 0.017
254# }
255#
256#30/04/11 - Lost LBA24 again
257# dead_fraction_map = {
258# TILBA: 0.032, # Mask dead modules
259# TILBC: 0.048, # Mask dead modules
260# TIEBA: dead_fraction_caution,
261# TIEBC: 0.017
262# }
263#
264#
265# dead_fraction_map = {
266# TILBA: 0.048, # Mask dead modules
267# TILBC: 0.048, # Mask dead modules
268# TIEBA: dead_fraction_caution,
269# TIEBC: 0.017
270# }
271# 4/July/11 - EBC is back again
272# dead_fraction_map = {
273# TILBA: 0.048, # Mask dead modules
274# TILBC: 0.048, # Mask dead modules
275# TIEBA: dead_fraction_caution,
276# TIEBC: 0.0
277# }
278# 10 July, EBC 37 lost again
279# dead_fraction_map = {
280# TILBA: 0.032, # Mask dead modules
281# TILBC: 0.048, # Mask dead modules
282# TIEBA: dead_fraction_caution,
283# TIEBC: 0.017
284# }
285# one more module in LBC
286# dead_fraction_map = {
287# TILBA: 0.032, # Mask dead modules
288# TILBC: 0.064, # Mask dead modules
289# TIEBA: dead_fraction_caution,
290# TIEBC: 0.017
291# }
292# status at 01-Sep-2014 - LBA10 dead
293# dead_fraction_map = {
294# TILBA: 0.017, # Mask dead modules
295# TILBC: dead_fraction_caution,
296# TIEBA: dead_fraction_caution,
297# TIEBC: dead_fraction_caution
298# }
299# status at 2015-06-11 - EBC21 also dead
300# dead_fraction_map = {
301# TILBA: 0.017, # Mask dead modules
302# TILBC: dead_fraction_caution,
303# TIEBA: dead_fraction_caution,
304# TIEBC: 0.017 # Mask dead modules
305# }
306# status at 2015-10-07 - Getting false trips in EBC, probably from 1/4 of EBC47
307# dead_fraction_map = {
308# TILBA: 0.017, # Mask dead modules
309# TILBC: dead_fraction_caution,
310# TIEBA: dead_fraction_caution,
311# TIEBC: 0.021 # Mask dead and partially dead modules
312# }
313
314# status at 2016-03-01 - All the dead modules are fixed and turned on.
315# dead_fraction_map = {
316# TILBA: dead_fraction_caution,
317# TILBC: dead_fraction_caution,
318# TIEBA: dead_fraction_caution,
319# TIEBC: dead_fraction_caution
320# }
321# status at 2017-06-01 - EBA03 and LBC63 are dead
322# dead_fraction_map = {
323# TILBA: dead_fraction_caution,
324# TILBC: 0.017
325# TIEBA: 0.017,
326# TIEBC: dead_fraction_caution
327# }
328# status at 2018-04-12 - all modules are fixed and turned on.
329 dead_fraction_map = {
330 TILBA: dead_fraction_caution,
331 TILBC: dead_fraction_caution,
332 TIEBA: dead_fraction_caution,
333 TIEBC: dead_fraction_caution
334 }
335
336
337 def calculate_dead_fraction(self, since, until, output_channel, states,
338 state_iovs):
339 """
340 This is for masking the unpowered Tile Cells. It returns the actual fraction of Tile that is off
341 but the R/Y/G is adjusted so that the unpowered modules don't hide new problems.
342 """
343 cdf = super(Tile, self).calculate_dead_fraction
344 result = cdf(since, until, output_channel, states, state_iovs)
345
346 code, dead_fraction, thrust, n_config, n_working = result
347
348 # Don't include channels which are "out of config" (see Tile_NoHighVoltage)
349 dead_fraction = 1 - (n_working / n_config)
350
351 # If n_working == n_config then we're good.
352 if dead_fraction == 0:
353 # Mask dead channels
354 code = GREEN
355
356 return code, dead_fraction, thrust, n_config, n_working
357
358 def __init__(self, *args, **kwargs):
359 #kwargs['keep_dcsofl'] = True
360 super(Tile, self).__init__(*args, **kwargs)
361 self.translators = [Tile.color_to_defect_translator(flag, defect, [RED, YELLOW])
362 for flag, defect in ((TILBA, 'TILE_LBA_TRIP'),
363 (TILBC, 'TILE_LBC_TRIP'),
364 (TIEBA, 'TILE_EBA_TRIP'),
365 (TIEBC, 'TILE_EBC_TRIP'),
366 )]
367 self.set_input_mapping("/TILE/OFL02/STATUS/ADC", self.mapping2)
Class providing the association between TileCal problems and status word bits.
static std::string getDescription(const Prb &prb)
Get description of problem.
Class holding bad channel problems.
static const TileCalibDrawerBch * getInstance(const coral::Blob &blob)
Returns a pointer to a const TileCalibDrawerBch.
static unsigned int max_gain()
Python compatibility function.
static unsigned int max_chan()
Python compatibility function.
set_input_mapping(self, what, mapping)
calculate_dead_fraction(self, since, until, output_channel, states, state_iovs)
Definition tile.py:338
__init__(self, *args, **kwargs)
Definition tile.py:358
decode_status(chan, calib_blob)
Definition tile.py:30