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