ATLAS Offline Software
Loading...
Searching...
No Matches
WriteBchToCrest.py
Go to the documentation of this file.
1#!/bin/env python
2
3# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4#
5# File: WriteBchToCrest.py
6# Sanya Solodkov <Sanya.Solodkov@cern.ch>, 2025-10-30
7#
8# Purpose: Prepare JSON file with new bad channel status
9# actual masking/unmasking of channels is done by
10# external script specified in --execfile= option
11# All modules are always written, for channels which are not
12# mentioned in input file previous status is copied from CREST DB
13#
14
15import getopt,sys,os,bisect
16os.environ['TERM'] = 'linux'
17
18def usage():
19 print ("Usage: ", sys.argv[0]," [OPTION] ... ")
20 print ("Update TileCal bad channels in COOL")
21 print ("")
22 print ("-h, --help shows this help")
23 print ("-f, --folder= specify folder to use, default is /TILE/OFL02/STATUS/ADC")
24 print ("-t, --tag= specify tag to use, default is RUN2-HLT-UPD1-00")
25 print ("-r, --run= specify run number, default is 0")
26 print ("-l, --lumi= specify lumi block number, default is 0")
27 print ("-b, --begin= specify run number of first iov in multi-iov mode, by default uses very first iov")
28 print ("-e, --end= specify run number of last iov in multi-iov mode, by default uses latest iov")
29 print ("-L, --endlumi= specify lumi block number for last iov in multi-iov mode, default is 0")
30 print ("-A, --adjust in multi-iov mode adjust iov boundaries to nearest iov available in DB, default is False")
31 print ("-M, --module= specify module to use in multi-IOV update, default is all")
32 print ("-c, --comment= specify comment which should be written to DB, in multi-iov mode it is appended to old comment")
33 print ("-C, --Comment= specify comment which should be written to DB, in mutli-iov mode it overwrites old comment")
34 print ("-U, --user= specify username for comment")
35 print ("-x, --execfile= specify python file which should be executed, default is bch.py")
36 print ("-i, --inschema= specify name of input JSON file or CREST_SERVER_PATH")
37 print ("-o, --outschema= specify name of output JSON file, default is tileCalib.json")
38 print ("-s, --schema= the same as --o, --outschema")
39 print ("-n, --online write additional file with online bad channel status")
40 print ("-p, --upd4 write additional file with CURRENT UPD4 tag")
41 print ("-v, --verbose verbose mode")
42
43letters = "hr:l:b:e:L:AM:s:i:o:t:f:x:c:C:U:npv"
44keywords = ["help","run=","lumi=","begin=","end=","endlumi=","adjust","module=","schema=","inschema=","outschema=","tag=","folder=","execfile=","comment=","Comment=","user=","online","upd4","verbose"]
45
46try:
47 opts, extraparams = getopt.getopt(sys.argv[1:], letters, keywords)
48except getopt.GetoptError as err:
49 print (str(err))
50 usage()
51 sys.exit(2)
52
53# defaults
54run = -1
55lumi = 0
56inSchema = 'CREST'
57outSchema = 'tileCalib.json'
58folderPath = "/TILE/OFL02/STATUS/ADC"
59onlSuffix = None
60curSuffix = None
61tag = "UPD1"
62execFile = "bch.py"
63comment = ""
64Comment = None
65verbose = False
66iov = False
67beg = 0
68end = 2147483647
69endlumi = 0
70moduleList = ['ALL']
71adjust = False
72
73try:
74 user=os.getlogin()
75except Exception:
76 user="UnknownUser"
77
78for o, a in opts:
79 a = a.strip()
80 if o in ("-f","--folder"):
81 folderPath = a
82 elif o in ("-t","--tag"):
83 tag = a
84 elif o in ("-s","--schema"):
85 outSchema = a
86 elif o in ("-i","--inschema"):
87 inSchema = a
88 elif o in ("-o","--outschema"):
89 outSchema = a
90 elif o in ("-n","--online"):
91 onlSuffix = True
92 elif o in ("-p","--upd4"):
93 curSuffix = True
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 beg = int(a)
100 iov = True
101 elif o in ("-e","--end"):
102 end = int(a)
103 iov = True
104 elif o in ("-L","--endlumi"):
105 endlumi = int(a)
106 elif o in ("-A","--adjust"):
107 adjust = True
108 elif o in ("-M","--module"):
109 moduleList = a.split(",")
110 elif o in ("-x","--execfile"):
111 execFile = a
112 elif o in ("-c","--comment"):
113 comment = a
114 elif o in ("-C","--Comment"):
115 Comment = a
116 comment = a
117 elif o in ("-U","--user"):
118 user = a
119 elif o in ("-v","--verbose"):
120 verbose = True
121 elif o in ("-h","--help"):
122 usage()
123 sys.exit(2)
124 else:
125 raise RuntimeError("unhandeled option")
126
127onl=("/TILE/ONL01" in folderPath)
128
129from TileCalibBlobPython import TileCalibCrest
130from TileCalibBlobPython import TileCalibTools
131from TileCalibBlobPython import TileBchCrest
132from TileCalibBlobObjs.Classes import TileBchPrbs, TileBchDecoder
133
134if iov and end >= TileCalibCrest.MAXRUN:
135 end = TileCalibCrest.MAXRUN
136 endlumi = TileCalibCrest.MAXLBK
137until = (TileCalibCrest.MAXRUN,TileCalibCrest.MAXLBK)
138
139from TileCalibBlobPython.TileCalibLogger import getLogger
140log = getLogger("WriteBchToCrest")
141import logging
142logLevel=logging.DEBUG
143log.setLevel(logLevel)
144
145if tag.upper().endswith('HEAD'):
146 tag=tag.upper()
147if len(tag)==0 or tag.endswith('HEAD'):
148 folderPath='/TILE/ONL01/STATUS/ADC'
149 log.info("tag is %s, using %s folder", tag if tag else 'empty', folderPath)
150 tag='TILEONL01STATUSADC-HEAD'
151
152folderTag = tag
153if folderTag.upper().startswith("TILE") or folderTag.upper().startswith("CALO"):
154 folderPath=""
155log.info("Initializing bad channels from %s folder %s with tag %s", inSchema, folderPath, folderTag)
156
157iovList = []
158iovUntil = []
159
160blobReader = TileCalibCrest.TileBlobReaderCrest(inSchema, folderPath, folderTag, None, None, 0, 0)
161tag = blobReader.getTag()
162if tag != "unknown":
163 folderTag = tag
164
165if iov:
166 #=== filling the iovList
167 log.info( "Looking for IOVs" )
168 iovList = blobReader.getIovs()
169 iovList+=[until]
170
171 since=(beg,lumi)
172 ib=bisect.bisect(iovList,since)-1
173 if ib<0:
174 ib=0
175 if iovList[ib] != since:
176 if adjust:
177 since = iovList[ib]
178 log.info( "Moving beginning of first IOV with new bad channels from (%d,%d) to (%d,%d)", beg,lumi,since[0],since[1])
179 else:
180 iovList[ib] = since
181 log.info( "Creating new IOV starting from (%d,%d) with new bad channels", beg,lumi)
182
183 if end<0:
184 ie=ib+1
185 if ie>=len(iovList):
186 ie=ib
187 until=iovList[ie]
188 log.info( "Next IOV without new bad channels starts from (%d,%d)", until[0],until[1])
189 else:
190 until=(end,endlumi)
191 ie=bisect.bisect_left(iovList,until)
192 if ie>=len(iovList):
193 ie=len(iovList)-1
194
195 if iovList[ie] != until:
196 if adjust:
197 until=iovList[ie]
198 log.info( "Moving end of last IOV from (%d,%d) to (%d,%d)", end,endlumi,until[0],until[1])
199 else:
200 log.info( "Keeping end of last IOV at (%d,%d) - new IOV is shorter than IOV in input DB", end,endlumi)
201 iovList[ie] = until
202
203
204 iovList = iovList[ib:ie]
205 iovUntil = iovList[1:] + [until]
206 begin = since
207 run = since[0]
208 lumi = since[1]
209 log.info( "IOVs: %s", str(iovList) )
210
211 log.info( "%d IOVs in total, end of last IOV is %s", ie-ib,str(until))
212
213else:
214 #=== set run number
215 if run<0:
216 lumi=0
217 if "UPD4" in folderTag:
218 run=TileCalibTools.getPromptCalibRunNumber()
219 log.warning( "Run number is not specified, using minimal run number in calibration loop %d", run )
220 else:
221 run=TileCalibTools.getNextRunNumber()
222 log.warning( "Run number is not specified, using next run number %d", run )
223 if run<0:
224 log.error( "Bad run number" )
225 sys.exit(2)
226
227 since = (run, lumi)
228 iovList = [since]
229 iovUntil = [until]
230 begin=since
231
232 log.info("Initializing for run %d, lumiblock %d", run,lumi)
233
234#=== create bad channel manager
235log.info("")
236comments = []
237mgrWriters = []
238nvalUpdated = []
239commentsSplit = []
240for since in iovList:
241 comm=blobReader.getComment(since)
242 #log.info("Comment: %s", comm)
243 comments+=[comm]
244 nvalUpdated += [0]
245 commentsSplit+=[blobReader.getComment(since,True)]
246 mgr = TileBchCrest.TileBchMgr()
247 mgr.setLogLvl(logLevel)
248 mgr.initialize(inSchema, folderPath, folderTag, since)
249 mgrWriters += [mgr]
250log.info("")
251
252#=== Tuples of empty channels
253emptyChannelLongBarrel = (30, 31, 43)
254emptyChannelExtendedBarrel = (18, 19, 24, 25, 26, 27, 28, 29, 33, 34, 42, 43, 44, 45, 46, 47)
255
256# remember: addAdcProblem(ros, module, channel, adc), where:
257# ros = 1 LBA
258# ros = 2 LBC
259# ros = 3 EBA
260# ros = 4 EBC
261# module = 0 - 63
262# channel = 0 - 47
263# adc: 0 = low gain, 1 = high gain.
264
265#=== print bad channels
266if verbose and not iov:
267 log.info("============================================================== ")
268 log.info("bad channels before update")
269 mgr.listBadAdcs()
270
271#=== Add problems with mgr.addAdcProblem(ros, drawer, channel, adc, problem)
272#=== Remove problems with mgr.delAdcProblem(ros, drawer, channel, adc, problem)
273
274
275if len(execFile):
276 log.info("Masking new bad channels, including file %s", execFile )
277
278 #=== loop over all IOVs
279 for io,since in enumerate(iovList):
280
281 until=iovUntil[io]
282 if since==until:
283 continue # nothing to do
284
285 log.info( "Updating IOV %s - %s", str(since), str(until) )
286 mgr = mgrWriters[io]
287
288 try:
289 exec(compile(open(execFile).read(),execFile,'exec'))
290 if len(comment)==0:
291 log.error( "Comment string is not provided, please put comment='bla-bla-bla' line in %s", execFile )
292 sys.exit(2)
293 except Exception as e:
294 log.error( e )
295 log.error( "Problem reading include file %s", execFile )
296 sys.exit(2)
297
298 #=== print bad channels
299 if verbose:
300 log.info("============================================================== ")
301 log.info("bad channels after update")
302 mgr.listBadAdcs()
303
304 #====================== Write new bad channel list =================
305
306 #=== commit changes
307 if Comment is not None:
308 comment = Comment
309 author = user
310 else:
311 if comment=="None" or comment=="keep":
312 comment = comments[io]
313 elif (iov and comments[io] not in comment) or (not iov and adjust):
314 comment += " // " + comments[io]
315 if io>0 and since!=until and 'ALL' not in moduleList:
316 author=commentsSplit[io]
317 for m in moduleList:
318 if m in comments[io]:
319 author=user
320 break
321 else:
322 author=user
323 mgr.commitToDb(outSchema, folderPath, folderTag, (TileBchDecoder.BitPat_onl01 if onl else TileBchDecoder.BitPat_ofl01), author, comment, since, moduleList)
324
325
326since = iovList[0]
327until = (TileCalibCrest.MAXRUN,TileCalibCrest.MAXLBK)
328
329if curSuffix and not onl:
330
331 if len(comment) == 0:
332 comment=blobReader.getComment(since)
333 if comment.find("): ") > -1:
334 comment = comment[(comment.find("): ")) + 3:]
335
336 log.info("")
337 log.info("============================================================== ")
338 log.info("")
339 log.info("creating DB with CURRENT UPD4 tag")
340
341 folderTagUPD4 = blobReader.getFolderTag(folderPath, None, "UPD4" )
342 if folderTagUPD4 == folderTag:
343 log.warning("CURRENT UPD4 tag %s is identical to the tag in DB which was created already", folderTagUPD4)
344 folderTagUPD4 = blobReader.getFolderTag(folderPath, None, "UPD1" )
345 log.warning("Additional UPD1 DB with tag %s will be created instead", folderTagUPD4 )
346
347 mgr.updateFromDb(inSchema, folderPath, folderTagUPD4, since, 0)
348
349 #=== commit changes
350 mgr.commitToDb(outSchema, folderPath, folderTagUPD4, TileBchDecoder.BitPat_ofl01, user, comment, since, moduleList)
351
352
353if onlSuffix and not onl:
354
355 if len(comment)==0:
356 comment = blobReader.getComment(since)
357 if comment.find("): ") > -1:
358 comment = comment[(comment.find("): ")) + 3:]
359
360 log.info("")
361 log.info("============================================================== ")
362 log.info("")
363 log.info("creating DB with ONLINE status")
364
365 #--- create online bad channel manager
366 folderOnl = "/TILE/ONL01/STATUS/ADC"
367 folderTagOnl = "TILEONL01STATUSADC-HEAD"
368
369 mgrOnl = TileBchCrest.TileBchMgr()
370 mgrOnl.setLogLvl(logLevel)
371 mgrOnl.initialize(inSchema, folderOnl, folderTagOnl, since)
372
373 #=== print online channel status
374 if verbose:
375 log.info("============================================================== ")
376 log.info("online channel status BEFORE update")
377 mgrOnl.listBadAdcs()
378
379 #=== synchronize
380 for ros in range(1, 5):
381 for mod in range(0, 64):
382 for chn in range(0, 48):
383 statlo = mgr.getAdcStatus(ros, mod, chn, 0)
384 stathi = mgr.getAdcStatus(ros, mod, chn, 1)
385
386 # remove all trigger problems first
387 for prb in [TileBchPrbs.TrigGeneralMask,
388 TileBchPrbs.TrigNoGain,
389 TileBchPrbs.TrigHalfGain,
390 TileBchPrbs.TrigNoisy]:
391 mgrOnl.delAdcProblem(ros, mod, chn, 0, prb)
392 mgrOnl.delAdcProblem(ros, mod, chn, 1, prb)
393 # and now set new trigger problems (if any)
394 if not statlo.isGood():
395 prbs = statlo.getPrbs()
396 for prb in prbs:
397 if prb in [TileBchPrbs.TrigGeneralMask,
398 TileBchPrbs.TrigNoGain,
399 TileBchPrbs.TrigHalfGain,
400 TileBchPrbs.TrigNoisy]:
401 mgrOnl.addAdcProblem(ros, mod, chn, 0, prb)
402 mgrOnl.addAdcProblem(ros, mod, chn, 1, prb)
403
404 #--- add IgnoreInHlt if either of the ADCs has isBad
405 #--- add OnlineGeneralMaskAdc if the ADCs has isBad
406 if statlo.isBad() and stathi.isBad():
407 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.IgnoredInHlt)
408 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineGeneralMaskAdc)
409 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.IgnoredInHlt)
410 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineGeneralMaskAdc)
411 elif statlo.isBad():
412 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.IgnoredInHlt)
413 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineGeneralMaskAdc)
414 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.IgnoredInHlt)
415 mgrOnl.delAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineGeneralMaskAdc)
416 elif stathi.isBad():
417 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.IgnoredInHlt)
418 mgrOnl.delAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineGeneralMaskAdc)
419 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.IgnoredInHlt)
420 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineGeneralMaskAdc)
421 else:
422 #--- delete IgnoreInHlt and OnlineGeneralMaskAdc if both ADCs are not Bad
423 mgrOnl.delAdcProblem(ros, mod, chn, 0, TileBchPrbs.IgnoredInHlt)
424 mgrOnl.delAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineGeneralMaskAdc)
425 mgrOnl.delAdcProblem(ros, mod, chn, 1, TileBchPrbs.IgnoredInHlt)
426 mgrOnl.delAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineGeneralMaskAdc)
427
428 #--- add OnlineBadTiming if either of the ADCs has isBadTiming
429 if statlo.isBadTiming() or stathi.isBadTiming():
430 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineBadTiming)
431 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineBadTiming)
432 else:
433 #--- delete OnlineBadTiming if the both ADCs has not isBadTiming
434 mgrOnl.delAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineBadTiming)
435 mgrOnl.delAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineBadTiming)
436
437 #--- add OnlineTimingDmuBcOffsetPos if either of the ADCs has isTimingDmuBcOffsetPos
438 if statlo.isTimingDmuBcOffsetPos() or stathi.isTimingDmuBcOffsetPos():
439 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineTimingDmuBcOffsetPos)
440 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineTimingDmuBcOffsetPos)
441 else:
442 #--- delete OnlineTimingDmuBcOffsetPos if the both ADCs has not isTimingDmuBcOffsetPos
443 mgrOnl.delAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineTimingDmuBcOffsetPos)
444 mgrOnl.delAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineTimingDmuBcOffsetPos)
445
446 #--- add OnlineTimingDmuBcOffsetNeg if either of the ADCs has isTimingDmuBcOffsetNeg
447 if statlo.isTimingDmuBcOffsetNeg() or stathi.isTimingDmuBcOffsetNeg():
448 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineTimingDmuBcOffsetNeg)
449 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineTimingDmuBcOffsetNeg)
450 else:
451 #--- delete OnlineTimingDmuBcOffsetNeg if the both ADCs has not isTimingDmuBcOffsetNeg
452 mgrOnl.delAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineTimingDmuBcOffsetNeg)
453 mgrOnl.delAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineTimingDmuBcOffsetNeg)
454
455 #--- add OnlineWrongBCID if either of the ADCs has isWrongBCID
456 if statlo.isWrongBCID() or stathi.isWrongBCID():
457 mgrOnl.addAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineWrongBCID)
458 mgrOnl.addAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineWrongBCID)
459 else:
460 #--- delete OnlineWrongBCID if the both ADCs has not isWrongBCID
461 mgrOnl.delAdcProblem(ros, mod, chn, 0, TileBchPrbs.OnlineWrongBCID)
462 mgrOnl.delAdcProblem(ros, mod, chn, 1, TileBchPrbs.OnlineWrongBCID)
463
464
465 #=== print online channel status
466 if verbose:
467 log.info("online channel status AFTER update")
468 mgrOnl.listBadAdcs()
469
470 #=== commit changes
471 mgrOnl.commitToDb(outSchema, folderOnl, folderTagOnl, TileBchDecoder.BitPat_onl01, user, comment, since, moduleList)
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)