ATLAS Offline Software
Loading...
Searching...
No Matches
AtlRunQueryHTML.py
Go to the documentation of this file.
1#!/bin/env python
2
3# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
4#
5# ----------------------------------------------------------------
6# Script : AtlRunQueryHTML.py
7# Project: AtlRunQuery
8# Purpose: Library with HTML code creation
9# Authors: Andreas Hoecker (CERN), Joerg Stelzer (DESY)
10# Created: Apr 19, 2010
11# ----------------------------------------------------------------
12#
13
14import datetime
15
16from CoolRunQuery.AtlRunQueryRun import Run
17
18from CoolRunQuery.utils.AtlRunQueryUtils import addKommaToNumber, filesize
19from CoolRunQuery.utils.AtlRunQueryTimer import timer
20
21from CoolRunQuery.html.AtlRunQueryPageMaker import PageMaker as PM
22from CoolRunQuery.selector.AtlRunQuerySelectorBase import DataKey
23
24
26
27 @classmethod
28 def makePage(cls, pageinfo, doDQPickle=True):
29
30 # turn dict pageinfo into local variables
31 class PI:
32 pass
33 for x in pageinfo:
34 setattr (PI, x, pageinfo[x])
35
36
37 # put in link to cache
38 cachelink = PI.datapath[PI.datapath.rfind('arq_'):].rstrip('/')
39 cachelinkline = '[ <a style="font-size:11px;font-weight:100;font-style:normal" href="query.py?q=%s"><i>cached link to this result page</i></a> ]' % cachelink
40
41 extraReplace = [ ('<!--INSERTLINKCACHE-->', cachelinkline) ]
42
43 # START WITH THE PAGE
44 body = u''
45
46 # overall summary output if requested
47 if PI.makeSummary:
48 body += cls._OverallSummary( pageinfo )
49
50 # overall summary output if requested
51 if PI.makeDQSummary or PI.makeDQPlots:
52 body += cls._DQSummaryWrap( pageinfo, doPickle=doDQPickle )
53 extraReplace += [ ('<!--CONTACT_START-->.*<!--CONTACT_END-->', '<a href="http://consult.cern.ch/xwho/people/572921">Jessica Leveque</a>') ]
54
55 # initial information (query, selection steps, totNEv)
56 pageinfo['selstr'] = cls._makeSelectionSteps( pageinfo )
57 body += cls._InitialSummary( pageinfo )
58
59 if PI.makeDQSummary or PI.makeDQPlots:
60 # only the global tooltips are needed
61 body += cls._defineToolTips( pageinfo, globalOnly=True )
62 else:
63 # horizontal line
64 body += '<hr style="width:95%; background-color: #999999; height:1px; margin-left:14px; border:0">\n<p>\n'
65
66 # results table
67 pageinfo['sumstr'] = cls._makeYellowLine( pageinfo ) # the yellow summary line
68 body += cls._makeResultsTable( pageinfo )
69
70 # tooltips
71 body += cls._defineToolTips( pageinfo )
72
73 # bottom table
74 body += '<p>\n'
75 body += cls._makeBottomTable(pageinfo)
76
77 PM.makePage(body, PI.origQuery, extraReplace=extraReplace, removeExamples = (PI.makeDQSummary or PI.makeDQPlots))
78
79
80
81 @classmethod
82 def _makeResultsTable( cls, pageinfo ):
83 class PI:
84 pass
85 for x in pageinfo:
86 setattr (PI, x, pageinfo[x])
87
88 # run results table
89 resultstable = '<table class="resulttable" id="resulttable" style="margin-left: 13px">\n'
90
91 # table head
92 resultstable += Run.header()
93
94 # runs
95 with timer("print the runs"):
96 for r in PI.runlist:
97 with timer("print run %i" % r.runNr):
98 resultstable += str(r)
99
100 # summary
101 headlist = Run.headerkeys()
102 resultstable += " <tr class=\"space\"><td style=\"text-align: left;\" colspan=\"%i\"><font size=-2><i>Summary</i>:</font></td></tr>\n" % (len(headlist)-1)
103 resultstable += " <tr class=\"sum\">" + PI.sumstr + "</tr>\n"
104 resultstable += "</table>\n"
105 return resultstable
106
107
108 @classmethod
109 def _defineToolTips( cls, pageinfo, globalOnly=False ):
110 class PI:
111 pass
112 for x in pageinfo:
113 setattr (PI, x, pageinfo[x])
114
115 tooltips = u''
116 with timer("print the tooltips"):
117 dw_call = ['<script type="text/javascript">']
118 dw_call += ["if(dw_Tooltip.content_vars==undefined) {dw_Tooltip.content_vars = {}; };"]
119 dw_call += Run.GlobalTooltips
120 if not globalOnly:
121 for r in PI.runlist:
122 dw_call += r.tooltips
123 dw_call += ['</script>']
124 for ttip in dw_call:
125 tooltips += ttip + '\n'
126 return tooltips
127
128
129
130 # makes the bottom table (between yellow line and footer
131 @classmethod
132 def _makeBottomTable( cls, pageinfo ):
133 class PI:
134 pass
135 for x in pageinfo:
136 setattr (PI, x, pageinfo[x])
137
138 bottomTable = '<table cellspacing="0" style="color: #777777; font-size: 80%; margin-left: 13px">\n'
139 bottomTable += '<tr>\n<td valign="top">\n'
140 bottomTable += cls._Description()
141 bottomTable += '<tr><td colspan="2"><p><hr style="width:40%; color:#999999; background-color: #999999; height:1px; margin-left:0; border:0"/>\n<p>\n</td></tr>'
142
143 # XML output (official format for input to good-run lists)
144 bottomTable += cls._XMLFormat(PI.datapath, PI.xmlfilename, PI.xmlhtmlstr)
145
146 # pickled output
147 bottomTable += cls._PickledOutput(PI.datapath)
148
149 # ROOT output
150 bottomTable += cls._RootOutput(PI.roothtmlstr, PI.datapath)
151
152 # end of bottom table
153 bottomTable += '<tr><td colspan="2"><p>\n<p>\n</td></tr>'
154 bottomTable += '</table>'
155 return bottomTable
156
157
158 # create DQ efficiency summary
159 @classmethod
160 def _makeDQeff( cls, pageinfo ):
161 class PI:
162 pass
163 for x in ["dicsum", "dic", "datapath", "makeDQeff"]:
164 setattr (PI, x, pageinfo[x])
165
166 if PI.dicsum and PI.makeDQeff:
167 with timer("make the DQ efficiency summary"):
168 from CoolRunQuery.utils.AtlRunQueryDQUtils import MakeDQeffHtml
169 return MakeDQeffHtml( PI.dic, PI.dicsum, PI.datapath )
170 else:
171 return ''
172
173 # build the yellow summary line
174 @classmethod
175 def _makeYellowLine( cls, pageinfo ):
176 class PI:
177 pass
178 for x in ["dicsum"]:
179 setattr (PI, x, pageinfo[x])
180
181 with timer("make the yellow summary line"):
182 sumdic = {}
183 for key, summary in PI.dicsum.items():
184 if key.Type == DataKey.STREAM:
185 s = addKommaToNumber(summary[0])+' <BR><font size="-2">(%s)</font>' % filesize(summary[1])
186 elif key=='Run':
187 s = addKommaToNumber(summary) + "&nbsp;runs"
188 else:
189 s = addKommaToNumber(summary)
190 sumdic[key.ResultKey] = s.strip()
191 sumstr = ''
192 headlist = Run.headerkeys()
193 for title in headlist:
194 sumstr += '<td style="text-align:right;">%s</td>' % (sumdic[title] if title in sumdic else '')
195 return sumstr
196
197
198 # selection steps
199 @classmethod
200 def _makeSelectionSteps( cls, pageinfo ):
201 class PI:
202 pass
203 for x in ["selout"]:
204 setattr (PI, x, pageinfo[x])
205
206 selstr = '<table style="color: #777777; font-size: 100%" cellpadding="0" cellspacing="0">'
207 for sel in PI.selout:
208 if 'SELOUT' == sel[0:6]:
209 selout = sel[7:].split('==>')
210 if len(selout)==1:
211 selstr += '<tr><td width="400" style="vertical-align:top">%s</td></tr>' % selout[0]
212 else:
213 selstr += '<tr><td width="400" style="vertical-align:top">%s</td><td width="20" style="vertical-align:top">:</td><td style="vertical-align:top">%s</td></tr>' % tuple(selout[0:2])
214 selstr += '</table>'
215 return selstr
216
217
218
219
220 @classmethod
221 def _prettyNumber( cls, n, width=-1, delim=',',decimal='.' ):
222 """Converts a float to a string with appropriately placed commas"""
223 if width >= 0:
224 s = "%.*f" % (width, n)
225 else:
226 s = str(n)
227 dec = s.find(decimal)
228 if dec == -1:
229 dec = len(s)
230 threes = int((dec-1)/3)
231 for i in range(threes):
232 loc = dec-3*(i+1)
233 s = s[:loc] + delim + s[loc:]
234 return s
235
236
237 @classmethod
238 def _OverallSummary( cls, pageinfo ):
239 class PI:
240 pass
241 for x in pageinfo:
242 setattr (PI, x, pageinfo[x])
243
244 with timer("make the summary"):
245 from CoolRunQuery.html.AtlRunQuerySummary import MakeSummaryHtml
246 overallsummarystr = MakeSummaryHtml( PI.dic, PI.dicsum, PI.datapath )
247 if overallsummarystr == '':
248 return ''
249 s = '''<table width="95%" cellpadding="5" style="margin-left: 13px">
250 <tr><td colspan=2 bgcolor=gainsboro><font size=+1><b>Search Result Summary</b></font></td></tr>
251 </table>'''
252 s += '<p></p>'
253 s += overallsummarystr
254 s += '<p></p>'
255 return s
256
257
258 @classmethod
259 def _DQSummaryWrap( cls, pageinfo, doPickle=True ):
260 from CoolRunQuery.utils.AtlRunQueryUtils import runsOnServer
261 if not runsOnServer() and doPickle:
262 import pickle
263 from CoolRunQuery.AtlRunQueryQueryConfig import QC
264 with open('%s/dqsum_pi.pickle' % QC.datapath, "wb") as fh:
265 pickle.dump(pageinfo, fh)
266
267 class PI:
268 pass
269 for x in pageinfo:
270 setattr (PI, x, pageinfo[x])
271
272 with timer("make the DQ summary"):
273 from CoolRunQuery.html.AtlRunQueryDQSummary import DQSummary
274 dqsummary = DQSummary.makeHTML( PI.dic, PI.dicsum, doDQSummary=PI.makeDQSummary, doDQPlots=PI.makeDQPlots, dqsumGRL=PI.dqsumgrl, dbbTag=PI.dbbtag)
275
276 if dqsummary == '':
277 return ''
278 s = '''<table width="95%" cellpadding="5" style="margin-left: 13px">
279 <tr><td colspan=2 bgcolor=gainsboro><font size=+1><b>Data Quality Summary</b></font></td></tr>
280 </table>'''
281 s += '<p></p>'
282 s += dqsummary
283 s += '<p></p>'
284 return s
285
286
287 @classmethod
288 def _InitialSummary(cls, pageinfo):
289 class PI:
290 pass
291 for x in pageinfo:
292 setattr (PI, x, pageinfo[x])
293
294 error = False
295 totEv,naEv = Run.totevents[0:2]
296 s_table = '''<table width="95%" cellpadding="5" style="margin-left: 13px">
297 <tr><td colspan=2 bgcolor=gainsboro><font size=+1><b>Search Result</b></font></td></tr>
298 </table>'''
299 s_table += '<table width="95%" cellpadding="0" cellspacing="3" style="font-size: 90%; margin-left: 13px">\n'
300 s_table += '<tr height="10"></tr>\n'
301 s_table += '<tr><td height="10" width="130" style="vertical-align:top"><i>Selection&nbsp;rule:</i></td><td width=10></td><td valign=top>%s</td></tr>\n' % PI.origQuery
302 if 'erbose' in PI.fullQuery:
303 s_table += '<tr><td height="10" style="vertical-align: top; color: #777777"><i>Query&nbsp;command:</i></td><td width=10 style="color: #777777"></td><td style="color: #777777">'
304 s_table += """<a href="javascript:animatedcollapse.toggle('AtlRunQueryCmd')">"""
305 s_table += '<font color="#777777">[ Click to expand/collapse command... ]</font></a>'
306 s_table += '<div id="AtlRunQueryCmd" style="width: 100%; background: #FFFFFF; color: #777777; display:none">'
307 s_table += '%s' % (PI.fullQuery)
308 s_table += '</div></td></tr>\n'
309 s_table += '<tr><td height="10" style="vertical-align: top; color: #777777"><i>Selection&nbsp;sequence:</i></td><td width=10 style="color: #777777"></td><td style="vertical-align: top">%s</td></tr>\n' % (PI.selstr)
310 if not error:
311 s_table += '<tr><td height="10" style="vertical-align: top"><i>No.&nbsp;of&nbsp;runs&nbsp;selected:</i></td><td></td><td valign="top">%s</td></tr>\n' % len(PI.runlist)
312 if totEv >= 0:
313 if naEv >= 0:
314 sr = 'run'
315 if naEv > 1:
316 sr += 's'
317 if naEv == 0:
318 s_table += '<tr><td height="10" valign="top"><i>Total&nbsp;no.&nbsp;of&nbsp;events:</i></td><td></td><td valign="top">%s</td></tr>\n' % (cls._prettyNumber(totEv))
319 else:
320 s_table += '<tr><td height="10" valign="top"><i>Total&nbsp;no.&nbsp;of&nbsp;events:</i></td><td></td><td valign="top">%s (excluding %i %s without available "#Events" information)</td></tr>\n' % (cls._prettyNumber(totEv), naEv, sr)
321 else:
322 s_table += '<tr><td height="10" valign="top"><i>Total&nbsp;no.&nbsp;of&nbsp;events:</i></td><td></td><td valign="top">%s</td></tr>\n' % (cls._prettyNumber(totEv))
323 s_table += '<tr><td height="10" valign="top"><i>Execution&nbsp;time:</i></td><td></td><td valign="top">%.1f sec</td></tr>\n' % round(PI.querytime,1)
324 s_table += '<tr><td height=5 valign=top></td></tr>\n'
325 s_table += '</table>'
326 return s_table
327
328
329 @classmethod
330 def _PickledOutput(cls, datapath):
331 return '''<tr><td style="vertical-align: top"><img vspace=0 src="images/download.gif">&nbsp;&nbsp;</td><td>
332 <a href="./%s/atlrunquery.pickle" target=_blank title="Query results as serialised python dictionary">
333 Result table as pickled <b>python dictionary</b> (right-click link to download)</a>
334 <br>
335 use as follows:<br>
336 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&minus;
337 open file (f) in python and deserialise ("unpickle")
338 via: dico = pickle.load(f)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&minus; the dictionary keys are equal to the column titles,
339 the lines are stored as list entries for each key
340 </td></tr>''' % datapath
341
342
343 @classmethod
344 def _RootOutput(cls, roothtmlstr, datapath):
345 if roothtmlstr is not None:
346 return '''
347 <tr><td style="vertical-align: top"><img vspace=0 width="17" src="images/tree_icon.gif">&nbsp;&nbsp;</td><td>
348 <a href="./%s/atlrunquery.root" title="Query results as ROOT TTree">Result table as <b>TTree</b> in ROOT file (right-click link to download)</a></td></tr>
349 <tr><td style="vertical-align: top"><img vspace=0 src="images/statistics.gif">&nbsp;&nbsp;</td><td style="vertical-align: top">
350 <font color="#333333"><b>Graphs</b> of table columns versus run numbers:</font>
351 </td></tr>
352 <tr><td style="vertical-align: top"></td><td style="vertical-align: top">%s
353 </td></tr>''' % (datapath, roothtmlstr)
354 else:
355 return '''
356 <tr><td style="vertical-align: top"><img vspace=0 width="17" src="images/tree_icon.gif">&nbsp;&nbsp;</td><td style="color: #000064;">
357 Not available. <font color="#333333">The creation of a ROOT file with the results has been disabled by default. Please use option <b><i>root</i></b> as shown in the examples under <font style="color:red">Xtras</font></font></td></tr>
358 <tr><td style="vertical-align: top"><img vspace=0 src="images/statistics.gif">&nbsp;&nbsp;</td><td style="vertical-align: top">
359 <font color="#333333">The creation of <b>Graphs</b> has been disabled by default. Please use option <b><i>root</i></b> as shown in the examples under <font style="color:red">Xtras</font></font>
360 </td></tr>'''
361
362
363 @classmethod
364 def _Description(cls):
365 return '''<tr style="line-height: 6.5"><td colspan="2"></td></tr>
366 <tr><td style="vertical-align: top"><img vspace=0 src="images/info.gif">&nbsp;&nbsp;</td><td height="55"><i>n.a.</i>
367 in the table stands for <i>not available</i>:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&minus;
368 in case of <i>#Events</i> this mostly indicates unproperly closed runs<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&minus;
369 in case of <i>data quality flags</i> it indicates that the corresponding flag was not set<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&minus;
370 <i><font color="red">runs in red</font></i> indicate that their selection is questionable due to n.a. information
371 (n.a. fields pass the corresponding selection query)
372 </td></tr>'''
373
374
375 @classmethod
376 def _PrintFormat(cls, s_table, resstr):
377 s = '<tr><td><img vspace=0 src="images/printtopic.gif">&nbsp;&nbsp;</td>\n'
378 s += '<td><a href="javascript:openWindow('
379 s += "'Print','<!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;><html xmlns:&quot;my&quot;><head><title>Run query result</title><LINK href=&quot;atlas-runquery.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;><body><table style=&quot;font-family: sans-serif; font-size: 85%%&quot;>"
380 s += '<tr><td>%s</td></tr>' % s_table.replace('"','&quot;')
381 s += '<tr><td>' + resstr.replace('resulttable','resulttabletext').replace('"','quot;') + '</td></tr>'
382 s += '<tr><td><hr color=&quot;red&quot; size=1></td></tr><tr><td><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())
383 s += "')"
384 s += '" title="Query results in text format for easy printing">Print version of results</a>'
385 s += '</td></tr>'
386 return s
387
388
389 @classmethod
390 def _XMLFormat(cls, datapath, xmlfilename, xmlhtmlstr):
391 if xmlhtmlstr is not None:
392 s = '''<tr><td style="vertical-align: top"><img vspace=0 src="images/xml-small.gif">&nbsp;&nbsp;</td><td>
393 <a href="./%s/%s" target="_blank" title="Query result as LB collection in standard XML good-run-list format">Query result as standard <b>Good Run-LB List in XML format</b> (right-click link to download)</a> /
394 <a href="./LumiRangeCollection.dtd" target="_blank" title="Corresponding DTD file">DTD file</a>
395 </td></tr>''' % (datapath, xmlfilename)
396 s += '<tr><td style="vertical-align: top"></td><td>'
397 s += '<a href="javascript:openTextWindow('
398 s += "'Print','<!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;><html xmlns:&quot;my&quot;><head><title>Run query result</title><LINK href=&quot;atlas-runquery.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;><body><table style=&quot;padding: 10px;font-family: sans-serif; font-size: 95%%&quot;>"
399 s += '<tr><td>%s</td></tr>' % xmlhtmlstr
400 s += '</table></body></html>'
401 s += "')"
402 s += '" title="Query result in text format">Query result as standard <b>Good Run-LB List in pretty-text format</b> for visual inspection (click for pop-up)</a>'
403 s += '</td></tr>'
404 return s
405 else:
406 return '''<tr><td style="vertical-align: top;"><img vspace=0 src="images/xml-small.gif">&nbsp;&nbsp;</td><td style="color: #000064;">
407 Not available. <font color="#333333">The creation of <b>GRLs</b> based on the query result has been disabled by default. Please use option <b><i>grl</i></b> as shown in the examples under <font style="color:red">Xtras</font></font></td></tr>'''
408
409
_prettyNumber(cls, n, width=-1, delim=',', decimal='.')
_DQSummaryWrap(cls, pageinfo, doPickle=True)
makePage(cls, pageinfo, doDQPickle=True)
_XMLFormat(cls, datapath, xmlfilename, xmlhtmlstr)
_defineToolTips(cls, pageinfo, globalOnly=False)
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
const float PI