5 from __future__
import print_function
9 from PyCool
import cool
10 from CoolConvUtilities.AtlCoolLib
import RangeList,indirectOpen
11 from DetectorStatus.DetStatusCoolLib
import statusCutsToRange
14 """Utility function to turn COOL 63bit time into string, or unknown"""
15 if (value
is not None):
16 stime=
int(value/1000000000)
17 return time.strftime(
'%F:%T',time.gmtime(stime))
22 """Utility function to turn bool into yes/no"""
23 if (value
is not None):
32 "Utility function to turn None into 0 (int) for use with integer/None args"
39 "Utility to turn None into '---' (string) for use with string/None args"
46 """Decode the detector mask into a string list of detectors"""
48 masklist=[
'Pix B',
'Pix EA',
'Pix EC',
'Pix B-layer',
'SCT BA',
'SCT BC',
'SCT EA',
'SCT EC',
'TRT BA',
'TRT BC',
'TRT EA',
'TRT EC',
'LAr EMBA',
'LAr EMBC',
'LAr EMECA',
'LAr EMECC',
'LAr HECA',
'LAr HECC',
'LAR FCALA',
'LAR FCALC',
'Til BA',
'Til BC',
'Til EA',
'Til EC',
'MDT BA',
'MDT BC',
'MDT EA',
'MDT EC',
'RPC BA',
'RPC BC',
'TGC EA',
'TGC EC',
'CSC EA',
'CSC EC',
'L1calo pre',
'L1calo cluDAQ',
'L1calo cluRoI',
'L1calo JetEDAQ',
'L1calo JetERoI',
'MUCTPI',
'CTP',
'L2SV',
'SFI',
'SFO',
'LVL2',
'EF']
51 if (mask & (1 << i)): res+=masklist[i]+
", "
53 if len(res)>1: res=res[:-2]
58 """Class to hold information from the LB_Params folder"""
66 """class to hold information from the Params folders"""
67 def __init__(self,run,start,runtype,daqconfig,detmask,filetag,rec,datasource):
107 if (self.loglevel>1):
108 self.
addMsg(
"EOR updates DAQConfig")
124 "Patch end of run time from Trigger info when missing EOR record"
130 "Set errorcode for bit x"
132 if (msg!=
""): self.
errlist+=[msg]
138 "Decode the errors for the run into a string representation"
146 errtxt=[
'NoEOR',
'BadEOR',
'NoLBParams',
'BadLBParams',
148 errstr=
'Run %i errcode %i : ' % (self.
run,self.
errcode)
149 for i
in range(0,len(errtxt)):
150 if (self.
errcode & (1 << i)): errstr+=errtxt[i]+
' '
156 "Class to hold info on runs and LBs read from TRIGGER schema"
165 """Extract information on ATLAS runs from online COOL information"""
166 def __init__(self,cooltdaqdbconn,cooltrigdbconn,coolstatusdbconn,
167 oracle=False,loglevel=1):
171 if (loglevel>=1):
print (
"Connected to",cooltdaqdbconn,
"for RunControl data")
172 except Exception
as e:
175 if (len(cooltrigdbconn)>0):
178 if (loglevel>=1):
print (
"Connected to",cooltrigdbconn,
"for CTP data")
180 except Exception
as e:
185 if (len(coolstatusdbconn)>0):
188 if (loglevel>=1):
print (
"Connected to",coolstatusdbconn,
"for detector status data")
189 except Exception
as e:
197 self.
nowtime=time.time()*1000000000
210 "Close the database connections"
211 self.
cooldb.closeDatabase()
216 def setSelection(self,onlyRec=False,mask=0,runType="",filenameTag="",detStatus="",detStatusTag="HEAD"):
224 def listFromTime(self,time1=cool.ValidityKeyMin,time2=cool.ValidityKeyMax):
225 "Main entry point - setup and check data given a range of times"
233 if (self.
loglevel>1):
print (
"listFromTime: Process run",run)
237 if (value.stop>self.
maxtime and value.stop<cool.ValidityKeyMax): self.
maxtime=value.stop
248 "Main entry point - setup and check data given inclusive range of runs"
253 self.
mintime=cool.ValidityKeyMax
254 self.
maxtime=cool.ValidityKeyMin
261 if (runp.stop
is not None and runp.stop>self.
maxtime): self.
maxtime=runp.stop
270 def runsFromTime(self,time1=cool.ValidityKeyMin,time2=cool.ValidityKeyMax):
271 """Query /TDAQ/RunCtrl/LB_Params to get list of runs/LBs in time range,
272 returning a map of run numbers to LB_Params objects"""
274 itr=folderLB_Params.browseObjects(time1,time2,cool.ChannelSelection.all())
280 while itr.goToNext():
284 if (obj.until()<cool.ValidityKeyMax
or obj.since()>=time1):
285 payload=obj.payload()
286 run=payload[
'RunNumber']
287 lb=payload[
'LuminosityBlock']
291 runlist[srun]=
LBParams(srun,slbmax,sstart,send)
297 if (lb>slbmax): slbmax=lb
298 if (obj.until()>send): send=obj.until()
299 if (obj.since()<sstart): sstart=obj.since()
303 runlist[srun]=
LBParams(srun,slbmax,sstart,send)
304 if (self.
loglevel>0):
print (
"Run list from LB_Params has %i entries" % len(runlist))
308 """Query /TDAQ/RunCtrl/LB_Params to get details of runs in runrange
309 Use both SOR_Params and EOR_Params to catch runs which ended badly.
310 Return a map of runs to RunParams objects"""
314 if (iov2>cool.ValidityKeyMax): iov2=cool.ValidityKeyMax
317 print (
"Applying detector status cuts: %s" % self.
detstatus)
320 gooddetstatus=RangeList(iov1,iov2)
323 folderSOR_Params=self.
cooldb.getFolder(self.
coolpath+
'/SOR_Params')
324 itr=folderSOR_Params.browseObjects((run1 << 32),(run2 << 32),cool.ChannelSelection.all())
325 while itr.goToNext():
327 payload=obj.payload()
328 run=payload[
'RunNumber']
330 if (self.
checkSelection(
not payload[
'RecordingEnabled'],payload[
'DetectorMask'],payload[
'RunType'],payload[
'FilenameTag'])
and len(gooddetstatus.getAllowedRanges(run << 32, (run+1) << 32))>0):
331 runlist[run]=
RunParams(run,payload[
'SORTime'],payload[
'RunType'],payload[
'DAQConfiguration'],payload[
'DetectorMask'],payload[
'FilenameTag'],payload[
'RecordingEnabled'],payload[
'DataSource'])
334 print (
"SOR_Params has data for %i runs" % len(runlist))
338 folderEOR_Params=self.
cooldb.getFolder(self.
coolpath+
'/EOR_Params')
339 itr=folderEOR_Params.browseObjects((run1 << 32),(run2 << 32),cool.ChannelSelection.all())
340 while itr.goToNext():
342 payload=obj.payload()
343 run=payload[
'RunNumber']
349 if (run
in runlist.keys()):
350 runlist[run].addEORInfo(payload[
'EORTime'],payload[
'TotalTime'],payload[
'CleanStop'],maxlb)
351 runlist[run].updateEORInfo(payload[
'DAQConfiguration'])
354 print (
"EOR_Params has data for %i runs" % neor)
359 folderSFOStat=self.
cooldb.getFolder(self.
coolpath+
'/FinalSFOStat')
360 itr=folderSFOStat.browseObjects((run1 << 32),(run2 << 32),cool.ChannelSelection.all())
361 while itr.goToNext():
363 payload=obj.payload()
364 run=obj.since() >> 32
365 if (run
in runlist.keys()):
366 runlist[run].addSFOStat(payload[
'PartitionName'],payload[
'ReceivedEvents'],payload[
'StoredEvents'])
370 print (
"FinalSFOStat has data for %i runs" % nsfo)
374 folderEvtCount=self.
cooldb.getFolder(self.
coolpath+
'/EventCounters')
375 itr=folderEvtCount.browseObjects((run1 << 32),(run2 << 32),cool.ChannelSelection.all())
376 while itr.goToNext():
378 payload=obj.payload()
379 run=obj.since() >> 32
380 if (run
in runlist.keys()):
381 runlist[run].addEventCounters(payload[
'PartitionName'],payload[
'L1Events'],payload[
'L2Events'],payload[
'EFEvents'],payload[
'RecordedEvents'])
385 print (
"EventCounters has data for %i runs" % nevc)
390 """Go through the runmap and lookup LB info, also flag missing EOR
391 in the error structures"""
396 if (runp.maxlb
is None):
400 if runp.cleanstop
is None:
404 "Check whether run passes selection cuts"
405 if (self.
onlyRec and not rec):
return False
407 if ((self.
mask & mask) != self.
mask):
return False
414 "Retrieve run/LB information from trigger and correlate with RunCtrl"
421 itr=folderTrigLBLB.browseObjects((self.
minrun << 32),((self.
maxrun+1) << 32),cool.ChannelSelection.all())
422 while itr.goToNext():
426 lb=since & 0xFFFFFFFF
427 payload=obj.payload()
428 start=payload[
'StartTime']
429 end=payload[
'EndTime']
439 if (lb>slbmax): slbmax=lb
440 if (start<sstart): sstart=start
441 if (end>send): send=end
447 print (
"Trigger LB map has data for %i runs" % len(self.
triglbmap))
456 if (runp.stop
is None):
458 print (
"Trigger end time will substitute %i %i" % (run,triglb.stop))
459 runp.patchEndTime(triglb.stop)
464 print (
"Missing trigger information for %i runs, patched EOR for %i" % (nbad,npatch))
467 "List runs which have errors to text output"
471 print (runp.decodeErr())
472 if (len(runp.errlist)>0):
473 for i
in runp.errlist:
474 print (
"Run %i %s" % (runp.run,i))
476 print (
"Total of %i runs with errors" % nerr)
479 "List run details to text output"
481 title=
" Run Events LumiB"
483 title+=
' StartTime StopTime'
485 title+=
' L1Events L2Events EFEvents'
491 title+=
' RunType DetectorMask'
493 title+=
' DAQConfiguration PartitionName FilenameTag '
496 runkeys.sort(reverse=lastfirst)
499 line=
"%8i %8i %6i" % (runp.run,
noneZero(runp.storedevents),
noneZero(runp.maxlb))
505 line+=
' %4i' % runp.errcode
509 line+=
' %-20s %16x' % (runp.runtype,runp.detmask)
511 line+=
' %-20s %-16s %-20s' % (runp.daqconfig,
noneStr(runp.partname),runp.filetag)
517 htfile=
open(filename,
'w')
518 htfile.write(
"""<head>
519 <title>Run Summary for %s</title></head>
521 <h2>COOL/RunControl Run Summary for %s</h2>
523 Data extracted from /TDAQ/RunCtrl SOR_Params, EOR_Params and LB_Params folders
524 for runs %i to %i (times %s to %s) on <b>%s</b>. All time are in <b>UTC</b>,
525 two hours behind Geneva local time. <font color=\"008000\">Green</font> runs
526 were recorded with clean stop, <font color=\"FF0000\">red</font> runs were
527 recorded without clean stop or RunCtrl EOR record.
528 Black runs were not recorded.
530 htfile.write(
"<table border=\"0\">\n<tr align=\"left\"><th>Run</th><th>Events</th><th>L1</th><th>L2</th><th>EF</th><th>MaxLB</th><th>Start time</th><th>Stop time</th><th>Duration</th><th>Rec</th><th>Clean</th><th>RunType</th><th>DetMask</th><th>DAQConfig</th><th>Partition</th><th>FilenameTag</th></tr>\n")
534 runkeys.sort(reverse=lastfirst)
538 if (runp.storedevents
is not None):
539 storeevt=
str(runp.storedevents)
542 if (runp.maxlb
is not None):
543 maxlb=
str(runp.maxlb)
548 if (runp.totaltime
is not None):
549 tottime=
str(runp.totaltime)
557 if (runp.cleanstop
is True):
565 ldetmask=
"<a href=#maskdecode%x>" % detmask
566 if (detmask
not in detmasklist): detmasklist+=[detmask]
567 htfile.write(
"<tr style=\"color:#%s\"><td>%i</td><td>%s</td><td>%i</td><td>%i</td><td>%i</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s%x</td><td>%s</td><td>%s</td><td>%s</td></tr>\n" % (col,runp.run,storeevt,
noneZero(runp.l1events),
noneZero(runp.l2events),
noneZero(runp.efevents),maxlb,start,stop,tottime,rec,clean,runp.runtype,ldetmask,detmask,runp.daqconfig,
noneStr(runp.partname),runp.filetag))
568 htfile.write(
"</table>\n")
569 htfile.write(
"<p>\nTotal of %i runs analysed\n<p>" % len(self.
runmap))
572 htfile.write(
"Detector mask decoding for these runs:\n<ul>\n")
573 for mask
in detmasklist:
574 htfile.write(
"<li><a name=maskdecode%x><b>%x</b>: %s</li>\n" % (mask,mask,
maskDecode(mask)))
575 htfile.write(
"</ul>\n")
576 htfile.write(
"\n</body>\n")