ATLAS Offline Software
AtlRunQueryXML.py
Go to the documentation of this file.
1 #!/usr/env python
2 
3 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4 #
5 # ----------------------------------------------------------------
6 # Script : AtlRunQueryXML.py
7 # Project: AtlRunQuery
8 # Purpose: XML file output of good run lists
9 # Authors: Andreas Hoecker (CERN), Joerg Stelzer (DESY)
10 # Created: May 6, 2009
11 # ----------------------------------------------------------------
12 #
13 # ---------------------------------------------------------------------------------------------------
14 # XML making
15 # ---------------------------------------------------------------------------------------------------
16 
17 from __future__ import with_statement
18 from CoolRunQuery.utils.AtlRunQueryTimer import timer
19 
20 import datetime, sys
21 from xml.dom.minidom import Document, DocumentType, Element
22 from CoolRunQuery.utils.AtlRunQueryUtils import prettyNumber
23 
24 # ---------------------------------------------------------------------------------------------------
25 # Creation of XML output file
26 # ---------------------------------------------------------------------------------------------------
27 
28 # This is an Element, but does not print sub-elements. It is designed
29 # to hold attributes and CharacterData, and prints everything in one
30 # line (unlike Element.writexml(), which always adds a 'newline'
31 class TextElement(Element):
32  def __init__(self,name,data,doc):
33  Element.__init__(self,name)
34  if not isinstance(data, str):
35  raise TypeError ("node contents must be a string")
36  self.tagName = name
37  self.data = data
38  self.ownerDocument = doc
39  self.attOrder = []
40 
41  def setAttribute(self, attname, value):
42  if attname not in self.attOrder:
43  self.attOrder += [attname]
44  Element.setAttribute(self, attname, value)
45 
46  def writexml(self, writer, indent="", addindent="", newl=""):
47  attrs = self._get_attributes()
48  atstr = ''
49  for a_name in self.attOrder:
50  atstr += ' %s="%s"' % (a_name, attrs[a_name].value)
51 
52  if self.data:
53  writer.write("%s<%s%s>%s</%s>%s" % (indent, self.tagName, atstr, self.data, self.tagName, newl ) )
54  else:
55  writer.write("%s<%s%s/>%s" % (indent, self.tagName, atstr, newl ) )
56 
58 
59  # open SFO DB connection
60  from CoolRunQuery.utils.AtlRunQueryUtils import coolDbConn
61  from CoolRunQuery.AtlRunQuerySFO import GetSFO_NeventsAllPhysics
62 
63  cursor = coolDbConn.GetSFODBConnection().cursor()
64  cursor.arraysize=1000
65 
66  # find streams
67  runnrlist = [r.runNr for r in runlist]
68  with timer('get SFO number of events AllPhysics'):
69  runstreamevents = GetSFO_NeventsAllPhysics( cursor, runnrlist ) # { runnr: { stream: [(LUMIBLOCKNR, NREVENTS)] } }
70  return runstreamevents, ",".join(['%i' % r for r in runnrlist])
71 
72 
73 
74 def CreateXMLFile( runlist, options, origQuery, datapath, xmlfname, xmllabel, svnversion='Unknown' ):
75  """
76  """
77 
78 
79  with timer('create RunStreamAndNeventsList'):
80 
81  # show number of events per stream per run ?
82  ShowNumberOfEventsPerStreamPerRun = False
83  ShowNumberOfEventsPerStreamSummary = True
84 
85 
86  # find streams
87  runstreamevents, runnrliststr = CreateRunStreamAndNeventsList( runlist ) # { runnr: { stream: [(LUMIBLOCKNR, NREVENTS)] } }
88 
89  with timer('prepare document'):
90 
91 
92 
93 
94 
95 
96  doc = Document()
97 
98  docType = DocumentType('LumiRangeCollection')
99  docType.systemId = 'http://atlas-runquery.cern.ch/LumiRangeCollection.dtd'
100  doc.appendChild(docType)
101 
102  # number of comments
103  txt = ' Good-runs-list created by %s on %s ' % (sys.argv[0].split('/')[-1], str(datetime.datetime.now()))
104  doc.appendChild( doc.createComment( txt ) )
105 
106  # root element
107  lrc = doc.createElement('LumiRangeCollection')
108  doc.appendChild(lrc)
109 
110  # NamedLumiRange
111  namedLR = doc.createElement('NamedLumiRange')
112  lrc.appendChild(namedLR)
113 
114  # name of NamedLumiRange
115  namedLR.appendChild(TextElement('Name',xmllabel,doc))
116 
117  # version of NamedLumiRange
118  namedLR.appendChild(TextElement('Version','2.1',doc))
119 
120  # metadata of NamedLumiRange
121  metadata = {
122  'Query' : origQuery.split('/')[0],
123  'RQTSVNVersion' : svnversion,
124  'RunList' : runnrliststr
125  }
126 
127  for md in metadata:
128  mdelm = TextElement('Metadata', metadata[md], doc)
129  mdelm.setAttribute('Name', md)
130  namedLR.appendChild(mdelm)
131 
132  with timer('ShowNumberOfEventsPerStreamSummary'):
133  if ShowNumberOfEventsPerStreamSummary:
134  strsummdelm = doc.createElement('Metadata')
135  strsummdelm.setAttribute('Name','StreamListInfo')
136  namedLR.appendChild(strsummdelm)
137 
138 
139  # lumiblock collections of NamedLumiRange
140  streams_sum = {}
141  streams_byrun = {}
142  with timer('Loop over all runs'):
143  for run in runlist:
144  lbc = doc.createElement('LumiBlockCollection')
145  # run number
146  runnrelm = TextElement('Run',str(run.runNr),doc)
147 
148 
149  if len(run.stats['SMK']['random'])==2:
150  (rd0,rd1) = run.stats['SMK']['random'][0:2]
151  # protect against missing information
152  if rd0 == 'n.a.':
153  rd0 = 0
154  if rd1 == 'n.a.':
155  rd1 = 0
156  runnrelm.setAttribute('PrescaleRD0',0x1<<(3+rd0))
157  runnrelm.setAttribute('PrescaleRD1',0x1<<(3+rd1))
158  else:
159  (rd0,rd1,rd2,rd3) = run.stats['SMK']['random'][0:4]
160  # protect against missing information
161  if rd0 == 'n.a.':
162  rd0 = 0
163  if rd1 == 'n.a.':
164  rd1 = 0
165  if rd2 == 'n.a.':
166  rd2 = 0
167  if rd3 == 'n.a.':
168  rd3 = 0
169  runnrelm.setAttribute('Cut0', rd0)
170  runnrelm.setAttribute('Cut1', rd1)
171  runnrelm.setAttribute('Cut2', rd2)
172  runnrelm.setAttribute('Cut3', rd3)
173 
174  lbc.appendChild(runnrelm)
175 
176  # streams (initialisation)
177  streams = {}
178  streams_byrun[run.runNr] = streams
179  if run.runNr in runstreamevents: # protection in case the run does not have any stream
180  for stream in runstreamevents[run.runNr].keys():
181  if 'physics_' == stream[:8]:
182  streams[stream] = [0,0] # only for physics streams
183  if stream not in streams_sum:
184  streams_sum[stream] = [0,0]
185  # total number of events in stream
186  for (nlb,nev) in runstreamevents[run.runNr][stream]:
187  streams[stream][0] += nev
188 
189  # lumiblock ranges
190 
191  for lbrange in run.data.getLBRanges(activeOnly=True):
192  lbrelm = TextElement('LBRange','',doc)
193  lbrelm.setAttribute('Start',lbrange[1])
194  lbrelm.setAttribute('End',lbrange[2]-1)
195  lbc.appendChild(lbrelm)
196  # count nevents in streams
197  if run.runNr in runstreamevents: # protection in case the run does not have any stream
198  for stream, lbnevts in runstreamevents[run.runNr].items():
199  if 'physics_' == stream[:8]:
200  for (nlb,nev) in lbnevts:
201  if nlb>=lbrange[1] and nlb<lbrange[2]:
202  streams[stream][1] += nev
203 
204  # append stream element
205  strselm = doc.createElement('StreamsInRun')
206 
207  for stream in sorted (streams.keys()):
208  nevts = streams[stream]
209  if ShowNumberOfEventsPerStreamPerRun:
210  strelm = TextElement('Stream','',doc)
211  strelm.setAttribute('Name', stream)
212  strelm.setAttribute('TotalNumOfEvents', nevts[0])
213  strelm.setAttribute('NumOfSelectedEvents', nevts[1])
214  strselm.appendChild(strelm)
215  eff = 0
216  if nevts[0] > 0:
217  eff = nevts[1]/float(nevts[0])*100.0
218 
219  # collect total number of events
220  streams_sum[stream][0] += nevts[0]
221  streams_sum[stream][1] += nevts[1]
222 
223  # append streams
224  if ShowNumberOfEventsPerStreamPerRun:
225  lbc.appendChild(strselm)
226 
227  # append LumiBlickCollection
228  namedLR.appendChild(lbc)
229 
230  with timer('Streams'):
231  for stream in sorted(streams_sum.keys()):
232  nevts = streams_sum[stream]
233  if ShowNumberOfEventsPerStreamSummary:
234  strelm = TextElement('Stream','',doc)
235  strelm.setAttribute('Name', stream)
236  strelm.setAttribute('TotalNumOfEvents', nevts[0])
237  strelm.setAttribute('NumOfSelectedEvents', nevts[1])
238  strsummdelm.appendChild(strelm)
239 
240 
241  with timer('Save GRL'):
242 
243  filename = '%s/%s' % (datapath, xmlfname)
244  #print "Writing",filename
245  xmlfile = open( filename, mode="w" )
246  xmlfile.write( doc.toprettyxml(' ') )
247  xmlfile.close()
248 
249  with timer('Create HTML'):
250 
251 
252 
253 
254 
255 
256 
257  # provide also pretty html text output
258  htmltext = ''
259  htmltext += '<table style=&quot;width: auto; border: 0px solid; border-width: margin: 0 0 0 0; 0px; border-spacing: 0px; border-collapse: separate; padding: 0px;&quot; font-family: sans-serif; font-size: 85%%&quot;>\n'
260  htmltext += '<tr><td colspan=&quot;2&quot;><b><font color=&quot;#999999&quot;>' + txt.strip() + '</font></b></td></tr>\n'
261  htmltext += '<tr><td style=&quot;vertical-align:top&quot;>SVN&nbsp;Version: </td><td> ' + svnversion + '</td></tr>\n'
262  htmltext += '<tr><td style=&quot;vertical-align:top&quot;>Query&nbsp;string:</td><td><b>' + origQuery.split('/')[0] + '</b></td></tr>\n'
263  htmltext += '<tr><td style=&quot;vertical-align:top&quot;>Run list:</td><td>' + runnrliststr + '</td></tr>\n'
264  htmltext += '</table>'
265  htmltext += '<hr color=&quot;#000000&quot; size=1><font color=&quot;#777777&quot;>\n'
266  htmltext += '<table style=&quot;width: auto; border: 0px solid; border-width: margin: 0 0 0 0; 0px; border-spacing: 0px; border-collapse: separate; padding: 0px;&quot; font-family: sans-serif; font-size: 90%%&quot;>\n'
267 
268 
269  # lumiblock collections of NamedLumiRange
270  for run in runlist:
271  # run number
272  htmltext += '<tr><td style=&quot;text-align:left;height:25px;vertical-align:bottom&quot;>Run <b>%i</b>:</td><td></td></tr>\n' % run.runNr
273 
274  # lumiblock ranges
275 
276  for lbrange in run.data.getLBRanges(activeOnly=True):
277  htmltext += '<tr><td></td><td style=&quot;text-align:left&quot;>LB range: [%5i-%5i]</td></tr>\n' % (lbrange[1],lbrange[2]-1)
278 
279  # append stream element
280  htmltext += '<tr><td></td><td style=&quot;text-align:left&quot;></td></tr>'
281  htmltext += '<tr><td></td><td style=&quot;text-align:left&quot;><table style=&quot;width: auto; border: 0px solid; border-width: margin: 0 0 0 0; 0px; border-spacing: 0px; border-collapse: separate; padding: 0px;font-family: sans-serif; font-size: 90%&quot;><tr><td>Stream name</td><td>#Events total</td><td>&nbsp;&nbsp;&nbsp;#Events selected</td><td>&nbsp;&nbsp;&nbsp;Sel. fraction (%)</td></tr>\n'
282 
283  streams = streams_byrun[run.runNr]
284  for stream in sorted(streams.keys()):
285  nevts = streams[stream]
286  eff = (nevts[1]/float(nevts[0])*100.0) if (nevts[0] > 0) else 0
287  htmltext += '<tr><td style=&quot;text-align:left&quot;><i>%s</i></td><td style=&quot;text-align:right&quot;>%s</td><td style=&quot;text-align:right&quot;>%s</td><td style=&quot;text-align:right&quot;>%.4g</td></tr>\n' % (stream, prettyNumber(nevts[0]),prettyNumber(nevts[1]),eff)
288 
289  htmltext += '</table></td></tr>\n'
290 
291 
292  # append stream element
293  htmltext += '</table>'
294  htmltext += '<hr color=&quot;#000000&quot; size=1><font color=&quot;#777777&quot;>\n'
295  htmltext += '<b>Stream summary for all selected runs:</b><br>\n'
296  htmltext += '<table style=&quot;width: auto; border: 0px solid; border-width: margin: 0 0 0 0; 0px; border-spacing: 0px; border-collapse: separate; padding: 0px;font-family: sans-serif; font-size: 95%&quot;><tr><td>Stream name</td><td>#Events total</td><td>&nbsp;&nbsp;&nbsp;#Events selected</td><td>&nbsp;&nbsp;&nbsp;Sel. fraction (%)</td></tr>\n'
297  for stream in sorted(streams_sum.keys()):
298  nevts = streams_sum[stream]
299  eff = 0
300  if nevts[0] > 0:
301  eff = nevts[1]/float(nevts[0])*100.0
302  htmltext += '<tr><td style=&quot;text-align:left&quot;><i>%s</i></td><td style=&quot;text-align:right&quot;>%s</td><td style=&quot;text-align:right&quot;>%s</td><td style=&quot;text-align:right&quot;>%.4g</td></tr>\n' % (stream, prettyNumber(nevts[0]),prettyNumber(nevts[1]),eff)
303  htmltext += '</table>\n'
304 
305  #print """========================================================
306  #%r
307  #===========================================================
308  #""" % htmltext
309 
310 
311  # provide also text output
312  return htmltext
python.output.AtlRunQueryXML.TextElement.tagName
tagName
Definition: AtlRunQueryXML.py:36
python.output.AtlRunQueryXML.TextElement.setAttribute
def setAttribute(self, attname, value)
Definition: AtlRunQueryXML.py:41
python.utils.AtlRunQueryUtils.prettyNumber
def prettyNumber(n, width=-1, delim=',', decimal='.')
Definition: AtlRunQueryUtils.py:73
python.output.AtlRunQueryXML.TextElement.__init__
def __init__(self, name, data, doc)
Definition: AtlRunQueryXML.py:32
python.output.AtlRunQueryXML.CreateRunStreamAndNeventsList
def CreateRunStreamAndNeventsList(runlist)
Definition: AtlRunQueryXML.py:57
python.output.AtlRunQueryXML.TextElement.data
data
Definition: AtlRunQueryXML.py:37
python.utils.AtlRunQueryTimer.timer
def timer(name, disabled=False)
Definition: AtlRunQueryTimer.py:86
python.output.AtlRunQueryXML.TextElement.writexml
def writexml(self, writer, indent="", addindent="", newl="")
Definition: AtlRunQueryXML.py:46
python.output.AtlRunQueryXML.TextElement.ownerDocument
ownerDocument
Definition: AtlRunQueryXML.py:38
python.output.AtlRunQueryXML.CreateXMLFile
def CreateXMLFile(runlist, options, origQuery, datapath, xmlfname, xmllabel, svnversion='Unknown')
Definition: AtlRunQueryXML.py:74
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
Trk::open
@ open
Definition: BinningType.h:40
python.output.AtlRunQueryXML.TextElement
Definition: AtlRunQueryXML.py:31
query_example.cursor
cursor
Definition: query_example.py:21
python.AtlRunQuerySFO.GetSFO_NeventsAllPhysics
def GetSFO_NeventsAllPhysics(cursor, runlist)
Definition: AtlRunQuerySFO.py:225
str
Definition: BTagTrackIpAccessor.cxx:11
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:798
readCCLHist.float
float
Definition: readCCLHist.py:83
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.output.AtlRunQueryXML.TextElement.attOrder
attOrder
Definition: AtlRunQueryXML.py:39