CMS 3D CMS Logo

simpleEdmComparison.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 from __future__ import print_function
4 import inspect
5 import itertools
6 import logging
7 import optparse
8 import pprint
9 import random
10 import sys
11 
12 import ROOT
13 from DataFormats.FWLite import Events, Handle
14 
15 typeMap = { 'double' : ['double', 'vector<double>'],
16  'int' : ['int', 'vector<int>'],}
17 
18 class ProductNotFoundError(RuntimeError):
19  """
20  Special exception for a product not in file
21  """
22  pass
23 
24 def compareEvents(event1, event2, handleName, label, options):
25  """
26  Compare two events
27  """
28 
29  # Is it a vector of objects or object (funky ROOT buffer for single value)
30  isSimpleObject = (handleName.find('vector') == -1)
31 
32  # Compare run, lumi, event
33  aux1 = event1.eventAuxiliary()
34  aux2 = event2.eventAuxiliary()
35 
36  rle1 = (aux1.run(), aux1.luminosityBlock(), aux1.event())
37  rle2 = (aux2.run(), aux2.luminosityBlock(), aux2.event())
38 
39  logging.debug("Comparing RLE #'s %s and %s" % (rle1, rle2))
40 
41  if rle1 != rle2:
42  raise RuntimeError("Run/Lumi/Events don't match: %s vs %s" % (rle1, rle2))
43  handle1 = Handle(handleName)
44  handle2 = Handle(handleName)
45 
46  if event1.getByLabel(label, handle1) and event2.getByLabel(label, handle2):
47  objects1 = handle1.product()
48  objects2 = handle1.product()
49  else:
50  raise ProductNotFoundError("Product %s %s not found." % (handleName, label))
51 
52  if isSimpleObject:
53  val1 = objects1[0]
54  val2 = objects2[0]
55  if options.blurRate and options.blur and random.random() < options.blurRate:
56  # This is different than Charles's method, which makes no sense to me
57  val1 += (random.random()-0.5) * options.blur
58  if val1 != val2:
59  logging.error("Mismatch %s and %s in %s" % (val1, val2, aux2.event()))
60  return (1, 1)
61  else:
62  logging.debug("Match of %s in %s" % (objects1[0], aux2.event()))
63  return (1, 0)
64  else:
65  count = 0
66  mismatch = 0
67  for val1, val2 in itertools.izip_longest(objects1, objects2):
68  count += 1
69  if options.blurRate and options.blur and random.random() < options.blurRate:
70  # This is different than Charles's method, which makes no sense to me
71  val1 += (random.random()-0.5) * options.blur * val1
72  if val1 != val2:
73  mismatch += 1
74  logging.error("Comparison problem %s != %s" % (val1, val2))
75  logging.debug("Compared %s elements" % count)
76  return (count, mismatch)
77 
78 if __name__ == "__main__":
79 
80  ###################
81  ## Setup Options ##
82  ###################
83 
84  random.seed()
85  logging.basicConfig(level=logging.INFO)
86 
87  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.")
88  modeGroup = optparse.OptionGroup (parser, "Mode Conrols")
89  tupleGroup = optparse.OptionGroup (parser, "Tuple Controls")
90  optionsGroup = optparse.OptionGroup (parser, "Options")
91 
92  modeGroup.add_option ('--compare', dest='compare', action='store_true',
93  help='Compare tuple1 to tuple2')
94 
95  tupleGroup.add_option ('--numEvents', dest='numEvents', type='int',
96  default=1e9,
97  help="number of events for first and second file")
98 
99  tupleGroup.add_option ('--label', dest='label', type='string',
100  action='append',
101  help="Change label ('tuple^object^label')")
102 
103  optionsGroup.add_option ('--blur1', dest='blur', type='float',
104  default=0.05,
105  help="Randomly changes values by 'BLUR' " +\
106  "from tuple1. For debugging only.")
107  optionsGroup.add_option ('--blurRate', dest='blurRate', type='float',
108  default=0.00,
109  help="Rate at which objects will be changed. " + \
110  "(%default default)")
111 
112  parser.add_option_group (modeGroup)
113  parser.add_option_group (tupleGroup)
114  parser.add_option_group (optionsGroup)
115  (options, args) = parser.parse_args()
116 
117  if len(args) != 3:
118  parser.error("Too many or too few arguments")
119  options.config = args[0]
120  options.file1 = args[1]
121  options.file2 = args[2]
122 
123  # Parse object name and label out of Charles format
124  tName, objName, lName = options.label[0].split('^')
125  label = lName.split(',')
126 
127  ROOT.gROOT.SetBatch()
128 
129  ROOT.gSystem.Load("libFWCoreFWLite.so")
130  ROOT.gSystem.Load("libDataFormatsFWLite.so")
131  ROOT.FWLiteEnabler.enable()
132 
133  chain1 = Events ([options.file1], forceEvent=True)
134  chain2 = Events ([options.file2], forceEvent=True)
135 
136  if chain1.size() != chain1.size():
137  raise RuntimeError("Files have different #'s of events")
138  numEvents = min(options.numEvents, chain1.size())
139 
140  # Parameters to this script are the same regardless if the
141  # product is double or vector<double> so have to try both
142  productsCompared = 0
143  totalCount = 0
144  mismatches = 0
145  for handleName in typeMap[objName]:
146  try:
147  chain1.toBegin()
148  chain2.toBegin()
149  logging.info("Testing identity for handle=%s, label=%s" % (handleName, label))
150  # Use itertools to iterate over lists in ||
151  for ev1, ev2, count in itertools.izip(chain1, chain2, xrange(numEvents)):
152  evCount, evMismatch = compareEvents(event1=ev1, event2=ev2, handleName=handleName, label=label, options=options)
153  totalCount += evCount
154  mismatches += evMismatch
155  logging.info("Compared %s events" % (count+1))
156  productsCompared += 1
157  # Try to reproduce the output that Charles's summary script is expecting
158  plagerDict = {'eventsCompared' : count+1}
159  plagerDict.update({'count_%s' % objName : totalCount})
160  if mismatches:
161  plagerDict.update({objName: {'_var' : {handleName:mismatches}}})
162  print("Summary")
163  pprint.pprint(plagerDict)
164  except ProductNotFoundError:
165  logging.info("No product found for handle=%s, label=%s" % (handleName, label))
166 
167  logging.info("Total products compared: %s, %s/%s" % (productsCompared, mismatches, totalCount))
168 
169  if not productsCompared:
170  print("Plager compatible message: not able to get any products")
171  sys.exit()
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:65
def compareEvents(event1, event2, handleName, label, options)
T min(T a, T b)
Definition: MathUtil.h:58
double split
Definition: MVATrainer.cc:139