CMS 3D CMS Logo

generateEDF.py
Go to the documentation of this file.
1 #! /usr/bin/env python3
2 
3 from __future__ import print_function
4 from __future__ import division
5 from builtins import zip
6 from builtins import object
7 from past.utils import old_div
8 from builtins import range
9 import sys
10 import re
11 import optparse
12 from pprint import pprint
13 import array
14 import ROOT
15 import math
16 
17 sepRE = re.compile (r'[\s,;:]+')
18 nonSpaceRE = re.compile (r'\S')
19 
20 
25 
26 class LumiInfo (object):
27 
28  lastSingleXingRun = 136175
29  lumiSectionLength = 23.310779
30 
31  def __init__ (self, line):
32  self.totInstLum = 0.
33  self.aveInstLum = 0.
34  self.numXings = 0
35  self.instLums = []
36  self.events = []
37  self.xingInfo = False
38  self.badXingInfo = False
39  pieces = sepRE.split (line.strip())
40  size = len (pieces)
41  if size % 2:
42  raise RuntimeError("Odd number of pieces")
43  if size < 4:
44  raise RuntimeError("Not enough pieces")
45  try:
46  self.run = int (pieces[0])
47  self.lumi = int (pieces[1])
48  self.delivered = float (pieces[2])
49  self.recorded = float (pieces[3])
50  except:
51  raise RuntimeError("Pieces not right format")
52  if size > 4:
53  try:
54  for xing, lum in zip (pieces[4::2],pieces[5::2]):
55  xing = int (xing)
56  lum = float (lum)
57  self.instLums.append( (xing, lum) )
58  self.totInstLum += lum
59  self.numXings += 1
60  except:
61  raise RuntimeError("Inst Lumi Info malformed")
62  self.aveInstLum = old_div(self.totInstLum, (self.numXings))
63  self.xingInfo = True
64  self.key = (self.run, self.lumi)
65  self.keyString = self.key.__str__()
66 
67 
68  def fixXingInfo (self):
69  if self.numXings:
70  # You shouldn't try and fix an event if it already has
71  # xing information.
72  raise RuntimeError("This event %s already has Xing information" \
73  % self.keyString)
74  if self.run > LumiInfo.lastSingleXingRun:
75  # this run may have more than one crossing. I don't know
76  # how to fix this.
77  self.badXingInfo = True
78  return False
79  self.numXings = 1
80  xing = 1
81  self.aveInstLum = self.totInstLum = lum = \
82  old_div(self.delivered, LumiInfo.lumiSectionLength)
83  self.instLums.append( (xing, lum) )
84  self.xingInfo = True
85  return True
86 
87 
88  def deadtime (self):
89  if not self.delivered:
90  return 1
91  return 1 - (old_div(self.recorded, self.delivered))
92 
93 
94  def __str__ (self):
95  return "%6d, %4d: %6.1f (%4.1f%%) %4.2f (%3d)" % \
96  (self.run,
97  self.lumi,
98  self.delivered,
99  self.deadtime(),
100  self.totInstLum,
101  self.numXings)
102 
103 
104 
109 
110 class LumiInfoCont (dict):
111 
112  def __init__ (self, filename, **kwargs):
113  print("loading luminosity information from '%s'." % filename)
114  source = open (filename, 'r')
115  self.minMaxKeys = ['totInstLum', 'aveInstLum', 'numXings',
116  'delivered', 'recorded']
117  self._min = {}
118  self._max = {}
119  self.totalRecLum = 0.
120  self.xingInfo = False
121  self.allowNoXing = kwargs.get ('ignore')
122  self.noWarnings = kwargs.get ('noWarnings')
123  self.minRun = 0
124  self.maxRun = 0
125  self.minIntLum = 0
126  self.maxIntLum = 0
127 
128  for key in self.minMaxKeys:
129  self._min[key] = -1
130  self._max[key] = 0
131  for line in source:
132  try:
133  lumi = LumiInfo (line)
134  except:
135  continue
136  self[lumi.key] = lumi
137  self.totalRecLum += lumi.recorded
138  if not self.xingInfo and lumi.xingInfo:
139  self.xingInfo = True
140  if lumi.xingInfo:
141  #print "yes", lumi.keyString
142  if not self.xingInfo:
143  print("huh?")
144  for key in self.minMaxKeys:
145  val = getattr (lumi, key)
146  if val < self._min[key] or self._min[key] < 0:
147  self._min[key] = val
148  if val > self._max[key] or not self._max[key]:
149  self._max[key] = val
150  source.close()
151 
156  self.invunits = 'nb'
157  lumFactor = 1e3
158  if self.totalRecLum > 1e9:
159  lumFactor = 1e9
160  self.invunits = 'fb'
161  elif self.totalRecLum > 1e6:
162  lumFactor = 1e6
163  self.invunits = 'pb'
164  # use lumFactor to make everything consistent
165  #print "units", self.invunits, "factor", lumFactor
166  self.totalRecLum /= lumFactor
167  for lumis in self.values():
168  lumis.delivered /= lumFactor
169  lumis.recorded /= lumFactor
170  # Probably want to rename this next subroutine, but I'll leave
171  # it alone for now...
172  self._integrateContainer()
173 
174 
175 
176  def __str__ (self):
177  retval = 'run, lum del ( dt ) inst (#xng)\n'
178  for key, value in sorted (self.items()):
179  retval += "%s\n" % value
180  return retval
181 
182 
183  def min (self, key):
184  return self._min[key]
185 
186 
187  def max (self, key):
188  return self._max[key]
189 
190 
191  def keys (self):
192  return sorted (dict.keys (self))
193 
194 
195  def iteritems (self):
196  return sorted (dict.iteritems (self))
197 
198 
200  # calculate numbers for recorded integrated luminosity
201  total = 0.
202  for key, lumi in self.items():
203  total += lumi.recorded
204  lumi.totalRecorded = total
205  lumi.fracRecorded = old_div(total, self.totalRecLum)
206  # calculate numbers for average xing instantaneous luminosity
207  if not self.xingInfo:
208  # nothing to do here
209  return
210  xingKeyList = []
211  maxAveInstLum = 0.
212  for key, lumi in self.items():
213  if not lumi.xingInfo and not lumi.fixXingInfo():
214  if not self.noWarnings:
215  print("Do not have lumi xing info for %s" % lumi.keyString)
216  if not self.allowNoXing:
217  print("Setting no Xing info flag")
218  self.xingInfo = False
219  return
220  continue
221  xingKeyList.append( (lumi.aveInstLum, key) )
222  if lumi.aveInstLum > maxAveInstLum:
223  maxAveInstLum = lumi.aveInstLum
224  xingKeyList.sort()
225  total = 0.
226  for tup in xingKeyList:
227  lumi = self[tup[1]]
228  total += lumi.recorded
229  lumi.totalAXILrecorded = total
230  lumi.fracAXILrecorded = old_div(total, self.totalRecLum)
231  lumi.fracAXIL = old_div(lumi.aveInstLum, maxAveInstLum)
232 
233 
234 
239 
240 def loadEvents (filename, cont, options):
241  eventsDict = {}
242  print("loading events from '%s'" % filename)
243  events = open (filename, 'r')
244  runIndex, lumiIndex, eventIndex, weightIndex = 0, 1, 2, 3
245  if options.relOrder:
246  lumiIndex, eventIndex = 2,1
247  minPieces = 3
248  totalWeight = 0.
249  if options.weights:
250  minPieces = 4
251  for line in events:
252  pieces = sepRE.split (line.strip())
253  if len (pieces) < minPieces:
254  if nonSpaceRE.search (line):
255  print("skipping", line)
256  continue
257  try:
258  run, lumi, event = int( pieces[runIndex] ), \
259  int( pieces[lumiIndex] ), \
260  int( pieces[eventIndex] )
261  except:
262  continue
263  key = (run, lumi)
264  if key not in cont:
265  if options.ignore:
266  print("Warning, %s is not found in the lumi information" \
267  % key.__str__())
268  continue
269  else:
270  raise RuntimeError("%s is not found in lumi information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
271  % key.__str__())
272  if options.edfMode != 'time' and not cont[key].xingInfo:
273  if options.ignore:
274  print("Warning, %s does not have Xing information" \
275  % key.__str__())
276  continue
277  else:
278  raise RuntimeError("%s does not have Xing information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
279  % key.__str__())
280  if options.weights:
281  weight = float (pieces[weightIndex])
282  else:
283  weight = 1
284  eventsDict.setdefault( key, []).append( (event, weight) )
285  totalWeight += weight
286  events.close()
287  return eventsDict, totalWeight
288 
289 
290 def makeEDFplot (lumiCont, eventsDict, totalWeight, outputFile, options):
291  # make TGraph
292  xVals = [0]
293  yVals = [0]
294  expectedVals = [0]
295  predVals = [0]
296  weight = 0
297  expectedChunks = []
298 
301  if 'time' == options.edfMode:
302  # if we have a minimum run number, clear the lists
303  if lumiCont.minRun or lumiCont.minIntLum:
304  xVals = []
305  yVals = []
306  expectedVals = []
307  predVals = []
308  # loop over events
309  for key, eventList in sorted( eventsDict.items() ):
310  usePoints = True
311  # should we add this point?
312  if lumiCont.minRun and lumiCont.minRun > key[0] or \
313  lumiCont.maxRun and lumiCont.maxRun < key[0]:
314  usePoints = False
315  for event in eventList:
316  weight += event[1]
317  if not usePoints:
318  continue
319  factor = old_div(weight, totalWeight)
320  try:
321  intLum = lumiCont[key].totalRecorded
322  except:
323  raise RuntimeError("key %s not found in lumi information" \
324  % key.__str__())
325  if lumiCont.minIntLum and lumiCont.minIntLum > intLum or \
326  lumiCont.maxIntLum and lumiCont.maxIntLum < intLum:
327  continue
328  lumFrac = old_div(intLum, lumiCont.totalRecLum)
329  xVals.append( lumiCont[key].totalRecorded)
330  yVals.append (factor)
331  expectedVals.append (lumFrac)
332  predVals.append (lumFrac * options.pred)
333  # put on the last point if we aren't giving a maximum run
334  if not lumiCont.maxRun and not lumiCont.maxIntLum:
335  xVals.append (lumiCont.totalRecLum)
336  yVals.append (1)
337  expectedVals.append (1)
338  predVals.append (options.pred)
339 
342  if options.resetExpected:
343  slope = old_div((yVals[-1] - yVals[0]), (xVals[-1] - xVals[0]))
344  print("slope", slope)
345  for index, old in enumerate (expectedVals):
346  expectedVals[index] = yVals[0] + \
347  slope * (xVals[index] - xVals[0])
348 
351  if options.breakExpectedIntLum:
352  breakExpectedIntLum = []
353  for chunk in options.breakExpectedIntLum:
354  pieces = sepRE.split (chunk)
355  try:
356  for piece in pieces:
357  breakExpectedIntLum.append( float(piece) )
358  except:
359  raise RuntimeError("'%s' from '%s' is not a valid float" \
360  % (piece, chunk))
361  breakExpectedIntLum.sort()
362  boundaries = []
363  breakIndex = 0
364  done = False
365  for index, xPos in enumerate (xVals):
366  if xPos > breakExpectedIntLum[breakIndex]:
367  boundaries.append (index)
368  while breakIndex < len (breakExpectedIntLum):
369  breakIndex += 1
370  if breakIndex >= len (breakExpectedIntLum):
371  done = True
372  break
373  # If this next position is different, than
374  # we're golden. Otherwise, let it go through
375  # the loop again.
376  if xPos <= breakExpectedIntLum[breakIndex]:
377  break
378  if done:
379  break
380  # do we have any boundaries?
381  if not boundaries:
382  raise RuntimeError("No values of 'breakExpectedIntLum' are in current range.")
383  # is the first boundary at 0? If not, add 0
384  if boundaries[0]:
385  boundaries.insert (0, 0)
386  # is the last boundary at the end? If not, make the end a
387  # boundary
388  if boundaries[-1] != len (xVals) - 1:
389  boundaries.append( len (xVals) - 1 )
390  rangeList = list(zip (boundaries, boundaries[1:]))
391  for thisRange in rangeList:
392  upper = thisRange[1]
393  lower = thisRange[0]
394  slope = old_div((yVals[upper] - yVals[lower]), \
395  (xVals[upper] - xVals[lower]))
396  print("slope", slope)
397  # now go over the range inclusively
398  pairList = []
399  for index in range (lower, upper + 1):
400  newExpected = yVals[lower] + \
401  slope * (xVals[index] - xVals[lower])
402  pairList.append( (xVals[index], newExpected) )
403  expectedVals[index] = newExpected
404  expectedChunks.append (pairList)
405 
408  elif 'instLum' == options.edfMode or 'instIntLum' == options.edfMode:
409  eventTupList = []
410  if not lumiCont.xingInfo:
411  raise RuntimeError("Luminosity Xing information missing.")
412  for key, eventList in sorted( eventsDict.items() ):
413  try:
414  lumi = lumiCont[key]
415  instLum = lumi.aveInstLum
416  fracAXIL = lumi.fracAXILrecorded
417  totalAXIL = lumi.totalAXILrecorded
418  except:
419  raise RuntimeError("key %s not found in lumi information" \
420  % key.__str__())
421  for event in eventList:
422  eventTupList.append( (instLum, fracAXIL, totalAXIL, key,
423  event[0], event[1], ) )
424  eventTupList.sort()
425  for eventTup in eventTupList:
426  weight += eventTup[5]
427  factor = old_div(weight, totalWeight)
428  if 'instLum' == options.edfMode:
429  xVals.append (eventTup[0])
430  else:
431  xVals.append (eventTup[2])
432  yVals.append (factor)
433  expectedVals.append (eventTup[1])
434  predVals.append (eventTup[1] * options.pred)
435  else:
436  raise RuntimeError("It looks like Charles screwed up if you are seeing this.")
437 
438  size = len (xVals)
439  step = int (old_div(math.sqrt(size), 2) + 1)
440  if options.printValues:
441  for index in range (size):
442  print("%8f %8f %8f" % (xVals[index], yVals[index], expectedVals[index]), end=' ')
443  if index > step:
444  denom = xVals[index] - xVals[index - step]
445  numer = yVals[index] - yVals[index - step]
446  if denom:
447  print(" %8f" % (old_div(numer, denom)), end=' ')
448  if 0 == index % step:
449  print(" **", end=' ')
451  print()
452  print()
453 
454  xArray = array.array ('d', xVals)
455  yArray = array.array ('d', yVals)
456  expected = array.array ('d', expectedVals)
457  graph = ROOT.TGraph( size, xArray, yArray)
458  graph.SetTitle (options.title)
459  graph.SetMarkerStyle (20)
460  expectedGraph = ROOT.TGraph( size, xArray, expected)
461  expectedGraph.SetLineColor (ROOT.kRed)
462  expectedGraph.SetLineWidth (3)
463  if options.noDataPoints:
464  expectedGraph.SetLineStyle (2)
465 
466  # run statistical tests
467  if options.weights:
468  print("average weight per event:", old_div(weight, ( size - 1)))
469  maxDistance = ROOT.TMath.KolmogorovTest (size, yArray,
470  size, expected,
471  "M")
472  prob = ROOT.TMath.KolmogorovProb( maxDistance * math.sqrt( size ) )
473 
474  # display everything
475  ROOT.gROOT.SetStyle('Plain')
476  ROOT.gROOT.SetBatch()
477  c1 = ROOT.TCanvas()
478  graph.GetXaxis().SetRangeUser (min (xVals), max (xVals))
479  minValue = min (min(yVals), min(expected))
480  if options.pred:
481  minValue = min (minValue, min (predVals))
482  graph.GetYaxis().SetRangeUser (minValue,
483  max (max(yVals), max(expected), max(predVals)))
484  graph.SetLineWidth (3)
485  if options.noDataPoints:
486  graph.Draw ("AL")
487  else:
488  graph.Draw ("ALP")
489  if 'instLum' == options.edfMode:
490  graph.GetXaxis().SetTitle ("Average Xing Inst. Luminosity (1/ub/s)")
491  graph.GetXaxis().SetRangeUser (0., lumiCont.max('aveInstLum'))
492  else:
493  if 'instIntLum' == options.edfMode:
494  graph.GetXaxis().SetTitle ("Integrated Luminosity - Inst. Lum. Ordered (1/%s)" \
495  % lumiCont.invunits)
496  else:
497  graph.GetXaxis().SetTitle ("Integrated Luminosity (1/%s)" \
498  % lumiCont.invunits)
499  graph.GetYaxis().SetTitle ("Fraction of Events Seen")
500  expectedGraphs = []
501  if expectedChunks:
502  for index, chunk in enumerate (expectedChunks):
503  expectedXarray = array.array ('d', [item[0] for item in chunk])
504  expectedYarray = array.array ('d', [item[1] for item in chunk])
505  expectedGraph = ROOT.TGraph( len(chunk),
506  expectedXarray,
507  expectedYarray )
508  expectedGraph.SetLineWidth (3)
509  if options.noDataPoints:
510  expectedGraph.SetLineStyle (2)
511  if index % 2:
512  expectedGraph.SetLineColor (ROOT.kBlue)
513  else:
514  expectedGraph.SetLineColor (ROOT.kRed)
515  expectedGraph.Draw("L")
516  expectedGraphs.append (expectedGraph)
517  exptectedGraph = expectedGraphs[0]
518  else:
519  expectedGraph.Draw ("L")
520  green = 0
521  if options.pred:
522  predArray = array.array ('d', predVals)
523  green = ROOT.TGraph (size, xArray, predArray)
524  green.SetLineWidth (3)
525  green.SetLineColor (8)
526  green.Draw ('l')
527  legend = ROOT.TLegend(0.15, 0.65, 0.50, 0.85)
528  legend.SetFillStyle (0)
529  legend.SetLineColor(ROOT.kWhite)
530  observed = 'Observed'
531  if options.weights:
532  observed += ' (weighted)'
533  legend.AddEntry(graph, observed,"PL")
534  if options.resetExpected:
535  legend.AddEntry(expectedGraph, "Expected from partial yield","L")
536  else:
537  legend.AddEntry(expectedGraph, "Expected from total yield","L")
538  if options.pred:
539  legend.AddEntry(green, options.predLabel,"L")
540  legend.AddEntry("","D_{stat}=%.3f, N=%d" % (maxDistance, size),"")
541  legend.AddEntry("","P_{KS}=%.3f" % prob,"")
542  legend.Draw()
543 
544  # save file
545  c1.Print (outputFile)
546 
547 
548 
555 
556 if __name__ == '__main__':
557 
560  allowedEDF = ['time', 'instLum', 'instIntLum']
561  parser = optparse.OptionParser ("Usage: %prog [options] lumi.csv events.txt output.png", description='Script for generating EDF curves. See https://twiki.cern.ch/twiki/bin/viewauth/CMS/SWGuideGenerateEDF for more details.')
562  plotGroup = optparse.OptionGroup (parser, "Plot Options")
563  rangeGroup = optparse.OptionGroup (parser, "Range Options")
564  inputGroup = optparse.OptionGroup (parser, "Input Options")
565  modeGroup = optparse.OptionGroup (parser, "Mode Options")
566  plotGroup.add_option ('--title', dest='title', type='string',
567  default = 'Empirical Distribution Function',
568  help = 'title of plot (default %default)')
569  plotGroup.add_option ('--predicted', dest='pred', type='float',
570  default = 0,
571  help = 'factor by which predicted curve is greater than observed')
572  plotGroup.add_option ('--predLabel', dest='predLabel', type='string',
573  default = 'Predicted',
574  help = 'label of predicted in legend')
575  plotGroup.add_option ('--noDataPoints', dest='noDataPoints',
576  action='store_true',
577  help="Draw lines but no points for data")
578  rangeGroup.add_option ('--minRun', dest='minRun', type='int', default=0,
579  help='Minimum run number to consider')
580  rangeGroup.add_option ('--maxRun', dest='maxRun', type='int', default=0,
581  help='Maximum run number to consider')
582  rangeGroup.add_option ('--minIntLum', dest='minIntLum', type='float', default=0,
583  help='Minimum integrated luminosity to consider')
584  rangeGroup.add_option ('--maxIntLum', dest='maxIntLum', type='float', default=0,
585  help='Maximum integrated luminosity to consider')
586  rangeGroup.add_option ('--resetExpected', dest='resetExpected',
587  action='store_true',
588  help='Reset expected from total yield to highest point considered')
589  rangeGroup.add_option ('--breakExpectedIntLum', dest='breakExpectedIntLum',
590  type='string', action='append', default=[],
591  help='Break expected curve into pieces at integrated luminosity boundaries')
592  inputGroup.add_option ('--ignoreNoLumiEvents', dest='ignore',
593  action='store_true',
594  help = 'Ignore (with a warning) events that do not have a lumi section')
595  inputGroup.add_option ('--noWarnings', dest='noWarnings',
596  action='store_true',
597  help = 'Do not print warnings about missing luminosity information')
598  inputGroup.add_option ('--runEventLumi', dest='relOrder',
599  action='store_true',
600  help = 'Parse event list assuming Run, Event #, Lumi# order')
601  inputGroup.add_option ('--weights', dest='weights', action='store_true',
602  help = 'Read fourth column as a weight')
603  modeGroup.add_option ('--print', dest='printValues', action='store_true',
604  help = 'Print X and Y values of EDF plot')
605  modeGroup.add_option ('--runsWithLumis', dest='runsWithLumis',
606  type='string',action='append', default=[],
607  help='Print out run and lumi sections corresponding to integrated luminosities provided and then exits')
608  modeGroup.add_option ('--edfMode', dest='edfMode', type='string',
609  default='time',
610  help="EDF Mode %s (default '%%default')" % allowedEDF)
611  parser.add_option_group (plotGroup)
612  parser.add_option_group (rangeGroup)
613  parser.add_option_group (inputGroup)
614  parser.add_option_group (modeGroup)
615  (options, args) = parser.parse_args()
616 
617  if options.edfMode not in allowedEDF:
618  raise RuntimeError("edfMode (currently '%s') must be one of %s" \
619  % (options.edfMode, allowedEDF))
620 
621  if len (args) != 3 and not (options.runsWithLumis and len(args) >= 1):
622  raise RuntimeError("Must provide lumi.csv, events.txt, and output.png")
623 
624 
625 
628  cont = LumiInfoCont (args[0], **options.__dict__)
629  cont.minRun = options.minRun
630  cont.maxRun = options.maxRun
631  cont.minIntLum = options.minIntLum
632  cont.maxIntLum = options.maxIntLum
633 
634 
638  if options.runsWithLumis:
639  recLumis = []
640  for line in options.runsWithLumis:
641  pieces = sepRE.split (line)
642  for piece in pieces:
643  try:
644  recLumValue = float (piece)
645  except:
646  raise RuntimeError("'%s' in '%s' is not a float" % \
647  (piece, line))
648  if recLumValue <= 0:
649  raise RuntimeError("You must provide positive values for -runsWithLumis ('%f' given)" % recLumValue)
650  recLumis.append (recLumValue)
651  if not recLumis:
652  raise RuntimeError("What did Charles do now?")
653  recLumis.sort()
654  recLumIndex = 0
655  recLumValue = recLumis [recLumIndex]
656  prevRecLumi = 0.
657  done = False
658  for key, lumi in cont.items():
659  if prevRecLumi >= recLumValue and recLumValue < lumi.totalRecorded:
660  # found it
661  print("%s contains total recorded lumi %f" % \
662  (key.__str__(), recLumValue))
663  while True:
664  recLumIndex += 1
665  if recLumIndex == len (recLumis):
666  done = True
667  break
668  recLumValue = recLumis [recLumIndex]
669  if prevRecLumi >= recLumValue and recLumValue < lumi.totalRecorded:
670  # found it
671  print("%s contains total recorded lumi %f" % \
672  (key.__str__(), recLumValue))
673  else:
674  break
675  if done:
676  break
677  prevRecLumi = lumi.totalRecorded
678  if recLumIndex < len (recLumis):
679  print("Theses lumis not found: %s" % recLumis[recLumIndex:])
680  sys.exit()
681 
682 
685  if options.edfMode != 'time' and not cont.xingInfo:
686  raise RuntimeError("'%s' does not have Xing info" % args[0])
687  eventsDict, totalWeight = loadEvents (args[1], cont, options)
688  makeEDFplot (cont, eventsDict, totalWeight, args[2], options)
def __init__(self, line)
Definition: generateEDF.py:31
def __init__(self, filename, kwargs)
Definition: generateEDF.py:112
def loadEvents(filename, cont, options)
General Functions
Definition: generateEDF.py:240
invunits
Now that everything is setup, switch integrated ## luminosity to more reasonable units.
Definition: generateEDF.py:156
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:47
def makeEDFplot(lumiCont, eventsDict, totalWeight, outputFile, options)
Definition: generateEDF.py:290
def fixXingInfo(self)
Definition: generateEDF.py:68
LumiInfoCont Class
Definition: generateEDF.py:110
LumiInfo Class
Definition: generateEDF.py:26