File indexing completed on 2024-04-06 12:33:24
0001 import os
0002 import collections
0003
0004 def _lowerFirst(s):
0005 return s[0].lower()+s[1:]
0006
0007 _sampleName = {
0008 "RelValMinBias": "Min Bias",
0009 "RelValTTbar": "TTbar",
0010 "RelValQCD_Pt_600_800": "QCD Pt 600 to 800",
0011 "RelValQCD_Pt_3000_3500": "QCD Pt 3000 to 3500",
0012 "RelValQCD_FlatPt_15_3000": "QCD Flat Pt 15 to 3000",
0013 "RelValZMM": "ZMuMu",
0014 "RelValWjet_Pt_3000_3500": "Wjet Pt 3000 to 3500",
0015 "RelValH125GGgluonfusion": "Higgs to gamma gamma",
0016 "RelValSingleElectronPt35": "Single Electron Pt 35",
0017 "RelValSingleElectronPt35Extended": "Single Electron Pt 35 (extended eta)",
0018 "RelValSingleElectronPt10": "Single Electron Pt 10",
0019 "RelValSingleMuPt1": "Single Muon Pt 1",
0020 "RelValSingleMuPt10": "Single Muon Pt 10",
0021 "RelValSingleMuPt10Extended": "Single Muon Pt 10 (extended eta)",
0022 "RelValSingleMuPt100": "Single Muon Pt 100",
0023 "RelValTenMuE_0_200": "Ten muon Pt 0-200",
0024 }
0025
0026 _sampleFileName = {
0027 "RelValMinBias": "minbias",
0028 "RelValTTbar": "ttbar",
0029 "RelValQCD_Pt_600_800": "qcd600",
0030 "RelValQCD_Pt_3000_3500": "qcd3000",
0031 "RelValQCD_FlatPt_15_3000": "qcdflat",
0032 "RelValZMM": "zmm",
0033 "RelValWjet_Pt_3000_3500": "wjet3000",
0034 "RelValH125GGgluonfusion": "hgg",
0035 "RelValSingleElectronPt35": "ele35",
0036 "RelValSingleElectronPt35Extended": "ele35ext",
0037 "RelValSingleElectronPt10": "ele10",
0038 "RelValSingleMuPt1": "mu1",
0039 "RelValSingleMuPt10": "mu10",
0040 "RelValSingleMuPt10Extended": "mu10ext",
0041 "RelValSingleMuPt100": "mu100",
0042 "RelValTenMuE_0_200": "tenmu200",
0043 }
0044
0045 _allName = "All tracks"
0046 _allTPEfficName = _allName+" (all TPs)"
0047 _fromPVName = "Tracks from PV"
0048 _fromPVAllTPName = "Tracks from PV (all TPs)"
0049 _tpPtLess09Name = "All tracks (TP pT < 0.9 GeV)"
0050 _tpEtaGreater2p7Name = "All tracks (TP |eta| > 2.7)"
0051 _conversionName = "Tracks for conversions"
0052 _gsfName = "Electron GSF tracks"
0053 _bhadronName = "All tracks (B-hadron TPs)"
0054 _displacedName = "All tracks (TPs with no tip or lip cuts)"
0055 def _toHP(s):
0056 return "High purity "+_lowerFirst(s)
0057 def _toOriAlgo(s):
0058 return s.replace("tracks", "tracks by originalAlgo")
0059 def _toAlgoMask(s):
0060 return s.replace("tracks", "tracks by algoMask")
0061 def _allToHP(s):
0062 return s.replace("All", "High purity")
0063 def _allToBTV(s):
0064 return s.replace("All", "BTV-like")
0065 def _allPtCut(s):
0066 return s.replace("All tracks", "Tracks pT > 0.9 GeV")
0067 def _ptCut(s):
0068 return s.replace("Tracks", "Tracks pT > 0.9 GeV").replace("tracks", "tracks pT > 0.9 GeV")
0069 def _allToPixel(s):
0070 return s.replace("All", "Pixel")
0071 def _toPixel(s):
0072 return s.replace("Tracks", "Pixel tracks")
0073 _trackQualityNameOrder = collections.OrderedDict([
0074 ("seeding_seeds", "Seeds"),
0075 ("seeding_seedsa", "Seeds A"),
0076 ("seeding_seedsb", "Seeds B"),
0077 ("seeding_seedsc", "Seeds C"),
0078 ("seeding_seedstripl", "Seeds triplets"),
0079 ("seeding_seedspair", "Seeds pairs"),
0080 ("building_", "Built tracks"),
0081 ("", _allName),
0082 ("highPurity", _allToHP(_allName)),
0083 ("Pt09", _allPtCut(_allName)),
0084 ("highPurityPt09", _ptCut(_allToHP(_allName))),
0085 ("ByOriginalAlgo", _toOriAlgo(_allName)),
0086 ("highPurityByOriginalAlgo", _toOriAlgo(_toHP(_allName))),
0087 ("ByAlgoMask", _toAlgoMask(_allName)),
0088 ("highPurityByAlgoMask", _toAlgoMask(_toHP(_allName))),
0089 ("tpPtLess09_", _tpPtLess09Name),
0090 ("tpPtLess09_highPurity", _allToHP(_tpPtLess09Name)),
0091 ("tpPtLess09_ByOriginalAlgo", _toOriAlgo(_tpPtLess09Name)),
0092 ("tpPtLess09_highPurityByOriginalAlgo", _toOriAlgo(_allToHP(_tpPtLess09Name))),
0093 ("tpPtLess09_ByAlgoMask", _toAlgoMask(_tpPtLess09Name)),
0094 ("tpPtLess09_highPurityByAlgoMask", _toAlgoMask(_allToHP(_tpPtLess09Name))),
0095 ("tpEtaGreater2p7_", _tpEtaGreater2p7Name),
0096 ("tpEtaGreater2p7_highPurity", _allToHP(_tpEtaGreater2p7Name)),
0097 ("btvLike", _allToBTV(_allName)),
0098 ("ak4PFJets", "AK4 PF jets"),
0099 ("allTPEffic_", _allTPEfficName),
0100 ("allTPEffic_highPurity", _allToHP(_allTPEfficName)),
0101 ("fromPV_", _fromPVName),
0102 ("fromPV_highPurity", _toHP(_fromPVName)),
0103 ("fromPV_Pt09", _ptCut(_fromPVName)),
0104 ("fromPV_highPurityPt09", _toHP(_ptCut(_fromPVName))),
0105 ("fromPVAllTP_", _fromPVAllTPName),
0106 ("fromPVAllTP_highPurity", _toHP(_fromPVAllTPName)),
0107 ("fromPVAllTP_Pt09", _ptCut(_fromPVAllTPName)),
0108 ("fromPVAllTP_highPurityPt09", _toHP(_ptCut(_fromPVAllTPName))),
0109 ("fromPVAllTP2_", _fromPVAllTPName.replace("PV", "PV v2")),
0110 ("fromPVAllTP2_highPurity", "High purity "+_lowerFirst(_fromPVAllTPName).replace("PV", "PV v2")),
0111 ("fromPVAllTP2_Pt09", _fromPVAllTPName.replace("Tracks", "Tracks pT > 0.9 GeV").replace("PV", "PV v2")),
0112 ("fromPVAllTP2_highPurityPt09", _toHP(_ptCut(_fromPVAllTPName)).replace("PV", "PV v2")),
0113 ("conversion_", _conversionName),
0114 ("gsf_", _gsfName),
0115 ("bhadron_", _bhadronName),
0116 ("bhadron_highPurity", _allToHP(_bhadronName)),
0117 ("bhadron_ByOriginalAlgo", _toOriAlgo(_bhadronName)),
0118 ("bhadron_highPurityByOriginalAlgo", _toOriAlgo(_toHP(_bhadronName))),
0119 ("bhadron_ByAlgoMask", _toAlgoMask(_bhadronName)),
0120 ("bhadron_highPurityByAlgoMask", _toAlgoMask(_allToHP(_bhadronName))),
0121 ("bhadron_btvLike", _allToBTV(_bhadronName)),
0122 ("displaced_", _displacedName),
0123 ("displaced_highPurity", _allToHP(_displacedName)),
0124 ("displaced_ByOriginalAlgo", _toOriAlgo(_displacedName)),
0125 ("displaced_highPurityByOriginalAlgo", _toOriAlgo(_allToHP(_displacedName))),
0126 ("displaced_ByAlgoMask", _toAlgoMask(_displacedName)),
0127 ("displaced_highPurityByAlgoMask", _toAlgoMask(_allToHP(_displacedName))),
0128
0129 ("pixel_", _allToPixel(_allName)),
0130 ("pixel_Pt09", _ptCut(_allToPixel(_allName))),
0131 ("pixelFromPV_", _toPixel(_fromPVName)),
0132 ("pixelFromPV_Pt09", _ptCut(_toPixel(_fromPVName))),
0133 ("pixelFromPVAllTP_", _toPixel(_fromPVAllTPName)),
0134 ("pixelFromPVAllTP_Pt09", _ptCut(_toPixel(_fromPVAllTPName))),
0135 ("pixelbhadron_", _allToPixel(_bhadronName)),
0136 ("pixelbhadron_Pt09", _ptCut(_allToPixel(_bhadronName))),
0137 ])
0138
0139 _trackAlgoName = {
0140 "ootb": "Out of the box",
0141 "iter0" : "Iterative Step 0",
0142 "iter1" : "Iterative Step 1",
0143 "iter2" : "Iterative Step 2",
0144 "iter3" : "Iterative Step 3",
0145 "iter4" : "Iterative Step 4",
0146 "iter5" : "Iterative Step 5",
0147 "iter6" : "Iterative Step 6",
0148 "iter7" : "Iterative Step 7",
0149 "iter9" : "Iterative Step 9",
0150 "iter10": "Iterative Step 10",
0151 "pixel": "Pixel tracks",
0152 }
0153
0154 _trackAlgoOrder = [
0155 'ootb',
0156 'initialStepPreSplitting',
0157 'initialStep',
0158 'highPtTripletStep',
0159 'detachedQuadStep',
0160 'detachedTripletStep',
0161 'lowPtQuadStep',
0162 'lowPtTripletStep',
0163 'pixelPairStep',
0164 'mixedTripletStep',
0165 'pixelLessStep',
0166 'tobTecStep',
0167 'displacedGeneralStep',
0168 'jetCoreRegionalStep',
0169 'muonSeededStepInOut',
0170 'muonSeededStepOutIn',
0171 'displacedRegionalStep',
0172 'duplicateMerge',
0173 'convStep',
0174 'conversionStep',
0175 'ckfInOutFromConversions',
0176 'ckfOutInFromConversions',
0177 'electronGsf',
0178 'iter0',
0179 'iter1',
0180 'iter2',
0181 'iter3',
0182 'iter4',
0183 'iter5',
0184 'iter6',
0185 'iter7',
0186 'iter9',
0187 'iter10',
0188 "pixel",
0189 ]
0190
0191 _pageNameMap = {
0192 "summary": "Summary",
0193 "vertex": "Vertex",
0194 "v0": "V0",
0195 "miniaod": "MiniAOD",
0196 "timing": "Timing",
0197 "hlt": "HLT",
0198 "pixel": "Pixel tracks",
0199 "pf": "PF",
0200 }
0201
0202 _sectionNameMapOrder = collections.OrderedDict([
0203
0204 ("seeding_seeds", "Seeds"),
0205 ("building", "Built tracks"),
0206 ("", _allName),
0207 ("Pt09", _allPtCut(_allName)),
0208 ("highPurity", _allToHP(_allName)),
0209 ("highPurityPt09", _ptCut(_allToHP(_allName))),
0210 ("tpPtLess09", _tpPtLess09Name),
0211 ("tpPtLess09_highPurity", _allToHP(_tpPtLess09Name)),
0212 ("tpEtaGreater2p7", _tpEtaGreater2p7Name),
0213 ("tpEtaGreater2p7_highPurity", _allToHP(_tpEtaGreater2p7Name)),
0214 ("btvLike", "BTV-like"),
0215 ("ak4PFJets", "AK4 PF jets"),
0216 ("allTPEffic", _allTPEfficName),
0217 ("allTPEffic_highPurity", _allToHP(_allTPEfficName)),
0218 ("fromPV", _fromPVName),
0219 ("fromPV_highPurity", "High purity "+_lowerFirst(_fromPVName)),
0220 ("fromPVAllTP", _fromPVAllTPName),
0221 ("fromPVAllTP_highPurity", "High purity "+_lowerFirst(_fromPVAllTPName)),
0222 ("conversion", _conversionName),
0223 ("gsf", _gsfName),
0224 ("bhadron", _bhadronName),
0225 ("bhadron_highPurity", _allToHP(_bhadronName)),
0226 ("displaced", _displacedName),
0227 ("displaced_highPurity", _allToHP(_displacedName)),
0228
0229 ("pixel", _allToPixel(_allName)),
0230 ("pixelPt09", _ptCut(_allToPixel(_allName))),
0231 ("pixelFromPV", _toPixel(_fromPVName)),
0232 ("pixelFromPVPt09", _ptCut(_toPixel(_fromPVName))),
0233 ("pixelFromPVAllTP", _toPixel(_fromPVAllTPName)),
0234 ("pixelFromPVAllTPPt09", _ptCut(_toPixel(_fromPVAllTPName))),
0235 ("pixelbhadron", _allToPixel(_bhadronName)),
0236 ("pixelbhadronPt09", _ptCut(_allToPixel(_bhadronName))),
0237
0238 ("genvertex", "Gen vertices"),
0239 ("pixelVertices", "Pixel vertices"),
0240 ("selectedPixelVertices", "Selected pixel vertices"),
0241 ("firstStepPrimaryVerticesPreSplitting", "firstStepPrimaryVerticesPreSplitting"),
0242 ("firstStepPrimaryVertices", "firstStepPrimaryVertices"),
0243 ("offlinePrimaryVertices", "All vertices (offlinePrimaryVertices)"),
0244 ("selectedOfflinePrimaryVertices", "Selected vertices (selectedOfflinePrimaryVertices)"),
0245 ("offlinePrimaryVerticesWithBS", "All vertices with BS constraint"),
0246 ("selectedOfflinePrimaryVerticesWithBS", "Selected vertices with BS constraint"),
0247
0248 ("k0", "K0"),
0249 ("lambda", "Lambda"),
0250 ])
0251 _btvLegend = "BTV-like selected tracks"
0252 _allTPEfficLegend = "All tracks, efficiency denominator contains all TrackingParticles"
0253 _fromPVLegend = "Tracks from reco PV vs. TrackingParticles from gen PV (fake rate includes pileup tracks)"
0254 _fromPVPtLegend = "Tracks (pT > 0.9 GeV) from reco PV vs. TrackingParticles from gen PV (fake rate includes pileup tracks)"
0255 _fromPVAllTPLegend = "Tracks from reco PV, fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
0256 _fromPVAllTPPtLegend = "Tracks (pT > 0.9 GeV) from reco PV, fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
0257 _fromPVAllTP2Legend = "Tracks from reco PV (another method), fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
0258 _fromPVAllTPPt2Legend = "Tracks (pT > 0.9 GeV) from reco PV (another method), fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
0259 _bhadronLegend = "All tracks, efficiency denominator contains only TrackingParticles from B-hadron decays"
0260 _bhadronPtLegend = "Tracks (pT > 0.9 GeV), efficiency denominator contains only TrackingParticles from B-hadron decays"
0261
0262 def _sectionNameLegend():
0263 return {
0264 "btvLike": _btvLegend,
0265 "ak4PFJets": "Tracks from AK4 PF jets (jet corrected pT > 10 GeV)",
0266 "allTPEffic": _allTPEfficLegend,
0267 "allTPEffic_": _allTPEfficLegend,
0268 "allTPEffic_highPurity": _allToHP(_allTPEfficLegend),
0269 "fromPV": _fromPVLegend,
0270 "fromPV_": _fromPVLegend,
0271 "fromPV_highPurity": _toHP(_fromPVLegend),
0272 "fromPV_Pt09": _fromPVPtLegend,
0273 "fromPV_highPurity_Pt09": _toHP(_fromPVPtLegend),
0274 "fromPVAllTP": _fromPVAllTPLegend,
0275 "fromPVAllTP_": _fromPVAllTPLegend,
0276 "fromPVAllTP_highPurity": _toHP(_fromPVAllTPLegend),
0277 "fromPVAllTP_Pt09": _fromPVAllTPPtLegend,
0278 "fromPVAllTP_highPurityPt09": _toHP(_fromPVAllTPPtLegend),
0279 "fromPVAllTP2_": _fromPVAllTP2Legend,
0280 "fromPVAllTP2_highPurity": _toHP(_fromPVAllTP2Legend),
0281 "fromPVAllTP2_Pt09": _fromPVAllTPPt2Legend,
0282 "fromPVAllTP2_highPurityPt09": _toHP(_fromPVAllTPPt2Legend),
0283 "bhadron_": _bhadronLegend,
0284 "bhadron_highPurity": _allToHP(_bhadronLegend),
0285 "bhadron_btvLike": _bhadronLegend.replace("All tracks", _btvLegend),
0286 "pixelFromPV_": _fromPVLegend,
0287 "pixelFromPV_Pt09": _fromPVPtLegend,
0288 "pixelFromPVAllTP_": _fromPVAllTPLegend,
0289 "pixelFromPVAllTP_Pt09": _fromPVAllTPPtLegend,
0290 "pixelbhadron_": _bhadronLegend,
0291 "pixelbhadron_Pt09": _bhadronPtLegend,
0292 }
0293
0294 class Table:
0295
0296 def __init__(self, columnHeaders, rowHeaders, table, purpose, page, section):
0297 if len(columnHeaders) != len(table):
0298 raise Exception("Got %d columnHeaders for table with %d columns for page %s, section %s" % (len(columnHeaders), len(table), page, section))
0299 lenRow = len(table[0])
0300 for icol, column in enumerate(table):
0301 if len(column) != lenRow:
0302 raise Exception("Got non-square table, first column has %d rows, column %d has %d rows" % (lenRow, icol, len(column)))
0303 if len(rowHeaders) != lenRow:
0304 raise Exception("Got %d rowHeaders for table with %d rows" % (len(rowHeaders), lenRow))
0305
0306 self._columnHeaders = columnHeaders
0307 self._rowHeaders = rowHeaders
0308 self._table = table
0309
0310 self._purpose = purpose
0311 self._page = page
0312 self._section = section
0313
0314 def getPurpose(self):
0315 return self._purpose
0316
0317 def getPage(self):
0318 return self._page
0319
0320 def getSection(self):
0321 return self._section
0322
0323 def ncolumns(self):
0324 return len(self._table)
0325
0326 def nrows(self):
0327 return len(self._table[0])
0328
0329 def columnHeaders(self):
0330 return self._columnHeaders
0331
0332 def rowHeaders(self):
0333 return self._rowHeaders
0334
0335 def tableAsColumnRow(self):
0336 return self._table
0337
0338 def tableAsRowColumn(self):
0339 return map(list, zip(*self._table))
0340
0341 class PlotPurpose:
0342 class TrackingIteration: pass
0343 class TrackingSummary: pass
0344 class Vertexing: pass
0345 class MiniAOD: pass
0346 class Timing: pass
0347 class HLT: pass
0348 class Pixel: pass
0349 class PF: pass
0350
0351 class Page(object):
0352 def __init__(self, title, sampleName):
0353 self._content = [
0354 '<html>',
0355 ' <head>',
0356 ' <title>%s</title>' % title,
0357 ' </head>',
0358 ' <body>',
0359 ' '+sampleName,
0360 ' <br/>',
0361 ' <br/>',
0362 ]
0363
0364 self._plotSets = {}
0365 self._tables = {}
0366
0367 def addPlotSet(self, section, plotSet):
0368 if section in self._plotSets:
0369 self._plotSets[section].extend(plotSet)
0370 else:
0371 self._plotSets[section] = plotSet
0372
0373 def addTable(self, section, table):
0374 self._tables[section] = table
0375
0376 def isEmpty(self):
0377 for plotSet in self._plotSets.values():
0378 if len(plotSet) > 0:
0379 return False
0380
0381 if len(self._tables) > 0:
0382 return False
0383
0384 return True
0385
0386 def write(self, fileName):
0387 self._legends = []
0388 self._sectionLegendIndex = {}
0389 self._columnHeaders = []
0390 self._columnHeadersIndex = {}
0391 self._formatPlotSets()
0392 self._formatTables()
0393 self._formatLegend()
0394
0395 self._content.extend([
0396 ' </body>',
0397 '</html>',
0398 ])
0399
0400
0401 f = open(fileName, "w")
0402 for line in self._content:
0403 f.write(line)
0404 f.write("\n")
0405 f.close()
0406
0407 def _appendLegend(self, section):
0408 leg = ""
0409 legends = _sectionNameLegend()
0410 if section in legends:
0411 if section in self._sectionLegendIndex:
0412 leg = self._sectionLegendIndex[section]
0413 else:
0414 legnum = len(self._legends)+1
0415 leg = "<sup>%d</sup>" % legnum
0416 leg2 = "<sup>%d)</sup>" % legnum
0417 self._legends.append("%s %s" % (leg2, legends[section]))
0418 self._sectionLegendIndex[section] = leg
0419 return leg
0420
0421 def _formatPlotSets(self):
0422 self._content.extend([
0423 ' <table>'
0424 ' <tr>',
0425 ])
0426
0427 fileTable = []
0428
0429 sections = self._orderSets(list(self._plotSets.keys()))
0430 for isec, section in enumerate(sections):
0431 leg = self._appendLegend(section)
0432
0433 self._content.extend([
0434 ' <td>%s%s</td>' % (self._mapSectionName(section), leg),
0435 ])
0436 files = [(os.path.basename(f), f) for f in self._plotSets[section]]
0437 for row in fileTable:
0438 found = False
0439 for i, (bsf, f) in enumerate(files):
0440 if bsf == row[0]:
0441 row.append(f)
0442 found = True
0443 del files[i]
0444 break
0445 if not found:
0446 row.append(None)
0447 for bsf, f in files:
0448 fileTable.append( [bsf] + [None]*isec + [f] )
0449
0450 self._content.extend([
0451 ' </tr>',
0452 ])
0453
0454 for row in fileTable:
0455 self._content.append(' <tr>')
0456 bs = row[0]
0457 for elem in row[1:]:
0458 if elem is not None:
0459 self._content.append(' <td><a href="%s">%s</a></td>' % (elem, bs))
0460 else:
0461 self._content.append(' <td></td>')
0462 self._content.append(' </tr>')
0463
0464
0465 self._content.extend([
0466 ' </table>',
0467 ])
0468
0469 if len(fileTable):
0470 first_row = fileTable[0]
0471 self._content.extend([
0472 ' <a href="%s">Browse Folder</a>' % (first_row[1][0:first_row[1].rfind('/')])
0473 ])
0474
0475 def _appendColumnHeader(self, header):
0476 leg = ""
0477 if header in self._columnHeadersIndex:
0478 leg = self._columnHeadersIndex[header]
0479 else:
0480 leg = str(chr(ord('A')+len(self._columnHeaders)))
0481 self._columnHeaders.append("%s: %s" % (leg, header))
0482 self._columnHeadersIndex[header] = leg
0483 return leg
0484
0485 def _formatTables(self):
0486 def _allNone(row):
0487 for item in row:
0488 if item is not None:
0489 return False
0490 return True
0491
0492 sections = self._orderSets(list(self._tables.keys()))
0493 for isec, section in enumerate(sections):
0494 leg = self._appendLegend(section)
0495
0496 table = self._tables[section]
0497 self._content.extend([
0498 ' <br/>',
0499 ' %s%s' % (self._mapSectionName(section), leg),
0500 ' <table border="1">'
0501 ])
0502
0503
0504 data = table.tableAsRowColumn()
0505
0506 self._content.extend([
0507 ' <tr>'
0508 ' <td></td>'
0509 ])
0510 heads = table.columnHeaders()
0511 if max(map(lambda h: len(h), heads)) > 20:
0512 heads = [self._appendColumnHeader(h) for h in heads]
0513 for head in heads:
0514 self._content.append(' <td>%s</td>' % head)
0515 self._content.append(' </tr>')
0516
0517 for irow, row in enumerate(data):
0518
0519 if _allNone(row):
0520 continue
0521
0522 self._content.extend([
0523 ' <tr>'
0524 ' <td>%s</td>' % table.rowHeaders()[irow]
0525 ])
0526
0527 for icol, item in enumerate(row):
0528 formatted = str(item) if item is not None else ""
0529 self._content.append(' <td align="right">%s</td>' % formatted)
0530 self._content.append(' </tr>')
0531
0532 self._content.append(' </table>')
0533
0534 for shortenedColumnHeader in self._columnHeaders:
0535 self._content.append(' %s<br/>' % shortenedColumnHeader)
0536 self._columnHeaders = []
0537 self._columnHeadersIndex = {}
0538
0539 def _formatLegend(self):
0540 if len(self._legends) > 0:
0541 self._content.extend([
0542 ' <br/>'
0543 ' Details:</br>',
0544 ])
0545 for leg in self._legends:
0546 self._content.append(' %s<br/>' % leg)
0547
0548
0549 def _mapSectionName(self, section):
0550 return _sectionNameMapOrder.get(section, section)
0551
0552 def _orderSets(self, keys):
0553 keys_sorted = sorted(keys)
0554 ret = []
0555 for section in _sectionNameMapOrder.keys():
0556 if section in keys_sorted:
0557 ret.append(section)
0558 keys_sorted.remove(section)
0559 ret.extend(keys_sorted)
0560 return ret
0561
0562 class PageSet(object):
0563 def __init__(self, title, sampleName, sample, fastVsFull, pileupComparison, dqmSubFolderTranslatedToSectionName=None):
0564 self._title = title
0565 self._sampleName = sampleName
0566 self._pages = collections.OrderedDict()
0567 self._dqmSubFolderTranslatedToSectionName = dqmSubFolderTranslatedToSectionName
0568
0569 self._prefix = ""
0570 if sample.fastsim():
0571 self._prefix += "fast_"
0572 if fastVsFull:
0573 self._prefix += "full_"
0574
0575 self._prefix += _sampleFileName.get(sample.label(), sample.label())+"_"
0576 if hasattr(sample, "hasScenario") and sample.hasScenario():
0577 self._prefix += sample.scenario()+"_"
0578
0579 if hasattr(sample, "hasPileup"):
0580 if sample.hasPileup():
0581 self._prefix += "pu"+str(sample.pileupNumber())+"_"+sample.pileupType()+"_"
0582 else:
0583 self._prefix += "nopu_"
0584 if pileupComparison:
0585 self._prefix += "vspu_"
0586
0587
0588 def _getPage(self, key, pageClass):
0589 if key not in self._pages:
0590 page = pageClass(self._title, self._sampleName)
0591 self._pages[key] = page
0592 else:
0593 page = self._pages[key]
0594 return page
0595
0596 def addPlotSet(self, plotterFolder, dqmSubFolder, plotFiles):
0597 pageKey = plotterFolder.getPage()
0598 if pageKey is None:
0599 if dqmSubFolder is not None:
0600 pageKey = dqmSubFolder.translated
0601 else:
0602 pageKey = plotterFolder.getName()
0603
0604 page = self._getPage(pageKey, Page)
0605 sectionName = plotterFolder.getSection()
0606 if sectionName is None:
0607 if plotterFolder.getPage() is not None and dqmSubFolder is not None:
0608 if self._dqmSubFolderTranslatedToSectionName is not None:
0609 sectionName = self._dqmSubFolderTranslatedToSectionName(dqmSubFolder.translated)
0610 else:
0611 sectionName = dqmSubFolder.translated
0612 else:
0613 sectionName = ""
0614
0615 page.addPlotSet(sectionName, plotFiles)
0616
0617 def addTable(self, table):
0618 if table is None:
0619 return
0620
0621 page = self._getPage(table.getPage(), Page)
0622 page.addTable(table.getSection(), table)
0623
0624 def write(self, baseDir):
0625
0626 ret = []
0627
0628 keys = self._orderPages(list(self._pages.keys()))
0629 for key in keys:
0630 page = self._pages[key]
0631 if page.isEmpty():
0632 continue
0633
0634 fileName = "%s%s.html" % (self._prefix, key)
0635 page.write(os.path.join(baseDir, fileName))
0636 ret.append( (self._mapPagesName(key), fileName) )
0637 return ret
0638
0639 def _mapPagesName(self, name):
0640 return _pageNameMap.get(name, name)
0641
0642 def _orderPages(self, keys):
0643 return keys
0644
0645
0646
0647 class TrackingIterPage(Page):
0648 def __init__(self, *args, **kwargs):
0649 super(TrackingIterPage, self).__init__(*args, **kwargs)
0650
0651 def _mapSectionName(self, quality):
0652 return _trackQualityNameOrder.get(quality, quality)
0653
0654 def _orderSets(self, qualities):
0655 ret = []
0656 for qual in _trackQualityNameOrder.keys():
0657 if qual in qualities:
0658 ret.append(qual)
0659 qualities.remove(qual)
0660 ret.extend(qualities)
0661 return ret
0662
0663 class TrackingPageSet(PageSet):
0664 def __init__(self, *args, **kwargs):
0665 super(TrackingPageSet, self).__init__(*args, **kwargs)
0666
0667 def addPlotSet(self, plotterFolder, dqmSubFolder, plotFiles):
0668 (algo, quality) = dqmSubFolder.translated
0669
0670 pageName = algo
0671 sectionName = quality
0672
0673
0674
0675
0676
0677 if algo != "ootb" and not plotterFolder._plotFolder.isAlgoIterative(algo):
0678 pageName = "ootb"
0679 sectionName = algo
0680
0681 folderName = plotterFolder.getName()
0682 if folderName != "":
0683 sectionName = folderName+"_"+sectionName
0684
0685 page = self._getPage(pageName, TrackingIterPage)
0686 page.addPlotSet(sectionName, plotFiles)
0687
0688 def _mapPagesName(self, algo):
0689 return _trackAlgoName.get(algo, algo)
0690
0691 def _orderPages(self, algos):
0692 ret = []
0693 for algo in _trackAlgoOrder:
0694 if algo in algos:
0695 ret.append(algo)
0696 algos.remove(algo)
0697 ret.extend(algos)
0698 return ret
0699
0700
0701
0702 class IndexSection:
0703 def __init__(self, sample, title, fastVsFull, pileupComparison):
0704 self._sample = sample
0705
0706 self._sampleName = ""
0707 if sample.fastsim():
0708 self._sampleName += "FastSim "
0709 if fastVsFull:
0710 self._sampleName += "vs FullSim "
0711
0712 pileup = ""
0713 if hasattr(sample, "hasPileup"):
0714 pileup = "with no pileup"
0715 if sample.hasPileup():
0716 pileup = "with %d pileup (%s)" % (sample.pileupNumber(), sample.pileupType())
0717 if pileupComparison is not None:
0718 pileup += " "+pileupComparison
0719 if hasattr(sample, "customPileupLabel"):
0720 pileup = sample.customPileupLabel()
0721
0722 scenario = ""
0723 if hasattr(sample, "hasScenario") and sample.hasScenario():
0724 scenario = " (\"%s\")" % sample.scenario()
0725 self._sampleName += "%s sample%s %s" % (_sampleName.get(sample.name(), sample.name()), scenario, pileup)
0726
0727 params = [title, self._sampleName, sample, fastVsFull, pileupComparison is not None]
0728 self._summaryPage = PageSet(*params)
0729 self._iterationPages = TrackingPageSet(*params)
0730 self._vertexPage = PageSet(*params)
0731 self._miniaodPage = PageSet(*params)
0732 self._timingPage = PageSet(*params)
0733 self._pfPages = PageSet(*params)
0734 self._hltPages = PageSet(*params, dqmSubFolderTranslatedToSectionName=lambda algoQuality: algoQuality[0])
0735 self._pixelPages = TrackingPageSet(*params)
0736 self._otherPages = PageSet(*params)
0737
0738 self._purposePageMap = {
0739 PlotPurpose.TrackingIteration: self._iterationPages,
0740 PlotPurpose.TrackingSummary: self._summaryPage,
0741 PlotPurpose.Vertexing: self._vertexPage,
0742 PlotPurpose.MiniAOD: self._miniaodPage,
0743 PlotPurpose.Timing: self._timingPage,
0744 PlotPurpose.PF: self._pfPages,
0745 PlotPurpose.HLT: self._hltPages,
0746 PlotPurpose.Pixel: self._pixelPages,
0747 }
0748
0749 def addPlots(self, plotterFolder, dqmSubFolder, plotFiles):
0750 page = self._purposePageMap.get(plotterFolder.getPurpose(), self._otherPages)
0751 page.addPlotSet(plotterFolder, dqmSubFolder, plotFiles)
0752
0753 def addTable(self, table):
0754 if table is None:
0755 return
0756
0757 page = self._purposePageMap.get(table.getPurpose(), self._otherPages)
0758 page.addTable(table)
0759 params = []
0760
0761 def write(self, baseDir):
0762 ret = [
0763 " "+self._sampleName,
0764 " <br/>",
0765 " <ul>",
0766 ]
0767
0768 for pages in [self._summaryPage, self._iterationPages, self._pixelPages, self._vertexPage, self._miniaodPage, self._timingPage, self._hltPages, self._pfPages, self._otherPages]:
0769 labelFiles = pages.write(baseDir)
0770 for label, fname in labelFiles:
0771 ret.append(' <li><a href="%s">%s</a></li>' % (fname, label))
0772
0773 ret.extend([
0774 ' </ul>',
0775 ' <br/>',
0776 ])
0777
0778 return ret
0779
0780 class HtmlReport:
0781 def __init__(self, validationName, newBaseDir):
0782 self._title = "Tracking validation "+validationName
0783 self._newBaseDir = newBaseDir
0784
0785 self._index = [
0786 '<html>',
0787 ' <head>',
0788 ' <title>%s</title>' % self._title,
0789 ' </head>',
0790 ' <body>',
0791 ]
0792
0793 self._sections = collections.OrderedDict()
0794
0795 def addNote(self, note):
0796 self._index.append(' <p>%s</p>'%note)
0797
0798 def beginSample(self, sample, fastVsFull=False, pileupComparison=None):
0799
0800
0801 rightAfterRefSample = fastVsFull or (pileupComparison is not None)
0802
0803 key = (sample.digest(), rightAfterRefSample)
0804 if key in self._sections:
0805 self._currentSection = self._sections[key]
0806 else:
0807 self._currentSection = IndexSection(sample, self._title, fastVsFull, pileupComparison)
0808 self._sections[key] = self._currentSection
0809
0810 def addPlots(self, *args, **kwargs):
0811 self._currentSection.addPlots(*args, **kwargs)
0812
0813 def addTable(self, *args, **kwargs):
0814 self._currentSection.addTable(*args, **kwargs)
0815
0816 def write(self):
0817
0818 keys = self._sections.keys()
0819 newkeys = []
0820 for key in keys:
0821 if not key[1]:
0822 newkeys.append(key)
0823 continue
0824
0825 ind_fast = newkeys.index( (key[0], False) )
0826 newkeys.insert(ind_fast+1, key)
0827
0828 for key in newkeys:
0829 section = self._sections[key]
0830 self._index.extend(section.write(self._newBaseDir))
0831
0832 self._index.extend([
0833 " </body>",
0834 "</html>",
0835 ])
0836
0837 f = open(os.path.join(self._newBaseDir, "index.html"), "w")
0838 for line in self._index:
0839 f.write(line)
0840 f.write("\n")
0841 f.close()
0842
0843 class HtmlReportDummy:
0844 def __init__(self):
0845 pass
0846
0847 def beginSample(self, *args, **kwargs):
0848 pass
0849
0850 def addPlots(self, *args, **kwargs):
0851 pass
0852
0853 def addTable(self, *args, **kwargs):
0854 pass