CMS 3D CMS Logo

produceOfflineValidationTex.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # This script creates a .tex-file for displaying the results
3 # of an offline alignment validation of the CMS tracker.
4 #
5 # HOW TO USE:
6 # -Pass the paths of the directories containing the plots as arguments
7 # (these would be the ExtendedValidationImages-directories of the
8 # relevant validations). E.g.
9 # produceOfflineValidationTex.py plotdir1 plotdir2
10 # -To change the general properties of the presentation to be produced,
11 # modify the templates found in presentationTemplates.py.
12 # -To produce different plots, use the writePageReg-function to select
13 # the types of files you want on a page.
14 #
15 #
16 # Originally by Eemeli Tomberg, 2014
17 
18 
19 
20 import sys
21 import re
22 import os
23 import stat
24 import math
25 import time
27 
28 subdetectors = ["BPIX", "FPIX", "TIB", "TOB", "TID", "TEC"]
29 
30 
31 # Plots related to a single validation:
33  def __init__(self, path):
34  if not os.path.isdir(path):
35  print "Error: Directory "+path+" not found!"
36  exit(1)
37  if not path.endswith('/'):
38  path += '/'
39  path = path.replace('\\', '/') # Beacause LaTeX has issues with '\'.
40  self.path = path
41  # List of plot files in given directory:
42  self.plots = [file for file in os.listdir(path)
43  if file.endswith('.eps')]
44 
45 
46 # Layout of plots on a page:
47 class PageLayout:
48  def __init__(self, pattern=[], width=1, height=1):
49  self.pattern = [] # List of rows; row contains the order numbers
50  # of its plots; e.g. [[1,2,3], [4,5,6]]
51  self.width = width # Maximum width of one plot,
52  # with respect to textwidth.
53  self.height = height # Maximum height of one plot,
54  # with respect to textheight.
55 
56  # Sets variables for the given plots and returns the plots
57  # in an appropriate order:
58  def fit(self, plots):
59  rowlengths = []
60  # First, try to place plots in a square.
61  nplots = sum(len(p) for p in plots)
62  length = int(math.ceil(math.sqrt(nplots)))
63  # Then, fill the square from the bottom and remove extra rows.
64  fullRows = int(nplots/length)
65  residual = nplots - length*fullRows
66  nrows = fullRows
67  if residual != 0:
68  rowlengths.append(residual)
69  nrows += 1
70  for _ in xrange(fullRows):
71  rowlengths.append(length)
72 
73  # Now, fill the pattern.
74  self.pattern = []
75  if residual == 0 and len(plots[0])%length != 0 and\
76  len(plots[0])%nrows == 0:
77  # It's better to arrange plots in columns, not rows.
78  self.pattern.extend(range(i, i+nrows*(length-1)+1, nrows)
79  for i in range(1, nrows+1))
80  else:
81  if residual != 0:
82  self.pattern.append(range(1, 1+residual))
83  self.pattern.extend(range(i, i+length) for i in
84  range(residual+1, nplots-length+2, length))
85 
86  self.width = 1.0/length
87  self.height = 0.8/nrows
88 
89 
90 # Write a set of pages, one for each subdetector.
91 # Arguments: identifier: regular expression to get the wanted plots,
92 # used together with subdetector name
93 # title: title of the plot type
94 # validations: list of relevant ValidationPlots objects.
95 # Returns the parsed script.
96 def writeSubsection(identifier, title, validations):
97  script = ''
98  for subdetector in subdetectors:
99  script += writePageReg('(?=.*%s)%s'%(subdetector, identifier),
100  title+': ' +subdetector, validations)
101  if script != '':
102  script = subsectionTemplate.replace('[title]', title)+script
103  return script
104 
105 
106 # Write a page containing plots of given type.
107 # Arguments: identifier: regular expression to get the wanted plots
108 # title: title of the plot type
109 # validations: list of relevant ValidationPlots objects
110 # layout: given page layout.
111 # Returns the parsed script.
112 def writePageReg(identifier, title, validations, layout=0):
113  plots = []
114  for validation in validations:
115  valiplots = [validation.path+plot for plot in validation.plots
116  if re.search(identifier, plot)]
117  valiplots.sort(key=plotSortKey)
118  plots.append(valiplots)
119  if sum(len(p) for p in plots) == 0:
120  print 'Warning: no plots matching ' + identifier
121  return ''
122 
123  # Create layout, if not given.
124  if layout == 0:
125  layout = PageLayout()
126  layout.fit(plots)
127 
128  return writePage([p for vali in plots for p in vali], title, layout)
129 
130 
131 # Write the given plots on a page.
132 # Arguments: plots: paths of plots to be drawn on the page
133 # title: title of the plot type
134 # layout: a PageLayout object definig the layout.
135 # Returns the parsed script.
136 def writePage(plots, title, layout):
137  plotrows = []
138  for row in layout.pattern:
139  plotrow = []
140  for i in xrange(len(row)):
141  plotrow.append(plotTemplate.replace('[width]', str(layout.width)).\
142  replace('[height]', str(layout.height)).\
143  replace('[path]', plots[row[i]-1]))
144  plotrows.append('\n'.join(plotrow))
145  script = ' \\\\\n'.join(plotrows)
146 
147  return frameTemplate.replace('[plots]', script).replace('[title]', title)
148 
149 
150 # Sort key to rearrange a plot list.
151 # Arguments: plot: to be sorted.
152 def plotSortKey(plot):
153  # Move normchi2 before chi2Prob
154  if plot.find('normchi2') != -1:
155  return 'chi2a'
156  if plot.find('chi2Prob') != -1:
157  return 'chi2b'
158  return plot
159 
160 
161 
162 
163 
164 
165 # Script execution.
166 def main():
167  print 'Producing a .tex file from plots...'
168 
169  # Get plots from given paths
170  if len(sys.argv) < 2:
171  print 'Error: Need path of plots as an argument!'
172  sys.exit(1)
173 
174  validations = []
175  for plotpath in sys.argv[1:]:
176  validations.append(ValidationPlots(plotpath))
177 
178  # Compose .tex frames
179  frames = ''
180  # chi2
181  frames += subsectionTemplate.replace('[title]', 'Chi^2 plots')
182  frames += writePageReg('chi2', r'$\chi^2$ plots', validations)
183  # DMRs
184  frames += writeSubsection('DmedianY*R.*plain.eps$', 'DMR', validations)
185  # Split DMRs
186  frames += writeSubsection('DmedianY*R.*split.eps$','Split DMR',validations)
187  # DRnRs:
188  frames += writeSubsection('DrmsNY*R.*plain.eps$', 'DRnR', validations)
189  # Surface Shapes
190  frames += writeSubsection('SurfaceShape', 'Surface Shape', validations)
191  # Additional plots
192  #frames += writePageReg('YourRegExp', 'PageTitle', validations)
193 
194  # Write final .tex file
195  file = open('presentation.tex', 'w')
196  file.write(texTemplate.replace('[frames]', frames).\
197  replace('[time]', time.ctime()))
198  file.close()
199 
200  # A script to get from .tex to .pdf
201  pdfScript = open('toPdf.sh', 'w')
202  pdfScript.write(toPdf)
203  pdfScript.close()
204  os.chmod("toPdf.sh", stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH)
205 
206 
207 
208 if __name__ == '__main__':
209  main()
def replace(string, replacements)
def __init__(self, pattern=[], width=1, height=1)
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
Definition: main.py:1
def writePageReg(identifier, title, validations, layout=0)
def writeSubsection(identifier, title, validations)