9 ROOT.gROOT.SetBatch(
True)
10 ROOT.PyConfig.IgnoreCommandLineOptions =
True 30 ROOT.gROOT.SetStyle(
"Plain")
31 ROOT.gStyle.SetPadRightMargin(0.07)
32 ROOT.gStyle.SetPadLeftMargin(0.13)
33 ROOT.gStyle.SetTitleFont(font,
"XYZ")
34 ROOT.gStyle.SetTitleSize(titleSize,
"XYZ")
35 ROOT.gStyle.SetTitleOffset(1.2,
"Y")
37 ROOT.gStyle.SetLabelFont(font,
"XYZ")
38 ROOT.gStyle.SetLabelSize(labelSize,
"XYZ")
39 ROOT.gStyle.SetTextSize(labelSize)
40 ROOT.gStyle.SetStatFont(font)
41 ROOT.gStyle.SetStatFontSize(statSize)
43 ROOT.TGaxis.SetMaxDigits(4)
46 obj = tdirectory.Get(name)
49 print "Did not find {obj} from {dir}".
format(obj=name, dir=tdirectory.GetPath())
54 if hasattr(nameOrCreator,
"create"):
55 return nameOrCreator.create(tdirectory)
70 """Get TDirectory from TFile.""" 73 for pdf
in possibleDirs:
76 if subDir
is not None:
83 print "Did not find subdirectory '%s' from directory '%s' in file %s" % (subDir, pdf, tfile.GetName())
90 print "Did not find any of directories '%s' from file %s" % (
",".
join(possibleDirs), tfile.GetName())
97 values = collections.OrderedDict()
98 for i
in xrange(1, th1.GetNbinsX()+1):
99 binLabel = th1.GetXaxis().GetBinLabel(i)
100 if renameBin
is not None:
101 binLabel = renameBin(binLabel)
102 values[binLabel] = (th1.GetBinContent(i), th1.GetBinError(i))
108 backup = ROOT.gErrorIgnoreLevel
109 ROOT.gErrorIgnoreLevel = ROOT.kError
110 canvas = ROOT.TCanvas(name, name, width, height)
112 ROOT.gErrorIgnoreLevel = backup
118 divisionPoint = 1-1/ratioFactor
120 topMargin = pad.GetTopMargin()
121 bottomMargin = pad.GetBottomMargin()
122 divisionPoint += (1-divisionPoint)*bottomMargin
123 divisionPointForPad1 = 1-( (1-divisionPoint) / (1-0.02) )
128 ylow = divisionPointForPad1
131 pad1.SetPad(xlow, ylow, xup, yup)
132 pad1.SetFillStyle(4000)
133 pad1.SetBottomMargin(0.02)
139 pad2.SetPad(xlow, ylow, xup, yup)
140 pad2.SetFillStyle(4000)
141 pad2.SetTopMargin(0.0)
142 pad2.SetBottomMargin(bottomMargin/(ratioFactor*divisionPoint))
145 """Calculate the ratios for a list of histograms""" 147 def _divideOrZero(numerator, denominator):
150 return numerator/denominator
153 if a == 0.
and b == 0.:
157 def findBins(wrap, bins_xvalues):
159 currBin = wrap.begin()
161 while i < len(bins_xvalues)
and currBin < wrap.end():
162 (xcenter, xlow, xhigh) = bins_xvalues[i]
163 xlowEdge = xcenter-xlow
164 xupEdge = xcenter+xhigh
166 (curr_center, curr_low, curr_high) = wrap.xvalues(currBin)
167 curr_lowEdge = curr_center-curr_low
168 curr_upEdge = curr_center+curr_high
170 if equal(xlowEdge, curr_lowEdge)
and equal(xupEdge, curr_upEdge):
174 elif curr_upEdge <= xlowEdge:
176 elif curr_lowEdge >= xupEdge:
183 if len(ret) != len(bins_xvalues):
184 ret.extend([
None]*( len(bins_xvalues) - len(ret) ))
190 def __init__(self, th1, uncertainty):
192 self._uncertainty = uncertainty
194 xaxis = th1.GetXaxis()
195 xaxis_arr = xaxis.GetXbins()
196 if xaxis_arr.GetSize() > 0:
197 lst = [xaxis_arr[i]
for i
in xrange(0, xaxis_arr.GetSize())]
198 arr = array.array(
"d", lst)
199 self._ratio = ROOT.TH1F(
"foo",
"foo", xaxis.GetNbins(), arr)
201 self._ratio = ROOT.TH1F(
"foo",
"foo", xaxis.GetNbins(), xaxis.GetXmin(), xaxis.GetXmax())
203 self._ratio.SetStats(0)
204 self._ratio.SetLineColor(ROOT.kBlack)
205 self._ratio.SetLineWidth(1)
206 def draw(self, style=None):
209 if self._uncertainty:
213 self._ratio.Draw(
"same "+st)
217 return self._th1.GetNbinsX()+1
218 def xvalues(self, bin):
219 xval = self._th1.GetBinCenter(bin)
220 xlow = xval-self._th1.GetXaxis().GetBinLowEdge(bin)
221 xhigh = self._th1.GetXaxis().GetBinUpEdge(bin)-xval
222 return (xval, xlow, xhigh)
223 def yvalues(self, bin):
224 yval = self._th1.GetBinContent(bin)
225 yerr = self._th1.GetBinError(bin)
226 return (yval, yerr, yerr)
228 return self._th1.GetBinContent(bin)
229 def divide(self, bin, scale):
230 self._ratio.SetBinContent(bin, _divideOrZero(self._th1.GetBinContent(bin), scale))
231 self._ratio.SetBinError(bin, _divideOrZero(self._th1.GetBinError(bin), scale))
238 def __init__(self, gr, uncertainty):
240 self._uncertainty = uncertainty
247 def draw(self, style=None):
248 if self._ratio
is None:
252 if self._uncertainty:
256 self._ratio.Draw(
"same "+st)
260 return self._gr.GetN()
261 def xvalues(self, bin):
262 return (self._gr.GetX()[bin], self._gr.GetErrorXlow(bin), self._gr.GetErrorXhigh(bin))
263 def yvalues(self, bin):
264 return (self._gr.GetY()[bin], self._gr.GetErrorYlow(bin), self._gr.GetErrorYhigh(bin))
266 return self._gr.GetY()[bin]
267 def divide(self, bin, scale):
272 if bin >= self._gr.GetN():
275 xvals = self.xvalues(bin)
278 self._xvalues.append(xval)
279 self._xerrslow.append(xvals[1])
280 self._xerrshigh.append(xvals[2])
281 yvals = self.yvalues(bin)
282 self._yvalues.append(yvals[0] / scale)
283 if self._uncertainty:
284 self._yerrslow.append(yvals[1] / scale)
285 self._yerrshigh.append(yvals[2] / scale)
287 self._yerrslow.append(0)
288 self._yerrshigh.append(0)
290 if len(self._xvalues) == 0:
293 self._ratio = ROOT.TGraphAsymmErrors(len(self._xvalues), array.array(
"d", self._xvalues), array.array(
"d", self._yvalues),
294 array.array(
"d", self._xerrslow), array.array(
"d", self._xerrshigh),
295 array.array(
"d", self._yerrslow), array.array(
"d", self._yerrshigh))
299 class WrapTGraph2D(WrapTGraph):
300 def __init__(self, gr, uncertainty):
301 WrapTGraph.__init__(self, gr, uncertainty)
302 def xvalues(self, bin):
303 return (self._gr.GetX()[bin], self._gr.GetErrorX(bin), self._gr.GetErrorX(bin))
304 def yvalues(self, bin):
305 return (self._gr.GetY()[bin], self._gr.GetErrorY(bin), self._gr.GetErrorY(bin))
308 if isinstance(o, ROOT.TH1):
309 return WrapTH1(o, ratioUncertainty)
310 elif isinstance(o, ROOT.TGraph):
311 return WrapTGraph(o, ratioUncertainty)
312 elif isinstance(o, ROOT.TGraph2D):
313 return WrapTGraph2D(o, ratioUncertainty)
315 wrappers = [
wrap(h)
for h
in histos]
319 ref_bins = [ref.xvalues(b)
for b
in xrange(ref.begin(), ref.end())]
321 wrappers_bins.append(findBins(w, ref_bins))
323 for i, bin
in enumerate(xrange(ref.begin(), ref.end())):
324 (scale, ylow, yhigh) = ref.yvalues(bin)
325 for w, bins
in zip(wrappers, wrappers_bins):
328 w.divide(bins[i], scale)
337 if isinstance(obj, ROOT.TH1):
338 xaxis = obj.GetXaxis()
339 if limitToNonZeroContent:
340 for i
in xrange(1, obj.GetNbinsX()+1):
341 if obj.GetBinContent(i) != 0:
342 return xaxis.GetBinLowEdge(i)
346 return xaxis.GetBinLowEdge(xaxis.GetFirst())
347 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
348 m =
min([obj.GetX()[i]
for i
in xrange(0, obj.GetN())])
349 return m*0.9
if m > 0
else m*1.1
353 if isinstance(obj, ROOT.TH1):
354 xaxis = obj.GetXaxis()
355 if limitToNonZeroContent:
356 for i
in xrange(obj.GetNbinsX(), 0, -1):
357 if obj.GetBinContent(i) != 0:
358 return xaxis.GetBinUpEdge(i)
362 return xaxis.GetBinUpEdge(xaxis.GetLast())
363 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
364 m =
max([obj.GetX()[i]
for i
in xrange(0, obj.GetN())])
365 return m*1.1
if m > 0
else m*0.9
369 if isinstance(obj, ROOT.TH2):
370 yaxis = obj.GetYaxis()
371 return yaxis.GetBinLowEdge(yaxis.GetFirst())
372 elif isinstance(obj, ROOT.TH1):
373 return obj.GetMinimum()
374 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
375 m =
min([obj.GetY()[i]
for i
in xrange(0, obj.GetN())])
376 return m*0.9
if m > 0
else m*1.1
380 if isinstance(obj, ROOT.TH2):
381 yaxis = obj.GetYaxis()
382 return yaxis.GetBinUpEdge(yaxis.GetLast())
383 elif isinstance(obj, ROOT.TH1):
384 return obj.GetMaximum()
385 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
386 m =
max([obj.GetY()[i]
for i
in xrange(0, obj.GetN())])
387 return m*1.1
if m > 0
else m*0.9
391 return max([th1.GetBinContent(i)+th1.GetBinError(i)
for i
in xrange(1, th1.GetNbinsX()+1)])
394 yvals =
filter(
lambda n: n>0, [th1.GetBinContent(i)
for i
in xrange(1, th1.GetNbinsX()+1)])
397 return th1.GetMinimum()
402 ind_min = len(yvals)-1 -
int(len(yvals)*0.95)
403 min_val = yvals[ind_min]
404 for i
in xrange(0, ind_min):
405 if yvals[i] > 0.1*min_val:
411 inRange =
lambda x:
True 412 inRange2 =
lambda xmin,xmax:
True 414 inRange =
lambda x: coverageRange[0] <= x <= coverageRange[1]
415 inRange2 =
lambda xmin,xmax: coverageRange[0] <= xmin
and xmax <= coverageRange[1]
417 if isinstance(obj, ROOT.TH1):
418 yvals = [obj.GetBinContent(i)
for i
in xrange(1, obj.GetNbinsX()+1)
if inRange2(obj.GetXaxis().GetBinLowEdge(i), obj.GetXaxis().GetBinUpEdge(i))]
419 yvals =
filter(
lambda x: x != 0, yvals)
420 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
421 yvals = [obj.GetY()[i]
for i
in xrange(0, obj.GetN())
if inRange(obj.GetX()[i])]
427 return (yvals[0], yvals[0])
429 return (yvals[0], yvals[1])
432 nvals =
int(len(yvals)*coverage)
435 if len(yvals) % 2 == 0:
437 return ( yvals[half-1], yvals[half] )
439 middle = len(yvals)/2
440 return ( yvals[middle-1], yvals[middle+1] )
441 ind_min = (len(yvals)-nvals)/2
442 ind_max = len(yvals)-1 - ind_min
444 return (yvals[ind_min], yvals[ind_max])
446 def _findBounds(th1s, ylog, xmin=None, xmax=None, ymin=None, ymax=None):
447 """Find x-y axis boundaries encompassing a list of TH1s if the bounds are not given in arguments. 451 ylog -- Boolean indicating if y axis is in log scale or not (affects the automatic ymax) 454 xmin -- Minimum x value; if None, take the minimum of TH1s 455 xmax -- Maximum x value; if None, take the maximum of TH1s 456 ymin -- Minimum y value; if None, take the minimum of TH1s 457 ymax -- Maximum y value; if None, take the maximum of TH1s 462 if xmin
is None or xmax
is None or isinstance(xmin, list)
or isinstance(max, list):
466 xmins.append(
_getXmin(th1, limitToNonZeroContent=isinstance(xmin, list)))
467 xmaxs.append(
_getXmax(th1, limitToNonZeroContent=isinstance(xmax, list)))
470 xmins =
filter(
lambda h: h
is not None, xmins)
471 xmaxs =
filter(
lambda h: h
is not None, xmaxs)
475 elif isinstance(xmin, list):
479 print "Histogram is zero, using the smallest given value for xmin from",
str(xmin)
482 xmins_below =
filter(
lambda x: x<=xm, xmin)
483 if len(xmins_below) == 0:
487 print "Histogram minimum x %f is below all given xmin values %s, using the smallest one" % (xm,
str(xmin))
489 xmin =
max(xmins_below)
493 elif isinstance(xmax, list):
497 print "Histogram is zero, using the smallest given value for xmax from",
str(xmin)
500 xmaxs_above =
filter(
lambda x: x>xm, xmax)
501 if len(xmaxs_above) == 0:
505 print "Histogram maximum x %f is above all given xmax values %s, using the maximum one" % (xm,
str(xmax))
507 xmax =
min(xmaxs_above)
510 th1.GetXaxis().SetRangeUser(xmin, xmax)
512 return (xmin, ymin, xmax, ymax)
514 def _findBoundsY(th1s, ylog, ymin=None, ymax=None, coverage=None, coverageRange=None):
515 """Find y axis boundaries encompassing a list of TH1s if the bounds are not given in arguments. 519 ylog -- Boolean indicating if y axis is in log scale or not (affects the automatic ymax) 522 ymin -- Minimum y value; if None, take the minimum of TH1s 523 ymax -- Maximum y value; if None, take the maximum of TH1s 524 coverage -- If set, use only values within the 'coverage' part around the median are used for min/max (useful for ratio) 525 coverageRange -- If coverage and this are set, use only the x axis specified by an (xmin,xmax) pair for the coverage 527 if coverage
is not None:
531 y_scale_max =
lambda y: y
532 y_scale_min =
lambda y: y
535 y_scale_max =
lambda y: y*1.5
537 y_scale_max =
lambda y: y*1.05
538 y_scale_min =
lambda y: y*0.9
540 if ymin
is None or ymax
is None or isinstance(ymin, list)
or isinstance(ymax, list):
544 if coverage
is not None:
547 if ylog
and isinstance(ymin, list):
559 elif isinstance(ymin, list):
560 ym_unscaled =
min(ymins)
561 ym = y_scale_min(ym_unscaled)
562 ymins_below =
filter(
lambda y: y<=ym, ymin)
563 if len(ymins_below) == 0:
565 if ym_unscaled < ymin:
567 print "Histogram minimum y %f is below all given ymin values %s, using the smallest one" % (ym,
str(ymin))
569 ymin =
max(ymins_below)
574 ymax = y_scale_max(
max(ymaxs+[ymin]))
575 elif isinstance(ymax, list):
576 ym_unscaled =
max(ymaxs)
577 ym = y_scale_max(ym_unscaled)
578 ymaxs_above =
filter(
lambda y: y>ym, ymax)
579 if len(ymaxs_above) == 0:
581 if ym_unscaled > ymax:
583 print "Histogram maximum y %f is above all given ymax values %s, using the maximum one" % (ym_unscaled,
str(ymax))
585 ymax =
min(ymaxs_above)
588 th1.GetYaxis().SetRangeUser(ymin, ymax)
593 """Class for subtracting two histograms""" 598 name -- String for name of the resulting histogram (A-B) 599 nameA -- String for A histogram 600 nameB -- String for B histogram 603 title -- String for a title of the resulting histogram (default "") 605 Uncertainties are calculated with the assumption that B is a 606 subset of A, and the histograms contain event counts. 614 """String representation, returns the name""" 618 """Create and return the fake+duplicate histogram from a TDirectory""" 622 if not histoA
or not histoB:
625 ret = histoA.Clone(self.
_name)
631 ret.SetCanExtend(
False)
633 for i
in xrange(0, histoA.GetNbinsX()+2):
634 val = histoA.GetBinContent(i)-histoB.GetBinContent(i)
635 ret.SetBinContent(i, val)
636 ret.SetBinError(i, math.sqrt(val))
641 """Class to transform bin contents in an arbitrary way.""" 646 name -- String for name of the resulting histogram 647 histo -- String for a source histogram (needs to be cumulative) 648 func -- Function to operate on the bin content 656 """String representation, returns the name""" 660 """Create and return the transformed histogram from a TDirectory""" 665 ret = histo.Clone(self.
_name)
671 ret.SetCanExtend(
False)
673 for i
in xrange(0, histo.GetNbinsX()+2):
674 ret.SetBinContent(i, self.
_func(histo.GetBinContent(i)))
678 """Class to calculate the fake+duplicate rate""" 679 def __init__(self, name, assoc, dup, reco, title=""):
683 name -- String for the name of the resulting efficiency histogram 684 assoc -- String for the name of the "associated" histogram 685 dup -- String for the name of the "duplicates" histogram 686 reco -- String for the name of the "reco" (denominator) histogram 689 title -- String for a title of the resulting histogram (default "") 691 The result is calculated as 1 - (assoc - dup) / reco 700 """String representation, returns the name""" 704 """Create and return the fake+duplicate histogram from a TDirectory""" 711 if not hassoc
or not hdup
or not hreco:
714 hfakedup = hreco.Clone(self.
_name)
715 hfakedup.SetTitle(self.
_title)
717 for i
in xrange(1, hassoc.GetNbinsX()+1):
718 numerVal = hassoc.GetBinContent(i) - hdup.GetBinContent(i)
719 denomVal = hreco.GetBinContent(i)
721 fakedupVal = (1 - numerVal / denomVal)
if denomVal != 0.0
else 0.0
722 errVal = math.sqrt(fakedupVal*(1-fakedupVal)/denomVal)
if (denomVal != 0.0
and fakedupVal <= 1)
else 0.0
724 hfakedup.SetBinContent(i, fakedupVal)
725 hfakedup.SetBinError(i, errVal)
730 """Class for making a cut efficiency histograms. 740 name -- String for name of the resulting histogram 741 histo -- String for a source histogram (needs to be cumulative) 748 """String representation, returns the name""" 752 """Create and return the cut efficiency histogram from a TDirectory""" 758 ascending = histo.GetBinContent(0) < histo.GetBinContent(histo.GetNbinsX())
760 n_tot = histo.GetBinContent(histo.GetNbinsX())
762 n_tot = histo.GetBinContent(0)
767 ret = histo.Clone(self.
_name)
771 for i
in xrange(1, histo.GetNbinsX()+1):
772 n = histo.GetBinContent(i)
774 errVal = math.sqrt(val*(1-val)/n_tot)
775 ret.SetBinContent(i, val)
776 ret.SetBinError(i, errVal)
780 """Class to create a histogram by aggregating bins of another histogram to a bin of the resulting histogram.""" 781 def __init__(self, name, histoName, mapping, normalizeTo=None, scale=None, renameBin=None, ignoreMissingBins=False, minExistingBins=None, originalOrder=False):
785 name -- String for the name of the resulting histogram 786 histoName -- String for the name of the source histogram 787 mapping -- Dictionary for mapping the bins (see below) 790 normalizeTo -- Optional string of a bin label in the source histogram. If given, all bins of the resulting histogram are divided by the value of this bin. 791 scale -- Optional number for scaling the histogram (passed to ROOT.TH1.Scale()) 792 renameBin -- Optional function (string -> string) to rename the bins of the input histogram 793 originalOrder -- Boolean for using the order of bins in the histogram (default False) 795 Mapping structure (mapping): 797 Dictionary (you probably want to use collections.OrderedDict) 798 should be a mapping from the destination bin label to a list 799 of source bin labels ("dst -> [src]"). 812 """String representation, returns the name""" 816 """Create and return the histogram from a TDirectory""" 822 binValues = [
None]*len(self.
_mapping)
828 for i, (key, labels)
in enumerate(self._mapping.iteritems()):
834 sumTime += values[l][0]
835 sumErrorSq += values[l][1]**2
841 binValues[i] = (sumTime, math.sqrt(sumErrorSq))
844 ivalue = len(values)+1
850 ivalue = values.keys().
index(lab)
852 binIndexOrder.append( (ivalue, i) )
855 binIndexOrder.sort(key=
lambda t: t[0])
858 for i
in xrange(0, len(binValues)):
859 fromIndex = binIndexOrder[i][1]
860 tmpVal.append(binValues[fromIndex])
861 tmpLab.append(binLabels[fromIndex])
869 for i, val
in enumerate(binValues):
872 binValues =
filter(
lambda v: v
is not None, binValues)
873 binLabels =
filter(
lambda v: v
is not None, binLabels)
874 if len(binValues) == 0:
877 result = ROOT.TH1F(self.
_name, self.
_name, len(binValues), 0, len(binValues))
878 for i, (value, label)
in enumerate(
zip(binValues, binLabels)):
879 if value
is not None:
880 result.SetBinContent(i+1, value[0])
881 result.SetBinError(i+1, value[1])
882 result.GetXaxis().SetBinLabel(i+1, label)
887 print "Trying to normalize {name} to {binlabel}, which does not exist".
format(name=self.
_name, binlabel=self.
_normalizeTo)
889 value = th1.GetBinContent(bin)
891 result.Scale(1/value)
893 if self.
_scale is not None:
899 """Class to create a histogram by aggregaging integrals of another histoggrams.""" 900 def __init__(self, name, mapping, normalizeTo=None):
904 name -- String for the name of the resulting histogram 905 mapping -- Dictionary for mapping the bin label to a histogram name 908 normalizeTo -- Optional string for a histogram. If given, all bins of the resulting histograqm are divided by the integral of this histogram. 915 """String representation, returns the name""" 919 """Create and return the histogram from a TDirectory""" 921 for key, histoName
in self._mapping.iteritems():
925 result.append( (key, th1.Integral(0, th1.GetNbinsX()+1)) )
929 res = ROOT.TH1F(self.
_name, self.
_name, len(result), 0, len(result))
931 for i, (name, count)
in enumerate(result):
932 res.SetBinContent(i+1, count)
933 res.GetXaxis().SetBinLabel(i+1, name)
939 scale = th1.Integral(0, th1.GetNbinsX()+1)
945 """Class to construct a ROC curve (e.g. efficiency vs. fake rate) from two histograms""" 946 def __init__(self, name, xhistoName, yhistoName, zaxis=False):
950 name -- String for the name of the resulting histogram 951 xhistoName -- String for the name of the x-axis histogram (or another "creator" object) 952 yhistoName -- String for the name of the y-axis histogram (or another "creator" object) 955 zaxis -- If set to True (default False), create a TGraph2D with z axis showing the cut value (recommended drawStyle 'pcolz') 963 """String representation, returns the name""" 967 """Create and return the histogram from a TDirectory""" 970 if xhisto
is None or yhisto
is None:
981 for i
in xrange(1, xhisto.GetNbinsX()+1):
982 x.append(xhisto.GetBinContent(i))
983 xerrup.append(xhisto.GetBinError(i))
984 xerrdown.append(xhisto.GetBinError(i))
986 y.append(yhisto.GetBinContent(i))
987 yerrup.append(yhisto.GetBinError(i))
988 yerrdown.append(yhisto.GetBinError(i))
990 z.append(xhisto.GetXaxis().GetBinUpEdge(i))
993 if x.count(0.0) == len(x)
or y.count(0.0) == len(y):
996 arr =
lambda v: array.array(
"d", v)
999 gr = ROOT.TGraph2D(len(x), arr(x), arr(y), arr(z))
1001 gr = ROOT.TGraphAsymmErrors(len(x), arr(x), arr(y), arr(xerrdown), arr(xerrup), arr(yerrdown), arr(yerrup))
1007 _plotStylesColor = [4, 2, ROOT.kBlack, ROOT.kOrange+7, ROOT.kMagenta-3]
1008 _plotStylesMarker = [21, 20, 22, 34, 33]
1010 def _drawFrame(pad, bounds, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, suffix=""):
1011 """Function to draw a frame 1014 pad -- TPad to where the frame is drawn 1015 bounds -- List or 4-tuple for (xmin, ymin, xmax, ymax) 1018 xbinlabels -- Optional list of strings for x axis bin labels 1019 xbinlabelsize -- Optional number for the x axis bin label size 1020 xbinlabeloption -- Optional string for the x axis bin options (passed to ROOT.TH1.LabelsOption()) 1021 suffix -- Optional string for a postfix of the frame name 1023 if xbinlabels
is None:
1024 frame = pad.DrawFrame(*bounds)
1027 nbins = len(xbinlabels)
1028 frame = ROOT.TH1F(
"hframe"+suffix,
"", nbins, bounds[0], bounds[2])
1029 frame.SetBit(ROOT.TH1.kNoStats)
1030 frame.SetBit(ROOT.kCanDelete)
1031 frame.SetMinimum(bounds[1])
1032 frame.SetMaximum(bounds[3])
1033 frame.GetYaxis().SetLimits(bounds[1], bounds[3])
1036 xaxis = frame.GetXaxis()
1037 for i
in xrange(nbins):
1038 xaxis.SetBinLabel(i+1, xbinlabels[i])
1039 if xbinlabelsize
is not None:
1040 xaxis.SetLabelSize(xbinlabelsize)
1041 if xbinlabeloption
is not None:
1042 frame.LabelsOption(xbinlabeloption)
1047 """Class for creating and managing a frame for a simple, one-pad plot""" 1048 def __init__(self, pad, bounds, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None):
1061 self._frame.GetYaxis().SetTitleOffset(self._frame.GetYaxis().GetTitleOffset()*yoffsetFactor)
1062 self._frame.GetXaxis().SetTitleOffset(self._frame.GetXaxis().GetTitleOffset()*xoffsetFactor)
1066 self._pad.SetLogx(log)
1069 self._pad.SetLogy(log)
1072 self._pad.SetGridx(grid)
1075 self._pad.SetGridy(grid)
1078 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1081 self._frame.Draw(
"")
1084 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1087 self._frame.Draw(
"")
1090 self._frame.SetTitle(title)
1093 self._frame.GetXaxis().SetTitle(title)
1096 self._frame.GetXaxis().SetTitleSize(size)
1099 self._frame.GetXaxis().SetTitleOffset(offset)
1102 self._frame.GetXaxis().SetLabelSize(size)
1105 self._frame.GetYaxis().SetTitle(title)
1108 self._frame.GetYaxis().SetTitleSize(size)
1111 self._frame.GetYaxis().SetTitleOffset(offset)
1114 self._pad.RedrawAxis()
1117 """Class for creating and managing a frame for a ratio plot with two subpads""" 1118 def __init__(self, pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None):
1121 if xbinlabels
is not None:
1128 self._frame.GetXaxis().SetLabelSize(0)
1129 self._frame.GetXaxis().SetTitleSize(0)
1131 yoffsetFactor = ratioFactor
1132 divisionPoint = 1-1/ratioFactor
1133 xoffsetFactor = 1/divisionPoint
1136 xoffsetFactor *= 0.6
1139 xoffsetFactor *= 1.5
1142 xoffsetFactor *= 2.3
1147 self._frame.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
1148 self._frameRatio.GetYaxis().SetLabelSize(
int(self._frameRatio.GetYaxis().GetLabelSize()*0.8))
1149 self._frameRatio.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
1150 self._frameRatio.GetXaxis().SetTitleOffset(self._frameRatio.GetXaxis().GetTitleOffset()*xoffsetFactor)
1152 self._frameRatio.GetYaxis().SetNdivisions(4, 5, 0)
1154 self._frameRatio.GetYaxis().SetTitle(ratioYTitle)
1157 self._pad.SetLogx(log)
1158 self._padRatio.SetLogx(log)
1161 self._pad.SetLogy(log)
1164 self._pad.SetGridx(grid)
1165 self._padRatio.SetGridx(grid)
1168 self._pad.SetGridy(grid)
1169 self._padRatio.SetGridy(grid)
1172 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1173 self._padRatio.SetLeftMargin(self._padRatio.GetLeftMargin()+adjust)
1176 self._frame.Draw(
"")
1178 self._frameRatio.Draw(
"")
1181 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1182 self._padRatio.SetRightMargin(self._padRatio.GetRightMargin()+adjust)
1185 self._frame.Draw(
"")
1187 self._frameRatio.Draw(
"")
1190 self._frame.SetTitle(title)
1193 self._frameRatio.GetXaxis().SetTitle(title)
1196 self._frameRatio.GetXaxis().SetTitleSize(size)
1199 self._frameRatio.GetXaxis().SetTitleOffset(offset)
1202 self._frameRatio.GetXaxis().SetLabelSize(size)
1205 self._frame.GetYaxis().SetTitle(title)
1208 self._frameRatio.GetYaxis().SetTitle(title)
1211 self._frame.GetYaxis().SetTitleSize(size)
1212 self._frameRatio.GetYaxis().SetTitleSize(size)
1215 self._frame.GetYaxis().SetTitleOffset(offset)
1216 self._frameRatio.GetYaxis().SetTitleOffset(offset)
1219 self._padRatio.RedrawAxis()
1220 self._pad.RedrawAxis()
1222 self._parentPad.cd()
1229 self.
_coverPad = ROOT.TPad(
"coverpad",
"coverpad", xmin, ymin, xmax, ymax)
1230 self._coverPad.SetBorderMode(0)
1231 self._coverPad.Draw()
1237 """Class for creating and managing a frame for a plot from TGraph2D""" 1238 def __init__(self, pad, bounds, histos, ratioOrig, ratioFactor):
1241 self.
_pad = pad.cd(1)
1245 (xlow, ylow, width, height) = (self._pad.GetXlowNDC(), self._pad.GetYlowNDC(), self._pad.GetWNDC(), self._pad.GetHNDC())
1249 bottomMargin = self._pad.GetBottomMargin()
1250 bottomMarginNew = ROOT.gStyle.GetPadBottomMargin()
1252 ylowNew = yup - (1-bottomMargin)/(1-bottomMarginNew) * (yup-ylow)
1253 topMarginNew = self._pad.GetTopMargin() * (yup-ylow)/(yup-ylowNew)
1255 self._pad.SetPad(xlow, ylowNew, xup, yup)
1256 self._pad.SetTopMargin(topMarginNew)
1257 self._pad.SetBottomMargin(bottomMarginNew)
1260 self._view.SetRange(bounds[0], bounds[1], 0, bounds[2], bounds[3], 20)
1262 self._view.ShowAxis()
1282 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1286 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1314 self._firstHisto.GetZaxis().SetTitle(title)
1317 self._firstHisto.GetZaxis().SetTitleOffset(offset)
1321 ROOT.TAxis3D.ToggleRulers()
1322 ROOT.TAxis3D.ToggleRulers()
1323 axis = ROOT.TAxis3D.GetPadAxis()
1324 axis.SetLabelColor(ROOT.kBlack);
1325 axis.SetAxisColor(ROOT.kBlack);
1330 if hasattr(self,
"_xtitle"):
1331 axis.GetXaxis().SetTitle(self.
_xtitle)
1332 if hasattr(self,
"_xtitlesize"):
1334 if hasattr(self,
"_xlabelsize"):
1335 axis.GetXaxis().SetLabelSize(self._labelsize)
1336 if hasattr(self,
"_ytitle"):
1337 axis.GetYaxis().SetTitle(self.
_ytitle)
1338 if hasattr(self,
"_ytitlesize"):
1340 if hasattr(self,
"_ytitleoffset"):
1344 """Abstraction on top of TLatex""" 1345 def __init__(self, x, y, text, size=None, bold=True, align="left", color=ROOT.kBlack, font=None):
1349 x -- X coordinate of the text (in NDC) 1350 y -- Y coordinate of the text (in NDC) 1351 text -- String to draw 1352 size -- Size of text (None for the default value, taken from gStyle) 1353 bold -- Should the text be bold? 1354 align -- Alignment of text (left, center, right) 1355 color -- Color of the text 1356 font -- Specify font explicitly 1365 self._l.SetTextFont(self._l.GetTextFont()-20)
1366 if font
is not None:
1367 self._l.SetTextFont(font)
1368 if size
is not None:
1369 self._l.SetTextSize(size)
1370 if isinstance(align, basestring):
1371 if align.lower() ==
"left":
1372 self._l.SetTextAlign(11)
1373 elif align.lower() ==
"center":
1374 self._l.SetTextAlign(21)
1375 elif align.lower() ==
"right":
1376 self._l.SetTextAlign(31)
1378 raise Exception(
"Error: Invalid option '%s' for text alignment! Options are: 'left', 'center', 'right'."%align)
1380 self._l.SetTextAlign(align)
1381 self._l.SetTextColor(color)
1384 """Draw the text to the current TPad. 1387 options -- For interface compatibility, ignored 1389 Provides interface compatible with ROOT's drawable objects. 1391 self._l.DrawLatex(self.
_x, self.
_y, self.
_text)
1395 """Class for drawing text and a background box.""" 1396 def __init__(self, xmin, ymin, xmax, ymax, lineheight=0.04, fillColor=ROOT.kWhite, transparent=True, **kwargs):
1400 xmin -- X min coordinate of the box (NDC) 1401 ymin -- Y min coordinate of the box (NDC) (if None, deduced automatically) 1402 xmax -- X max coordinate of the box (NDC) 1403 ymax -- Y max coordinate of the box (NDC) 1404 lineheight -- Line height 1405 fillColor -- Fill color of the box 1406 transparent -- Should the box be transparent? (in practive the TPave is not created) 1408 Keyword arguments are forwarded to constructor of PlotText 1420 self._textArgs.update(kwargs)
1425 """Add text to current position""" 1432 def move(self, dx=0, dy=0, dw=0, dh=0):
1433 """Move the box and the contained text objects 1436 dx -- Movement in x (positive is to right) 1437 dy -- Movement in y (positive is to up) 1438 dw -- Increment of width (negative to decrease width) 1439 dh -- Increment of height (negative to decrease height) 1441 dx and dy affect to both box and text objects, dw and dh 1442 affect the box only. 1446 if self.
_ymin is not None:
1451 if self.
_ymin is not None:
1459 """Draw the box and the text to the current TPad. 1462 options -- Forwarded to ROOT.TPave.Draw(), and the Draw() of the contained objects 1467 ymin = self.currenty - 0.01
1468 self.
_pave = ROOT.TPave(self.xmin, self.ymin, self.xmax, self.ymax, 0,
"NDC")
1469 self._pave.SetFillColor(self.fillColor)
1470 self._pave.Draw(options)
1476 if hasattr(src,
"GetLineColor")
and hasattr(dst,
"SetLineColor"):
1477 properties.extend([
"LineColor",
"LineStyle",
"LineWidth"])
1478 if hasattr(src,
"GetFillColor")
and hasattr(dst,
"SetFillColor"):
1479 properties.extend([
"FillColor",
"FillStyle"])
1480 if hasattr(src,
"GetMarkerColor")
and hasattr(dst,
"SetMarkerColor"):
1481 properties.extend([
"MarkerColor",
"MarkerSize",
"MarkerStyle"])
1483 for prop
in properties:
1484 getattr(dst,
"Set"+prop)(getattr(src,
"Get"+prop)())
1487 """Represents one plot, comparing one or more histograms.""" 1492 name -- String for name of the plot, or Efficiency object 1495 fallback -- Dictionary for specifying fallback (default None) 1496 outname -- String for an output name of the plot (default None for the same as 'name') 1497 title -- String for a title of the plot (default None) 1498 xtitle -- String for x axis title (default None) 1499 xtitlesize -- Float for x axis title size (default None) 1500 xtitleoffset -- Float for x axis title offset (default None) 1501 xlabelsize -- Float for x axis label size (default None) 1502 ytitle -- String for y axis title (default None) 1503 ytitlesize -- Float for y axis title size (default None) 1504 ytitleoffset -- Float for y axis title offset (default None) 1505 ztitle -- String for z axis title (default None) 1506 ztitleoffset -- Float for z axis title offset (default None) 1507 xmin -- Float for x axis minimum (default None, i.e. automatic) 1508 xmax -- Float for x axis maximum (default None, i.e. automatic) 1509 ymin -- Float for y axis minimum (default 0) 1510 ymax -- Float for y axis maximum (default None, i.e. automatic) 1511 xlog -- Bool for x axis log status (default False) 1512 ylog -- Bool for y axis log status (default False) 1513 xgrid -- Bool for x axis grid status (default True) 1514 ygrid -- Bool for y axis grid status (default True) 1515 stat -- Draw stat box? (default False) 1516 fit -- Do gaussian fit? (default False) 1517 statx -- Stat box x coordinate (default 0.65) 1518 staty -- Stat box y coordinate (default 0.8) 1519 statyadjust -- List of floats for stat box y coordinate adjustments (default None) 1520 normalizeToUnitArea -- Normalize histograms to unit area? (default False) 1521 normalizeToNumberOfEvents -- Normalize histograms to number of events? If yes, the PlotFolder needs 'numberOfEventsHistogram' set to a histogram filled once per event (default False) 1522 profileX -- Take histograms via ProfileX()? (default False) 1523 fitSlicesY -- Take histograms via FitSlicesY() (default False) 1524 rebinX -- rebin x axis (default None) 1525 scale -- Scale histograms by a number (default None) 1526 xbinlabels -- List of x axis bin labels (if given, default None) 1527 xbinlabelsize -- Size of x axis bin labels (default None) 1528 xbinlabeloption -- Option string for x axis bin labels (default None) 1529 removeEmptyBins -- Bool for removing empty bins, but only if histogram has bin labels (default False) 1530 printBins -- Bool for printing bin values, but only if histogram has bin labels (default False) 1531 drawStyle -- If "hist", draw as line instead of points (default None) 1532 drawCommand -- Deliver this to Draw() (default: None for same as drawStyle) 1533 lineWidth -- If drawStyle=="hist", the width of line (default 2) 1534 legendDx -- Float for moving TLegend in x direction for separate=True (default None) 1535 legendDy -- Float for moving TLegend in y direction for separate=True (default None) 1536 legendDw -- Float for changing TLegend width for separate=True (default None) 1537 legendDh -- Float for changing TLegend height for separate=True (default None) 1538 legend -- Bool to enable/disable legend (default True) 1539 adjustMarginRight -- Float for adjusting right margin (default None) 1540 ratio -- Possibility to disable ratio for this particular plot (default None) 1541 ratioYmin -- Float for y axis minimum in ratio pad (default: list of values) 1542 ratioYmax -- Float for y axis maximum in ratio pad (default: list of values) 1543 ratioFit -- Fit straight line in ratio? (default None) 1544 ratioUncertainty -- Plot uncertainties on ratio? (default True) 1545 ratioCoverageXrange -- Range of x axis values (xmin,xmax) to limit the automatic ratio y axis range calculation to (default None for disabled) 1546 histogramModifier -- Function to be called in create() to modify the histograms (default None) 1550 def _set(attr, default):
1551 setattr(self,
"_"+attr, kwargs.get(attr, default))
1553 _set(
"fallback",
None)
1554 _set(
"outname",
None)
1557 _set(
"xtitle",
None)
1558 _set(
"xtitlesize",
None)
1559 _set(
"xtitleoffset",
None)
1560 _set(
"xlabelsize",
None)
1561 _set(
"ytitle",
None)
1562 _set(
"ytitlesize",
None)
1563 _set(
"ytitleoffset",
None)
1564 _set(
"ztitle",
None)
1565 _set(
"ztitleoffset",
None)
1582 _set(
"statyadjust",
None)
1584 _set(
"normalizeToUnitArea",
False)
1585 _set(
"normalizeToNumberOfEvents",
False)
1586 _set(
"profileX",
False)
1587 _set(
"fitSlicesY",
False)
1588 _set(
"rebinX",
None)
1591 _set(
"xbinlabels",
None)
1592 _set(
"xbinlabelsize",
None)
1593 _set(
"xbinlabeloption",
None)
1594 _set(
"removeEmptyBins",
False)
1595 _set(
"printBins",
False)
1597 _set(
"drawStyle",
"EP")
1598 _set(
"drawCommand",
None)
1599 _set(
"lineWidth", 2)
1601 _set(
"legendDx",
None)
1602 _set(
"legendDy",
None)
1603 _set(
"legendDw",
None)
1604 _set(
"legendDh",
None)
1605 _set(
"legend",
True)
1607 _set(
"adjustMarginRight",
None)
1610 _set(
"ratioYmin", [0, 0.2, 0.5, 0.7, 0.8, 0.9, 0.95])
1611 _set(
"ratioYmax", [1.05, 1.1, 1.2, 1.3, 1.5, 1.8, 2, 2.5, 3, 4, 5])
1612 _set(
"ratioFit",
None)
1613 _set(
"ratioUncertainty",
True)
1614 _set(
"ratioCoverageXrange",
None)
1616 _set(
"histogramModifier",
None)
1621 for name, value
in kwargs.iteritems():
1622 if not hasattr(self,
"_"+name):
1623 raise Exception(
"No attribute '%s'" % name)
1624 setattr(self,
"_"+name, value)
1628 raise Exception(
"Plot can be cloned only before histograms have been created")
1629 cl = copy.copy(self)
1630 cl.setProperties(**kwargs)
1634 """Return number of existing histograms.""" 1638 """Return true if there are no histograms created for the plot""" 1643 if isinstance(h, ROOT.TGraph2D):
1648 if self._ratio
is None:
1650 return ratio
and self._ratio
1653 if self._outname
is not None:
1654 return self._outname
1655 if isinstance(self.
_name, list):
1661 """Return true if the ratio uncertainty should be drawn""" 1662 return self._ratioUncertainty
1665 """Create one histogram from a TDirectory.""" 1670 if isinstance(name, list):
1674 if h
is not None and self._normalizeToNumberOfEvents
and nevents
is not None and nevents != 0:
1675 h.Scale(1.0/nevents)
1678 def create(self, tdirNEvents, requireAllHistograms=False):
1679 """Create histograms from list of TDirectories""" 1680 self.
_histograms = [self.
_createOne(self.
_name, i, tdirNEvent[0], tdirNEvent[1])
for i, tdirNEvent
in enumerate(tdirNEvents)]
1682 if self._fallback
is not None:
1686 self.
_histograms[i] = self.
_createOne(self._fallback[
"name"], i, tdirNEvents[i][0], tdirNEvents[i][1])
1687 profileX[i] = self._fallback.get(
"profileX", self._profileX)
1689 if self._histogramModifier
is not None:
1693 raise Exception(
"More histograms (%d) than there are plot styles (%d) defined. Please define more plot styles in this file" % (len(self.
_histograms), len(_plotStylesColor)))
1698 def _modifyHisto(th1, profileX):
1703 th1 = th1.ProfileX()
1705 if self._fitSlicesY:
1706 ROOT.TH1.AddDirectory(
True)
1708 th1 = ROOT.gDirectory.Get(th1.GetName()+
"_2")
1709 th1.SetDirectory(
None)
1711 ROOT.TH1.AddDirectory(
False)
1713 if self._title
is not None:
1714 th1.SetTitle(self._title)
1716 if self._scale
is not None:
1717 th1.Scale(self._scale)
1721 if self._fallback
is not None:
1725 if requireAllHistograms
and None in self.
_histograms:
1729 """Set stats box.""" 1732 if h
is not None and hasattr(h,
"SetStats"):
1736 def _doStats(h, col, dy):
1741 if self._fit
and h.GetEntries() > 0.5:
1743 f = h.GetListOfFunctions().FindObject(
"gaus")
1751 st = h.GetListOfFunctions().FindObject(
"stats")
1755 st.SetX1NDC(startingX)
1756 st.SetX2NDC(startingX+0.3)
1757 st.SetY1NDC(startingY+dy)
1758 st.SetY2NDC(startingY+dy+0.15)
1759 st.SetTextColor(col)
1762 for i, h
in enumerate(histos):
1763 if self._statyadjust
is not None and i < len(self._statyadjust):
1764 dy += self._statyadjust[i]
1766 _doStats(h, _plotStylesColor[i], dy)
1770 """Normalise histograms to unit area""" 1778 if h.GetSumw2().fN <= 0:
1782 def draw(self, pad, ratio, ratioFactor, nrows):
1783 """Draw the histograms using values for a given algorithm.""" 1794 if self._normalizeToUnitArea:
1797 if self._rebinX
is not None:
1799 h.Rebin(self._rebinX)
1801 def _styleMarker(h, msty, col):
1802 h.SetMarkerStyle(msty)
1803 h.SetMarkerColor(col)
1804 h.SetMarkerSize(0.7)
1808 def _styleHist(h, msty, col):
1809 _styleMarker(h, msty, col)
1811 h.SetLineWidth(self._lineWidth)
1814 style = _styleMarker
1815 if "hist" in self._drawStyle.lower():
1818 if "l" in self._drawStyle.lower():
1826 style(h, _plotStylesMarker[i], _plotStylesColor[i])
1828 if len(histos) == 0:
1830 print "No histograms for plot {name}".
format(name=self.
getName())
1835 histosHaveBinLabels = len(histos[0].GetXaxis().GetBinLabel(1)) > 0
1836 xbinlabels = self._xbinlabels
1837 if xbinlabels
is None:
1838 if histosHaveBinLabels:
1839 xbinlabels = [histos[0].GetXaxis().GetBinLabel(i)
for i
in xrange(1, histos[0].GetNbinsX()+1)]
1841 for h
in histos[1:]:
1842 labels = [h.GetXaxis().GetBinLabel(i)
for i
in xrange(1, h.GetNbinsX()+1)]
1843 diff = difflib.unified_diff(xbinlabels, labels, n=
max(len(xbinlabels), len(labels)))
1847 if item[:2] ==
"@@":
1850 operation.append(item[0])
1852 if lab
in xbinlabels:
1854 ind = xbinlabels.index(lab)
1855 if operation[ind] ==
"-" and operation[-1] ==
"+":
1856 xbinlabels.remove(lab)
1858 elif operation[ind] ==
"+" and operation[-1] ==
"-":
1862 raise Exception(
"This should never happen")
1863 xbinlabels.append(lab)
1866 if len(xbinlabels) == 0:
1871 h_new = h.Clone(h.GetName()+
"_xbinlabels")
1872 h_new.SetBins(len(xbinlabels), h.GetBinLowEdge(1), h.GetBinLowEdge(1)+len(xbinlabels))
1873 for i, label
in enumerate(xbinlabels):
1874 bin = h.GetXaxis().FindFixBin(label)
1876 h_new.SetBinContent(i+1, h.GetBinContent(bin))
1877 h_new.SetBinError(i+1, h.GetBinError(bin))
1879 h_new.SetBinContent(i+1, 0)
1880 h_new.SetBinError(i+1, 0)
1881 histos_new.append(h_new)
1886 if self._removeEmptyBins
and histosHaveBinLabels:
1889 binsToRemove = set()
1890 for b
in xrange(1, histos[0].GetNbinsX()+1):
1893 if h.GetBinContent(b) > 0:
1899 if len(binsToRemove) > 0:
1902 for i
in xrange(len(xbinlabels)):
1903 if (i+1)
not in binsToRemove:
1904 xbinlab_new.append(xbinlabels[i])
1905 xbinlabels = xbinlab_new
1911 for b
in xrange(1, h.GetNbinsX()+1):
1912 if b
not in binsToRemove:
1913 values.append( (h.GetXaxis().GetBinLabel(b), h.GetBinContent(b), h.GetBinError(b)) )
1916 h_new = h.Clone(h.GetName()+
"_empty")
1917 h_new.SetBins(len(values), h.GetBinLowEdge(1), h.GetBinLowEdge(1)+len(values))
1918 for b, (l, v, e)
in enumerate(values):
1919 h_new.GetXaxis().SetBinLabel(b+1, l)
1920 h_new.SetBinContent(b+1, v)
1921 h_new.SetBinError(b+1, e)
1923 histos_new.append(h_new)
1927 if len(histos) == 0:
1929 print "No histograms with non-empty bins for plot {name}".
format(name=self.
getName())
1932 if self._printBins
and histosHaveBinLabels:
1933 print "####################" 1935 width =
max([len(l)
for l
in xbinlabels])
1936 tmp =
"%%-%ds " % width
1937 for b
in xrange(1, histos[0].GetNbinsX()+1):
1938 s = tmp % xbinlabels[b-1]
1940 s +=
"%.3f " % h.GetBinContent(b)
1945 xmin=self._xmin, xmax=self._xmax,
1946 ymin=self._ymin, ymax=self._ymax)
1954 ratioHistos =
filter(
lambda h: h
is not None, [r.getRatio()
for r
in self.
_ratios[1:]])
1956 if len(ratioHistos) > 0:
1957 ratioBoundsY =
_findBoundsY(ratioHistos, ylog=
False, ymin=self._ratioYmin, ymax=self._ratioYmax, coverage=0.68, coverageRange=self._ratioCoverageXrange)
1959 ratioBoundsY = (0.9, 1,1)
1961 if self._ratioFit
is not None:
1962 for i, rh
in enumerate(ratioHistos):
1963 tf_line = ROOT.TF1(
"line%d"%i,
"[0]+x*[1]")
1964 tf_line.SetRange(self._ratioFit[
"rangemin"], self._ratioFit[
"rangemax"])
1965 fitres = rh.Fit(tf_line,
"RINSQ")
1966 tf_line.SetLineColor(rh.GetMarkerColor())
1967 tf_line.SetLineWidth(2)
1968 self._ratioAdditional.append(tf_line)
1969 box =
PlotTextBox(xmin=self._ratioFit.get(
"boxXmin", 0.14), ymin=
None,
1970 xmax=self._ratioFit.get(
"boxXmax", 0.35), ymax=self._ratioFit.get(
"boxYmax", 0.09),
1971 color=rh.GetMarkerColor(), font=43, size=11, lineheight=0.02)
1972 box.move(dx=(box.width()+0.01)*i)
1975 box.addText(
"Const: %.4f#pm%.4f" % (fitres.Parameter(0), fitres.ParError(0)))
1976 box.addText(
"Slope: %.4f#pm%.4f" % (fitres.Parameter(1), fitres.ParError(1)))
1977 self._mainAdditional.append(box)
1987 self.
_setStats(histos, self._statx, self._staty)
1991 frame =
FrameTGraph2D(pad, bounds, histos, ratioOrig, ratioFactor)
1994 ratioBounds = (bounds[0], ratioBoundsY[0], bounds[2], ratioBoundsY[1])
1995 frame =
FrameRatio(pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption)
1997 frame =
Frame(pad, bounds, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption)
2000 frame.setLogx(self._xlog)
2001 frame.setLogy(self._ylog)
2002 frame.setGridx(self._xgrid)
2003 frame.setGridy(self._ygrid)
2008 if self._drawStyle
is not None:
2009 ds = self._drawStyle
2010 if self._drawCommand
is not None:
2011 ds = self._drawCommand
2016 frame.setTitle(histos[0].GetTitle())
2017 if self._xtitle
is not None:
2018 frame.setXTitle(self._xtitle)
2019 if self._xtitlesize
is not None:
2020 frame.setXTitleSize(self._xtitlesize)
2021 if self._xtitleoffset
is not None:
2022 frame.setXTitleOffset(self._xtitleoffset)
2023 if self._xlabelsize
is not None:
2024 frame.setXLabelSize(self._xlabelsize)
2025 if self._ytitle
is not None:
2026 frame.setYTitle(self._ytitle)
2027 if self._ytitlesize
is not None:
2028 frame.setYTitleSize(self._ytitlesize)
2029 if self._ytitleoffset
is not None:
2030 frame.setYTitleOffset(self._ytitleoffset)
2031 if self._ztitle
is not None:
2032 frame.setZTitle(self._ztitle)
2033 if self._ztitleoffset
is not None:
2034 frame.setZTitleOffset(self._ztitleoffset)
2035 if self._adjustMarginRight
is not None:
2036 frame.adjustMarginRight(self._adjustMarginRight)
2038 frame.adjustMarginLeft(0.03)
2039 frame.adjustMarginRight(0.08)
2052 if ratio
and len(histos) > 0:
2053 frame._padRatio.cd()
2054 firstRatio = self.
_ratios[0].getRatio()
2055 if self._ratioUncertainty
and firstRatio
is not None:
2056 firstRatio.SetFillStyle(1001)
2057 firstRatio.SetFillColor(ROOT.kGray)
2058 firstRatio.SetLineColor(ROOT.kGray)
2059 firstRatio.SetMarkerColor(ROOT.kGray)
2060 firstRatio.SetMarkerSize(0)
2062 frame._padRatio.RedrawAxis(
"G")
2073 """Add histograms to a legend. 2077 legendLabels -- List of strings for the legend labels 2079 first = denomUncertainty
2086 self._forLegend.SetFillStyle(1001)
2087 self._forLegend.SetFillColor(ROOT.kGray)
2088 entry = legend.AddEntry(self.
_forLegend, label,
"lpf")
2091 legend.AddEntry(h, label,
"LP")
2094 """Group of plots, results a TCanvas""" 2099 name -- String for name of the TCanvas, used also as the basename of the picture files 2100 plots -- List of Plot objects 2103 ncols -- Number of columns (default 2) 2104 legendDx -- Float for moving TLegend in x direction (default None) 2105 legendDy -- Float for moving TLegend in y direction (default None) 2106 legendDw -- Float for changing TLegend width (default None) 2107 legendDh -- Float for changing TLegend height (default None) 2108 legend -- Bool for disabling legend (default True for legend being enabled) 2109 overrideLegendLabels -- List of strings for legend labels, if given, these are used instead of the ones coming from Plotter (default None) 2110 onlyForPileup -- Plots this group only for pileup samples 2115 def _set(attr, default):
2116 setattr(self,
"_"+attr, kwargs.get(attr, default))
2120 _set(
"legendDx",
None)
2121 _set(
"legendDy",
None)
2122 _set(
"legendDw",
None)
2123 _set(
"legendDh",
None)
2124 _set(
"legend",
True)
2126 _set(
"overrideLegendLabels",
None)
2128 _set(
"onlyForPileup",
False)
2133 for name, value
in kwargs.iteritems():
2134 if not hasattr(self,
"_"+name):
2135 raise Exception(
"No attribute '%s'" % name)
2136 setattr(self,
"_"+name, value)
2145 for i, plot
in enumerate(self.
_plots):
2146 if plot.getName() == name:
2149 raise Exception(
"Did not find Plot '%s' from PlotGroup '%s'" % (name, self.
_name))
2155 self._plots.append(plot)
2159 if plot.getName() == name:
2161 raise Exception(
"No Plot named '%s'" % name)
2164 """Return True if the PlotGroup is intended only for pileup samples""" 2165 return self._onlyForPileup
2167 def create(self, tdirectoryNEvents, requireAllHistograms=False):
2168 """Create histograms from a list of TDirectories. 2171 tdirectoryNEvents -- List of (TDirectory, nevents) pairs 2172 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False) 2175 plot.create(tdirectoryNEvents, requireAllHistograms)
2177 def draw(self, legendLabels, prefix=None, separate=False, saveFormat=".pdf", ratio=True):
2178 """Draw the histograms using values for a given algorithm. 2181 legendLabels -- List of strings for legend labels (corresponding to the tdirectories in create()) 2182 prefix -- Optional string for file name prefix (default None) 2183 separate -- Save the plots of a group to separate files instead of a file per group (default False) 2184 saveFormat -- String specifying the plot format (default '.pdf') 2185 ratio -- Add ratio to the plot (default True) 2188 if self._overrideLegendLabels
is not None:
2189 legendLabels = self._overrideLegendLabels
2192 onlyEmptyPlots =
True 2194 if not plot.isEmpty():
2195 onlyEmptyPlots =
False 2201 return self.
_drawSeparate(legendLabels, prefix, saveFormat, ratio)
2203 cwidth = 500*self._ncols
2204 nrows =
int((len(self.
_plots)+self._ncols-1)/self._ncols)
2205 cheight = 500 * nrows
2212 canvas.Divide(self._ncols, nrows)
2214 for i, plot
in enumerate(self.
_plots):
2215 pad = canvas.cd(i+1)
2219 for i, plot
in enumerate(self.
_plots):
2220 pad = canvas.cd(i+1)
2221 if not plot.isEmpty():
2226 if len(self.
_plots) <= 4:
2236 if self._legendDx
is not None:
2237 lx1 += self._legendDx
2238 lx2 += self._legendDx
2239 if self._legendDy
is not None:
2240 ly1 += self._legendDy
2241 ly2 += self._legendDy
2242 if self._legendDw
is not None:
2243 lx2 += self._legendDw
2244 if self._legendDh
is not None:
2245 ly1 -= self._legendDh
2246 plot =
max(self.
_plots, key=
lambda p: p.getNumberOfHistograms())
2247 denomUnc = sum([p.drawRatioUncertainty()
for p
in self.
_plots]) > 0
2248 legend = self.
_createLegend(plot, legendLabels, lx1, ly1, lx2, ly2,
2249 denomUncertainty=(ratio
and denomUnc))
2251 return self.
_save(canvas, saveFormat, prefix=prefix)
2254 """Internal method to do the drawing to separate files per Plot instead of a file per PlotGroup""" 2262 for c
in [canvas, canvasRatio]:
2263 c.SetTopMargin(0.05)
2264 c.SetBottomMargin(0.13)
2265 c.SetLeftMargin(0.16)
2266 c.SetRightMargin(0.05)
2279 ratioForThisPlot = plot.isRatio(ratio)
2281 if ratioForThisPlot:
2297 if plot._legendDx
is not None:
2298 lx1 += plot._legendDx
2299 lx2 += plot._legendDx
2300 if plot._legendDy
is not None:
2301 ly1 += plot._legendDy
2302 ly2 += plot._legendDy
2303 if plot._legendDw
is not None:
2304 lx2 += plot._legendDw
2305 if plot._legendDh
is not None:
2306 ly1 -= plot._legendDh
2309 legend = self.
_createLegend(plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.03,
2310 denomUncertainty=(ratioForThisPlot
and plot.drawRatioUncertainty))
2312 ret.extend(self.
_save(c, saveFormat, prefix=prefix, postfix=
"_"+plot.getName(), single=
True))
2316 """Internal method to set divide a pad to two for ratio plots""" 2319 def _createLegend(self, plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.016, denomUncertainty=True):
2320 if not self._legend:
2323 l = ROOT.TLegend(lx1, ly1, lx2, ly2)
2324 l.SetTextSize(textSize)
2331 plot.addToLegend(l, legendLabels, denomUncertainty)
2335 def _save(self, canvas, saveFormat, prefix=None, postfix=None, single=False):
2338 if prefix
is not None:
2340 if postfix
is not None:
2344 backup = ROOT.gErrorIgnoreLevel
2345 ROOT.gErrorIgnoreLevel = ROOT.kWarning
2346 canvas.SaveAs(name+saveFormat)
2348 ROOT.gErrorIgnoreLevel = backup
2352 canvas.SetLogx(
False)
2353 canvas.SetLogy(
False)
2357 return [name+saveFormat]
2360 """Represents a collection of PlotGroups, produced from a single folder in a DQM file""" 2365 plotGroups -- List of PlotGroup objects 2368 loopSubFolders -- Should the subfolders be looped over? (default: True) 2369 onlyForPileup -- Plots this folder only for pileup samples 2370 onlyForElectron -- Plots this folder only for electron samples 2371 onlyForConversion -- Plots this folder only for conversion samples 2372 purpose -- html.PlotPurpose member class for the purpose of the folder, used for grouping of the plots to the HTML pages 2373 page -- Optional string for the page in HTML generatin 2374 section -- Optional string for the section within a page in HTML generation 2375 numberOfEventsHistogram -- Optional path to histogram filled once per event. Needed if there are any plots normalized by number of events. Path is relative to "possibleDqmFolders". 2387 raise Exception(
"Got unexpected keyword arguments: "+
",".
join(kwargs.keys()))
2390 """Return True if the PlotGroups of this folder should be applied to the all subfolders""" 2394 """Return True if the folder is intended only for pileup samples""" 2416 self._plotGroups.append(plotGroup)
2426 if pg.getName() == name:
2428 raise Exception(
"No PlotGroup named '%s'" % name)
2430 def create(self, dirsNEvents, labels, isPileupSample=True, requireAllHistograms=False):
2431 """Create histograms from a list of TFiles. 2434 dirsNEvents -- List of (TDirectory, nevents) pairs 2435 labels -- List of strings for legend labels corresponding the files 2436 isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup) 2437 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False) 2440 if len(dirsNEvents) != len(labels):
2441 raise Exception(
"len(dirsNEvents) should be len(labels), now they are %d and %d" % (len(dirsNEvents), len(labels)))
2446 if pg.onlyForPileup()
and not isPileupSample:
2448 pg.create(dirsNEvents, requireAllHistograms)
2450 def draw(self, prefix=None, separate=False, saveFormat=".pdf", ratio=True):
2451 """Draw and save all plots using settings of a given algorithm. 2454 prefix -- Optional string for file name prefix (default None) 2455 separate -- Save the plots of a group to separate files instead of a file per group (default False) 2456 saveFormat -- String specifying the plot format (default '.pdf') 2457 ratio -- Add ratio to the plot (default True) 2462 ret.extend(pg.draw(self.
_labels, prefix=prefix, separate=separate, saveFormat=saveFormat, ratio=ratio))
2468 """Method called to (possibly) translate a subfolder name to more 'readable' form 2470 The implementation in this (base) class just returns the 2471 argument. The idea is that a deriving class might want to do 2472 something more complex (like trackingPlots.TrackingPlotFolder 2475 return dqmSubFolderName
2478 """Iterate over possible selections name (used in output directory name and legend) from the name of PlotterFolder, and a return value of translateSubFolder""" 2480 if plotFolderName !=
"":
2481 ret +=
"_"+plotFolderName
2482 if translatedDqmSubFolder
is not None:
2483 ret +=
"_"+translatedDqmSubFolder
2487 """Return True if this subfolder should be processed 2490 limitOnlyTo -- List/set/similar containing the translatedDqmSubFolder 2491 translatedDqmSubFolder -- Return value of translateSubFolder 2493 return translatedDqmSubFolder
in limitOnlyTo
2496 """Class to hold the original name and a 'translated' name of a subfolder in the DQM ROOT file""" 2502 """Equality is defined by the 'translated' name""" 2506 """Plotter for one DQM folder. 2508 This class is supposed to be instantiated by the Plotter class (or 2509 PlotterItem, to be more specific), and not used directly by the 2512 def __init__(self, name, possibleDqmFolders, dqmSubFolders, plotFolder, fallbackNames, fallbackDqmSubFolders, tableCreators):
2517 name -- Name of the folder (is used in the output directory naming) 2518 possibleDqmFolders -- List of strings for possible directories of histograms in TFiles 2519 dqmSubFolders -- List of lists of strings for list of subfolders per input file, or None if no subfolders 2520 plotFolder -- PlotFolder object 2521 fallbackNames -- List of names for backward compatibility (can be empty). These are used only by validation.Validation (class responsible of the release validation workflow) in case the reference file pointed by 'name' does not exist. 2522 fallbackDqmSubFolders -- List of dicts of (string->string) for mapping the subfolder names found in the first file to another names. Use case is comparing files that have different iteration naming convention. 2523 tableCreators -- List of PlotterTableItem objects for tables to be created from this folder 2529 if dqmSubFolders
is None:
2535 for sf_list
in dqmSubFolders:
2537 sf_translated = self._plotFolder.translateSubFolder(sf)
2538 if sf_translated
is not None and not sf_translated
in subfolders:
2539 subfolders[sf_translated] =
DQMSubFolder(sf, sf_translated)
2542 self._dqmSubFolders.sort(key=
lambda sf: sf.subfolder)
2552 return self._plotFolder.getPurpose()
2555 return self._plotFolder.getPage()
2558 return self._plotFolder.getSection()
2561 return self._plotFolder.onlyForPileup()
2564 return self._plotFolder.onlyForElectron()
2567 return self._plotFolder.onlyForConversion()
2573 """Get list of subfolders, possibly limiting to some of them. 2576 limitOnlyTo -- Object depending on the PlotFolder type for limiting the set of subfolders to be processed 2582 if limitOnlyTo
is None:
2585 return filter(
lambda s: self._plotFolder.limitSubFolder(limitOnlyTo, s.translated), self.
_dqmSubFolders)
2591 """Get a generator for the 'selection name', looping over the name and fallbackNames""" 2593 for selname
in self._plotFolder.iterSelectionName(name, dqmSubFolder.translated
if dqmSubFolder
is not None else None):
2599 def create(self, files, labels, dqmSubFolder, isPileupSample=True, requireAllHistograms=False):
2600 """Create histograms from a list of TFiles. 2602 files -- List of TFiles 2603 labels -- List of strings for legend labels corresponding the files 2604 dqmSubFolder -- DQMSubFolder object for a subfolder (or None for no subfolder) 2605 isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup) 2606 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False) 2609 subfolder = dqmSubFolder.subfolder
if dqmSubFolder
is not None else None 2610 neventsHisto = self._plotFolder.getNumberOfEventsHistogram()
2618 fallback = fallbackFunc(subfolder)
2619 if fallback
is not None:
2623 d = GetDirectoryCode.codesToNone(ret)
2625 if neventsHisto
is not None and tfile
is not None:
2627 if hnev
is not None:
2628 nev = hnev.GetEntries()
2629 dirsNEvents.append( (d, nev) )
2631 self._plotFolder.create(dirsNEvents, labels, isPileupSample, requireAllHistograms)
2634 """Draw and save all plots using settings of a given algorithm.""" 2635 return self._plotFolder.draw(*args, **kwargs)
2639 """Instance of plotter that knows the directory content, holds many folders.""" 2646 if limitSubFoldersOnlyTo
is not None:
2647 limitOnlyTo = limitSubFoldersOnlyTo.get(plotterFolder.getName(),
None)
2649 for dqmSubFolder
in plotterFolder.getDQMSubFolders(limitOnlyTo=limitOnlyTo):
2650 yield plotterFolder, dqmSubFolder
2654 def __init__(self, name, possibleDirs, plotFolder, fallbackNames=[], fallbackDqmSubFolders=[]):
2658 name -- Name of the folder (is used in the output directory naming) 2659 possibleDirs -- List of strings for possible directories of histograms in TFiles 2660 plotFolder -- PlotFolder object 2663 fallbackNames -- Optional list of names for backward compatibility. These are used only by validation.Validation (class responsible of the release validation workflow) in case the reference file pointed by 'name' does not exist. 2664 fallbackDqmSubFolders -- Optional list of functions for (string->string) mapping the subfolder names found in the first file to another names (function should return None for no mapping). Use case is comparing files that have different iteration naming convention. 2680 self._tableCreators.append(tc)
2683 """Read available subfolders from the files 2686 files -- List of strings for paths to files, or list of TFiles 2688 For each file, loop over 'possibleDirs', and read the 2689 subfolders of first one that exists. 2691 Returns a PlotterFolder if at least one file for which one of 2692 'possibleDirs' exists. Otherwise, return None to signal that 2693 there is nothing available for this PlotFolder. 2696 if self._plotFolder.loopSubFolders():
2698 possibleDirFound =
False 2703 isOpenFile = isinstance(fname, ROOT.TFile)
2707 tfile = ROOT.TFile.Open(fname)
2711 possibleDirFound =
True 2712 if subFolders
is not None:
2714 for key
in d.GetListOfKeys():
2715 if isinstance(key.ReadObj(), ROOT.TDirectory):
2716 subf.append(key.GetName())
2717 subFolders.append(subf)
2723 if not possibleDirFound:
2733 def create(self, openFiles, legendLabels, dqmSubFolder):
2734 if isinstance(dqmSubFolder, list):
2735 if len(dqmSubFolder) != len(openFiles):
2736 raise Exception(
"When dqmSubFolder is a list, len(dqmSubFolder) should be len(openFiles), now they are %d and %d" % (len(dqmSubFolder), len(openFiles)))
2738 dqmSubFolder = [dqmSubFolder]*len(openFiles)
2739 dqmSubFolder = [sf.subfolder
if sf
is not None else None for sf
in dqmSubFolder]
2742 for f, sf
in zip(openFiles, dqmSubFolder):
2745 if tdir
is not None:
2746 data = self._tableCreator.create(tdir)
2761 for i
in xrange(len(tbl)):
2763 tbl[i] = [
None]*colLen
2765 return html.Table(columnHeaders=legendLabels, rowHeaders=self._tableCreator.headers(), table=tbl,
2766 purpose=self._tableCreator.getPurpose(), page=self._tableCreator.getPage(), section=self._tableCreator.getSection(dqmSubFolder[0]))
2769 """Contains PlotFolders, i.e. the information what plots to do, and creates a helper object to actually produce the plots.""" 2773 ROOT.TH1.AddDirectory(
False)
2776 """Append a plot folder to the plotter. 2778 All arguments are forwarded to the constructor of PlotterItem. 2783 for plotterItem
in self.
_plots:
2784 if plotterItem.getName() == attachToFolder:
2787 raise Exception(
"Did not find plot folder '%s' when trying to attach a table creator to it" % attachToFolder)
2790 """Remove all plot folders and tables""" 2794 return [item.getName()
for item
in self.
_plots]
2797 return [item.getPlotFolder()
for item
in self.
_plots]
2801 if item.getName() == name:
2802 return item.getPlotFolder()
2803 raise Exception(
"No PlotFolder named '%s'" % name)
2806 """Returns PlotterInstance object, which knows how exactly to produce the plots for these files""" def __init__(self, pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None)
def create(self, tdirectory)
def iterSelectionName(self, plotFolderName, translatedDqmSubFolder)
def __init__(self, x, y, text, size=None, bold=True, align="left", color=ROOT.kBlack, font=None)
def draw(self, prefix=None, separate=False, saveFormat=".pdf", ratio=True)
def append(self, plotGroup)
def __init__(self, name, plots, kwargs)
def __init__(self, name, nameA, nameB, title="")
def getPossibleDQMFolders(self)
def adjustMarginLeft(self, adjust)
def _findBoundsY(th1s, ylog, ymin=None, ymax=None, coverage=None, coverageRange=None)
def set(self, plotGroups)
def setXTitle(self, title)
def readDirs(self, files)
def setXLabelSize(self, size)
def _getOrCreateObject(tdirectory, nameOrCreator)
def iterFolders(self, limitSubFoldersOnlyTo=None)
def _save(self, canvas, saveFormat, prefix=None, postfix=None, single=False)
def setYTitleSize(self, size)
def setXLabelSize(self, size)
def _findBounds(th1s, ylog, xmin=None, xmax=None, ymin=None, ymax=None)
def _modifyPadForRatio(self, pad)
def Draw(self, options="")
def __init__(self, name, xhistoName, yhistoName, zaxis=False)
def adjustMarginRight(self, adjust)
def __init__(self, possibleDirs, tableCreator)
def getTableCreators(self)
def __init__(self, xmin, ymin, xmax, ymax, lineheight=0.04, fillColor=ROOT.kWhite, transparent=True, kwargs)
def setXTitleSize(self, size)
def create(self, tdirectory)
def adjustMarginLeft(self, adjust)
def setXLabelSize(self, size)
def _getYminIgnoreOutlier(th1)
def divide(outfile, dest, numer, denom)
def append(self, args, kwargs)
def getDQMSubFolders(self, limitOnlyTo=None)
def _getXmax(obj, limitToNonZeroContent=False)
def setZTitle(self, title)
def __init__(self, pad, bounds, histos, ratioOrig, ratioFactor)
def setZTitleOffset(self, offset)
def setXTitleSize(self, size)
def getNumberOfHistograms(self)
def create(self, tdirectoryNEvents, requireAllHistograms=False)
bool equal(const T &first, const T &second)
def move(self, dx=0, dy=0, dw=0, dh=0)
def __init__(self, name, kwargs)
def create(self, openFiles, legendLabels, dqmSubFolder)
def _calculateRatios(histos, ratioUncertainty=False)
def appendTable(self, attachToFolder, args, kwargs)
def setYTitleOffset(self, offset)
def setYTitle(self, title)
def setYTitleSize(self, size)
def onlyForElectron(self)
def _setStats(self, histos, startingX, startingY)
def getSelectionName(self, dqmSubFolder)
def _getDirectory(args, kwargs)
def setYTitle(self, title)
def Draw(self, options=None)
def draw(self, pad, ratio, ratioFactor, nrows)
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
def setTitle(self, title)
def setXTitle(self, title)
def create(self, tdirectory)
def draw(self, legendLabels, prefix=None, separate=False, saveFormat=".pdf", ratio=True)
def readDirs(self, files)
Abs< T >::type abs(const T &t)
def adjustMarginRight(self, adjust)
def adjustMarginLeft(self, adjust)
def setProperties(self, kwargs)
def addToLegend(self, legend, legendLabels, denomUncertainty)
def _getYmaxWithError(th1)
def setXTitleOffset(self, offset)
def _getDirectoryDetailed(tfile, possibleDirs, subDir=None)
def setXTitleOffset(self, size)
def create(self, tdirectory)
def onlyForConversion(self)
def _getYminMaxAroundMedian(obj, coverage, coverageRange=None)
def getPlotFolder(self, name)
def setYTitleOffset(self, offset)
def __init__(self, name, histo, title="")
def onlyForConversion(self)
def limitSubFolder(self, limitOnlyTo, translatedDqmSubFolder)
def setXTitleSize(self, size)
def setYTitleRatio(self, title)
def drawRatioUncertainty(self)
static std::string join(char **cmd)
def create(self, dirsNEvents, labels, isPileupSample=True, requireAllHistograms=False)
def __init__(self, name, assoc, dup, reco, title="")
def adjustMarginRight(self, adjust)
def __init__(self, subfolder, translated)
def create(self, tdirectory)
def setXTitleOffset(self, offset)
def __init__(self, pad, bounds, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None)
def __init__(self, name, mapping, normalizeTo=None)
def _createLegend(self, plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.016, denomUncertainty=True)
def translateSubFolder(self, dqmSubFolderName)
def __init__(self, folders)
def setTitle(self, title)
def __init__(self, name, possibleDqmFolders, dqmSubFolders, plotFolder, fallbackNames, fallbackDqmSubFolders, tableCreators)
def setXTitle(self, title)
def setYTitleSize(self, size)
def setYTitle(self, title)
def _getXmin(obj, limitToNonZeroContent=False)
def onlyForElectron(self)
def _drawSeparate(self, legendLabels, prefix, saveFormat, ratio)
def create(self, tdirNEvents, requireAllHistograms=False)
def getPlotGroup(self, name)
def _drawFrame(pad, bounds, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, suffix="")
def appendTableCreator(self, tc)
def _modifyPadForRatio(pad, ratioFactor)
def create(self, files, labels, dqmSubFolder, isPileupSample=True, requireAllHistograms=False)
def _createCanvas(name, width, height)
def setYTitleOffset(self, offset)
auto wrap(F iFunc) -> decltype(iFunc())
def getPlotFolderNames(self)
def getNumberOfEventsHistogram(self)
def __init__(self, plotGroups, kwargs)
def draw(self, args, kwargs)
def _th1ToOrderedDict(th1, renameBin=None)
def getSelectionNameIterator(self, dqmSubFolder)
def create(self, tdirectory)
def setProperties(self, kwargs)
def _createOne(self, name, index, tdir, nevents)
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
def setTitle(self, title)
def __init__(self, name, possibleDirs, plotFolder, fallbackNames=[], fallbackDqmSubFolders=[])
def _getObject(tdirectory, name)
def __init__(self, name, histoName, mapping, normalizeTo=None, scale=None, renameBin=None, ignoreMissingBins=False, minExistingBins=None, originalOrder=False)