File indexing completed on 2024-04-20 02:32:05
0001
0002
0003 from builtins import range
0004 import sys, os.path, json
0005 from collections import defaultdict
0006 import ROOT
0007 ROOT.PyConfig.IgnoreCommandLineOptions = True
0008 ROOT.gROOT.SetBatch(True)
0009
0010
0011 class FileData:
0012 def __init__(self,data):
0013 self._json = data
0014 for k,v in data.items():
0015 setattr(self,k,v)
0016 self.Events = self.trees["Events"]
0017 self.nevents = self.Events["entries"]
0018 self.Runs = self.trees["Runs"]
0019 self.nruns = self.Runs["entries"]
0020 self.LuminosityBlocks = self.trees["LuminosityBlocks"]
0021 self.nluminosityblocks = self.LuminosityBlocks["entries"]
0022
0023 class Branch:
0024 def __init__(self, tree, branch):
0025 self.tree = tree
0026 self.branch = branch
0027 self.name = branch.GetName()
0028 self.doc = branch.GetTitle()
0029 self.tot = branch.GetZipBytes()/1024.0
0030 self.entries = None;
0031 self.single = True
0032 self.kind = "Unknown"
0033 if branch.GetNleaves() != 1:
0034 sys.stderr.write("Cannot parse branch '%s' in tree %s (%d leaves)\n"%(branch.GetName(), tree.GetName(), branch.GetNleaves()))
0035 return
0036 self.leaf = branch.FindLeaf(branch.GetName())
0037 if not self.leaf:
0038 sys.stderr.write("Cannot parse branch '%s' in tree %s (no leaf)\n"%(branch.GetName(), tree.GetName()))
0039 return
0040 self.kind = self.leaf.GetTypeName()
0041 if "Idx" in self.name:
0042 self.kind+="(index to %s)"%((self.name[self.name.find("_")+1:self.name.find("Idx")]).title())
0043 if self.leaf.GetLen() == 0 and self.leaf.GetLeafCount() != None:
0044 self.single = False
0045 self.counter = self.leaf.GetLeafCount().GetName()
0046 def toJSON(self):
0047 return ( self.name, dict(name = self.name, doc = self.doc, tot=self.tot, entries=self.entries, single=self.single, kind=self.kind, counter = getattr(self,'counter','')) )
0048
0049 class BranchGroup:
0050 def __init__(self, name):
0051 self.name = name
0052 self.tot = 0
0053 self.entries = None;
0054 self.subs = []
0055 self.kind = None
0056 self.doc = ''
0057 def append(self, sub):
0058 self.subs.append(sub)
0059 self.tot += sub.tot
0060 if not self.doc: self.doc = sub.doc
0061 def getKind(self):
0062 if self.kind: return self.kind
0063 if len(self.subs) == 1:
0064 if self.subs[0].single: self.kind = "Variable"
0065 else:
0066 self.kind = "Vector"
0067 self.counter = self.subs[0].counter
0068 else:
0069 allsingles, commonCounter = True, True
0070 counter = None
0071 for s in self.subs:
0072 if not s.single:
0073 allsingles = False
0074 if counter == None: counter = s.counter
0075 elif counter != s.counter:
0076 commonCounter = False
0077 if allsingles:
0078 self.kind = "Singleton"
0079 elif commonCounter:
0080 self.kind = "Collection"
0081 self.counter = counter
0082 else:
0083 self.kind = "ItsComplicated"
0084 return self.kind
0085 def toJSON(self):
0086 return (self.name, dict(name = self.name, doc = self.doc, kind = self.kind, tot = self.tot, entries = self.entries, subs = [s.name for s in self.subs]))
0087
0088
0089 def inspectRootFile(infile):
0090 if not os.path.isfile(infile): raise RuntimeError
0091 filesize = os.path.getsize(infile)/1024.0
0092 tfile = ROOT.TFile.Open(infile)
0093 trees = {}
0094 for treeName in "Events", "Runs", "LuminosityBlocks":
0095 toplevelDoc={}
0096 tree = tfile.Get(treeName)
0097 entries = tree.GetEntries()
0098 trees[treeName] = tree
0099 branchList = tree.GetListOfBranches()
0100 allbranches = [ Branch(tree, br) for br in branchList ]
0101 branchmap = dict((b.name,b) for b in allbranches)
0102 branchgroups = {}
0103
0104 counters = defaultdict(list)
0105 for b in allbranches:
0106 if not b.single:
0107 counters[b.counter].append(b.name)
0108 else:
0109 b.entries = entries
0110 c1 = ROOT.TCanvas("c1","c1")
0111 for counter,countees in counters.items():
0112 n = tree.Draw(counter+">>htemp")
0113 if n != 0:
0114 htemp = ROOT.gROOT.FindObject("htemp")
0115 n = htemp.GetEntries() * htemp.GetMean()
0116 htemp.Delete()
0117 branchmap[counter].entries = entries
0118 for c in countees:
0119 br = branchmap[c]
0120 br.entries = n
0121
0122 for b in allbranches:
0123 if b.name in counters:
0124 if len(b.doc) > 0:
0125 toplevelDoc[b.name[1:]]=b.doc
0126 continue
0127 if "_" in b.name:
0128 head, tail = b.name.split("_",1)
0129 else:
0130 head = b.name
0131 toplevelDoc[b.name]=b.doc
0132 if head not in branchgroups:
0133 branchgroups[head] = BranchGroup(head)
0134 branchgroups[head].append(b)
0135 for bg in branchgroups.values():
0136 if bg.name in toplevelDoc:
0137 bg.doc = toplevelDoc[bg.name]
0138 kind = bg.getKind()
0139 bg.entries = bg.subs[0].entries
0140 if kind == "Vector" or kind == "Collection":
0141 bg.append(branchmap[bg.counter])
0142 elif kind == "ItsComplicated":
0143 for counter in set(s.counter for s in bg.subs if not s.single):
0144 bg.append(branchmap[counter])
0145 allsize_c = sum(b.tot for b in allbranches)
0146 allsize = sum(b.tot for b in branchgroups.values())
0147 if abs(allsize_c - allsize) > 1e-6*(allsize_c+allsize):
0148 sys.stderr.write("Total size mismatch for tree %s: %10.4f kb vs %10.4f kb\n" % (treeName, allsize, allsize_c))
0149 trees[treeName] = dict(
0150 entries = entries,
0151 allsize = allsize,
0152 branches = dict(b.toJSON() for b in allbranches),
0153 branchgroups = dict(bg.toJSON() for bg in branchgroups.values()),
0154 )
0155 c1.Close()
0156 tfile.Close()
0157 return dict(filename = os.path.basename(infile), filesize = filesize, trees = trees)
0158
0159 def makeSurvey(treeName, treeData):
0160 allsize = treeData['allsize']
0161 entries = treeData['entries']
0162 survey = list(treeData['branchgroups'].values())
0163 survey.sort(key = lambda bg : - bg['tot'])
0164 scriptdata = []
0165 runningtotal = 0
0166 unit = treeName[:-1].lower()
0167 for s in survey:
0168 if s['tot'] < 0.01*allsize:
0169 tag = "<b>Others</b><br/>Size: %.0f b/%s (%.1f%%)" % ((allsize - runningtotal)/entries*1024, unit, (allsize-runningtotal)/allsize*100)
0170 scriptdata.append( "{ 'label':'others', 'tag':'top', 'size':%s, 'tip':'%s' }" % ((allsize-runningtotal)/entries, tag) )
0171 break
0172 else:
0173 tag = "<b><a href=\"#%s\">%s</a></b><br/>" % (s['name'],s['name']);
0174 tag += "Size: %.0f b/%s (%.1f%%)" % (s['tot']/entries*1024, unit, s['tot']/allsize*100);
0175 if (s['kind'] in ("Vector","Collection")) and s['entries'] > 0:
0176 tag += "<br/>Items/%s: %.1f, %.0f b/item" %(unit, float(s['entries'])/entries, s['tot']/s['entries']*1024);
0177 scriptdata.append( "{ 'label':'%s', 'tag':'%s', 'size':%s, 'tip':'%s' }" % ( s['name'], s['name'], s['tot']/entries, tag) )
0178 runningtotal += s['tot']
0179 return (survey, "\n,\t".join(scriptdata))
0180
0181 def writeSizeReport(fileData, trees, stream):
0182 filename = fileData.filename
0183 filesize = fileData.filesize
0184 events = fileData.nevents
0185 surveys = {}
0186 for treename, treeData in trees.items():
0187 surveys[treename] = makeSurvey(treename, treeData)
0188 title = "%s (%.3f Mb, %d events, %.2f kb/event)" % (filename, filesize/1024.0, events, filesize/events)
0189 stream.write("""
0190 <html>
0191 <head>
0192 <title>{title}</title>
0193 <link rel="stylesheet" type="text/css" href="http://gpetrucc.web.cern.ch/gpetrucc/micro/patsize.css" />
0194 <script type="text/javascript" src="http://gpetrucc.web.cern.ch/gpetrucc/rgraph/RGraph.common.core.js"></script>
0195 <script type="text/javascript" src="http://gpetrucc.web.cern.ch/gpetrucc/rgraph/RGraph.pie.js"></script>
0196 <script type="text/javascript" src="http://gpetrucc.web.cern.ch/gpetrucc/rgraph/RGraph.common.dynamic.js"></script>
0197 <script type="text/javascript" src="http://gpetrucc.web.cern.ch/gpetrucc/rgraph/RGraph.common.tooltips.js"></script>
0198 <script type="text/javascript" src="http://gpetrucc.web.cern.ch/gpetrucc/rgraph/RGraph.common.key.js"></script>
0199 </head>
0200 <body>
0201 <a name="top" id="top"><h1>{title}</h1></a>
0202 """.format(title=title))
0203 stream.write("\n".join("""
0204 <h1>{treename} data</h1>
0205 <canvas id="{treename}Canvas" width="800" height="300">[No canvas support]</canvas>
0206 """.format(treename=treename) for treename in surveys.keys()))
0207 stream.write(' <script type="text/javascript">\n')
0208 stream.write("\n".join("""
0209 var data_{treename} = [ {scriptdata} ];
0210 """.format(treename=treename, scriptdata=scriptdata)
0211 for treename, (_, scriptdata) in surveys.items()))
0212 stream.write("""
0213 window.onload = function() {{
0214 {0}
0215 }}
0216 </script>
0217 """.format(
0218 "\n".join("""
0219 values = [];
0220 labels = [];
0221 keys = [];
0222 tips = [];
0223 for (var i = 0; i < data_{treename}.length; i++) {{
0224 values.push( data_{treename}[i].size );
0225 labels.push( data_{treename}[i].label );
0226 keys.push( data_{treename}[i].label );
0227 tips.push( data_{treename}[i].tip );
0228 }}
0229 var chart_{treename} = new RGraph.Pie("{treename}Canvas", values)
0230 .Set('exploded', 7)
0231 .Set('tooltips', tips)
0232 .Set('tooltips.event', 'onmousemove')
0233 .Set('key', labels)
0234 .Set('key.position.graph.boxed', false)
0235 .Draw();
0236 """.format(treename=treename, scriptdata=scriptdata)
0237 for treename, (_, scriptdata) in surveys.items())))
0238
0239 if len(trees) > 1:
0240 stream.write(" <h1>Collections summary</h1>\n")
0241 stream.write(" <table>\n")
0242 stream.write("<tr class='header'><th>" + "</th><th>".join([ "collection", "kind", "vars", "items/evt", "kb/evt", "b/item", "plot", "%" ]) + "</th><th colspan=\"2\">cumulative %</th></tr>\n");
0243 runningtotal = 0
0244 for treename, (survey, _) in surveys.items():
0245 treetotal = trees[treename]['allsize']
0246 treerunningtotal = 0
0247 for s in survey:
0248 stream.write("<tr><th title=\"%s\"><a href='#%s'>%s</a></th><td style='text-align : left;'>%s</td><td>%d</td>" % (s['doc'],s['name'],s['name'],s['kind'].lower(),len(s['subs'])))
0249 stream.write("<td>%.2f</td><td>%.3f</td><td>%.1f</td>" % (s['entries']/events, s['tot']/events, s['tot']/s['entries']*1024 if s['entries'] else 0))
0250 stream.write("<td class=\"img\"><img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/blue-dot.gif' width='%d' height='%d' /></td>" % (s['tot']/treetotal*200,10))
0251 stream.write("<td>%.1f%%</td>" % ( s['tot']/treetotal * 100.0))
0252 stream.write("<td>%.1f%%</td>" % ( (runningtotal+s['tot'])/treetotal * 100.0))
0253 stream.write("<td>%.1f%%</td>" % ( (treetotal-runningtotal)/treetotal * 100.0))
0254 stream.write("</tr>\n")
0255 treerunningtotal += s['tot']
0256 runningtotal += treerunningtotal
0257
0258
0259 stream.write("<tr><th>All %s data</th>" % treename)
0260 stream.write("<td> </td><td> </td><td> </td><td><b>%.2f</b></td><td> </td>" % (treetotal/events))
0261 stream.write("<td class=\"img\"><img src=\"http://gpetrucc.web.cern.ch/gpetrucc/micro/green-dot.gif\" width='%d' height='10' />" % ( treetotal/filesize*100.0))
0262 stream.write("</td><td>%.1f%%<sup>a</sup></td>" % (treetotal/filesize*100.0))
0263 stream.write("</tr>\n")
0264
0265 if treename == "Events":
0266
0267 stream.write("<tr><th>Non per-event data or overhead</th>")
0268 stream.write("<td> </td><td> </td><td> </td><td>%.2f</td><td> </td>" % ( (filesize-treetotal)/events))
0269 stream.write("<td class=\"img\"><img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/red-dot.gif' width='%d' height='%d' /></td>" % ( (filesize-treetotal)/filesize * 100, 10 ))
0270 stream.write("<td>%.1f%%<sup>a</sup></td>" % ( (filesize-treetotal)/filesize * 100.0 ))
0271 stream.write("</tr>\n")
0272
0273 if len(surveys) > 1:
0274
0275 stream.write("<tr><th>Overhead</th>")
0276 stream.write("<td> </td><td> </td><td> </td><td>%.2f</td><td> </td>" % ( (filesize-runningtotal)/events))
0277 stream.write("<td class=\"img\"><img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/red-dot.gif' width='%d' height='%d' /></td>" % ( (filesize-runningtotal)/filesize * 100, 10 ))
0278 stream.write("<td>%.1f%%<sup>a</sup></td>" % ( (filesize-runningtotal)/filesize * 100.0 ))
0279 stream.write("</tr>\n")
0280
0281
0282 stream.write("<tr><th>File size</th>")
0283 stream.write("<td> </td><td> </td><td> </td><td><b>%.2f</b></td><td> </td>" % (filesize/events))
0284 stream.write("<td> </td><td> </td></tr>\n")
0285
0286 stream.write("""
0287 </table>
0288 Note: size percentages of individual event products are relative to the total size of Event data only (or equivalent for non-Events trees).<br />
0289 Percentages with <sup>a</sup> are instead relative to the full file size.
0290 """)
0291 for treename, treeData in trees.items():
0292 stream.write("""
0293 <h1>%s detail</h1>
0294 """ % treename)
0295 for s in sorted(surveys[treename][0], key = lambda s : s['name']):
0296 stream.write("<h2><a name='%s' id='%s'>%s</a> (%.1f items/evt, %.3f kb/evt) <sup><a href=\"#top\">[back to top]</a></sup></h2>" % (s['name'], s['name'], s['name'], s['entries']/events, s['tot']/events))
0297 stream.write("<table>\n")
0298 stream.write("<tr class='header'><th>" + "</th><th>".join( [ "branch", "kind", "b/event", "b/item", "plot", "%" ]) + "</th></tr>\n")
0299 subs = [ treeData['branches'][b] for b in s['subs'] ]
0300 for b in sorted(subs, key = lambda s : - s['tot']):
0301 stream.write("<tr><th title=\"%s\">%s</th><td style='text-align : left;'>%s</td><td>%.1f</td><td>%.1f</td>" % (b['doc'],b['name'], b['kind'], b['tot']/events*1024, b['tot']/s['entries']*1024 if s['entries'] else 0))
0302 stream.write("<td class=\"img\"><img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/blue-dot.gif' width='%d' height='%d' /></td>" % ( b['tot']/s['tot']*200, 10 ))
0303 stream.write("<td>%.1f%%</td>" % (b['tot']/s['tot'] * 100.0))
0304 stream.write("</tr>\n")
0305 stream.write("</table>\n")
0306 stream.write("""
0307 </body></html>
0308 """)
0309
0310 def writeDocReport(fileName, trees, stream):
0311 stream.write( """
0312 <html>
0313 <head>
0314 <title>Documentation for {filename} </title>
0315 <link rel="stylesheet" type="text/css" href="http://gpetrucc.web.cern.ch/gpetrucc/micro/patsize.css" />
0316 </head>
0317 <body>
0318 """.format(filename=fileName))
0319 for treename, treeData in trees.items():
0320 stream.write("""
0321 <h1>{treename} Content</h1>
0322 <table>
0323 """.format(treename=treename))
0324 stream.write( "<tr class='header'><th>Collection</th><th>Description</th></tr>\n" )
0325 groups = list(treeData['branchgroups'].values())
0326 groups.sort(key = lambda s : s['name'])
0327 for s in groups:
0328 stream.write( "<th><a href='#%s'>%s</a></th><td style='text-align : left;'>%s</td></tr>\n" % (s['name'],s['name'],s['doc']) )
0329 stream.write("</table>\n\n<h1>{treename} detail</h1>\n".format(treename=treename))
0330 for s in groups:
0331 stream.write( "<h2><a name='%s' id='%s'>%s</a> <sup><a href=\"#top\">[back to top]</a></sup></h2>\n" % (s['name'], s['name'], s['name']) )
0332 stream.write( "<table>\n" )
0333 stream.write( "<tr class='header'><th>Object property</th><th>Type</th><th>Description</th></tr>\n" )
0334 subs = [ treeData['branches'][b] for b in s['subs'] ]
0335 for b in sorted(subs, key = lambda s : s['name']):
0336 stream.write( "<th>%s</th><td style='text-align : left;'>%s</td><td style='text-align : left;'>%s</td>" % (b['name'], b['kind'], b['doc']) )
0337 stream.write( "</tr>\n" )
0338 stream.write( "</table>\n" )
0339 stream.write( """
0340 </body></html>
0341 """ )
0342
0343 def writeMarkdownSizeReport(fileData, trees, stream):
0344 filename = fileData.filename
0345 filesize = fileData.filesize
0346 events = fileData.nevents
0347 surveys = {}
0348 for treename, treeData in trees.items():
0349 surveys[treename] = makeSurvey(treename, treeData)[0]
0350
0351 stream.write("**%s (%.3f Mb, %d events, %.2f kb/event)**\n" % (filename, filesize/1024.0, events, filesize/events))
0352 stream.write("\n# Event data\n" if len(trees) == 1 else "\n# Collection data\n")
0353 stream.write("| collection | kind | vars | items/evt | kb/evt | b/item | plot | % | ascending cumulative % | descending cumulative % |\n")
0354 stream.write("| - | - | - | - | - | - | - | - | - | - |\n")
0355 runningtotal = 0
0356 for treename, survey in surveys.items():
0357 treetotal = trees[treename]['allsize']
0358 treerunningtotal = 0
0359 for s in survey:
0360 stream.write("| [**%s**](#%s '%s') | %s | %d" % (s['name'], s['name'].lower(), s['doc'].replace('|', '\|').replace('\'', '\"'), s['kind'].lower(), len(s['subs'])))
0361 stream.write("| %.2f|%.3f|%.1f" % (s['entries']/events, s['tot']/events, s['tot'] / s['entries'] * 1024 if s['entries'] else 0))
0362 stream.write("| <img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/blue-dot.gif' width='%d' height='%d' />" % (s['tot'] / treetotal * 200, 10))
0363 stream.write("| %.1f%%" % (s['tot'] / treetotal * 100.0))
0364 stream.write("| %.1f%%" % ((runningtotal+s['tot'])/treetotal * 100.0))
0365 stream.write("| %.1f%% |\n" % ((treetotal-runningtotal)/treetotal * 100.0))
0366 runningtotal += s['tot']
0367
0368
0369 stream.write("**All %s data**" % treename)
0370 stream.write("| | | | **%.2f**" % (treetotal/events))
0371 stream.write("| | <img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/green-dot.gif' width='%d' height='%d' />" % (treetotal / filesize * 100.0, 10))
0372 stream.write("| %.1f%%<sup>a</sup> | | |\n" % (treetotal/filesize * 100.0))
0373
0374 if treename == "Events":
0375
0376 stream.write("**Non per-event data or overhead**")
0377 stream.write("| | | | %.2f" % ((filesize-treetotal)/events))
0378 stream.write("| | <img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/red-dot.gif' width='%d' height='%d' />" % ((filesize - treetotal) / filesize * 100, 10))
0379 stream.write("| %.1f%%<sup>a</sup> | | |\n" % ((filesize-treetotal)/filesize * 100.0))
0380
0381 if len(surveys) > 1:
0382
0383 stream.write("**Overhead**")
0384 stream.write("| | | | %.2f" % ((filesize-runningtotal)/events))
0385 stream.write("| | <img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/red-dot.gif' width='%d' height='%d' />" % ((filesize - runningtotal) / filesize * 100, 10))
0386 stream.write("| %.1f%%<sup>a</sup> | | |\n" % ((filesize-runningtotal)/filesize * 100.0))
0387
0388
0389 stream.write("**File size**")
0390 stream.write("| | | | **%.2f**" % (filesize/events))
0391 stream.write("| | | | | |\n\n")
0392
0393 stream.write("Note: size percentages of individual event products are relative to the total size of Event data only (or equivalent for non-Events trees).\\\n")
0394 stream.write("Percentages with <sup>a</sup> are instead relative to the full file size.\n\n")
0395
0396 for treename, survey in surveys.items():
0397 stream.write("# %s detail\n" % treename)
0398 for s in sorted(survey, key=lambda s: s['name']):
0399 stream.write("## <a id='%s'></a>%s (%.1f items/evt, %.3f kb/evt) [<sup>[back to top]</sup>](#event-data)\n" % (s['name'].lower(), s['name'], s['entries'] / events, s['tot'] / events))
0400 stream.write("| branch | kind | b/event | b/item | plot | % |\n")
0401 stream.write("| - | - | - | - | - | - |\n")
0402 subs = [trees[treename]['branches'][b] for b in s['subs']]
0403 for b in sorted(subs, key = lambda s: - s['tot']):
0404 stream.write("| <b title='%s'>%s</b> | %s | %.1f | %.1f" % (b['doc'].replace('|', '\|').replace('\'', '\"'), b['name'], b['kind'], b['tot'] / events * 1024, b['tot'] / s['entries'] * 1024 if s['entries'] else 0))
0405 stream.write("| <img src='http://gpetrucc.web.cern.ch/gpetrucc/micro/blue-dot.gif' width='%d' height='%d' />" % (b['tot'] / s['tot'] * 200, 10))
0406 stream.write("| %.1f%% |\n" % (b['tot'] / s['tot'] * 100.0))
0407 stream.write("\n")
0408
0409 def writeMarkdownDocReport(trees, stream):
0410 for treename, treeData in trees.items():
0411 stream.write("# %s Content\n" % treename)
0412 stream.write("\n| Collection | Description |\n")
0413 stream.write("| - | - |\n")
0414 groups = list(treeData['branchgroups'].values())
0415 groups.sort(key = lambda s : s['name'])
0416 for s in groups:
0417 stream.write("| [**%s**](#%s) | %s |\n" % (s['name'], s['name'].lower(), s['doc'].replace('|', '\|').replace('\'', '\"')))
0418 stream.write("\n# %s detail\n" % treename)
0419 for s in groups:
0420 stream.write("\n### <a id='%s'></a>%s [<sup>[back to top]</sup>](#%s-content)\n" % (s['name'].lower(), s['name'],treename.lower()))
0421 stream.write("| Object property | Type | Description |\n")
0422 stream.write("| - | - | - |\n")
0423 subs = [treeData['branches'][b] for b in s['subs']]
0424 for b in sorted(subs, key = lambda s : s['name']):
0425 stream.write("| **%s** | %s| %s |\n" % (b['name'], b['kind'], b['doc'].replace('|', '\|').replace('\'', '\"')))
0426 stream.write("\n")
0427
0428 def _maybeOpen(filename):
0429 return open(filename, 'w') if filename != "-" else sys.stdout
0430
0431 if __name__ == '__main__':
0432 from argparse import ArgumentParser
0433 parser = ArgumentParser()
0434 parser.add_argument("-j", "--json", dest="json", type=str, default=None, help="Write out json file")
0435 parser.add_argument("-d", "--doc", dest="doc", type=str, default=None, help="Write out html doc")
0436 parser.add_argument("-s", "--size", dest="size", type=str, default=None, help="Write out html size report")
0437 parser.add_argument("--docmd", dest="docmd", type=str, default=None, help="Write out markdown doc")
0438 parser.add_argument("--sizemd", dest="sizemd", type=str, default=None, help="Write out markdown size report")
0439 parser.add_argument("inputFile", type=str)
0440 options = parser.parse_args()
0441
0442 if options.inputFile.endswith(".root"):
0443 filedata = FileData(inspectRootFile(options.inputFile))
0444 elif options.inputFile.endswith(".json"):
0445 filedata = FileData(json.load(open(options.inputFile,'r')))
0446 else: raise RuntimeError("Input file %s is not a root or json file" % options.inputFile)
0447
0448 if options.json:
0449 json.dump(filedata._json, _maybeOpen(options.json), indent=4)
0450 sys.stderr.write("JSON output saved to %s\n" % options.json)
0451
0452 treedata = {}
0453 if len(filedata.Runs["branches"]) > 1:
0454 treedata["Runs"] = filedata.Runs
0455 if len(filedata.LuminosityBlocks["branches"]) > 2:
0456 treedata["LuminosityBlocks"] = filedata.LuminosityBlocks
0457 treedata["Events"] = filedata.Events
0458
0459 if options.doc:
0460 writeDocReport(filedata.filename, treedata, _maybeOpen(options.doc))
0461 sys.stderr.write("HTML documentation saved to %s\n" % options.doc)
0462 if options.size:
0463 writeSizeReport(filedata, treedata, _maybeOpen(options.size))
0464 sys.stderr.write("HTML size report saved to %s\n" % options.size)
0465 if options.docmd:
0466 writeMarkdownDocReport(treedata, _maybeOpen(options.docmd))
0467 sys.stderr.write("Markdown documentation saved to %s\n" % options.docmd)
0468 if options.sizemd:
0469 writeMarkdownSizeReport(filedata, treedata, _maybeOpen(options.sizemd))
0470 sys.stderr.write("Markdown size report saved to %s\n" % options.sizemd)