ATLAS Offline Software
COOLRates.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
4 
5 #====================================================================================================================
6 
7 __author__ = "Peter Radloff"
8 __version__ = "$Revision: 1.0$"
9 __doc__ = "Fast Rate plotter from COOL database"
10 
11 #====================================================================================================================
12 
13 from PyCool import cool
14 from multiprocessing import Queue, cpu_count, Process
15 from time import sleep
16 import argparse,sys,logging,time,os
17 from math import log10
18 import signal
19 from Queue import Empty
20 
21 logger = logging.getLogger(__name__)
22 ch = logging.StreamHandler()
23 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
24 ch.setFormatter(formatter)
25 logger.addHandler(ch)
26 
27 if __name__=='__main__':
28 
29  parser = argparse.ArgumentParser(prog='COOLRates.py',description='Plots rate information from COOL')
30  parser.add_argument(dest='RATES',help='String specifing rates to plot, comma seperated with a bar seperating groups. Separate rate and alias with colon: "L1_L1A:L1_total", add -0,-1 for before prescale/after prescale [default is output]\nExample:\nCOOLQuery.py "L1_L1A:L1_total,L2_total,EF_total|L1_EM10VH,L1_EM6_2MU6,L1_2EM6_MU6,L1_EM6,L1_EM12|EF_2g40_loose,EF_g100_loose,EF_mu18_tight_e7_medium1,EF_e60_medium1" -r 201257 201269')
31  parser.add_argument('-r','--run',default=None,dest='RUNNUMBER', metavar='R',type=int, nargs='+',help='Run number(s) for which to plot rates')
32  parser.add_argument('-f','--fill',default=None,dest='FILLNUMBER', metavar='F',type=int, nargs='+',help='Fill number(s) for which to plot rates')
33  parser.add_argument('-t','--timerange',default=None,dest='TIMERANGE',help='Time range for which to plot rates YYYY-MM-DD:HH:MM:SS;YYYY-MM-DD:HH:MM:SS')
34  parser.add_argument('-n','--nofilter',dest='FILTER',action='store_false',help='Turns off filtering for dead time, stable beams and Atlas ready.')
35  parser.add_argument('-b','--batch',dest='BATCH',action='store_true',help='Enables batch mode, automatically saves canvases instead of displaying')
36  parser.add_argument('-x','--xunit',default='time',dest='XUNIT',help='X axis unit to plot rates against, ["time","luminosity","noBX"]')
37  parser.add_argument('-v','--verbose',dest='VERBOSE',action='store_true',help='Sets verbosity to TRUE, default is FALSE')
38  parser.add_argument('-l','--label',dest='LABEL',action='store_true',help='Adds Atlas Trigger Operations label')
39  parser.add_argument('-a','--linear',dest='LINEAR',action='store_false',help='Sets linear scale for plotting')
40  parser.add_argument('-s','--bunches',default=None,type=int,dest='LUMINOUSBUNCHES',help='Required luminous bunches')
41  parser.add_argument('-e','--envelope',dest='ENVELOPE',action='store_true',help='Draws filled error envelope, recommended for large fluctuations compared average rate')
42  parser.add_argument('-p','--points',dest='POINTS',action='store_true',help='Draws standard profile points')
43  parser.add_argument('-m','--processes',dest='PROCESSES',default=2,type=int,help='Sets number of processes for multiprocessing retrieval of COOL data')
44  args = parser.parse_args()
45 
46 from ROOT import TDatime, TProfile, TCanvas, TLegend, TGaxis, gROOT, SetOwnership, TColor, TLatex
47 
48 #====================================================================================================================
49 
50 def waitForReturn(fd):
51  logger.critical('Press Return to safely exit')
52  signal.signal(signal.SIGINT, signal.SIG_IGN)
53  while(1):
54  ch = os.read(fd,1)
55  if ch == '\n': break
56  logger.critical('Received signal, exiting at first chance')
57  return
58 
59 #====================================================================================================================
60 
61 def commonKeys(dictionaries):
62  if not len(dictionaries): return []
63  elif not len(dictionaries) >= 1: return dictionaries[0].keys()
64  keys = set(dictionaries[0].keys())
65  for dictionary in dictionaries[1:]:
66  keys = set(dictionary.keys())&keys
67  return list(keys)
68 
69 #====================================================================================================================
70 
72  def __init__(self,timeConverter = {}):
73  self.db_svc = cool.DatabaseSvcFactory.databaseService()
74  self.timeConverter=timeConverter
75  self.db = {}
76  self.folder = {}
77 
78  def getdb(self,dbName):
79  if dbName not in self.db:
80  self.db[dbName] = self.db_svc.openDatabase(dbName,True)
81  return self.db.get(dbName)
82 
83  def getFolder(self,folderName):
84  if folderName not in self.folder:
85  dbName = self.getdbName(folderName)
86  db = self.getdb(dbName)
87  self.folder[folderName] = db.getFolder(folderName)
88  return self.folder.get(folderName)
89 
90  def getdbName(self,folderName):
91  if folderName.startswith('/LHC/DCS/'):
92  return 'oracle://ATLAS_COOLPROD;schema=ATLAS_COOLOFL_DCS;dbname=COMP200;'
93  if folderName.startswith('/TRIGGER/HLT/') and 'Rates' in folderName:
94  return "oracle://ATLAS_COOLPROD;schema=ATLAS_COOLONL_TRIGGER;dbname=MONP200;"
95  if not folderName.startswith('/'): folderName = '/'+folderName
96  return "oracle://ATLAS_COOLPROD;schema=ATLAS_COOLONL_{0};dbname=COMP200;".format(folderName.split("/")[1])
97 
98  def convertTime(self,timeStart,timeEnd,timeConverter):
99  validRunLbs = [runLb for runLb,time in timeConverter.items() if timeStart<=time<=timeEnd]
100  return validRunLbs
101 
102  def processQuery(self,queryBundle):
103  folder = self.getFolder(queryBundle.folderName)
104  folder.setPrefetchAll(False)
105  result = {}
106  for payloadName,payloadAlias,cast in queryBundle.payloadRequests: result[payloadAlias]={}
107  folderIterator = folder.browseObjects(queryBundle.IoVStart,queryBundle.IoVEnd,queryBundle.channelSelection)
108  if queryBundle.timeBased:
109  while folderIterator.goToNext():
110  currentSlice = folderIterator.currentRef()
111  for payloadName,payloadAlias,cast in queryBundle.payloadRequests:
112  payload = cast(currentSlice.payloadValue(payloadName))
113  if payloadName in queryBundle.payloadRequirements:
114  if not eval(queryBundle.payloadRequirements[payloadName].format(repr(payload))): continue
115  runLbs = self.convertTime(int(currentSlice.since()),int(currentSlice.until()),queryBundle.timeConverter)
116  result[payloadAlias].update(dict.fromkeys(runLbs,payload))
117  else:
118  while folderIterator.goToNext():
119  currentSlice = folderIterator.currentRef()
120  for payloadName,payloadAlias,cast in queryBundle.payloadRequests:
121  payload = cast(currentSlice.payloadValue(payloadName))
122  if payloadName in queryBundle.payloadRequirements:
123  if not eval(queryBundle.payloadRequirements['payloadName'].format(repr(payload))): continue
124  runLbs = range(max(currentSlice.since(),queryBundle.IoVStart),min(currentSlice.until(),queryBundle.IoVEnd))
125  result[payloadAlias].update(dict.fromkeys(runLbs,payload))
126 
127  folderIterator.close()
128  return result
129 
130  def close(self):
131  for db in self.db.values(): db.closeDatabase()
132 
133  def __call__(self,queueIn,queueOut):
134  signal.signal(signal.SIGINT, signal.SIG_IGN)
135  try:
136  while True:
137  try:
138  queryBundle = queueIn.get(False,.001)
139  except Empty:
140  sleep(.001)
141  continue
142  if queryBundle is True:
143  break
144  resultBundle = self.processQuery(queryBundle)
145  queueOut.put(resultBundle)
146  except Exception as exception:
147  logger.critical(exception)
148 
149  self.close()
150  queueOut.put(True)
151  return
152 
153 #====================================================================================================================
154 
156  def __init__(self,mySignal,numProc=None,timeConverter={},verbose=False):
159  self.QueryProcesses = []
160  self.result = {}
161  self.counter=0
162  self.verbose = verbose
163  self.timeConverter = timeConverter
164  self.mySignal = mySignal
165  if numProc is None: numProc = cpu_count()
166  self.numProc = numProc
167 
168  def createProcesses(self):
169  self.QueryProcesses = []
170  for i in range(self.numProc):
171  process = Process(target = COOLQueryWorker(timeConverter=self.timeConverter), args = (self.troughQueue,self.resultQueue,))
172  self.QueryProcesses.append(process)
173 
174  def addQueryBundle(self,queryBundle):
175  self.counter+=1
176  self.troughQueue.put(queryBundle)
177 
178  def beginQuery(self):
179  self.createProcesses()
180  for i in range(self.numProc):
181  self.troughQueue.put(True)
182  logger.info('{0} queries distributed over {1} workers'.format(self.counter,len(self.QueryProcesses)))
183  for process in self.QueryProcesses: process.start()
184  try:
185  self.collectResults()
186  except KeyboardInterrupt:
187  logger.critical('Caught signal, terminating processes')
188  self.terminateProcesses()
189  return
190  for process in self.QueryProcesses: process.join()
191  return
192 
193  def processResults(self,resultBundle):
194  for resultAlias in resultBundle:
195  if resultAlias not in self.result: self.result[resultAlias]={}
196  self.result[resultAlias].update(resultBundle[resultAlias])
197 
199  while 1:
200  try:self.troughQueue.get(False)
201  except Empty: break
202  logger.critical('Queue is empty')
203  for i in range(self.numProc): self.troughQueue.put(True)
204  time.sleep(1)
205  for process in self.QueryProcesses:
206  process.terminate()
207  process.join()
208  logger.critical('Processes are joined')
209  raise KeyboardInterrupt
210 
211  def collectResults(self):
212  finished = 0
213  startingQueries = self.counter
214  target=0.
215  while True:
216  if not self.mySignal.is_alive():
217  raise KeyboardInterrupt
218  break
219  #sys.exit(0)
220  try: resultBundle = self.resultQueue.get(False,0.001)
221  except Empty:
222  sleep(.001)
223  continue
224  if resultBundle is True:
225  finished+=1
226  if finished == self.numProc: break
227  continue
228  self.counter-=1
229  percentComplete = min(100,int(round(float(startingQueries-self.counter)/startingQueries*100+.5)))
230  if percentComplete>=target:
231  target+=5.
232  logger.info('{0}% complete'.format(percentComplete))
233  self.processResults(resultBundle)
234 # except KeyboardInterrupt:
235 # logger.critical('Caught signal, terminating processes')
236 # self.terminateProcesses()
237  return
238 
239 #====================================================================================================================
240 
241 def createTimeConverter(runLbRanges):
242  timeConverter = {}
243  worker = COOLQueryWorker()
244 
245  if runLbRanges is not None:
246  folder = worker.getFolder('/TRIGGER/LUMI/LBLB')
247  folder.setPrefetchAll(False)
248  for runLbStart,runLbEnd in runLbRanges:
249  timeConverter[(runLbStart,runLbEnd)]={}
250  folderIterator = folder.browseObjects(runLbStart,runLbEnd,cool.ChannelSelection())
251  while folderIterator.goToNext():
252  currentSlice = folderIterator.currentRef()
253  timeConverter[(runLbStart,runLbEnd)][int(currentSlice.since())] = int(currentSlice.payloadValue('StartTime'))
254  folderIterator.close()
255 
256  return timeConverter
257 
258 #====================================================================================================================
259 
260 class QueryBundle():
261  def __init__(self,IoVStart,IoVEnd,payloadRequests,folderName,channelSelection=None,timeBased=False,payloadRequirements={},timeConverter={}):
262  self.IoVStart = IoVStart
263  self.IoVEnd = IoVEnd
264  for request in payloadRequests:
265  if not len(request)==3:
266  print(payloadRequests)
267  sys.exit(0)
268  self.payloadRequests = payloadRequests
269  self.payloadRequirements = payloadRequirements
270  self.folderName = folderName
271  self.timeBased=timeBased
272  self.timeConverter=timeConverter
273  self.channelSelection = channelSelection or cool.ChannelSelection()
274 
275 #====================================================================================================================
276 
277 
285 
286 folderLocations = {}
287 
288 folderLocations[0] = {}
289 folderLocations[0]['Input'] = ('/TRIGGER/LUMI/LVL1COUNTERS','BeforePrescale','/TRIGGER/LVL1/CTPCORELBDATA','BeforePrescaleTurnCounter')
290 folderLocations[0]['AfterPrescale'] = ('/TRIGGER/LUMI/LVL1COUNTERS','AfterPrescale','/TRIGGER/LVL1/CTPCORELBDATA','AfterPrescaleTurnCounter')
291 folderLocations[0]['Output'] = ('/TRIGGER/LUMI/LVL1COUNTERS','L1Accept','/TRIGGER/LVL1/CTPCORELBDATA','L1AcceptTurnCounter')
292 
293 folderLocations[1] = {}
294 folderLocations[1]['Input'] = ('/TRIGGER/HLT/L2Rates','Prescale',None,None)
295 folderLocations[1]['AfterPrescale'] = ('/TRIGGER/HLT/L2Rates','Input',None,None)
296 folderLocations[1]['Output'] = ('/TRIGGER/HLT/L2Rates','Output',None,None)
297 
298 folderLocations[2] = {}
299 folderLocations[2]['Input'] = ('/TRIGGER/HLT/EFRates','Prescale',None,None)
300 folderLocations[2]['AfterPrescale'] = ('/TRIGGER/HLT/EFRates','Input',None,None)
301 folderLocations[2]['Output'] = ('/TRIGGER/HLT/EFRates','Output',None,None)
302 
303 folderLocations[3] = {}
304 folderLocations[3]['Input'] = ('/TRIGGER/HLT/TotalRates','Input',None,None)
305 folderLocations[3]['AfterPrescale'] = ('/TRIGGER/HLT/TotalRates','Input',None,None)
306 folderLocations[3]['Output'] = ('/TRIGGER/HLT/TotalRates','Output',None,None)
307 
308 def rateNameInfo(runLbRanges,mySignal,numProc=1):
309  def rateNameWorker(queueIn,queueOut):
310  worker = COOLQueryWorker()
311  while(1):
312  try: run = queueIn.get(False,0.001)
313  except Empty:
314  sleep(.001)
315  continue
316  if run is True:
317  break
318  runLbStart=run<<32
319  runLbEnd=runLbStart+1
320  nameToChannel={}
321  nameToFolder={}
322  #L1 Triggers
323  folder = worker.getFolder("/TRIGGER/LVL1/Menu")
324  folder.setPrefetchAll(False)
325  folderIterator = folder.browseObjects(runLbStart,runLbEnd,cool.ChannelSelection())
326  while folderIterator.goToNext():
327  currentSlice = folderIterator.currentRef()
328  nameToChannel[currentSlice.payloadValue('ItemName')] = currentSlice.channelId()
329  nameToFolder[currentSlice.payloadValue('ItemName')] = 0
330  folderIterator.close()
331  #HLT Triggers
332  folder = worker.getFolder("/TRIGGER/HLT/Menu")
333  folder.setPrefetchAll(False)
334  folderIterator = folder.browseObjects(runLbStart,runLbEnd,cool.ChannelSelection())
335  while folderIterator.goToNext():
336  currentSlice = folderIterator.currentRef()
337  if currentSlice.payloadValue('ChainName').startswith('L2'):
338  nameToChannel[currentSlice.payloadValue('ChainName')] = int(currentSlice.payloadValue('ChainCounter'))
339  nameToFolder[currentSlice.payloadValue('ChainName')] = 1
340  elif currentSlice.payloadValue('ChainName').startswith('EF'):
341  nameToChannel[currentSlice.payloadValue('ChainName')] = int(currentSlice.payloadValue('ChainCounter'))
342  nameToFolder[currentSlice.payloadValue('ChainName')] = 2
343  folderIterator.close()
344  #Totals/Streams
345  folder = worker.getFolder("/TRIGGER/HLT/TotalRates")
346  folder.setPrefetchAll(False)
347  for channel in folder.listChannels():
348  nameToChannel[folder.channelName(channel)] = channel
349  nameToFolder[folder.channelName(channel)] = 3
350  queueOut.put(({run:nameToChannel},{run:nameToFolder}))
351  queueOut.put(True)
352  return
353 
354  def terminateProcesses(QueryProcesses,troughQueue):
355  while 1:
356  try:troughQueue.get(False)
357  except Empty: break
358  logger.critical('Queue is empty')
359  for i in range(numProc): troughQueue.put(True)
360  time.sleep(1)
361  for process in QueryProcesses:
362  process.terminate()
363  process.join()
364  logger.critical('Processes are joined')
365  raise KeyboardInterrupt
366 
367  nameToChannel = {}
368  nameToFolder = {}
369 
370  troughQueue = Queue()
371  resultQueue = Queue()
372 
373  processes = [Process(target=rateNameWorker,args=(troughQueue,resultQueue,)) for i in range(numProc)]
374  for process in processes: process.start()
375 
376  counter = 0
377  target = 0.
378  finished = 0
379 
380  runs = list(set([runLbStart>>32 for runLbStart,runLbEnd in runLbRanges]))
381 
382  for run in runs:
383  counter+=1
384  troughQueue.put(run)
385 
386  startingQueries = counter
387 
388  logger.info('{0} queries distributed over {1} workers'.format(startingQueries,numProc))
389 
390  for i in range(numProc): troughQueue.put(True)
391 
392  try:
393  while(1):
394  if not mySignal.is_alive():
395  raise KeyboardInterrupt
396  break
397  try: result = resultQueue.get(False,0.001)
398  except Empty:
399  time.sleep(.001)
400  continue
401  if result is True:
402  finished+=1
403  if finished==numProc: break
404  continue
405  tempNTC,tempNTF = result
406  nameToChannel.update(tempNTC)
407  nameToFolder.update(tempNTF)
408  counter-=1
409  percentComplete = min(100,int(round(float(startingQueries-counter)/startingQueries*100+.5)))
410  if percentComplete>=target:
411  target+=5.
412  logger.info('{0}% complete'.format(percentComplete))
413  except KeyboardInterrupt:
414  logger.critical('Caught signal, terminating processes')
415  terminateProcesses(processes,troughQueue)
416 
417  for process in processes: process.join()
418 
419  return nameToChannel,nameToFolder
420 
421 #====================================================================================================================
422 
424  def __init__(self):
425  COOLQueryWorker.__init__(self)
426 
427  def processQuery(self,rateBundle):
428  result = {}
429  result[rateBundle.alias] = {}
430 
431  #Get first result
432  firstResult = {}
433  folder = self.getFolder(rateBundle.folderName)
434  folder.setPrefetchAll(False)
435  folderIterator = folder.browseObjects(rateBundle.IoVStart,rateBundle.IoVEnd,rateBundle.channelSelection)
436  while folderIterator.goToNext():
437  currentSlice = folderIterator.currentRef()
438  firstResult[currentSlice.since()]=float(currentSlice.payloadValue(rateBundle.payloadName))
439  folderIterator.close()
440 
441  #Get second result (if counts based)
442  if rateBundle.turnCountFolderName is not None:
443  secondResult = {}
444  folder = self.getFolder(rateBundle.turnCountFolderName)
445  folder.setPrefetchAll(False)
446  folderIterator = folder.browseObjects(rateBundle.IoVStart,rateBundle.IoVEnd,cool.ChannelSelection())
447  while folderIterator.goToNext():
448  currentSlice = folderIterator.currentRef()
449  secondResult[currentSlice.since()]=float(currentSlice.payloadValue(rateBundle.turnCountPayloadName))
450  folderIterator.close()
451  result[rateBundle.alias].update(dict((key,11246.0*firstResult.get(key)/secondResult.get(key)) for key in commonKeys([firstResult,secondResult])))
452  else:
453  result[rateBundle.alias].update(firstResult)
454  return result
455 
456 #====================================================================================================================
457 
459  def __init__(self,IoVStart,IoVEnd,alias,folderName,payloadName,turnCountFolderName,turnCountPayloadName,channel):
460  self.IoVStart = IoVStart
461  self.IoVEnd = IoVEnd
462  self.alias = alias
463  self.folderName = folderName
464  self.payloadName = payloadName
465  self.turnCountFolderName = turnCountFolderName
466  self.turnCountPayloadName = turnCountPayloadName
467  self.channelSelection = cool.ChannelSelection(channel)
468 
469 #====================================================================================================================
470 
471 def generateRateQueryBundles(name,level,runLbRanges,nameToChannel,nameToFolder,alias=None):
472  queryBundles = []
473  if alias is None: alias = name
474  for runLbStart,runLbEnd in runLbRanges:
475  run = runLbStart>>32
476  if run not in nameToChannel:continue
477  if name not in nameToChannel[run]:continue
478  channel = nameToChannel[run][name]
479  if run not in nameToFolder:continue
480  if name not in nameToFolder[run]:continue
481  rateType = nameToFolder[run][name]
482  if rateType not in folderLocations:continue
483  if level not in folderLocations[rateType]:continue
484  folderName,payloadName,turnCounterFolder,turnCountPayloadName = folderLocations[rateType][level]
485  queryBundle = RateQueryBundle(runLbStart,runLbEnd,alias,folderName,payloadName,turnCounterFolder,turnCountPayloadName,channel)
486  queryBundles.append(queryBundle)
487  return queryBundles
488 
489 #====================================================================================================================
490 
492  def __init__(self,mySignal,numProc=None,verbose=False):
493  COOLQueryHandler.__init__(self,mySignal,numProc=numProc,verbose=verbose)
494  self.QueryWorkers = []
495  for i in range(self.numProc):
496  worker = RateQueryWorker()
497  self.QueryWorkers.append(worker)
498 
499  def createProcesses(self):
500  self.QueryProcesses = []
501  for i in range(self.numProc):
502  process = Process(target = RateQueryWorker(), args = (self.troughQueue,self.resultQueue,))
503  self.QueryProcesses.append(process)
504 #====================================================================================================================
505 
506 def parseRatesString(ratesString):
507  groups_ = []
508  groups = ratesString.split('|')
509  for group in groups:
510  if group == '': continue
511  groups_.append([])
512  for rate in group.split(','):
513  if rate == '': continue
514  if ':' in rate:
515  rateName,alias = tuple(rate.split(':'))
516  else:
517  rateName,alias = (rate,rate)
518  if rateName.endswith('-0'):
519  level = 'Input'
520  rateName = rateName[:-2]
521  elif rateName.endswith('-1'):
522  level = 'AfterPrescale'
523  rateName = rateName[:-2]
524  else:
525  level = 'Output'
526  groups_[-1].append((rateName,alias,level))
527  return groups_
528 
529 #====================================================================================================================
530 
531 def runNumberToRunLbRange(runNumbers):
532  runLbRanges = []
533  worker = COOLQueryWorker()
534  folder = worker.getFolder('/TRIGGER/LUMI/LBLB')
535  folder.setPrefetchAll(False)
536  channelSelection = cool.ChannelSelection()
537  for runNumber in runNumbers:
538  folderIterator = folder.browseObjects(runNumber<<32,((runNumber+1)<<32)-1,channelSelection)
539  if folderIterator.isEmpty():
540  folderIterator.close()
541  continue
542  runLbs = []
543  while folderIterator.goToNext():
544  currentSlice = folderIterator.currentRef()
545  runLbs.append(currentSlice.since())
546  folderIterator.close()
547  runLbRanges.append((min(runLbs),max(runLbs)))
548  worker.close()
549  return runLbRanges
550 
551 #====================================================================================================================
552 
553 def timeRangeToRunLbRange(timeRange):
554 
555  if len(timeRange.split(';'))!=2:
556  logger.critical('Time range "{0}" does not match YYYY-MM-DD:HH:mm:ss;YYYY-MM-DD:HH:mm:ss'.format(timeRange))
557  sys.exit(0)
558  timeStart,timeEnd = tuple(timeRange.split(';'))
559  try:
560  timeStart = time.strptime(timeStart,'%Y-%m-%d:%H:%M:%S')
561  timeEnd = time.strptime(timeEnd,'%Y-%m-%d:%H:%M:%S')
562  except Exception:
563  logger.critical('Time range "{0}" does not match YYYY-MM-DD:HH:mm:ss;YYYY-MM-DD:HH:mm:ss'.format(timeRange))
564  sys.exit(0)
565 
566  timeStart = int(time.mktime(timeStart))*10**9
567  timeEnd = int(time.mktime(timeEnd))*10**9
568 
569  return nanoTimeRangesToRunLbRanges([(timeStart,timeEnd)])
570 
571 #====================================================================================================================
572 
573 def nanoTimeRangesToRunLbRanges(nanoTimeRanges):
574  runLbRanges = []
575  worker = COOLQueryWorker()
576  folder = worker.getFolder('/TRIGGER/LUMI/LBTIME')
577  folder.setPrefetchAll(False)
578  channelSelection = cool.ChannelSelection()
579  for timeStart,timeEnd in nanoTimeRanges:
580  folderIterator = folder.browseObjects(timeStart,timeEnd,channelSelection)
581  if folderIterator.isEmpty():
582  folderIterator.close()
583  continue
584  temp = {}
585  while folderIterator.goToNext():
586  currentSlice = folderIterator.currentRef()
587  run = int(currentSlice.payloadValue('Run'))
588  lb = int(currentSlice.payloadValue('LumiBlock'))
589  runLb = (run<<32)+lb
590  if run not in temp: temp[run]=[]
591  temp[run].append(runLb)
592  for run,runLbs in temp.items():
593  runLbRanges.append((min(runLbs),max(runLbs)))
594  folderIterator.close()
595  worker.close()
596  return runLbRanges
597 
598 #====================================================================================================================
599 
600 def fillNumberToRunLbRange(fillNumbers):
601  minFill = min(fillNumbers)-1
602  worker = COOLQueryWorker()
603  result = {}
604  folder = worker.getFolder('/LHC/DCS/FILLSTATE')
605  folder.setPrefetchAll(False)
606  timeEnd = int(time.mktime(time.localtime()))*10**9
607  channelSelection = cool.ChannelSelection()
608  for i in range(25):
609  timeStart = timeEnd-259200000000000
610  #load information in 3 day chunks until lowest fill is less than or equal to minFill (break after loading full year)
611  folderIterator = folder.browseObjects(timeStart,timeEnd,channelSelection)
612  while folderIterator.goToNext():
613  currentSlice = folderIterator.currentRef()
614  fillNumber = currentSlice.payloadValue('FillNumber')
615  if not fillNumber.isdigit(): continue
616  fillNumber = int(fillNumber)
617  if fillNumber not in result: result[fillNumber]=[]
618  result[fillNumber].append(currentSlice.since())
619  result[fillNumber].append(currentSlice.until())
620  folderIterator.close()
621  timeEnd = timeStart
622  if not len(result): continue
623  if min(result.keys())<=minFill: break
624  nanoTimeRanges = []
625  for fillNumber in list(set(fillNumbers)&set(result.keys())):
626  nanoTimes = result[fillNumber]
627  nanoTimeRanges.append((min(nanoTimes),max(nanoTimes)))
628  worker.close()
629  return nanoTimeRangesToRunLbRanges(nanoTimeRanges)
630 
631 #====================================================================================================================
632 """
633 This marks the beginning of plotting related tools
634 """
635 #====================================================================================================================
636 
638  from ROOT import TStyle
639 
640  atlasStyle = TStyle("ATLAS","Atlas style")
641 
642  atlasStyle.SetFrameBorderMode(0)
643  atlasStyle.SetFrameFillColor(0)
644  atlasStyle.SetCanvasBorderMode(0)
645  atlasStyle.SetCanvasColor(0)
646  atlasStyle.SetPadBorderMode(0)
647  atlasStyle.SetPadColor(0)
648  atlasStyle.SetStatColor(0)
649  atlasStyle.SetPaperSize(20,26)
650  atlasStyle.SetPadTopMargin(0.07)
651  atlasStyle.SetPadRightMargin(0.05)
652  atlasStyle.SetPadBottomMargin(0.16)
653  atlasStyle.SetPadLeftMargin(0.16)
654  atlasStyle.SetTitleXOffset(1.4)
655  atlasStyle.SetTitleYOffset(1.2)
656  font=43
657  tsize=0.05
658  atlasStyle.SetTextFont(font)
659  atlasStyle.SetTextSize(tsize)
660  atlasStyle.SetLabelFont(font,"x")
661  atlasStyle.SetTitleFont(font,"x")
662  atlasStyle.SetLabelFont(font,"y")
663  atlasStyle.SetTitleFont(font,"y")
664  atlasStyle.SetLabelFont(font,"z")
665  atlasStyle.SetTitleFont(font,"z")
666  atlasStyle.SetLabelSize(tsize,"x")
667  atlasStyle.SetTitleSize(tsize,"x")
668  atlasStyle.SetLabelSize(tsize,"y")
669  atlasStyle.SetTitleSize(tsize,"y")
670  atlasStyle.SetLabelSize(tsize,"z")
671  atlasStyle.SetTitleSize(tsize,"z")
672  atlasStyle.SetMarkerStyle(20)
673  atlasStyle.SetMarkerSize(1.2)
674  atlasStyle.SetHistLineWidth(2)
675  atlasStyle.SetLineStyleString(2,"[12 12]")
676  atlasStyle.SetEndErrorSize(0.)
677  atlasStyle.SetOptTitle(0)
678  atlasStyle.SetOptStat(0)
679  atlasStyle.SetOptFit(0)
680  atlasStyle.SetPadTickX(1)
681  atlasStyle.SetPadTickY(1)
682 
683  gROOT.SetStyle("ATLAS")
684  gROOT.ForceStyle()
685 
686 #====================================================================================================================
687 
688 
693 
694 MarkerColors = [TColor.GetColor(hexColor) for hexColor in ['#000000','#2956B2','#7DBD00','#FF542E','#AA0078','#FFCC00','#D01A55','#A6AF7A','#DCF600','#FF5B00','#659CEF','#F2BC00','#FFF0BA']]
695 MarkerStyles = [20,21,22, 29,31, 33, 34, 23,24,25,26,27,28, 30]
696 MarkerSizes = [1.,1.,1.4,1.8,1.,1.8,1.4,1.4,1.,1.,1.,1.,1.,1.8]
697 
698 def fillProfile(profileName,numBins,xMin,xMax,xValues,yValues):
699  profile = TProfile(profileName,profileName,int(numBins),xMin,xMax)
700  for x,y in zip(xValues,yValues):
701  profile.Fill(x,y)
702  return profile
703 
704 #====================================================================================================================
705 
707  rates = []
708  if 'profiles' not in data: data['profiles'] = {}
709  for group in data['groups']:
710  for rate in group:
711  rates.append(rate)
712  xOffset = data['plotConfig']['xOffset']
713  xScale = data['plotConfig']['xScale']
714  for rateName,alias,level in rates:
715  if data['xUnit'] == 'noBX':
716  if 'filter' in data:
717  runLbs = commonKeys([data[data['xUnit']],data['filter'],data['rates'][alias],data['luminosity']])
718  else:
719  runLbs = commonKeys([data[data['xUnit']],data['rates'][alias],data['luminosity']])
720  else:
721  if 'filter' in data:
722  runLbs = commonKeys([data[data['xUnit']],data['filter'],data['rates'][alias]])
723  else:
724  runLbs = commonKeys([data[data['xUnit']],data['rates'][alias]])
725  xValues = []
726  yValues = []
727  if data['xUnit'] == 'noBX':
728  for runLb in runLbs:
729  luminosity = data['luminosity'].get(runLb)
730  if luminosity==0.: continue
731  yValue = data['rates'][alias].get(runLb)/luminosity
732  xValues.append(data[data['xUnit']].get(runLb)/xScale - xOffset)
733  yValues.append(yValue)
734  else:
735  for runLb in runLbs:
736  xValues.append(data[data['xUnit']].get(runLb)/xScale - xOffset)
737  yValues.append(data['rates'][alias].get(runLb))
738  data['profiles'][alias] = fillProfile(alias,data['plotConfig']['numBins'],data['plotConfig']['xMin'],data['plotConfig']['xMax'],xValues,yValues)
739  return data
740 
741 #====================================================================================================================
742 
743 
757 
759  xUnit = data['xUnit']
760  if xUnit == 'time':
761  data.update(configureTime(data))
762  elif xUnit == 'luminosity':
763  data.update(configureLuminosity(data))
764  elif xUnit == 'noBX':
765  data.update(configureNoBX(data))
766  return data
767 
768 #====================================================================================================================
769 
770 def configureTime(data):
771  xScale = 1.0*10**9
772  validPoints = len(data['time'])
773  if validPoints:
774  xOffset = min(data['time'].values())/xScale
775  xMin = 0.
776  xMax = max(data['time'].values())/xScale-xOffset
777  maxBins = xMax/300
778  minBins = xMax/1200
779  if maxBins <= 160:
780  numBins = maxBins
781  elif maxBins/2 <= 160:
782  numBins = maxBins/2
783  elif maxBins/3 <= 160:
784  numBins = maxBins/3
785  else:
786  numBins = minBins
787  if xMax > 48*60*60: xFormat = "%d/%m"
788  elif xMax > 12*60*60: xFormat = "%d-%Hh"
789  else: xFormat = "%H:%M"
790  else:
791  xOffset = 0.
792  xMin = 0.
793  xMax = 1.
794  numBins = 1.
795  xFormat = "%d/%m"
796  xLabel = time.strftime("%Z Time")
797  if 'filter' in data:
798  validPoints = len(commonKeys([data['time'],data['filter']]))
799  data['plotConfig'] = {'xMin':xMin,'xMax':xMax,'xLabel':xLabel,'xScale':xScale,'xOffset':xOffset,'xFormat':xFormat,'numBins':numBins,'validPoints':validPoints,'yLabel':'Rate [Hz]'}
800  return data
801 
802 #====================================================================================================================
803 
805  if 'filter' in data:
806  validPoints = len(commonKeys([data['luminosity'],data['filter']]))
807  if not validPoints:
808  xMin = 0
809  xMax = 0
810  else:
811  xMin = min([data['luminosity'][runLb] for runLb in commonKeys([data['luminosity'],data['filter']])])
812  xMax = max([data['luminosity'][runLb] for runLb in commonKeys([data['luminosity'],data['filter']])])
813  else:
814  validPoints = len(data['luminosity'])
815  if not validPoints:
816  xMin = 0
817  xMax = 0
818  else:
819  xMin = min(data['luminosity'].values())
820  xMax = max(data['luminosity'].values())
821  if xMin and xMax:
822  xScale=round(log10(xMax)-.5)
823  xLabel = 'Inst. Luminosity [10^{'+str(int(30+xScale))+'} cm^{-2} s^{-1}]'
824  xScale = float(10**xScale)
825  else:
826  xScale = 1.0
827  xLabel = 'Inst. Luminosity [10^{'+str(int(xScale+30))+'} cm^{-2} s^{-1}]'
828  xMin/=xScale
829  xMax/=xScale
830  xOffset = 0.0
831  numBins = int(min(validPoints/3.,100))
832  xFormat = None
833  data['plotConfig'] = {'xMin':xMin,'xMax':xMax,'xLabel':xLabel,'xScale':xScale,'xOffset':xOffset,'xFormat':xFormat,'numBins':numBins,'validPoints':validPoints,'yLabel':'Rate [Hz]'}
834  return data
835 
836 #====================================================================================================================
837 
838 def configureNoBX(data):
839  if 'filter' in data:
840  validPoints = len(commonKeys([data['noBX'],data['filter']]))
841  if not validPoints:
842  xMin = 0
843  xMax = 0
844  else:
845  xMin = min([data['noBX'][runLb] for runLb in commonKeys([data['noBX'],data['filter']])])
846  xMax = max([data['noBX'][runLb] for runLb in commonKeys([data['noBX'],data['filter']])])
847  else:
848  validPoints = len(data['noBX'])
849  if not validPoints:
850  xMin = 0
851  xMax = 0
852  else:
853  xMin = min(data['noBX'].values())
854  xMax = max(data['noBX'].values())
855  xScale = 1.0
856  xLabel = 'Average Interactions per Bunch Crossing'
857  xOffset = 0.0
858  numBins = int(min(validPoints/3.,100))
859  xFormat = None
860  data['plotConfig'] = {'xMin':xMin,'xMax':xMax,'xLabel':xLabel,'xScale':xScale,'xOffset':xOffset,'xFormat':xFormat,'numBins':numBins,'validPoints':validPoints,'yLabel':'Cross-section [outhouse]'}
861  return data
862 
863 #====================================================================================================================
864 
865 def getNiceCanvas(name,aliases,textSize=25):
866  canvas = TCanvas(name, name, 4, 45, 700, 500)
867  canvas.SetGridx(1)
868  canvas.SetGridy(1)
869  canvas.SetFillColor(0)
870  canvas.SetBorderMode(0)
871  canvas.SetBorderSize(0)
872  canvas.SetFrameFillColor(0)
873  #Stretch width and add subpad for legend
874  width = int(max([len(nm) for nm in aliases])*textSize*.50)+70
875  oldWidth = canvas.GetWindowWidth()
876  newWidth = oldWidth+width
877  canvas.SetCanvasSize(newWidth,canvas.GetWindowHeight())
878  canvas.Divide(2,1)
879  subPad1 = canvas.GetPad(1)
880  subPad1.SetPad(.005,.005,float(oldWidth)/newWidth,.995)
881  subPad2 = canvas.GetPad(2)
882  subPad2.SetPad(float(oldWidth)/newWidth,.005,.995,.995)
883  SetOwnership(canvas, 0)
884  return canvas
885 
886 #====================================================================================================================
887 
888 def configureCanvasLegend(canvas,aliases,textSize=25):
889  height = 1.2*len(aliases)*textSize/canvas.GetWh()
890  width = int(max([len(name) for name in aliases])*textSize*.50)+70
891  canvas.SetLeftMargin(canvas.GetLeftMargin()*textSize/14.)
892  canvas.SetBottomMargin(canvas.GetBottomMargin()*textSize/14.)
893  legend = TLegend(0.00,1-canvas.GetTopMargin(),150./width,1-canvas.GetTopMargin()-height)
894  legend.SetTextSize(textSize)
895  legend.SetFillColor(0)
896  legend.SetShadowColor(0)
897  legend.SetBorderSize(0)
898  SetOwnership(legend, 0)
899 
900  return canvas,legend
901 
902 #====================================================================================================================
903 
904 def plotRateProfiles(data,label=False,runNumber=None,fillNumber=None,log=True,minY=None,maxY=None,luminousBunches=None,drawOption='H'):
905 
906  TGaxis.SetMaxDigits(3)
907 
908  data['canvases']={}
909 
910  for groupNum,group in enumerate(data['groups']):
911 
912  if minY is None: minY = 0.
913  if log: minY = max([10**-9,minY])
914  if maxY is None: maxY = 10.**10
915 
916  currentMin = maxY
917  currentMax = minY
918 
919  aliases = []
920  for rateName,alias,level in group:
921  aliases.append(alias)
922  temp = [data['profiles'][alias].GetBinContent(i) for i in range(data['profiles'][alias].GetNbinsX()+1) if minY<data['profiles'][alias].GetBinContent(i)<maxY]
923  if not len(temp): continue
924  thisMin = min(temp)
925  thisMax = max(temp)
926  currentMin = min(currentMin,thisMin)
927  currentMax = max(currentMax,thisMax)
928 
929  canvas = getNiceCanvas('canvas{0}'.format(('000'+str(groupNum))[-3:]),aliases)
930 
931  if currentMin>=currentMax:
932  logger.warning('No data in group, {0} is empty'.format(canvas.GetName()))
933  data['canvases'].update({canvas.GetName():canvas})
934  continue
935 
936  scale = 1.1
937  if log: scale = 1.5
938  thisMinY = currentMin/scale
939  thisMaxY = currentMax*scale
940 
941  subPad1 = canvas.GetPad(1)
942  if log: subPad1.SetLogy()
943 
944  canvas,legend = configureCanvasLegend(canvas,aliases)
945 
946  legendOption = 'L'
947  if 'P' in drawOption: legendOption = 'p'
948 
949  canvas.cd(1)
950  for i,(rateName,alias,level) in enumerate(group):
951 
952  profile = data['profiles'][alias]
953  profile = configureProfile(profile,i,thisMinY,thisMaxY,drawOption,data,log)
954  if drawOption:
955  if not i: profile.Draw(drawOption)
956  else: profile.Draw('{0} SAME'.format(drawOption))
957  else:
958  if not i: profile.Draw()
959  else: profile.Draw('SAME')
960  if log:
961  yAxis = profile.GetYaxis()
962  if int(log10(minY)) == int(log10(maxY)): yAxis.SetMoreLogLabels(True)
963  else: yAxis.SetMoreLogLabels(False)
964  yAxis.Draw()
965  legend.AddEntry(profile,alias,legendOption)
966 
967  canvas.cd(2)
968  legend.Draw()
969 
970  canvas.cd(1)
971  if label:
972  scale = 1.0*10**9
973  timeStart = min(data['time'].values())/scale
974  timeEnd = max(data['time'].values())/scale
975  timeLabel = fetchTimeLabel(timeStart,timeEnd)
976  #startLumi,endLumi = getLumiEndPoints(data)
977  canvas = generateAtlasLabel(canvas,timeLabel,luminousBunches,runNumber=runNumber,fillNumber=fillNumber)
978  data['canvases'].update({canvas.GetName():canvas})
979 
980  return data
981 
982 #====================================================================================================================
983 
984 def configureProfile(profile,i,minY,maxY,drawOption,data,log,textSize=25):
985  profile.SetMarkerColor(MarkerColors[i])
986  profile.SetMarkerStyle(MarkerStyles[i])
987  profile.SetMarkerSize(MarkerSizes[i])
988  profile.SetLineColor(MarkerColors[i])
989  if drawOption!='P': profile.SetMarkerSize(0.0)
990  if drawOption=='E3':
991  #profile.SetFillStyle(3001)
992  profile.SetFillColor(MarkerColors[i])
993  if not i:
994  profile.GetXaxis().SetLabelSize(textSize)
995  profile.GetXaxis().SetTitleSize(textSize)
996  profile.GetYaxis().SetLabelSize(textSize)
997  profile.GetYaxis().SetTitleSize(textSize)
998  profile.SetMinimum(minY)
999  profile.SetMaximum(maxY)
1000  profile.GetXaxis().SetTitle(data['plotConfig']['xLabel'])
1001  profile.GetYaxis().SetTitle(data['plotConfig']['yLabel'])
1002  if data['xUnit'] == 'time':
1003  profile.GetXaxis().SetTimeDisplay(1)
1004  profile.GetXaxis().SetTimeFormat(data['plotConfig']['xFormat'])
1005  dh = TDatime()
1006  dh.Set(int(data['plotConfig']['xOffset']), False)
1007  profile.GetXaxis().SetTimeOffset(dh.Convert(False))
1008  profile.GetXaxis().SetNdivisions(507)
1009  else:
1010  profile.GetXaxis().SetTimeDisplay(0)
1011  return profile
1012 
1013 #====================================================================================================================
1014 
1016  if 'filter' in data:
1017  validPoints = len(commonKeys([data['luminosity'],data['filter']]))
1018  if not validPoints:
1019  lumiStart = 0.
1020  lumiEnd = 0.
1021  else:
1022  lumiStart = data['luminosity'][min(commonKeys([data['luminosity'],data['filter']]))]
1023  lumiEnd = data['luminosity'][max(commonKeys([data['luminosity'],data['filter']]))]
1024  else:
1025  if not validPoints:
1026  lumiStart = 0.
1027  lumiEnd = 0.
1028  else:
1029  lumiStart = data['luminosity'][min(data['luminosity'].keys())]
1030  lumiEnd = data['luminosity'][max(data['luminosity'].keys())]
1031  return (lumiStart,lumiEnd)
1032 
1033 #====================================================================================================================
1034 
1035 def generateAtlasLabel(canvas,timeLabel,luminousBunches,runNumber = None,fillNumber = None):
1036  canvas.cd(1)
1037 
1038  xOffset = .30
1039  yOffset = .27
1040 
1041  AtlasLabel = []
1042 
1043  AtlasLabel.append(TLatex())
1044  AtlasLabel[-1].SetNDC()
1045  AtlasLabel[-1].SetTextFont(42)
1046 
1047  if runNumber is None: runNumber = []
1048  if fillNumber is None: fillNumber = []
1049 
1050  if len(runNumber)==1:
1051  AtlasLabel[-1].DrawLatex(xOffset+0.115,yOffset,'Run {0} {1}'.format(runNumber[0],timeLabel))
1052  AtlasLabel.append(TLatex())
1053  AtlasLabel[-1].SetNDC()
1054  AtlasLabel[-1].SetTextFont(72)
1055  AtlasLabel[-1].DrawLatex(xOffset,yOffset,"ATLAS")
1056  elif len(fillNumber)==1:
1057  AtlasLabel[-1].DrawLatex(xOffset,yOffset,'LHC Fill {0} {1}'.format(fillNumber[0],timeLabel))
1058  else:
1059  AtlasLabel[-1].DrawLatex(xOffset,yOffset,'Running {0}'.format(timeLabel))
1060 
1061  AtlasLabel.append(TLatex())
1062  AtlasLabel[-1].SetNDC()
1063  AtlasLabel[-1].SetTextFont(72)
1064  AtlasLabel[-1].DrawLatex(xOffset,yOffset+.07,"ATLAS")
1065 
1066  AtlasLabel.append(TLatex())
1067  AtlasLabel[-1].SetNDC()
1068  AtlasLabel[-1].SetTextFont(42)
1069  AtlasLabel[-1].DrawLatex(xOffset+0.115,yOffset+.07,'Trigger Operations')
1070 
1071  if luminousBunches is not None:
1072  AtlasLabel.append(TLatex())
1073  AtlasLabel[-1].SetNDC()
1074  AtlasLabel[-1].SetTextFont(42)
1075  AtlasLabel[-1].DrawLatex(xOffset,yOffset-.07,'{0} Luminous Bunches'.format(luminousBunches))
1076 
1077  return canvas
1078 
1079 #====================================================================================================================
1080 
1081 def fetchTimeLabel(timeStart,timeEnd):
1082  timeTupleStart = time.localtime(timeStart)
1083  timeTupleEnd = time.localtime(timeEnd)
1084 
1085  if timeTupleStart.tm_year != timeTupleEnd.tm_year:
1086  timeLabel = '{0} - {1}'.format(time.strftime('%b. %e %Y',timeTupleStart),time.strftime('%b. %e %Y',timeTupleEnd))
1087  else:
1088  if timeTupleStart.tm_mon != timeTupleEnd.tm_mon:
1089  timeLabel = '{0} - {1} {2}'.format(time.strftime('%b. %e',timeTupleStart),time.strftime('%b. %e',timeTupleEnd),timeTupleEnd.tm_year)
1090  else:
1091  if timeTupleStart.tm_mday != timeTupleEnd.tm_mday:
1092  timeLabel = '{0}-{1} {2}'.format(time.strftime('%b. %e',timeTupleStart),time.strftime('%e',timeTupleEnd),timeTupleEnd.tm_year)
1093  else:
1094  timeLabel = time.strftime('%b. %e %Y',timeTupleStart)
1095  return timeLabel
1096 
1097 #====================================================================================================================
1098 """
1099 This marks the beginning of the script
1100 """
1101 #====================================================================================================================
1102 
1103 
1104 if __name__=='__main__':
1105  try:
1106  mySignal = Process(target = waitForReturn, args=(sys.stdin.fileno(),))
1107  mySignal.start()
1108 
1109  logger = logging.getLogger(__name__)
1110  if args.VERBOSE: logger.setLevel(logging.INFO)
1111 
1112  if args.RUNNUMBER is not None:
1113  logger.info('Getting runLb range for run(s) {0}'.format(args.RUNNUMBER))
1114  runLbRanges = runNumberToRunLbRange(args.RUNNUMBER)
1115  args.FILLNUMBER = None
1116  args.TIMERANGE = None
1117  elif args.FILLNUMBER is not None:
1118  logger.info('Getting runLb range for fill(s) {0}'.format(args.FILLNUMBER))
1119  runLbRanges = fillNumberToRunLbRange(args.FILLNUMBER)
1120  args.RUNNUMBER = None
1121  args.TIMERANGE = None
1122  elif args.TIMERANGE is not None:
1123  logger.info('Getting runLb range for time range {0}'.format(args.TIMERANGE))
1124  runLbRanges = timeRangeToRunLbRange(args.TIMERANGE)
1125  args.RUNNUMBER = None
1126  args.FILLNUMBER = None
1127  else:
1128  logger.critical('No range given for which to gather data')
1129  sys.exit(0)
1130 
1131  if not (args.XUNIT in ['time','luminosity','noBX']):
1132  logger.critical('Cannot plot against x-axis unit {0}'.format(args.XUNIT))
1133  sys.exit(0)
1134 
1135  logger.info('Creating time converter')
1136  timeConverter = createTimeConverter(runLbRanges)
1137 
1138  coolQueryHandler = COOLQueryHandler(mySignal,numProc=args.PROCESSES,verbose=args.VERBOSE)
1139  rateQueryHandler = RateQueryHandler(mySignal,numProc=args.PROCESSES,verbose=args.VERBOSE)
1140 
1141  logger.info('Creating rate name lookups')
1142  nameToChannel,nameToFolder = rateNameInfo(runLbRanges,mySignal,numProc=args.PROCESSES)
1143 
1144  if not mySignal.is_alive(): sys.exit(0)
1145 
1146  """
1147  folderName | payloadName | timeBased | Special
1148  ====================================================================================>
1149  /TRIGGER/LUMI/LBLB | StartTime | False | None
1150  /TRIGGER/LUMI/LBLB | EndTime | False | None
1151  /TRIGGER/LUMI/LBLESTONL | LBAvInstLumi | False | 0
1152  /TDAQ/OLC/LHC/FILLPARAMS | LuminousBunches | True | None
1153  /TRIGGER/LUMI/LBLESTONL | LBAvEvtsPerBX | False | 0
1154  /TDAQ/RunCtrl/DataTakingMode | ReadyForPhysics | False | None
1155  /LHC/DCS/FILLSTATE | StableBeams | True | None
1156  /LHC/DCS/FILLSTATE | FillNumber | True | None
1157  ====================================================================================>
1158  """
1159 
1160  coolQueryHandler.result['stable'] = {}
1161  coolQueryHandler.result['ready'] = {}
1162  coolQueryHandler.result['noBX'] = {}
1163  coolQueryHandler.result['luminosity'] = {}
1164  coolQueryHandler.result['time'] = {}
1165  coolQueryHandler.result['luminousBunches'] = {}
1166 
1167  if args.FILTER:
1168  for runLbStart,runLbEnd in runLbRanges:
1169  coolQueryHandler.addQueryBundle(QueryBundle(timeConverter[(runLbStart,runLbEnd)][runLbStart],timeConverter[(runLbStart,runLbEnd)][runLbEnd],[('StableBeams','stable',str)],'/LHC/DCS/FILLSTATE',timeBased=True,payloadRequirements={'StableBeams':'{0}==\'TRUE\''},timeConverter=timeConverter[(runLbStart,runLbEnd)]))
1170  coolQueryHandler.addQueryBundle(QueryBundle(runLbStart,runLbEnd,[('ReadyForPhysics','ready',int)],'/TDAQ/RunCtrl/DataTakingMode'))
1171  for rateName,alias,level in [('L1_RD0_FILLED','deadTime1','Output'),('L1_RD0_FILLED','deadTime2','AfterPrescale')]:
1172  for rateQueryBundle in generateRateQueryBundles(rateName,level,runLbRanges,nameToChannel,nameToFolder,alias=alias):
1173  rateQueryHandler.addQueryBundle(rateQueryBundle)
1174  if args.XUNIT == 'noBX':
1175  for runLbStart,runLbEnd in runLbRanges:
1176  coolQueryHandler.addQueryBundle(QueryBundle(runLbStart,runLbEnd,[('LBAvInstLumi','luminosity',float),('LBAvEvtsPerBX','noBX',float)],'/TRIGGER/LUMI/LBLESTONL',channelSelection = cool.ChannelSelection(0)))
1177  else:
1178  for runLbStart,runLbEnd in runLbRanges:
1179  coolQueryHandler.addQueryBundle(QueryBundle(runLbStart,runLbEnd,[('LBAvInstLumi','luminosity',float)],'/TRIGGER/LUMI/LBLESTONL',channelSelection = cool.ChannelSelection(0)))
1180  for runLbStart,runLbEnd in runLbRanges:
1181  coolQueryHandler.addQueryBundle(QueryBundle(runLbStart,runLbEnd,[('StartTime','time',int),('EndTime','timeEnd',int)],'/TRIGGER/LUMI/LBLB'))
1182  coolQueryHandler.addQueryBundle(QueryBundle(timeConverter[(runLbStart,runLbEnd)][runLbStart],timeConverter[(runLbStart,runLbEnd)][runLbEnd],[('LuminousBunches','luminousBunches',int)],'/TDAQ/OLC/LHC/FILLPARAMS',timeBased=True,timeConverter=timeConverter[(runLbStart,runLbEnd)]))
1183 
1184  logger.info('Retrieving general data')
1185 
1186  coolQueryHandler.beginQuery()
1187 
1188  rateQueryHandler.result['deadTime1']={}
1189  rateQueryHandler.result['deadTime2']={}
1190 
1191  for group in parseRatesString(args.RATES):
1192  for rateName,alias,level in group:
1193  rateQueryHandler.result[alias]={}
1194  for rateQueryBundle in generateRateQueryBundles(rateName,level,runLbRanges,nameToChannel,nameToFolder,alias=alias):
1195  rateQueryHandler.addQueryBundle(rateQueryBundle)
1196 
1197  if not mySignal.is_alive(): sys.exit(0)
1198 
1199  logger.info('Retrieving rate data')
1200  rateQueryHandler.beginQuery()
1201 
1202  Data = {}
1203  Data.update(coolQueryHandler.result)
1204  Data['rates']={}
1205  Data['rates'].update(rateQueryHandler.result)
1206 
1207  Data['xUnit']=args.XUNIT
1208 
1209  Data['groups']=parseRatesString(args.RATES)
1210 
1211  if not mySignal.is_alive(): sys.exit(0)
1212 
1213  if args.FILTER:
1214  Data['lowDeadTime']={}
1215  for runLb in commonKeys([Data['rates']['deadTime1'],Data['rates']['deadTime2']]):
1216  rateOutput = Data['rates']['deadTime1'].get(runLb)
1217  rateAfterPrescale = Data['rates']['deadTime2'].get(runLb)
1218  if rateAfterPrescale == 0.:
1219  continue
1220  deadTime = 1.0-rateOutput/rateAfterPrescale
1221  if deadTime < 0.05:
1222  Data['lowDeadTime'][runLb] = 1
1223  Data['filter']={}
1224  logger.info('Creating filter')
1225  if args.LUMINOUSBUNCHES is not None:
1226  Data['filter'].update(dict((key,1) for key in commonKeys([Data['lowDeadTime'],Data['ready'],Data['stable'],Data['luminousBunches']]) if Data['ready'].get(key) == 1 and Data['stable'].get(key) == 'TRUE' and Data['luminousBunches'].get(key) == args.LUMINOUSBUNCHES))
1227  else:
1228  Data['filter'].update(dict((key,1) for key in commonKeys([Data['lowDeadTime'],Data['ready'],Data['stable']]) if Data['ready'].get(key) == 1 and Data['stable'].get(key) == 'TRUE'))
1229 
1230  setAtlasStyle()
1231  gROOT.SetBatch(args.BATCH)
1232  logger.info('Configuring plots')
1233  if not mySignal.is_alive(): sys.exit(0)
1234  Data.update(configurePlotting(Data))
1235  logger.info('Filling profiles')
1236  if not mySignal.is_alive(): sys.exit(0)
1237  Data.update(fillRateProfiles(Data))
1238  logger.info('Plotting rates')
1239  if not mySignal.is_alive(): sys.exit(0)
1240 
1241  drawOption = 'H'
1242  if args.ENVELOPE: drawOption = 'E3'
1243  if args.POINTS: drawOption = 'P'
1244 
1245  Data.update(plotRateProfiles(Data,label=args.LABEL,runNumber=args.RUNNUMBER,fillNumber=args.FILLNUMBER,luminousBunches=args.LUMINOUSBUNCHES,log=args.LINEAR,drawOption=drawOption))
1246  if mySignal.is_alive():
1247  mySignal.terminate()
1248  mySignal.join()
1249  if not args.BATCH:
1250  logger.info('Drawing canvases')
1251  for canvasName,canvas in Data['canvases'].items(): canvas.Draw()
1252  import code
1253  code.interact(local=globals())
1254  else:
1255  for canvasName,canvas in Data['canvases'].items(): canvas.Print('{0}.eps'.format(canvasName))
1256  except KeyboardInterrupt:
1257  logger.critical('Caught signal, exiting')
1258  if mySignal.is_alive():
1259  mySignal.terminate()
1260  mySignal.join()
COOLRates.int
int
Definition: COOLRates.py:31
COOLRates.COOLQueryWorker.db
db
Definition: COOLRates.py:75
COOLRates.COOLQueryHandler.timeConverter
timeConverter
Definition: COOLRates.py:163
COOLRates.QueryBundle.__init__
def __init__(self, IoVStart, IoVEnd, payloadRequests, folderName, channelSelection=None, timeBased=False, payloadRequirements={}, timeConverter={})
Definition: COOLRates.py:261
COOLRates.timeRangeToRunLbRange
def timeRangeToRunLbRange(timeRange)
Definition: COOLRates.py:553
vtune_athena.format
format
Definition: vtune_athena.py:14
COOLRates.RateQueryBundle.folderName
folderName
Definition: COOLRates.py:463
COOLRates.COOLQueryHandler.result
result
Definition: COOLRates.py:160
COOLRates.RateQueryHandler.createProcesses
def createProcesses(self)
Definition: COOLRates.py:499
COOLRates.COOLQueryHandler.QueryProcesses
QueryProcesses
Definition: COOLRates.py:159
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
COOLRates.waitForReturn
waitForReturn
Definition: COOLRates.py:1106
COOLRates.COOLQueryHandler.processResults
def processResults(self, resultBundle)
Definition: COOLRates.py:193
COOLRates.RateQueryWorker.__init__
def __init__(self)
Definition: COOLRates.py:424
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
COOLRates.plotRateProfiles
def plotRateProfiles(data, label=False, runNumber=None, fillNumber=None, log=True, minY=None, maxY=None, luminousBunches=None, drawOption='H')
Definition: COOLRates.py:904
COOLRates.RateQueryBundle.payloadName
payloadName
Definition: COOLRates.py:464
COOLRates.RateQueryHandler.__init__
def __init__(self, mySignal, numProc=None, verbose=False)
Definition: COOLRates.py:492
COOLRates.RateQueryBundle.channelSelection
channelSelection
Definition: COOLRates.py:467
COOLRates.QueryBundle.payloadRequirements
payloadRequirements
Definition: COOLRates.py:269
COOLRates.RateQueryBundle
Definition: COOLRates.py:458
COOLRates.RateQueryHandler.QueryWorkers
QueryWorkers
Definition: COOLRates.py:494
COOLRates.configureLuminosity
def configureLuminosity(data)
Definition: COOLRates.py:804
COOLRates.generateAtlasLabel
def generateAtlasLabel(canvas, timeLabel, luminousBunches, runNumber=None, fillNumber=None)
Definition: COOLRates.py:1035
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
COOLRates.configurePlotting
def configurePlotting(data)
Definition: COOLRates.py:758
while
while((inf=(TStreamerInfo *) nextinfo()) !=0)
Definition: liststreamerinfos.cxx:13
COOLRates.COOLQueryHandler.terminateProcesses
def terminateProcesses(self)
Definition: COOLRates.py:198
COOLRates.COOLQueryWorker.processQuery
def processQuery(self, queryBundle)
Definition: COOLRates.py:102
COOLRates.COOLQueryHandler.numProc
numProc
Definition: COOLRates.py:166
COOLRates.RateQueryBundle.IoVEnd
IoVEnd
Definition: COOLRates.py:461
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:805
COOLRates.COOLQueryHandler.verbose
verbose
Definition: COOLRates.py:162
COOLRates.RateQueryBundle.turnCountFolderName
turnCountFolderName
Definition: COOLRates.py:465
COOLRates.RateQueryBundle.alias
alias
Definition: COOLRates.py:462
COOLRates.QueryBundle.IoVStart
IoVStart
Definition: COOLRates.py:262
COOLRates.QueryBundle.IoVEnd
IoVEnd
Definition: COOLRates.py:263
COOLRates.QueryBundle.folderName
folderName
Definition: COOLRates.py:270
COOLRates.fetchTimeLabel
def fetchTimeLabel(timeStart, timeEnd)
Definition: COOLRates.py:1081
COOLRates.fillRateProfiles
def fillRateProfiles(data)
Definition: COOLRates.py:706
COOLRates.configureProfile
def configureProfile(profile, i, minY, maxY, drawOption, data, log, textSize=25)
Definition: COOLRates.py:984
python.TrigEgammaMonitorHelper.TProfile
def TProfile(*args, **kwargs)
Definition: TrigEgammaMonitorHelper.py:81
COOLRates.COOLQueryWorker.folder
folder
Definition: COOLRates.py:76
COOLRates.RateQueryBundle.__init__
def __init__(self, IoVStart, IoVEnd, alias, folderName, payloadName, turnCountFolderName, turnCountPayloadName, channel)
Definition: COOLRates.py:459
COOLRates.COOLQueryWorker.__call__
def __call__(self, queueIn, queueOut)
Definition: COOLRates.py:133
COOLRates.RateQueryWorker.processQuery
def processQuery(self, rateBundle)
Definition: COOLRates.py:427
COOLRates.QueryBundle
Definition: COOLRates.py:260
COOLRates.COOLQueryHandler
Definition: COOLRates.py:155
COOLRates.COOLQueryHandler.resultQueue
resultQueue
Definition: COOLRates.py:158
COOLRates.COOLQueryWorker.getdb
def getdb(self, dbName)
Definition: COOLRates.py:78
COOLRates.configureTime
def configureTime(data)
Definition: COOLRates.py:770
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
PyAthena::repr
std::string repr(PyObject *o)
returns the string representation of a python object equivalent of calling repr(o) in python
Definition: PyAthenaUtils.cxx:106
COOLRates.QueryBundle.payloadRequests
payloadRequests
Definition: COOLRates.py:268
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
ReadCoolUPD4.openDatabase
def openDatabase(dbstring)
Definition: ReadCoolUPD4.py:21
COOLRates.createTimeConverter
def createTimeConverter(runLbRanges)
Definition: COOLRates.py:241
Queue
struct _Queue Queue
A double-ended queue.
Definition: queue.h:52
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
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
COOLRates.RateQueryBundle.IoVStart
IoVStart
Definition: COOLRates.py:460
COOLRates.generateRateQueryBundles
def generateRateQueryBundles(name, level, runLbRanges, nameToChannel, nameToFolder, alias=None)
Definition: COOLRates.py:471
COOLRates.COOLQueryHandler.mySignal
mySignal
Definition: COOLRates.py:164
COOLRates.rateNameInfo
def rateNameInfo(runLbRanges, mySignal, numProc=1)
Definition: COOLRates.py:308
COOLRates.QueryBundle.channelSelection
channelSelection
Definition: COOLRates.py:273
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
COOLRates.COOLQueryWorker.getFolder
def getFolder(self, folderName)
Definition: COOLRates.py:83
COOLRates.nanoTimeRangesToRunLbRanges
def nanoTimeRangesToRunLbRanges(nanoTimeRanges)
Definition: COOLRates.py:573
COOLRates.COOLQueryHandler.collectResults
def collectResults(self)
Definition: COOLRates.py:211
COOLRates.COOLQueryWorker.convertTime
def convertTime(self, timeStart, timeEnd, timeConverter)
Definition: COOLRates.py:98
COOLRates.fillNumberToRunLbRange
def fillNumberToRunLbRange(fillNumbers)
Definition: COOLRates.py:600
COOLRates.getNiceCanvas
def getNiceCanvas(name, aliases, textSize=25)
Definition: COOLRates.py:865
COOLRates.setAtlasStyle
def setAtlasStyle()
Definition: COOLRates.py:637
COOLRates.COOLQueryHandler.counter
counter
Definition: COOLRates.py:161
COOLRates.COOLQueryWorker.close
def close(self)
Definition: COOLRates.py:130
COOLRates.COOLQueryHandler.addQueryBundle
def addQueryBundle(self, queryBundle)
Definition: COOLRates.py:174
COOLRates.COOLQueryWorker.db_svc
db_svc
Definition: COOLRates.py:73
COOLRates.runNumberToRunLbRange
def runNumberToRunLbRange(runNumbers)
Definition: COOLRates.py:531
COOLRates.COOLQueryHandler.__init__
def __init__(self, mySignal, numProc=None, timeConverter={}, verbose=False)
Definition: COOLRates.py:156
COOLRates.COOLQueryHandler.beginQuery
def beginQuery(self)
Definition: COOLRates.py:178
COOLRates.configureNoBX
def configureNoBX(data)
Definition: COOLRates.py:838
COOLRates.parseRatesString
def parseRatesString(ratesString)
Definition: COOLRates.py:506
COOLRates.getLumiEndPoints
def getLumiEndPoints(data)
Definition: COOLRates.py:1015
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
COOLRates.configureCanvasLegend
def configureCanvasLegend(canvas, aliases, textSize=25)
Definition: COOLRates.py:888
COOLRates.COOLQueryWorker
Definition: COOLRates.py:71
COOLRates.COOLQueryHandler.troughQueue
troughQueue
Definition: COOLRates.py:157
COOLRates.fillProfile
def fillProfile(profileName, numBins, xMin, xMax, xValues, yValues)
Definition: COOLRates.py:698
str
Definition: BTagTrackIpAccessor.cxx:11
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:798
COOLRates.COOLQueryHandler.createProcesses
def createProcesses(self)
Definition: COOLRates.py:168
COOLRates.RateQueryWorker
Definition: COOLRates.py:423
COOLRates.COOLQueryWorker.timeConverter
timeConverter
Definition: COOLRates.py:74
COOLRates.COOLQueryWorker.getdbName
def getdbName(self, folderName)
Definition: COOLRates.py:90
COOLRates.QueryBundle.timeConverter
timeConverter
Definition: COOLRates.py:272
COOLRates.RateQueryHandler
Definition: COOLRates.py:491
WriteBchToCool.update
update
Definition: WriteBchToCool.py:67
readCCLHist.float
float
Definition: readCCLHist.py:83
COOLRates.RateQueryBundle.turnCountPayloadName
turnCountPayloadName
Definition: COOLRates.py:466
COOLRates.COOLQueryWorker.__init__
def __init__(self, timeConverter={})
Definition: COOLRates.py:72
COOLRates.QueryBundle.timeBased
timeBased
Definition: COOLRates.py:271
COOLRates.commonKeys
def commonKeys(dictionaries)
Definition: COOLRates.py:61