ATLAS Offline Software
Loading...
Searching...
No Matches
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
13from PyCool import cool
14from multiprocessing import Queue, cpu_count, Process
15from time import sleep
16import argparse,sys,logging,time,os
17from math import log10
18import signal
19from Queue import Empty
20
21logger = logging.getLogger(__name__)
22ch = logging.StreamHandler()
23formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
24ch.setFormatter(formatter)
25logger.addHandler(ch)
26
27if __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
46from ROOT import TDatime, TProfile, TCanvas, TLegend, TGaxis, gROOT, SetOwnership, TColor, TLatex
47
48#====================================================================================================================
49
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
61def 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):
157 self.troughQueue = Queue()
158 self.resultQueue = Queue()
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
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
241def 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
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
286folderLocations = {}
287
288folderLocations[0] = {}
289folderLocations[0]['Input'] = ('/TRIGGER/LUMI/LVL1COUNTERS','BeforePrescale','/TRIGGER/LVL1/CTPCORELBDATA','BeforePrescaleTurnCounter')
290folderLocations[0]['AfterPrescale'] = ('/TRIGGER/LUMI/LVL1COUNTERS','AfterPrescale','/TRIGGER/LVL1/CTPCORELBDATA','AfterPrescaleTurnCounter')
291folderLocations[0]['Output'] = ('/TRIGGER/LUMI/LVL1COUNTERS','L1Accept','/TRIGGER/LVL1/CTPCORELBDATA','L1AcceptTurnCounter')
292
293folderLocations[1] = {}
294folderLocations[1]['Input'] = ('/TRIGGER/HLT/L2Rates','Prescale',None,None)
295folderLocations[1]['AfterPrescale'] = ('/TRIGGER/HLT/L2Rates','Input',None,None)
296folderLocations[1]['Output'] = ('/TRIGGER/HLT/L2Rates','Output',None,None)
297
298folderLocations[2] = {}
299folderLocations[2]['Input'] = ('/TRIGGER/HLT/EFRates','Prescale',None,None)
300folderLocations[2]['AfterPrescale'] = ('/TRIGGER/HLT/EFRates','Input',None,None)
301folderLocations[2]['Output'] = ('/TRIGGER/HLT/EFRates','Output',None,None)
302
303folderLocations[3] = {}
304folderLocations[3]['Input'] = ('/TRIGGER/HLT/TotalRates','Input',None,None)
305folderLocations[3]['AfterPrescale'] = ('/TRIGGER/HLT/TotalRates','Input',None,None)
306folderLocations[3]['Output'] = ('/TRIGGER/HLT/TotalRates','Output',None,None)
307
308def 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
471def 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
501 for i in range(self.numProc):
502 process = Process(target = RateQueryWorker(), args = (self.troughQueue,self.resultQueue,))
503 self.QueryProcesses.append(process)
504#====================================================================================================================
505
506def 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
531def 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
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
573def 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
600def 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"""
633This 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
694MarkerColors = [TColor.GetColor(hexColor) for hexColor in ['#000000','#2956B2','#7DBD00','#FF542E','#AA0078','#FFCC00','#D01A55','#A6AF7A','#DCF600','#FF5B00','#659CEF','#F2BC00','#FFF0BA']]
695MarkerStyles = [20,21,22, 29,31, 33, 34, 23,24,25,26,27,28, 30]
696MarkerSizes = [1.,1.,1.4,1.8,1.,1.8,1.4,1.4,1.,1.,1.,1.,1.,1.8]
697
698def 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
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
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
865def 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
888def 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
904def 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
984def 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
1035def 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
1081def 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"""
1099This marks the beginning of the script
1100"""
1101#====================================================================================================================
1102
1103
1104if __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
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()
void print(char *figname, TCanvas *c1)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
processResults(self, resultBundle)
Definition COOLRates.py:193
__init__(self, mySignal, numProc=None, timeConverter={}, verbose=False)
Definition COOLRates.py:156
addQueryBundle(self, queryBundle)
Definition COOLRates.py:174
getFolder(self, folderName)
Definition COOLRates.py:83
convertTime(self, timeStart, timeEnd, timeConverter)
Definition COOLRates.py:98
getdbName(self, folderName)
Definition COOLRates.py:90
processQuery(self, queryBundle)
Definition COOLRates.py:102
__init__(self, timeConverter={})
Definition COOLRates.py:72
__call__(self, queueIn, queueOut)
Definition COOLRates.py:133
__init__(self, IoVStart, IoVEnd, payloadRequests, folderName, channelSelection=None, timeBased=False, payloadRequirements={}, timeConverter={})
Definition COOLRates.py:261
__init__(self, IoVStart, IoVEnd, alias, folderName, payloadName, turnCountFolderName, turnCountPayloadName, channel)
Definition COOLRates.py:459
__init__(self, mySignal, numProc=None, verbose=False)
Definition COOLRates.py:492
processQuery(self, rateBundle)
Definition COOLRates.py:427
STL class.
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
while((inf=(TStreamerInfo *) nextinfo()) !=0)
configureProfile(profile, i, minY, maxY, drawOption, data, log, textSize=25)
Definition COOLRates.py:984
generateAtlasLabel(canvas, timeLabel, luminousBunches, runNumber=None, fillNumber=None)
waitForReturn(fd)
Definition COOLRates.py:50
runNumberToRunLbRange(runNumbers)
Definition COOLRates.py:531
fillProfile(profileName, numBins, xMin, xMax, xValues, yValues)
Definition COOLRates.py:698
setAtlasStyle()
Definition COOLRates.py:637
parseRatesString(ratesString)
Definition COOLRates.py:506
configureTime(data)
Definition COOLRates.py:770
createTimeConverter(runLbRanges)
Definition COOLRates.py:241
fetchTimeLabel(timeStart, timeEnd)
fillRateProfiles(data)
Definition COOLRates.py:706
getLumiEndPoints(data)
configureNoBX(data)
Definition COOLRates.py:838
rateNameInfo(runLbRanges, mySignal, numProc=1)
Definition COOLRates.py:308
plotRateProfiles(data, label=False, runNumber=None, fillNumber=None, log=True, minY=None, maxY=None, luminousBunches=None, drawOption='H')
Definition COOLRates.py:904
generateRateQueryBundles(name, level, runLbRanges, nameToChannel, nameToFolder, alias=None)
Definition COOLRates.py:471
configureLuminosity(data)
Definition COOLRates.py:804
timeRangeToRunLbRange(timeRange)
Definition COOLRates.py:553
commonKeys(dictionaries)
Definition COOLRates.py:61
configurePlotting(data)
Definition COOLRates.py:758
getNiceCanvas(name, aliases, textSize=25)
Definition COOLRates.py:865
fillNumberToRunLbRange(fillNumbers)
Definition COOLRates.py:600
nanoTimeRangesToRunLbRanges(nanoTimeRanges)
Definition COOLRates.py:573
configureCanvasLegend(canvas, aliases, textSize=25)
Definition COOLRates.py:888