File indexing completed on 2024-12-01 23:40:46
0001
0002
0003 import optparse
0004 import subprocess
0005 import pprint
0006 import re
0007 import os
0008 import sys
0009
0010 piecesRE = re.compile (r'(.+?)\s+"(\S+)"\s+"(\S*)"\s+"(\S+)"')
0011
0012 nonAlphaRE = re.compile (r'\W')
0013 commaRE = re.compile (r',')
0014 queueCommand = '/uscms/home/cplager/bin/clpQueue.pl addjob %s'
0015 logDir = 'logfiles'
0016 compRootDir = 'compRoot'
0017
0018
0019 doubleRE = re.compile (r'^(double|int)')
0020 vectorRE = re.compile (r'^vector<([^<>]+)>')
0021 detSetVecRE = re.compile (r'^edm::DetSetVector<([^<>]+)>')
0022 edColRE = re.compile (r'^edm::EDCollection<([^<>]+)>')
0023 sortedColRE = re.compile (r'^edm::SortedCollection<([^<>]+),\S+?> >')
0024 singletonRE = re.compile (r'^([\w:]+)$')
0025 containerList = [vectorRE, detSetVecRE, edColRE, sortedColRE, doubleRE]
0026
0027 class EdmObject (object):
0028
0029 def __init__ (self, tup):
0030 self.container, self.one, self.two, self.three = tup
0031 self.bool = False
0032 for regex in containerList:
0033 match = regex.search( self.container)
0034 if match:
0035 self.bool = True
0036 self.name = match.group(1)
0037 break
0038
0039 def __str__ (self):
0040 return pprint.pformat (self.__dict__)
0041
0042 def __bool__ (self):
0043 return self.bool
0044
0045 def label (self):
0046 return "%s,%s,%s" % (self.one, self.two, self.three)
0047
0048
0049 if __name__ == "__main__":
0050
0051
0052
0053
0054 parser = optparse.OptionParser ("%prog [options] file1.root [file2.root]"\
0055 "\nFor more details, see\nhttps://twiki.cern.ch/twiki/bin/view/CMS/SWGuidePhysicsToolsEdmOneToOneComparison")
0056 describeGroup = optparse.OptionGroup (parser, "Description Options")
0057 precisionGroup = optparse.OptionGroup (parser, "Precision Options")
0058 summaryGroup = optparse.OptionGroup (parser, "Summary Options")
0059 queueGroup = optparse.OptionGroup (parser, "Queue Options")
0060 verboseGroup = optparse.OptionGroup (parser, "Verbose Options")
0061
0062 parser.add_option ("--compRoot", dest="compRoot",
0063 action="store_true", default=False,
0064 help="Make compRoot files.")
0065 parser.add_option ('--strictPairing', dest='strictPairing',
0066 action='store_true',
0067 help="Objects are paired uniquely by order in collection")
0068 parser.add_option ("--prefix", dest="prefix", type="string",
0069 help="Prefix to prepend to logfile name")
0070 parser.add_option ("--regex", dest='regex', action="append",
0071 type="string", default=[],
0072 help="Only run on branches containing regex")
0073
0074 describeGroup.add_option ("--describeOnly", dest="describeOnly",
0075 action="store_true", default=False,
0076 help="Run description step only and stop.")
0077 describeGroup.add_option ("--forceDescribe", dest="forceDescribe",
0078 action="store_true", default=False,
0079 help="Run description step even if "\
0080 "file already exists.")
0081 describeGroup.add_option ("--singletons", dest="singletons",
0082 action="store_true", default=False,
0083 help="Describe singleton objects (" \
0084 "used only with --describeOnly option).")
0085 describeGroup.add_option ("--privateMemberData", dest="privateMemberData",
0086 action="store_true", default=False,
0087 help="include private member data "\
0088 "(NOT for comparisons)")
0089
0090 precisionGroup.add_option ("--precision", dest="precision", type="string",
0091 help="Change precision use for floating "\
0092 "point numbers")
0093 precisionGroup.add_option ('--absolute', dest='absolute',
0094 action='store_true', default=False,
0095 help='Precision is checked against '\
0096 'absolute difference')
0097 precisionGroup.add_option ('--relative', dest='relative',
0098 action='store_true', default=False,
0099 help='Precision is checked against '\
0100 'relative difference')
0101
0102 summaryGroup.add_option ("--summary", dest="summary",
0103 action="store_true", default=False,
0104 help="Print out summary counts at end")
0105 summaryGroup.add_option ("--summaryFull", dest="summaryFull",
0106 action="store_true", default=False,
0107 help="Print out full summary at end (VERY LONG)")
0108
0109 queueGroup.add_option ("--noQueue", dest="noQueue",
0110 action="store_true", default=True,
0111 help="Do not use queue, but run "\
0112 "jobs serially (default).")
0113 queueGroup.add_option ("--queue", dest="noQueue",
0114 action="store_false",
0115 help="Use defaultqueueing system.")
0116 queueGroup.add_option ("--queueCommand", dest="queueCommand", type="string",
0117 help="Use QUEUECOMMAND TO queue jobs")
0118
0119 verboseGroup.add_option ("--verbose", dest="verbose",
0120 action="store_true", default=False,
0121 help="Verbose output")
0122 verboseGroup.add_option ("--verboseDebug", dest="verboseDebug",
0123 action="store_true", default=False,
0124 help="Verbose output for debugging")
0125 parser.add_option_group (describeGroup)
0126 parser.add_option_group (precisionGroup)
0127 parser.add_option_group (summaryGroup)
0128 parser.add_option_group (queueGroup)
0129 parser.add_option_group (verboseGroup)
0130 options, args = parser.parse_args()
0131
0132
0133 from Validation.Tools.GenObject import GenObject
0134 if len (args) < 1 or len (args) > 2:
0135 raise RuntimeError("You must provide 1 or 2 root files")
0136
0137
0138
0139
0140 if options.queueCommand:
0141 queueCommand = options.queueCommand
0142 options.noQueue = False
0143 if not re.match (r'%%s', queueCommand):
0144 queueCommand += ' %s'
0145 if options.noQueue:
0146 command = 'src/Validation/Tools/scripts/runCommand.bash'
0147 else:
0148 command = 'src/Validation/Tools/scripts/runCMScommand.bash'
0149
0150
0151 if options.compRoot or options.summary or options.summaryFull:
0152 raise RuntimeError("You can not use --compRoot or --summary "\
0153 "in --queue mode")
0154
0155
0156
0157
0158 base = os.environ.get ('CMSSW_BASE')
0159 release_base = os.environ.get ('CMSSW_RELEASE_BASE')
0160 if not base or not release_base:
0161 raise RuntimeError("You must have already setup a CMSSW environment.")
0162
0163 found = False
0164 for directory in [base, release_base]:
0165 fullCommand = directory + '/' + command
0166 if os.path.exists (fullCommand):
0167 found = True
0168 break
0169 if not found:
0170 raise RuntimeError("Can not find %s" % command)
0171 if not options.noQueue:
0172 fullCommand = queueCommand % fullCommand
0173 if not os.path.isdir (logDir):
0174 os.mkdir (logDir)
0175 if not os.path.isdir (logDir):
0176 raise RuntimeError("Can't create %s directory" % logDir)
0177 if options.compRoot and not os.path.isdir (compRootDir):
0178 os.mkdir (compRootDir)
0179 if not os.path.isdir (compRootDir):
0180 raise RuntimeError("Can't create %s directory" % compRootDir)
0181 logPrefix = logDir + '/'
0182 compRootPrefix = compRootDir + '/'
0183 if options.prefix:
0184 logPrefix += options.prefix + '_'
0185 currentDir = os.getcwd()
0186 filename1 = args[0]
0187 if len (args) == 2:
0188 filename2 = args[1]
0189 else:
0190 filename2 = filename1
0191 if not os.path.exists (filename1) or not os.path.exists (filename2):
0192 raise RuntimeError("Can not find '%s' or '%s'" % (filename1, filename2))
0193
0194 if options.verboseDebug:
0195 options.verbose = True
0196 if options.verbose:
0197 print("files", filename1, filename2)
0198 if options.singletons and not options.describeOnly:
0199 raise RuntimeError("--singletons can only be used with "\
0200 "--describeOnly option")
0201 if options.privateMemberData and not options.describeOnly:
0202 raise RuntimeError("--privateMemberData can only be used with "\
0203 "--describeOnly option")
0204 if options.singletons:
0205 containerList.append (singletonRE)
0206
0207
0208
0209
0210 print("Getting edmDumpEventContent output")
0211 regexLine = ""
0212 for regex in options.regex:
0213 regexLine += ' "--regex=%s"' % regex
0214 dumpCommand = 'edmDumpEventContent %s %s' % (regexLine, filename1)
0215 if options.verboseDebug:
0216 print(dumpCommand, '\n')
0217 output = subprocess.getoutput (dumpCommand).split("\n")
0218 if not len(output):
0219 raise RuntimeError("No output from edmDumpEventContent.")
0220 if options.verboseDebug:
0221 print("output:\n", "\n".join(output))
0222 collection = {}
0223 total = failed = skipped = useless = 0
0224 for line in output:
0225 total += 1
0226 match = piecesRE.search(line)
0227 if match:
0228 obj = EdmObject( match.group(1,2,3,4) )
0229 if obj.bool:
0230 collection.setdefault( obj.container, [] ).append(obj)
0231 else:
0232 skipped += 1
0233 else:
0234 skipped += 1
0235
0236
0237
0238
0239 for key, value in sorted (collection.items()):
0240 name = value[0].name
0241 prettyName = nonAlphaRE.sub('', name)
0242 descriptionName = prettyName + '.txt'
0243 if os.path.exists (descriptionName) \
0244 and os.path.getsize (descriptionName) \
0245 and not options.forceDescribe:
0246 if options.verbose:
0247 print('%s exists. Skipping' % descriptionName)
0248 continue
0249
0250 describeCmd = "%s %s %s useReflexToDescribeForGenObject.py %s '--type=%s'" \
0251 % (fullCommand, currentDir, logPrefix + prettyName,
0252 GenObject.encodeNonAlphanumerics (name),
0253
0254 GenObject.encodeNonAlphanumerics (key))
0255 if options.precision:
0256 describeCmd += " --precision=" + options.precision
0257 if options.verbose:
0258 print("describing %s" % name)
0259 if options.verboseDebug:
0260 print(describeCmd, '\n')
0261 returnCode = os.system (describeCmd)
0262 if returnCode:
0263
0264 if returnCode == GenObject.uselessReturnCode << 8:
0265 useless += 1
0266 else:
0267 print("Error trying to describe '%s'. Continuing.\n" % \
0268 (name))
0269 failed += 1
0270 if options.describeOnly:
0271 print("Total: %3d Skipped: %3d Failed: %3d Useless: %3d" % \
0272 (total, skipped, failed, useless))
0273 if not options.noQueue:
0274 print("Note: Failed not recorded when using queuing system.")
0275 sys.exit()
0276
0277
0278
0279
0280 for key, value in sorted (collection.items()):
0281
0282 for obj in value:
0283
0284 name = obj.name
0285 prettyName = nonAlphaRE.sub('', name)
0286 scriptName = 'edmOneToOneComparison.py'
0287 if prettyName in ['int', 'double']:
0288 scriptName = 'simpleEdmComparison.py'
0289 prettyLabel = commaRE.sub ('_', obj.label())
0290 compareCmd = '%s %s %s %s --compare --label=reco^%s^%s' \
0291 % (scriptName,
0292 prettyName + '.txt',
0293 filename1,
0294 filename2,
0295 prettyName,
0296 obj.label())
0297 fullCompareCmd = '%s %s %s %s' \
0298 % (fullCommand, currentDir,
0299 logPrefix + prettyName + '_' + prettyLabel,
0300 compareCmd)
0301 if options.relative:
0302 fullCompareCmd += ' --relative'
0303 elif options.absolute:
0304 fullCompareCmd += ' --absolute'
0305 if options.compRoot:
0306 compRootName = compRootPrefix + prettyName \
0307 + '_' + prettyLabel + '.root'
0308 fullCompareCmd += ' --compRoot=%s' % compRootName
0309 if options.strictPairing:
0310 fullCompareCmd += ' --strictPairing'
0311 if options.verbose:
0312 print("comparing branch %s %s" % (name, obj.label()))
0313 if options.verboseDebug:
0314 print(fullCompareCmd,'\n')
0315 os.system (fullCompareCmd)
0316
0317
0318
0319
0320 if options.summary or options.summaryFull:
0321 if options.prefix:
0322 summaryMask = options.prefix + '_%_'
0323 else:
0324 summaryMask = '%_'
0325 if options.summaryFull:
0326 summaryOptions = '--diffTree'
0327 else:
0328 summaryOptions = '--counts'
0329 summaryCmd = 'summarizeEdmComparisonLogfiles.py %s %s logfiles' \
0330 % (summaryOptions, summaryMask)
0331 print(summaryCmd)
0332 print(subprocess.getoutput (summaryCmd))