CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
presentation.py
Go to the documentation of this file.
1 from __future__ import print_function
2 from __future__ import absolute_import
3 from builtins import range
4 import abc
5 import math
6 import os
7 import re
8 
9 from .genericValidation import ValidationForPresentation, ValidationWithPlotsSummary
10 from .helperFunctions import recursivesubclasses
11 from .presentationTemplates import *
12 from .TkAlExceptions import AllInOneError
13 
14 # Plots related to a single validation:
15 class ValidationPlots(object):
16  def __init__(self, path):
17  if not os.path.isdir(path):
18  print("Error: Directory "+path+" not found!")
19  exit(1)
20  if not path.endswith('/'):
21  path += '/'
22  path = path.replace('\\', '/') # Beacause LaTeX has issues with '\'.
23  self.path = path
24  # List of plot files in given directory:
25  self.plots = [file for file in os.listdir(path)
26  if file.endswith('.eps')]
27 
28  @property
29  def validationclass(self):
30  possiblenames = []
31  for cls in recursivesubclasses(ValidationForPresentation):
32  if cls.__abstractmethods__: continue
33  if cls.plotsdirname() == os.path.basename(os.path.realpath(self.path.rstrip("/"))):
34  return cls
35  possiblenames.append(cls.plotsdirname())
36  raise AllInOneError("{} does not match any of the possible folder names:\n{}".format(self.path, ", ".join(possiblenames)))
37 
38 def validationclasses(validations):
39  from collections import OrderedDict
40  classes = [validation.validationclass for validation in validations]
41  #remove duplicates - http://stackoverflow.com/a/39835527/5228524
42  classes = list(OrderedDict.fromkeys(classes))
43  return classes
44 
45 # Layout of plots on a page:
46 class PageLayout(object):
47  def __init__(self, pattern=[], width=1, height=1):
48  self.pattern = [] # List of rows; row contains the order numbers
49  # of its plots; e.g. [[1,2,3], [4,5,6]]
50  self.width = width # Maximum width of one plot,
51  # with respect to textwidth.
52  self.height = height # Maximum height of one plot,
53  # with respect to textheight.
54 
55  # Sets variables for the given plots and returns the plots
56  # in an appropriate order:
57  def fit(self, plots):
58  rowlengths = []
59  # First, try to place plots in a square.
60  nplots = sum(len(p) for p in plots)
61  length = int(math.ceil(math.sqrt(nplots)))
62  # Then, fill the square from the bottom and remove extra rows.
63  fullRows = int(nplots/length)
64  residual = nplots - length*fullRows
65  nrows = fullRows
66  if residual != 0:
67  rowlengths.append(residual)
68  nrows += 1
69  for _ in range(fullRows):
70  rowlengths.append(length)
71 
72  # Now, fill the pattern.
73  self.pattern = []
74  if residual == 0 and len(plots[0])%length != 0 and\
75  len(plots[0])%nrows == 0:
76  # It's better to arrange plots in columns, not rows.
77  self.pattern.extend(list(range(i, i+nrows*(length-1)+1, nrows))
78  for i in range(1, nrows+1))
79  else:
80  if residual != 0:
81  self.pattern.append(list(range(1, 1+residual)))
82  self.pattern.extend(list(range(i, i+length)) for i in
83  range(residual+1, nplots-length+2, length))
84 
85  self.width = 1.0/length
86  self.height = 0.8/nrows
87 
88 
89 # Write a set of pages, one for each subdetector.
90 # Arguments: identifier: regular expression to get the wanted plots,
91 # used together with subdetector name
92 # title: title of the plot type
93 # validations: list of relevant ValidationPlots objects.
94 # Returns the parsed script.
95 class SubsectionBase(object):
96  __metaclass__ = abc.ABCMeta
97  def __init__(self, title):
98  self.title = title
99  def write(self, validations):
100  script = '\n'.join(_ for _ in self.pages(validations) if _)
101  if script != '':
102  script = subsectionTemplate.replace('[title]', self.title)+script
103  return script
104  @abc.abstractmethod
105  def pages(self, validations):
106  pass
107 
108 class SubsectionOnePage(SubsectionBase):
109  def __init__(self, identifier, title):
110  self.identifier = identifier
111  super(SubsectionOnePage, self).__init__(title)
112  def pages(self, validations):
113  return [writePageReg(self.identifier, self.title, validations)]
114 
116  def __init__(self, identifier, title):
117  self.identifier = identifier
118  super(SubsectionFromList, self).__init__(title)
119  def pages(self, validations):
120  return [writePageReg('(?=.*%s)%s'%(pageidentifier, self.identifier),
121  self.title+': ' +pagetitle, validations)
122  for pageidentifier, pagetitle in self.pageidentifiers]
123  @abc.abstractproperty
124  def pageidentifiers(self):
125  pass
126 
127 class SummarySection(SubsectionBase):
128  def __init__(self):
129  super(SummarySection, self).__init__("Summary")
130  def pages(self, validations):
131  return [summaryTemplate.replace('[title]', self.title)
132  .replace('[summary]', validation.validationclass.summaryitemsstring(folder=validation.path, latex=True))
133  .replace("tabular", "longtable") for validation in validations
134  if issubclass(validation.validationclass, ValidationWithPlotsSummary)]
135 
136 # Write a page containing plots of given type.
137 # Arguments: identifier: regular expression to get the wanted plots
138 # title: title of the plot type
139 # validations: list of relevant ValidationPlots objects
140 # layout: given page layout.
141 # Returns the parsed script.
142 def writePageReg(identifier, title, validations, layout=0):
143  plots = []
144  for validation in validations:
145  valiplots = [validation.path+plot for plot in validation.plots
146  if re.search(identifier, plot)]
147  valiplots.sort(key=plotSortKey)
148  plots.append(valiplots)
149  if sum(len(p) for p in plots) == 0:
150  print('Warning: no plots matching ' + identifier)
151  return ''
152 
153  # Create layout, if not given.
154  if layout == 0:
155  layout = PageLayout()
156  layout.fit(plots)
157 
158  return writePage([p for vali in plots for p in vali], title, layout)
159 
160 
161 # Write the given plots on a page.
162 # Arguments: plots: paths of plots to be drawn on the page
163 # title: title of the plot type
164 # layout: a PageLayout object definig the layout.
165 # Returns the parsed script.
166 def writePage(plots, title, layout):
167  plotrows = []
168  for row in layout.pattern:
169  plotrow = []
170  for i in range(len(row)):
171  plotrow.append(plotTemplate.replace('[width]', str(layout.width)).\
172  replace('[height]', str(layout.height)).\
173  replace('[path]', plots[row[i]-1]))
174  plotrows.append('\n'.join(plotrow))
175  script = ' \\\\\n'.join(plotrows)
176 
177  return frameTemplate.replace('[plots]', script).replace('[title]', title)
178 
179 
180 # Sort key to rearrange a plot list.
181 # Arguments: plot: to be sorted.
182 def plotSortKey(plot):
183  # Move normchi2 before chi2Prob
184  if plot.find('normchi2') != -1:
185  return 'chi2a'
186  if plot.find('chi2Prob') != -1:
187  return 'chi2b'
188  return plot
189 
190 import Alignment.OfflineValidation.TkAlAllInOneTool.geometryComparison
const uint16_t range(const Frame &aFrame)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
static std::string join(char **cmd)
Definition: RemoteFile.cc:19
#define str(s)
def validationclasses
Definition: presentation.py:38