CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
html.py
Go to the documentation of this file.
1 import os
2 import collections
3 
4 def _lowerFirst(s):
5  return s[0].lower()+s[1:]
6 
7 _sampleName = {
8  "RelValMinBias": "Min Bias",
9  "RelValTTbar": "TTbar",
10  "RelValQCD_Pt_600_800": "QCD Pt 600 to 800",
11  "RelValQCD_Pt_3000_3500": "QCD Pt 3000 to 3500",
12  "RelValQCD_FlatPt_15_3000": "QCD Flat Pt 15 to 3000",
13  "RelValZMM": "ZMuMu",
14  "RelValWjet_Pt_3000_3500": "Wjet Pt 3000 to 3500",
15  "RelValSingleElectronPt35": "Single Electron Pt 35",
16  "RelValSingleElectronPt10": "Single Electron Pt 10",
17  "RelValSingleMuPt10": "Single Muon Pt 10",
18  "RelValSingleMuPt100": "Single Muon Pt 100",
19 }
20 
21 _sampleFileName = {
22  "RelValMinBias": "minbias",
23  "RelValTTbar": "ttbar",
24  "RelValQCD_Pt600_800": "qcd600",
25  "RelValQCD_Pt3000_3500": "qcd3000",
26  "RelValQCD_FlatPt_15_3000": "qcdflat",
27  "RelValZMM": "zmm",
28  "RelValWjet_Pt_3000_3500": "wjet3000",
29  "RelValSingleElectronPt35": "ele35",
30  "RelValSingleElectronPt10": "ele10",
31  "RelValSingleMuPt10": "mu10",
32  "RelValSingleMuPt100": "mu100",
33 }
34 
35 _allTPEfficName = "All tracks (all TPs)"
36 _fromPVName = "Tracks from PV"
37 _fromPVAllTPName = "Tracks from PV (all TPs)"
38 _conversionName = "Tracks for conversions"
39 _trackQualityNameOrder = collections.OrderedDict([
40  ("seeding_seeds", "Seeds"),
41  ("seeding_seedsa", "Seeds A"),
42  ("seeding_seedsb", "Seeds B"),
43  ("seeding_seedstripl", "Seeds triplets"),
44  ("seeding_seedspair", "Seeds pairs"),
45  ("building_", "Built tracks"),
46  ("", "All tracks"),
47  ("highPurity", "High purity tracks"),
48  ("Pt", "Tracks pT > 0.9 GeV"),
49  ("highPurityPt", "High purity tracks pT > 0.9 GeV"),
50  ("ByOriginalAlgo", "All tracks by originalAlgo"),
51  ("highPurityByOriginalAlgo", "High purity tracks by originalAlgo"),
52  ("ByAlgoMask", "All tracks by algoMask"),
53  ("highPurityByAlgoMask", "High purity tracks by algoMask"),
54  ("btvLike", "BTV-like"),
55  ("ak4PFJets", "AK4 PF jets"),
56  ("allTPEffic_", _allTPEfficName),
57  ("allTPEffic_highPurity", _allTPEfficName.replace("All", "High purity")),
58  ("fromPV_", _fromPVName),
59  ("fromPV_highPurity", "High purity "+_lowerFirst(_fromPVName)),
60  ("fromPVAllTP_", _fromPVAllTPName),
61  ("fromPVAllTP_highPurity", "High purity "+_lowerFirst(_fromPVAllTPName)),
62  ("fromPVAllTP_Pt", _fromPVAllTPName.replace("Tracks", "Tracks pT > 0.9 GeV")),
63  ("fromPVAllTP_highPurityPt", "High purity "+_lowerFirst(_fromPVAllTPName).replace("tracks", "tracks pT > 0.9 GeV")),
64  ("fromPVAllTP2_", _fromPVAllTPName.replace("PV", "PV v2")),
65  ("fromPVAllTP2_highPurity", "High purity "+_lowerFirst(_fromPVAllTPName).replace("PV", "PV v2")),
66  ("fromPVAllTP2_Pt", _fromPVAllTPName.replace("Tracks", "Tracks pT > 0.9 GeV").replace("PV", "PV v2")),
67  ("fromPVAllTP2_highPurityPt", "High purity "+_lowerFirst(_fromPVAllTPName).replace("tracks", "tracks pT > 0.9 GeV").replace("PV", "PV v2")),
68  ("conversion_", _conversionName)
69 ])
70 
71 _trackAlgoName = {
72  "ootb": "Out of the box",
73  "iter0" : "Iterative Step 0",
74  "iter1" : "Iterative Step 1",
75  "iter2" : "Iterative Step 2",
76  "iter3" : "Iterative Step 3",
77  "iter4" : "Iterative Step 4",
78  "iter5" : "Iterative Step 5",
79  "iter6" : "Iterative Step 6",
80  "iter7" : "Iterative Step 7",
81  "iter9" : "Iterative Step 9",
82  "iter10": "Iterative Step 10",
83 }
84 
85 _trackAlgoOrder = [
86  'ootb',
87  'initialStepPreSplitting',
88  'initialStep',
89  'highPtTripletStep',
90  'lowPtQuadStep',
91  'lowPtTripletStep',
92  'pixelPairStep',
93  'detachedQuadStep',
94  'detachedTripletStep',
95  'mixedTripletStep',
96  'pixelLessStep',
97  'tobTecStep',
98  'jetCoreRegionalStep',
99  'muonSeededStepInOut',
100  'muonSeededStepOutIn',
101  'duplicateMerge',
102  'convStep',
103  'conversionStep',
104  'ckfInOutFromConversions',
105  'ckfOutInFromConversions',
106  'iter0',
107  'iter1',
108  'iter2',
109  'iter3',
110  'iter4',
111  'iter5',
112  'iter6',
113  'iter7',
114  'iter9',
115  'iter10',
116 ]
117 
118 _pageNameMap = {
119  "summary": "Summary",
120  "vertex": "Vertex",
121  "v0": "V0",
122  "miniaod": "MiniAOD",
123  "timing": "Timing",
124 }
125 
126 _sectionNameMapOrder = collections.OrderedDict([
127  # These are for the summary page
128  ("seeding_seeds", "Seeds"),
129  ("building", "Built tracks"),
130  ("", "All tracks"),
131  ("highPurity", "High purity tracks"),
132  ("allTPEffic", _allTPEfficName),
133  ("allTPEffic_highPurity", _allTPEfficName.replace("All", "High purity")),
134  ("fromPV", _fromPVName),
135  ("fromPV_highPurity", "High purity "+_lowerFirst(_fromPVName)),
136  ("fromPVAllTP", _fromPVAllTPName),
137  ("fromPVAllTP_highPurity", "High purity "+_lowerFirst(_fromPVAllTPName)),
138  ("conversion", _conversionName),
139  # These are for vertices
140  ("offlinePrimaryVertices", "All vertices (offlinePrimaryVertices)"),
141  ("selectedOfflinePrimaryVertices", "Selected vertices (selectedOfflinePrimaryVertices)"),
142  # These are for V0
143  ("k0", "K0"),
144  ("lambda", "Lambda"),
145 ])
146 _allTPEfficLegend = "All tracks, efficiency denominator contains all TrackingParticles"
147 _fromPVLegend = "Tracks from reco PV vs. TrackingParticles from gen PV (fake rate includes pileup tracks)"
148 _fromPVAllTPLegend = "Tracks from reco PV, fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
149 _fromPVAllTPPtLegend = "Tracks (pT &gt 0.9 GeV) from reco PV, fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
150 _fromPVAllTP2Legend = "Tracks from reco PV (another method), fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
151 _fromPVAllTPPt2Legend = "Tracks (pT &gt 0.9 GeV) from reco PV (another method), fake rate numerator contains all TrackingParticles (separates fake tracks from pileup tracks)"
152 
154  return {
155  "btvLike": "BTV-like selected tracks",
156  "ak4PFJets": "Tracks from AK4 PF jets (jet corrected pT > 10 GeV)",
157  "allTPEffic": _allTPEfficLegend,
158  "allTPEffic_": _allTPEfficLegend,
159  "allTPEffic_highPurity": _allTPEfficLegend.replace("All", "High purity"),
160  "fromPV": _fromPVLegend,
161  "fromPV_": _fromPVLegend,
162  "fromPV_highPurity": "High purity "+_lowerFirst(_fromPVLegend),
163  "fromPVAllTP": _fromPVAllTPLegend,
164  "fromPVAllTP_": _fromPVAllTPLegend,
165  "fromPVAllTP_highPurity": "High purity "+_lowerFirst(_fromPVAllTPLegend),
166  "fromPVAllTP_Pt": _fromPVAllTPPtLegend,
167  "fromPVAllTP_highPurityPt": "High purity "+_lowerFirst(_fromPVAllTPPtLegend),
168  "fromPVAllTP2_": _fromPVAllTP2Legend,
169  "fromPVAllTP2_highPurity": "High purity "+_lowerFirst(_fromPVAllTP2Legend),
170  "fromPVAllTP2_Pt": _fromPVAllTPPt2Legend,
171  "fromPVAllTP2_highPurityPt": "High purity "+_lowerFirst(_fromPVAllTPPt2Legend),
172  }
173 
174 class Table:
175  # table [column][row]
176  def __init__(self, columnHeaders, rowHeaders, table, purpose, page, section):
177  if len(columnHeaders) != len(table):
178  raise Exception("Got %d columnHeaders for table with %d columns for page %s, section %s" % (len(columnHeaders), len(table), page, section))
179  lenRow = len(table[0])
180  for icol, column in enumerate(table):
181  if len(column) != lenRow:
182  raise Exception("Got non-square table, first column has %d rows, column %d has %d rows" % (lenRow, icol, len(column)))
183  if len(rowHeaders) != lenRow:
184  raise Exception("Got %d rowHeaders for table with %d rows" % (len(rowHeaders), lenRow))
185 
186  self._columnHeaders = columnHeaders
187  self._rowHeaders = rowHeaders
188  self._table = table
189 
190  self._purpose = purpose
191  self._page = page
192  self._section = section
193 
194  def getPurpose(self):
195  return self._purpose
196 
197  def getPage(self):
198  return self._page
199 
200  def getSection(self):
201  return self._section
202 
203  def ncolumns(self):
204  return len(self._table)
205 
206  def nrows(self):
207  return len(self._table[0])
208 
209  def columnHeaders(self):
210  return self._columnHeaders
211 
212  def rowHeaders(self):
213  return self._rowHeaders
214 
215  def tableAsColumnRow(self):
216  return self._table
217 
218  def tableAsRowColumn(self):
219  return map(list, zip(*self._table))
220 
222  class TrackingIteration: pass
223  class TrackingSummary: pass
224  class Vertexing: pass
225  class MiniAOD: pass
226  class Timing: pass
227 
228 class Page(object):
229  def __init__(self, title, sampleName):
230  self._content = [
231  '<html>',
232  ' <head>',
233  ' <title>%s</title>' % title,
234  ' </head>',
235  ' <body>',
236  ' '+sampleName,
237  ' <br/>',
238  ' <br/>',
239  ]
240 
241  self._plotSets = {}
242  self._tables = {}
243 
244  def addPlotSet(self, section, plotSet):
245  self._plotSets[section] = plotSet
246 
247  def addTable(self, section, table):
248  self._tables[section] = table
249 
250  def isEmpty(self):
251  for plotSet in self._plotSets.itervalues():
252  if len(plotSet) > 0:
253  return False
254 
255  if len(self._tables) > 0:
256  return False
257 
258  return True
259 
260  def write(self, fileName):
261  self._legends = []
263  self._columnHeaders = []
265  self._formatPlotSets()
266  self._formatTables()
267  self._formatLegend()
268 
269  self._content.extend([
270  ' </body>',
271  '</html>',
272  ])
273 
274  #print "Writing HTML report page", fileName
275  f = open(fileName, "w")
276  for line in self._content:
277  f.write(line)
278  f.write("\n")
279  f.close()
280 
281  def _appendLegend(self, section):
282  leg = ""
283  legends = _sectionNameLegend()
284  if section in legends:
285  if section in self._sectionLegendIndex:
286  leg = self._sectionLegendIndex[section]
287  else:
288  legnum = len(self._legends)+1
289  leg = "<sup>%d</sup>" % legnum
290  leg2 = "<sup>%d)</sup>" % legnum
291  self._legends.append("%s %s" % (leg2, legends[section]))
292  self._sectionLegendIndex[section] = leg
293  return leg
294 
295  def _formatPlotSets(self):
296  self._content.extend([
297  ' <table>'
298  ' <tr>',
299  ])
300 
301  fileTable = []
302 
303  sections = self._orderSets(self._plotSets.keys())
304  for isec, section in enumerate(sections):
305  leg = self._appendLegend(section)
306 
307  self._content.extend([
308  ' <td>%s%s</td>' % (self._mapSectionName(section), leg),
309  ])
310  files = [(os.path.basename(f), f) for f in self._plotSets[section]]
311  for row in fileTable:
312  found = False
313  for i, (bsf, f) in enumerate(files):
314  if bsf == row[0]:
315  row.append(f)
316  found = True
317  del files[i]
318  break
319  if not found:
320  row.append(None)
321  for bsf, f in files:
322  fileTable.append( [bsf] + [None]*isec + [f] )
323 
324  self._content.extend([
325  ' </tr>',
326  ])
327 
328  for row in fileTable:
329  self._content.append(' <tr>')
330  bs = row[0]
331  for elem in row[1:]:
332  if elem is not None:
333  self._content.append(' <td><a href="%s">%s</a></td>' % (elem, bs))
334  else:
335  self._content.append(' <td></td>')
336  self._content.append(' </tr>')
337 
338 
339  self._content.extend([
340  ' </table>',
341  ])
342 
343  def _appendColumnHeader(self, header):
344  leg = ""
345  if header in self._columnHeadersIndex:
346  leg = self._columnHeadersIndex[header]
347  else:
348  leg = str(chr(ord('A')+len(self._columnHeaders)))
349  self._columnHeaders.append("%s: %s" % (leg, header))
350  self._columnHeadersIndex[header] = leg
351  return leg
352 
353  def _formatTables(self):
354  def _allNone(row):
355  for item in row:
356  if item is not None:
357  return False
358  return True
359 
360  sections = self._orderSets(self._tables.keys())
361  for isec, section in enumerate(sections):
362  leg = self._appendLegend(section)
363 
364  table = self._tables[section]
365  self._content.extend([
366  ' <br/>',
367  ' %s%s' % (self._mapSectionName(section), leg),
368  ' <table border="1">'
369  ])
370 
371  # table is stored in column-row, need to transpose
372  data = table.tableAsRowColumn()
373 
374  self._content.extend([
375  ' <tr>'
376  ' <td></td>'
377  ])
378  heads = table.columnHeaders()
379  if max(map(lambda h: len(h), heads)) > 20:
380  heads = [self._appendColumnHeader(h) for h in heads]
381  for head in heads:
382  self._content.append(' <td>%s</td>' % head)
383  self._content.append(' </tr>')
384 
385  for irow, row in enumerate(data):
386  # Skip row if all values are non-existent
387  if _allNone(row):
388  continue
389 
390  self._content.extend([
391  ' <tr>'
392  ' <td>%s</td>' % table.rowHeaders()[irow]
393  ])
394  # align the number columns to right
395  for icol, item in enumerate(row):
396  formatted = str(item) if item is not None else ""
397  self._content.append(' <td align="right">%s</td>' % formatted)
398  self._content.append(' </tr>')
399 
400  self._content.append(' </table>')
401 
402  for shortenedColumnHeader in self._columnHeaders:
403  self._content.append(' %s<br/>' % shortenedColumnHeader)
404  self._columnHeaders = []
405  self._columnHeadersIndex = {}
406 
407  def _formatLegend(self):
408  if len(self._legends) > 0:
409  self._content.extend([
410  ' <br/>'
411  ' Details:</br>',
412  ])
413  for leg in self._legends:
414  self._content.append(' %s<br/>' % leg)
415 
416 
417  def _mapSectionName(self, section):
418  return _sectionNameMapOrder.get(section, section)
419 
420  def _orderSets(self, keys):
421  ret = []
422  for section in _sectionNameMapOrder.keys():
423  if section in keys:
424  ret.append(section)
425  keys.remove(section)
426  ret.extend(keys)
427  return ret
428 
429 class PageSet(object):
430  def __init__(self, title, sampleName, sample, fastVsFull):
431  self._title = title
432  self._sampleName = sampleName
433  self._pages = collections.OrderedDict()
434 
435  self._prefix=""
436  if hasattr(sample, "hasPileup"):
437  self._prefix = "nopu"
438  if sample.hasPileup():
439  self._prefix = "pu"+sample.pileupType()
440  self._prefix += "_"
441 
442  if sample.fastsim():
443  self._prefix += "fast_"
444  if fastVsFull:
445  self._prefix += "full_"
446 
447  self._prefix += _sampleFileName.get(sample.label(), sample.label())+"_"
448 
449  def _getPage(self, key, pageClass):
450  if key not in self._pages:
451  page = pageClass(self._title, self._sampleName)
452  self._pages[key] = page
453  else:
454  page = self._pages[key]
455  return page
456 
457  def addPlotSet(self, plotterFolder, dqmSubFolder, plotFiles):
458  pageKey = plotterFolder.getPage()
459  if pageKey is None:
460  if dqmSubFolder is not None:
461  pageKey = dqmSubFolder.translated
462  else:
463  pageKey = plotterFolder.getName()
464 
465  page = self._getPage(pageKey, Page)
466  sectionName = plotterFolder.getSection()
467  if sectionName is None:
468  if plotterFolder.getPage() is not None and dqmSubFolder is not None:
469  sectionName = dqmSubFolder.translated
470  else:
471  sectionName = ""
472 
473  page.addPlotSet(sectionName, plotFiles)
474 
475  def addTable(self, table):
476  if table is None:
477  return
478 
479  page = self._getPage(table.getPage(), Page)
480  page.addTable(table.getSection(), table)
481 
482  def write(self, baseDir):
483  #print "TrackingPageSet.write"
484  ret = []
485 
486  keys = self._orderPages(self._pages.keys())
487  for key in keys:
488  page = self._pages[key]
489  if page.isEmpty():
490  continue
491 
492  fileName = "%s%s.html" % (self._prefix, key)
493  page.write(os.path.join(baseDir, fileName))
494  ret.append( (self._mapPagesName(key), fileName) )
495  return ret
496 
497  def _mapPagesName(self, name):
498  return _pageNameMap.get(name, name)
499 
500  def _orderPages(self, keys):
501  return keys
502 
503 
504 
506  def __init__(self, *args, **kwargs):
507  super(TrackingIterPage, self).__init__(*args, **kwargs)
508 
509  def _mapSectionName(self, quality):
510  return _trackQualityNameOrder.get(quality, quality)
511 
512  def _orderSets(self, qualities):
513  ret = []
514  for qual in _trackQualityNameOrder.keys():
515  if qual in qualities:
516  ret.append(qual)
517  qualities.remove(qual)
518  ret.extend(qualities)
519  return ret
520 
522  def __init__(self, *args, **kwargs):
523  super(TrackingPageSet, self).__init__(*args, **kwargs)
524 
525  def addPlotSet(self, plotterFolder, dqmSubFolder, plotFiles):
526  (algo, quality) = dqmSubFolder.translated
527 
528  pageName = algo
529  sectionName = quality
530 
531  # put all non-iterative stuff under OOTB
532  #
533  # it is bit of a hack to access trackingPlots.TrackingPlotFolder this way,
534  # but it was simple and it works
535  if algo != "ootb" and not plotterFolder._plotFolder.isAlgoIterative(algo):
536  pageName = "ootb"
537  sectionName = algo
538 
539  folderName = plotterFolder.getName()
540  if folderName != "":
541  sectionName = folderName+"_"+sectionName
542 
543  page = self._getPage(pageName, TrackingIterPage)
544  page.addPlotSet(sectionName, plotFiles)
545 
546  def _mapPagesName(self, algo): # algo = pageName
547  return _trackAlgoName.get(algo, algo)
548 
549  def _orderPages(self, algos):
550  ret = []
551  for algo in _trackAlgoOrder:
552  if algo in algos:
553  ret.append(algo)
554  algos.remove(algo)
555  ret.extend(algos)
556  return ret
557 
558 
559 
561  def __init__(self, sample, fastVsFull, title):
562  self._sample = sample
563 
564  self._sampleName = ""
565  if sample.fastsim():
566  self._sampleName += "FastSim "
567  if fastVsFull:
568  self._sampleName += "vs FullSim "
569 
570  pileup = ""
571  if hasattr(sample, "hasPileup"):
572  pileup = "with no pileup"
573  if sample.hasPileup():
574  pileup = "with %s pileup" % sample.pileupType()
575  self._sampleName += "%s sample %s" % (_sampleName.get(sample.name(), sample.name()), pileup)
576 
577  params = [title, self._sampleName, sample, fastVsFull]
578  self._summaryPage = PageSet(*params)
580  self._vertexPage = PageSet(*params)
581  self._miniaodPage = PageSet(*params)
582  self._timingPage = PageSet(*params)
583  self._otherPages = PageSet(*params)
584 
591  }
592 
593  def addPlots(self, plotterFolder, dqmSubFolder, plotFiles):
594  page = self._purposePageMap.get(plotterFolder.getPurpose(), self._otherPages)
595  page.addPlotSet(plotterFolder, dqmSubFolder, plotFiles)
596 
597  def addTable(self, table):
598  if table is None:
599  return
600 
601  page = self._purposePageMap.get(table.getPurpose(), self._otherPages)
602  page.addTable(table)
603  params = []
604 
605  def write(self, baseDir):
606  ret = [
607  " "+self._sampleName,
608  " <br/>",
609  " <ul>",
610  ]
611 
612  for pages in [self._summaryPage, self._iterationPages, self._vertexPage, self._miniaodPage, self._timingPage, self._otherPages]:
613  labelFiles = pages.write(baseDir)
614  for label, fname in labelFiles:
615  ret.append(' <li><a href="%s">%s</a></li>' % (fname, label))
616 
617  ret.extend([
618  ' </ul>',
619  ' <br/>',
620  ])
621 
622  return ret
623 
625  def __init__(self, validationName, newBaseDir):
626  self._title = "Tracking validation "+validationName
627  self._newBaseDir = newBaseDir
628 
629  self._index = [
630  '<html>',
631  ' <head>',
632  ' <title>%s</title>' % self._title,
633  ' </head>',
634  ' <body>',
635  ]
636 
637  self._sections = collections.OrderedDict()
638 
639  def addNote(self, note):
640  self._index.append(' <p>%s</p>'%note)
641 
642  def beginSample(self, sample, fastVsFull=False):
643  key = (sample.digest(), fastVsFull)
644  if key in self._sections:
645  self._currentSection = self._sections[key]
646  else:
647  self._currentSection = IndexSection(sample, fastVsFull, self._title)
648  self._sections[key] = self._currentSection
649 
650  def addPlots(self, *args, **kwargs):
651  self._currentSection.addPlots(*args, **kwargs)
652 
653  def addTable(self, *args, **kwargs):
654  self._currentSection.addTable(*args, **kwargs)
655 
656  def write(self):
657  # Reorder sections such that Fast vs. Full becomes just after the corresponding Fast
658  keys = self._sections.iterkeys()
659  newkeys = []
660  for key in keys:
661  if not key[1]:
662  newkeys.append(key)
663  continue
664  # is fast vs full
665  ind_fast = newkeys.index( (key[0], False) )
666  newkeys.insert(ind_fast+1, key)
667 
668  for key in newkeys:
669  section = self._sections[key]
670  self._index.extend(section.write(self._newBaseDir))
671 
672  self._index.extend([
673  " </body>",
674  "</html>",
675  ])
676 
677  f = open(os.path.join(self._newBaseDir, "index.html"), "w")
678  for line in self._index:
679  f.write(line)
680  f.write("\n")
681  f.close()
682 
684  def __init__(self):
685  pass
686 
687  def beginSample(self, *args, **kwargs):
688  pass
689 
690  def addPlots(self, *args, **kwargs):
691  pass
692 
693  def addTable(self, *args, **kwargs):
694  pass
def _formatPlotSets
Definition: html.py:295
_purpose
Definition: html.py:190
def addTable
Definition: html.py:653
def ncolumns
Definition: html.py:203
_legends
Definition: html.py:261
def addPlotSet
Definition: html.py:457
def rowHeaders
Definition: html.py:212
_content
Definition: html.py:230
_rowHeaders
Definition: html.py:187
def addPlotSet
Definition: html.py:244
def _sectionNameLegend
Definition: html.py:153
def getPurpose
Definition: html.py:194
def tableAsRowColumn
Definition: html.py:218
def columnHeaders
Definition: html.py:209
_columnHeaders
Definition: html.py:186
def addNote
Definition: html.py:639
def __init__
Definition: html.py:176
def _formatTables
Definition: html.py:353
def beginSample
Definition: html.py:642
def _lowerFirst
Definition: html.py:4
def _getPage
Definition: html.py:449
def _formatLegend
Definition: html.py:407
def getPage
Definition: html.py:197
def _orderPages
Definition: html.py:500
def addPlots
Definition: html.py:650
_columnHeaders
Definition: html.py:263
def _orderSets
Definition: html.py:420
def __init__
Definition: html.py:625
def write
Definition: html.py:482
_plotSets
Definition: html.py:241
def __init__
Definition: html.py:229
def _mapPagesName
Definition: html.py:497
def addTable
Definition: html.py:475
def __init__
Definition: html.py:430
def tableAsColumnRow
Definition: html.py:215
def nrows
Definition: html.py:206
def getSection
Definition: html.py:200
def _appendLegend
Definition: html.py:281
def write
Definition: html.py:260
_columnHeadersIndex
Definition: html.py:264
_section
Definition: html.py:192
def _mapSectionName
Definition: html.py:417
_tables
Definition: html.py:242
def isEmpty
Definition: html.py:250
def addTable
Definition: html.py:247
_sectionLegendIndex
Definition: html.py:262
def _appendColumnHeader
Definition: html.py:343