CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/Validation/Tools/scripts/simpleEdmComparison.py

Go to the documentation of this file.
00001 #! /usr/bin/env python
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     # Is it a vector of objects or object (funky ROOT buffer for single value)
00029     isSimpleObject = (handleName.find('vector') == -1)
00030 
00031     # Compare run, lumi, event
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             # This is different than Charles's method, which makes no sense to me
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                 # This is different than Charles's method, which makes no sense to me
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     ## Setup Options ##
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     # Parse object name and label out of Charles format
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     # Parameters to this script are the same regardless if the
00140     # product is double or vector<double> so have to try both
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             # Use itertools to iterate over lists in ||
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             # Try to reproduce the output that Charles's summary script is expecting
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()