ATLAS Offline Software
Loading...
Searching...
No Matches
AtlRunQueryRun.py
Go to the documentation of this file.
1#!/bin/env python
2
3# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4#
5# ----------------------------------------------------------------
6# Script : AtlRunQueryRun.py
7# Project: AtlRunQuery
8# Purpose: Library with the Run class
9# Authors: Andreas Hoecker (CERN), Joerg Stelzer (DESY)
10# Created: Feb 10, 2009
11# ----------------------------------------------------------------
12#
13from functools import total_ordering
14from CoolRunQuery.utils.AtlRunQueryTimer import timer
15
16from CoolRunQuery.utils.AtlRunQueryUtils import addKommaToNumber, filesize, prettyNumber, RunPeriods
17from CoolRunQuery.utils.AtlRunQueryLookup import DecodeDetectorMask
18from CoolRunQuery.utils.AtlRunQueryIOV import IOVRange,IOVTime
19from CoolRunQuery.utils.AtlRunQueryLookup import LArConfig, isDQ, OLCAlgorithms
20from CoolRunQuery.output.AtlRunQueryRoot import makeLBPlot, makeLBPlotList, makeTimePlotList, makeBSPlots, SaveGraphsToFile
21from CoolRunQuery.AtlRunQueryQueryConfig import QC
22from CoolRunQuery.selector.AtlRunQuerySelectorBase import DataKey, Selector
23
24import math
25import time, calendar
26import sys
27import re
28import datetime
29import subprocess
30import urllib.request
31
32_fW = {'Run' : 12, 'NLB': 5, 'Time': 50, '#Events': 10, 'Stream': 10}
33
35 def __init__(self, iov, value, reject=False, valueForStorage=None):
36 self.iov = iov
37 self.lbrange = (self.iov.startTime.lb, self.iov.endTime.lb) # note that the end lb is not part of the iov
38 self.value = value
39 self.rejected = reject
40 self.valueForStorage = valueForStorage
41
42 def __str__(self):
43 return "[%i-%i) %s %r" % (self.lbrange[0], self.lbrange[1], "r" if self.rejected else "a", self.value)
44
45 def __repr__(self):
46 return "<DataEntry %s>" % self
47
48 def __len__(self):
49 length_L = self.lastlb-self.startlb+1
50 if length_L>0x7FFFFFFF:
51 length_L = 0x7FFFFFFF
52 return int(length_L)
53
54 @property
55 def startlb(self):
56 return self.lbrange[0]
57
58 @property
59 def endlb(self):
60 return self.lbrange[1]
61
62 @property
63 def lastlb(self):
64 return ((0x100000000 + self.endlb)-1) & 0xFFFFFFFF
65
66 def __getitem__(self,k):
67 return self.valueForStorage[k]
68
69 def contains(self, lb):
70 return self.lbrange[0]<=lb and lb<self.lbrange[1]
71
72 def intersects(self,lbrange):
73 lbstart, lbend = lbrange
74 return self.contains(lbstart) or self.contains(lbend-1) or (lbstart<=self.lbrange[0] and self.lbrange[1]<lbend)
75
76 def pickled(self):
77 v = self.value.pickled() if hasattr(self.value,'pickled') else self.value
78 return { 'firstlb' : self.startlb, 'lastlb' : self.lastlb, 'value' : v, 'accepted' : not self.rejected }
79
80 def json(self):
81 retDict = { 'lbrange' : [self.startlb, self.lastlb] }
82 if self.valueForStorage is None:
83 v = self.value.pickled() if hasattr(self.value,'pickled') else self.value
84 retDict["value"] = v
85 else:
86 retDict.update(self.valueForStorage)
87 return retDict
88
89
90class DataEntryList(list):
91 def __init__(self, key, run):
92 super(DataEntryList,self).__init__()
93 self.key = key
94 self.run = run
95
96 def atLB(self,lb):
97 for e in self:
98 return [x for x in self if x.contains(lb)]
99 return None
100
101 def stops(self):
102 return set([e.startlb for e in self]).union(set([e.lastlb+1 for e in self]))
103
104 @property
105 def lastlb(self):
106 return max([e.lastlb for e in self])
107
108 @property
109 def endlb(self):
110 return max([e.endlb for e in self])
111
112 def pickled(self):
113 return [e.pickled() for e in self]
114
115 def json(self):
116 return [e.json() for e in self]
117
118
120
121 # this is a temporary thing to get the DQDefects working, I still want to change the way the selectors work
122 DQKeys = []
123 DQLogic = []
124 DefectSelector = None
125
126 def __init__(self,run):
127 self.__run_o = run
128 self.run = run.runNr
129 self.data = {}
131 self.current_lb = 0
132 self.stops = []
133
134 def __contains__(self,k):
135 if type(k)==DataKey:
136 return k in self.data or k.ResultKey in self.data
137 return k in self.data
138
139 def __getitem__(self,k):
140 if k not in self:
141 self.data[k] = DataEntryList(key=k, run=self.run)
142 return self.data[k]
143 else:
144 if type(k)==DataKey:
145 return self.data[k] if k in self.data else self.data[k.ResultKey]
146 return self.data[k]
147
148 def __setitem__(self,k,value):
149 self.data[k]=value
150
151 def __iter__(self):
152 self.stops = self._calcStops()
153 for lb in self.stops: # the last stop is the LB after the last
154 if lb>self.__run_o.lastlb:
155 break
156 self._setLB(lb)
157 yield self
158
159 def keys(self):
160 return self.data.keys()
161
162 @property
163 def runNrS(self):
164 return str(self.run)
165
166 @property
167 def lb(self):
168 return self.current_lb
169
170 def lbend(self,lb=None):
171 if lb is None:
172 lb=self.current_lb
173 return self.stops[self.stops.index(lb)+1]-1
174
175 @property
176 def NrLBs(self):
177 return "%i" % max([el.lastlb for el in self.data.values()])
178
179 @property
180 def result(self):
181 return self.data_current_lb
182
183 @property
185 #print ("Checking Reject for LB",self.lb,"-",self.lbend())
186 need_dq_check = False
187 for k,s in self.data_current_lb.items():
188 if k in RunData.DQKeys:
189 need_dq_check = True
190 continue # exclude DQ from this, since it gets its own treatment
191 if s is None:
192 continue
193 for e in s:
194 if e.rejected:
195 return True
196 if need_dq_check:
197 if self.isDQRejected():
198 return True
199 if self.isDQDefectRejected():
200 return True
201 return False
202
203 def isDQRejected(self):
204 for orGroup in RunData.DQLogic:
205 groupAccept = False
206 for k in orGroup:
207 if len(self.data_current_lb[k])==0:
208 passes = False
209 else:
210 passes = not self.data_current_lb[k][0].rejected
211 if passes:
212 groupAccept = True
213 break
214 if not groupAccept:
215 return True
216 return False
217
219 if 'DQ' not in self.data_current_lb:
220 return False
221 return not RunData.DefectSelector(self.data_current_lb['DQ'])
222
223
224 @property
225 def isRejected(self):
226 for s in self:
227 if not s.isRejectedCurrentLB:
228 return False
229 return True
230
231
232 def isReady(self,lb=None):
233 if 'Ready for physics' not in self:
234 raise RuntimeError("No ready data available")
235 readydata = [x for x in self.data['Ready for physics'] if x.value=='1']
236 if lb is None:
237 return readydata
238 if type(lb)==int:
239 for x in readydata:
240 if x.contains(lb):
241 return True
242 return False
243 if type(lb)==tuple and len(lb)==2:
244 for x in readydata:
245 if x.intersects(lb):
246 return True
247 return False
248 raise RuntimeError("Can't interpret lb to check isReady(lb=%r)" % lb)
249
250
251 def getLBRanges(self,activeOnly=False):
252 last_lb = self.__run_o.nr_lb
253 a = [(int(data.lb),not data.isRejectedCurrentLB) for data in self if data.lb<=last_lb]
254 #a = [(int(data.lb),not data.isRejectedCurrentLB) for data in self]
255 if not a:
256 return []
257 start,state = a[0]
258 ranges = []
259 for x in a[:-1]:
260 if x[1] == state:
261 continue
262 ranges += [(state, start, x[0])]
263 start,state = x
264 last_start,last_state = a[-1]
265 if last_state==state:
266 ranges += [(state, start, last_lb+1)]
267 else:
268 ranges += [(state, start, last_start)]
269 ranges += [(last_state, last_start, last_lb+1)]
270 if activeOnly:
271 return [x for x in ranges if x[0]]
272 else:
273 return ranges
274
275 def _setLB(self,lb):
276 self.current_lb = lb
277 self.data_current_lb = dict([(k,entrylist.atLB(lb)) for k,entrylist in self.data.items()])
278
279 def _calcStops(self):
280 stops = set()
281 for entrylist in self.data.values():
282 stops.update(entrylist.stops())
283 return sorted(list(stops))
284
285 def addResult(self, iov, k, value, reject, valueForStorage = None):
286 if not iov:
287 iov = IOVRange(runStart=self.run, lbStart=1, runEnd=self.run+1, lbEnd=0)
288 self[k].append(DataEntry(iov=iov, value=value, reject=reject, valueForStorage=valueForStorage))
289
290 def astxt(self):
291 s = ""
292 if Run.showrunnr:
293 s += "%*s %*s " % (4, self.lb, 4, self.lbend())
294 s += ("r" if self.isRejectedCurrentLB else "a")
295 if Run.showtime:
296 s += "%*s " % (_fW['Time'],'')
297 if Run.showduration:
298 s += " "
299 for k in Run.SortedShowOrder():
300 k = k.ResultKey
301 w = 10
302 if k in _fW:
303 w = _fW[k]
304 v=""
305 if self.data_current_lb[k]:
306 v = [x.value for x in self.data_current_lb[k]][0]
307 if v is None:
308 v=""
309 if k == "#Events" or k[0:4] == "STR:" or k=="TriggerMenu" or k=="TriggerRates" or k=="olc:bcidmask":
310 v = ""
311 s += "%*s " % (w,v)
312 return s
313
314
315@total_ordering
316class Run:
317 ShowOrder = []
318 _SortedShowOrder = None
319 DisplayOrder = map(re.compile,['#Events','Ready','lhc:|olc:', 'TriggerMenu|SMK|Release|L1 PSK|HLT PSK|BGS|TriggerRates', 'bs:', 'STR:', 'DQ|SHIFTOFL:|LBSUMM:', 'lar:', 'Detector','.*'])
320 PromptCalibRuns = []
321 NemoTasks = {}
322 showrunnr = False
323 showtime = False
324 showduration = False
325 writehtml = False
326 bgcolor = "1"
327 totevents = [0, 0]
328 runnropen = -1
329 showCAFLinks = False
330 Datapath = ''
331 Fieldinfo = {}
332 GlobalTooltips = []
333 BeamspotSource = ''
334 runPeriods = RunPeriods()
335 TmpBoxContent = ''
336
337 @classmethod
338 def AddToShowOrder(cls,key):
339 #print ("ADDING TO SHOWORDER %r" % key)
340 if key not in cls.ShowOrder:
341 cls.ShowOrder += [ key ]
342
343 @classmethod
344 def addGlobalToolTip(cls, var, content):
345 cls.GlobalTooltips += ['dw_Tooltip.content_vars["%s"] = {content: \'%s\'};' % (var, content.replace("'","&#39;"))]
346
347 def __init__(self, runNr=0):
348 self.runNr = runNr
349 self.lhcRun = 0
350 self.sor = 0
351 self.eor = 0
352 self.lastlb = 0
353 self.selDataIncomplete = False
355 self.xvecStb = []
357 # the results of the query index by query key
358 self.result = {}
359 # the run statistics index by query key (filled in selector.runAfterQuery)
360 self.stats = {}
361 # the start times of all lumiblocks [start_LB1, start_LB2, start_LB3, ..., start_LBN]
362 self.lbtimes = []
363 self.tooltips = []
364 self.data = RunData(run=self)
365 # luminosity unil
366 self.lumiunit = 1.0 # default unit
367 self.lumiunittxt = 'nb'
368 self.instlumiunittxt = '30'
369 self.givepeakmuinfo = True
370 if self.runNr > 378000:
371 # last Run-2 run with SMK 2787 and release AthenaP1,21.1.56 is 376153
372 # first Run-3 with SMK 59 and release 22.0.13 is 379453
373 self.lhcRun = 3
374 elif self.runNr > 249000:
375 # last Run-1 run with SMK 1670 and release AtlasP1HLT,19.3.0.4 is 248373
376 # first Run-2 run with SMK 2002 and release AtlasP1HLT,20.1.0.1 is 249785
377 self.lhcRun = 2
378 else:
379 self.lhcRun = 1
380
381 if self.runNr > 168206 and self.runNr <= 170482:
382 self.lumiunit = 1.0e6 # unit is mbarn for heavy ions
383 self.lumiunittxt = 'mb'
384 self.instlumiunittxt = '24'
385 self.givepeakmuinfo = False
386
387
388 @property
389 def runNrS(self):
390 return "%i" % self.runNr
391
392 @property
394 return self.data.data_current_lb
395
396 @property
397 def NrLBs(self):
398 return "%i" % self.lastlb
399
400 @property
401 def nr_lb(self):
402 return self.lastlb
403
404 def addToolTip(self, var, content):
405 self.tooltips += ['dw_Tooltip.content_vars["%s\"] = {content: \'%s\'};' % (var, content.replace("'","&#39;"))]
406
408 if len(self.xvecStb)==0 and 'lhc:stablebeams' in Run.ShowOrder and 'lhc:stablebeams' in self.data:
409 entries = self.data['lhc:stablebeams']
410 for entry in entries:
411 if entry.startlb == 0:
412 continue
413 if 'true' in entry.value.lower():
414 self.xvecStb += range(entry.startlb,entry.endlb)
415 self.hasStableBeamsInfo = len(self.xvecStb)>0
416 return self.hasStableBeamsInfo, self.xvecStb
417
418 @classmethod
420 if Run._SortedShowOrder is not None:
421 if len(Run._SortedShowOrder) != len(Run.ShowOrder):
422 raise RuntimeError ("Sorting not up-to-date %i %i" % (len(Run._SortedShowOrder), len(Run.ShowOrder) ))
423 return Run._SortedShowOrder
424 hk = []
425 for order in Run.DisplayOrder:
426 for x in Run.ShowOrder:
427 if not order.match(x.ResultKey):
428 continue
429 if x in hk:
430 continue
431 hk += [x]
432 Run._SortedShowOrder = hk
433 if len(Run._SortedShowOrder) != len(Run.ShowOrder):
434 raise RuntimeError ("Sorting not up-to-date after creation %i %i" % (len(Run._SortedShowOrder), len(Run.ShowOrder) ))
435 return Run._SortedShowOrder
436
437 @classmethod
438 def headerkeys(cls):
439 hk = []
440 if Run.showrunnr:
441 hk += ['Run','Links','#LB']
442 if Run.showtime:
443 hk += ['Start and endtime (%s)' % QC.localStr()]
444 if Run.showduration:
445 hk += ['Duration']
446 for x in cls.SortedShowOrder():
447 x = x.ResultKey
448 if 'L1 PSK' in x or ('olc:' in x and ('beam1bunches' in x or 'beam2bunches' in x or 'collbunches' in x or 'beam1intensity' in x or 'beam2intensity' in x)):
449 continue
450 hk += [x]
451 return hk
452
453
454 @classmethod
455 def header(cls):
456 if Run.writehtml:
457 # flags...
458 ofllumiFlag = False
459 s = '<tr>\n'
460 if Run.showrunnr:
461 s += ' <th>Run</th><th>Links</th><th>#LB</th>\n'
462 if Run.showtime:
463 s += ' <th>Start and endtime (%s)</th>\n' % QC.localStr()
464 if Run.showduration:
465 s += ' <th>Duration</th>\n'
466 for ik, data_key in enumerate(Run.SortedShowOrder()):
467 k = data_key.ResultKey
468 if k[0:4] == 'STR:':
469 s += ' <th><font size="-2">%s_<BR>%s</font></th>' % tuple(k[4:].split('_',1))
470 elif k[0:8] == "Detector":
471 s += ' <th>%s</th>' % k
472 elif "SolCurrent" in k:
473 s += ' <th>Solenoid<br>current&nbsp;(A)</th>'
474 elif "TorCurrent" in k:
475 s += ' <th>Toroid<br>current&nbsp;(A)</th>'
476 elif 'DQ' == k:
477 s += ' '
478 matching_names = dict(Run.Fieldinfo['DQ']['DefMatch'])
479 first = True
480 for channelname in Run.Fieldinfo['DQ']['DefChannels']:
481 tip = "defect_match_%s" % channelname
482 info = "%s # %s" % (channelname if channelname!="" else "*",data_key._second_internal_key if data_key._second_internal_key!="" else "HEAD")
483 s += '<th style="align:center; white-space:nowrap; padding-right: 10px; padding-left: 10px; ">'
484 s += 'Data Quality<br><span class="showTip %s tooltip" style="font-weight:normal; font-size:80%%">(%s)</span>' % (tip, info)
485 if first:
486 s += '<div style="font-size: xx-small; cursor: pointer;" onclick="toggle_dq(this)">[show tolerable]</div>'
487 first = False
488 s += '</th>'
489
490 allDefects = sorted(matching_names[channelname])
491 n = 4*[len(allDefects)//4]
492 for x in range(len(allDefects) % 4):
493 n[x]+=1
494
495 # put the list of all defects into 4 columns
496 cx = 0
497 columns = []
498 for x in n:
499 columns.append( allDefects[slice(cx,cx+x)] )
500 cx+=x
501
502 for x in columns[1:]: # padding at the end of each column except the first to make zip include the last line
503 x += ['']
504
505 columnsTransposed = zip(*columns) # transpose
506
507 tts = ''
508 for z in columnsTransposed:
509 tts += '<tr>%s</tr>' % ''.join(["<td>%s</td>"% x for x in z])
510 content = '<table style="width:500px; font-size:80%%;">%s</table>' % tts
511 Run.addGlobalToolTip(tip,content)
512
513 elif isDQ(k):
514 foldertag,flag = k.split(':')
515
516 if flag in Run.Fieldinfo:
517 tipname = 'dqvfdesc_%s' % flag
518 commentbox = '%s' % (Run.Fieldinfo[flag])
519 Run.addGlobalToolTip(tipname, commentbox)
520 s += '<th class="showTip %s tooltip" style="cursor:pointer">' % tipname
521 else:
522 s += ' <th>'
523
524 s += '<font size="-1">%s</font><BR><font style="font-weight:normal;font-size:70%%">' % flag
525 if '#' in foldertag:
526 s += '(%s #<br>%s)' % tuple(foldertag.split('#',1))
527 else:
528 s += '(%s)' % (foldertag)
529 s += '</font></th>'
530
531 elif k == "L1 PSK":
532 continue
533 elif k == "HLT PSK":
534 s += ' <th>Prescale keys</th>'
535 elif k == "Release":
536 s += ' <th>HLT Release</th>'
537 elif k == "Datasets":
538 s += ' <th>Tier-0 Datasets</th>'
539 elif k == '#Events (incl. calib.)':
540 s += ' <th>#Events<br><font size="-2">(incl.&nbsp;calib.)</font></th>'
541 elif k == '#Events (streamed)' :
542 s += ' <th>#Events<br><font size="-2">(streamed)</font></th>'
543 elif 'lar:' in k:
544 if 'runtype' in k:
545 s += ' <th><font size="-2">Run type</font></th>'
546 elif 'nsamples' in k:
547 s += ' <th><font size="-2">#Samples</font></th>'
548 elif 'firstsample' in k:
549 s += ' <th><font size="-2">1st sample</font></th>'
550 elif 'format' in k:
551 s += ' <th><font size="-2">Format</font></th>'
552 else:
553 print ('ERROR: unknown LAr option "%s"' % k)
554 sys.exit(1)
555 elif 'lhc:' in k:
556 if 'fillnumber' in k:
557 s += ' <th> LHC Fill</th>'
558 elif 'stablebeams' in k:
559 s += ' <th>Stable beams</th>'
560 if 'lhc:beammode' in Run.ShowOrder:
561 s += ' <th>Beam mode</th>'
562 if 'lhc:beamenergy' in Run.ShowOrder:
563 s += ' <th>Beam&nbsp;energy and&nbsp;intensities</th>'
564
565 elif 'beamenergy' in k:
566 continue # included in 'fillbeams' summary
567 elif 'nbunch1' in k:
568 s += ' <th>#Bunches B1 <br><font size="-2"><b>(NOT YET RELIABLE)</b></font></th>'
569 elif 'nbunch2' in k:
570 s += ' <th>#Bunches B2 <br><font size="-2"><b>(NOT YET RELIABLE)</b></font></th>'
571 elif 'nbunchcoll' in k:
572 s += ' <th>#Bunches<br>colliding <br><font size="-2"><b>(NOT YET RELIABLE)</b></font></th>'
573 elif 'beamtype1' in k:
574 s += ' <th>Beam type&nbsp;B1</th>'
575 elif 'beamtype2' in k:
576 s += ' <th>Beam type&nbsp;B2</th>'
577 elif 'machinemode' in k:
578 s += ' <th>LHC mode</th>'
579 elif 'beammode' in k:
580 continue
581 else:
582 print ('ERROR: unknown LHC option "%s"' % k)
583 sys.exit(1)
584 elif 'ofllumi:' in k:
585 if not ofllumiFlag:
586 s += ' <th>Offline Luminosity<br><font style="font-weight:normal">(%s)</font></font></th>' % k.split(':')[-1]
587 ofllumiFlag = True
588 elif 'bs:' in k:
589 kt = k.replace('bs:','')
590 if 'bs:Pos' in k or 'bs:Sig' in k:
591 s += ' <th><font size="-2">%s<br><font style="font-weight:normal">(mm)</font></font></th>' % kt
592 elif 'bs:Tilt' in k:
593 s += ' <th><font size="-2">%s<br><font style="font-weight:normal">(rad)</font></font></th>' % kt
594 else:
595 s += ' <th><font size="-2">%s</font></th>' % kt
596 elif 'BPM' in k:
597 s += ' <th>Beam&nbsp;Position Monitors&nbsp;(BPM)</th>'
598 elif 'olc:' in k:
599 if 'olc:lumi' in k:
600 tp1, tp2, chan = k.split(':')
601 try:
602 chan = float(chan)
603 except ValueError:
604 chan = -1
605 if chan in OLCAlgorithms:
606 chanstr = OLCAlgorithms[chan]
607 else:
608 chanstr = 'UNKNOWN'
609 s += ' <th>Online&nbsp;del.&nbsp;Luminosity&nbsp;<font size="-2"><br><font style="font-weight:normal">[%s]</font></font></th>' % chanstr
610 elif 'beam1bunches' in k:
611 continue # not used anymore
612 elif 'beam2bunches' in k:
613 continue # not used anymore
614 elif 'collbunches' in k:
615 continue # not used anymore
616 elif 'bcidmask' in k:
617 s += ' <th>Bunch&nbsp;structure</th>'
618 elif 'beam1intensity' in k:
619 continue # included in 'fillbeams' summary
620 elif 'beam2intensity' in k:
621 continue # included in 'fillbeams' summary
622 else:
623 s += ' <th>%s</th>' % k
624
625 elif 'BGS Key' in k:
626 s += ' <th>Bunch group key</th>'
627
628 else:
629 s += ' <th>%s</th>' % k
630 s += '\n'
631 s += '</tr>'
632
633 # generate a second header line
634 secondheader = ''
635 patterns = [ ('lar:', 'LAr configuration'),
636 ('lhc:|olc:', 'LHC and online luminosity information' if any(['olc:' in x for x in Run.headerkeys()]) else 'LHC information' ),
637 ('bs:', 'Beam spot parameters (%s)' % Run.BeamspotSource),
638 ('STR:', 'Data stream statistics'),
639 ('TriggerMenu|SMK|Release|L1 PSK|HLT PSK|BGS|TriggerRates', 'Trigger information'),
640 ('SHIFTOFL:', 'Data quality (SHIFTOFL)'),
641 ('LBSUMM:', 'Data quality (LBSUMM)')
642 ]
643
644 order = []
645 for (p,hdesc) in patterns:
646 matchedpositions = [idx for (idx,head) in enumerate(Run.headerkeys()) if re.match(p,head)]
647 #print ("pattern",p,matchedpositions)
648 if matchedpositions:
649 order += [(min(matchedpositions),max(matchedpositions),hdesc)]
650 order.sort()
651
652 mergeempty = True
653 if len(order)>0:
654 current=0
655 for th in order:
656 if mergeempty:
657 if th[0]>current:
658 secondheader += '<th colspan="%s"></th>' % (th[0]-current)
659 else:
660 for x in range(th[0]-current):
661 secondheader += '<th></th>'
662 secondheader += '<th colspan="%s">%s</th>' % (th[1]-th[0]+1,th[2])
663 current=th[1]+1
664 if len(Run.headerkeys())>current:
665 if mergeempty:
666 secondheader += '<th colspan="%s"></th>' % (len(Run.headerkeys())-current)
667 else:
668 for x in range(len(Run.headerkeys())-current):
669 secondheader += '<th></th>'
670 secondheader = "<tr>%s</tr>" % secondheader
671
672
673 s = '<thead>' + secondheader + s + '</thead>\n'
674
675 # Global (run independent) tooltips
676
677 # OLC
678 if any([k for k in Run.ShowOrder if "olc:lumi" in k.ResultKey]):
679 boxcontent = '<font color="#AA0000">Click&nbsp;to&nbsp;enlarge&nbsp;figure and&nbsp;to&nbsp;obtain&nbsp;online&nbsp;integrated&nbsp;luminosity&nbsp;versus&nbsp;LB</font>'
680 Run.addGlobalToolTip("OLCLumi", boxcontent)
681
682 # OFLLumi
683 if any([k for k in Run.ShowOrder if "ofllumi" in k.ResultKey]):
684 boxcontent = '<font color="#AA0000">Click to obtain offline integrated luminosity versus LB</font>'
685 Run.addGlobalToolTip("OFLLumi", boxcontent)
686
687 # OFLBS - beamspot
688 if any([k for k in Run.ShowOrder if "bs:" in k.ResultKey]):
689 boxcontent = '<font color="#AA0000">Click to obtain %s beamspot versus LB</font>' % (Run.BeamspotSource.split()[0])
690 Run.addGlobalToolTip("OFLBS", boxcontent)
691
692 # BPM info
693 if any([k for k in Run.ShowOrder if "BPM" == k.ResultKey]):
694 boxcontent = '<font color="#AA0000">Click to enlarge figure</font>'
695 Run.addGlobalToolTip("BPM", boxcontent)
696
697 # LHC Summary
698 if any([k for k in Run.ShowOrder if "lhc:fillnumber" in k.ResultKey]):
699 boxcontent = '<font color="#AA0000">Click to enlarge figure</font>'
700 Run.addGlobalToolTip("LHCSummary", boxcontent)
701
702 else:
703 s = ''
704 for lll in [1,2]:
705 if Run.showrunnr:
706 if lll==0:
707 s += '%-*s %*s ' % (_fW['Run'],'Run',_fW['NLB'],'#LB')
708 if lll==1:
709 s += '%-*s %*s ' % (_fW['Run'],' ',_fW['NLB'],' ')
710 s+=" " # accept/reject flag
711 if Run.showtime:
712 hstr = 'Start and endtime (%s)' % QC.localStr()
713 if lll==0:
714 s += '%*s ' %(_fW['Time'],hstr)
715 if lll==1:
716 s += '%*s ' %(_fW['Time'],' ')
717 if Run.showduration:
718 if lll==0:
719 s += '%*s ' % (10,'Duration')
720 if lll==1:
721 s += '%*s ' % (10,' ')
722 for k in Run.SortedShowOrder():
723 if k.Type == DataKey.STREAM:
724 w = max(len(k.Header)-k.Header.find('_'),_fW['Stream'])
725 if lll==0:
726 s += '%*s ' % (w,k.Header[4:k.Header.find('_')])
727 if lll==1:
728 s += '%*s ' % (w,k.Header[k.Header.find('_')+1:])
729 else:
730 w = 10
731 if k in _fW:
732 w = _fW[k.ResultKey]
733 if lll==0:
734 s += '%*s ' % (w,k.Header)
735 if lll==1:
736 s += '%*s ' % (w,' ')
737 if lll==0:
738 s+='\n'
739 return s
740
741 def addResult(self, resDictKey, value, iov=None, reject=False, valueForStorage=None):
742 if resDictKey=='DQ' and value=='n.a.':
743 return
744 if resDictKey not in self.result:
745 self.result[resDictKey] = value
746 if iov:
747 if iov.startTime.lb>self.lastlb:
748 return # sometimes there are IOVs completely outside the run e.g. run 165821 DQ SHIFTOFL
749 iov.endTime = min(iov.endTime, IOVTime(self.runNr,self.lastlb+1) )
750 self.data.addResult(iov, resDictKey, value, reject, valueForStorage=valueForStorage)
751
752 def runlinks(self):
753 s = ''
754 # DS
755 if time.gmtime(self.sor/1.E9).tm_year >= 2010:
756 s += ' <a href="http://atlas.web.cern.ch/Atlas/GROUPS/DATAPREPARATION/DataSummary/%i/run.py?run=%i" target="_blank" title="Data summary information for run %i"><font size="-3">DS</font></a>,&nbsp;\n' % (time.gmtime(self.sor/1.E9).tm_year, self.runNr, self.runNr)
757 # RS
758 s += ' <a href="http://atlas-service-db-runlist.web.cern.ch/atlas-service-db-runlist/php/runDetails.php?run=%i" target="_blank" title="Run summary information for run %i"><font size="-3">RS</font></a>,&nbsp;\n' % (self.runNr, self.runNr)
759 # BS
760 s += ' <a href="https://atlas-beamspot.cern.ch/webapp/jobs/?r=%i" target="_blank" title="Beam spot fit information for run %i"><font size="-3">BS</font></a>,&nbsp;\n' % (self.runNr, self.runNr)
761 # AMI
762 s += ' <a href="https://ami.in2p3.fr/AMI/servlet/net.hep.atlas.Database.Bookkeeping.AMI.Servlet.Command?Converter=/AMIXmlToAMIProdHtml.xsl&Command=FormBrowseDatasetPerRun+-runNumber=%i" target="_blank" title="AMI reference for run %i"><font size="-3">AMI</font></a>,&nbsp;\n' % (self.runNr, self.runNr)
763 # DQ
764 s += ' <a href="https://atlasdqm.web.cern.ch/atlasdqm/DQBrowser/makeMatrix.php?selection=All&run=%i&runup=&dbinstance=COMP200_SHIFTOFL&tag=HEAD" target="_blank" title="Browse detailed data quality entries for run %i (uses SHIFTOFL folder in COMP200 conditions database)"><font size="-3">DQ</font></a>,<br>\n' % (self.runNr, self.runNr)
765 # ELOG
766 s += ' <a href="https://atlasop.cern.ch/elog/ATLAS/ATLAS/?mode=full&reverse=0&reverse=1&npp=20&ma=1&ya=2008&last=3064&subtext=%i&sall=0" target="_blank" title="Search for ELOG entries on run %i"><font size="-3">ELOG</font></a>,&nbsp;\n' % (self.runNr, self.runNr)
767 # DCS reference, format: http://atlas-dcs.cern.ch/navigation.php?datestring=2009-07-26-10-12
768 tbeg = time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime(self.sor/1.E9))
769 t = time.gmtime(self.eor/1.E9)
770 tend = "%4i-%02i-%02i-%02i-%02i" % (t[0], t[1], t[2], t[3], t[4])
771 s += ' <a href="http://atlas-dcs.cern.ch/navigation.php?date2=%s" target="_blank" title="DCS status at begin of run %i"><font size="-3">DCS:SoR</font></a>/' % (tbeg, self.runNr)
772 s += '<a href="http://atlas-dcs.cern.ch/navigation.php?date2=%s" target="_blank" title="DCS status at end of run %i"><font size="-3">EoR</font></a>,&nbsp;\n ' % (tend, self.runNr)
773 #s += ' <a href="https://atlas-dcs.cern.ch/navigation.php?date2=2008-09-29-19-01-42">DCS:SoR</font></a>/' % (tbeg, self.runNr)
774 #s += '<a href="https://atlas-dcs.cern.ch/navigation.php?date2=2008-09-30-08-17"><font size="-3">EoR</font></a>,&nbsp;\n ' % (tend, self.runNr)
775
776 # OKS
777 if self.data['oks']:
778 if self.lhcRun<3:
779 s += ' <a href="http://cern.ch/atlas-project-tdaq-cc/cgi/getdata.sh?tdaq-05-05-00&oracle://atlas_oks/r&atlas_oks_archive&%i&%i&ATLAS" target="_blank" title="Download online configuration for run %i"><font size="-3">OKS</font></a>\n' % ( self.data['oks'][0].value + (self.runNr,) )
780 else:
781 (hash, release) = self.data["oks"][0].value
782 s+= f' <a href="https://gitlab.cern.ch/atlas-tdaq-oks/p1/{release}/-/tree/{hash[5:]}" target="_blank" title="Browse online configuration for run {self.runNr}"><font size="-3">OKS</font></a>\n'
783 # lumi summary
784 # typical address: https://atlas.web.cern.ch/Atlas/GROUPS/DATAPREPARATION/RunSummary/run142308_summary.html
785 # OLD: fname = 'https://atlas.web.cern.ch/Atlas/GROUPS/DATAPREPARATION/RunSummary/run%i_summary.html' % (self.runNr)
786 fname = 'http://atlas.web.cern.ch/Atlas/GROUPS/DATAPREPARATION/DataSummary/runsum.py?run=%i\n' % (self.runNr)
787 fwget = urllib.request.urlopen(fname)
788
789 wincontent = ''
790 for line in fwget:
791 if '</head>' in str(line) and '<base href' not in wincontent:
792 wincontent += '<base href="http://atlas.web.cern.ch/Atlas/GROUPS/DATAPREPARATION/DataSummary/2010/"></base>'
793 wincontent += str(line)
794 wincontent = wincontent.replace('href="css/atlas-datasummary.css"', 'href="http://atlas.web.cern.ch/Atlas/GROUPS/DATAPREPARATION/DataSummary/css/atlas-datasummary.css"')
795
796 # remove temporarily second plot with integration
797 wincontent = wincontent.replace( '<td>\n<a href="rundata/run%i/run%i_ilumr.png"><img src="rundata/run%i/run%i_ilumr.png" alt="InstLumi" style="width: 200px; "></a></td>' % (self.runNr,self.runNr,self.runNr,self.runNr),'')
798 wincontent = wincontent.replace('"','&quot;')
799 wincontent = wincontent.replace('./RunSummary/figs','https://atlas.web.cern.ch/Atlas/GROUPS/DATAPREPARATION/RunSummary/figs')
800 wincontent = wincontent.replace('<a href','<a target=&quot;_blank&quot; href')
801 wincontent = wincontent.replace('width: 200px','width: 350px')
802 wincontent = wincontent.replace('width: 250px','width: 350px')
803
804
805 openwincmd = 'javascript:openLumiWindow('
806 openwincmd += "'Print','<!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;><html xmlns:&quot;my&quot;><head><title>Luminosity information for run %i</title></head><body style=&quot;background-color:#ffffff&quot;>" % self.runNr
807 openwincmd += wincontent
808 openwincmd += '</body></html>'
809 openwincmd += "')"
810
811 return s
812
813
814 def timestr(self,format='html',closed=True):
815 """ sor and eor is always in UTC, so sor=0 means the run started 1.1.1970 at 00:00:00"""
816 if QC.localtime:
817 begin = time.localtime(self.sor/1.E9)
818 end = time.localtime(self.eor/1.E9)
819 else:
820 begin = time.gmtime(self.sor/1.E9)
821 end = time.gmtime(self.eor/1.E9)
822
823 # begin string
824 beginstr = time.strftime("%a %b %d %Y %X",begin)
825
826 # end format
827 endformat = "%X"
828 if end[0]>begin[0]:
829 endformat = "%a %b %d, %Y %X"
830 elif end[1]>begin[1] or end[2]>begin[2]:
831 endformat = "%a %b %d, %X"
832
833 # end string
834 if closed:
835 endstr = time.strftime(endformat,end)
836 else:
837 endstr = '<font color=#BB0000>ongoing</font>' if format=='html' else 'ongoing'
838
839 # output
840 if format=='html':
841 return '%s&nbsp;&minus;&nbsp;%s' % (beginstr,endstr)
842 elif format=='seconds': #mainly for dictionary
843 return '%12.3f, %12.3f' % (self.sor/1.E9, self.eor/1.E9)
844 elif format=='secondsNum': #mainly for dictionary
845 return self.sor/1.E9, self.eor/1.E9
846 else:
847 return '%s - %s' % (beginstr,endstr)
848
849 def durationstr(self):
850 dt = time.gmtime((self.eor-self.sor)/1.E9)[2:6]
851 if dt[0]>1:
852 return "%id %ih %im %is" % ((dt[0]-1,) + dt[1:])
853 else:
854 return "%ih %im %is" % dt[1:]
855
856 @classmethod
857 def prettyChain(cls,tr,ps):
858 i = len(ps)-1
859 while i>0:
860 if ps[i]==ps[i-1]:
861 ps[i]=' '
862 elif ps[i]<0:
863 ps[i]='x'
864 else:
865 ps[i]=str(ps[i])
866 i-=1
867 if ps[0] is None:
868 ps[0]='n.a.'
869 elif ps[0]<0:
870 ps[0]='x'
871 else:
872 ps[0]=str(ps[0])
873
874 pss = '-'.join(ps)
875 s = "%s (%s)" % (tr.name,pss)
876 return s
877
878 def splitTriggerChains(self, chainlist):
879 res = { 'L1': [], 'L2': [], 'EF': [] }
880 for tr,pslist in chainlist.items():
881 if not tr.forshow:
882 continue
883 k = tr.name[0:2]
884 res[k] += [Run.prettyChain(tr,pslist)]
885 res['L1'].sort()
886 res['L2'].sort()
887 res['EF'].sort()
888 l1chains = '<br> '.join(res['L1'])
889 l2chains = '<br> '.join(res['L2'])
890 efchains = '<br> '.join(res['EF'])
891 ret = ()
892 if l1chains:
893 ret += (l1chains.replace('.0',''), )
894 if l2chains:
895 ret += (l2chains.replace('.0',''), )
896 if efchains:
897 ret += (efchains.replace('.0',''), )
898 return ret
899
900 def __str__(self):
901 if Run.writehtml:
902 s = ashtml(self)
903 return s
904 else:
905 s = self.astxt()
906 for lbr in self.data:
907 s+= "\n" + lbr.astxt()
908 return s
909
910 def __lt__(self,other):
911 if isinstance(other,Run):
912 return self.runNr < other.runNr
913 return self.runNr < other
914
915 def __eq__(self,other):
916 if isinstance(other,Run):
917 return self.runNr == other.runNr
918 return self.runNr == other
919
920
921 def astxt(self):
922 s = ""
923 if Run.showrunnr:
924 s += "run %*s %*s " % (_fW['Run']-4,self.runNrS, _fW['NLB'], self.NrLBs)
925 s += " "
926
927 if Run.showtime:
928 s += "%*s " % (_fW['Time'],self.timestr('txt'))
929
930 if Run.showduration:
931 dt = time.gmtime((self.eor-self.sor)/1.E9)[2:6]
932 if dt[0]>1:
933 s += "%id %ih %im %is " % ((dt[0]-1,) + dt[1:])
934 else:
935 s += "%2ih %2im %2is " % dt[1:]
936
937 for k in Run.SortedShowOrder():
938 w = 10
939 if k in _fW:
940 w = _fW[k]
941 v = self.result[k.ResultKey]
942 ostr=v
943 if k == "#Events":
944 ostr = addKommaToNumber(v)
945 elif k.Type == DataKey.STREAM:
946 w=max(len(k.Header)-k.Header.find('_'),_fW['Stream'])
947 if isinstance(ostr,tuple):
948 ostr = ostr[0]
949 elif k=="TriggerMenu":
950 pv = [Run.prettyChain(tr,pslist) for (tr,pslist) in v.items() if tr.forshow]
951 ostr = ", ".join(pv)
952 elif k=="TriggerRates":
953 ostr = "NOT YET"
954 elif k=="olc:bcidmask":
955 ostr = "NOT YET"
956
957 s += "%*s " % (w,ostr)
958
959 return s
960
961
962
963def ashtml(run):
964 import CoolRunQuery.html.AtlRunQueryHtmlUtils as HU
965
966 with timer("print runnur, runtime, etc"):
967 s = "<!-- Run %s -->\n" % run.runNrS
968
969 # disctionary with results
970 if Run.bgcolor == "1":
971 Run.bgcolor = "2"
972 else:
973 Run.bgcolor = "1"
974 color = Run.bgcolor
975
976 runrowclass = "out"
977 if run.showDataIncomplete:
978 runrowclass="showmiss"
979 if run.selDataIncomplete:
980 runrowclass="selmiss"
981 runrowclass += color
982
983 s += '<tr class="out%s">\n' % (color)
984
985 if Run.showrunnr: # show columns Run, Links, LB
986 # run number
987 if run.runNr == Run.runnropen: # is the run still ongoing?
988 s += ' <td style="text-align:center" class="%s"><font color="#BB0000">%s<br><font size="-2">(ongoing)</font></font>' % (runrowclass, run.runNrS)
989 else:
990 s += '<td style="text-align:center" class="%s">%s' % (runrowclass, run.runNrS)
991 p = Run.runPeriods.findPeriod( run.runNr )
992 if p:
993 # split in the middle
994 idx=-1
995 for i in range(p.count(',')//2+1):
996 idx = p.find(',',idx+1)
997 s += '<br><font color="#488AC7"><font size=-2><nobr>Period: %s<br>%s</nobr></font></font>' % (p[:idx],p[idx+1:])
998
999 # open for prompt calibration?
1000 if run.runNr in Run.PromptCalibRuns:
1001 s += '<br><font color="#008800"><font size="-2">(in&nbsp;calib&nbsp;loop)</font></font>'
1002 s += '</td>'
1003
1004 # links to other information
1005 s += '\n <td>\n%s</td>' % run.runlinks()
1006
1007 # luminosity block and average lb duration
1008 lbcontent = '%s' % run.NrLBs
1009 try:
1010 vf = float(run.NrLBs)
1011 if vf > 0:
1012 lbcontent = '%s<br><font size="-2">(%i&nbsp;s)</font>' % (run.NrLBs, (run.eor-run.sor)/(1.0E9*vf) )
1013 except ValueError:
1014 pass
1015
1016 window = HU.OpenWindow( HU.CreateLBTable(run), extracss=['html/atlas-runquery-lb.css'] )
1017
1018 # put into html page
1019 tip = 'showTip LBStart_%i' % run.runNr
1020 s += '\n <!-- LB Content -->\n'
1021 s += ' <td style="text-align: right"><div class="%s tooltip" style="display:inline;cursor:pointer">%s%s</a></div></td>\n' % (tip, window, lbcontent)
1022
1023
1024 if Run.showtime:
1025 s += ' <td>%s</td>' % run.timestr('html',run.runNr != Run.runnropen) # is the run still ongoing?
1026
1027
1028 if Run.showduration:
1029 if run.runNr == Run.runnropen:
1030 s += ' <td><font color="#BB0000">%s<br><font size="-2">(ongoing)</font></font></td>' % run.durationstr()
1031 else:
1032 s += " <td>%s</td>" % run.durationstr()
1033
1034 # find maximum output rate in case of streams
1035 sumstrnev = 0
1036 for k in Run.SortedShowOrder():
1037 if k.Type == DataKey.STREAM and k.ResultKey in run.stats and 'calibration' not in k.ResultKey:
1038 sumstrnev += run.result[k.ResultKey][0]
1039 if sumstrnev == 0:
1040 sumstrnev = -1
1041
1042 # flags...
1043 ofllumiFlag = False
1044
1045
1046 # the loop
1047 with timer("print keys"):
1048 for data_key in Run.SortedShowOrder():
1049 k = data_key.ResultKey
1050 v = run.result[k]
1051
1052 with timer("keybuild %s" % k, disabled=True):
1053 if any(['olc:beam2intensity' in k,
1054 'olc:beam1intensity' in k,
1055 'lhc:beamenergy' in k,
1056 'beam1bunches' in k,
1057 'beam2bunches' in k,
1058 'collbunches' in k,
1059 'L1 PSK' == k,
1060 ]):
1061 continue
1062
1063 s += '\n '
1064
1065 # -----------------------------------------------------------------------------------------------------------------------
1066
1067 if k == "#Events":
1068 # compute approximative output rate in Hz
1069 durInSec = (run.eor-run.sor)/1.0E9
1070 rate = 'n.a. Hz'
1071 try:
1072 if durInSec > 0:
1073 rate = '%.1f Hz' % (float(v)/durInSec)
1074 except ValueError: # if n.a.
1075 pass
1076 s += ' <td style="text-align: right">%s<BR><font size="-2">(%s)</font></td>' % (addKommaToNumber(v),rate)
1077 continue
1078
1079 # -----------------------------------------------------------------------------------------------------------------------
1080
1081 if k == "#L1A" or k == '#L2A' or k == '#EFA' or k == '#Events (streamed)' or k == '#Events (incl. calib.)':
1082 s += ' <td style="text-align: right">%s</td>' % addKommaToNumber(v)
1083 continue
1084
1085 # -----------------------------------------------------------------------------------------------------------------------
1086
1087 if k == 'DQ': # DEFECT
1088 intolerable = Run.Fieldinfo['DQ']['IntolerableDefects']
1089
1090 for channelname in Run.Fieldinfo['DQ']['DefChannels']:
1091 if channelname == '':
1092 matching_dqentries = run.stats[k]["defects"]
1093 elif channelname == 'DET':
1094 matching_dqentries = [dqentry for dqentry in run.stats[k]["defects"] if '_' not in dqentry[0]]
1095 else:
1096 from re import compile
1097 pattern = compile(channelname)
1098 matching_dqentries = [dqentry for dqentry in run.stats[k]["defects"] if pattern.match(dqentry[0])]
1099
1100
1101 # reduce to LB ranges inside READY
1102 matching_dqentries_ready = []
1103 for (defect, listLBranges) in matching_dqentries: # dqentry is of format ('SCT_GLOBAL_STANDBY', [(1L, 49L), (119L, 123L)])
1104 readyLBRanges = [lbrange for lbrange in listLBranges if run.data.isReady(lbrange)]
1105 if len(readyLBRanges)>0:
1106 matching_dqentries_ready += [ (defect, readyLBRanges) ]
1107
1108
1109 if len(matching_dqentries_ready)==0:
1110 dq_info = "<table class='dqdefects' style='border-color: limegreen; height=100%'><tr><td>&nbsp;</td></tr></table>\n"
1111 else:
1112 dq_info = "<table class='dqdefects'>\n"
1113 for defect,listLBranges in matching_dqentries_ready:
1114 tip = 'showTip dqdefect_%i_%s tooltip' % (run.runNr, defect)
1115 if defect in intolerable:
1116 dq_info += "<tr class='%s'><td class='intolerable'>%s</td><td class='lb'>" % (tip, defect)
1117 else:
1118 dq_info += "<tr class='%s tolerable' style='visibility:collapse;'><td>%s</td><td class='lb'>" % (tip, defect)
1119 dq_info += ", ".join([("%g&minus;%g" % (x[0],x[1]-1) if x[1]-x[0]!=1 else "%g" % x[0]) for x in listLBranges])
1120 dq_info += "</td></tr>\n"
1121 dq_info += '<tr height="100%%"><td height="100%%"></td></tr>\n'
1122 dq_info += "</table>\n"
1123 s += '<td class="def">%s</td>' % dq_info
1124
1125 continue
1126
1127 # -----------------------------------------------------------------------------------------------------------------------
1128
1129 if isDQ(k): # old, traffic-light DQ
1130 extraDQInfo = ''
1131 tip = ''
1132 dqmax = run.stats[k]["max"]
1133 n = run.stats[k]["counts"]
1134
1135 foundComment = False
1136 for (dq,comment), start, end in run.stats[k]["blocks"]:
1137 dqcss = dq
1138 if dq == 'n.a.':
1139 dqcss = 'NA'
1140 elif comment:
1141 foundComment = True
1142
1143 if n[dq]>0 and dq != dqmax:
1144 if start == end-1: # only one LB
1145 extraDQInfo += '<tr><td class="td%s" style="min-width: 45px; text-align: left; border-width: 0px; padding:1px;">&nbsp;LB&nbsp;%g:</td><td class="td%s" style="text-align: left; border-width: 0px; padding: 1px; ">%s&nbsp;</td></tr>' % (dqcss,start,dqcss,dq)
1146 else: # range of LBs
1147 extraDQInfo += '<tr><td class="td%s" style="min-width: 45px; text-align: left; border-width: 0px; padding:1px;">&nbsp;LB&nbsp;%g&minus;%g:</td><td class="td%s" style="text-align: left; border-width: 0px; padding: 1px; ">%s&nbsp;</td></tr>' % (dqcss,start,end-1,dqcss,dq)
1148
1149 if foundComment:
1150 tip = 'showTip dqcomm_%s_%i' % (k, run.runNr)
1151 if extraDQInfo:
1152 extraDQInfo = '<br><img vspace=2 height="1" width="1" src="wdot.jpg"><br><table style="width: 100%; border: 1px solid; border-width: 1px; border-spacing: 0px; border-color: #eeeeee; border-collapse: separate; padding: 0px; font-size: 65%"><tr>' + extraDQInfo + '</table>'
1153
1154 if tip:
1155 s += '<td class="%s td tooltip td%s">%s%s</td>' % (tip,dqmax,dqmax,extraDQInfo)
1156 else:
1157 s += '<td class="td td%s">%s%s</td>' % (dqmax,dqmax,extraDQInfo)
1158
1159 continue
1160
1161 # -----------------------------------------------------------------------------------------------------------------------
1162
1163 if "detector systems" in k.lower():
1164 if v!='n.a.':
1165 mask = '0x'+v if Selector.condDB()=='CONDBR2' else v # run2 the format is a hex string, in run 1 it is an int (represented as string)
1166 v = DecodeDetectorMask( mask=mask, lhcRun=run.lhcRun, smart=True)
1167 s += ' <td style="min-width:%ipx"><font size="-2">%s<hr color="#aaaaaa" size=1>[<a href="http://sroe.home.cern.ch/sroe/cgi-bin/avgmodule.py?run=%i" target=_blank>SCT HV setting</a>]</font></td>' % (1.1*len(v),v,run.runNr)
1168 continue
1169
1170 # -----------------------------------------------------------------------------------------------------------------------
1171
1172 if 'olc:lumi' in k:
1173
1174 # find range with stable beams (requires LHC information to be available)
1175 hasStableBeamsInfo, xvecStb = run.getStableBeamsVector()
1176
1177 # is pileup information available?
1178 printMu = 'olc:bcidmask' in Run.SortedShowOrder() and run.runNr>=151260 and run.givepeakmuinfo
1179
1180 # insert events per LB
1181 xvec = []
1182 yvec = []
1183 yvecInt = []
1184 for entry in run.data[k]:
1185 assert entry.startlb != 0, 'entry should not start at LB=0'
1186 val = entry.value if (entry.value!='n.a.' and entry.value>0) else 0
1187 lastlb = min(entry.lastlb,run.nr_lb)
1188 xvec += range(entry.startlb,lastlb+1)
1189 nlb = lastlb - entry.startlb + 1
1190 yvec += nlb*[val]
1191 yvecInt += nlb*[val]
1192
1193 # correct for time span
1194 intlumi, intlumiStb = (0, 0)
1195
1196 # for lifetime
1197 lifetime = 0
1198 lb1 = 0
1199 lb2 = 0
1200 t1 = 0
1201 t2 = 0
1202 y1 = 0
1203 y2 = 0
1204 if len(xvecStb) > 15:
1205 lb1 = xvecStb[3]
1206 lb2 = xvecStb[-1-5]
1207
1208 peaklumi = -1
1209 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
1210 lb=idx+1
1211 dt = (float(lbendtime)-float(lbtime))/1.E9
1212 yvecInt[idx] *= dt/1000.0*run.lumiunit # unit of yvec was: ub-1 s-1 -> nb-1
1213 yvec[idx] *= 1.0*run.lumiunit # unit of yvec was: ub-1 s-1, transform to: 10^30 cm-2s-1
1214 intlumi += yvecInt[idx]
1215
1216 if yvec[idx] > peaklumi:
1217 peaklumi = yvec[idx]
1218 if lb in xvecStb:
1219 intlumiStb += yvecInt[idx]
1220 if lb == lb1:
1221 t1 = lbtime/1.E9
1222 y1 = yvec[idx]
1223 elif lb == lb2:
1224 t2 = lbtime/1.E9
1225 y2 = yvec[idx]
1226
1227 if y1 > 0 and y2 > 0:
1228 lifetime = (t2 - t1)/(3600*math.log(y1/y2)) # unit: hours
1229
1230 # line to be printed in column
1231 if hasStableBeamsInfo:
1232 fullprint_ = 'All&nbsp;LBs:&nbsp;%0.4g<br>Stable&nbsp;B:&nbsp;%0.4g' % (intlumi,intlumiStb)
1233 histoText = 'Integrated luminosity: %.4g %s-1 (all LBs) and %.4g %s-1 (stable beams)' % (intlumi,run.lumiunittxt,intlumiStb,run.lumiunittxt)
1234 else:
1235 fullprint_ = 'All&nbsp;LBs:&nbsp;%0.4g' % (intlumi)
1236 histoText = 'Integrated luminosity: %.4g %s-1 (all LBs)' % (intlumi,run.lumiunittxt)
1237
1238 # find out which channel was used
1239 tp1, tp2, chan = k.split(':')
1240 try:
1241 chan = int(chan)
1242 if chan in OLCAlgorithms:
1243 chanstr = OLCAlgorithms[chan]
1244 else:
1245 chanstr = 'UNKNOWN'
1246 except ValueError:
1247 chanstr = chan
1248
1249 path = makeLBPlot( xvec, xvecStb, yvec, 'Luminosity block number', 'Online luminosity (10^{%s}cm^{-2}s^{-1})' % run.instlumiunittxt, '',
1250 'olclumi_vs_lb_run_%i' % (run.runNr),
1251 'Online lumi [%s] per LB for run %i' % (chanstr, run.runNr),
1252 QC.datapath, histoText )
1253
1254 # create window and tooltip
1255 wincontent = '<table class=&quot;outer&quot; style=&quot;padding: 5px&quot;><tr><td>'
1256 wincontent += '<strong><b>Online luminosity [algorithm: %s] per LB for run %i:</b></strong><br><font size=&quot;-1&quot; color=&quot;#888888&quot;>(Begin/end of run: %s)</font>' % (chanstr, run.runNr, run.timestr('html', run.runNr != Run.runnropen))
1257 wincontent += '<hr color=&quot;black&quot; size=1>'
1258 wincontent += '<table style=&quot;padding: 0px&quot;><tr><td>'
1259 wincontent += '<img src=&quot;%s&quot; align=&quot;left&quot;>' % path
1260 wincontent += '</td></tr></table>'
1261 wincontent += '<hr color=&quot;black&quot; size=1>'
1262 wincontent += '<table class=&quot;LB&quot;>'
1263 wincontent += '<tr><th>LB</th><th>Start time<br> (%s)</th><th>Duration<br>(sec)</th><th>Inst. luminosity<br>(1e%s&nbsp;cm<sup>&minus;2</sup>s<sup>&minus;1</sup>)</th>' % (QC.tzdesc(), run.instlumiunittxt)
1264 wincontent += '<th>Int. luminosity<br>(%s<sup>&minus;1</sup>)</th><th>Cumul. luminosity<br>(%s<sup>&minus;1</sup>)</th>' % (run.lumiunittxt, run.lumiunittxt)
1265 if printMu:
1266 wincontent += '<th>&nbsp;&nbsp;&lt;&mu;&gt;&nbsp;&nbsp;</th>'
1267 if hasStableBeamsInfo:
1268 wincontent += '<th>Stable beams</th>'
1269 wincontent += '</tr><tr style=&quot;background:%s&quot;>' % '#eeeeee'
1270 intlumi = 0
1271 mumax = -1
1272 minBiasXsec = 80.0 if Selector.isRun2() else 71.5 # minbias cross-section for 8TeV (71.5) and 13TeV (80.0)
1273
1274 is5TeVRun = (run.sor/1.E9) > time.mktime((2017,11,11,0,0,0,0,0,0)) and (run.sor/1.E9) < time.mktime((2017,11,21,8,0,0,0,0,0))
1275 if is5TeVRun:
1276 minBiasXsec = 66.25
1277
1278 is5TeVHIRun = (run.sor/1.E9) > time.mktime((2018,11,7,0,0,0,0,0,0)) and (run.sor/1.E9) < time.mktime((2018,12,31,0,0,0,0,0,0))
1279 if is5TeVHIRun:
1280 minBiasXsec = 7660
1281
1282 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
1283 lb=idx+1
1284 isStableBeams = (lb in xvecStb)
1285 intlumi += yvecInt[idx]
1286 stbBeams = 'T' if isStableBeams else '&minus;'
1287 timetuple = time.localtime(lbtime/1.E9) if QC.localtime else time.gmtime(lbtime/1.E9)
1288 wincontent += '<td>%s</td><td>%s</td><td>%.2f</td><td>%.4g</td><td>%.4g</td><td>%.4g</td>' % (lb, time.strftime("%X",timetuple), (float(lbendtime)-float(lbtime))/1.E9, yvec[idx], yvecInt[idx], intlumi)
1289 # pileup <mu> information?
1290 if printMu:
1291 nb = 0
1292 for n,v,lbstart,lbend in run.stats['olc:bcidmask']['blocks']:
1293 if lb >= lbstart and lb <= lbend:
1294 if v:
1295 nb = len(v[2])
1296 break
1297 # compute expected number of interactions
1298 lumi_mb = yvec[idx]*1000.0
1299 mu = 0
1300 if nb:
1301 mu = lumi_mb * minBiasXsec / 11245.511 / nb
1302 wincontent += '<td>%.3g</td>' % mu
1303 if isStableBeams and mu > mumax:
1304 mumax = mu
1305 if hasStableBeamsInfo:
1306 wincontent += '<td>%s</td>' % stbBeams
1307 if idx%2!=0:
1308 col = '#eeeeee'
1309 else:
1310 col = '#ffffff'
1311 wincontent += '</tr><tr style=&quot;background:%s&quot;>' % col
1312
1313 printMuInfoToFile = True
1314 if printMuInfoToFile:
1315 mutextfilename = QC.datapath + '/mu_vs_run_output.txt'
1316 muout = open( mutextfilename, 'a' )
1317 muout.write( '%10i %f\n' % (run.runNr, mumax) )
1318 muout.close()
1319
1320 if mumax < 0:
1321 s_mumax = "n.a."
1322 elif mumax < 0.1:
1323 s_mumax = "%0.3e" % mumax
1324 else:
1325 s_mumax = "%0.3f" % mumax
1326
1327 if run.runNr == Run.runnropen: # run still ongoing
1328 wincontent += '<tr><td style=&quot;text-align:left&quot;colspan=&quot;3&quot;><i>&nbsp;&nbsp;Run still ongoing ...</i></td></tr>'
1329 wincontent += '</tr></table>'
1330
1331 wincontent += """<hr color=&quot;red&quot; size=1><font color=&quot;#777777&quot;><font size=&quot;-1&quot;><i><font size=&quot;-2&quot;>Created by AtlRunQuery on: %s</font></i></font></td></tr></table><script type=&quot;text/javascript&quot;></script></body></html>""" % str(datetime.datetime.now())
1332 wincontent += '</td></tr></table>'
1333
1334 openwincmd = '<a href="javascript:openLargeWindow('
1335 openwincmd += "'Print','<!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;><html xmlns:&quot;my&quot;><head><title>Run query result for online luminosity</title><LINK href=&quot;html/atlas-runquery-lb.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;></head><body><table style=&quot;font-family: sans-serif; font-size: 85%%&quot;>"
1336 openwincmd += wincontent
1337 openwincmd += "')\">"
1338
1339 # line to be printed in column
1340 fullprint = '<table class="bcidtable">'
1341 fullprint += '<tr><td colspan="2"><img src="%s" align="left" width="90px"></td></tr>' % path
1342 if hasStableBeamsInfo:
1343 fullprint += '<tr><td style="text-align:left">Entire&nbsp;run:</td><td style="text-align:left">&nbsp;%0.4g&nbsp;%s<sup>&minus;1</sup></td></tr><tr><td style="text-align:left">Stable&nbsp;beams:</td><td style="text-align:left">&nbsp;%0.4g&nbsp;%s<sup>&minus;1</sup></td></tr><tr><td style="text-align:left">Peak&nbsp;lumi:</td><td style="text-align:left">&nbsp;%.2g&nbsp;e%s&nbsp;cm<sup>&minus;2</sup>s<sup>&minus;1</sup></td></tr><tr><td style="text-align:left">Peak&nbsp;&lt;&mu;&gt;:</td><td style="text-align:left">&nbsp;%s</td></tr>' % (intlumi, run.lumiunittxt, intlumiStb, run.lumiunittxt, peaklumi, run.instlumiunittxt, s_mumax)
1344 if lifetime > 0:
1345 fullprint += '<tr><td style="text-align:left">Approx.&nbsp;lifetime:</td><td style="text-align:left">&nbsp;%0.2g&nbsp;h</td></tr>' % (lifetime)
1346 else:
1347 fullprint += '<td style="text-align:left">All&nbsp;LBs:</td><td style="text-align:left">&nbsp;%0.4g</td></tr>' % (intlumi)
1348 fullprint += '</table>'
1349
1350 # put into html page
1351 s += '<td class="showTip OLCLumi stream" style="text-decoration:none; text-align: right">%s%s</a></td>' % (openwincmd, fullprint)
1352
1353 continue
1354
1355 # -----------------------------------------------------------------------------------------------------------------------
1356
1357 if 'olc:bcidmask' in k:
1358
1359 firstGoodRun = 151260
1360 if run.runNr < firstGoodRun: # OLC information not properly filled
1361 s += '<td style="text-align:center;color:#AA0000;font-size:60%%;">BCID information only available for run numbers larger than %i</font></td>' % firstGoodRun
1362 continue
1363
1364 # line to be printed in column
1365 fullprint = '<font size=-2><i>Run without stable beams (or, in few cases, missing bunch information in COOL). Click here to obtain bunch crossing information</i>.</font>'
1366
1367 wincontent = '<table class=&quot;outer&quot; style=&quot;padding: 5px&quot;><tr><td>'
1368 wincontent += '<strong><b>Identifiers (BCID) for paired and unpaired bunches for run %i:</b></strong><br><font size=&quot;-1&quot; color=&quot;#888888&quot;>(Begin/end of run: %s)</font>' % (run.runNr, run.timestr('html', run.runNr != Run.runnropen))
1369 wincontent += '<hr color=&quot;black&quot; size=1>'
1370 wincontent += '<table class=&quot;bcidtable&quot; align=&quot;center&quot;><tr class=&quot;tr0&quot;><td style=&quot;text-align:left;font-weight:bold&quot; colspan=&quot;3&quot;>LB&nbsp;range</td><td style=&quot;text-align:right;font-weight:bold&quot;>&nbsp;&nbsp;&nbsp;&nbsp;Stable<br>beams</td><td style=&quot;text-align:right;font-weight:bold&quot;>%s</td><td style=&quot;text-align:right;font-weight:bold&quot;>%s</td><td style=&quot;text-align:right;font-weight:bold&quot;>%s</td></tr>' % ('&nbsp;&nbsp;Crossing&nbsp;(Paired)', '<nobr>&nbsp;&nbsp;Unpaired&nbsp;Beam-1&nbsp;</nobr>', '<nobr>&nbsp;&nbsp;Unpaired&nbsp;Beam-2</nobr>')
1371 ic = 0
1372
1373 # retrieve stable beam information
1374 hasStableBeamsInfo, xvecStb = run.getStableBeamsVector()
1375
1376 first = True
1377 for n,v,lbstart,lbend in run.stats[k]['blocks']:
1378 ic += 1
1379 cls = 'tr1' if (ic%2==1) else 'tr2'
1380
1381 # is this block during stable beams ?
1382 isInStableBeamPeriod = False
1383 stableBeamWord = '&minus;'
1384 if hasStableBeamsInfo:
1385 if lbstart <= xvecStb[-1] and lbend >= xvecStb[0]:
1386 isInStableBeamPeriod = True
1387 stableBeamWord = '<b>T</b>'
1388
1389 wincontent += '<tr class=&quot;%s&quot;><td class=&quot;td1&quot; style=&quot;text-align:right&quot;><b>%s</b></td><td style=&quot;text-align:right&quot;><b>&minus;</b></td><td style=&quot;text-align:right&quot;><b>%s:</b>&nbsp;&nbsp;&nbsp;</td><td>%s&nbsp;&nbsp;&nbsp;&nbsp;</td>' % (cls,str(lbstart),str(lbend-1),stableBeamWord)
1390 if v:
1391 beam1, beam2, beam12 = v
1392 unpaired1 = [b for b in beam1 if b not in beam12]
1393 unpaired2 = [b for b in beam2 if b not in beam12]
1394
1395 noBunches = not unpaired1 and not unpaired2 and not beam12 # happens at least in run 152508
1396 if not unpaired1:
1397 unpaired1 = ['&minus;']
1398 if not unpaired2:
1399 unpaired2 = ['&minus;']
1400 if not beam12:
1401 beam12 = ['&minus;']
1402
1403 # analyse bunch train structure
1404 if isInStableBeamPeriod and first and not noBunches:
1405 first = False # don't do that again
1406
1407 maxBunchDistanceInTrain = 6
1408 if int(run.runNr) > 168665:
1409 maxBunchDistanceInTrain = 25 # large (20) bunch distance for Heavy Ion collisions
1410 trains = []
1411 bp = -1
1412 for b in beam12:
1413 if bp > 0 and b - bp <= maxBunchDistanceInTrain:
1414 if trains[-1][-1] != bp:
1415 trains.append([bp])
1416 trains[-1].append(b)
1417 elif len(beam12) > 1 and bp <= 0 and beam12[0] - b <= maxBunchDistanceInTrain:
1418 trains.append([b])
1419 bp = b
1420
1421 fullprint = '<table class = "triggerlinktable">'
1422 fullprint += '<tr><td style="text-align:left"><nobr>No. of coll. bunches:&nbsp;&nbsp;</nobr></td><td> <b>%i</b></td></tr>' % len(beam12)
1423 fullprint += '<tr><td style="text-align:left"><nobr>No. of bunch trains:</nobr></td><td><b> %i</b></td></tr>' % len(trains)
1424 if trains:
1425 Run.TmpBoxContent = '<strong><b><nobr>Bunch train configuration for run <font color="#AA0000">%i</font></nobr></b></strong>' % run.runNr
1426 Run.TmpBoxContent += '<hr size=1>'
1427
1428 # it may be that the BCID=1 is a single pilot bunch only without a train
1429 # in that case, don't use it to compute bunch distance in train, but print comment
1430 icoor = 0
1431 if len(trains) > 1:
1432 icoor = 1
1433 if len(trains[icoor]) > 1:
1434 bunchDist = trains[icoor][1] - trains[icoor][0]
1435 fullprint += '<tr><td style="text-align:left"><nobr>Bunch dist. in trains:</nobr></td><td><nobr><b> %i</b> (%i ns)</nobr></td></tr>' % (bunchDist, bunchDist*25)
1436 # print the comment in case of single pilot bunch
1437 if len(trains) > 0:
1438 if len(trains[0]) == 1:
1439 fullprint += '<tr><td style="text-align:left;color:#4477EE" colspan=2><i>The first "bunch train" is trivial and consists of only the colliding pilot bunch</td></tr>'
1440 fullprint += '</table><hr size=1>'
1441 Run.TmpBoxContent += '<table><tr><td>Train</td><td><nobr>No. of bunches</nobr></td><td style="text-align:right">&nbsp;&nbsp;&nbsp;BCID range</td></tr>'
1442 for it, train in enumerate(trains):
1443 Run.TmpBoxContent += '<tr><td>&nbsp;&nbsp;%i:&nbsp;&nbsp;</td><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%i</td><td style="text-align:right"><nobr>&nbsp;&nbsp;%i &minus; %i</nobr></td></tr>' % (it+1, len(train), train[0], train[-1])
1444 Run.TmpBoxContent += '</table><hr size=1>'
1445 else:
1446 Run.TmpBoxContent = '<nobr>No bunch trains in this run</nobr> <hr size=1>'
1447 fullprint += '</table><hr size=1>'
1448 Run.TmpBoxContent += '<p><font color="#AA0000"><b><nobr>Click to obtain full list of BCIDs</nobr></b></font>'
1449 fullprint += '<span style="font-size: xx-small; color: #555555">[ <i>Mouse over for train configuration. Click for full list of BCIDs</i> ]</span>'
1450
1451 wincontent += '<td class=&quot;td1&quot; style=&quot;text-align:right&quot;>%s</td><td style=&quot;text-align:right; border-left:1px #C0C0D0 solid;border-right:1px #C0C0D0 solid&quot;>%s</td><td style=&quot;text-align:right&quot;>%s</td>' % (', '.join(map(str,beam12)), ', '.join(map(str,unpaired1)), ', '.join(map(str,unpaired2)) )
1452 else:
1453 wincontent += '<td class=&quot;td1&quot; style=&quot;text-align:right&quot;>%s</td><td style=&quot;text-align:right&quot;>%s</td><td style=&quot;text-align:right&quot;>%s</td>' % ('&minus;','&minus;','&minus;')
1454
1455 wincontent += '</tr>'
1456
1457
1458 wincontent += '</table></td>'
1459 wincontent += '</td></tr></table>'
1460
1461
1462 openwincmd = HU.OpenWindow(wincontent, title="Run query result for online luminosity", extracss=None, size="large")
1463 #openwincmd = '<a href="javascript:openLargeWindow('
1464 #openwincmd += "'Print','<!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;><html xmlns:&quot;my&quot;><head><title>Run query result for online luminosity</title><LINK href=&quot;html/atlas-runquery-results.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;></head><body><table style=&quot;font-family: sans-serif; font-size: 85%%&quot;>"
1465 #openwincmd += wincontent
1466 #openwincmd += "')\">"
1467
1468 s += '<td class="showTip OLCBCID_%i stream" style="text-decoration:none; text-align: left">%s%s</a></td>' % (run.runNr, openwincmd, fullprint)
1469
1470 continue
1471
1472 # -----------------------------------------------------------------------------------------------------------------------
1473
1474 if k.startswith('bs:Pos') or k.startswith('bs:Sig') or k.startswith('bs:Tilt'):
1475
1476 # reference for average
1477 refkey = 'bs:Sig-X' # must exist !
1478 statkey = 'bs:Status' # must exist !
1479
1480 onloffltype = 'Online' if (run.stats['Beamspot']=='online') else 'Offline'
1481
1482 # given is beamspot position or width or tilt
1483 xvec = []
1484 yvec = []
1485 yvecSt = []
1486 bsidx = []
1487 isOK = False
1488 vave = 0
1489 eave = 0
1490 iave = float(0)
1491 idx = 0
1492
1493 for entry in run.data[k]:
1494 if entry.startlb==0 and entry.lastlb==0:
1495 continue
1496
1497 val,valerr = entry.value
1498 ref = run.data[refkey].atLB(entry.startlb)[0].value[0]
1499 stat = run.data[statkey].atLB(entry.startlb)[0].value
1500
1501 lastlb = min(entry.lastlb,run.lastlb)
1502 lbs = range(entry.startlb,lastlb+1)
1503 nlb = len(lbs)
1504
1505 xvec += [nlb]
1506 yvec += [(val,valerr)]# * nlb
1507 yvecSt += [stat]# * nlb
1508 bsidx += [idx] * nlb
1509 idx += 1
1510
1511 # compute average if BS has been determined
1512 if ref < 10:
1513 vave += nlb * val
1514 eave += nlb * val**2
1515 iave += nlb
1516 isOK = True
1517
1518 if not isOK:
1519 s += '<td>n.a.</td>'
1520 continue
1521
1522 if iave>0:
1523 vave /= float(iave)
1524 rad = eave/iave - vave*vave
1525 if rad>=0:
1526 eave = math.sqrt(rad)
1527 else:
1528 eave = 0
1529 else:
1530 vave = -1
1531
1532 ymin = vave - 3*eave
1533 ymax = vave + 3*eave
1534
1535 if ymin >= ymax:
1536 ymin = ymin*0.9
1537 ymax = ymin*1.1
1538 if ymin >= ymax:
1539 ymin = -0.1
1540 ymax = 0.1
1541
1542 if ymin==ymax:
1543 delta = 0.1*abs(ymax)
1544 else:
1545 delta = 0.1*(ymax-ymin)
1546 ymin -= delta
1547 ymax += delta
1548
1549
1550 bstype = 'pos'
1551 if 'Sig' in k:
1552 bstype = 'width'
1553 elif 'Tilt' in k:
1554 bstype = 'tilt'
1555 bstype += k[k.find('-'):]
1556
1557 histoText = 'Average beam spot %s: (%.4g +- %.1g) mm' % (bstype, vave, eave)
1558
1559 path = makeBSPlots( xvec=xvec, yvec=yvec,
1560 xtitle = 'Luminosity block number', ytitle = '%s beamspot %s (mm)' % (onloffltype, bstype),
1561 histname = '%s_vs_lb_run_%i' % (k.replace(':','_').replace('-','_'), run.runNr),
1562 histtitle = '%s beamspot %s per LB for run %i' % (onloffltype, bstype, run.runNr),
1563 datapath = QC.datapath, ymin = ymin, ymax = ymax, printText = histoText )
1564
1565
1566 # create window and tooltip
1567 wincontent = '<table class=&quot;outer&quot; style=&quot;padding: 5px&quot;><tr><td>'
1568 wincontent += '<strong><b>%s beamspot %s per LB for run %i:</b></strong><br><font size=&quot;-1&quot;><font color=&quot;#888888&quot;>(Begin/end of run: %s)</font></font><hr color=&quot;black&quot; size=1>' % (onloffltype, bstype, run.runNr, run.timestr('html', run.runNr != Run.runnropen))
1569 wincontent += '<table style=&quot;padding: 0px&quot;><tr><td>'
1570 wincontent += '<img src=&quot;%s&quot; align=&quot;left&quot;>' % (path)
1571 wincontent += '</td></tr></table>'
1572 wincontent += '<hr color=&quot;black&quot; size=1>'
1573
1574 wincontent += '<table style=&quot;width: auto; border: 0px solid; border-width: margin: 0 0 0 0; border-spacing: 0px; border-collapse: separate; padding: 0px; font-size: 90%; vertical-align:top; &quot;>'
1575 wincontent += '<tr><th style=&quot;text-align:right&quot;>LB</th><th style=&quot;text-align:right&quot;>&nbsp;&nbsp;&nbsp;Start time<br> (%s)</th><th style=&quot;text-align:right&quot;>&nbsp;&nbsp;&nbsp;Duration<br>(sec)</th><th style=&quot;text-align:right&quot;>&nbsp;&nbsp;&nbsp;Beamspot %s<br>(mm)</th><th style=&quot;text-align:right&quot;>&nbsp;&nbsp;&nbsp;Fit&nbsp;status</th>' % (QC.tzdesc(),bstype)
1576 wincontent += '</tr><tr style=&quot;background:%s&quot;>' % '#eeeeee'
1577 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
1578 lb=idx+1
1579 timetuple = time.localtime(lbtime/1.E9) if QC.localtime else time.gmtime(lbtime/1.E9)
1580 wincontent += '<td style=&quot;text-align:right&quot;>&nbsp;&nbsp;%s</td>' % lb
1581 wincontent += '<td style=&quot;text-align:right&quot;>&nbsp;%s</td>' % time.strftime("%X",timetuple)
1582 wincontent += '<td style=&quot;text-align:right&quot;>%.2f</td>' % ((float(lbendtime)-float(lbtime))/1.E9)
1583 wincontent += '<td style=&quot;text-align:right&quot;>%.4g &plusmn; %.2g</td>' % yvec[bsidx[idx]]
1584 wincontent += '<td style=&quot;text-align:right&quot;>%i</td>' % yvecSt[bsidx[idx]]
1585
1586 if idx%2!=0:
1587 col = '#eeeeee'
1588 else:
1589 col = '#ffffff'
1590 wincontent += '</tr><tr style=&quot;background:%s&quot;>' % col
1591 if run.runNr == Run.runnropen: # run still ongoing
1592 wincontent += '<tr><td style=&quot;text-align:left&quot;colspan=&quot;3&quot;><i>&nbsp;&nbsp;Run still ongoing ...</i></td></tr>'
1593 wincontent += '</tr></table>'
1594
1595 wincontent += """<hr color=&quot;red&quot; size=1><font color=&quot;#777777&quot;><font size=&quot;-1&quot;><i><font size=&quot;-2&quot;>Created by AtlRunQuery on: %s</font></i></font></td></tr></table><script type=&quot;text/javascript&quot;></script></body></html>""" % str(datetime.datetime.now())
1596 wincontent += '</td></tr></table>'
1597
1598 openwincmd = '<a href="javascript:openWindow('
1599 openwincmd += "'Print','<!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;>"
1600 openwincmd += "<html><head><title>Run query result for the %s beamspot</title><LINK href=&quot;html/atlas-runquery-lb.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;></head>" % (onloffltype.lower())
1601 openwincmd += "<body><table style=&quot;font-family: sans-serif; font-size: 85%&quot;>"
1602 openwincmd += wincontent
1603 openwincmd += "</table></body></html>"
1604 openwincmd += "')\">"
1605
1606 # plot
1607 fullprint = '<table class="triggerlinktable">'
1608 fullprint += '<tr><td colspan="2"><img src="%s" align="left" width="90px"></td></tr>' % path
1609 fullprint += '<tr><td colspan="2"></td></tr>'
1610 if isOK:
1611 fullprint += '<tr><td style="text-align:left">Average&nbsp;%s:</td></tr><tr><td style="text-align:left"><nobr>&nbsp;%0.3g&nbsp;&plusmn;&nbsp;%.2g&nbsp;(RMS)</nobr></td></tr>' % (bstype, vave, eave)
1612 fullprint += '</table>'
1613
1614 # put into html page
1615 s += '<td class="showTip OFLBS stream" style="text-decoration:none; text-align: right">%s%s</a></td>' % (openwincmd, fullprint)
1616 continue
1617
1618 # -----------------------------------------------------------------------------------------------------------------------
1619
1620 if "STR:" == k[0:4]:
1621 streamName = k[4:]
1622 if 'n.a.' in v:
1623 s += '<td class="tdna">n.a.</td>'
1624 continue
1625
1626 # compute approximative output rate in Hz
1627 durInSec = (run.eor-run.sor)/1.0E9
1628 rate = 'n.a.&nbsp;Hz'
1629 try:
1630 if durInSec > 0:
1631 rate = '%.3f&nbsp;Hz' % (v[0]/durInSec)
1632 except ValueError:
1633 pass
1634 strevents = v[0]
1635 strsize = v[1]
1636 # add relative fraction (only if not calibrtion string)
1637 fracstr = ''
1638 if 'calibration' not in k:
1639 fracstr = '%.1f%%,' % (float(strevents)/sumstrnev*100)
1640
1641
1642 ev = {}
1643 xvec = []
1644 xvecStb = []
1645 yvecN = []
1646 yvecR = []
1647 nevtot = 0
1648
1649 # statistics
1650 maxrate = -1
1651 averate = 0
1652 nc = 0
1653
1654 # insert events per LB
1655 lbrecinfo = run.stats[k]['LBRecInfo']
1656
1657 isPhysicsStream = lbrecinfo is not None and len(lbrecinfo)>0
1658 if isPhysicsStream: # only for physics stream we have LB wise information
1659 ev = dict(lbrecinfo)
1660 for lb in ev:
1661 ev[lb]=0
1662 for lb,nev in lbrecinfo:
1663 ev[lb] += nev
1664 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
1665 lb=idx+1
1666 nev = 0
1667 if lb in ev:
1668 nev = ev[lb]
1669 xvec.append(lb)
1670 yvecN.append(nev)
1671 yvecR.append(0)
1672 nevtot += nev
1673 try:
1674 if float(lbendtime)-float(lbtime) > 0:
1675 yvecR[-1] = nev/((float(lbendtime)-float(lbtime))/1.E9)
1676 except ValueError:
1677 pass
1678
1679
1680 # find range with stable beams (requires LHC information to be available)
1681 hasStableBeamsInfo, xvecStb = run.getStableBeamsVector()
1682
1683 # prepare pop-up window
1684 wincontent = '<table class=&quot;outer&quot; style=&quot;padding: 5px&quot;>'
1685 wincontent += '<tr><td><b>Number of events and rates per LB for stream %s run %i:</b><br><font size=&quot;-1&quot;><font color=&quot;#888888&quot;>(Begin/end of run: %s)</font></font><hr color=&quot;black&quot; size=1>' % (streamName, run.runNr, run.timestr('html', run.runNr != Run.runnropen))
1686
1687 # create plot
1688 pathN = makeLBPlot( xvec, xvecStb, yvecN, 'Luminosity block number', 'Number of events / LB', '',
1689 'nev_vs_lb_str_%s_run_%i' % (streamName, run.runNr),
1690 'N events per LB in stream "%s", run %i' % (streamName, run.runNr),
1691 QC.datapath, 'Total number of events: %i' % nevtot )
1692 pathR = makeLBPlot( xvec, xvecStb, yvecR, 'Luminosity block numer', 'Event rate [Hz] / LB', '',
1693 'rate_vs_lb_str_%s_run_%i' % (streamName, run.runNr),
1694 'Event rate per LB in stream "%s", run %i' % (streamName, run.runNr),
1695 QC.datapath )
1696 wincontent += '<table style="padding: 0px">\n<tr><td>'
1697 wincontent += '<img src="%s" width="350">' % pathN.split('/')[-1]
1698 wincontent += '</td><td>'
1699 wincontent += '<img src="%s" width="350">' % pathR.split('/')[-1]
1700 wincontent += '</td></tr></table>\n'
1701 wincontent += '<hr color="black" size=1>\n'
1702 wincontent += '<table class="lb">\n'
1703 wincontent += '<tr><th>LB</th><th>Start time (%s)</th><th>Duration (sec)</th><th>Nevents</th><th>Cumul. Nevents</th><th>Rate [Hz]</th>' % QC.tzdesc()
1704 if hasStableBeamsInfo:
1705 wincontent += '<th>Stable beams</th>'
1706 wincontent += '</tr>\n<tr style="background:%s">' % '#eeeeee'
1707 sumnev = 0
1708 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
1709 lb=idx+1
1710 nev = 0
1711 if lb in ev:
1712 nev = ev[lb]
1713 sumnev += nev
1714 stbBeams = '&minus;'
1715 if yvecR[idx] > 0:
1716 averate += yvecR[idx]
1717 if yvecR[idx] > maxrate:
1718 maxrate = yvecR[idx]
1719 nc += 1
1720 if lb in xvecStb:
1721 stbBeams = 'T'
1722
1723 timetuple = time.localtime(lbtime/1.E9) if QC.localtime else time.gmtime(lbtime/1.E9)
1724 wincontent += '<td>%s</td><td>%s</td><td>%.2f</td><td>%i</td><td>%i</td><td>%.3g</td>' % (lb, time.strftime("%X",timetuple), (float(lbendtime)-float(lbtime))/1.E9, int(yvecN[idx]), sumnev, yvecR[idx])
1725 if hasStableBeamsInfo:
1726 wincontent += '<td>%s</td>' % stbBeams
1727 if idx%2!=0:
1728 col = '#eeeeee'
1729 else:
1730 col = '#ffffff'
1731 wincontent += '</tr>\n<tr style="background:%s">' % col
1732
1733 # compute max and averages
1734 if nc>0:
1735 averate /= float(nc)
1736
1737 if run.runNr == Run.runnropen: # run still ongoing
1738 wincontent += '<tr><td style="text-align:left"colspan="3"><i>&nbsp;&nbsp;Run still ongoing ...</i></td></tr>\n'
1739 wincontent += '</tr></table>\n'
1740 wincontent += '<hr color="red" size=1><font color="#777777"><font size="-1"><i><font size="-2">Created by AtlRunQuery on: %s</font></i></font></td></tr></table><script type="text/javascript"></script></body></html>' % str(datetime.datetime.now())
1741 wincontent += '</td></tr></table>'
1742 else:
1743 wincontent = ""
1744
1745 # the output
1746 tooltipkey = "STROV_%i_%s" % (run.runNr, streamName)
1747
1748 physStrOnlyInfo = ""
1749 if isPhysicsStream:
1750 maxrate = 'max:&nbsp;%.2f&nbsp;Hz' % (maxrate)
1751 averate = 'ave:&nbsp;%.2f&nbsp;Hz' % (averate)
1752 physStrOnlyInfo = "%s,<br>%s,<br>%s,&nbsp;" % (maxrate, averate, fracstr)
1753 debugStrLink = ""
1754 if 'debug_' in k:
1755 debugStrLink = '&nbsp;<a href="https://trigmon.web.cern.ch/trigmon/ResultsAnalysis/RESULTS/%i/00%i_%s" target=_blank><font color="#993333">[MON]</font></a>' % (time.gmtime(run.sor/1.E9)[0], run.runNr, k[4:].strip())
1756 evtsize = ',<br>%s/evt' % filesize(float(strsize)/float(strevents)) if (strevents>0) else ""
1757 tdcontent = '%s <BR><font size="-2">(%s%s/run%s%s)' % (addKommaToNumber(strevents), physStrOnlyInfo, filesize(strsize), evtsize, debugStrLink)
1758
1759 # wrap content in div with tooltip
1760 tdcontent = '<div class="showTip %s stream" style="display:inline;cursor:pointer">%s</div>' % (tooltipkey, tdcontent)
1761
1762 if isPhysicsStream:
1763 # create popup page and wrap content into href
1764 filename = HU.CreatePopupHtmlPage( 'streamov_%i_%s' % (run.runNr, streamName), HU.WrapIntoHTML(wincontent, title="%s Stream Content" % streamName) )
1765 tdcontent = '<a class="externalWindow" style="text-decoration:none" href="%s">%s</a>' % (filename, tdcontent)
1766
1767 s += '<td style="text-decoration:none">%s</td>' % (tdcontent)
1768
1769 continue
1770
1771 # -----------------------------------------------------------------------------------------------------------------------
1772
1773 if k=="TriggerMenu":
1774 chains = run.splitTriggerChains(v)
1775 if len(chains)==0:
1776 s += '<td></td>'
1777 elif len(chains)==1:
1778 s += '<td style="min-width:300px"><font size="-2">%s</font></td>' % ( chains )
1779 elif len(chains)==2:
1780 s += '<td style="min-width:300px"><font size="-2">%s<hr color="gray" size=1>%s</font></td>' % ( chains )
1781 else:
1782 s += '<td style="min-width:300px"><font size="-2">%s<hr color="gray" size=1>%s<hr color="gray" size=1>%s</font></td>' % ( chains )
1783 continue
1784
1785 # -----------------------------------------------------------------------------------------------------------------------
1786
1787 if k=="TriggerRates":
1788 if type(v)==str:
1789 s += '<td>%s</td>'%v
1790 else:
1791 tablecontent = ""
1792 triggergroups,imgpaths,openwincmds = HU.createRatePopupWindow(v,run)
1793 for idx,(trgroup,imgpath,openwincmd) in enumerate(zip(triggergroups,imgpaths,openwincmds)):
1794 tooltipkey = "TrRate_Set%i_%i" % (idx,run.runNr)
1795 contentpage = "%s/popupContent_trRates_%i_%i.html" % (QC.datapath, run.runNr, idx)
1796
1797 if idx!=0:
1798 tablecontent += ' <tr><td colspan="2"><hr color="gray"></td></tr>'
1799 imgcontent = '<img src="%s" align="center" width="90px"><br>' % imgpath
1800 imagerow = '<div class="showTip %s ratespopup" id="%s" style="display:inline;cursor:pointer;font-size:80%%;">%s</div>' % (tooltipkey, contentpage, imgcontent)
1801 tablecontent += ' <tr><td colspan="2" >%s</td></tr>' % imagerow
1802 for tr,avr in trgroup:
1803 tablecontent += ' <tr><td>%s</td><td>: %3.1f Hz</td></tr>' % (tr,avr)
1804 s+="<td><table class='ratestable'>\n%s\n </table></td>" % tablecontent
1805 continue
1806
1807 # -----------------------------------------------------------------------------------------------------------------------
1808
1809 if "Datasets" == k:
1810 # separate datasets into stream types
1811 streamtypes = ['physics_','express_','calibration_','debug_', 'debugrec_']
1812 steptypes = ['.daq.','.recon.','.merge.','other','Reproc' ]
1813 datatypes = ['.RAW','.DRAW','.ESD.','.DESD','.AOD.','.TAG.','.TAG_COMM.','.HIST.','.NTUP','other']
1814 vetotypes = ['_TMP']
1815 shownlist = []
1816
1817 s += '<td>'
1818 s += '<table class="datasettable">'
1819 hrline = ''
1820 allcafdsnames = ''
1821 first = True
1822 for stype in streamtypes:
1823 for step in steptypes:
1824 for dtype in datatypes:
1825 selectedds = {}
1826 for ds in v:
1827 if (stype in ds[0] and step in ds[0] and dtype in ds[0]) or (stype in ds[0] and stype == 'debug_' and step == 'other' and (dtype in ds[0] or dtype == 'other')) and not ds[0] in shownlist:
1828 vetoed = False
1829 for veto in vetotypes:
1830 if veto in ds[0]:
1831 vetoed = True
1832 break
1833 if not vetoed:
1834 # number of files, size, events
1835 st = ['&nbsp;%s&nbsp;files' % (prettyNumber(ds[4]))]
1836 st += ['&nbsp;%s' % (filesize(ds[5]))]
1837 if ds[6] == 0:
1838 st += ['&nbsp;unkn.&nbsp;evts&nbsp;']
1839 else:
1840 st += ['&nbsp;%s&nbsp;evts&nbsp;' % (prettyNumber(ds[6]))]
1841 selectedds[ds[0]] = st
1842 # replication status
1843 if 'replicate:done' in ds[2]:
1844 selectedds[ds[0]] += [True]
1845 else:
1846 selectedds[ds[0]] += [False]
1847 if ds[3] == 'DONE':
1848 selectedds[ds[0]] += [True]
1849 else:
1850 selectedds[ds[0]] += [False]
1851 selectedds[ds[0]] += [ds[7]] # add dataset creation time
1852 shownlist.append(ds[0])
1853
1854 if not selectedds:
1855 continue
1856 dsnames = selectedds.keys()
1857 dsnames.sort()
1858 if not first:
1859 s += hrline
1860 first = False
1861 s += '<tr><td colspan="1"><font color="#666666"><i>[&nbsp;Stream&nbsp;type&nbsp;+&nbsp;processing&nbsp;step&nbsp;+&nbsp;data&nbsp;type:&nbsp;<b>%s</b>&nbsp;+&nbsp;<b>%s</b>&nbsp;+&nbsp;<b>%s</b>&nbsp;]</i> </font></td></tr>' % (stype, step, dtype)
1862 for dsname in dsnames:
1863 # build AMI link to dataset
1864 dsnspl = dsname.split('.')
1865 lk = "https://ami.in2p3.fr/AMI/servlet/net.hep.atlas.Database.Bookkeeping.AMI.Servlet.Command?Converter=/AMIXmlToAMIProdHtml.xsl&Command=FormBrowseDatasetPerParameter+-runNumber%3D"
1866 project = dsnspl[0]
1867 runNum = dsnspl[1]
1868 stream = dsnspl[2]
1869 format = dsnspl[4]
1870 s += '<tr><td>'
1871 s += '<a href="https://ami.in2p3.fr/AMI/servlet/net.hep.atlas.Database.Bookkeeping.AMI.Servlet.Command?Converter=/AMIXmlToAMIProdHtml.xsl&Command=FormBrowseDatasetPerParameter+-runNumber%3D'
1872 s += runNum + "+-dataType=" + format + "+-projectName=" + project + "+-streamName=" + stream
1873 s += '" target="_blank" title="AMI dataset information">'
1874 s += dsname + '</td>'
1875 res = selectedds[dsname]
1876 s += '<td style="text-align:right"><font color="#005500">&nbsp;[</font></td>'
1877 for st in res[0:3]:
1878 s += '<td style="text-align:right"><font color="#005500">%s</font></td>' % st
1879 s += '<td style="text-align:right"><font color="#005500">]</font></td>'
1880 if res[3]:
1881 if Run.showCAFLinks:
1882 s += '<td><a href="javascript:openPageWindow('
1883 s += "'data/%s.html','%s')" % (dsname,dsname)
1884 s += '"title="Check which files of this dataset are available on ATLCAL disk pool">'
1885 s += '<font color="#BB0517">&nbsp;[&nbsp;on&nbsp;CAF&nbsp;]</font></a></td>'
1886
1887 # get age of file in hours
1888 deltat = (datetime.datetime.utcnow() - res[5])
1889 deltat = deltat.days*24.*3600. + deltat.seconds
1890 allcafdsnames += dsname + '@' + '%g' % deltat + ','
1891 else:
1892 s +='<td><font color="#BB0517">&nbsp;[&nbsp;on&nbsp;CAF&nbsp;]</font></td>'
1893 else:
1894 s += '<td></td>'
1895 if res[4]:
1896 lk = '<a href="https://ami.in2p3.fr/AMI/servlet/net.hep.atlas.Database.Bookkeeping.AMI.Servlet.Command?Command=FormGetDQ2InfoPerDataset+-logicalDatasetName%3D%22' + dsname + '%22&Converter=%2FAMIXmlToProdFrameHtml.xsl" target="_blank" title="DQ2 information (via AMI) for dataset: ' + dsname + '">'
1897 s += '<td>%s<font color="#153EBB">&nbsp;[&nbsp;in&nbsp;DDM&nbsp;]</font></a></td>' % lk
1898 else:
1899 s += '<td></td>'
1900
1901 s += '</tr>'
1902 if dtype != datatypes[-1]:
1903 hrline = '<tr><td colspan="8"><hr style="width:100%; background-color: #BBBBBB; height:1px; margin-left:0; border:0"/></td>'
1904 else:
1905 hrline = ''
1906
1907 if step != steptypes[-1]:
1908 hrline = '<tr><td colspan="8"><hr style="width:100%; background-color: #666666; height:2px; margin-left:0; border:0"/></td>'
1909 if stype != streamtypes[-1]:
1910 hrline = '<tr><td colspan="8"><hr style="width:100%; background-color: #6D7B8D; height:3px; margin-left:0; border:0"/></td>'
1911 # sanity check
1912 s_ = ''
1913 for ds in v:
1914 if 'TMP.' not in ds[0] and ds[0] not in shownlist:
1915 s_ += '<tr><td colspan=8>' + ds[0] + '</td></tr>'
1916 if s_:
1917 s += '<tr><td colspan="8"><hr style="width:100%; background-color: #EE0000; height:3px; margin-left:0; border:0"/></td>'
1918 s += '<tr><td colspan=8><font color="#EE0000"><i>Remaining, unassigned datasets:</i></font></td></tr>'
1919 s += s_
1920
1921 # close table
1922 s += '</table>\n'
1923 s += '</td>'
1924
1925 # call subprocesses
1926 if allcafdsnames:
1927 subprocess.Popen('python subproc.py caf %s' % (allcafdsnames[:-1]), shell=True)
1928
1929 continue
1930
1931 # -----------------------------------------------------------------------------------------------------------------------
1932
1933 if 'HLT PSK' == k:
1934 # add another column with links to trigger menu for all SMK and PSKs combinations
1935 linklist = run.stats['PSK']['blocks']
1936 linkRun12 = (
1937 '<a href="https://atlas-trigconf.cern.ch/run/smkey/{smk}/l1key/{l1psk}/hltkey/{hltpsk}/" target="_blank" '
1938 'title="L1: \'{l1name}\', HLT \'{hltname}\'. '
1939 'You can obtain the full trigger menu corresponding to SMK={smk} and prescale keys L1={l1psk}, HLT={hltpsk} in an independent window"'
1940 '>{l1psk}&nbsp;|&nbsp;{hltpsk}</a>'
1941 )
1942 linkRun3L1 = (
1943 '<a href="https://atlas-triggertool.web.cern.ch/db/{db}/smk/{smk}/l1psk/{l1psk}/" target="_blank" '
1944 'title="L1: \'{l1name}\'. You can obtain the full trigger menu corresponding to SMK={smk} and L1 prescale key {l1psk} in an independent window"'
1945 '>{l1psk}</a>'
1946 )
1947 linkRun3HLT = (
1948 '<a href="https://atlas-triggertool.web.cern.ch/db/{db}/smk/{smk}/hltpsk/{hltpsk}/" target="_blank" '
1949 'title="HLT: \'{hltname}\'. You can obtain the full trigger menu corresponding to SMK={smk} and HLT prescale key {l1psk} in an independent window"'
1950 '>{hltpsk}</a>'
1951 )
1952 if linklist:
1953 if len(linklist)<=15:
1954 ncol = 1
1955 elif len(linklist)<=30:
1956 ncol = 2
1957 else:
1958 ncol = 3
1959 if len(linklist)<=15:
1960 nrow = len(linklist)
1961 elif len(linklist)<=45:
1962 nrow = 15
1963 else:
1964 nrow = (len(linklist)+2)//3
1965
1966 s += '<td align="center"><table class="triggerlinktable" align="center">'
1967 s += '<tr>'
1968 for x in range(ncol):
1969 s += '<td style="text-align:center;font-weight:bold" colspan="3">LB&nbsp;range</td><td style="text-align:center;font-weight:bold">L1&nbsp;&nbsp;&nbsp;HLT</td>'
1970 s += '</tr>'
1971
1972 for row in range(nrow):
1973 s += '<tr>'
1974 for col in range(ncol):
1975 entry = row + col*nrow
1976 if entry>=len(linklist):
1977 continue
1978 link = dict(zip( ("startlb", "endlb", "l1psk", "hltpsk", "l1name", "hltname"),linklist[entry]))
1979 link.update({
1980 "smk" : run.result["SMK"],
1981 "db" : "dev1_i8" if int(run.result["SMK"]) < 3000 else "run3"
1982 })
1983 s += f'<td style="padding-left: 0.8em">{link["startlb"]}</td><td>&minus;</td><td>{link["endlb"]}:&nbsp;</td>'
1984 if run.lhcRun < 3:
1985 cellContent = linkRun12.format(**link)
1986 else:
1987 cellContent = linkRun3L1.format(**link) + "&nbsp;|&nbsp;" + linkRun3HLT.format(**link)
1988 s += f'<td style="border-right: 1px solid gray; padding-right: 0.8em">{cellContent}</td>'
1989 s += '</tr>'
1990 s += '</table>'
1991 s += '<hr style="width:100%; background-color: #AAAABB; height:1px; margin-left:0; border:0"/>'
1992 s += '<a href="https://atlas-trigconf.cern.ch/psevo/%i/" target="_blank" title="Obtain prescale evolution for all L1/L2/EF chains of this run in independent window"><font size="-2"><i>Prescale&nbsp;evolution...</i></font></a>' % run.runNr
1993 s+='</td>'
1994 else:
1995 s += '<td style="text-align:center">n.a.</td>'
1996 continue
1997
1998 # -----------------------------------------------------------------------------------------------------------------------
1999
2000 if 'BGS Key' == k:
2001 if v!='n.a.':
2002 smk = int(run.result["SMK"])
2003 bgskOffset = 10000 if (smk<3000 and run.lhcRun==3) else 0
2004
2005 if len(run.stats['BGS Key' ]['blocks'])>0:
2006 s += '<td align="center"><table class="triggerlinktable" align="center"><tr><td style="text-align:left;font-weight:bold" colspan="3">LB&nbsp;range</td><td style="text-align:right;font-weight:bold">BGS</td></tr>'
2007 for bgskey, lbbeg, lbend in run.stats['BGS Key' ]['blocks']:
2008 s += '<tr><td style="text-align:right">%i</td><td style="text-align:right">&minus;</td><td style="text-align:right">%i:&nbsp;</td>' % (lbbeg, lbend-1)
2009 cellContent = (
2010 f'&nbsp;<a href="https://atlas-trigconf.cern.ch/bunchgroups?key={bgskey+bgskOffset}" target="_blank" '
2011 f'title="Obtain bunch group description for BGS Key={bgskey} in independent window"'
2012 f'>{bgskey}</a>'
2013 )
2014 s += f'<td>{cellContent}</td></tr>'
2015 s += '</table>'
2016 s+='</td>'
2017 else:
2018 s += '<td style="text-align:center">n.a.</td>'
2019 else:
2020 s += '<td class="tdna">n.a.</td>'
2021 continue
2022
2023 # -----------------------------------------------------------------------------------------------------------------------
2024
2025 if "SMK" == k:
2026 if v=='n.a.':
2027 s += '<td class="tdna">n.a.</td>'
2028 else:
2029 namecomment = '<div style="font-size:80%%;color:#488AC7"><b>%s</b> (v.%i)</div><div style="width:200px;font-size:60%%;color:#777777;text-align:left">%s</div>' % run.stats['SMK']['info']
2030 s += '<td style="text-align: center;">%s<br>%s</td>' % (v,namecomment)
2031 continue
2032
2033 # -----------------------------------------------------------------------------------------------------------------------
2034
2035 if 'lar:runtype' in k or 'lar:format' in k:
2036 info = LArConfig(k.replace('lar:',''))
2037 try:
2038 s += '<td style="text-align: center">%s<br><font size="-2">(%s)</font></td>' % (v,info[int(v)])
2039 except ValueError:
2040 if v=='n.a.':
2041 s += '<td class="tdna">n.a.</td>'
2042 else:
2043 s += '<td style="text-align: right">%s</td>' % v
2044 continue
2045
2046 # -----------------------------------------------------------------------------------------------------------------------
2047
2048 if 'BPM' == k:
2049
2050 # compute average and RMS BPMs
2051 fullprint = '<table class="triggerlinktable" align="center">'
2052 keys = v.keys()
2053 keys.sort()
2054
2055 # time results
2056 xvec = []
2057 yvec = []
2058 toffset = int(run.sor/1.E9)
2059 deltat = int(run.eor/1.E9) - int(run.sor/1.E9)
2060
2061 # LB axis
2062 xveclb = []
2063 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
2064 lb=idx+1
2065 xveclb.append( [lbtime/1.E9-toffset, (float(lbendtime)-float(lbtime))/1.E9] )
2066
2067 ymin = +1e30
2068 ymax = -1e30
2069 legend = []
2070 for ik,key in enumerate(keys):
2071 y = 0
2072 y2 = 0
2073 xvec.append([])
2074 yvec.append([])
2075 for (val,dte) in v[key]:
2076 y += val
2077 y2 += val*val
2078
2079 ts = time.strptime( dte[:dte.rfind(':')] + '/UTC','%d-%m-%Y %H:%M:%S/%Z' )
2080 tsec = int(calendar.timegm(ts))
2081 xvec[-1].append(tsec - toffset) # time defined with respect to offset
2082 yvec[-1].append(val)
2083
2084 ic = len(v[key])
2085 if ic > 0:
2086 y /= float(ic)
2087 arg = y2/float(ic) - y*y
2088 if arg > 0:
2089 y2 = math.sqrt(arg)
2090 else:
2091 y2 = 0
2092 ymin = min(ymin,y - 1.5*y2)
2093 ymax = max(ymax,y + 1.5*y2)
2094
2095 # fill table
2096 vname = 'unknown'
2097 if 'B1' in key and 'hori' in key:
2098 vname = 'B1&nbsp;horiz.&nbsp;IP'
2099 lname = 'B1 horizont IP pos.'
2100 elif 'B1' in key and 'vert' in key:
2101 vname = 'B1&nbsp;vert.&nbsp;IP'
2102 lname = 'B1 vertical IP pos.'
2103 elif 'B2' in key and 'hori' in key:
2104 vname = 'B2&nbsp;horiz.&nbsp;IP'
2105 lname = 'B2 horizontal IP pos.'
2106 elif 'B2' in key and 'vert' in key:
2107 vname = 'B2&nbsp;vert.&nbsp;IP'
2108 lname = 'B2 vertical IP pos.'
2109 legend.append( lname )
2110 fullprint += '<tr><td style="text-align:left">%s:&nbsp;</td><td>(</td><td style="text-align:right">&nbsp;%s</td><td style="text-align:left">&nbsp;&#177;&nbsp;</td><td style="text-align:left">%.4g</td><td>)&nbsp;um</td><td>&nbsp;&nbsp;&nbsp;</td>' % (vname, ('%.4g' % y).replace('-','&minus;'), y2)
2111
2112 if ik == 0:
2113 fullprint += '<td rowspan="4">REPLACEME</td>'
2114 fullprint += '</tr>'
2115
2116 # write to file (as text and TGraphs)
2117 bpmrootfilename = QC.datapath + '/bpm_output_run%i.root' % run.runNr
2118 SaveGraphsToFile( bpmrootfilename, keys, xvec, yvec, "TimeOffset", toffset )
2119
2120 bpmtextfilename = QC.datapath + '/bpm_output_run%i.txt' % run.runNr
2121 bpmout = open( bpmtextfilename, 'w' )
2122
2123 bpmout.write( '# BPM Output for run %i\n' % run.runNr )
2124 bpmout.write( '# Start - end of run: %s [UTC]\n' % run.timestr('txt') )
2125 bpmout.write( '# Time offset applied below in seconds: %i\n' % int(toffset) )
2126 bpmout.write( '#\n' )
2127 bpmout.write( '# ---------------------------------------------------------------------------------\n' )
2128 for ik,key in enumerate(keys):
2129 bpmout.write( '# Output for variable: "%s"\n' % key )
2130 bpmout.write( '# Format: index / timestamp (seconds) wrt. begin of run / BPM position in microns\n' )
2131 bpmout.write( '#\n' )
2132 for i in range(len(xvec[ik])):
2133 bpmout.write( "%4i %9.2f %14.6f\n" % (i, xvec[ik][i], yvec[ik][i]) )
2134 bpmout.write( '#\n' )
2135 bpmout.write( '# ---------------------------------------------------------------------------------\n' )
2136 bpmout.close()
2137
2138 fullprint += '<tr><td colspan=8><hr style="width:100%; background-color:#999999; height:1px; margin-left:0; border:0"/></td></tr>'
2139 fullprint += '<tr><td colspan=8 style="text-align:left"><a href="%s" target="_blank" title="Tabulated BPM information versus time for run %i"><i>Click here for tabulated BPM values versus time...</i></a></td></tr>' % (bpmtextfilename, run.runNr)
2140 fullprint += '<tr><td colspan=8 style="text-align:left"><a href="%s" target="_blank" title="BPM information versus time for run %i as four TGraph objects in ROOT file"><i>Right-click to download ROOT file with TGraphs...</i></a></td></tr>' % (bpmrootfilename, run.runNr)
2141 fullprint += '</table>'
2142
2143 # make plot
2144 path = makeTimePlotList( xvec, xveclb, yvec, toffset, deltat, ymin, ymax,
2145 'Time of day (UTC)', 'Beam position (microns)', legend,
2146 'bp_vs_time_run_%i' % (run.runNr),
2147 'Beam position versus time of day for run %i' % (run.runNr),
2148 QC.datapath, '' )
2149
2150 replacetxt = '<img src="%s" align="left" width="70px">' % path
2151 fullprint = fullprint.replace('REPLACEME',replacetxt)
2152
2153 # create window and tooltip
2154 wincontent = '<table class=&quot;outer&quot; style=&quot;padding: 5px&quot;><tr><td>'
2155 wincontent += '<strong><b>LHC beam positions at IP verssu time for run %i:</b></strong><br><font size=&quot;-1&quot;><font color=&quot;#888888&quot;>(Begin/end of run: %s)</font></font><hr color=&quot;black&quot; size=1>' % (run.runNr, run.timestr('html', run.runNr != Run.runnropen))
2156 wincontent += '<table style=&quot;padding: 0px&quot;><tr><td>'
2157 wincontent += '<img src=&quot;%s&quot; align=&quot;left&quot;></td>' % path
2158 wincontent += '</td></tr></table>'
2159 wincontent += """<hr color=&quot;red&quot; size=1><font color=&quot;#777777&quot;><font size=&quot;-1&quot;><i><font size=&quot;-2&quot;>Created by AtlRunQuery on: %s</font></i></font></td></tr></table><script type=&quot;text/javascript&quot;></script></body></html>""" % str(datetime.datetime.now())
2160 wincontent += '</td></tr></table>'
2161
2162
2163 openwincmd = HU.OpenWindow(wincontent,title="Summary of LHC information")
2164
2165 # put into html page
2166 s += '<td style="text-decoration:none">%s<div class="showTip BPM stream" style="display:inline;cursor:pointer">%s</div></a></td>' % (tooltipkey, fullprint)
2167 continue
2168
2169 # -----------------------------------------------------------------------------------------------------------------------
2170
2171 if 'ofllumi:' in k:
2172
2173 if ofllumiFlag:
2174 continue
2175 ofllumiFlag = True
2176
2177 # find range with stable beams (requires LHC information to be available)
2178 hasStableBeamsInfo, xvecStb = run.getStableBeamsVector()
2179
2180 # find all channels that should be printed
2181 kref = []
2182 chans = []
2183 tags = []
2184 for kp in Run.ShowOrder:
2185 if 'ofllumi:' in kp.ResultKey:
2186 name, chanstr, tagstr = kp.ResultKey.split(':')
2187 kref.append(kp)
2188 chans.append(chanstr)
2189 tags.append(tagstr)
2190
2191 # get the channel names
2192 chanstr = []
2193 for ch in chans:
2194 ich = int(ch)
2195 if ich in OLCAlgorithms:
2196 chanstr.append(OLCAlgorithms[ich])
2197 else:
2198 chanstr.append('Unknown')
2199
2200 # insert events per LB
2201 xvec = []
2202 yvec = []
2203 peaklumi = []
2204 intlumi = []
2205 intlumiStb = []
2206 for ikp,kp in enumerate(kref):
2207 yvec.append([])
2208 peaklumi.append(-1)
2209 intlumi.append(0)
2210 intlumiStb.append(0)
2211 for entry in run.data[kp]:
2212 if entry.startlb == 0:
2213 continue
2214 val = entry.value if entry.value!='n.a.' and entry.value>0 else 0
2215 lastlb = min(entry.lastlb,run.lastlb)
2216 lbs = range(entry.startlb,lastlb+1)
2217 if ikp == 0:
2218 xvec += lbs
2219 yvec[-1] += len(lbs)*[float(val)]
2220
2221
2222 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
2223 lb=idx+1
2224 dt = (float(lbendtime)-float(lbtime))/1.E9
2225 for ich in range(len(chans)):
2226 tmp = yvec[ich]
2227 intlumi[ich] += tmp[idx]*dt/1000.0 # unit of yvec was: ub-1 s-1 -> nb-1
2228 if lb in xvecStb:
2229 intlumiStb[ich] += yvec[ich][idx]*dt/1000.0
2230
2231 yvec[ich][idx] *= 1.0 # unit of yvec was: ub-1 s-1, transform to: 10^30 cm-2s-1
2232 if yvec[ich][idx] > peaklumi[ich]:
2233 peaklumi[ich] = yvec[ich][idx]
2234
2235 # line to be printed in column
2236 fullprint_ = ''
2237 if hasStableBeamsInfo:
2238 for ich,ch in enumerate(chans):
2239 fullprint_ += 'Integrated&nbsp;(channel:&nbsp;%s):&nbsp;%0.4g<br>Stable&nbsp;B:&nbsp;%0.4g<br>' % (ch,intlumi[ich],intlumiStb[ich])
2240 histoText = 'Integr. lumi (channel: %i): %.4g nb-1 (all LBs) and %.4g nb-1 (stable beams)' % (0, intlumi[0],intlumiStb[0])
2241 else:
2242 for ich,ch in enumerate(chans):
2243 fullprint_ += 'Integrated&nbsp;(channel:&nbsp;%s):&nbsp;%0.4g<br>' % (ch,intlumi[ich])
2244 histoText = 'Integr. lumi (channel: %i): %.4g nb-1 (all LBs)' % (0, intlumi[0])
2245
2246 # make plot
2247 path = makeLBPlotList( xvec, xvecStb, yvec,
2248 'Luminosity block number', 'Offline luminosity (10^{30}cm^{-2}s^{-1})', chanstr,
2249 'ofllumi%s_vs_lb_run_%i' % (chans[0],run.runNr),
2250 'Offline lumi per LB for run %i' % (run.runNr),
2251 QC.datapath, histoText )
2252
2253 # create window and tooltip
2254 wincontent = '<table class=&quot;outer&quot; style=&quot;padding: 5px&quot;><tr><td>'
2255 wincontent += '<strong><b>Offline luminosity per LB for run %i:</b></strong><br><font size=&quot;-1&quot; color=&quot;#888888&quot;>(Begin/end of run: %s)</font>' % (run.runNr, run.timestr('html', run.runNr != Run.runnropen))
2256 wincontent += '<hr color=&quot;black&quot; size=1>'
2257 wincontent += '<table style=&quot;padding: 0px&quot;><tr><td>'
2258 wincontent += '<img src=&quot;%s&quot; align=&quot;left&quot;>' % path
2259 wincontent += '</td></tr></table>'
2260 wincontent += '<hr color=&quot;black&quot; size=1>'
2261 wincontent += '<table class=&quot;LB&quot;>'
2262 wincontent += '<tr><th>LB</th><th>Start time<br> (%s)</th><th>Duration<br>(sec)</th>' % QC.tzdesc()
2263 for ch in chanstr:
2264 wincontent += '<th>Inst. luminosity<br>(1e%s&nbsp;cm<sup>&minus;2</sup>s<sup>&minus;1</sup>)<br>[ %s ]</th>' % (run.instlumiunittxt,ch)
2265 wincontent += '<th>Stable beams</th>'
2266 wincontent += '</tr><tr style=&quot;background:%s&quot;>' % '#eeeeee'
2267 for idx,(lbtime,lbendtime) in enumerate(run.lbtimes):
2268 lb=idx+1
2269 stbBeams = '&minus;'
2270 if lb in xvecStb:
2271 stbBeams = 'T'
2272 timetuple = time.localtime(lbtime/1.E9) if QC.localtime else time.gmtime(lbtime/1.E9)
2273 wincontent += '<td>%i</td><td>%s</td><td>%.2f</td>' % (lb, time.strftime("%X",timetuple), (float(lbendtime)-float(lbtime))/1.E9)
2274 for ich in range(len(chans)):
2275 wincontent += '<td>%.4g</td>' % (yvec[ich][idx])
2276 wincontent += '<td>%s</td>' % stbBeams
2277 if idx%2!=0:
2278 col = '#eeeeee'
2279 else:
2280 col = '#ffffff'
2281 wincontent += '</tr><tr style=&quot;background:%s&quot;>' % col
2282 if run.runNr == Run.runnropen: # run still ongoing
2283 wincontent += '<tr><td style=&quot;text-align:left&quot;colspan=&quot;3&quot;><i>&nbsp;&nbsp;Run still ongoing ...</i></td></tr>'
2284 wincontent += '</tr></table>'
2285 wincontent += """<hr color=&quot;red&quot; size=1><font color=&quot;#777777&quot;><font size=&quot;-1&quot;><i><font size=&quot;-2&quot;>Created by AtlRunQuery on: %s</font></i></font></td></tr></table><script type=&quot;text/javascript&quot;></script></body></html>""" % str(datetime.datetime.now())
2286 wincontent += '</td></tr></table>'
2287
2288 openwincmd = HU.OpenWindow(wincontent,title="Run query result for online luminosity")
2289
2290 # line to be printed in column
2291 fullprint = '<table class="bcidtable">'
2292 fullprint += '<tr><td colspan="2"><img src="%s" align="left" width="90px"></td></tr>' % path
2293 if hasStableBeamsInfo:
2294 for ich in range(len(chans)):
2295 fullprint += '<tr><td style="text-align:left">Entire&nbsp;run:</td><td style="text-align:left">&nbsp;%0.4g&nbsp;%s<sup>&minus;1</sup></td></tr><tr><td style="text-align:left">Stable&nbsp;beams:</td><td style="text-align:left">&nbsp;%0.4g&nbsp;%s<sup>&minus;1</sup></td></tr><tr><td style="text-align:left">Peak&nbsp;lumi:</td><td style="text-align:left">&nbsp;%0.3g&nbsp;e%s&nbsp;cm<sup>&minus;2</sup>s<sup>&minus;1</sup></td></tr>' % (intlumi[ich], run.lumiunittxt, intlumiStb[ich], run.lumiunittxt, peaklumi[ich], run.instlumiunittxt)
2296 else:
2297 for ich in range(len(chans)):
2298 fullprint += '<td style="text-align:left">All&nbsp;LBs:</td><td style="text-align:left">&nbsp;%0.4g</td></tr>' % (intlumi[ich])
2299 fullprint += '</table>'
2300
2301 # put into html page
2302 s += '<td class="showTip OFLLumi stream" style="text-decoration:none; text-align: right">%s%s</a></td>' % (openwincmd, fullprint)
2303 continue
2304
2305 # -----------------------------------------------------------------------------------------------------------------------
2306
2307 if any( [ ('lhc:' in k and 'beamenergy' not in k),
2308 ('TorCurrent' in k),
2309 ('SolCurrent' in k),
2310 ('bs:' in k),
2311 ('Ready for physics' in k),
2312 ] ):
2313 res = []
2314 keys = []
2315
2316 # search unique ranges
2317 for entry in run.data[k]:
2318 if entry.startlb == 0:
2319 continue
2320 val = entry.value
2321
2322 try:
2323 val = float(val)
2324 if 'bs:' not in k and 'ofllumi:' not in k and 'beam1intensity' not in k and 'beam2intensity' not in k:
2325 val = round(val) # no floating points, unless it is 'bs'
2326 except ValueError:
2327 pass
2328
2329 # special treatment for E-beam = 7864
2330 if 'beamenergy' in k and val>=7864:
2331 val = 'ASYNC'
2332
2333 if not keys or res[-1] != val:
2334 if keys:
2335 keys[-1][1] = entry.startlb
2336 res.append ( val )
2337 keys.append( [entry.startlb, entry.endlb] )
2338 elif res[-1] == val:
2339 keys[-1][1] = entry.endlb
2340
2341
2342 if len(keys) > 1:
2343 s += '<td><table class="triggerlinktable" align="center">'
2344 for i, c in enumerate(keys):
2345 if int(c[0]) != int(c[1])-1:
2346 s += '<tr><td>LB&nbsp;</td><td style="text-align:right">%i</td><td style="text-align:right">&minus;</td><td style="text-align:right">%i:&nbsp;</td>' % (int(c[0]),int(c[1])-1)
2347 else:
2348 s += '<tr><td>LB&nbsp;</td><td style="text-align:right">%i</td><td style="text-align:right"></td><td style="text-align:right">:&nbsp;</td>' % (int(c[0]))
2349 try:
2350 val = float(res[i])
2351 if 'bs:' in k or 'beam1intensity' in k or 'beam2intensity' in k:
2352 vt = '%.4g' % abs(val)
2353 if val < 0:
2354 vt = '&minus;' + vt
2355 if 'e-' in vt:
2356 vt = vt.replace('e-','e&minus;')
2357 s += '<td style="text-align:right">%s</td></tr>' % vt
2358 elif 'ofllumi:' in k:
2359 s += '<td style="text-align:right">%g</td></tr>' % val
2360 else:
2361 s += '<td style="text-align:right">%i</td></tr>' % round(val)
2362 except ValueError:
2363 s += '<td style="text-align:left">%s</td></tr>' % res[i].strip()
2364 s += '</table></td>'
2365
2366 else:
2367 try:
2368 if 'bs:' in k:
2369 vt = '%.4g' % abs(float(v))
2370 if float(v) < 0:
2371 v = '&minus;' + vt
2372 else:
2373 v = vt
2374 if 'e-' in v:
2375 v = v.replace('e-','e&minus;')
2376 else:
2377 v = round(float(v))
2378 if 'beamenergy' in k and v >= 7864:
2379 v = 'ASYNC'
2380 else:
2381 v = '%i' % v
2382 except ValueError:
2383 pass
2384 s += '<td style="text-align:center;font-size: 85%%">%s</td>' % v
2385
2386
2387 if ('lhc:stablebeams' in k and 'lhc:beamenergy' in Run.ShowOrder and 'lhc:beammode' not in Run.ShowOrder) or 'lhc:beammode' in k:
2388 imgpath, xvec, yvec, ymax = HU.makeSummaryPlotForLHC(run)
2389 wincontent = HU.makeSummaryPageForLHC(run, yvec, imgpath)
2390 openwincmd = HU.OpenWindow(wincontent, 'Summary of LHC information')
2391 fullprint = '<table class="bcidtable">'
2392 fullprint += '<tr><td><img src="%s" align="left" width="90px"></td></tr>' % imgpath
2393 fullprint += '<tr><td style="text-align:left">Maximum&nbsp;intensities:<br>Beam&nbsp;1:&nbsp;%0.3g&nbsp;e11&nbsp;protons<br>Beam&nbsp;2:&nbsp;%0.3g&nbsp;e11&nbsp;protons</td></tr>' % (ymax[0], ymax[1])
2394 fullprint += '<tr><td style="text-align:left">Maximum&nbsp;beam&nbsp;energy:<br>%i&nbsp;GeV</td></tr>' % int(ymax[2])
2395 fullprint += '</table>'
2396 fullprint += '<span style="font-size: xx-small; color: #555555">[ <i>Numbers given for stable beam period (if applies)</i> ]</span>'
2397 # put into html page
2398 s += '<td class="showTip LHCSummary stream" style="text-decoration:none; text-align: left">%s %s </a></td>' % (openwincmd, fullprint)
2399
2400 continue
2401
2402 # -----------------------------------------------------------------------------------------------------------------------
2403
2404 # all others
2405 if v=='n.a.':
2406 s += '<td class="tdna">n.a.</td>'
2407 else:
2408 s += '<td style="text-align: right">%s</td>' % v
2409
2410
2411 s += "</tr>\n\n"
2412
2413
2416
2417 # here we start filling the tooltips. there are quite a lot and we should be a bit smarter about them.
2418 # For instance, there is no need to define the whole table for each single box
2419
2420 with timer("Tooltips"):
2421 createToolTips(run)
2422
2423 return s
2424
2425
2426
2428 import CoolRunQuery.html.AtlRunQueryHtmlUtils as HU
2429
2430 HU.CreateLBTooltip(run)
2431
2432 # DQ DEFECTS
2433 if 'DQ' in Run.ShowOrder:
2434 HU.CreateDQTooltip(run)
2435
2436 # stream overlaps
2437 for k in [k for k in Run.ShowOrder if k.Type==DataKey.STREAM and k.ResultKey in run.stats]:
2438 HU.CreateStreamOverlapTooltip(run, k)
2439
2440 # DQ (old)
2441 for data_key in Run.ShowOrder:
2442 k = data_key.ResultKey
2443 if not isDQ(k):
2444 continue
2445 if k not in run.stats:
2446 continue
2447 commentbox = ''
2448 for (dq,comment), start, end in run.stats[k]["blocks"]:
2449 if dq != 'n.a.':
2450 if not comment:
2451 comment = 'no comment'
2452 col = "#000000"
2453 if dq == 'R':
2454 col = "#AA0000"
2455 elif dq == 'G':
2456 col = "#006600"
2457 elif dq == 'Y':
2458 col = "#716309"
2459 if start == end-1:
2460 commentbox += '<tr style="color:%s"><td style="vertical-align:top;">LB&nbsp;</td><td style="text-align:right;vertical-align:top;">%s</td><td style="text-align:right;vertical-align:top;"></td><td style="text-align:right;vertical-align:top;">&nbsp;(%s)&nbsp;:&nbsp;</td><td style="text-align:left;vertical-align:top;"><i><strong><b>"%s"</b></strong></i></td></tr>' % (col,start,dq,comment)
2461 else:
2462 commentbox += '<tr style="color:%s"><td style="vertical-align:top;">LB&nbsp;</td><td style="text-align:right;vertical-align:top;">%s</td><td style="text-align:right;vertical-align:top;">&minus;</td><td style="text-align:right;vertical-align:top;">%s&nbsp;(%s)&nbsp;:&nbsp;</td><td style="text-align:left;vertical-align:top;"><i><strong><b>"%s"</b></strong></i></td></tr>' % (col,start,end-1,dq,comment)
2463 else:
2464 if start == end-1:
2465 commentbox += '<tr style="color:#222222"><td style="vertical-align:top;">LB&nbsp;</td><td style="text-align:right;vertical-align:top;">%s</td><td style="text-align:right;vertical-align:top;"></td><td style="text-align:right;vertical-align:top;">&nbsp;(n.a.)&nbsp;</td><td style="text-align:left;vertical-align:top;"></td></tr>' % (start)
2466 else:
2467 commentbox += '<tr style="color:#222222"><td style="vertical-align:top;">LB&nbsp;</td><td style="text-align:right;vertical-align:top;">%s</td><td style="text-align:right;vertical-align:top;">&minus;</td><td style="text-align:right;vertical-align:top;">%s&nbsp;(n.a.)&nbsp;</td><td style="text-align:left;vertical-align:top;"></td></tr>' % (start,end-1)
2468 if commentbox:
2469 sp = k.split(':')
2470 commentbox = '<strong><b>Comments&nbsp;for&nbsp;%s&nbsp;DQ&nbsp;channel&nbsp;"%s"&nbsp;in&nbsp;run&nbsp;%s:</b></strong>' % (sp[0],sp[1],run.runNr) + '<table>' + commentbox
2471 commentbox += '</table>'
2472 run.addToolTip( "dqcomm_%s_%i" % (k, run.runNr), commentbox)
2473
2474
2475 # trigger keys
2476 lbtrigtypes = { 'L1 PSK': ['L1&nbsp;PSK', 'L1K'], 'HLT PSK' : ['HLT&nbsp;PSK','HLTK'] }
2477 for lbtrigtype, c in lbtrigtypes.items():
2478 if lbtrigtype in Run.ShowOrder and 'blocks' in run.stats[lbtrigtype] and len(run.stats[lbtrigtype]['blocks'])>1:
2479 boxcontent = '<strong><b>%s&nbsp;evolved&nbsp;during&nbsp;run:</b></strong><br>' % c[0]
2480 boxcontent += '<table style="width: auto; border: 0px solid; border-width: margin: 0 0 0 0; 0px; border-spacing: 0px; border-collapse: separate; padding: 0px; font-size: 100%">'
2481 for item, start, stop in run.stats[lbtrigtype]['blocks']:
2482 boxcontent += '<tr><td>LB&nbsp;</td><td style="text-align:right">%s</td><td style="text-align:right">&minus;</td><td style="text-align:right">%s</td><td style="text-align:right">:&nbsp;%s</td></tr>' % (start,stop-1,item)
2483 boxcontent += '</table>'
2484 run.addToolTip("%s_%i" % (c[1], run.runNr), boxcontent)
2485
2486
2487 # OLC BCID
2488 if any([k for k in Run.ShowOrder if "olc:bcidmask" in k.ResultKey]):
2489 boxcontent = Run.TmpBoxContent
2490 if boxcontent:
2491 Run.addGlobalToolTip("OLCBCID_%i" % run.runNr, boxcontent)
2492
nlohmann::json json
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
Validity Range object.
Definition IOVRange.h:30
Basic time unit for IOVSvc.
Definition IOVTime.h:33
STL class.
__init__(self, iov, value, reject=False, valueForStorage=None)
getLBRanges(self, activeOnly=False)
addResult(self, iov, k, value, reject, valueForStorage=None)
addToolTip(self, var, content)
timestr(self, format='html', closed=True)
addResult(self, resDictKey, value, iov=None, reject=False, valueForStorage=None)
splitTriggerChains(self, chainlist)
addGlobalToolTip(cls, var, content)
STL class.
int lb
Definition globals.cxx:23
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
static std::vector< uint32_t > lbend
Definition iLumiCalc.h:39
Definition index.py:1