00001
00002
00003 import inspect
00004 import itertools
00005 import logging
00006 import optparse
00007 import pprint
00008 import random
00009 import sys
00010
00011 import ROOT
00012 from DataFormats.FWLite import Events, Handle
00013
00014 typeMap = { 'double' : ['double', 'vector<double>'],
00015 'int' : ['int', 'vector<int>'],}
00016
00017 class ProductNotFoundError(RuntimeError):
00018 """
00019 Special exception for a product not in file
00020 """
00021 pass
00022
00023 def compareEvents(event1, event2, handleName, label, options):
00024 """
00025 Compare two events
00026 """
00027
00028
00029 isSimpleObject = (handleName.find('vector') == -1)
00030
00031
00032 aux1 = event1.eventAuxiliary()
00033 aux2 = event2.eventAuxiliary()
00034
00035 rle1 = (aux1.run(), aux1.luminosityBlock(), aux1.event())
00036 rle2 = (aux2.run(), aux2.luminosityBlock(), aux2.event())
00037
00038 logging.debug("Comparing RLE #'s %s and %s" % (rle1, rle2))
00039
00040 if rle1 != rle2:
00041 raise RuntimeError("Run/Lumi/Events don't match: %s vs %s" % (rle1, rle2))
00042 handle1 = Handle(handleName)
00043 handle2 = Handle(handleName)
00044
00045 if event1.getByLabel(label, handle1) and event2.getByLabel(label, handle2):
00046 objects1 = handle1.product()
00047 objects2 = handle1.product()
00048 else:
00049 raise ProductNotFoundError("Product %s %s not found." % (handleName, label))
00050
00051 if isSimpleObject:
00052 val1 = objects1[0]
00053 val2 = objects2[0]
00054 if options.blurRate and options.blur and random.random() < options.blurRate:
00055
00056 val1 += (random.random()-0.5) * options.blur
00057 if val1 != val2:
00058 logging.error("Mismatch %s and %s in %s" % (val1, val2, aux2.event()))
00059 return (1, 1)
00060 else:
00061 logging.debug("Match of %s in %s" % (objects1[0], aux2.event()))
00062 return (1, 0)
00063 else:
00064 count = 0
00065 mismatch = 0
00066 for val1, val2 in itertools.izip_longest(objects1, objects2):
00067 count += 1
00068 if options.blurRate and options.blur and random.random() < options.blurRate:
00069
00070 val1 += (random.random()-0.5) * options.blur * val1
00071 if val1 != val2:
00072 mismatch += 1
00073 logging.error("Comparison problem %s != %s" % (val1, val2))
00074 logging.debug("Compared %s elements" % count)
00075 return (count, mismatch)
00076
00077 if __name__ == "__main__":
00078
00079
00080
00081
00082
00083 random.seed()
00084 logging.basicConfig(level=logging.INFO)
00085
00086 parser = optparse.OptionParser("usage: %prog [options] config.txt file1.root file2.root\nVisit https://twiki.cern.ch/twiki/bin/view/CMS/SWGuidePhysicsToolsEdmOneToOneComparison\nfor full documentation.")
00087 modeGroup = optparse.OptionGroup (parser, "Mode Conrols")
00088 tupleGroup = optparse.OptionGroup (parser, "Tuple Controls")
00089 optionsGroup = optparse.OptionGroup (parser, "Options")
00090
00091 modeGroup.add_option ('--compare', dest='compare', action='store_true',
00092 help='Compare tuple1 to tuple2')
00093
00094 tupleGroup.add_option ('--numEvents', dest='numEvents', type='int',
00095 default=1e9,
00096 help="number of events for first and second file")
00097
00098 tupleGroup.add_option ('--label', dest='label', type='string',
00099 action='append',
00100 help="Change label ('tuple^object^label')")
00101
00102 optionsGroup.add_option ('--blur1', dest='blur', type='float',
00103 default=0.05,
00104 help="Randomly changes values by 'BLUR' " +\
00105 "from tuple1. For debugging only.")
00106 optionsGroup.add_option ('--blurRate', dest='blurRate', type='float',
00107 default=0.00,
00108 help="Rate at which objects will be changed. " + \
00109 "(%default default)")
00110
00111 parser.add_option_group (modeGroup)
00112 parser.add_option_group (tupleGroup)
00113 parser.add_option_group (optionsGroup)
00114 (options, args) = parser.parse_args()
00115
00116 if len(args) != 3:
00117 parser.error("Too many or too few arguments")
00118 options.config = args[0]
00119 options.file1 = args[1]
00120 options.file2 = args[2]
00121
00122
00123 tName, objName, lName = options.label[0].split('^')
00124 label = lName.split(',')
00125
00126 ROOT.gROOT.SetBatch()
00127
00128 ROOT.gSystem.Load("libFWCoreFWLite.so")
00129 ROOT.gSystem.Load("libDataFormatsFWLite.so")
00130 ROOT.AutoLibraryLoader.enable()
00131
00132 chain1 = Events ([options.file1], forceEvent=True)
00133 chain2 = Events ([options.file2], forceEvent=True)
00134
00135 if chain1.size() != chain1.size():
00136 raise RuntimeError("Files have different #'s of events")
00137 numEvents = min(options.numEvents, chain1.size())
00138
00139
00140
00141 productsCompared = 0
00142 totalCount = 0
00143 mismatches = 0
00144 for handleName in typeMap[objName]:
00145 try:
00146 chain1.toBegin()
00147 chain2.toBegin()
00148 logging.info("Testing identity for handle=%s, label=%s" % (handleName, label))
00149
00150 for ev1, ev2, count in itertools.izip(chain1, chain2, xrange(numEvents)):
00151 evCount, evMismatch = compareEvents(event1=ev1, event2=ev2, handleName=handleName, label=label, options=options)
00152 totalCount += evCount
00153 mismatches += evMismatch
00154 logging.info("Compared %s events" % (count+1))
00155 productsCompared += 1
00156
00157 plagerDict = {'eventsCompared' : count+1}
00158 plagerDict.update({'count_%s' % objName : totalCount})
00159 if mismatches:
00160 plagerDict.update({objName: {'_var' : {handleName:mismatches}}})
00161 print "Summary"
00162 pprint.pprint(plagerDict)
00163 except ProductNotFoundError:
00164 logging.info("No product found for handle=%s, label=%s" % (handleName, label))
00165
00166 logging.info("Total products compared: %s, %s/%s" % (productsCompared, mismatches, totalCount))
00167
00168 if not productsCompared:
00169 print "Plager compatible message: not able to get any products"
00170 sys.exit()