CMS 3D CMS Logo

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