6 from pprint
import pprint
12 sepRE = re.compile (
r'[\s,;:]+')
13 nonSpaceRE = re.compile (
r'\S')
23 lastSingleXingRun = 136175
24 lumiSectionLength = 23.310779
34 pieces = sepRE.split (line.strip())
37 raise RuntimeError(
"Odd number of pieces")
39 raise RuntimeError(
"Not enough pieces")
41 self.
run = int (pieces[0])
42 self.
lumi = int (pieces[1])
46 raise RuntimeError(
"Pieces not right format")
49 for xing, lum
in zip (pieces[4::2],pieces[5::2]):
52 self.instLums.append( (xing, lum) )
56 raise RuntimeError(
"Inst Lumi Info malformed")
67 raise RuntimeError(
"This event %s already has Xing information" \
69 if self.
run > LumiInfo.lastSingleXingRun:
77 self.
delivered / LumiInfo.lumiSectionLength
78 self.instLums.append( (xing, lum) )
90 return "%6d, %4d: %6.1f (%4.1f%%) %4.2f (%3d)" % \
108 print "loading luminosity information from '%s'." % filename
109 source = open (filename,
'r') 111 'delivered',
'recorded']
128 lumi = LumiInfo (line)
131 self[lumi.key] = lumi
133 if not self.
xingInfo and lumi.xingInfo:
140 val = getattr (lumi, key)
141 if val < self.
_min[key]
or self.
_min[key] < 0:
143 if val > self.
_max[key]
or not self.
_max[key]:
162 for lumis
in self.values():
163 lumis.delivered /= lumFactor
164 lumis.recorded /= lumFactor
172 retval =
'run, lum del ( dt ) inst (#xng)\n' 173 for key, value
in sorted (six.iteritems(self)):
174 retval +=
"%s\n" % value
179 return self.
_min[key]
183 return self.
_max[key]
187 return sorted (dict.keys (self))
191 return sorted (dict.iteritems (self))
197 for key, lumi
in six.iteritems(self):
198 total += lumi.recorded
199 lumi.totalRecorded = total
207 for key, lumi
in six.iteritems(self):
208 if not lumi.xingInfo
and not lumi.fixXingInfo():
210 print "Do not have lumi xing info for %s" % lumi.keyString
212 print "Setting no Xing info flag" 216 xingKeyList.append( (lumi.aveInstLum, key) )
217 if lumi.aveInstLum > maxAveInstLum:
218 maxAveInstLum = lumi.aveInstLum
221 for tup
in xingKeyList:
223 total += lumi.recorded
224 lumi.totalAXILrecorded = total
226 lumi.fracAXIL = lumi.aveInstLum / maxAveInstLum
237 print "loading events from '%s'" % filename
238 events = open (filename,
'r') 239 runIndex, lumiIndex, eventIndex, weightIndex = 0, 1, 2, 3 241 lumiIndex, eventIndex = 2,1
247 pieces = sepRE.split (line.strip())
248 if len (pieces) < minPieces:
249 if nonSpaceRE.search (line):
250 print "skipping", line
253 run, lumi, event =
int( pieces[runIndex] ), \
254 int( pieces[lumiIndex] ), \
255 int( pieces[eventIndex] )
261 print "Warning, %s is not found in the lumi information" \
265 raise RuntimeError(
"%s is not found in lumi information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
267 if options.edfMode !=
'time' and not cont[key].xingInfo:
269 print "Warning, %s does not have Xing information" \
273 raise RuntimeError(
"%s does not have Xing information. Use '--ignoreNoLumiEvents' option to ignore these events and continue." \
276 weight = float (pieces[weightIndex])
279 eventsDict.setdefault( key, []).
append( (event, weight) )
280 totalWeight += weight
282 return eventsDict, totalWeight
285 def makeEDFplot (lumiCont, eventsDict, totalWeight, outputFile, options):
296 if 'time' == options.edfMode:
298 if lumiCont.minRun
or lumiCont.minIntLum:
304 for key, eventList
in sorted( six.iteritems(eventsDict) ):
307 if lumiCont.minRun
and lumiCont.minRun > key[0]
or \
308 lumiCont.maxRun
and lumiCont.maxRun < key[0]:
310 for event
in eventList:
314 factor = weight / totalWeight
316 intLum = lumiCont[key].totalRecorded
318 raise RuntimeError(
"key %s not found in lumi information" \
320 if lumiCont.minIntLum
and lumiCont.minIntLum > intLum
or \
321 lumiCont.maxIntLum
and lumiCont.maxIntLum < intLum:
323 lumFrac = intLum / lumiCont.totalRecLum
324 xVals.append( lumiCont[key].totalRecorded)
325 yVals.append (factor)
326 expectedVals.append (lumFrac)
327 predVals.append (lumFrac * options.pred)
329 if not lumiCont.maxRun
and not lumiCont.maxIntLum:
330 xVals.append (lumiCont.totalRecLum)
332 expectedVals.append (1)
333 predVals.append (options.pred)
337 if options.resetExpected:
338 slope = (yVals[-1] - yVals[0]) / (xVals[-1] - xVals[0])
340 for index, old
in enumerate (expectedVals):
341 expectedVals[index] = yVals[0] + \
342 slope * (xVals[index] - xVals[0])
346 if options.breakExpectedIntLum:
347 breakExpectedIntLum = []
348 for chunk
in options.breakExpectedIntLum:
349 pieces = sepRE.split (chunk)
352 breakExpectedIntLum.append(
float(piece) )
354 raise RuntimeError(
"'%s' from '%s' is not a valid float" \
356 breakExpectedIntLum.sort()
360 for index, xPos
in enumerate (xVals):
361 if xPos > breakExpectedIntLum[breakIndex]:
362 boundaries.append (index)
363 while breakIndex < len (breakExpectedIntLum):
365 if breakIndex >= len (breakExpectedIntLum):
371 if xPos <= breakExpectedIntLum[breakIndex]:
377 raise RuntimeError(
"No values of 'breakExpectedIntLum' are in current range.")
380 boundaries.insert (0, 0)
383 if boundaries[-1] != len (xVals) - 1:
384 boundaries.append( len (xVals) - 1 )
385 rangeList =
list(zip (boundaries, boundaries[1:]))
386 for thisRange
in rangeList:
389 slope = (yVals[upper] - yVals[lower]) / \
390 (xVals[upper] - xVals[lower])
394 for index
in range (lower, upper + 1):
395 newExpected = yVals[lower] + \
396 slope * (xVals[index] - xVals[lower])
397 pairList.append( (xVals[index], newExpected) )
398 expectedVals[index] = newExpected
399 expectedChunks.append (pairList)
403 elif 'instLum' == options.edfMode
or 'instIntLum' == options.edfMode:
405 if not lumiCont.xingInfo:
406 raise RuntimeError(
"Luminosity Xing information missing.")
407 for key, eventList
in sorted( six.iteritems(eventsDict) ):
410 instLum = lumi.aveInstLum
411 fracAXIL = lumi.fracAXILrecorded
412 totalAXIL = lumi.totalAXILrecorded
414 raise RuntimeError(
"key %s not found in lumi information" \
416 for event
in eventList:
417 eventTupList.append( (instLum, fracAXIL, totalAXIL, key,
418 event[0], event[1], ) )
420 for eventTup
in eventTupList:
421 weight += eventTup[5]
422 factor = weight / totalWeight
423 if 'instLum' == options.edfMode:
424 xVals.append (eventTup[0])
426 xVals.append (eventTup[2])
427 yVals.append (factor)
428 expectedVals.append (eventTup[1])
429 predVals.append (eventTup[1] * options.pred)
431 raise RuntimeError(
"It looks like Charles screwed up if you are seeing this.")
434 step = int (math.sqrt(size) / 2 + 1)
435 if options.printValues:
436 for index
in range (size):
437 print "%8f %8f %8f" % (xVals[index], yVals[index], expectedVals[index]),
439 denom = xVals[index] - xVals[index - step]
440 numer = yVals[index] - yVals[index - step]
442 print " %8f" % (numer / denom),
443 if 0 == index % step:
449 xArray = array.array (
'd', xVals)
450 yArray = array.array (
'd', yVals)
451 expected = array.array (
'd', expectedVals)
452 graph = ROOT.TGraph( size, xArray, yArray)
453 graph.SetTitle (options.title)
454 graph.SetMarkerStyle (20)
455 expectedGraph = ROOT.TGraph( size, xArray, expected)
456 expectedGraph.SetLineColor (ROOT.kRed)
457 expectedGraph.SetLineWidth (3)
458 if options.noDataPoints:
459 expectedGraph.SetLineStyle (2)
463 print "average weight per event:", weight / ( size - 1)
464 maxDistance = ROOT.TMath.KolmogorovTest (size, yArray,
467 prob = ROOT.TMath.KolmogorovProb( maxDistance * math.sqrt( size ) )
470 ROOT.gROOT.SetStyle(
'Plain')
471 ROOT.gROOT.SetBatch()
473 graph.GetXaxis().SetRangeUser (min (xVals), max (xVals))
474 minValue = min (
min(yVals),
min(expected))
476 minValue = min (minValue, min (predVals))
477 graph.GetYaxis().SetRangeUser (minValue,
478 max (
max(yVals),
max(expected),
max(predVals)))
479 graph.SetLineWidth (3)
480 if options.noDataPoints:
484 if 'instLum' == options.edfMode:
485 graph.GetXaxis().SetTitle (
"Average Xing Inst. Luminosity (1/ub/s)")
486 graph.GetXaxis().SetRangeUser (0., lumiCont.max(
'aveInstLum'))
488 if 'instIntLum' == options.edfMode:
489 graph.GetXaxis().SetTitle (
"Integrated Luminosity - Inst. Lum. Ordered (1/%s)" \
492 graph.GetXaxis().SetTitle (
"Integrated Luminosity (1/%s)" \
494 graph.GetYaxis().SetTitle (
"Fraction of Events Seen")
497 for index, chunk
in enumerate (expectedChunks):
498 expectedXarray = array.array (
'd', [item[0]
for item
in chunk])
499 expectedYarray = array.array (
'd', [item[1]
for item
in chunk])
500 expectedGraph = ROOT.TGraph( len(chunk),
503 expectedGraph.SetLineWidth (3)
504 if options.noDataPoints:
505 expectedGraph.SetLineStyle (2)
507 expectedGraph.SetLineColor (ROOT.kBlue)
509 expectedGraph.SetLineColor (ROOT.kRed)
510 expectedGraph.Draw(
"L")
511 expectedGraphs.append (expectedGraph)
512 exptectedGraph = expectedGraphs[0]
514 expectedGraph.Draw (
"L")
517 predArray = array.array (
'd', predVals)
518 green = ROOT.TGraph (size, xArray, predArray)
519 green.SetLineWidth (3)
520 green.SetLineColor (8)
522 legend = ROOT.TLegend(0.15, 0.65, 0.50, 0.85)
523 legend.SetFillStyle (0)
524 legend.SetLineColor(ROOT.kWhite)
525 observed =
'Observed' 527 observed +=
' (weighted)' 528 legend.AddEntry(graph, observed,
"PL")
529 if options.resetExpected:
530 legend.AddEntry(expectedGraph,
"Expected from partial yield",
"L")
532 legend.AddEntry(expectedGraph,
"Expected from total yield",
"L")
534 legend.AddEntry(green, options.predLabel,
"L")
535 legend.AddEntry(
"",
"D_{stat}=%.3f, N=%d" % (maxDistance, size),
"")
536 legend.AddEntry(
"",
"P_{KS}=%.3f" % prob,
"")
540 c1.Print (outputFile)
551 if __name__ ==
'__main__':
555 allowedEDF = [
'time',
'instLum',
'instIntLum']
556 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.')
557 plotGroup = optparse.OptionGroup (parser,
"Plot Options")
558 rangeGroup = optparse.OptionGroup (parser,
"Range Options")
559 inputGroup = optparse.OptionGroup (parser,
"Input Options")
560 modeGroup = optparse.OptionGroup (parser,
"Mode Options")
561 plotGroup.add_option (
'--title', dest=
'title', type=
'string',
562 default =
'Empirical Distribution Function',
563 help =
'title of plot (default %default)')
564 plotGroup.add_option (
'--predicted', dest=
'pred', type=
'float',
566 help =
'factor by which predicted curve is greater than observed')
567 plotGroup.add_option (
'--predLabel', dest=
'predLabel', type=
'string',
568 default =
'Predicted',
569 help =
'label of predicted in legend')
570 plotGroup.add_option (
'--noDataPoints', dest=
'noDataPoints',
572 help=
"Draw lines but no points for data")
573 rangeGroup.add_option (
'--minRun', dest=
'minRun', type=
'int', default=0,
574 help=
'Minimum run number to consider')
575 rangeGroup.add_option (
'--maxRun', dest=
'maxRun', type=
'int', default=0,
576 help=
'Maximum run number to consider')
577 rangeGroup.add_option (
'--minIntLum', dest=
'minIntLum', type=
'float', default=0,
578 help=
'Minimum integrated luminosity to consider')
579 rangeGroup.add_option (
'--maxIntLum', dest=
'maxIntLum', type=
'float', default=0,
580 help=
'Maximum integrated luminosity to consider')
581 rangeGroup.add_option (
'--resetExpected', dest=
'resetExpected',
583 help=
'Reset expected from total yield to highest point considered')
584 rangeGroup.add_option (
'--breakExpectedIntLum', dest=
'breakExpectedIntLum',
585 type=
'string', action=
'append', default=[],
586 help=
'Break expected curve into pieces at integrated luminosity boundaries')
587 inputGroup.add_option (
'--ignoreNoLumiEvents', dest=
'ignore',
589 help =
'Ignore (with a warning) events that do not have a lumi section')
590 inputGroup.add_option (
'--noWarnings', dest=
'noWarnings',
592 help =
'Do not print warnings about missing luminosity information')
593 inputGroup.add_option (
'--runEventLumi', dest=
'relOrder',
595 help =
'Parse event list assuming Run, Event #, Lumi# order')
596 inputGroup.add_option (
'--weights', dest=
'weights', action=
'store_true',
597 help =
'Read fourth column as a weight')
598 modeGroup.add_option (
'--print', dest=
'printValues', action=
'store_true',
599 help =
'Print X and Y values of EDF plot')
600 modeGroup.add_option (
'--runsWithLumis', dest=
'runsWithLumis',
601 type=
'string',action=
'append', default=[],
602 help=
'Print out run and lumi sections corresponding to integrated luminosities provided and then exits')
603 modeGroup.add_option (
'--edfMode', dest=
'edfMode', type=
'string',
605 help=
"EDF Mode %s (default '%%default')" % allowedEDF)
606 parser.add_option_group (plotGroup)
607 parser.add_option_group (rangeGroup)
608 parser.add_option_group (inputGroup)
609 parser.add_option_group (modeGroup)
610 (options, args) = parser.parse_args()
612 if options.edfMode
not in allowedEDF:
613 raise RuntimeError(
"edfMode (currently '%s') must be one of %s" \
614 % (options.edfMode, allowedEDF))
616 if len (args) != 3
and not (options.runsWithLumis
and len(args) >= 1):
617 raise RuntimeError(
"Must provide lumi.csv, events.txt, and output.png")
623 cont = LumiInfoCont (args[0], **options.__dict__)
624 cont.minRun = options.minRun
625 cont.maxRun = options.maxRun
626 cont.minIntLum = options.minIntLum
627 cont.maxIntLum = options.maxIntLum
633 if options.runsWithLumis:
635 for line
in options.runsWithLumis:
636 pieces = sepRE.split (line)
639 recLumValue = float (piece)
641 raise RuntimeError(
"'%s' in '%s' is not a float" % \
644 raise RuntimeError(
"You must provide positive values for -runsWithLumis ('%f' given)" % recLumValue)
645 recLumis.append (recLumValue)
647 raise RuntimeError(
"What did Charles do now?")
650 recLumValue = recLumis [recLumIndex]
653 for key, lumi
in six.iteritems(cont):
654 if prevRecLumi >= recLumValue
and recLumValue < lumi.totalRecorded:
656 print "%s contains total recorded lumi %f" % \
657 (key.__str__(), recLumValue)
660 if recLumIndex == len (recLumis):
663 recLumValue = recLumis [recLumIndex]
664 if prevRecLumi >= recLumValue
and recLumValue < lumi.totalRecorded:
666 print "%s contains total recorded lumi %f" % \
667 (key.__str__(), recLumValue)
672 prevRecLumi = lumi.totalRecorded
673 if recLumIndex < len (recLumis):
674 print "Theses lumis not found: %s" % recLumis[recLumIndex:]
680 if options.edfMode !=
'time' and not cont.xingInfo:
681 raise RuntimeError(
"'%s' does not have Xing info" % args[0])
682 eventsDict, totalWeight = loadEvents (args[1], cont, options)
683 makeEDFplot (cont, eventsDict, totalWeight, args[2], options)
def _integrateContainer(self)
def __init__(self, filename, kwargs)
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