ATLAS Offline Software
DeMoUpdate.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 # Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 # Author : Benjamin Trocme (CNRS/IN2P3 - LPSC Grenoble) - 2017 - 2023
4 # Python 3 migration by Miaoran Lu (University of Iowa)- 2022
5 #
6 # Queries the defect database, computes and displays the data losses.
7 # On request update the year stats.
8 #
9 # Documentation: https://twiki.cern.ch/twiki/bin/viewauth/Atlas/DataQualityDemo
10 
11 
12 import os, sys, socket, pathlib, errno
13 
14 import time
15 
16 from ROOT import TFile
17 from ROOT import TH1F,TProfile
18 from ROOT import TCanvas,TPaveText
19 from ROOT import kBlack,kAzure,kBlue,kGreen,kRed
20 from ROOT import gStyle
21 from ROOT import gROOT
22 from ROOT import TLatex,TText
23 gROOT.SetBatch(False)
24 
25 import xmlrpc.client
26 
27 sys.path.append("/afs/cern.ch/user/l/larmon/public/prod/Misc")
28 from LArMonCoolLib import GetLBTimeStamps,GetOnlineLumiFromCOOL,GetOfflineLumiFromCOOL,GetLBDuration,GetReadyFlag,GetNumberOfCollidingBunches
29 
30 from DeMoLib import strLumi,plotStack,initializeMonitoredDefects,retrieveYearTagProperties,MakeTH1,MakeTProfile,SetXLabel
31 import DQDefects
32 
33 sys.path.append("/afs/cern.ch/user/l/larcalib/LArDBTools/python/")
34 import showEventVeto,showEventVetoNoLumi
35 
36 from DQUtils import fetch_iovs
37 
38 global startrun
39 global endrun
40 
41 global debug
42 debug = False
43 #debug = True
44 
45 passfile = open("/afs/cern.ch/user/l/larmon/public/atlasdqmpass.txt")
46 passwd = passfile.read().strip(); passfile.close()
47 dqmapi = xmlrpc.client.ServerProxy('https://%s@atlasdqm.cern.ch'%(passwd))
48 
49 #scriptdir = str(pathlib.Path(__file__).parent.resolve())
50 runListDir = "./YearStats-common"
51 
52 
53 
55 def sort_period(text):
56  letter = "".join([i for i in text if not i.isdigit()])
57  number = "".join([i for i in text if i.isdigit()])
58  return (letter, int(number))
59 
60 def printProp(varname):
61  print("**",varname,"**")
62  if hasattr(sys.modules[__name__],varname):
63  print(getattr(sys.modules[__name__],varname))
64 
65 
66 
67 def listify(l):
68  if len(l)==0: return ''
69  elif len(l)==1: return str(l[0])
70  l.sort()
71  interval=False
72  a = ''
73  for i in range(len(l)-1):
74  if interval:
75  if l[i+1]-l[i]==1: pass
76  else: a += str(l[i])+' '; interval=False
77  else:
78  a += str(l[i])
79  if l[i+1]-l[i]==1: a += '-'; interval=True
80  else: a += ' '
81  a += str(l[-1])
82  return a
83 
84 
85 def findLB(lbts,startOfVetoPeriod):
86  # Find the lumiblock where a veto period starts
87  for i in list(lbts.keys()):
88  if (startOfVetoPeriod>lbts[i][0] and startOfVetoPeriod<lbts[i][1]):
89  return i
90  return i
91 
92 
94 def printBoth(string0,boolean,f):
95  # Print and, if the boolean is true, also write to the provided file
96  print(string0)
97  if boolean:# Also write on txt file
98  f.write(string0+'\n')
99  return
100 
101 def singleRunReport(runNumber,dict1,dict2,directory,defects,veto,exactVetoComput):
102  # Print single run report. Only printing, no computation
103  import string
104 
105  runDir = directory+"/Run"
106 
107  if dict1['signoff'] == "DONE" or dict1['signoff'] == "FINAL OK":
108  repOnDisk = True
109  f = open(runDir+'/%s.txt' % (runNumber), 'w')
110  else:
111  repOnDisk = False
112  f = open(runDir+'/dummy.txt', 'w')
113 
114  printBoth('Run start : %s'%dict1['Start'],repOnDisk,f)
115  printBoth('Run stop : %s'%dict1['Stop'],repOnDisk,f)
116  printBoth('LB with ATLAS ready = %9s'%(listify(dict1["readyLB"])),repOnDisk,f)
117  printBoth('LB with ATLAS ready and no global defect = %9s'%(listify(dict1["readyLB_globalFilter"])),repOnDisk,f)
118  printBoth('Nb of bunches = %d'%(dict1['nBunches']),repOnDisk,f)
119  printBoth('Peak lumi = %.1e'%(dict1['peakLumi']*1e30),repOnDisk,f)
120  printBoth('Integrated luminosity used for normalis. = %s'%(strLumi(dict1['Lumi'],"ub",False,True)),repOnDisk,f)
121  printBoth('%s GRL inefficiency : %.2f%% / %s'%(options["system"],dict1["ineffDefect_allIntol"],strLumi(dict1['Lumi']*dict1["ineffDefect_allIntol"]/100.,"ub",False,True)),repOnDisk,f)
122  for idef in (defects["globIntol"]):
123  if (len(dict2[idef])>0):
124  printBoth('Nb of LBs with %24s: %i -> %.2f%% (%s)'%(defectVeto["description"][idef].ljust(24),len(dict2[idef]),dict1["ineffDefect_%s"%(idef)],str(dict2[idef])),repOnDisk,f)
125  for idef in (defects["partIntol"]):
126  if (len(dict2[idef]["AllPartitions"])>0):
127  printBoth('Nb of LBs with %24s: %i -> %.2f%% (%s)'%(defectVeto["description"][idef].ljust(24),len(dict2[idef]["AllPartitions"]),dict1["ineffDefect_%s"%(idef)],str(dict2[idef]["AllPartitions"])),repOnDisk,f)
128  if len(veto["all"])>0:
129  if exactVetoComput:
130  printBoth('LAr veto inefficiency : %.3f%%'%(dict1["ineffVeto_allVeto"]),repOnDisk,f)
131  else:
132  printBoth('LAr veto inefficiency (rough computat.): %.3f%%'%(dict1["ineffVeto_allVeto"]),repOnDisk,f)
133  for iVeto in veto["all"]:
134  printBoth('%s veto inefficiency : %.3f%%'%(defectVeto["description"][iVeto],dict1["ineffVeto_%s"%(iVeto)]),repOnDisk,f)
135  f.close()
136 
137  return
138 
139 
141 def extractNamePartition(foundDefect):
142  # Parse the defect name, return name, partition where available
143  defectName = ""
144  defectPart = ""
145  if (foundDefect.startswith("PIXEL")): # [PIXEL]_[PARTITION]_[NAME]
146  defectSplitted = foundDefect.split("_",2)
147  if len(defectSplitted) > 2:
148  defectPart=defectSplitted[1]
149  defectName=defectSplitted[2]
150  elif (foundDefect.startswith("SCT")): # SCT_[NAME]
151  defectSplitted = foundDefect.split("_",1)
152  if len(defectSplitted) > 1:
153  defectName=defectSplitted[1]
154  elif (foundDefect.startswith("TRT")): # TRT_[NAME]
155  defectSplitted = foundDefect.split("_",1)
156  if len(defectSplitted) > 1:
157  defectName=defectSplitted[1]
158  elif (foundDefect.startswith("LAR")): # [LAR]_[PART]_[Name] or [LAR]_[Name] - No "_" in any [NAME]
159  defectSplitted = foundDefect.split("_",2)
160  if len(defectSplitted) == 2: # LAR_[NAME]
161  defectName=defectSplitted[1]
162  elif len(defectSplitted) == 3: # LAR_[PART]_[NAME]
163  defectPart=defectSplitted[1]
164  defectName=defectSplitted[2]
165  elif (foundDefect.startswith("CALO_ONLINEDB")):# CALO_ONLINEDB_[NAME] (only for CALO_ONLINEDB_LOWMU) - Accounted to LAr
166  defectSplitted = foundDefect.split("_",2)
167  if len(defectSplitted) > 2:
168  defectName=defectSplitted[2]
169  elif (foundDefect.startswith("TILE")): # [TILE]_[PART]_[Name]
170  defectSplitted = foundDefect.split("_",2)
171  if len(defectSplitted) > 2:
172  defectPart=defectSplitted[1]
173  defectName=defectSplitted[2]
174  elif (foundDefect.startswith("MS")): # MS_[SUBDETECTOR]_[PARTITION]_[NAME]
175  defectSplitted = foundDefect.split("_",3)
176  if len(defectSplitted) > 3:
177  systemAffected=defectSplitted[1]
178  defectPart=defectSplitted[2]
179  defectName=defectSplitted[3]
180  elif (foundDefect.startswith("MCP")): # MCP_[NAME]
181  defectSplitted = foundDefect.split("_",1)
182  if len(defectSplitted) > 1:
183  defectName=defectSplitted[1]
184  elif (foundDefect.startswith("ID")):# ID_[NAME]
185  defectSplitted = foundDefect.split("_",1)
186  if len(defectSplitted) > 1:
187  defectName=defectSplitted[1]
188  elif (foundDefect.startswith("JET")):# JET_[NAME]
189  defectSplitted = foundDefect.split("_",1)
190  if len(defectSplitted) > 1:
191  defectName=defectSplitted[1]
192  elif (foundDefect.startswith("MET")):# MET_[NAME]
193  defectSplitted = foundDefect.split("_",1)
194  if len(defectSplitted) > 1:
195  defectName=defectSplitted[1]
196  elif (foundDefect.startswith("EGAMMA")):# EGAMMA_[NAME]_[PART] or EGAMMA_[NAME]
197  if ("BARREL" in foundDefect or "ENDCAP" in foundDefect or "FORWARD" in foundDefect): #EGAMMA_[NAME]_[PART]
198  defectSplitted = foundDefect.split("_",2)
199  if len(defectSplitted) > 2:
200  defectName=defectSplitted[1]
201  defectPart=defectSplitted[2]
202  else:
203  defectSplitted = foundDefect.split("_",1)
204  if len(defectSplitted) > 1:
205  defectName=defectSplitted[1]
206  elif (foundDefect.startswith("TAU")): # TAU_[PART]_[NAME]
207  defectSplitted = foundDefect.split("_",2)
208  if len(defectSplitted) > 2:
209  defectPart=defectSplitted[1]
210  defectName=defectSplitted[2]
211  elif (foundDefect.startswith("CALO")): # CALO_[PART]_[NAME]
212  defectSplitted = foundDefect.split("_",2)
213  if len(defectSplitted) > 2:
214  defectPart=defectSplitted[1]
215  defectName=defectSplitted[2]
216  elif (foundDefect.startswith("BTAG")):# BTAG_[NAME]
217  defectSplitted = foundDefect.split("_",1)
218  if len(defectSplitted) > 1:
219  defectName=defectSplitted[1]
220  elif (foundDefect.startswith("TRIG")): # TRIG_L1_[NAME] TRIG_HLT_[NAME]
221  defectSplitted = foundDefect.split("_",2)
222  if len(defectSplitted) > 2:
223  defectName=defectSplitted[2]
224  elif (foundDefect.startswith("LUMI")): # LUMI_[NAME]
225  defectSplitted = foundDefect.split("_",1)
226  if len(defectSplitted) > 1:
227  defectName=defectSplitted[1]
228  elif (foundDefect.startswith("ALFA")): # ALFA_[NAME]
229  defectSplitted = foundDefect.split("_",1)
230  if len(defectSplitted) > 1:
231  defectName=defectSplitted[1]
232  elif (foundDefect.startswith("AFP")): # AFP_[NAME] or AFP_[PART]_[NAME]
233  if ("_A_" in foundDefect or "_C_" in foundDefect): #AFP_[PART]_[NAME]
234  defectSplitted = foundDefect.split("_",2)
235  if len(defectSplitted) > 2:
236  defectName=defectSplitted[2]
237  defectPart=defectSplitted[1]
238  if ("_A_NEAR_" in foundDefect or "_C_NEAR_" in foundDefect or "_A_FAR_" in foundDefect or "_C_FAR_" in foundDefect): #AFP_[PART]_[NEAR/FAR]_[NAME]
239  defectSplitted = foundDefect.split("_",3)
240  if len(defectSplitted) > 3:
241  defectName=defectSplitted[3]
242  defectPart="%s_%s"%(defectSplitted[1],defectSplitted[2])
243  else:
244  defectSplitted = foundDefect.split("_",1)
245  if len(defectSplitted) > 1:
246  defectName=defectSplitted[1]
247  elif (foundDefect.startswith("LCD")): # LCD_[NAME]
248  defectSplitted = foundDefect.split("_",1)
249  if len(defectSplitted) > 1:
250  defectName=defectSplitted[1]
251  elif (foundDefect.startswith("ZDC")): # ZDC_[NAME]
252  defectSplitted = foundDefect.split("_",1)
253  if len(defectSplitted) > 1:
254  defectName=defectSplitted[1]
255  elif (foundDefect.startswith("GLOBAL")): # GLOBAL_[NAME]
256  defectSplitted = foundDefect.split("_",1)
257  if len(defectSplitted) > 1:
258  defectName=defectSplitted[1]
259 
260  return defectName, defectPart
261 
262 def retrieveDefectsFromDB(run, defectTag, grlDef,signOffDefects):
263  # Get the list of defects for this run, parse them
264  defectDatabase = DQDefects.DefectsDB(tag=defectTag)
265  system_defects = []
266  for iPrefix in grlDef["prefix"]:
267  system_defects += [d for d in (defectDatabase.defect_names | defectDatabase.virtual_defect_names) if (d.startswith(iPrefix))]
268  for iSignOff in signOffDefects.keys():
269  if (signOffDefects[iSignOff] != ""):
270  system_defects += signOffDefects[iSignOff]
271  retrievedDefects = defectDatabase.retrieve((run, 1), (run+1, 0), system_defects)
272  parsed_defects = {}
273  for rd in retrievedDefects:
274  defectName, defectPart = extractNamePartition(rd.channel)
275  if not( defectName is None and defectName is None):
276  parsed_defects[rd] = [defectName, defectPart]
277  return parsed_defects
278 
279 
281 def updateRunList(year=time.localtime().tm_year):
282  # Update list of runs. If there is not an up-to-date file, get the latest info from the atlas dqm APIs'''
283  print("Checking run list for year",year)
284 
285  latestRun=dqmapi.get_latest_run()
286  recentRuns = dqmapi.get_run_beamluminfo({'low_run':str(latestRun-1000),'high_run':str(latestRun)})
287  def writeRuns(outfile, fileRuns = []):
288  for r in sorted(recentRuns.keys(), key=int):
289  if (recentRuns[r][2]): # ATLAS ready
290  if r not in fileRuns:
291  fileRuns.append(r)
292  print("Adding the ATLAS ready run: %s"%r)
293  outfile.write("%s\n"%r)
294  allRunListDat = "%s/%s/runlist-%s-AtlasReady.dat"%(runListDir,str(year),str(year))
295  if os.path.isfile(allRunListDat):
296  fRunList = open(allRunListDat,'r+')
297  fileRuns = [l.strip() for l in fRunList.readlines() ]
298  if len(fileRuns)>0:
299  latestFileRun = max([int(r) for r in fileRuns])
300  else: latestFileRun = 0
301  if latestFileRun < latestRun:
302  print("Run file",allRunListDat,"is not up-to-date")
303  print("Latest run is ",latestRun, " while latest run in file is",latestFileRun)
304  print("Will check ATLAS ready filters & update if needed")
305  writeRuns(fRunList, fileRuns)
306  fRunList.close()
307  sys.exit()
308  else:
309  print("The run list for year ",year," is not available... please create one by hand")
310  sys.exit()
311 
312 
314 def getRunInfo(runlist, defectTag="HEAD"):
315  # Retrieve run characteristics (period, time...)
316  possSignoffDefects = sum(list(signOff.values()),[])
317  run_signoffDefects = dqmapi.get_defects_lb({'run_list':runlist},possSignoffDefects,defectTag,True,True)
318 
319  infokeys = ["Run type", "Project tag", "Partition name", "Number of events passing Event Filter", "Run start", "Run end", "Number of luminosity blocks", "Data source", "Detector mask", "Recording enabled", "Number of events in physics streams" ]
320 
321  defectvals = [ "startlb", "endlb", "status", "time"]
322 
323  beamkeys = ["Max beam energy during run", "Stable beam flag enabled during run", "ATLAS ready flag enabled during run", "Total integrated luminosity", "ATLAS ready luminosity (/nb)"]
324 
325  for rd in run_signoffDefects.keys():
326  for defect in run_signoffDefects[rd].keys():
327  run_signoffDefects[rd][defect] = { ik:li for ik,li in zip(defectvals,run_signoffDefects[rd][defect][0]) }
328 
329  run_spec = {'run_list':runlist, 'stream': 'physics_CosmicCalo', 'source': 'tier0'}
330  run_info = dqmapi.get_run_information(run_spec)
331  for ri in run_info.keys():
332  run_info[ri] = { ik:li for ik,li in zip(infokeys,run_info[ri]) }
333 
334  beam_info = dqmapi.get_run_beamluminfo(run_spec)
335  for bi in beam_info.keys():
336  beam_info[bi] = { ik:li for ik,li in zip(beamkeys,beam_info[bi]) }
337 
338  run_periods = dqmapi.get_data_periods({'run_list':runlist})
339  allinfo = {}
340  def addDetails(inputDict, col=None):
341  for r in inputDict.keys():
342  run = int(r)
343  if run not in allinfo.keys():
344  allinfo[run] = {}
345  if col is not None:
346  allinfo[run][col] = inputDict[r]
347  else:
348  allinfo[run].update(inputDict[r])
349  addDetails(run_info)
350  addDetails(beam_info)
351  addDetails(run_periods, "periods")
352  addDetails(run_signoffDefects, "signoffDefects")
353 
354  # only take first period??
355  for r in allinfo.keys():
356  try:
357  allinfo[r]["period"] = allinfo[r]["periods"][0]
358  except IndexError:
359  print("Weird list of periods for",r,":",allinfo[r]["periods"])
360  allinfo[r]["period"]="?"
361 
362 
363  return allinfo
364 
365 
366 
369 from argparse import RawTextHelpFormatter,ArgumentParser
370 
371 parser = ArgumentParser(description='',formatter_class=RawTextHelpFormatter)
372 # General arguments
373 parser.add_argument('-y','--year',dest='year',default = str(time.localtime().tm_year),help='Year [Default: '+str(time.localtime().tm_year)+']. May also include special conditions such as 5TeV, hi...',action='store')
374 parser.add_argument('-t','--tag',dest='tag',default = "AtlasReady",help='Defect tag [Default: "AtlasReady"]',action='store')
375 parser.add_argument('-s','--system',dest='system',default="LAr",help='System: LAr, Pixel, IDGlobal, RPC... [Default: "LAr"]',action='store')
376 parser.add_argument('-b','--batch',dest='batchMode',help='Batch mode',action='store_true')
377 # Different options.
378 parser.add_argument('--runListUpdate',dest='runListUpdate',help='Update of the run list for the AtlasReady tag. No other action allowed. Exit when done.',action='store_true')
379 parser.add_argument('--weeklyReport',dest='weekly',help='Weekly report. No run range to specify, no year-stats update.',action='store_true')
380 # Selection of runs to be considered
381 parser.add_argument('--runRange',type=int,dest='runRange',default=[],help='Run or run range (in addition to RunList)',nargs='*',action='store')
382 parser.add_argument('--skipAlreadyUpdated',dest='skipAlreadyUpdated',help='Ignore completely runs that are already included in year stats',action='store_true')
383 parser.add_argument('--noGlobalFilter',dest='noGlobalFilter',help='Switch off the primary filter based on GLOBAL defects. So far, the global defects used are: "GLOBAL_LHC_50NS","GLOBAL_LHC_NONSTANDARD_BC","GLOBAL_LHC_LOW_N_BUNCHES","GLOBAL_LHC_NOBUNCHTRAIN","GLOBAL_LHC_COMMISSIONING","GLOBAL_LHC_HIGHBETA","GLOBAL_LOWMUCONFIG_IN_HIGHMU","LUMI_VDM","GLOBAL_NOTCONSIDERED (defined in DeMoLib.py)"',action='store_true')
384 # Option related to year stats
385 parser.add_argument('--resetYearStats',dest='resetYearStats',help='Reset year stats. To be used only the incremental update can not be used (for example, when runs were removed or when a defect of an already signed off run was changed)',action='store_true')
386 parser.add_argument('--updateYearStats',dest='updateYearStats',help='Update year stats with the new runs fully signed off',action='store_true')
387 # Veto options (relevant only for LAr)
388 parser.add_argument('--noVeto',dest='noVeto',help='Do not consider time-veto information',action='store_true')
389 parser.add_argument('--vetoLumiEvol',dest='vetoLumiEvolution',help='Plot the evolution of veto as a function of lumi',action='store_true')
390 parser.add_argument('--roughVetoComput',dest='exactVetoComput',help='Rough veto computation (no lumi weighting,no correlation with intol defect.)',action='store_false')
391 # Plotting, saving
392 parser.add_argument('--noPlot',dest='plotResults',help='Do not plot the results',action='store_false')
393 parser.add_argument('--saveHistos',dest='saveHistos',help='Save all histograms (NOT needed for year stats)',action='store_true')
394 parser.add_argument('--savePlots',dest='savePlots',help='Save all plots in Weekly dir',action='store_true')
395 # Characteristics of luminosity used for nirmalisation
396 parser.add_argument('--deliveredLumiNorm',dest='deliveredLumiNorm',help='Normalize by the delivered lumi',action='store_true')
397 parser.add_argument('--onlineLumiNorm',dest='onlineLumiNorm',help='Normalize by the online lumi',action='store_true')
398 
399 
400 args = parser.parse_args()
401 # parser.print_help()
402 
403 if args.batchMode:
404  gROOT.SetBatch(True)
405 
406 print("Current time: %s"%(time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())))
407 print("Currently running from",os.getcwd(),"on",socket.gethostname())
408 options = {}
409 yearTagProperties = {}
410 partitions = {}
411 grlDef = {}
412 defectVeto = {}
413 veto = {}
414 signOff = {}
415 runlist = {'filename':"",'primary':[],'toprocess':[],'weeklyfile':[],'weekly-dqmeeting':"",'roughVeto':[]}
416 
417 if args.runListUpdate:
418  updateRunList(year=args.year)
419  print("Done.I am exiting...")
420  sys.exit()
421 
422 options = args.__dict__
423 initializeMonitoredDefects(options['system'],partitions,grlDef,defectVeto,veto,signOff,options['year'],options['tag'],runlist)
424 yearTagProperties = retrieveYearTagProperties(options['year'],options['tag'])
425 
426 if debug:
427  printProp("yearTagProperties")
428  printProp("partitions")
429  printProp("grlDef")
430  printProp("defectVeto")
431  printProp("veto")
432  printProp("signOff")
433 
434 # Choose between recorded and delivered luminosity - By default, use the delivered one
435 options['recordedLumiNorm'] = not options['deliveredLumiNorm']
436 # tag to access defect database and COOL database (for veto windows) - Defined in DeMoLib.py
437 options['defectTag']=yearTagProperties["Defect tag"]
438 if len(yearTagProperties["Veto tag"])>0: # The veto tag is not defined for all systems
439  options['vetoTag']=yearTagProperties["Veto tag"]
440 else:
441  options['vetoTag']=""
442 options['yearStatsDir'] = "YearStats-%s/%s/%s"%(options['system'],options['year'],options['tag'])
443 
444 # No run range active, no update years stats, no filter... in weekly report
445 if (options['weekly']):
446  options['tag'] = "AtlasReady" # Weekly reports are relevant only for the AtlasReady tag
447  options['updateYearStats'] = False
448  options['runRange'] = []
449 
450 # Token to avoid having multiple yearStats update in the same time
451 if options['updateYearStats']:
452  tokenName = "DeMo-%s-%s-%s.token"%(options['system'],options['year'],options['tag'])
453  if os.path.exists(tokenName):
454  print("A different DeMoUpdate is apparently running (or it was not properly ended recently). This may cause trouble when updating yearStats")
455  os.system("ls -ltr %s"%tokenName)
456  print("If you are sure that it is not the case, you can remove the %s..."%tokenName)
457  print("If you are not the owner, contact the DQ coordinator")
458  sys.exit()
459  else:
460  os.system("touch %s"%tokenName)
461 
462 startrun = 0
463 endrun = 1e12
464 if len(options['runRange']) == 1: # Single run
465  startrun = options['runRange'][0]
466  endrun = options['runRange'][0]
467 if len(options['runRange']) == 2: # Run range
468  startrun = options['runRange'][0]
469  endrun = options['runRange'][1]
470 
471 # runlist['primary'] contains all runs extracted from the runList convoluted with the run range (if any was defined - not mandatory - Deactivated for weeklyReport)
472 # runlist['toprocess'] is derived from the primary list. Some runs may be removed depending on the options (skipAlreadyUpdated) and also for the weekly report (see below)
473 # runlist['toprocess'] contains all run that will be processed and that will be displayed in the final table / plots
474 runListFilename = "%s/%s/%s"%(runListDir,options['year'],runlist['filename'])
475 if os.path.exists(runListFilename):
476  fRunList = open(runListFilename,'r')
477  for iRun in fRunList.readlines():
478  if (int(iRun) >= startrun and int(iRun) <= endrun):
479  runlist['primary'].append(int(iRun))
480  fRunList.close()
481 else:
482  print("The %s file does not exist. Create it or choose a different tag."%runListFilename)
483  sys.exit()
484 
485 if (len(runlist['primary']) == 0):
486  print("No run found -> Exiting")
487  sys.exit()
488 
489 roughVetoFilename = runListDir+"/%s/%s/roughVeto-%s.dat"%(options['system'],options['year'],options['year'])
490 if os.path.exists(roughVetoFilename):
491  fRoughVeto = open(roughVetoFilename,'r')
492  for iRun in fRoughVeto.readlines():
493  runlist['roughVeto'].append(int(iRun))
494  fRoughVeto.close()
495 
496 if len(veto["all"]) == 0:
497  options['noVeto'] = True
498  print("No veto information provided in DeMoLib.py")
499 else:
500  if options['noVeto']:
501  print("WARNING: I do not consider time veto information...")
502 
503 yearStatsArchiveFilename = '%s/TProfiles.root'%options['yearStatsDir']
504 if options['updateYearStats']:
505  if not os.path.exists(yearStatsArchiveFilename):
506  print("No archive file found in %s"%options['yearStatsDir'])
507  print("I am forcing the year stats reset...")
508  options['resetYearStats'] = True
509  elif os.path.getsize("%s/runs-ALL.dat"%options['yearStatsDir']) == 0.:
510  # Test here relevant at the beginning of the year when some runs have been reviewed at EXPR/BULK level (but not FINAL hence no year stats)
511  # In such a case a TProfiles.root file may exist even if no update was made
512  # April 18: I am not sure that this situation is still relevant...
513  print("No run found in %s"%options['yearStatsDir'])
514  print("I am forcing the year stats reset...")
515  options['resetYearStats'] = True
516 
517 # Reseting the year stats - Allowed even if updateYearStats not requested
518 if options['resetYearStats']:
519  print("WARNING: I am going to reset the %s stats..."%options['yearStatsDir'])
520  if (options['batchMode']): # In batch mode, no confirmation requested
521  confirm = "y"
522  else:
523  confirm = input("Please confirm by typing y: ")
524 
525  if ("y" in confirm):
526  print("I reset the %s stats"%options['yearStatsDir'])
527  os.system("rm -f %s/lumi*.dat"%options['yearStatsDir'])
528  os.system("rm -f %s/runs*.dat"%options['yearStatsDir'])
529  os.system("rm -f %s/errors.log"%options['yearStatsDir'])
530  os.system("rm -f %s/loss*.dat"%options['yearStatsDir'])
531  os.system("rm -f %s/Run/*.txt"%options['yearStatsDir'])
532  os.system("rm -f %s"%(yearStatsArchiveFilename))
533  fLastReset = open("%s/lastResetYS.dat"%options['yearStatsDir'],"w")
534  fLastReset.write("%s\n"%(time.strftime("%a, %d %b %H:%M",time.localtime())))
535  fLastReset.close()
536 
537 # Open log file : errors and not yet signed off runs
538 errorLogFile = open("%s/errors.log"%options['yearStatsDir'],'a')
539 notYetSignedOffRuns = open('%s/runs-notYetSignedOff.dat'%options['yearStatsDir'],'w')
540 
541 # Retrieve all characteristics of the runs of the primary list (start, end, nb of LB, ATLAS ready LB...)x
542 runinfo = getRunInfo(runlist['primary'],options['defectTag'])
543 
544 # If the run is too recent (< 2 hours) or still ongoing, remove it from the runlist['primary']
545 for run in runlist['primary']:
546  if runinfo[run]["Run end"] == 0:
547  print("Run",run,"is still ongoing")
548  runinfo.pop(run)
549  runlist['primary'].pop(runlist['primary'].index(run))
550  if (time.time() - runinfo[run]["Run end"])/3600 < 2:
551  print("Run",run,"ended very recently. It is best to wait for the defects DBs to properly populate")
552  runinfo.pop(run)
553  runlist['primary'].pop(runlist['primary'].index(run))
554 
555 # Fill the list of runs to be considered
556 oldRunsNotYetignedOff = []
557 if options['weekly']: # Weekly report - Look for the last 7-days runs + the signed off runs in the last 7 days
558  print("===== Weekly =====")
559  print("I am looking for all runs taken or signed off in the past week...")
560  options['savePlots'] = True
561  options['updateYearStats'] = False
562  oneWeek = 7*24*3600 # Nb of seconds in one week
563  for run in sorted(runlist['primary'], key=int, reverse=True):
564  if "signoffDefects" not in runinfo[run].keys():
565  print("Run",run, "has no defects... perhaps it is still ongoing?")
566  continue
567  defects = runinfo[run]["signoffDefects"].keys()
568  statuses = [ runinfo[run]["signoffDefects"][d]["status"] for d in defects ]
569 
570  fullySignedOff = True
571  if any('Red' in s for s in statuses):
572  fullySignedOff = False
573  if (time.time()-runinfo[run]["Run start"] > oneWeek):
574  oldRunsNotYetignedOff.append(run)
575 
576  signOffTime = 0
577  if any('Green' in s for s in statuses):
578  signOffTime = max([ runinfo[run]["signoffDefects"][d]["time"] for d in defects if runinfo[run]["signoffDefects"][d]["status"] == "Green" ] )
579  if (fullySignedOff and time.time()-signOffTime < oneWeek):
580  print("Old run",run,"was fully signed off during the last seven days")
581  runlist['toprocess'].append(run)
582  elif (time.time()-runinfo[run]["Run start"] < oneWeek):
583  print("Run",run,"was acquired during the last seven days")
584  runlist['toprocess'].append(run)
585  if (os.path.exists("%s/%s/runlist-weekly.dat"%(runListDir,options['year']))):
586  weeklyFile = open("%s/%s/runlist-weekly.dat"%(runListDir,options['year']),'r')
587  print("I found a runlist-weekly.dat file and will add some runs...")
588  for iRun in weeklyFile.readlines():
589  if runlist['weekly-dqmeeting'] == "": # The first line of the weekly file contains the date of the DQ meeting
590  runlist['weekly-dqmeeting'] = iRun
591  continue
592  runlist['weeklyfile'].append(int(iRun))
593  if (int(iRun) not in runlist['toprocess'] and int(iRun) in runlist['primary']):
594  print(iRun)
595  runlist['toprocess'].append(int(iRun))
596  weeklyFile.close()
597 
598  runlist['toprocess'].sort(reverse=False)
599  print("I will process these runs :",runlist['toprocess'])
600 else: # Default option (i.e. not a weekly report). The possible run range was already filtered in the runlist['primary'] list
601  runlist['toprocess'] = runlist['primary']
602 
603 if len(runlist['toprocess']) == 0:
604  print("No run to process")
605  print("Please double check your run range (if any) or update the runlist file...")
606  if options['updateYearStats']:
607  os.system("rm -f %s"%tokenName)
608  sys.exit()
609 
610 periodListCurrent = {} # Dictionary of all runs referenced by period name
611 newPeriodInYearStats = [] # List of periods not yet considered
612 bool_newRunsInYearStats = False
613 
614 allperiods_full = list(set([ p for irun in runlist['toprocess'] for p in runinfo[irun]["periods"] ])) # should we just take the first period listed??
615 allperiods = list(set([runinfo[irun]["period"] for irun in runlist['toprocess'] if runinfo[irun]["period"] != "?"])) # should we just take the first period listed??
616 print("Periods (full)", allperiods_full)
617 print("Periods",allperiods)
618 for p in allperiods:
619  for run in runlist['toprocess']:
620  if run in runinfo.keys() and p in runinfo[run]["periods"]:
621  if p not in periodListCurrent:
622  periodListCurrent[p] = [run]
623  else:
624  periodListCurrent[p].append(run)
625 
626 if (len(allperiods) == 0 and options['updateYearStats']):
627  print("No period available yet for the runs to process")
628  print("I am exiting...")
629  if options['updateYearStats']:
630  os.system("rm -f %s"%tokenName)
631  sys.exit()
632 
633 for irun in runinfo.keys():
634  runinfo[irun]['newInYearStats'] = False
635 
636 for iper in allperiods:
637  periodFileName = "%s/runs-%s.dat"%(options['yearStatsDir'],iper)
638  if os.path.exists(periodFileName): # This period is already treated in year stats. Look for new runs
639  f = open(periodFileName,'r')
640  existingRuns = f.readlines()
641  for irun in periodListCurrent[iper]:
642  if (options['updateYearStats'] and "%d\n"%(irun) not in existingRuns):
643  runinfo[irun]['newInYearStats'] = True
644  else:
645  runinfo[irun]['newInYearStats'] = False
646  f.close()
647  else: # This is a period not yet treated in year stats.
648  periodToBeAdded = False
649  for irun in periodListCurrent[iper]:
650  if options['updateYearStats']:
651  runinfo[irun]['newInYearStats'] = True
652  periodToBeAdded = True
653  else:
654  runinfo[irun]['newInYearStats'] = False
655  if options['updateYearStats'] and periodToBeAdded:
656  print("I am going to add period %s in year stats!"%(iper))
657  newPeriodInYearStats.append(iper)
658 
659 for iper in list(periodListCurrent.keys()): # Loop on all periods found and print the runs to be updated
660  for irun in periodListCurrent[iper]:
661  if runinfo[irun]['newInYearStats']:
662  print("I am going to add run %d (period %s) in %s stats (provided that it is fully signed off - Not yet known...)!"%(irun,runinfo[irun]['period'],options['year']))
663  else:
664  if (options['skipAlreadyUpdated']):
665  runinfo.pop(irun)
666  runlist['toprocess'].pop(runlist['toprocess'].index(irun))
667  print("%d was already processed in yearStats - I am complety skipping it..."%(irun))
668 
669 if (len(runlist['toprocess']) == 0):
670  print("No run to process :-). Exiting...")
671  if options['updateYearStats']:
672  os.system("rm -f %s"%tokenName)
673  sys.exit()
674 
675 
676 
677 runinfo['AllRuns'] = {}
678 runinfo['AllRuns']['Start'] = "-"
679 runinfo['AllRuns']['Stop'] = "-"
680 runinfo['AllRuns']['readyLB'] = "-"
681 runinfo['AllRuns']['readyLB_globalFilter'] = "-"
682 runinfo['AllRuns']['peakLumi'] = 0.
683 runinfo['AllRuns']['period'] = "-"
684 runinfo['AllRuns']['signoff'] = "-"
685 
686 
689 hProfRun_IntolDefect = {}
690 hProfRun_Veto = {}
691 
692 if (options['updateYearStats']):
693  hProfPeriod_IntolDefect = {}
694  hProfPeriod_Veto = {}
695 
696 allIntolDef = ["allIntol","allIntol_recov"] # New histograms defined to avoid double counting
697 
698 for idef in grlDef["intol"]+grlDef["intol_recov"]+allIntolDef: #Intolerable defects only
699  idefName = idef.split("__")[0] # Trick needed to get the defect name for the recoverable defect histogram
700  # Histogram of defect ineffiency per run
701  hProfRun_IntolDefect[idef] = MakeTProfile("hProfRun_Defect_%s"%(idef),"%s"%(defectVeto["description"][idefName]),"Lost luminosity (%)", -0.5,+0.5+len(runlist['toprocess']),len(runlist['toprocess'])+1,defectVeto["color"][idefName])
702  SetXLabel(hProfRun_IntolDefect[idef],runlist['toprocess'])
703  hProfRun_IntolDefect[idef].GetXaxis().SetBinLabel(len(runlist['toprocess'])+1,"All")
704  # If an update of year stats is requested, define empty histograms, retrieve the already known periods and fill the new histos
705  if (options['updateYearStats']):
706  periodListYear = [] # This is the period list used for the TProfile
707  profPeriodName = "hProfPeriod_IntolDefect_%s"%(idef)
708  if (not options['resetYearStats']): # Retrieve the already known period
709  file = TFile(yearStatsArchiveFilename)
710  hProfPeriod_archive = file.Get("%s_archive"%(profPeriodName))
711  for iBin in range(1,hProfPeriod_archive.GetNbinsX()): # Retrieve name of past periods
712  periodListYear.append(hProfPeriod_archive.GetXaxis().GetBinLabel(iBin))
713  file.Close()
714 
715  if len(periodListYear) != 0 or len(periodListCurrent) != 0: # At least one period found in current or past runs, otherwise no way to plot year stats
716  # Collect all periods (archived ones + new ones)
717  periodListYear = periodListYear + newPeriodInYearStats
718  periodListYear = sorted(periodListYear, key=sort_period) # The list of periods is now sorted
719  periodNbYear = len(periodListYear) # Number of periods
720  # Create the empty year stats TProfile histograms for the updated period list
721  hProfPeriod_IntolDefect[idef] = MakeTProfile(profPeriodName,"%s"%(defectVeto["description"][idefName]),"Lost luminosity (%)", -0.5,+0.5+periodNbYear,periodNbYear+1,defectVeto["color"][idefName])
722  SetXLabel(hProfPeriod_IntolDefect[idef],periodListYear)
723  hProfPeriod_IntolDefect[idef].GetXaxis().SetBinLabel(periodNbYear+1,"All") # In all bins, all runs
724  # Fill them with the previous period data
725  if (not options['resetYearStats']):
726  file = TFile(yearStatsArchiveFilename)
727  hProfPeriod_archive = file.Get("%s_archive"%(profPeriodName))
728  for iBin in range(1,periodNbYear+1): # Loop on all extended periods and check if already considered in past runs - Mandatory as periodListYear was sorted
729  for iBin2 in range(1,hProfPeriod_archive.GetNbinsX()):
730  if (hProfPeriod_IntolDefect[idef].GetXaxis().GetBinLabel(iBin) == hProfPeriod_archive.GetXaxis().GetBinLabel(iBin2)):
731  hProfPeriod_IntolDefect[idef].Fill(iBin-1,hProfPeriod_archive.GetBinContent(iBin2),hProfPeriod_archive.GetBinEntries(iBin2))
732  # And the last bin for all periods
733  hProfPeriod_IntolDefect[idef].Fill(len(periodListYear),hProfPeriod_archive.GetBinContent(hProfPeriod_archive.GetNbinsX()),hProfPeriod_archive.GetBinEntries(hProfPeriod_archive.GetNbinsX()))
734  file.Close()
735 
736 # Book histograms for time window veto
737 if (not options['noVeto']):
738  for iVeto in veto["all"]+["allVeto"]: # New "allVeto" histograms defined similarly as for defect - Not sure how to deal with double counting in veto but not problematic at first order.
739  hProfRun_Veto[iVeto] = MakeTProfile("hProfRun_Veto_%s"%(iVeto),"","Inefficiency - Time veto (%)",-0.5,+0.5+len(runlist['toprocess']),len(runlist['toprocess'])+1,defectVeto["color"][iVeto])
740  hProfRun_Veto[iVeto].SetMarkerColor(defectVeto["color"][iVeto])
741  SetXLabel(hProfRun_Veto[iVeto],runlist['toprocess'])
742  hProfRun_Veto[iVeto].GetXaxis().SetBinLabel(len(runlist['toprocess'])+1,"All")
743 
744  if (options['updateYearStats']):
745  profPeriodName = "hProfPeriod_Veto_%s"%(iVeto)
746  # Create the period TProfile - The extended period list is the same as for the defects
747  hProfPeriod_Veto[iVeto] = MakeTProfile(profPeriodName,"","Inefficiency - Time veto (%%) %s"%(defectVeto["description"][iVeto]), -0.5,+0.5+len(periodListYear),len(periodListYear)+1,defectVeto["color"][iVeto])
748  hProfPeriod_Veto[iVeto].SetMarkerColor(defectVeto["color"][iVeto])
749  SetXLabel(hProfPeriod_Veto[iVeto],periodListYear)
750  hProfPeriod_Veto[iVeto].GetXaxis().SetBinLabel(len(periodListYear)+1,"All")
751 
752  if (not options['resetYearStats']): # Fill with the previous period data
753  file = TFile(yearStatsArchiveFilename)
754  hProfPeriod_archive = file.Get("%s_archive"%(profPeriodName))
755  for iBin in range(1,periodNbYear+1): # Loop on all extended periods and check if already considered in past runs - Mandatory as periodListYear was sorted
756  for iBin2 in range(1,hProfPeriod_archive.GetNbinsX()):
757  if (hProfPeriod_Veto[iVeto].GetXaxis().GetBinLabel(iBin) == hProfPeriod_archive.GetXaxis().GetBinLabel(iBin2)):
758  hProfPeriod_Veto[iVeto].Fill(iBin-1,hProfPeriod_archive.GetBinContent(iBin2),hProfPeriod_archive.GetBinEntries(iBin2))
759  # And the last bin for all periods
760  hProfPeriod_Veto[iVeto].Fill(len(periodListYear),hProfPeriod_archive.GetBinContent(hProfPeriod_archive.GetNbinsX()),hProfPeriod_archive.GetBinEntries(hProfPeriod_archive.GetNbinsX()))
761  file.Close()
762 
763 h1Run_IntLuminosity = MakeTH1("h1_IntLumi","Run","Integrated luminosity", -0.5,+0.5+len(runlist['toprocess']),len(runlist['toprocess'])+1,kBlack)
764 SetXLabel(h1Run_IntLuminosity,runlist['toprocess'])
765 h1Run_IntLuminosity.GetXaxis().SetBinLabel(len(runlist['toprocess'])+1,"All")
766 
767 
768 if (options['updateYearStats'] and periodNbYear>0): # If update is required, it is now sure that some periods exist. Create a TH1 to store the integrated luminosity
769  h1Per_IntLumi = MakeTH1("periodLuminosity","Period","Luminosity(pb-1)",-0.5,+0.5+periodNbYear,periodNbYear+1,1)
770  h1Per_IntLumi.SetTitle("")
771  SetXLabel(h1Per_IntLumi,periodListYear)
772  h1Per_IntLumi.GetXaxis().SetBinLabel(periodNbYear+1,"All")
773 
774  for iBin in range(1,hProfPeriod_IntolDefect[idef].GetNbinsX()+1): # No matter what is idef, we just need the number of entries per bin to get the luminosity of past periods
775  h1Per_IntLumi.Fill(iBin-1,hProfPeriod_IntolDefect[idef].GetBinEntries(iBin)/1e6)
776 
777 
778 
780 if options['vetoLumiEvolution']:
781  h1_vetoInstLumiEvol = {}
782  h1_vetoInstLumiEvol['NoVeto'] = MakeTH1("LuminosityProfile","Instantaneous luminosity (10^{33} cm^{-2}s^{-1})","Time length (s)",4,19,60,1)
783  for iVeto in veto["all"]:
784  h1_vetoInstLumiEvol[iVeto] = MakeTH1("LuminosityVeto_%s"%(iVeto),"Instantaneous luminosity (10^{33} cm^{-2}s^{-1}) - Runs %d-%d"%(runlist['toprocess'][0],runlist['toprocess'][-1]),"#splitline{Inefficiency Time Veto}{(%s) [percent]}"%(defectVeto["description"][iVeto]),4,19,60,1)
785 
786 
787 
789 runinfo['AllRuns']['Lumi'] = 0. # Total luminosity
790 for idef in (grlDef["tol"]+grlDef["intol"]+grlDef["intol_recov"]+allIntolDef):
791  runinfo['AllRuns']['lumiDefect_%s'%(idef)] = 0.
792  runinfo['AllRuns']['ineffDefect_%s'%(idef)] = 0.
793 
794 for iVeto in veto["all"]+["allVeto"]:
795  runinfo['AllRuns']['lumiVeto_%s'%iVeto] = 0. # Total luminosity rejected by each time veto
796  runinfo['AllRuns']['ineffVeto_%s'%iVeto] = 0. # Overall inefficiency due to each time veto
797 
798 if (len(list(runinfo.keys())) == 1):
799  print("I did not find any run in runList.")
800  print("Please check the run range/options")
801 
802 print("I will use the following defect/veto tags:%s %s"%(options['defectTag'],options['vetoTag']))
803 
804 
806 for irun,runNb in enumerate(runlist['toprocess']):
807  print("=================================================================")
808  print("=============================Run %d (%d/%d)======================"%(runNb,irun+1,len(runlist['toprocess'])))
809 
810  # Init variables - List (indexed by partition) of tables of lumi blocks affected by defects
811  lbAffected = {}
812  for idef in grlDef["part"]+grlDef["partIntol_recov"]: # All partition defects
813  lbAffected[idef] = {}
814  lbAffected[idef]["AllPartitions"] = []
815  for idef in grlDef["glob"]+grlDef["globIntol_recov"]: # All global defects
816  lbAffected[idef] = [] # Global defect - Simple list and not dictionnary
817 
818  lbAffected['allIntol'] = [] # List of LBs affected with intolerable defect independant of the defect/partition
819  lbAffected['allIntol_recov'] = [] # List of LBs affected with intolerable recoverable defect independant of the defect/partition
820  lbAffected['allIntol_irrecov'] = [] # List of LBs affected with intolerable irrecoverable defect independant of the defect/partition
821 
822 
823  boolExactVetoComput_run = (options['exactVetoComput']) and (runNb not in runlist['roughVeto'])
824 
825  # Start retrieving the general characteristics of the run
826  # Get run infos
827  # Luminosity blocks UTC timestamps
828  v_lbTimeSt = GetLBTimeStamps(runNb)
829  runinfo[runNb]['Start'] = time.strftime("%a, %d %b %H:%M",time.localtime(v_lbTimeSt[1][0]))
830  runinfo[runNb]['Stop'] = time.strftime("%a, %d %b %H:%M",time.localtime(v_lbTimeSt[len(v_lbTimeSt)][1]))
831  runinfo[runNb]['nBunches'] = GetNumberOfCollidingBunches(runNb)
832  # Number of luminosity blocks
833  runinfo[runNb]['nLB'] = len(v_lbTimeSt)
834 
835  defectDatabase = DQDefects.DefectsDB(tag=options['defectTag'])
836  # Treatement of global filter
837  globalFilterLB = []
838  runinfo[runNb]['globalFilter'] = False
839  runinfo["AllRuns"]['globalFilter'] = False
840  if not options['noGlobalFilter']:
841  retrievedDefects = defectDatabase.retrieve((runNb, 1), (runNb, runinfo[runNb]['nLB']), grlDef["globalFilterDefects"])
842  for iRetrievedDefects in retrievedDefects:
843  if (iRetrievedDefects.until.lumi > 4000000000):
844  # The GLOBAL_NOTCONSIDERED defect is apparently set by default with a huge end of IOV.
845  # A priori, it should not survive the 48 hours calibration loop but anyway, In such a case, no filter is applied.
846  # BT October 2022 : this protection should be obsolete with the change of run 2 lines above. To be confirmed
847 # if (time.time()-v_lbTimeSt[len(v_lbTimeSt)][1]) > 48*3600: # During 48 hours after the end of run, the global filter is deactived to display all recent runs
848 # for lb in range(iRetrievedDefects.since.lumi,runinfo[runNb]['nLB']+1):
849 # globalFilterLB.append(lb)
850  continue
851  else:
852  for lb in range(iRetrievedDefects.since.lumi,iRetrievedDefects.until.lumi):
853  globalFilterLB.append(lb)
854 
855  # Atlas Ready
856  atlasready=GetReadyFlag(runNb)
857  runinfo[runNb]['readyLB']=[]
858  runinfo[runNb]['readyLB_globalFilter']=[]
859  for lb in list(atlasready.keys()):
860  if (atlasready[lb]>0): runinfo[runNb]['readyLB']+=[lb]
861  if (atlasready[lb]>0) and (lb not in globalFilterLB): runinfo[runNb]['readyLB_globalFilter']+=[lb]
862  if (lb in globalFilterLB):
863  runinfo[runNb]['globalFilter'] = True
864  runinfo["AllRuns"]['globalFilter'] = True
865  runinfo[runNb]['nLBready'] = float(len(runinfo[runNb]['readyLB_globalFilter']))
866 
867  thisRunPerLB = dict() # Contains various per LB run characteristics retrieved from COOL
868  # COOL delivered luminosity
869  if options['onlineLumiNorm']:
870  thisRunPerLB["deliveredLumi"] = GetOnlineLumiFromCOOL(runNb,0)
871  else:
872  thisRunPerLB["deliveredLumi"] = GetOfflineLumiFromCOOL(runNb,0,yearTagProperties["OflLumi tag"])
873 
874  # Look for peak lumi
875  runinfo[runNb]['peakLumi'] = 0.
876  for lb in list(thisRunPerLB['deliveredLumi'].keys()):
877  if thisRunPerLB['deliveredLumi'][lb] > runinfo[runNb]['peakLumi']: runinfo[runNb]['peakLumi']=thisRunPerLB['deliveredLumi'][lb]
878  if thisRunPerLB['deliveredLumi'][lb] > runinfo['AllRuns']['peakLumi']: runinfo['AllRuns']['peakLumi']=thisRunPerLB['deliveredLumi'][lb]
879 
880  # Store the duration
881  thisRunPerLB['duration'] = GetLBDuration(runNb)
882 
883  # Back up method. Retrieve the precise LB duration (more precise than GetLBDuration(runNb)) and liveFraction (relevant if recorded lumi normalisation).
884  lumiacct=fetch_iovs('COOLOFL_TRIGGER::/TRIGGER/OFLLUMI/LumiAccounting', tag=yearTagProperties["OflLumiAcct tag"], since=v_lbTimeSt[1][0]*1000000000, until=v_lbTimeSt[len(v_lbTimeSt)][1]*1000000000)
885  thisRunPerLB['duration'] = dict()
886  for iLumiAcct in range(len(lumiacct)):
887  if options['recordedLumiNorm']: # The LB duration is corrected by the live fraction
888  thisRunPerLB['duration'][lumiacct[iLumiAcct].LumiBlock] = lumiacct[iLumiAcct].LBTime*lumiacct[iLumiAcct].LiveFraction
889  else:
890  thisRunPerLB['duration'][lumiacct[iLumiAcct].LumiBlock] = lumiacct[iLumiAcct].LBTime
891 
892  # Store the luminosity used for the efficiency normalisations
893  for lb in range(1,runinfo[runNb]['nLB']+2): # Loop on all LB - Protection to set a zero luminosity if not available
894  if lb in runinfo[runNb]['readyLB_globalFilter']:
895  if lb not in list(thisRunPerLB["deliveredLumi"].keys()):
896  thisRunPerLB["deliveredLumi"][lb] = 0.
897  errorMsg = "Missing lumi for Run %d - LB %d\n"%(runNb,lb)
898  print(errorMsg)
899  errorLogFile.write(errorMsg)
900  if lb not in list(thisRunPerLB["duration"].keys()):
901  thisRunPerLB["duration"][lb] = 0.
902  errorMsg = "Missing duration/LiveFraction for Run %d - LB %d\n"%(runNb,lb)
903  print(errorMsg)
904  errorLogFile.write(errorMsg)
905  else:
906  if lb not in list(thisRunPerLB["deliveredLumi"].keys()):
907  thisRunPerLB["deliveredLumi"][lb] = 0.
908  if lb not in list(thisRunPerLB["deliveredLumi"].keys()):
909  thisRunPerLB["duration"][lb] = 0.
910 
911  if options['vetoLumiEvolution']:
912  for lb in runinfo[runNb]['readyLB_globalFilter']: # Fill the luminosity profile
913  if thisRunPerLB["deliveredLumi"][lb] != 0.:
914  h1_vetoInstLumiEvol['NoVeto'].Fill(thisRunPerLB["deliveredLumi"][lb]/1e3,v_lbTimeSt[lb][1]-v_lbTimeSt[lb][0])
915 
916  # Finished retrieving the general characteristics of the run
917 
918  # Get defects
919 
920  parsedDefects = retrieveDefectsFromDB(runNb, options['defectTag'], grlDef,signOff)
921  retrievedDefects = list(parsedDefects.keys())
922 
923  runinfo[runNb]['exprSignedOff'] = True
924  runinfo[runNb]['bulkSignedOff'] = True
925  runinfo[runNb]['signoff'] = 'FINAL OK'
926  # Loop over all defects and store in list (1 per partition and type) the affected LB
927  # Consider only LB in runinfo[runNb]["readyLB_globalFilter"]
928  for iRetrievedDefects in retrievedDefects:
929  # keep track of runs with missing sign-off - Store the earliest stage of the sign off procedure
930  for iSignOff in signOff["EXPR."]:
931  if iRetrievedDefects.channel == iSignOff:
932  runinfo[runNb]['signoff'] = "EXPR."
933  if "EXPR." not in runinfo[runNb]['signoff']:
934  for iSignOff in signOff["BULK"]:
935  if iRetrievedDefects.channel == iSignOff:
936  runinfo[runNb]['signoff'] = "BULK"
937  if "BULK" not in runinfo[runNb]['signoff']:
938  for iSignOff in signOff["FINAL"]:
939  if iRetrievedDefects.channel == iSignOff:
940  runinfo[runNb]['signoff'] = "DONE"
941 
942  if runinfo[runNb]['signoff'] != 'FINAL OK': # Update year stats only after final signoff
943  runinfo[runNb]['newInYearStats'] = False
944 
945  # Checks if the defect corresponds to a defect in the system list
946  defectFound, partAffected = parsedDefects[iRetrievedDefects]
947 
948  # Now stored the affected
949  if defectFound in grlDef["part"]:
950  for lb in range(iRetrievedDefects.since.lumi,iRetrievedDefects.until.lumi):
951  if(lb in runinfo[runNb]['readyLB_globalFilter']):# The LB is with ATLAS ready
952 
953  if partAffected not in lbAffected[defectFound]: # Store the affected partitions - A priori no longer used
954  lbAffected[defectFound][partAffected]=[]
955  lbAffected[defectFound][partAffected].append(lb)
956 
957  lbAffected[defectFound]["AllPartitions"].append(lb)
958  if (defectFound in grlDef["partIntol"]):# Update the LBs affected by an intolerable defect whatever is the partition
959  if (lb not in lbAffected['allIntol']):
960  lbAffected['allIntol'].append(lb)
961  if (not iRetrievedDefects.recoverable and lb not in lbAffected['allIntol_irrecov']): # Update the LBs affected by an intolerable irrecoverable defect
962  lbAffected['allIntol_irrecov'].append(lb)
963 
964  if defectFound in grlDef["glob"]:
965  # The min is a protection for a single 2017 run with Trig_HLT (326468) that lead to a crash...
966  for lb in range(iRetrievedDefects.since.lumi,min(iRetrievedDefects.until.lumi,runinfo[runNb]['nLB']+1)):
967  if(lb in runinfo[runNb]["readyLB_globalFilter"]):
968  lbAffected[defectFound].append(lb)
969  if (defectFound in grlDef["globIntol"]):# Update the LBs affected by an intolerable irrecoverable defect
970  if (lb not in lbAffected['allIntol']):
971  lbAffected['allIntol'].append(lb)
972  if (not iRetrievedDefects.recoverable and lb not in lbAffected['allIntol_irrecov']):
973  lbAffected['allIntol_irrecov'].append(lb)
974 
975  # Now treat recoverability - Storing all irrecoverable lb per defect (not partition wise as useless)
976  for idef in grlDef["partIntol"]:
977  lbAffected['%s__recov'%idef]["AllPartitions"]=[]
978  for ilb in lbAffected[idef]["AllPartitions"]:
979  if ilb not in lbAffected['allIntol_irrecov']:
980  lbAffected['%s__recov'%idef]["AllPartitions"].append(ilb)
981  for idef in grlDef["globIntol"]:
982  for ilb in lbAffected[idef]:
983  if ilb not in lbAffected['allIntol_irrecov']:
984  lbAffected['%s__recov'%idef].append(ilb)
985  lbAffected['allIntol_recov'].append(ilb)
986 
987  # Prepare the computation of inefficiencies - Initialization
988  for idef in (grlDef["tol"]+grlDef["intol"]+grlDef["intol_recov"]+allIntolDef):
989  runinfo[runNb]["lumiDefect_%s"%(idef)] = 0.
990  runinfo[runNb]["ineffDefect_%s"%(idef)] = 0.
991  runinfo[runNb]['Lumi'] = 0.
992 
993  # Loop on all LB of the run
994  for lb in runinfo[runNb]["readyLB_globalFilter"]:
995  # Compute integrated luminosities
996  runinfo[runNb]['Lumi'] = runinfo[runNb]['Lumi'] +thisRunPerLB["deliveredLumi"][lb]*thisRunPerLB['duration'][lb]
997  runinfo['AllRuns']['Lumi'] = runinfo['AllRuns']['Lumi'] +thisRunPerLB["deliveredLumi"][lb]*thisRunPerLB['duration'][lb]
998  # Loop on defects already stored - Partition defect (Tolerable + intolerable)
999  for idef in grlDef["part"]+grlDef["partIntol_recov"]:
1000  if lb in lbAffected[idef]["AllPartitions"]:
1001  runinfo[runNb]["lumiDefect_%s"%(idef)] = runinfo[runNb]["lumiDefect_%s"%(idef)] + thisRunPerLB["deliveredLumi"][lb]*thisRunPerLB['duration'][lb]
1002  runinfo["AllRuns"]["lumiDefect_%s"%(idef)] = runinfo["AllRuns"]["lumiDefect_%s"%(idef)] + thisRunPerLB["deliveredLumi"][lb]*thisRunPerLB['duration'][lb]
1003  if (runinfo[runNb]["Lumi"] != 0.):
1004  runinfo[runNb]["ineffDefect_%s"%(idef)] = runinfo[runNb]["lumiDefect_%s"%(idef)]/runinfo[runNb]["Lumi"]*100.
1005 
1006  # Loop on defects already stored - Global defect (Tolerable + intolerable) + all intolerable (used to avoid double counting)
1007  for idef in grlDef["glob"]+grlDef["globIntol_recov"]+allIntolDef:
1008  if lb in lbAffected[idef]:
1009  runinfo[runNb]["lumiDefect_%s"%(idef)] = runinfo[runNb]["lumiDefect_%s"%(idef)] + thisRunPerLB["deliveredLumi"][lb]*thisRunPerLB['duration'][lb]
1010  runinfo["AllRuns"]["lumiDefect_%s"%(idef)] = runinfo["AllRuns"]["lumiDefect_%s"%(idef)] + thisRunPerLB["deliveredLumi"][lb]*thisRunPerLB['duration'][lb]
1011  if (runinfo[runNb]["Lumi"] != 0.):
1012  runinfo[runNb]["ineffDefect_%s"%(idef)] = runinfo[runNb]["lumiDefect_%s"%(idef)]/runinfo[runNb]["Lumi"]*100.
1013 
1014  if runinfo[runNb]['Lumi']==0: runinfo[runNb]['Lumi']=1e-50
1015 
1016  for idef in grlDef["intol"]+grlDef["intol_recov"]+allIntolDef:
1017  hProfRun_IntolDefect[idef].Fill(irun,runinfo[runNb]["ineffDefect_%s"%(idef)])
1018  hProfRun_IntolDefect[idef].Fill(len(runlist['toprocess']),runinfo[runNb]["ineffDefect_%s"%(idef)],runinfo[runNb]['Lumi']) # Fill last bins (all runs) - Reminder : this is a profile !
1019  if (options['updateYearStats'] and runinfo[runNb]['newInYearStats']):
1020  hProfPeriod_IntolDefect[idef].Fill(periodListYear.index(runinfo[runNb]["period"]),runinfo[runNb]["ineffDefect_%s"%(idef)],runinfo[runNb]['Lumi'])
1021  hProfPeriod_IntolDefect[idef].Fill(len(periodListYear),runinfo[runNb]["ineffDefect_%s"%(idef)],runinfo[runNb]['Lumi'])
1022 
1023  h1Run_IntLuminosity.Fill(irun,runinfo[runNb]['Lumi']/1e6)
1024  h1Run_IntLuminosity.Fill(len(runlist['toprocess']),runinfo[runNb]['Lumi']/1e6)
1025 
1026  if (options['updateYearStats'] and runinfo[runNb]['newInYearStats']):
1027  h1Per_IntLumi.Fill(periodListYear.index(runinfo[runNb]["period"]),runinfo[runNb]['Lumi']/1e6)
1028  h1Per_IntLumi.Fill(h1Per_IntLumi.GetNbinsX()-1,runinfo[runNb]['Lumi']/1e6) # Cumulated for the year
1029 
1030  # Now starts veto inefficiency
1031  # Retrieve the length of time period vetoed
1032  db2="COOLOFL_LAR/CONDBR2"
1033  folderName="/LAR/BadChannelsOfl/EventVeto"
1034  if (not options['noVeto']):
1035  if (boolExactVetoComput_run):
1036  totalVeto = showEventVeto.showEventVetoFolder(db2,folderName,options['vetoTag'],runNb,runNb,0)
1037  else:
1038  print("WARNING: you use the rough event veto loss. To be used only if default is too slow...")
1039  totalVeto = showEventVetoNoLumi.showEventVetoFolder(db2,folderName,options['vetoTag'],runNb,runNb,0)
1040  else:
1041  totalVeto = None
1042 
1043  for iVeto in veto["all"]+["allVeto"]:
1044  runinfo[runNb]["lumiVeto_%s"%(iVeto)] = 0.
1045  runinfo[runNb]["ineffVeto_%s"%(iVeto)] = 0.
1046 
1047  if (totalVeto is not None):
1048  if (boolExactVetoComput_run):# Computation of veto rejection weighting by inst. lumi and ignoring LB already in intolerable defect list
1049  for iVeto in veto["all"]:
1050  for iVetoedLB in range(len(totalVeto[veto["COOL"][iVeto]])): # Loop on all veto periods
1051  lb0 = findLB(v_lbTimeSt,totalVeto[veto["COOL"][iVeto]][iVetoedLB][0]/1e9) # Start of veto period
1052  lb1 = findLB(v_lbTimeSt,totalVeto[veto["COOL"][iVeto]][iVetoedLB][0]/1e9) # End of veto period
1053  if options['vetoLumiEvolution']:
1054  h1_vetoInstLumiEvol[iVeto].Fill(thisRunPerLB["deliveredLumi"][lb0]/1e3,(totalVeto[veto["COOL"][iVeto]][iVetoedLB][1]-totalVeto[veto["COOL"][iVeto]][iVetoedLB][0])/1e9)
1055  if (lb0 not in lbAffected['allIntol'] and lb1 not in lbAffected['allIntol'] and (lb0 in runinfo[runNb]["readyLB_globalFilter"] or lb1 in runinfo[runNb]["readyLB_globalFilter"])): # If end/start not in lb with intol defect, add rejection period - Incorrect if > 1 LBs
1056  runinfo[runNb]["lumiVeto_%s"%iVeto] = runinfo[runNb]["lumiVeto_%s"%iVeto] + thisRunPerLB["deliveredLumi"][lb0]*((totalVeto[veto["COOL"][iVeto]][iVetoedLB][1]-totalVeto[veto["COOL"][iVeto]][iVetoedLB][0])/1e9)
1057  # Assumption that there is no overlap between the different tipes of time veto. To be fixed ideally...
1058  runinfo[runNb]["lumiVeto_allVeto"] = runinfo[runNb]["lumiVeto_allVeto"] + runinfo[runNb]["lumiVeto_%s"%iVeto]
1059  else:
1060  for iVeto in veto["all"]:
1061  if len(runinfo[runNb]["readyLB_globalFilter"]) != 0.:
1062  runinfo[runNb]["lumiVeto_%s"%(iVeto)] = totalVeto[iVeto][1] # WARNING : the veto inefficiency is computed from time (and not lumi). To be normalized by time
1063  # Assumption that there is no overlap between the different tipes of time veto. To be fixed ideally...
1064  runinfo[runNb]["lumiVeto_allVeto"] = runinfo[runNb]["lumiVeto_allVeto"] + runinfo[runNb]["lumiVeto_%s"%iVeto]
1065 
1066  if (not options['noVeto']):
1067  for iVeto in veto["all"]+["allVeto"]:
1068  if boolExactVetoComput_run:
1069  runinfo[runNb]["ineffVeto_%s"%(iVeto)] = runinfo[runNb]["lumiVeto_%s"%(iVeto)]/runinfo[runNb]['Lumi']*100.
1070  else:# The veto inefficiency is computed from time (and not lumi). The ineff is normalized by time
1071  if len(runinfo[runNb]["readyLB_globalFilter"]) != 0.:
1072  runinfo[runNb]["ineffVeto_%s"%(iVeto)] = runinfo[runNb]["lumiVeto_%s"%(iVeto)]/(len(runinfo[runNb]["readyLB_globalFilter"])*60*1e9)*100.
1073  else:
1074  runinfo[runNb]["ineffVeto_%s"%(iVeto)] = 0.
1075 
1076  hProfRun_Veto[iVeto].Fill(irun,runinfo[runNb]["ineffVeto_%s"%(iVeto)])
1077  hProfRun_Veto[iVeto].Fill(len(runlist['toprocess']),runinfo[runNb]["ineffVeto_%s"%(iVeto)],runinfo[runNb]['Lumi']) # Fill last bins (all runs) - Reminder : this is a profile !
1078 
1079  if (options['updateYearStats'] and runinfo[runNb]['newInYearStats']):
1080  hProfPeriod_Veto[iVeto].Fill(periodListYear.index(runinfo[runNb]["period"]),runinfo[runNb]["ineffVeto_%s"%(iVeto)],runinfo[runNb]['Lumi'])
1081  hProfPeriod_Veto[iVeto].Fill(len(periodListYear),runinfo[runNb]["ineffVeto_%s"%(iVeto)],runinfo[runNb]['Lumi']) # Fill last bins (all periods)
1082 
1083  runinfo['AllRuns']['lumiVeto_%s'%iVeto] = runinfo['AllRuns']['lumiVeto_%s'%iVeto] + runinfo[runNb]["lumiVeto_%s"%iVeto]
1084 
1085  singleRunReport(runNb,runinfo[runNb],lbAffected,options['yearStatsDir'],grlDef,veto,boolExactVetoComput_run)
1086 
1087 
1088 # End of loop on runs
1089 
1090 
1091 
1092 if options['vetoLumiEvolution']:
1093  for iVeto in veto["all"]:
1094  h1_vetoInstLumiEvol[iVeto].Divide(h1_vetoInstLumiEvol[iVeto],h1_vetoInstLumiEvol['NoVeto'],100.,1.)
1095 
1096 
1097 if (runinfo['AllRuns']['Lumi']!=0):
1098  # Compute inefficiencies for the whole period
1099 
1100  # Defect inefficencies first
1101  for iDef in grlDef["intol"]+grlDef["intol_recov"]+allIntolDef:
1102  runinfo['AllRuns']['ineffDefect_%s'%iDef] = hProfRun_IntolDefect[iDef].GetBinContent(hProfRun_IntolDefect[iDef].GetNbinsX())
1103 
1104  if (not options['noVeto']):
1105  for iVeto in veto["all"]+["allVeto"]:
1106  runinfo['AllRuns']['ineffVeto_%s'%iVeto] = hProfRun_Veto[iVeto].GetBinContent(hProfRun_IntolDefect[iDef].GetNbinsX())
1107 
1108  # Prepare the summary tables
1109  lineNb = {}
1110  column = {}
1111  lineNb = {}
1112  c1 = {}
1113 
1114  canvasIndex = 0
1115  newCanvas = True
1116  for runNb in runlist['toprocess']+["AllRuns"]:
1117  if runNb not in list(runinfo.keys()):
1118  continue # Protection in case of the runs was not yet signed off and removed (with Unsignedoff option) from the list
1119 
1120  if newCanvas:
1121  # NewCanvas facility almost removed (70 runs cut) Size of the last TCanvas not properly computed
1122  c1[canvasIndex] = TCanvas("runSummary_%s"%canvasIndex,"Run collection - %s"%canvasIndex,10,10,1000,(len(runlist['toprocess'])+6)*22)
1123  column[canvasIndex] = []
1124  lineNb[canvasIndex] = 0
1125  labels_col = ["Run","Run start / stop","LB ready","Peak lumi","Filt. lumi","GRL ineff.","Veto ineff.","Period","Status"]
1126  xlow_col = [0.01,0.075,0.405,0.485,0.57,0.65,0.735,0.83,0.89,0.99]
1127  ylowTable = 0.99 - 0.98/(len(runlist['toprocess'])+6)*(len(runlist['toprocess'])+2)
1128 
1129  for i in range(len(labels_col)):
1130  column[canvasIndex].append(TPaveText(xlow_col[i],ylowTable,xlow_col[i+1],0.99))
1131  column[canvasIndex][i].AddText(labels_col[i])
1132  if (i%2 == 0):
1133  column[canvasIndex][i].SetFillColor(kAzure+2)
1134  else:
1135  column[canvasIndex][i].SetFillColor(kBlue-10)
1136  notYetSignedOff_TPave = TPaveText(xlow_col[0],0.01,xlow_col[len(labels_col)],ylowTable)
1137  if runlist['weekly-dqmeeting'] != "":
1138  notYetSignedOff_TPave.AddText("#club: runs to be signed off at %s"%runlist['weekly-dqmeeting'])
1139  if runinfo['AllRuns']['globalFilter'] != "":
1140  notYetSignedOff_TPave.AddText("#diamond: runs for which a global filter has been applied (for more information, look at the Global system)")
1141  notYetSignedOff_TPave.AddText("Completed at %s"%(time.strftime("%H:%M (%d %b)", time.localtime())))
1142  notYetSignedOff_TPave.SetFillColor(kAzure+2)
1143 
1144  newCanvas = False
1145  if runNb == "AllRuns":
1146  column[canvasIndex][0].AddText("ALL")
1147  else:
1148  column[canvasIndex][0].AddText("%d"%(runNb))
1149  column[canvasIndex][1].AddText("%s / %s"%(runinfo[runNb]['Start'],runinfo[runNb]['Stop']))
1150  column[canvasIndex][2].AddText("%s"%(listify(runinfo[runNb]["readyLB"])))
1151  column[canvasIndex][3].AddText("%.1e"%(runinfo[runNb]['peakLumi']*1e30))
1152  if (runinfo[runNb]['globalFilter']):
1153  column[canvasIndex][4].AddText("%s #diamond"%(strLumi(runinfo[runNb]['Lumi'])))
1154  else:
1155  column[canvasIndex][4].AddText("%s"%(strLumi(runinfo[runNb]['Lumi'])))
1156  column[canvasIndex][5].AddText("%.2f %%"%(runinfo[runNb]['ineffDefect_allIntol']))
1157  column[canvasIndex][6].AddText("%.2f %%"%(runinfo[runNb]['ineffVeto_allVeto']))
1158  column[canvasIndex][7].AddText("%s"%(runinfo[runNb]["period"]))
1159  if (runNb in runlist['weeklyfile']):
1160  column[canvasIndex][8].AddText("%8s #club"%(runinfo[runNb]["signoff"]))
1161  else:
1162  column[canvasIndex][8].AddText("%10s"%(runinfo[runNb]["signoff"]))
1163  lineNb[canvasIndex] += 1
1164  if (lineNb[canvasIndex]==70 or runNb == "AllRuns"):
1165  for i in range(len(column[canvasIndex])):
1166  column[canvasIndex][i].Draw()
1167  tmp = "Old runs (> 7 days) not yet signed off: "
1168  tmp2 = ""
1169  if len(oldRunsNotYetignedOff):
1170  for iRun in range(len(oldRunsNotYetignedOff)):
1171  if (iRun < 10):
1172  tmp = tmp + "%d "%oldRunsNotYetignedOff[iRun]
1173  else:
1174  tmp2 = tmp2 + "%d "%oldRunsNotYetignedOff[iRun]
1175  else:
1176  tmp = tmp + "None :-)"
1177  notYetSignedOff_TPave.AddText(tmp)
1178  notYetSignedOff_TPave.AddText(tmp2)
1179  notYetSignedOff_TPave.Draw()
1180 
1181  c1[canvasIndex].SetWindowSize(1000,lineNb[canvasIndex]*40)
1182  c1[canvasIndex].Update()
1183 
1184  newCanvas = True
1185  canvasIndex += 1
1186 
1187  if options['updateYearStats'] and (runinfo[runNb]["signoff"] != "FINAL OK" or runinfo[runNb]['Lumi'] < 1e-40) and runNb != "AllRuns":
1188  if (runinfo[runNb]['Lumi'] < 1e-40 ):
1189  print("Run %d has zero luminosity (wrong faulty db tag?) -> no year stats update. Current status: %s"%(runNb,runinfo[runNb]["signoff"]))
1190  if (runinfo[runNb]["signoff"] != "FINAL OK"):
1191  print("Run %d not fully signed off -> no year stats update. Current status: %s"%(runNb,runinfo[runNb]["signoff"]))
1192  notYetSignedOffRuns.write("%d (period %s) -> Current status : %s \n"%(runNb,runinfo[runNb]['period'],runinfo[runNb]["signoff"]))
1193  if options['updateYearStats'] and runinfo[runNb]["signoff"] == "FINAL OK" and runinfo[runNb]['newInYearStats']:
1194  bool_newRunsInYearStats = True
1195 
1196  if options['savePlots']:
1197  for iCanvas in range(len(c1)):
1198  c1[iCanvas].SaveAs("%s/Weekly/summary-%d.png"%(options['yearStatsDir'],iCanvas))
1199 
1200 
1201 canvasResults = {}
1202 legendResults = {}
1203 stackResults = {}
1204 
1205 
1206 gStyle.SetOptStat(0)
1207 if options['plotResults']:
1208  gStyle.SetHistMinimumZero()
1209 
1210  plotStack("defects--Run--%s"%(options['tag']),hProfRun_IntolDefect,grlDef["intol"],defectVeto["description"],h1Run_IntLuminosity,False,stackResults,canvasResults,legendResults)
1211  if (len(veto["all"])):
1212  plotStack("veto--Run--%s"%(options['tag']),hProfRun_Veto,veto["all"],defectVeto["description"],h1Run_IntLuminosity,False,stackResults,canvasResults,legendResults)
1213 
1214  if options['vetoLumiEvolution']:
1215  for iVeto in veto["all"]:
1216  canvasResults["%s_veto_evol"%(iVeto)] = TCanvas("%s_veto_evol"%(iVeto),"%s inefficiency (%s time veto) vs Inst.Lumi."%(options["system"],defectVeto["description"][iVeto]), 200, 10, 1000, 500)
1217  canvasResults["%s_veto_evol"%(iVeto)].SetGridy(1)
1218  h1_vetoInstLumiEvol[iVeto].Draw()
1219 
1220  if options['savePlots']:
1221  for iCanvas in list(canvasResults.keys()):
1222  canvasResults[iCanvas].SaveAs("%s/Weekly/%s.png"%(options['yearStatsDir'],iCanvas))
1223 
1224 # End of plots
1225 # Save the histograms when requested. NB:This is different from yearStats update
1226 if (options['saveHistos']):
1227  filename = 'Files/weeklyHisto-%s-%s.root'%(startrun, endrun)
1228  f = TFile(filename,"recreate")
1229  for idef in grlDef["intol"]:
1230  hProfRun_IntolDefect[idef].Write()
1231  if options['vetoLumiEvolution']:
1232  h1_vetoInstLumiEvol["NoVeto"].Write()
1233  for iVeto in veto["all"]:
1234  hProfRun_Veto[iVeto].Write()
1235  if options['vetoLumiEvolution']:
1236  h1_vetoInstLumiEvol[iVeto].Write()
1237  f.Close()
1238  print("Histos saved in %s"%(filename))
1239 
1240 # yearStats update
1241 # If new runs were added to period plots, save them
1242 if (options['updateYearStats'] and bool_newRunsInYearStats):
1243  print("WARNING: I am going to update the %s stats with the following runs:"%(options['year']))
1244  print("NB: only runs fully signed off are considered")
1245  for irun in list(runinfo.keys()):
1246  if (irun != "AllRuns"):
1247  if runinfo[irun]['newInYearStats']:
1248  print(irun)
1249 
1250  if (options['batchMode']): # In batch mode, no confirmation requested
1251  confirm = "y"
1252  else:
1253  confirm = input("Are you sure ([y]/n)?: ")
1254 
1255  if ("n" not in confirm):
1256  f = TFile(yearStatsArchiveFilename,"recreate") #this file summarize all year stats with proper periods assigned
1257  for idef in grlDef["intol"] + grlDef["intol_recov"]+allIntolDef:#Intolerable defects only
1258  hProfPeriod_IntolDefect[idef].SetName("%s_archive"%(hProfPeriod_IntolDefect[idef].GetName()))
1259  hProfPeriod_IntolDefect[idef].Write()
1260  if (len(veto["all"])):
1261  for iVeto in (veto["all"]+["allVeto"]):
1262  hProfPeriod_Veto[iVeto].SetName("%s_archive"%(hProfPeriod_Veto[iVeto].GetName()))
1263  hProfPeriod_Veto[iVeto].Write()
1264 
1265  h1Per_IntLumi.SetName("h1Period_IntLuminosity_archive")
1266  h1Per_IntLumi.Write()
1267  f.Close()
1268 
1269  # Creating empty files for new period
1270  for iper in newPeriodInYearStats:
1271  periodFileName = "%s/runs-%s.dat"%(options['yearStatsDir'],iper)
1272  f = open(periodFileName,'w')
1273  f.close()
1274 
1275  # Adding all runs not treated in year stats
1276  fAll = open("%s/runs-ALL.dat"%options['yearStatsDir'],'a')
1277  for iper in list(periodListCurrent.keys()): # Loop on all periods found
1278  periodFileName = "%s/runs-%s.dat"%(options['yearStatsDir'],iper)
1279  f = open(periodFileName,'a')
1280  for irun in periodListCurrent[iper]:
1281  if (irun in list(runinfo.keys()) and runinfo[irun]['newInYearStats']): # Runs not yet considered in yearStats
1282  f.write("%d\n"%(irun))
1283  fAll.write("%d (%s)\n"%(irun,iper))
1284  f.close()
1285  fAll.close()
1286  print("I have updated year stats")
1287 
1288 # The update of the defect dat files is now decoupled from the yearStatsUpdate to allows to also monitor runs (special runs notably)
1289 # that are not in the GRL.
1290 # for irun in list(runinfo.keys()): # should just be processed runs, or we don't have signoff
1291 for irun in runlist['toprocess']:
1292  if runinfo[irun]['signoff'] == 'FINAL OK' and irun != "AllRuns" and options['updateYearStats']:
1293  # NB : GRL information no longer stored here
1294  # Backwards compatibility with DeMoScan to be checked
1295  irun_string = "%d (%.0f ub-1)"%(irun,runinfo[irun]['Lumi'])
1296 
1297  for idef in grlDef["intol"]+grlDef["tol"]:
1298  if (runinfo[irun]["lumiDefect_%s"%(idef)]>0.):
1299  defectFileName = "%s/loss-%s.dat"%(options['yearStatsDir'],idef)
1300  if idef in grlDef["intol"]:
1301  defString = "%s -> %.6f pb-1 (recov: %.6f pb-1)\n"%(irun_string,runinfo[irun]["lumiDefect_%s"%(idef)]/1e6,runinfo[irun]["lumiDefect_%s__recov"%(idef)]/1e6)
1302  else:
1303  defString = "%s -> %.6f pb-1\n"%(irun_string,runinfo[irun]["lumiDefect_%s"%(idef)]/1e6)
1304  toAdd = True
1305  if (os.path.exists(defectFileName)):# Check that the same defect was not already stored
1306  f2 = open(defectFileName,'r')
1307  if defString in f2.readlines():
1308  toAdd = False
1309  f2.close()
1310  if toAdd:
1311  f2 = open(defectFileName,'a')
1312  f2.write(defString)
1313  f2.close()
1314 
1315  if runinfo[irun]["ineffVeto_allVeto"]>0. : # Loss due to veto. Update the veto dat files
1316  for iVeto in veto["all"]:
1317  if (runinfo[irun]["lumiVeto_%s"%(iVeto)]>0.):
1318  vetoFileName = "%s/loss-%sVETO.dat"%(options['yearStatsDir'],iVeto)
1319  vetoString = "%s -> %.6f pb-1 \n"%(irun_string,runinfo[irun]["lumiVeto_%s"%(iVeto)]/1e6)
1320  toAdd = True
1321  if (os.path.exists(vetoFileName)):# Check that the same veto was not already stored
1322  f2 = open(vetoFileName,'r')
1323  if vetoString in f2.readlines():
1324  toAdd = False
1325  f2.close()
1326  if toAdd:
1327  f2 = open(vetoFileName,'a')
1328  f2.write(vetoString)
1329  f2.close()
1330 
1331 errorLogFile.close()
1332 notYetSignedOffRuns.close()
1333 
1334 if options['updateYearStats']:
1335  os.system("rm -f %s"%tokenName)
1336 if not options['batchMode']:
1337  input("I am done. Type <return> to exit...")
max
#define max(a, b)
Definition: cfImp.cxx:41
python.db.fetch_iovs
def fetch_iovs(folder_name, since=None, until=None, channels=None, tag="", what="all", max_records=-1, with_channel=True, loud=False, database=None, convert_time=False, named_channels=False, selection=None, runs=None, with_time=False, unicode_strings=False)
Definition: DQUtils/python/db.py:67
index
Definition: index.py:1
DeMoLib.MakeTProfile
def MakeTProfile(name, xtitle, ytitle, xmin, xmax, nbins, color)
Definition: DeMoLib.py:18
DeMoUpdate.printProp
def printProp(varname)
Definition: DeMoUpdate.py:60
DeMoUpdate.sort_period
def sort_period(text)
Ancillary functions.
Definition: DeMoUpdate.py:55
DeMoLib.MakeTH1
def MakeTH1(name, xtitle, ytitle, xmin, xmax, nbins, color)
Definition: DeMoLib.py:30
python.html.AtlRunQueryDQSummary.SetXLabel
def SetXLabel(h, labels)
Definition: AtlRunQueryDQSummary.py:520
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
DeMoUpdate.findLB
def findLB(lbts, startOfVetoPeriod)
Definition: DeMoUpdate.py:85
convertTimingResiduals.sum
sum
Definition: convertTimingResiduals.py:55
DeMoUpdate.getRunInfo
def getRunInfo(runlist, defectTag="HEAD")
Retrieval of run characteristics.
Definition: DeMoUpdate.py:314
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
DeMoLib.retrieveYearTagProperties
def retrieveYearTagProperties(year, tag)
Return the year/tag properties (defect/veto/lumi tags...) stored in YearStats-common/DeMoConfig-[year...
Definition: DeMoLib.py:68
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
min
#define min(a, b)
Definition: cfImp.cxx:40
DeMoUpdate.singleRunReport
def singleRunReport(runNumber, dict1, dict2, directory, defects, veto, exactVetoComput)
Definition: DeMoUpdate.py:101
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
Trk::open
@ open
Definition: BinningType.h:40
DeMoUpdate.int
int
Definition: DeMoUpdate.py:381
DeMoUpdate.printBoth
def printBoth(string0, boolean, f)
Functions dedicated to output printing.
Definition: DeMoUpdate.py:94
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
DeMoLib.initializeMonitoredDefects
def initializeMonitoredDefects(system, partitions, defects0, defectVeto, veto, signOff, year, tag, runlist={})
Definition: DeMoLib.py:294
str
Definition: BTagTrackIpAccessor.cxx:11
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:798
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
DeMoUpdate.listify
def listify(l)
Definition: DeMoUpdate.py:67
DeMoLib.strLumi
def strLumi(lumi, unit="ub", latex=True, floatNumber=False)
Return a string with the luminosity in a human readable way If the unit is %%, this is a percentage.
Definition: DeMoLib.py:86
DeMoUpdate.retrieveDefectsFromDB
def retrieveDefectsFromDB(run, defectTag, grlDef, signOffDefects)
Definition: DeMoUpdate.py:262
WriteBchToCool.update
update
Definition: WriteBchToCool.py:67
readCCLHist.float
float
Definition: readCCLHist.py:83
DeMoUpdate.extractNamePartition
def extractNamePartition(foundDefect)
Functions dedicated to defect retrieval and basic string manipulations.
Definition: DeMoUpdate.py:141
DeMoLib.plotStack
def plotStack(name, histo, index, indexName, histoIntLumi, lumiBool, resStack, resCanvas, resLegend, recovBool=True, compBool=False, approvedPlots=False)
Definition: DeMoLib.py:118
DeMoUpdate.updateRunList
def updateRunList(year=time.localtime().tm_year)
Retrieval of new runs not yet in YearStats-common/runlist-[year]-AtlasReady.dat.
Definition: DeMoUpdate.py:281