3 from __future__
import print_function
7 from pprint
import pprint
13 sepRE = re.compile (
r'[\s,;:]+')
14 nonSpaceRE = re.compile (
r'\S')
24 lastSingleXingRun = 136175
25 lumiSectionLength = 23.310779
35 pieces = sepRE.split (line.strip())
38 raise RuntimeError(
"Odd number of pieces")
40 raise RuntimeError(
"Not enough pieces")
42 self.
run = int (pieces[0])
43 self.
lumi = int (pieces[1])
47 raise RuntimeError(
"Pieces not right format")
50 for xing, lum
in zip (pieces[4::2],pieces[5::2]):
53 self.instLums.append( (xing, lum) )
57 raise RuntimeError(
"Inst Lumi Info malformed")
68 raise RuntimeError(
"This event %s already has Xing information" \
70 if self.
run > LumiInfo.lastSingleXingRun:
78 self.
delivered / LumiInfo.lumiSectionLength
79 self.instLums.append( (xing, lum) )
91 return "%6d, %4d: %6.1f (%4.1f%%) %4.2f (%3d)" % \
109 print(
"loading luminosity information from '%s'." % filename)
110 source = open (filename,
'r') 112 'delivered',
'recorded']
129 lumi = LumiInfo (line)
132 self[lumi.key] = lumi
134 if not self.
xingInfo and lumi.xingInfo:
141 val = getattr (lumi, key)
142 if val < self.
_min[key]
or self.
_min[key] < 0:
144 if val > self.
_max[key]
or not self.
_max[key]:
163 for lumis
in self.values():
164 lumis.delivered /= lumFactor
165 lumis.recorded /= lumFactor
173 retval =
'run, lum del ( dt ) inst (#xng)\n' 174 for key, value
in sorted (six.iteritems(self)):
175 retval +=
"%s\n" % value
180 return self.
_min[key]
184 return self.
_max[key]
188 return sorted (dict.keys (self))
192 return sorted (dict.iteritems (self))
198 for key, lumi
in six.iteritems(self):
199 total += lumi.recorded
200 lumi.totalRecorded = total
208 for key, lumi
in six.iteritems(self):
209 if not lumi.xingInfo
and not lumi.fixXingInfo():
211 print(
"Do not have lumi xing info for %s" % lumi.keyString)
213 print(
"Setting no Xing info flag")
217 xingKeyList.append( (lumi.aveInstLum, key) )
218 if lumi.aveInstLum > maxAveInstLum:
219 maxAveInstLum = lumi.aveInstLum
222 for tup
in xingKeyList:
224 total += lumi.recorded
225 lumi.totalAXILrecorded = total
227 lumi.fracAXIL = lumi.aveInstLum / maxAveInstLum
238 print(
"loading events from '%s'" % filename)
239 events = open (filename,
'r') 240 runIndex, lumiIndex, eventIndex, weightIndex = 0, 1, 2, 3 242 lumiIndex, eventIndex = 2,1
248 pieces = sepRE.split (line.strip())
249 if len (pieces) < minPieces:
250 if nonSpaceRE.search (line):
251 print(
"skipping", line)
254 run, lumi, event =
int( pieces[runIndex] ), \
255 int( pieces[lumiIndex] ), \
256 int( pieces[eventIndex] )
262 print(
"Warning, %s is not found in the lumi information" \
266 raise RuntimeError(
"%s is not found in lumi information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
268 if options.edfMode !=
'time' and not cont[key].xingInfo:
270 print(
"Warning, %s does not have Xing information" \
274 raise RuntimeError(
"%s does not have Xing information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
277 weight = float (pieces[weightIndex])
280 eventsDict.setdefault( key, []).
append( (event, weight) )
281 totalWeight += weight
283 return eventsDict, totalWeight
286 def makeEDFplot (lumiCont, eventsDict, totalWeight, outputFile, options):
297 if 'time' == options.edfMode:
299 if lumiCont.minRun
or lumiCont.minIntLum:
305 for key, eventList
in sorted( six.iteritems(eventsDict) ):
308 if lumiCont.minRun
and lumiCont.minRun > key[0]
or \
309 lumiCont.maxRun
and lumiCont.maxRun < key[0]:
311 for event
in eventList:
315 factor = weight / totalWeight
317 intLum = lumiCont[key].totalRecorded
319 raise RuntimeError(
"key %s not found in lumi information" \
321 if lumiCont.minIntLum
and lumiCont.minIntLum > intLum
or \
322 lumiCont.maxIntLum
and lumiCont.maxIntLum < intLum:
324 lumFrac = intLum / lumiCont.totalRecLum
325 xVals.append( lumiCont[key].totalRecorded)
326 yVals.append (factor)
327 expectedVals.append (lumFrac)
328 predVals.append (lumFrac * options.pred)
330 if not lumiCont.maxRun
and not lumiCont.maxIntLum:
331 xVals.append (lumiCont.totalRecLum)
333 expectedVals.append (1)
334 predVals.append (options.pred)
338 if options.resetExpected:
339 slope = (yVals[-1] - yVals[0]) / (xVals[-1] - xVals[0])
340 print(
"slope", slope)
341 for index, old
in enumerate (expectedVals):
342 expectedVals[index] = yVals[0] + \
343 slope * (xVals[index] - xVals[0])
347 if options.breakExpectedIntLum:
348 breakExpectedIntLum = []
349 for chunk
in options.breakExpectedIntLum:
350 pieces = sepRE.split (chunk)
353 breakExpectedIntLum.append(
float(piece) )
355 raise RuntimeError(
"'%s' from '%s' is not a valid float" \
357 breakExpectedIntLum.sort()
361 for index, xPos
in enumerate (xVals):
362 if xPos > breakExpectedIntLum[breakIndex]:
363 boundaries.append (index)
364 while breakIndex < len (breakExpectedIntLum):
366 if breakIndex >= len (breakExpectedIntLum):
372 if xPos <= breakExpectedIntLum[breakIndex]:
378 raise RuntimeError(
"No values of 'breakExpectedIntLum' are in current range.")
381 boundaries.insert (0, 0)
384 if boundaries[-1] != len (xVals) - 1:
385 boundaries.append( len (xVals) - 1 )
386 rangeList =
list(zip (boundaries, boundaries[1:]))
387 for thisRange
in rangeList:
390 slope = (yVals[upper] - yVals[lower]) / \
391 (xVals[upper] - xVals[lower])
392 print(
"slope", slope)
395 for index
in range (lower, upper + 1):
396 newExpected = yVals[lower] + \
397 slope * (xVals[index] - xVals[lower])
398 pairList.append( (xVals[index], newExpected) )
399 expectedVals[index] = newExpected
400 expectedChunks.append (pairList)
404 elif 'instLum' == options.edfMode
or 'instIntLum' == options.edfMode:
406 if not lumiCont.xingInfo:
407 raise RuntimeError(
"Luminosity Xing information missing.")
408 for key, eventList
in sorted( six.iteritems(eventsDict) ):
411 instLum = lumi.aveInstLum
412 fracAXIL = lumi.fracAXILrecorded
413 totalAXIL = lumi.totalAXILrecorded
415 raise RuntimeError(
"key %s not found in lumi information" \
417 for event
in eventList:
418 eventTupList.append( (instLum, fracAXIL, totalAXIL, key,
419 event[0], event[1], ) )
421 for eventTup
in eventTupList:
422 weight += eventTup[5]
423 factor = weight / totalWeight
424 if 'instLum' == options.edfMode:
425 xVals.append (eventTup[0])
427 xVals.append (eventTup[2])
428 yVals.append (factor)
429 expectedVals.append (eventTup[1])
430 predVals.append (eventTup[1] * options.pred)
432 raise RuntimeError(
"It looks like Charles screwed up if you are seeing this.")
435 step = int (math.sqrt(size) / 2 + 1)
436 if options.printValues:
437 for index
in range (size):
438 print(
"%8f %8f %8f" % (xVals[index], yVals[index], expectedVals[index]), end=
' ')
440 denom = xVals[index] - xVals[index - step]
441 numer = yVals[index] - yVals[index - step]
443 print(
" %8f" % (numer / denom), end=
' ')
444 if 0 == index % step:
445 print(
" **", end=
' ')
450 xArray = array.array (
'd', xVals)
451 yArray = array.array (
'd', yVals)
452 expected = array.array (
'd', expectedVals)
453 graph = ROOT.TGraph( size, xArray, yArray)
454 graph.SetTitle (options.title)
455 graph.SetMarkerStyle (20)
456 expectedGraph = ROOT.TGraph( size, xArray, expected)
457 expectedGraph.SetLineColor (ROOT.kRed)
458 expectedGraph.SetLineWidth (3)
459 if options.noDataPoints:
460 expectedGraph.SetLineStyle (2)
464 print(
"average weight per event:", weight / ( size - 1))
465 maxDistance = ROOT.TMath.KolmogorovTest (size, yArray,
468 prob = ROOT.TMath.KolmogorovProb( maxDistance * math.sqrt( size ) )
471 ROOT.gROOT.SetStyle(
'Plain')
472 ROOT.gROOT.SetBatch()
474 graph.GetXaxis().SetRangeUser (min (xVals), max (xVals))
475 minValue = min (
min(yVals),
min(expected))
477 minValue = min (minValue, min (predVals))
478 graph.GetYaxis().SetRangeUser (minValue,
479 max (
max(yVals),
max(expected),
max(predVals)))
480 graph.SetLineWidth (3)
481 if options.noDataPoints:
485 if 'instLum' == options.edfMode:
486 graph.GetXaxis().SetTitle (
"Average Xing Inst. Luminosity (1/ub/s)")
487 graph.GetXaxis().SetRangeUser (0., lumiCont.max(
'aveInstLum'))
489 if 'instIntLum' == options.edfMode:
490 graph.GetXaxis().SetTitle (
"Integrated Luminosity - Inst. Lum. Ordered (1/%s)" \
493 graph.GetXaxis().SetTitle (
"Integrated Luminosity (1/%s)" \
495 graph.GetYaxis().SetTitle (
"Fraction of Events Seen")
498 for index, chunk
in enumerate (expectedChunks):
499 expectedXarray = array.array (
'd', [item[0]
for item
in chunk])
500 expectedYarray = array.array (
'd', [item[1]
for item
in chunk])
501 expectedGraph = ROOT.TGraph( len(chunk),
504 expectedGraph.SetLineWidth (3)
505 if options.noDataPoints:
506 expectedGraph.SetLineStyle (2)
508 expectedGraph.SetLineColor (ROOT.kBlue)
510 expectedGraph.SetLineColor (ROOT.kRed)
511 expectedGraph.Draw(
"L")
512 expectedGraphs.append (expectedGraph)
513 exptectedGraph = expectedGraphs[0]
515 expectedGraph.Draw (
"L")
518 predArray = array.array (
'd', predVals)
519 green = ROOT.TGraph (size, xArray, predArray)
520 green.SetLineWidth (3)
521 green.SetLineColor (8)
523 legend = ROOT.TLegend(0.15, 0.65, 0.50, 0.85)
524 legend.SetFillStyle (0)
525 legend.SetLineColor(ROOT.kWhite)
526 observed =
'Observed' 528 observed +=
' (weighted)' 529 legend.AddEntry(graph, observed,
"PL")
530 if options.resetExpected:
531 legend.AddEntry(expectedGraph,
"Expected from partial yield",
"L")
533 legend.AddEntry(expectedGraph,
"Expected from total yield",
"L")
535 legend.AddEntry(green, options.predLabel,
"L")
536 legend.AddEntry(
"",
"D_{stat}=%.3f, N=%d" % (maxDistance, size),
"")
537 legend.AddEntry(
"",
"P_{KS}=%.3f" % prob,
"")
541 c1.Print (outputFile)
552 if __name__ ==
'__main__':
556 allowedEDF = [
'time',
'instLum',
'instIntLum']
557 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.')
558 plotGroup = optparse.OptionGroup (parser,
"Plot Options")
559 rangeGroup = optparse.OptionGroup (parser,
"Range Options")
560 inputGroup = optparse.OptionGroup (parser,
"Input Options")
561 modeGroup = optparse.OptionGroup (parser,
"Mode Options")
562 plotGroup.add_option (
'--title', dest=
'title', type=
'string',
563 default =
'Empirical Distribution Function',
564 help =
'title of plot (default %default)')
565 plotGroup.add_option (
'--predicted', dest=
'pred', type=
'float',
567 help =
'factor by which predicted curve is greater than observed')
568 plotGroup.add_option (
'--predLabel', dest=
'predLabel', type=
'string',
569 default =
'Predicted',
570 help =
'label of predicted in legend')
571 plotGroup.add_option (
'--noDataPoints', dest=
'noDataPoints',
573 help=
"Draw lines but no points for data")
574 rangeGroup.add_option (
'--minRun', dest=
'minRun', type=
'int', default=0,
575 help=
'Minimum run number to consider')
576 rangeGroup.add_option (
'--maxRun', dest=
'maxRun', type=
'int', default=0,
577 help=
'Maximum run number to consider')
578 rangeGroup.add_option (
'--minIntLum', dest=
'minIntLum', type=
'float', default=0,
579 help=
'Minimum integrated luminosity to consider')
580 rangeGroup.add_option (
'--maxIntLum', dest=
'maxIntLum', type=
'float', default=0,
581 help=
'Maximum integrated luminosity to consider')
582 rangeGroup.add_option (
'--resetExpected', dest=
'resetExpected',
584 help=
'Reset expected from total yield to highest point considered')
585 rangeGroup.add_option (
'--breakExpectedIntLum', dest=
'breakExpectedIntLum',
586 type=
'string', action=
'append', default=[],
587 help=
'Break expected curve into pieces at integrated luminosity boundaries')
588 inputGroup.add_option (
'--ignoreNoLumiEvents', dest=
'ignore',
590 help =
'Ignore (with a warning) events that do not have a lumi section')
591 inputGroup.add_option (
'--noWarnings', dest=
'noWarnings',
593 help =
'Do not print warnings about missing luminosity information')
594 inputGroup.add_option (
'--runEventLumi', dest=
'relOrder',
596 help =
'Parse event list assuming Run, Event #, Lumi# order')
597 inputGroup.add_option (
'--weights', dest=
'weights', action=
'store_true',
598 help =
'Read fourth column as a weight')
599 modeGroup.add_option (
'--print', dest=
'printValues', action=
'store_true',
600 help =
'Print X and Y values of EDF plot')
601 modeGroup.add_option (
'--runsWithLumis', dest=
'runsWithLumis',
602 type=
'string',action=
'append', default=[],
603 help=
'Print out run and lumi sections corresponding to integrated luminosities provided and then exits')
604 modeGroup.add_option (
'--edfMode', dest=
'edfMode', type=
'string',
606 help=
"EDF Mode %s (default '%%default')" % allowedEDF)
607 parser.add_option_group (plotGroup)
608 parser.add_option_group (rangeGroup)
609 parser.add_option_group (inputGroup)
610 parser.add_option_group (modeGroup)
611 (options, args) = parser.parse_args()
613 if options.edfMode
not in allowedEDF:
614 raise RuntimeError(
"edfMode (currently '%s') must be one of %s" \
615 % (options.edfMode, allowedEDF))
617 if len (args) != 3
and not (options.runsWithLumis
and len(args) >= 1):
618 raise RuntimeError(
"Must provide lumi.csv, events.txt, and output.png")
624 cont = LumiInfoCont (args[0], **options.__dict__)
625 cont.minRun = options.minRun
626 cont.maxRun = options.maxRun
627 cont.minIntLum = options.minIntLum
628 cont.maxIntLum = options.maxIntLum
634 if options.runsWithLumis:
636 for line
in options.runsWithLumis:
637 pieces = sepRE.split (line)
640 recLumValue = float (piece)
642 raise RuntimeError(
"'%s' in '%s' is not a float" % \
645 raise RuntimeError(
"You must provide positive values for -runsWithLumis ('%f' given)" % recLumValue)
646 recLumis.append (recLumValue)
648 raise RuntimeError(
"What did Charles do now?")
651 recLumValue = recLumis [recLumIndex]
654 for key, lumi
in six.iteritems(cont):
655 if prevRecLumi >= recLumValue
and recLumValue < lumi.totalRecorded:
657 print(
"%s contains total recorded lumi %f" % \
658 (key.__str__(), recLumValue))
661 if recLumIndex == len (recLumis):
664 recLumValue = recLumis [recLumIndex]
665 if prevRecLumi >= recLumValue
and recLumValue < lumi.totalRecorded:
667 print(
"%s contains total recorded lumi %f" % \
668 (key.__str__(), recLumValue))
673 prevRecLumi = lumi.totalRecorded
674 if recLumIndex < len (recLumis):
675 print(
"Theses lumis not found: %s" % recLumis[recLumIndex:])
681 if options.edfMode !=
'time' and not cont.xingInfo:
682 raise RuntimeError(
"'%s' does not have Xing info" % args[0])
683 eventsDict, totalWeight = loadEvents (args[1], cont, options)
684 makeEDFplot (cont, eventsDict, totalWeight, args[2], options)
def _integrateContainer(self)
def __init__(self, filename, kwargs)
S & print(S &os, JobReport::InputFile const &f)
def loadEvents(filename, cont, options)
General Functions
invunits
Now that everything is setup, switch integrated ## luminosity to more reasonable units.
def makeEDFplot(lumiCont, eventsDict, totalWeight, outputFile, options)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run