CMS 3D CMS Logo

valtools.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # set of tools to create and submit validation webpages
3 # author: Colin
4 
5 from __future__ import print_function
6 import shutil, sys, os, re, glob, string
7 
8 from optparse import OptionParser
9 
10 
11 class webpage:
12 
13  # sets variables related to the creation of the local webpage.
14  def __init__(self):
15  self.parser_ = OptionParser()
16  self.parser_.add_option("-c", "--comments", dest="comments",
17  help="name of another release",
18  default=None)
19  self.parser_.add_option("-f", "--force", dest="force",
20  action="store_true",
21  help="overwrites the local benchmark page.",
22  default=False)
23  self.rootFile_ = 'benchmark.root'
24  self.dirPlots_ = './'
25  self.templates_ = '../Tools/templates'
26  self.date_ = os.popen( 'date' ).read()
27  self.benchmarkName_ = os.path.basename( os.getcwd() )
28 
29  def parseArgs(self):
30  (self.options_, self.args_) = self.parser_.parse_args()
31 
32  #create output dir, if it does not exist
33  def setOutputDir(self, outputDir ):
34 
35  self.outputDir_ = outputDir
36  if os.path.isdir( outputDir ):
37  print(outputDir, "already exists")
38  if self.options_.force == False:
39  print('sorry... run the script with the -h option for more information')
40  sys.exit(3)
41  else:
42  print('overwriting local output directory...')
43  else:
44  os.makedirs( outputDir )
45 
46  # read the caption file and produce the html
47  # code for the Plots section
48  def readCaptions(self, captions):
49  imgTemplate = '<IMG src="%s" width="500" align="left" border="0"><br clear="ALL">'
50  images = ''
51  captionsContents = open( captions )
52  for line in captionsContents:
53  try:
54  (picfile, caption) = self.readCaption( line )
55  img = imgTemplate % os.path.basename(picfile)
56  images = "%s<h3>%s:</h3>\n%s\n" % (images, caption, img)
57  # what to do if the file's not there?
58  # : print a warning
59  shutil.copy(picfile, self.outputDir_)
60  except Exception:
61  print('File %s does not exist. Did you generate the comparison plots?' % picfile)
62  print('Aborting the script.\n')
63  print('Solution 1: run without the -m "" option, to run the compare.C macro')
64  print('Solution 2: run with the -m "myMacro.C" option, to run another macro')
65  sys.exit(1)
66  raise
67  return images
68 
69  # decode a caption line, and return
70  # the caption, and the filename
71  # COULD HANDLE SEVERAL FILES
72  def readCaption( self, line ):
73 
74  if( re.compile('^\s*$').match(line) ):
75  raise Exception
76 
77  p = re.compile('^\s*(\S+)\s*\"(.*)\"');
78  m = p.match(line)
79  if m:
80  pic = m.group(1)
81  caption = m.group(2)
82  return (pic, caption)
83  else:
84  print('bad caption format: "%s"' % line)
85  raise Exception
86 
87 class website:
88  def __init__(self):
89  self.website_ = '/afs/cern.ch/cms/Physics/particleflow/Validation/cms-project-pfvalidation/Releases'
90  self.url_ = 'http://cern.ch/pfvalidation/Releases'
91 
92  def __str__(self):
93  return self.website_
94 
95 
96  def writeAccess(self):
97  if( os.access(self.website_, os.W_OK)==False ):
98  print('cannot write to the website. Please ask Colin to give you access.')
99  sys.exit(1)
100 
101  def listBenchmarks(self, pattern, afs=False, url=False):
102  for bench in glob.glob(self.website_ + '/' + pattern):
103  # strip off the root path of the website
104  p = re.compile('^%s/(\S+)$' % self.website_);
105  m = p.match( bench )
106  if m:
107  (release, benchName, extension) = decodePath( m.group(1) )
108  if release == None:
109  # this is a comparison
110  continue
111  print()
112  bench = benchmark(m.group(1))
113  print(bcolors.OKGREEN + m.group(1) + bcolors.ENDC)
114  if afs or url:
115  if afs: print(' ',bench.benchmarkOnWebSite( self ))
116  if url: print(' ',bench.benchmarkUrl( self ))
117 
118  def listComparisons(self, benchmark):
119 
120  comparisons = []
121  find = 'find %s -type d' % self.website_
122  for dir in os.popen( find ):
123  dir = dir.rstrip()
124  #print dir
125  comp = '%s/\S+/\S+/%s' % (self.website_,
126  benchmark.fullName() )
127  #print "** ", comp
128  p = re.compile(comp)
129  m = p.match(dir)
130  if m:
131  comparisons.append(dir)
132  #print ' ',dir
133  return comparisons
134 
135 class benchmark:
136 
137  # arg can be either the full name of a benchmark, or
138  # an extension, in which case, the release and benchmark name are guessed
139  # from the environment variables.
140  def __init__(self, arg=None):
141 
142  release = None
143  benchName = None
144  extension = None
145  self.indexHtml_ = 'index.html'
146 
147  if arg != None:
148  (release, benchName, extension) = decodePath( arg )
149 
150  if release == None:
151  # we get there if:
152  # - arg == None
153  # - the decoding of arg as a full benchmark name has failed.
154  self.release_ = os.environ['CMSSW_VERSION']
155 
156  # benchmark directory, as the current working directory
157  self.benchmark_ = os.path.basename( os.getcwd() )
158 
159  # underscore are not allowed in extension names
160  if arg!=None and arg.count('_'):
161  print('sorry, as said many times, underscores are not allowed in the extension ;P')
162  sys.exit(5)
163 
164  extension = arg
165  else:
166  self.release_ = release
167  self.benchmark_ = benchName
168 
170  if( extension != None ):
171  self.benchmarkWithExt_ = '%s_%s' % (self.benchmark_, extension)
172 
173 
174  def __str__(self):
175  return self.release_ + '/' + self.benchmarkWithExt_
176 
177  def fullName(self):
178  return self.release_ + '/' + self.benchmarkWithExt_
179 
180  def releaseOnWebSite( self, website ):
181  return '%s/%s' % ( website, self.release_ )
182 
183  def benchmarkOnWebSite( self, website ):
184  return '%s/%s' % ( website, self.fullName() )
185 # return '%s/%s' % ( self.releaseOnWebSite(website),
186 # self.benchmarkWithExt_ )
187 
188  def rootFileOnWebSite( self, website ):
189  return '%s/%s' % ( self.benchmarkOnWebSite(website),
190  'benchmark.root' )
191 
192  def releaseUrl( self, website ):
193  return '%s/%s' % ( website.url_, self.release_ )
194 
195 
196  def benchmarkUrl( self, website ):
197  return '%s/%s' % ( self.releaseUrl( website ),
198  self.benchmarkWithExt_ )
199 
200  def makeRelease( self, website):
201  rel = self.releaseOnWebSite(website)
202  if( os.path.isdir( rel )==False):
203  print('creating release %s' % self.release_)
204  print(rel)
205  os.mkdir( rel )
206 
207  def exists( self, website):
208  if( os.path.isdir( self.benchmarkOnWebSite(website) )):
209  print('benchmark %s exists for release %s' % (self.benchmarkWithExt_, self.release_))
210  return True
211  else:
212  print('benchmark %s does not exist for release %s' % (self.benchmarkWithExt_, self.release_))
213  return False
214 
215  def addLinkToComparison( self, website, comparison ):
216  url = comparison.comparisonUrl( website )
217  index = self.benchmarkOnWebSite(website) + '/' + self.indexHtml_
218  indexTmp = self.benchmarkOnWebSite(website) + '/index.tmp.html'
219  indexFile = open( index)
220  indexFileTmp = open( indexTmp, 'w')
221  for line in indexFile:
222  p = re.compile('<h2>Comparisons:</h2>')
223  m = p.match(line)
224  indexFileTmp.write(line)
225  if m:
226  link = '<A href="%s">%s</A><BR>\n' % (url, url)
227  indexFileTmp.write(link)
228  shutil.move( indexTmp, index)
229 
231 
232  def __init__(self, benchmark, comparisonPath):
233  self.benchmark_ = benchmark
234  self.path_ = comparisonPath
235 
236  def comparisonOnWebSite(self, website):
237  return '%s/%s' % ( self.benchmark_.benchmarkOnWebSite(website),
238  self.path_ )
239 
240  def comparisonUrl(self, website):
241  return '%s/%s' % ( self.benchmark_.benchmarkUrl(website),
242  self.path_ )
243 
244  def submit(self, website, force=False):
245  print('Submitting comparison:')
246  print(' from: ',self.path_)
247  print(' to : ',self.comparisonOnWebSite(website))
248 
249  if( os.path.isdir(self.comparisonOnWebSite(website) ) ):
250  print('comparison already exists')
251  if force:
252  print('overwriting comparison on the website...')
253  else:
254  print('submission cancelled. run with -h for a solution.')
255  return False
256  else:
257  print('comparison directory does not yet exist. creating it.')
258  mkdir = 'mkdir -p ' + self.comparisonOnWebSite(website)
259  print(mkdir)
260  if os.system( mkdir ):
261  print('problem creating the output directory on the website. Aborting.')
262  return False
263  cp = 'cp %s %s' % (self.path_ + '/*',
264  self.comparisonOnWebSite(website))
265  if os.system(cp):
266  print('problem copying the files to the website aborting')
267  return False
268 
269  print('access your comparison here:')
270  print(' ', self.comparisonUrl(website))
271 
272 
273 
274 # pathname in the form: CMSSW_3_1_0_pre7/TauBenchmarkGeneric_Extension
275 def decodePath( path ):
276  p = re.compile('^(\S+)/([^\s_]+)_(\S+)');
277  m = p.match(path)
278  if m:
279  release = m.group(1)
280  benchmarkname = m.group(2)
281  extension = m.group(3)
282  return (release, benchmarkname, extension )
283  else:
284  return (None, None, None)
285 
286 #test that a given file is a file with the correct extenstion, e.g. .root
287 def testFileType( file, ext ):
288 
289  if file == "None":
290  return
291 
292  if os.path.isfile( file ) == False:
293  print('%s is not a file' % file)
294  sys.exit(2)
295 
296  (fileroot, fileext) = os.path.splitext( file )
297  if fileext != ext:
298  print('%s does not end with %s' % (file, ext))
299  sys.exit(3)
300 
301 
302 # copy a file to a destination directory, and return the basename
303 # that is the filename without the path. that name is used
304 # to set a relative link in the html code
305 def processFile( file, outputDir ):
306 
307  if file == "None":
308  return 'infoNotFound.html'
309  else:
310  if os.path.isfile(file):
311  shutil.copy(file, outputDir)
312  return os.path.basename(file)
313  else:
314  return file
315 
316 class bcolors:
317  HEADER = '\033[95m'
318  OKBLUE = '\033[94m'
319  OKGREEN = '\033[92m'
320  WARNING = '\033[93m'
321  FAIL = '\033[91m'
322  ENDC = '\033[0m'
323 
324  def disable(self):
325  self.HEADER = ''
326  self.OKBLUE = ''
327  self.OKGREEN = ''
328  self.WARNING = ''
329  self.FAIL = ''
330  self.ENDC = ''
331 
def decodePath(path)
Definition: valtools.py:275
def __init__(self, benchmark, comparisonPath)
Definition: valtools.py:232
def parseArgs(self)
Definition: valtools.py:29
def writeAccess(self)
Definition: valtools.py:96
def rootFileOnWebSite(self, website)
Definition: valtools.py:188
def disable(self)
Definition: valtools.py:324
def __init__(self)
Definition: valtools.py:14
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def __str__(self)
Definition: valtools.py:174
def comparisonOnWebSite(self, website)
Definition: valtools.py:236
def readCaptions(self, captions)
Definition: valtools.py:48
def exists(self, website)
Definition: valtools.py:207
def processFile(file, outputDir)
Definition: valtools.py:305
def fullName(self)
Definition: valtools.py:177
def listComparisons(self, benchmark)
Definition: valtools.py:118
def releaseOnWebSite(self, website)
Definition: valtools.py:180
def testFileType(file, ext)
Definition: valtools.py:287
def listBenchmarks(self, pattern, afs=False, url=False)
Definition: valtools.py:101
def releaseUrl(self, website)
Definition: valtools.py:192
def __init__(self)
Definition: valtools.py:88
def comparisonUrl(self, website)
Definition: valtools.py:240
def readCaption(self, line)
Definition: valtools.py:72
def addLinkToComparison(self, website, comparison)
Definition: valtools.py:215
def submit(self, website, force=False)
Definition: valtools.py:244
def benchmarkOnWebSite(self, website)
Definition: valtools.py:183
def __init__(self, arg=None)
Definition: valtools.py:140
def __str__(self)
Definition: valtools.py:92
def benchmarkUrl(self, website)
Definition: valtools.py:196
def setOutputDir(self, outputDir)
Definition: valtools.py:33
std::pair< typename Association::data_type::first_type, double > match(Reference key, Association association, bool bestMatchByMaxValue)
Generic matching function.
Definition: Utils.h:10
def makeRelease(self, website)
Definition: valtools.py:200