7 __author__ =
"Peter Radloff"
8 __version__ =
"$Revision: 1.0$"
9 __doc__ =
"Fast Rate plotter from COOL database"
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
19 from Queue
import Empty
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)
27 if __name__==
'__main__':
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()
46 from ROOT
import TDatime, TProfile, TCanvas, TLegend, TGaxis, gROOT, SetOwnership, TColor, TLatex
51 logger.critical(
'Press Return to safely exit')
52 signal.signal(signal.SIGINT, signal.SIG_IGN)
56 logger.critical(
'Received signal, exiting at first chance')
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
73 self.
db_svc = cool.DatabaseSvcFactory.databaseService()
79 if dbName
not in self.
db:
81 return self.
db.
get(dbName)
84 if folderName
not in self.
folder:
86 db = self.
getdb(dbName)
87 self.
folder[folderName] = db.getFolder(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])
99 validRunLbs = [runLb
for runLb,time
in timeConverter.items()
if timeStart<=time<=timeEnd]
103 folder = self.
getFolder(queryBundle.folderName)
104 folder.setPrefetchAll(
False)
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))
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))
127 folderIterator.close()
131 for db
in self.
db.
values(): db.closeDatabase()
134 signal.signal(signal.SIGINT, signal.SIG_IGN)
138 queryBundle = queueIn.get(
False,.001)
142 if queryBundle
is True:
145 queueOut.put(resultBundle)
146 except Exception
as exception:
147 logger.critical(exception)
156 def __init__(self,mySignal,numProc=None,timeConverter={},verbose=False):
165 if numProc
is None: numProc = cpu_count()
186 except KeyboardInterrupt:
187 logger.critical(
'Caught signal, terminating processes')
194 for resultAlias
in resultBundle:
195 if resultAlias
not in self.
result: self.
result[resultAlias]={}
196 self.
result[resultAlias].
update(resultBundle[resultAlias])
202 logger.critical(
'Queue is empty')
208 logger.critical(
'Processes are joined')
209 raise KeyboardInterrupt
217 raise KeyboardInterrupt
224 if resultBundle
is True:
226 if finished == self.
numProc:
break
230 if percentComplete>=target:
232 logger.info(
'{0}% complete'.
format(percentComplete))
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()
261 def __init__(self,IoVStart,IoVEnd,payloadRequests,folderName,channelSelection=None,timeBased=False,payloadRequirements={},timeConverter={}):
264 for request
in payloadRequests:
265 if not len(request)==3:
266 print(payloadRequests)
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')
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)
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)
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)
309 def rateNameWorker(queueIn,queueOut):
312 try: run = queueIn.get(
False,0.001)
319 runLbEnd=runLbStart+1
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()
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()
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}))
354 def terminateProcesses(QueryProcesses,troughQueue):
356 try:troughQueue.get(
False)
358 logger.critical(
'Queue is empty')
359 for i
in range(numProc): troughQueue.put(
True)
361 for process
in QueryProcesses:
364 logger.critical(
'Processes are joined')
365 raise KeyboardInterrupt
370 troughQueue =
Queue()
371 resultQueue =
Queue()
373 processes = [Process(target=rateNameWorker,args=(troughQueue,resultQueue,))
for i
in range(numProc)]
374 for process
in processes: process.start()
380 runs =
list(
set([runLbStart>>32
for runLbStart,runLbEnd
in runLbRanges]))
386 startingQueries = counter
388 logger.info(
'{0} queries distributed over {1} workers'.
format(startingQueries,numProc))
390 for i
in range(numProc): troughQueue.put(
True)
394 if not mySignal.is_alive():
395 raise KeyboardInterrupt
397 try: result = resultQueue.get(
False,0.001)
403 if finished==numProc:
break
405 tempNTC,tempNTF = result
406 nameToChannel.update(tempNTC)
407 nameToFolder.update(tempNTF)
409 percentComplete =
min(100,
int(
round(
float(startingQueries-counter)/startingQueries*100+.5)))
410 if percentComplete>=target:
412 logger.info(
'{0}% complete'.
format(percentComplete))
413 except KeyboardInterrupt:
414 logger.critical(
'Caught signal, terminating processes')
415 terminateProcesses(processes,troughQueue)
417 for process
in processes: process.join()
419 return nameToChannel,nameToFolder
425 COOLQueryWorker.__init__(self)
429 result[rateBundle.alias] = {}
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()
442 if rateBundle.turnCountFolderName
is not None:
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])))
453 result[rateBundle.alias].
update(firstResult)
459 def __init__(self,IoVStart,IoVEnd,alias,folderName,payloadName,turnCountFolderName,turnCountPayloadName,channel):
473 if alias
is None: alias = name
474 for runLbStart,runLbEnd
in runLbRanges:
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)
492 def __init__(self,mySignal,numProc=None,verbose=False):
493 COOLQueryHandler.__init__(self,mySignal,numProc=numProc,verbose=verbose)
508 groups = ratesString.split(
'|')
510 if group ==
'':
continue
512 for rate
in group.split(
','):
513 if rate ==
'':
continue
515 rateName,alias = tuple(rate.split(
':'))
517 rateName,alias = (rate,rate)
518 if rateName.endswith(
'-0'):
520 rateName = rateName[:-2]
521 elif rateName.endswith(
'-1'):
522 level =
'AfterPrescale'
523 rateName = rateName[:-2]
526 groups_[-1].
append((rateName,alias,level))
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()
543 while folderIterator.goToNext():
544 currentSlice = folderIterator.currentRef()
545 runLbs.append(currentSlice.since())
546 folderIterator.close()
547 runLbRanges.append((
min(runLbs),
max(runLbs)))
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))
558 timeStart,timeEnd = tuple(timeRange.split(
';'))
560 timeStart = time.strptime(timeStart,
'%Y-%m-%d:%H:%M:%S')
561 timeEnd = time.strptime(timeEnd,
'%Y-%m-%d:%H:%M:%S')
563 logger.critical(
'Time range "{0}" does not match YYYY-MM-DD:HH:mm:ss;YYYY-MM-DD:HH:mm:ss'.
format(timeRange))
566 timeStart =
int(time.mktime(timeStart))*10**9
567 timeEnd =
int(time.mktime(timeEnd))*10**9
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()
585 while folderIterator.goToNext():
586 currentSlice = folderIterator.currentRef()
587 run =
int(currentSlice.payloadValue(
'Run'))
588 lb =
int(currentSlice.payloadValue(
'LumiBlock'))
590 if run
not in temp: temp[run]=[]
592 for run,runLbs
in temp.items():
593 runLbRanges.append((
min(runLbs),
max(runLbs)))
594 folderIterator.close()
601 minFill =
min(fillNumbers)-1
604 folder = worker.getFolder(
'/LHC/DCS/FILLSTATE')
605 folder.setPrefetchAll(
False)
606 timeEnd =
int(time.mktime(time.localtime()))*10**9
607 channelSelection = cool.ChannelSelection()
609 timeStart = timeEnd-259200000000000
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()
622 if not len(result):
continue
623 if min(result.keys())<=minFill:
break
625 for fillNumber
in list(
set(fillNumbers)&
set(result.keys())):
626 nanoTimes = result[fillNumber]
627 nanoTimeRanges.append((
min(nanoTimes),
max(nanoTimes)))
633 This marks the beginning of plotting related tools
638 from ROOT
import TStyle
640 atlasStyle = TStyle(
"ATLAS",
"Atlas style")
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)
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)
683 gROOT.SetStyle(
"ATLAS")
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]
699 profile =
TProfile(profileName,profileName,
int(numBins),xMin,xMax)
700 for x,y
in zip(xValues,yValues):
708 if 'profiles' not in data: data[
'profiles'] = {}
709 for group
in data[
'groups']:
712 xOffset = data[
'plotConfig'][
'xOffset']
713 xScale = data[
'plotConfig'][
'xScale']
714 for rateName,alias,level
in rates:
715 if data[
'xUnit'] ==
'noBX':
717 runLbs =
commonKeys([data[data[
'xUnit']],data[
'filter'],data[
'rates'][alias],data[
'luminosity']])
719 runLbs =
commonKeys([data[data[
'xUnit']],data[
'rates'][alias],data[
'luminosity']])
722 runLbs =
commonKeys([data[data[
'xUnit']],data[
'filter'],data[
'rates'][alias]])
724 runLbs =
commonKeys([data[data[
'xUnit']],data[
'rates'][alias]])
727 if data[
'xUnit'] ==
'noBX':
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)
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)
759 xUnit = data[
'xUnit']
762 elif xUnit ==
'luminosity':
764 elif xUnit ==
'noBX':
772 validPoints = len(data[
'time'])
774 xOffset =
min(data[
'time'].
values())/xScale
776 xMax =
max(data[
'time'].
values())/xScale-xOffset
781 elif maxBins/2 <= 160:
783 elif maxBins/3 <= 160:
787 if xMax > 48*60*60: xFormat =
"%d/%m"
788 elif xMax > 12*60*60: xFormat =
"%d-%Hh"
789 else: xFormat =
"%H:%M"
796 xLabel = time.strftime(
"%Z Time")
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]'}
806 validPoints = len(
commonKeys([data[
'luminosity'],data[
'filter']]))
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']])])
814 validPoints = len(data[
'luminosity'])
822 xScale=
round(log10(xMax)-.5)
823 xLabel =
'Inst. Luminosity [10^{'+
str(
int(30+xScale))+
'} cm^{-2} s^{-1}]'
824 xScale =
float(10**xScale)
827 xLabel =
'Inst. Luminosity [10^{'+
str(
int(xScale+30))+
'} cm^{-2} s^{-1}]'
831 numBins =
int(
min(validPoints/3.,100))
833 data[
'plotConfig'] = {
'xMin':xMin,
'xMax':xMax,
'xLabel':xLabel,
'xScale':xScale,
'xOffset':xOffset,
'xFormat':xFormat,
'numBins':numBins,
'validPoints':validPoints,
'yLabel':
'Rate [Hz]'}
840 validPoints = len(
commonKeys([data[
'noBX'],data[
'filter']]))
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']])])
848 validPoints = len(data[
'noBX'])
856 xLabel =
'Average Interactions per Bunch Crossing'
858 numBins =
int(
min(validPoints/3.,100))
860 data[
'plotConfig'] = {
'xMin':xMin,
'xMax':xMax,
'xLabel':xLabel,
'xScale':xScale,
'xOffset':xOffset,
'xFormat':xFormat,
'numBins':numBins,
'validPoints':validPoints,
'yLabel':
'Cross-section [outhouse]'}
866 canvas = TCanvas(name, name, 4, 45, 700, 500)
869 canvas.SetFillColor(0)
870 canvas.SetBorderMode(0)
871 canvas.SetBorderSize(0)
872 canvas.SetFrameFillColor(0)
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())
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)
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)
904 def plotRateProfiles(data,label=False,runNumber=None,fillNumber=None,log=True,minY=None,maxY=None,luminousBunches=None,drawOption='H'):
906 TGaxis.SetMaxDigits(3)
910 for groupNum,group
in enumerate(data[
'groups']):
912 if minY
is None: minY = 0.
913 if log: minY =
max([10**-9,minY])
914 if maxY
is None: maxY = 10.**10
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
926 currentMin =
min(currentMin,thisMin)
927 currentMax =
max(currentMax,thisMax)
931 if currentMin>=currentMax:
932 logger.warning(
'No data in group, {0} is empty'.
format(canvas.GetName()))
933 data[
'canvases'].
update({canvas.GetName():canvas})
938 thisMinY = currentMin/scale
939 thisMaxY = currentMax*scale
941 subPad1 = canvas.GetPad(1)
942 if log: subPad1.SetLogy()
947 if 'P' in drawOption: legendOption =
'p'
950 for i,(rateName,alias,level)
in enumerate(group):
952 profile = data[
'profiles'][alias]
955 if not i: profile.Draw(drawOption)
956 else: profile.Draw(
'{0} SAME'.
format(drawOption))
958 if not i: profile.Draw()
959 else: profile.Draw(
'SAME')
961 yAxis = profile.GetYaxis()
962 if int(log10(minY)) ==
int(log10(maxY)): yAxis.SetMoreLogLabels(
True)
963 else: yAxis.SetMoreLogLabels(
False)
965 legend.AddEntry(profile,alias,legendOption)
973 timeStart =
min(data[
'time'].
values())/scale
974 timeEnd =
max(data[
'time'].
values())/scale
977 canvas =
generateAtlasLabel(canvas,timeLabel,luminousBunches,runNumber=runNumber,fillNumber=fillNumber)
978 data[
'canvases'].
update({canvas.GetName():canvas})
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)
992 profile.SetFillColor(MarkerColors[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'])
1006 dh.Set(
int(data[
'plotConfig'][
'xOffset']),
False)
1007 profile.GetXaxis().SetTimeOffset(dh.Convert(
False))
1008 profile.GetXaxis().SetNdivisions(507)
1010 profile.GetXaxis().SetTimeDisplay(0)
1016 if 'filter' in data:
1017 validPoints = len(
commonKeys([data[
'luminosity'],data[
'filter']]))
1022 lumiStart = data[
'luminosity'][
min(
commonKeys([data[
'luminosity'],data[
'filter']]))]
1023 lumiEnd = data[
'luminosity'][
max(
commonKeys([data[
'luminosity'],data[
'filter']]))]
1029 lumiStart = data[
'luminosity'][
min(data[
'luminosity'].
keys())]
1030 lumiEnd = data[
'luminosity'][
max(data[
'luminosity'].
keys())]
1031 return (lumiStart,lumiEnd)
1043 AtlasLabel.append(TLatex())
1044 AtlasLabel[-1].SetNDC()
1045 AtlasLabel[-1].SetTextFont(42)
1047 if runNumber
is None: runNumber = []
1048 if fillNumber
is None: fillNumber = []
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))
1059 AtlasLabel[-1].DrawLatex(xOffset,yOffset,
'Running {0}'.
format(timeLabel))
1061 AtlasLabel.append(TLatex())
1062 AtlasLabel[-1].SetNDC()
1063 AtlasLabel[-1].SetTextFont(72)
1064 AtlasLabel[-1].DrawLatex(xOffset,yOffset+.07,
"ATLAS")
1066 AtlasLabel.append(TLatex())
1067 AtlasLabel[-1].SetNDC()
1068 AtlasLabel[-1].SetTextFont(42)
1069 AtlasLabel[-1].DrawLatex(xOffset+0.115,yOffset+.07,
'Trigger Operations')
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))
1082 timeTupleStart = time.localtime(timeStart)
1083 timeTupleEnd = time.localtime(timeEnd)
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))
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)
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)
1094 timeLabel = time.strftime(
'%b. %e %Y',timeTupleStart)
1099 This marks the beginning of the script
1104 if __name__==
'__main__':
1106 mySignal = Process(target = waitForReturn, args=(sys.stdin.fileno(),))
1109 logger = logging.getLogger(__name__)
1110 if args.VERBOSE: logger.setLevel(logging.INFO)
1112 if args.RUNNUMBER
is not None:
1113 logger.info(
'Getting runLb range for run(s) {0}'.
format(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))
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))
1125 args.RUNNUMBER =
None
1126 args.FILLNUMBER =
None
1128 logger.critical(
'No range given for which to gather data')
1131 if not (args.XUNIT
in [
'time',
'luminosity',
'noBX']):
1132 logger.critical(
'Cannot plot against x-axis unit {0}'.
format(args.XUNIT))
1135 logger.info(
'Creating time converter')
1141 logger.info(
'Creating rate name lookups')
1142 nameToChannel,nameToFolder =
rateNameInfo(runLbRanges,mySignal,numProc=args.PROCESSES)
1144 if not mySignal.is_alive(): sys.exit(0)
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 ====================================================================================>
1160 coolQueryHandler.result[
'stable'] = {}
1161 coolQueryHandler.result[
'ready'] = {}
1162 coolQueryHandler.result[
'noBX'] = {}
1163 coolQueryHandler.result[
'luminosity'] = {}
1164 coolQueryHandler.result[
'time'] = {}
1165 coolQueryHandler.result[
'luminousBunches'] = {}
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')]:
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)))
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)]))
1184 logger.info(
'Retrieving general data')
1186 coolQueryHandler.beginQuery()
1188 rateQueryHandler.result[
'deadTime1']={}
1189 rateQueryHandler.result[
'deadTime2']={}
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)
1197 if not mySignal.is_alive(): sys.exit(0)
1199 logger.info(
'Retrieving rate data')
1200 rateQueryHandler.beginQuery()
1203 Data.update(coolQueryHandler.result)
1205 Data[
'rates'].
update(rateQueryHandler.result)
1207 Data[
'xUnit']=args.XUNIT
1211 if not mySignal.is_alive(): sys.exit(0)
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.:
1220 deadTime = 1.0-rateOutput/rateAfterPrescale
1222 Data[
'lowDeadTime'][runLb] = 1
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))
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'))
1231 gROOT.SetBatch(args.BATCH)
1232 logger.info(
'Configuring plots')
1233 if not mySignal.is_alive(): sys.exit(0)
1235 logger.info(
'Filling profiles')
1236 if not mySignal.is_alive(): sys.exit(0)
1238 logger.info(
'Plotting rates')
1239 if not mySignal.is_alive(): sys.exit(0)
1242 if args.ENVELOPE: drawOption =
'E3'
1243 if args.POINTS: drawOption =
'P'
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()
1250 logger.info(
'Drawing canvases')
1251 for canvasName,canvas
in Data[
'canvases'].
items(): canvas.Draw()
1253 code.interact(local=globals())
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()