ATLAS Offline Software
Loading...
Searching...
No Matches
ReadBchFromCrest.py
Go to the documentation of this file.
1#!/bin/env python
2
3# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4#
5# File: ReadBchFromCrest.py
6# Sanya Solodkov <Sanya.Solodkov@cern.ch>, 2025-10-20
7#
8# Purpose: Read channel status from CREST DB or from JSON file
9# ReadBchFromCrest.py --schema='CREST' --tag='UPD4'
10#
11
12import getopt,sys,os
13os.environ['TERM'] = 'linux'
14
15def usage():
16 print ("Usage: ",sys.argv[0]," [OPTION] ... ")
17 print ("Dumps the TileCal status bits from various schemas / folders")
18 print ("")
19 print ("-h, --help shows this help")
20 print ("-f, --folder= specify status folder to use ONL01 or OFL02, don't need to specify full path")
21 print ("-t, --tag= specify tag to use, f.i. UPD1 or UPD4 or full suffix like RUN2-HLT-UPD1-00")
22 print ("-r, --run= specify run number, by default uses latest iov")
23 print ("-l, --lumi= specify lumi block number, default is 0")
24 print ("-b, --begin= specify run number of first iov in multi-iov mode, by default uses very first iov")
25 print ("-e, --end= specify run number of last iov in multi-iov mode, by default uses latest iov")
26 print ("-m, --module= specify module to use, default is not set")
27 print ("-N, --chmin= specify minimal channel to use, default is 0")
28 print ("-X, --chmax= specify maximal channel to use, default is 47")
29 print ("-c, --chan= specify channel to use , default is all channels from chmin to chmax")
30 print ("-g, --gain=, -a, --adc= specify adc(gain) to use, default is 2 (i.e. both low and high gains)")
31 print ("-C, --comment print comment for every IOV")
32 print ("-i, --iov print IOVs only for every module")
33 print ("-I, --IOV print IOVs only")
34 print ("-d, --default print also default values stored in AUX01-AUX20")
35 print ("-B, --blob print additional blob info")
36 print ("-H, --hex print frag id instead of module name")
37 print ("-P, --pmt print pmt number in addition to channel number")
38 print ("-s, --schema= specify name of input JSON file or CREST_SERVER_PATH")
39 print ("-w, --warning suppress warning messages about missing drawers in DB")
40
41letters = "hr:l:s:t:f:dBHPwm:b:e:a:g:c:N:X:CiI"
42keywords = ["help","run=","lumi=","schema=","tag=","folder=","default","blob","hex","pmt","warning","module=","begin=","end=","chmin=","chmax=","gain=","adc=","chan=","comment","iov","IOV"]
43
44try:
45 opts, extraparams = getopt.getopt(sys.argv[1:],letters,keywords)
46except getopt.GetoptError as err:
47 print (str(err))
48 usage()
49 sys.exit(2)
50
51# defaults
52run = 2147483647
53lumi = 0
54schema = 'CREST'
55folderPath = "/TILE/OFL02/STATUS/ADC"
56tag = "UPD4"
57rosmin = 1
58rosmax = 5
59blob = False
60hexid = False
61pmt = False
62warn = 1
63modmin = 0
64modmax = 99999
65modulename="AUX-1"
66partname=""
67one_mod = False
68mod = -1
69ros = -1
70chan_n= -1
71chanmin = -1
72chanmax = -1
73gain_n = -1
74gainmin = -1
75gainmax = -1
76begin = -1
77end = 2147483647
78iov = False
79iovonly = False
80IOVONLY = False
81comment = False
82
83for o, a in opts:
84 a = a.strip()
85 if o in ("-f","--folder"):
86 if '/TILE' in a:
87 folderPath = a
88 else:
89 folderPath = "/TILE/%s/STATUS/ADC" % a
90 elif o in ("-t","--tag"):
91 tag = a
92 elif o in ("-s","--schema"):
93 schema = a
94 elif o in ("-r","--run"):
95 run = int(a)
96 elif o in ("-l","--lumi"):
97 lumi = int(a)
98 elif o in ("-b","--begin"):
99 begin = int(a)
100 iov = True
101 one_mod = True
102 elif o in ("-e","--end"):
103 end = int(a)
104 iov = True
105 one_mod = True
106 elif o in ("-i","--iov"):
107 iov = True
108 iovonly = True
109 if modulename=='AUX-1':
110 modulename='ALL00'
111 elif o in ("-I","--IOV"):
112 iov = True
113 IOVONLY = True
114 if modulename=='AUX-1':
115 modulename='ALL00'
116 elif o in ("-a","--adc","-g","--gain"):
117 gain_n = int(a)
118 elif o in ("-m","--module"):
119 modulename = a
120 one_mod = True
121 elif o in ("-c","--chan"):
122 chan_n = int(a)
123 elif o in ("-N","--chmin"):
124 chanmin = int(a)
125 elif o in ("-X","--chmax"):
126 chanmax = int(a)
127 elif o in ("-C","--comment"):
128 comment = True
129 elif o in ("-d","--default"):
130 rosmin = 0
131 elif o in ("-B","--blob"):
132 blob = True
133 elif o in ("-H","--hex"):
134 hexid = True
135 elif o in ("-P","--pmt"):
136 pmt = True
137 elif o in ("-w","--warning"):
138 warn = -1
139 elif o in ("-h","--help"):
140 usage()
141 sys.exit(2)
142 else:
143 raise RuntimeError("unhandled option")
144
145
146from TileCalibBlobPython import TileBchCrest
147from TileCalibBlobObjs.Classes import TileCalibUtils
148
149from TileCalibBlobPython.TileCalibLogger import getLogger
150log = getLogger("ReadBchFrCrest")
151import logging
152logLevel=logging.DEBUG
153log.setLevel(logLevel)
154log1 = getLogger("TileBchCrest")
155log1.setLevel(logLevel)
156log2 = getLogger("TileCalibCrest")
157log2.setLevel(logLevel)
158
159if tag.upper().endswith('HEAD'):
160 tag=tag.upper()
161if len(tag)==0 or tag.endswith('HEAD'):
162 folderPath='/TILE/ONL01/STATUS/ADC'
163 log.info("tag is %s, using %s folder", tag if tag else 'empty', folderPath)
164 if tag=='HEAD':
165 tag=''
166
167folderTag = tag
168if folderTag.upper().startswith("TILE") or folderTag.upper().startswith("CALO") :
169 folderPath=""
170log.info("Initializing folder %s with tag %s", folderPath, folderTag)
171
172#=== create bad channel manager
173mgr = TileBchCrest.TileBchMgr()
174mgr.setLogLvl(logLevel)
175mgr.initialize(schema, folderPath, folderTag, (run,lumi), warn, -2)
176if iov or comment or warn<0:
177 blobReader = mgr.getBlobReader()
178
179#=== Dump the current isBad definition
181if len(list(isBadDef.keys())):
182 log.info( "isBad Definition: " )
183 for prbCode in sorted(isBadDef.keys()):
184 prbDesc = isBadDef[prbCode]
185 msg = "- %2i (%s)" % (prbCode,prbDesc)
186 log.info( msg )
187#=== Dump the current isBadTiming definition
189if len(list(isBadTimingDef.keys())):
190 log.info( "isBadTiming Definition: " )
191 for prbCode in sorted(isBadTimingDef.keys()):
192 prbDesc = isBadTimingDef[prbCode]
193 msg = "- %2i (%s)" % (prbCode,prbDesc)
194 log.info( msg )
195
196
197#=== check ROS and module numbers
198if one_mod:
199 partname = modulename[:3]
200 mod = int(modulename[3:]) -1
201
202part_dict = {'AUX':0,'LBA':1,'LBC':2,'EBA':3,'EBC':4}
203if partname in part_dict:
204 ros = part_dict[partname]
205 rosmin = ros
206 rosmax = ros+1
207else:
208 ros = -1
209
210if mod >= 0:
211 modmin = mod
212 modmax = mod+1
213elif mod < -1:
214 modmax = modmin
215
216if chan_n >= 0 and chan_n < TileCalibUtils.max_chan():
217 chanmin = chan_n
218 chanmax = chan_n+1
219else:
220 if chanmin<0:
221 chanmin = 0
222 if chanmax<0:
223 chanmax = TileCalibUtils.max_chan()
224 else:
225 chanmax += 1
226
227if gain_n >= 0 and gain_n < TileCalibUtils.max_gain():
228 gainmin = gain_n
229 gainmax = gain_n+1
230else:
231 gainmin = 0
232 gainmax = TileCalibUtils.max_gain()
233
234
235#=== Filling the iovList
236iovList = []
237if iov:
238 if begin<0:
239 if iovonly or IOVONLY:
240 begin = end
241 else:
242 begin=0
243 iovList = blobReader.getIovs((begin,0),(end,0))
244
245 be=iovList[0][0]
246 en=iovList[-1][0]
247
248 if begin != be or end != en:
249 log.info( "" )
250 if be != begin:
251 log.info( "Changing begin run from %d to %d (start of IOV)", begin,be)
252 begin=be
253 if en != end:
254 if en>end:
255 log.info( "Changing end run from %d to %d (start of next IOV)", end,en)
256 else:
257 log.info( "Changing end run from %d to %d (start of last IOV)", end,en)
258 end=en
259 log.info( "%d IOVs in total", len(iovList))
260
261 #=== IOV only option
262 if iovonly or IOVONLY:
263 option = 1 if iovonly else 0
264 option += (2 if IOVONLY else 0)
265 blobReader.dumpIovs(iovList,rosmin,rosmax,modmin,modmax,option,(rosmin<=0),True)
266 sys.exit(0)
267else:
268 iovList.append((run,lumi))
269
270log.info( "\n" )
271
272
273
276dummy = [0]*48
277barrel = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
278 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
279 27, 26, 25, 30, 29, 28,-33,-32, 31, 36, 35, 34,
280 39, 38, 37, 42, 41, 40, 45,-44, 43, 48, 47, 46]
281extbar = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
282 13, 14, 15, 16, 17, 18,-19,-20, 21, 22, 23, 24,
283 -27,-26,-25,-31,-32,-28, 33, 29, 30,-36,-35, 34,
284 44, 38, 37, 43, 42, 41,-45,-39,-40,-48,-47,-46]
285
286ch2pmt = [ dummy, barrel, barrel, extbar, extbar ]
287gname = [ "LG", "HG" ]
288
289#=== Get ADC problems
290
291#=== get the channel status (if it is bad and will be masked)
292#=== the channel status depends on the definition of isBad stored
293#=== in the database drawer 1, channel 0
294#=== isAffected = has a problem not included in isBad definition
295#=== isGood = has no problem at all
296
297oneModule = ((rosmax-rosmin==1) and (modmax-modmin==1) and iov)
298oldBlob = None
299pref = ""
300for iovs in iovList:
301 if iov:
302 pref = "(%i,%i) " % (iovs[0],iovs[1])
303 mgr.updateFromDb(schema, folderPath, folderTag, iovs, 1, warn)
304 if comment:
305 log.info( pref + str(blobReader.getComment(iovs)) )
306 modOk = False
307 miss = 0
308 good = 0
309 aff = 0
310 bad = 0
311 nMod = 0
312 for ros in range(rosmin,rosmax):
313 for mod in range(modmin, min(modmax,TileCalibUtils.getMaxDrawer(ros))):
314 nMod += 1
315 if hexid:
316 modName = "0x%x" % ((ros<<8)+mod)
317 else:
318 modName = TileCalibUtils.getDrawerString(ros,mod)
319 if oneModule:
320 newBlob = blobReader.getBlob(ros, mod, iovs, False)
321 if oldBlob == newBlob:
322 log.info( f'{modName} in IOV {iovs} is identical to previous IOV')
323 continue
324 else:
325 if oldBlob is None:
326 log.info( f'Reading IOV {iovs} for module {modName}')
327 else:
328 log.info( f'{modName} was updated in IOV {iovs}')
329 oldBlob = newBlob
330 if warn<0:
331 bch = blobReader.getDrawer(ros, mod, iovs, False, False)
332 if bch is None:
333 modOk = False
334 miss+=1
335 #print ("%s is missing in DB" % modName)
336 else:
337 modOk = True
338 if blob and bch:
339 print ("%s Blob type: %d Version: %d Nchannels: %d Ngains: %d Nval: %d" % (modName, bch.getObjType(), bch.getObjVersion(), bch.getNChans(), bch.getNGains(), bch.getObjSizeUint32()))
340 nBad=0
341 for chn in range(chanmin,chanmax):
342 chnName = " %2i" % chn
343 for adc in range(gainmin,gainmax):
344
345 stat = mgr.getAdcStatus(ros,mod,chn,adc)
346 #log.info( "- ADC status = isBad: %d" % stat.isBad() )
347 #log.info( "- ADC status = isGood: %d" % stat.isGood() )
348 #log.info( "- ADC status = isAffected: %d" % stat.isAffected() )
349
350 #=== get all problems of the channel
351 prbs = mgr.getAdcProblems(ros,mod,chn,adc)
352 #log.info( "ADC Problems: " )
353 if len(prbs) or iov:
354 modOk = False
355 if pmt:
356 msg = "%s pm %02i ch %02i %s " % ( modName, abs(ch2pmt[ros][chn]), chn, gname[adc] )
357 else:
358 msg = "%s %2i %1i " % ( modName,chn,adc )
359 for prbCode in sorted(prbs.keys()):
360 prbDesc = prbs[prbCode]
361 msg += " %5i (%s)" % (prbCode,prbDesc)
362 if stat.isBad():
363 msg += " => BAD"
364 nBad+=1
365 elif stat.isAffected():
366 msg += " => Affected"
367 elif stat.isGood():
368 msg += " => good"
369 print (pref+msg)
370 if modOk:
371 good+=1
372 print ("%s ALL GOOD" % (modName))
373 elif nBad==0:
374 aff+=1
375 elif nBad==TileCalibUtils.max_gain()*TileCalibUtils.max_chan() or (nBad==90 and 'LB' in modName) or (nBad==64 and 'EB'in modName) or (nBad==60 and 'EBA15' in modName) or (nBad==60 and 'EBC18' in modName):
376 bad+=1
377 if warn<0:
378 if miss:
379 print ("%3i drawers are missing in DB" % miss)
380 print ("%3i drawers are absolutely good" % good)
381 print ("%3i drawers have good and affected channels" % (aff-miss))
382 print ("%3i drawers have some bad channels" % (nMod-good-bad-aff))
383 print ("%3i drawers are completely bad" % bad)
384 #=== print all bad channels
385 #log.info("listing bad channels")
386 #mgr.listBadAdcs()
#define min(a, b)
Definition cfImp.cxx:40
static unsigned int max_gain()
Python compatibility function.
static unsigned int badtiming_definition_chan()
Python compatibility function.
static std::string getDrawerString(unsigned int ros, unsigned int drawer)
Return the drawer name, e.g.
static unsigned int max_chan()
Python compatibility function.
static unsigned int getMaxDrawer(unsigned int ros)
Returns the maximal channel number for a given drawer.
static unsigned int definitions_draweridx()
Python compatibility function.
static unsigned int bad_definition_chan()
Python compatibility function.