3 from __future__
import print_function
4 from builtins
import range
8 from pprint
import pprint
14 sepRE = re.compile (
r'[\s,;:]+')
15 nonSpaceRE = re.compile (
r'\S')
25 lastSingleXingRun = 136175
26 lumiSectionLength = 23.310779
36 pieces = sepRE.split (line.strip())
39 raise RuntimeError(
"Odd number of pieces")
41 raise RuntimeError(
"Not enough pieces")
43 self.
run = int (pieces[0])
44 self.
lumi = int (pieces[1])
48 raise RuntimeError(
"Pieces not right format")
51 for xing, lum
in zip (pieces[4::2],pieces[5::2]):
54 self.instLums.append( (xing, lum) )
58 raise RuntimeError(
"Inst Lumi Info malformed")
69 raise RuntimeError(
"This event %s already has Xing information" \
71 if self.
run > LumiInfo.lastSingleXingRun:
79 self.
delivered / LumiInfo.lumiSectionLength
80 self.instLums.append( (xing, lum) )
92 return "%6d, %4d: %6.1f (%4.1f%%) %4.2f (%3d)" % \
110 print(
"loading luminosity information from '%s'." % filename)
111 source = open (filename,
'r') 113 'delivered',
'recorded']
130 lumi = LumiInfo (line)
133 self[lumi.key] = lumi
135 if not self.
xingInfo and lumi.xingInfo:
142 val = getattr (lumi, key)
143 if val < self.
_min[key]
or self.
_min[key] < 0:
145 if val > self.
_max[key]
or not self.
_max[key]:
164 for lumis
in self.values():
165 lumis.delivered /= lumFactor
166 lumis.recorded /= lumFactor
174 retval =
'run, lum del ( dt ) inst (#xng)\n' 175 for key, value
in sorted (six.iteritems(self)):
176 retval +=
"%s\n" % value
181 return self.
_min[key]
185 return self.
_max[key]
189 return sorted (dict.keys (self))
193 return sorted (dict.iteritems (self))
199 for key, lumi
in six.iteritems(self):
200 total += lumi.recorded
201 lumi.totalRecorded = total
209 for key, lumi
in six.iteritems(self):
210 if not lumi.xingInfo
and not lumi.fixXingInfo():
212 print(
"Do not have lumi xing info for %s" % lumi.keyString)
214 print(
"Setting no Xing info flag")
218 xingKeyList.append( (lumi.aveInstLum, key) )
219 if lumi.aveInstLum > maxAveInstLum:
220 maxAveInstLum = lumi.aveInstLum
223 for tup
in xingKeyList:
225 total += lumi.recorded
226 lumi.totalAXILrecorded = total
228 lumi.fracAXIL = lumi.aveInstLum / maxAveInstLum
239 print(
"loading events from '%s'" % filename)
240 events = open (filename,
'r') 241 runIndex, lumiIndex, eventIndex, weightIndex = 0, 1, 2, 3 243 lumiIndex, eventIndex = 2,1
249 pieces = sepRE.split (line.strip())
250 if len (pieces) < minPieces:
251 if nonSpaceRE.search (line):
252 print(
"skipping", line)
255 run, lumi, event =
int( pieces[runIndex] ), \
256 int( pieces[lumiIndex] ), \
257 int( pieces[eventIndex] )
263 print(
"Warning, %s is not found in the lumi information" \
267 raise RuntimeError(
"%s is not found in lumi information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
269 if options.edfMode !=
'time' and not cont[key].xingInfo:
271 print(
"Warning, %s does not have Xing information" \
275 raise RuntimeError(
"%s does not have Xing information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
278 weight = float (pieces[weightIndex])
281 eventsDict.setdefault( key, []).
append( (event, weight) )
282 totalWeight += weight
284 return eventsDict, totalWeight
287 def makeEDFplot (lumiCont, eventsDict, totalWeight, outputFile, options):
298 if 'time' == options.edfMode:
300 if lumiCont.minRun
or lumiCont.minIntLum:
306 for key, eventList
in sorted( six.iteritems(eventsDict) ):
309 if lumiCont.minRun
and lumiCont.minRun > key[0]
or \
310 lumiCont.maxRun
and lumiCont.maxRun < key[0]:
312 for event
in eventList:
316 factor = weight / totalWeight
318 intLum = lumiCont[key].totalRecorded
320 raise RuntimeError(
"key %s not found in lumi information" \
322 if lumiCont.minIntLum
and lumiCont.minIntLum > intLum
or \
323 lumiCont.maxIntLum
and lumiCont.maxIntLum < intLum:
325 lumFrac = intLum / lumiCont.totalRecLum
326 xVals.append( lumiCont[key].totalRecorded)
327 yVals.append (factor)
328 expectedVals.append (lumFrac)
329 predVals.append (lumFrac * options.pred)
331 if not lumiCont.maxRun
and not lumiCont.maxIntLum:
332 xVals.append (lumiCont.totalRecLum)
334 expectedVals.append (1)
335 predVals.append (options.pred)
339 if options.resetExpected:
340 slope = (yVals[-1] - yVals[0]) / (xVals[-1] - xVals[0])
341 print(
"slope", slope)
342 for index, old
in enumerate (expectedVals):
343 expectedVals[index] = yVals[0] + \
344 slope * (xVals[index] - xVals[0])
348 if options.breakExpectedIntLum:
349 breakExpectedIntLum = []
350 for chunk
in options.breakExpectedIntLum:
351 pieces = sepRE.split (chunk)
354 breakExpectedIntLum.append(
float(piece) )
356 raise RuntimeError(
"'%s' from '%s' is not a valid float" \
358 breakExpectedIntLum.sort()
362 for index, xPos
in enumerate (xVals):
363 if xPos > breakExpectedIntLum[breakIndex]:
364 boundaries.append (index)
365 while breakIndex < len (breakExpectedIntLum):
367 if breakIndex >= len (breakExpectedIntLum):
373 if xPos <= breakExpectedIntLum[breakIndex]:
379 raise RuntimeError(
"No values of 'breakExpectedIntLum' are in current range.")
382 boundaries.insert (0, 0)
385 if boundaries[-1] != len (xVals) - 1:
386 boundaries.append( len (xVals) - 1 )
387 rangeList =
list(zip (boundaries, boundaries[1:]))
388 for thisRange
in rangeList:
391 slope = (yVals[upper] - yVals[lower]) / \
392 (xVals[upper] - xVals[lower])
393 print(
"slope", slope)
396 for index
in range (lower, upper + 1):
397 newExpected = yVals[lower] + \
398 slope * (xVals[index] - xVals[lower])
399 pairList.append( (xVals[index], newExpected) )
400 expectedVals[index] = newExpected
401 expectedChunks.append (pairList)
405 elif 'instLum' == options.edfMode
or 'instIntLum' == options.edfMode:
407 if not lumiCont.xingInfo:
408 raise RuntimeError(
"Luminosity Xing information missing.")
409 for key, eventList
in sorted( six.iteritems(eventsDict) ):
412 instLum = lumi.aveInstLum
413 fracAXIL = lumi.fracAXILrecorded
414 totalAXIL = lumi.totalAXILrecorded
416 raise RuntimeError(
"key %s not found in lumi information" \
418 for event
in eventList:
419 eventTupList.append( (instLum, fracAXIL, totalAXIL, key,
420 event[0], event[1], ) )
422 for eventTup
in eventTupList:
423 weight += eventTup[5]
424 factor = weight / totalWeight
425 if 'instLum' == options.edfMode:
426 xVals.append (eventTup[0])
428 xVals.append (eventTup[2])
429 yVals.append (factor)
430 expectedVals.append (eventTup[1])
431 predVals.append (eventTup[1] * options.pred)
433 raise RuntimeError(
"It looks like Charles screwed up if you are seeing this.")
436 step = int (math.sqrt(size) / 2 + 1)
437 if options.printValues:
438 for index
in range (size):
439 print(
"%8f %8f %8f" % (xVals[index], yVals[index], expectedVals[index]), end=
' ')
441 denom = xVals[index] - xVals[index - step]
442 numer = yVals[index] - yVals[index - step]
444 print(
" %8f" % (numer / denom), end=
' ')
445 if 0 == index % step:
446 print(
" **", end=
' ')
451 xArray = array.array (
'd', xVals)
452 yArray = array.array (
'd', yVals)
453 expected = array.array (
'd', expectedVals)
454 graph = ROOT.TGraph( size, xArray, yArray)
455 graph.SetTitle (options.title)
456 graph.SetMarkerStyle (20)
457 expectedGraph = ROOT.TGraph( size, xArray, expected)
458 expectedGraph.SetLineColor (ROOT.kRed)
459 expectedGraph.SetLineWidth (3)
460 if options.noDataPoints:
461 expectedGraph.SetLineStyle (2)
465 print(
"average weight per event:", weight / ( size - 1))
466 maxDistance = ROOT.TMath.KolmogorovTest (size, yArray,
469 prob = ROOT.TMath.KolmogorovProb( maxDistance * math.sqrt( size ) )
472 ROOT.gROOT.SetStyle(
'Plain')
473 ROOT.gROOT.SetBatch()
475 graph.GetXaxis().SetRangeUser (min (xVals), max (xVals))
476 minValue = min (
min(yVals),
min(expected))
478 minValue = min (minValue, min (predVals))
479 graph.GetYaxis().SetRangeUser (minValue,
480 max (
max(yVals),
max(expected),
max(predVals)))
481 graph.SetLineWidth (3)
482 if options.noDataPoints:
486 if 'instLum' == options.edfMode:
487 graph.GetXaxis().SetTitle (
"Average Xing Inst. Luminosity (1/ub/s)")
488 graph.GetXaxis().SetRangeUser (0., lumiCont.max(
'aveInstLum'))
490 if 'instIntLum' == options.edfMode:
491 graph.GetXaxis().SetTitle (
"Integrated Luminosity - Inst. Lum. Ordered (1/%s)" \
494 graph.GetXaxis().SetTitle (
"Integrated Luminosity (1/%s)" \
496 graph.GetYaxis().SetTitle (
"Fraction of Events Seen")
499 for index, chunk
in enumerate (expectedChunks):
500 expectedXarray = array.array (
'd', [item[0]
for item
in chunk])
501 expectedYarray = array.array (
'd', [item[1]
for item
in chunk])
502 expectedGraph = ROOT.TGraph( len(chunk),
505 expectedGraph.SetLineWidth (3)
506 if options.noDataPoints:
507 expectedGraph.SetLineStyle (2)
509 expectedGraph.SetLineColor (ROOT.kBlue)
511 expectedGraph.SetLineColor (ROOT.kRed)
512 expectedGraph.Draw(
"L")
513 expectedGraphs.append (expectedGraph)
514 exptectedGraph = expectedGraphs[0]
516 expectedGraph.Draw (
"L")
519 predArray = array.array (
'd', predVals)
520 green = ROOT.TGraph (size, xArray, predArray)
521 green.SetLineWidth (3)
522 green.SetLineColor (8)
524 legend = ROOT.TLegend(0.15, 0.65, 0.50, 0.85)
525 legend.SetFillStyle (0)
526 legend.SetLineColor(ROOT.kWhite)
527 observed =
'Observed' 529 observed +=
' (weighted)' 530 legend.AddEntry(graph, observed,
"PL")
531 if options.resetExpected:
532 legend.AddEntry(expectedGraph,
"Expected from partial yield",
"L")
534 legend.AddEntry(expectedGraph,
"Expected from total yield",
"L")
536 legend.AddEntry(green, options.predLabel,
"L")
537 legend.AddEntry(
"",
"D_{stat}=%.3f, N=%d" % (maxDistance, size),
"")
538 legend.AddEntry(
"",
"P_{KS}=%.3f" % prob,
"")
542 c1.Print (outputFile)
553 if __name__ ==
'__main__':
557 allowedEDF = [
'time',
'instLum',
'instIntLum']
558 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.')
559 plotGroup = optparse.OptionGroup (parser,
"Plot Options")
560 rangeGroup = optparse.OptionGroup (parser,
"Range Options")
561 inputGroup = optparse.OptionGroup (parser,
"Input Options")
562 modeGroup = optparse.OptionGroup (parser,
"Mode Options")
563 plotGroup.add_option (
'--title', dest=
'title', type=
'string',
564 default =
'Empirical Distribution Function',
565 help =
'title of plot (default %default)')
566 plotGroup.add_option (
'--predicted', dest=
'pred', type=
'float',
568 help =
'factor by which predicted curve is greater than observed')
569 plotGroup.add_option (
'--predLabel', dest=
'predLabel', type=
'string',
570 default =
'Predicted',
571 help =
'label of predicted in legend')
572 plotGroup.add_option (
'--noDataPoints', dest=
'noDataPoints',
574 help=
"Draw lines but no points for data")
575 rangeGroup.add_option (
'--minRun', dest=
'minRun', type=
'int', default=0,
576 help=
'Minimum run number to consider')
577 rangeGroup.add_option (
'--maxRun', dest=
'maxRun', type=
'int', default=0,
578 help=
'Maximum run number to consider')
579 rangeGroup.add_option (
'--minIntLum', dest=
'minIntLum', type=
'float', default=0,
580 help=
'Minimum integrated luminosity to consider')
581 rangeGroup.add_option (
'--maxIntLum', dest=
'maxIntLum', type=
'float', default=0,
582 help=
'Maximum integrated luminosity to consider')
583 rangeGroup.add_option (
'--resetExpected', dest=
'resetExpected',
585 help=
'Reset expected from total yield to highest point considered')
586 rangeGroup.add_option (
'--breakExpectedIntLum', dest=
'breakExpectedIntLum',
587 type=
'string', action=
'append', default=[],
588 help=
'Break expected curve into pieces at integrated luminosity boundaries')
589 inputGroup.add_option (
'--ignoreNoLumiEvents', dest=
'ignore',
591 help =
'Ignore (with a warning) events that do not have a lumi section')
592 inputGroup.add_option (
'--noWarnings', dest=
'noWarnings',
594 help =
'Do not print warnings about missing luminosity information')
595 inputGroup.add_option (
'--runEventLumi', dest=
'relOrder',
597 help =
'Parse event list assuming Run, Event #, Lumi# order')
598 inputGroup.add_option (
'--weights', dest=
'weights', action=
'store_true',
599 help =
'Read fourth column as a weight')
600 modeGroup.add_option (
'--print', dest=
'printValues', action=
'store_true',
601 help =
'Print X and Y values of EDF plot')
602 modeGroup.add_option (
'--runsWithLumis', dest=
'runsWithLumis',
603 type=
'string',action=
'append', default=[],
604 help=
'Print out run and lumi sections corresponding to integrated luminosities provided and then exits')
605 modeGroup.add_option (
'--edfMode', dest=
'edfMode', type=
'string',
607 help=
"EDF Mode %s (default '%%default')" % allowedEDF)
608 parser.add_option_group (plotGroup)
609 parser.add_option_group (rangeGroup)
610 parser.add_option_group (inputGroup)
611 parser.add_option_group (modeGroup)
612 (options, args) = parser.parse_args()
614 if options.edfMode
not in allowedEDF:
615 raise RuntimeError(
"edfMode (currently '%s') must be one of %s" \
616 % (options.edfMode, allowedEDF))
618 if len (args) != 3
and not (options.runsWithLumis
and len(args) >= 1):
619 raise RuntimeError(
"Must provide lumi.csv, events.txt, and output.png")
625 cont = LumiInfoCont (args[0], **options.__dict__)
626 cont.minRun = options.minRun
627 cont.maxRun = options.maxRun
628 cont.minIntLum = options.minIntLum
629 cont.maxIntLum = options.maxIntLum
635 if options.runsWithLumis:
637 for line
in options.runsWithLumis:
638 pieces = sepRE.split (line)
641 recLumValue = float (piece)
643 raise RuntimeError(
"'%s' in '%s' is not a float" % \
646 raise RuntimeError(
"You must provide positive values for -runsWithLumis ('%f' given)" % recLumValue)
647 recLumis.append (recLumValue)
649 raise RuntimeError(
"What did Charles do now?")
652 recLumValue = recLumis [recLumIndex]
655 for key, lumi
in six.iteritems(cont):
656 if prevRecLumi >= recLumValue
and recLumValue < lumi.totalRecorded:
658 print(
"%s contains total recorded lumi %f" % \
659 (key.__str__(), recLumValue))
662 if recLumIndex == len (recLumis):
665 recLumValue = recLumis [recLumIndex]
666 if prevRecLumi >= recLumValue
and recLumValue < lumi.totalRecorded:
668 print(
"%s contains total recorded lumi %f" % \
669 (key.__str__(), recLumValue))
674 prevRecLumi = lumi.totalRecorded
675 if recLumIndex < len (recLumis):
676 print(
"Theses lumis not found: %s" % recLumis[recLumIndex:])
682 if options.edfMode !=
'time' and not cont.xingInfo:
683 raise RuntimeError(
"'%s' does not have Xing info" % args[0])
684 eventsDict, totalWeight = loadEvents (args[1], cont, options)
685 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