CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
runEdmFileComparison.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 import optparse
4 import commands
5 import pprint
6 import re
7 import os
8 import sys
9 
10 piecesRE = re.compile (r'(.+?)\s+"(\S+)"\s+"(\S*)"\s+"(\S+)"')
11 #colonRE = re.compile (r':+')
12 nonAlphaRE = re.compile (r'\W')
13 commaRE = re.compile (r',')
14 queueCommand = '/uscms/home/cplager/bin/clpQueue.pl addjob %s'
15 logDir = 'logfiles'
16 compRootDir = 'compRoot'
17 # Containers
18 #vectorRE = re.compile (r'^vector<(\S+)>')
19 vectorRE = re.compile (r'^vector<([^<>]+)>')
20 detSetVecRE = re.compile (r'^edm::DetSetVector<([^<>]+)>')
21 edColRE = re.compile (r'^edm::EDCollection<([^<>]+)>')
22 sortedColRE = re.compile (r'^edm::SortedCollection<([^<>]+),\S+?> >')
23 singletonRE = re.compile (r'^([\w:]+)$')
24 containerList = [vectorRE, detSetVecRE, edColRE, sortedColRE]
25 
26 class EdmObject (object):
27 
28  def __init__ (self, tup):
29  self.container, self.one, self.two, self.three = tup
30  self.bool = False
31  for regex in containerList:
32  match = regex.search( self.container)
33  if match:
34  self.bool = True
35  self.name = match.group(1)
36  break
37 
38  def __str__ (self):
39  return pprint.pformat (self.__dict__)
40 
41  def __bool__ (self):
42  return self.bool
43 
44  def label (self):
45  return "%s,%s,%s" % (self.one, self.two, self.three)
46 
47 
48 if __name__ == "__main__":
49 
50  ###################
51  ## Setup Options ##
52  ###################
53  parser = optparse.OptionParser ("%prog [options] file1.root [file2.root]"\
54  "\nFor more details, see\nhttps://twiki.cern.ch/twiki/bin/view/CMS/SWGuidePhysicsToolsEdmOneToOneComparison")
55  describeGroup = optparse.OptionGroup (parser, "Description Options")
56  precisionGroup = optparse.OptionGroup (parser, "Precision Options")
57  summaryGroup = optparse.OptionGroup (parser, "Summary Options")
58  queueGroup = optparse.OptionGroup (parser, "Queue Options")
59  verboseGroup = optparse.OptionGroup (parser, "Verbose Options")
60  # general optionos
61  parser.add_option ("--compRoot", dest="compRoot",
62  action="store_true", default=False,
63  help="Make compRoot files.")
64  parser.add_option ("--prefix", dest="prefix", type="string",
65  help="Prefix to prepend to logfile name")
66  parser.add_option ("--regex", dest='regex', action="append",
67  type="string", default=[],
68  help="Only run on branches containing regex")
69  # describe options
70  describeGroup.add_option ("--describeOnly", dest="describeOnly",
71  action="store_true", default=False,
72  help="Run description step only and stop.")
73  describeGroup.add_option ("--forceDescribe", dest="forceDescribe",
74  action="store_true", default=False,
75  help="Run description step even if "\
76  "file already exists.")
77  describeGroup.add_option ("--singletons", dest="singletons",
78  action="store_true", default=False,
79  help="Describe singleton objects (" \
80  "used only with --describeOnly option).")
81  describeGroup.add_option ("--privateMemberData", dest="privateMemberData",
82  action="store_true", default=False,
83  help="include private member data "\
84  "(NOT for comparisons)")
85  # precision options
86  precisionGroup.add_option ("--precision", dest="precision", type="string",
87  help="Change precision use for floating "\
88  "point numbers")
89  precisionGroup.add_option ('--absolute', dest='absolute',
90  action='store_true', default=False,
91  help='Precision is checked against '\
92  'absolute difference')
93  precisionGroup.add_option ('--relative', dest='relative',
94  action='store_true', default=False,
95  help='Precision is checked against '\
96  'relative difference')
97  # summary options
98  summaryGroup.add_option ("--summary", dest="summary",
99  action="store_true", default=False,
100  help="Print out summary counts at end")
101  summaryGroup.add_option ("--summaryFull", dest="summaryFull",
102  action="store_true", default=False,
103  help="Print out full summary at end (VERY LONG)")
104  # queue options
105  queueGroup.add_option ("--noQueue", dest="noQueue",
106  action="store_true", default=True,
107  help="Do not use queue, but run "\
108  "jobs serially (default).")
109  queueGroup.add_option ("--queue", dest="noQueue",
110  action="store_false",
111  help="Use defaultqueueing system.")
112  queueGroup.add_option ("--queueCommand", dest="queueCommand", type="string",
113  help="Use QUEUECOMMAND TO queue jobs")
114  # verbose options
115  verboseGroup.add_option ("--verbose", dest="verbose",
116  action="store_true", default=False,
117  help="Verbose output")
118  verboseGroup.add_option ("--verboseDebug", dest="verboseDebug",
119  action="store_true", default=False,
120  help="Verbose output for debugging")
121  parser.add_option_group (describeGroup)
122  parser.add_option_group (precisionGroup)
123  parser.add_option_group (summaryGroup)
124  parser.add_option_group (queueGroup)
125  parser.add_option_group (verboseGroup)
126  options, args = parser.parse_args()
127  # Because Root and PyRoot are _really annoying_, you have wait to
128  # import this until command line options are parsed.
129  from Validation.Tools.GenObject import GenObject
130  if len (args) < 1 or len (args) > 2:
131  raise RuntimeError, "You must provide 1 or 2 root files"
132 
133  ###########################
134  ## Check Queuing Options ##
135  ###########################
136  if options.queueCommand:
137  queueCommand = options.queueCommand
138  options.noQueue = False
139  if not re.match (r'%%s', queueCommand):
140  queueCommand += ' %s'
141  if options.noQueue:
142  command = 'src/Validation/Tools/scripts/runCommand.bash'
143  else:
144  command = 'src/Validation/Tools/scripts/runCMScommand.bash'
145  # make sure we aren't trying to use options that should not be
146  # used with the queueing system
147  if options.compRoot or options.summary or options.summaryFull:
148  raise RuntimeError, "You can not use --compRoot or --summary "\
149  "in --queue mode"
150 
151  ##############################
152  ## Make Sure CMSSW is Setup ##
153  ##############################
154  base = os.environ.get ('CMSSW_BASE')
155  release_base = os.environ.get ('CMSSW_RELEASE_BASE')
156  if not base or not release_base:
157  raise RuntimeError, "You must have already setup a CMSSW environment."
158  # find command
159  found = False
160  for directory in [base, release_base]:
161  fullCommand = directory + '/' + command
162  if os.path.exists (fullCommand):
163  found = True
164  break
165  if not found:
166  raise RuntimeError, "Can not find %s" % command
167  if not options.noQueue:
168  fullCommand = queueCommand % fullCommand
169  if not os.path.isdir (logDir):
170  os.mkdir (logDir)
171  if not os.path.isdir (logDir):
172  raise RuntimeError, "Can't create %s directory" % logDir
173  if options.compRoot and not os.path.isdir (compRootDir):
174  os.mkdir (compRootDir)
175  if not os.path.isdir (compRootDir):
176  raise RuntimeError, "Can't create %s directory" % compRootDir
177  logPrefix = logDir + '/'
178  compRootPrefix = compRootDir + '/'
179  if options.prefix:
180  logPrefix += options.prefix + '_'
181  currentDir = os.getcwd()
182  filename1 = args[0]
183  if len (args) == 2:
184  filename2 = args[1]
185  else:
186  filename2 = filename1
187  if not os.path.exists (filename1) or not os.path.exists (filename2):
188  raise RuntimeError, "Can not find '%s' or '%s'" % (filename1, filename2)
189  # if verboseDebug is set, set verbose as well
190  if options.verboseDebug:
191  options.verbose = True
192  if options.verbose:
193  print "files", filename1, filename2
194  if options.singletons and not options.describeOnly:
195  raise RuntimeError, "--singletons can only be used with "\
196  "--describeOnly option"
197  if options.privateMemberData and not options.describeOnly:
198  raise RuntimeError, "--privateMemberData can only be used with "\
199  "--describeOnly option"
200  if options.singletons:
201  containerList.append (singletonRE)
202 
203  #############################
204  ## Run edmDumpEventContent ##
205  #############################
206  print "Getting edmDumpEventContent output"
207  regexLine = ""
208  for regex in options.regex:
209  regexLine += ' "--regex=%s"' % regex
210  dumpCommand = 'edmDumpEventContent %s %s' % (regexLine, filename1)
211  if options.verboseDebug:
212  print dumpCommand, '\n'
213  output = commands.getoutput (dumpCommand).split("\n")
214  if not len(output):
215  raise RuntimeError, "No output from edmDumpEventContent."
216  if options.verboseDebug:
217  print "output:\n", "\n".join(output)
218  collection = {}
219  total = failed = skipped = useless = 0
220  for line in output:
221  total += 1
222  match = piecesRE.search(line)
223  if match:
224  obj = EdmObject( match.group(1,2,3,4) )
225  if obj.bool:
226  collection.setdefault( obj.container, [] ).append(obj)
227  else:
228  skipped += 1
229  else:
230  skipped += 1
231 
232  #########################################
233  ## Run useReflexToDescribeForGenObject ##
234  #########################################
235  for key, value in sorted (collection.iteritems()):
236  name = value[0].name
237  prettyName = nonAlphaRE.sub('', name)
238  descriptionName = prettyName + '.txt'
239  if os.path.exists (descriptionName) \
240  and os.path.getsize (descriptionName) \
241  and not options.forceDescribe:
242  if options.verbose:
243  print '%s exists. Skipping' % descriptionName
244  continue
245  #print name, prettyName, key
246  describeCmd = "%s %s %s useReflexToDescribeForGenObject.py %s '--type=%s'" \
247  % (fullCommand, currentDir, logPrefix + prettyName,
248  GenObject.encodeNonAlphanumerics (name),
249  #name,
250  GenObject.encodeNonAlphanumerics (key))
251  if options.precision:
252  describeCmd += " --precision=" + options.precision
253  if options.verbose:
254  print "describing %s" % name
255  if options.verboseDebug:
256  print describeCmd, '\n'
257  returnCode = os.system (describeCmd)
258  if returnCode:
259  # return codes are shifted by 8 bits:
260  if returnCode == GenObject.uselessReturnCode << 8:
261  useless += 1
262  else:
263  print "Error trying to describe '%s'. Continuing.\n" % \
264  (name)
265  failed += 1
266  if options.describeOnly:
267  print "Total: %3d Skipped: %3d Failed: %3d Useless: %3d" % \
268  (total, skipped, failed, useless)
269  if not options.noQueue:
270  print "Note: Failed not recorded when using queuing system."
271  sys.exit()
272 
273  ##################################
274  ## Run edmOneToOneComparison.py ##
275  ##################################
276  for key, value in sorted (collection.iteritems()):
277  #print "%-40s" % key,
278  for obj in value:
279  # print " ", obj.label(),
280  name = obj.name
281  prettyName = nonAlphaRE.sub('', name)
282  prettyLabel = commaRE.sub ('_', obj.label())
283  compareCmd = 'edmOneToOneComparison.py %s %s %s --compare --label=reco^%s^%s' \
284  % (prettyName + '.txt',
285  filename1,
286  filename2,
287  prettyName,
288  obj.label())
289  fullCompareCmd = '%s %s %s %s' \
290  % (fullCommand, currentDir,
291  logPrefix + prettyName + '_' + prettyLabel,
292  compareCmd)
293  if options.relative:
294  fullCompareCmd += ' --relative'
295  elif options.absolute:
296  fullCompareCmd += ' --absolute'
297  if options.compRoot:
298  compRootName = compRootPrefix + prettyName \
299  + '_' + prettyLabel + '.root'
300  fullCompareCmd += ' --compRoot=%s' % compRootName
301  if options.verbose:
302  print "comparing branch %s %s" % (name, obj.label())
303  if options.verboseDebug:
304  print fullCompareCmd,'\n'
305  os.system (fullCompareCmd)
306 
307  ##################################
308  ## Print Summary (if requested) ##
309  ##################################
310  if options.summary or options.summaryFull:
311  if options.prefix:
312  summaryMask = options.prefix + '_%_'
313  else:
314  summaryMask = '%_'
315  if options.summaryFull:
316  summaryOptions = '--diffTree'
317  else:
318  summaryOptions = '--counts'
319  summaryCmd = 'summarizeEdmComparisonLogfiles.py %s %s logfiles' \
320  % (summaryOptions, summaryMask)
321  print commands.getoutput (summaryCmd)
static std::string join(char **cmd)
Definition: RemoteFile.cc:18
list object
Definition: dbtoconf.py:77
double split
Definition: MVATrainer.cc:139