CMS 3D CMS Logo

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