9 ROOT.gROOT.SetBatch(
True)
10 ROOT.PyConfig.IgnoreCommandLineOptions =
True 15 _ratioYTitle =
"Ratio" 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 if limitToNonZeroContent:
374 lst = [obj.GetBinContent(i)
for i
in xrange(1, obj.GetNbinsX()+1)
if obj.GetBinContent(i) != 0 ]
375 return min(lst)
if len(lst) != 0
else 0
377 return obj.GetMinimum()
378 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
379 m =
min([obj.GetY()[i]
for i
in xrange(0, obj.GetN())])
380 return m*0.9
if m > 0
else m*1.1
384 if isinstance(obj, ROOT.TH2):
385 yaxis = obj.GetYaxis()
386 return yaxis.GetBinUpEdge(yaxis.GetLast())
387 elif isinstance(obj, ROOT.TH1):
388 if limitToNonZeroContent:
389 lst = [obj.GetBinContent(i)
for i
in xrange(1, obj.GetNbinsX()+1)
if obj.GetBinContent(i) != 0 ]
390 return max(lst)
if len(lst) != 0
else 0
392 return obj.GetMaximum()
393 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
394 m =
max([obj.GetY()[i]
for i
in xrange(0, obj.GetN())])
395 return m*1.1
if m > 0
else m*0.9
399 return max([th1.GetBinContent(i)+th1.GetBinError(i)
for i
in xrange(1, th1.GetNbinsX()+1)])
402 yvals =
filter(
lambda n: n>0, [th1.GetBinContent(i)
for i
in xrange(1, th1.GetNbinsX()+1)])
405 return th1.GetMinimum()
410 ind_min = len(yvals)-1 -
int(len(yvals)*0.95)
411 min_val = yvals[ind_min]
412 for i
in xrange(0, ind_min):
413 if yvals[i] > 0.1*min_val:
419 inRange =
lambda x:
True 420 inRange2 =
lambda xmin,xmax:
True 422 inRange =
lambda x: coverageRange[0] <= x <= coverageRange[1]
423 inRange2 =
lambda xmin,xmax: coverageRange[0] <= xmin
and xmax <= coverageRange[1]
425 if isinstance(obj, ROOT.TH1):
426 yvals = [obj.GetBinContent(i)
for i
in xrange(1, obj.GetNbinsX()+1)
if inRange2(obj.GetXaxis().GetBinLowEdge(i), obj.GetXaxis().GetBinUpEdge(i))]
427 yvals =
filter(
lambda x: x != 0, yvals)
428 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
429 yvals = [obj.GetY()[i]
for i
in xrange(0, obj.GetN())
if inRange(obj.GetX()[i])]
435 return (yvals[0], yvals[0])
437 return (yvals[0], yvals[1])
440 nvals =
int(len(yvals)*coverage)
443 if len(yvals) % 2 == 0:
445 return ( yvals[half-1], yvals[half] )
447 middle = len(yvals)/2
448 return ( yvals[middle-1], yvals[middle+1] )
449 ind_min = (len(yvals)-nvals)/2
450 ind_max = len(yvals)-1 - ind_min
452 return (yvals[ind_min], yvals[ind_max])
454 def _findBounds(th1s, ylog, xmin=None, xmax=None, ymin=None, ymax=None):
455 """Find x-y axis boundaries encompassing a list of TH1s if the bounds are not given in arguments. 459 ylog -- Boolean indicating if y axis is in log scale or not (affects the automatic ymax) 462 xmin -- Minimum x value; if None, take the minimum of TH1s 463 xmax -- Maximum x value; if None, take the maximum of TH1s 464 ymin -- Minimum y value; if None, take the minimum of TH1s 465 ymax -- Maximum y value; if None, take the maximum of TH1s 470 if xmin
is None or xmax
is None or isinstance(xmin, list)
or isinstance(max, list):
474 xmins.append(
_getXmin(th1, limitToNonZeroContent=isinstance(xmin, list)))
475 xmaxs.append(
_getXmax(th1, limitToNonZeroContent=isinstance(xmax, list)))
478 xmins =
filter(
lambda h: h
is not None, xmins)
479 xmaxs =
filter(
lambda h: h
is not None, xmaxs)
483 elif isinstance(xmin, list):
487 print "Histogram is zero, using the smallest given value for xmin from",
str(xmin)
490 xmins_below =
filter(
lambda x: x<=xm, xmin)
491 if len(xmins_below) == 0:
495 print "Histogram minimum x %f is below all given xmin values %s, using the smallest one" % (xm,
str(xmin))
497 xmin =
max(xmins_below)
501 elif isinstance(xmax, list):
505 print "Histogram is zero, using the smallest given value for xmax from",
str(xmin)
508 xmaxs_above =
filter(
lambda x: x>xm, xmax)
509 if len(xmaxs_above) == 0:
513 print "Histogram maximum x %f is above all given xmax values %s, using the maximum one" % (xm,
str(xmax))
515 xmax =
min(xmaxs_above)
518 th1.GetXaxis().SetRangeUser(xmin, xmax)
520 return (xmin, ymin, xmax, ymax)
522 def _findBoundsY(th1s, ylog, ymin=None, ymax=None, coverage=None, coverageRange=None):
523 """Find y axis boundaries encompassing a list of TH1s if the bounds are not given in arguments. 527 ylog -- Boolean indicating if y axis is in log scale or not (affects the automatic ymax) 530 ymin -- Minimum y value; if None, take the minimum of TH1s 531 ymax -- Maximum y value; if None, take the maximum of TH1s 532 coverage -- If set, use only values within the 'coverage' part around the median are used for min/max (useful for ratio) 533 coverageRange -- If coverage and this are set, use only the x axis specified by an (xmin,xmax) pair for the coverage 535 if coverage
is not None:
539 y_scale_max =
lambda y: y
540 y_scale_min =
lambda y: y
543 y_scale_max =
lambda y: y*1.5
545 y_scale_max =
lambda y: y*1.05
546 y_scale_min =
lambda y: y*0.9
548 if ymin
is None or ymax
is None or isinstance(ymin, list)
or isinstance(ymax, list):
552 if coverage
is not None:
555 if ylog
and isinstance(ymin, list):
558 _ymin =
_getYmin(th1, limitToNonZeroContent=isinstance(ymin, list))
559 _ymax =
_getYmax(th1, limitToNonZeroContent=isinstance(ymax, list))
567 elif isinstance(ymin, list):
568 ym_unscaled =
min(ymins)
569 ym = y_scale_min(ym_unscaled)
570 ymins_below =
filter(
lambda y: y<=ym, ymin)
571 if len(ymins_below) == 0:
573 if ym_unscaled < ymin:
575 print "Histogram minimum y %f is below all given ymin values %s, using the smallest one" % (ym,
str(ymin))
577 ymin =
max(ymins_below)
582 ymax = y_scale_max(
max(ymaxs+[ymin]))
583 elif isinstance(ymax, list):
584 ym_unscaled =
max(ymaxs)
585 ym = y_scale_max(ym_unscaled)
586 ymaxs_above =
filter(
lambda y: y>ym, ymax)
587 if len(ymaxs_above) == 0:
589 if ym_unscaled > ymax:
591 print "Histogram maximum y %f is above all given ymax values %s, using the maximum one" % (ym_unscaled,
str(ymax))
593 ymax =
min(ymaxs_above)
596 th1.GetYaxis().SetRangeUser(ymin, ymax)
601 """Class for subtracting two histograms""" 606 name -- String for name of the resulting histogram (A-B) 607 nameA -- String for A histogram 608 nameB -- String for B histogram 611 title -- String for a title of the resulting histogram (default "") 613 Uncertainties are calculated with the assumption that B is a 614 subset of A, and the histograms contain event counts. 622 """String representation, returns the name""" 626 """Create and return the fake+duplicate histogram from a TDirectory""" 630 if not histoA
or not histoB:
633 ret = histoA.Clone(self.
_name)
639 ret.SetCanExtend(
False)
641 for i
in xrange(0, histoA.GetNbinsX()+2):
642 val = histoA.GetBinContent(i)-histoB.GetBinContent(i)
643 ret.SetBinContent(i, val)
644 ret.SetBinError(i, math.sqrt(val))
649 """Class to transform bin contents in an arbitrary way.""" 654 name -- String for name of the resulting histogram 655 histo -- String for a source histogram (needs to be cumulative) 656 func -- Function to operate on the bin content 664 """String representation, returns the name""" 668 """Create and return the transformed histogram from a TDirectory""" 673 ret = histo.Clone(self.
_name)
679 ret.SetCanExtend(
False)
681 for i
in xrange(0, histo.GetNbinsX()+2):
682 ret.SetBinContent(i, self.
_func(histo.GetBinContent(i)))
686 """Class to calculate the fake+duplicate rate""" 687 def __init__(self, name, assoc, dup, reco, title=""):
691 name -- String for the name of the resulting efficiency histogram 692 assoc -- String for the name of the "associated" histogram 693 dup -- String for the name of the "duplicates" histogram 694 reco -- String for the name of the "reco" (denominator) histogram 697 title -- String for a title of the resulting histogram (default "") 699 The result is calculated as 1 - (assoc - dup) / reco 708 """String representation, returns the name""" 712 """Create and return the fake+duplicate histogram from a TDirectory""" 719 if not hassoc
or not hdup
or not hreco:
722 hfakedup = hreco.Clone(self.
_name)
723 hfakedup.SetTitle(self.
_title)
725 for i
in xrange(1, hassoc.GetNbinsX()+1):
726 numerVal = hassoc.GetBinContent(i) - hdup.GetBinContent(i)
727 denomVal = hreco.GetBinContent(i)
729 fakedupVal = (1 - numerVal / denomVal)
if denomVal != 0.0
else 0.0
730 errVal = math.sqrt(fakedupVal*(1-fakedupVal)/denomVal)
if (denomVal != 0.0
and fakedupVal <= 1)
else 0.0
732 hfakedup.SetBinContent(i, fakedupVal)
733 hfakedup.SetBinError(i, errVal)
738 """Class for making a cut efficiency histograms. 748 name -- String for name of the resulting histogram 749 histo -- String for a source histogram (needs to be cumulative) 756 """String representation, returns the name""" 760 """Create and return the cut efficiency histogram from a TDirectory""" 766 ascending = histo.GetBinContent(0) < histo.GetBinContent(histo.GetNbinsX())
768 n_tot = histo.GetBinContent(histo.GetNbinsX())
770 n_tot = histo.GetBinContent(0)
775 ret = histo.Clone(self.
_name)
779 for i
in xrange(1, histo.GetNbinsX()+1):
780 n = histo.GetBinContent(i)
782 errVal = math.sqrt(val*(1-val)/n_tot)
783 ret.SetBinContent(i, val)
784 ret.SetBinError(i, errVal)
788 """Class to create a histogram by aggregating bins of another histogram to a bin of the resulting histogram.""" 789 def __init__(self, name, histoName, mapping, normalizeTo=None, scale=None, renameBin=None, ignoreMissingBins=False, minExistingBins=None, originalOrder=False):
793 name -- String for the name of the resulting histogram 794 histoName -- String for the name of the source histogram 795 mapping -- Dictionary for mapping the bins (see below) 798 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. 799 scale -- Optional number for scaling the histogram (passed to ROOT.TH1.Scale()) 800 renameBin -- Optional function (string -> string) to rename the bins of the input histogram 801 originalOrder -- Boolean for using the order of bins in the histogram (default False) 803 Mapping structure (mapping): 805 Dictionary (you probably want to use collections.OrderedDict) 806 should be a mapping from the destination bin label to a list 807 of source bin labels ("dst -> [src]"). 820 """String representation, returns the name""" 824 """Create and return the histogram from a TDirectory""" 830 binValues = [
None]*len(self.
_mapping)
836 for i, (key, labels)
in enumerate(self._mapping.iteritems()):
842 sumTime += values[l][0]
843 sumErrorSq += values[l][1]**2
849 binValues[i] = (sumTime, math.sqrt(sumErrorSq))
852 ivalue = len(values)+1
858 ivalue = values.keys().
index(lab)
860 binIndexOrder.append( (ivalue, i) )
863 binIndexOrder.sort(key=
lambda t: t[0])
866 for i
in xrange(0, len(binValues)):
867 fromIndex = binIndexOrder[i][1]
868 tmpVal.append(binValues[fromIndex])
869 tmpLab.append(binLabels[fromIndex])
877 for i, val
in enumerate(binValues):
880 binValues =
filter(
lambda v: v
is not None, binValues)
881 binLabels =
filter(
lambda v: v
is not None, binLabels)
882 if len(binValues) == 0:
885 result = ROOT.TH1F(self.
_name, self.
_name, len(binValues), 0, len(binValues))
886 for i, (value, label)
in enumerate(
zip(binValues, binLabels)):
887 if value
is not None:
888 result.SetBinContent(i+1, value[0])
889 result.SetBinError(i+1, value[1])
890 result.GetXaxis().SetBinLabel(i+1, label)
895 print "Trying to normalize {name} to {binlabel}, which does not exist".
format(name=self.
_name, binlabel=self.
_normalizeTo)
897 value = th1.GetBinContent(bin)
899 result.Scale(1/value)
901 if self.
_scale is not None:
907 """Class to create a histogram by aggregaging integrals of another histoggrams.""" 908 def __init__(self, name, mapping, normalizeTo=None):
912 name -- String for the name of the resulting histogram 913 mapping -- Dictionary for mapping the bin label to a histogram name 916 normalizeTo -- Optional string for a histogram. If given, all bins of the resulting histograqm are divided by the integral of this histogram. 923 """String representation, returns the name""" 927 """Create and return the histogram from a TDirectory""" 929 for key, histoName
in self._mapping.iteritems():
933 result.append( (key, th1.Integral(0, th1.GetNbinsX()+1)) )
937 res = ROOT.TH1F(self.
_name, self.
_name, len(result), 0, len(result))
939 for i, (name, count)
in enumerate(result):
940 res.SetBinContent(i+1, count)
941 res.GetXaxis().SetBinLabel(i+1, name)
947 scale = th1.Integral(0, th1.GetNbinsX()+1)
953 """Class to construct a ROC curve (e.g. efficiency vs. fake rate) from two histograms""" 954 def __init__(self, name, xhistoName, yhistoName, zaxis=False):
958 name -- String for the name of the resulting histogram 959 xhistoName -- String for the name of the x-axis histogram (or another "creator" object) 960 yhistoName -- String for the name of the y-axis histogram (or another "creator" object) 963 zaxis -- If set to True (default False), create a TGraph2D with z axis showing the cut value (recommended drawStyle 'pcolz') 971 """String representation, returns the name""" 975 """Create and return the histogram from a TDirectory""" 978 if xhisto
is None or yhisto
is None:
989 for i
in xrange(1, xhisto.GetNbinsX()+1):
990 x.append(xhisto.GetBinContent(i))
991 xerrup.append(xhisto.GetBinError(i))
992 xerrdown.append(xhisto.GetBinError(i))
994 y.append(yhisto.GetBinContent(i))
995 yerrup.append(yhisto.GetBinError(i))
996 yerrdown.append(yhisto.GetBinError(i))
998 z.append(xhisto.GetXaxis().GetBinUpEdge(i))
1001 if x.count(0.0) == len(x)
or y.count(0.0) == len(y):
1004 arr =
lambda v: array.array(
"d", v)
1007 gr = ROOT.TGraph2D(len(x), arr(x), arr(y), arr(z))
1009 gr = ROOT.TGraphAsymmErrors(len(x), arr(x), arr(y), arr(xerrdown), arr(xerrup), arr(yerrdown), arr(yerrup))
1015 _plotStylesColor = [4, 2, ROOT.kBlack, ROOT.kOrange+7, ROOT.kMagenta-3]
1016 _plotStylesMarker = [21, 20, 22, 34, 33]
1018 def _drawFrame(pad, bounds, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, suffix=""):
1019 """Function to draw a frame 1022 pad -- TPad to where the frame is drawn 1023 bounds -- List or 4-tuple for (xmin, ymin, xmax, ymax) 1026 xbinlabels -- Optional list of strings for x axis bin labels 1027 xbinlabelsize -- Optional number for the x axis bin label size 1028 xbinlabeloption -- Optional string for the x axis bin options (passed to ROOT.TH1.LabelsOption()) 1029 suffix -- Optional string for a postfix of the frame name 1031 if xbinlabels
is None:
1032 frame = pad.DrawFrame(*bounds)
1035 nbins = len(xbinlabels)
1036 frame = ROOT.TH1F(
"hframe"+suffix,
"", nbins, bounds[0], bounds[2])
1037 frame.SetBit(ROOT.TH1.kNoStats)
1038 frame.SetBit(ROOT.kCanDelete)
1039 frame.SetMinimum(bounds[1])
1040 frame.SetMaximum(bounds[3])
1041 frame.GetYaxis().SetLimits(bounds[1], bounds[3])
1044 xaxis = frame.GetXaxis()
1045 for i
in xrange(nbins):
1046 xaxis.SetBinLabel(i+1, xbinlabels[i])
1047 if xbinlabelsize
is not None:
1048 xaxis.SetLabelSize(xbinlabelsize)
1049 if xbinlabeloption
is not None:
1050 frame.LabelsOption(xbinlabeloption)
1055 """Class for creating and managing a frame for a simple, one-pad plot""" 1056 def __init__(self, pad, bounds, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None):
1069 self._frame.GetYaxis().SetTitleOffset(self._frame.GetYaxis().GetTitleOffset()*yoffsetFactor)
1070 self._frame.GetXaxis().SetTitleOffset(self._frame.GetXaxis().GetTitleOffset()*xoffsetFactor)
1074 self._pad.SetLogx(log)
1077 self._pad.SetLogy(log)
1080 self._pad.SetGridx(grid)
1083 self._pad.SetGridy(grid)
1086 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1089 self._frame.Draw(
"")
1092 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1095 self._frame.Draw(
"")
1098 self._frame.SetTitle(title)
1101 self._frame.GetXaxis().SetTitle(title)
1104 self._frame.GetXaxis().SetTitleSize(size)
1107 self._frame.GetXaxis().SetTitleOffset(offset)
1110 self._frame.GetXaxis().SetLabelSize(size)
1113 self._frame.GetYaxis().SetTitle(title)
1116 self._frame.GetYaxis().SetTitleSize(size)
1119 self._frame.GetYaxis().SetTitleOffset(offset)
1122 self._pad.RedrawAxis()
1125 """Class for creating and managing a frame for a ratio plot with two subpads""" 1126 def __init__(self, pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ratioYTitle=_ratioYTitle):
1129 if xbinlabels
is not None:
1136 self._frame.GetXaxis().SetLabelSize(0)
1137 self._frame.GetXaxis().SetTitleSize(0)
1139 yoffsetFactor = ratioFactor
1140 divisionPoint = 1-1/ratioFactor
1141 xoffsetFactor = 1/divisionPoint
1144 xoffsetFactor *= 0.6
1147 xoffsetFactor *= 1.5
1150 xoffsetFactor *= 2.3
1155 self._frame.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
1156 self._frameRatio.GetYaxis().SetLabelSize(
int(self._frameRatio.GetYaxis().GetLabelSize()*0.8))
1157 self._frameRatio.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
1158 self._frameRatio.GetXaxis().SetTitleOffset(self._frameRatio.GetXaxis().GetTitleOffset()*xoffsetFactor)
1160 self._frameRatio.GetYaxis().SetNdivisions(4, 5, 0)
1162 self._frameRatio.GetYaxis().SetTitle(ratioYTitle)
1165 self._pad.SetLogx(log)
1166 self._padRatio.SetLogx(log)
1169 self._pad.SetLogy(log)
1172 self._pad.SetGridx(grid)
1173 self._padRatio.SetGridx(grid)
1176 self._pad.SetGridy(grid)
1177 self._padRatio.SetGridy(grid)
1180 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1181 self._padRatio.SetLeftMargin(self._padRatio.GetLeftMargin()+adjust)
1184 self._frame.Draw(
"")
1186 self._frameRatio.Draw(
"")
1189 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1190 self._padRatio.SetRightMargin(self._padRatio.GetRightMargin()+adjust)
1193 self._frame.Draw(
"")
1195 self._frameRatio.Draw(
"")
1198 self._frame.SetTitle(title)
1201 self._frameRatio.GetXaxis().SetTitle(title)
1204 self._frameRatio.GetXaxis().SetTitleSize(size)
1207 self._frameRatio.GetXaxis().SetTitleOffset(offset)
1210 self._frameRatio.GetXaxis().SetLabelSize(size)
1213 self._frame.GetYaxis().SetTitle(title)
1216 self._frameRatio.GetYaxis().SetTitle(title)
1219 self._frame.GetYaxis().SetTitleSize(size)
1220 self._frameRatio.GetYaxis().SetTitleSize(size)
1223 self._frame.GetYaxis().SetTitleOffset(offset)
1224 self._frameRatio.GetYaxis().SetTitleOffset(offset)
1227 self._padRatio.RedrawAxis()
1228 self._pad.RedrawAxis()
1230 self._parentPad.cd()
1237 self.
_coverPad = ROOT.TPad(
"coverpad",
"coverpad", xmin, ymin, xmax, ymax)
1238 self._coverPad.SetBorderMode(0)
1239 self._coverPad.Draw()
1245 """Class for creating and managing a frame for a plot from TGraph2D""" 1246 def __init__(self, pad, bounds, histos, ratioOrig, ratioFactor):
1249 self.
_pad = pad.cd(1)
1253 (xlow, ylow, width, height) = (self._pad.GetXlowNDC(), self._pad.GetYlowNDC(), self._pad.GetWNDC(), self._pad.GetHNDC())
1257 bottomMargin = self._pad.GetBottomMargin()
1258 bottomMarginNew = ROOT.gStyle.GetPadBottomMargin()
1260 ylowNew = yup - (1-bottomMargin)/(1-bottomMarginNew) * (yup-ylow)
1261 topMarginNew = self._pad.GetTopMargin() * (yup-ylow)/(yup-ylowNew)
1263 self._pad.SetPad(xlow, ylowNew, xup, yup)
1264 self._pad.SetTopMargin(topMarginNew)
1265 self._pad.SetBottomMargin(bottomMarginNew)
1268 self._view.SetRange(bounds[0], bounds[1], 0, bounds[2], bounds[3], 20)
1270 self._view.ShowAxis()
1290 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1294 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1322 self._firstHisto.GetZaxis().SetTitle(title)
1325 self._firstHisto.GetZaxis().SetTitleOffset(offset)
1329 ROOT.TAxis3D.ToggleRulers()
1330 ROOT.TAxis3D.ToggleRulers()
1331 axis = ROOT.TAxis3D.GetPadAxis()
1332 axis.SetLabelColor(ROOT.kBlack);
1333 axis.SetAxisColor(ROOT.kBlack);
1338 if hasattr(self,
"_xtitle"):
1339 axis.GetXaxis().SetTitle(self.
_xtitle)
1340 if hasattr(self,
"_xtitlesize"):
1342 if hasattr(self,
"_xlabelsize"):
1343 axis.GetXaxis().SetLabelSize(self._labelsize)
1344 if hasattr(self,
"_ytitle"):
1345 axis.GetYaxis().SetTitle(self.
_ytitle)
1346 if hasattr(self,
"_ytitlesize"):
1348 if hasattr(self,
"_ytitleoffset"):
1352 """Abstraction on top of TLatex""" 1353 def __init__(self, x, y, text, size=None, bold=True, align="left", color=ROOT.kBlack, font=None):
1357 x -- X coordinate of the text (in NDC) 1358 y -- Y coordinate of the text (in NDC) 1359 text -- String to draw 1360 size -- Size of text (None for the default value, taken from gStyle) 1361 bold -- Should the text be bold? 1362 align -- Alignment of text (left, center, right) 1363 color -- Color of the text 1364 font -- Specify font explicitly 1373 self._l.SetTextFont(self._l.GetTextFont()-20)
1374 if font
is not None:
1375 self._l.SetTextFont(font)
1376 if size
is not None:
1377 self._l.SetTextSize(size)
1378 if isinstance(align, basestring):
1379 if align.lower() ==
"left":
1380 self._l.SetTextAlign(11)
1381 elif align.lower() ==
"center":
1382 self._l.SetTextAlign(21)
1383 elif align.lower() ==
"right":
1384 self._l.SetTextAlign(31)
1386 raise Exception(
"Error: Invalid option '%s' for text alignment! Options are: 'left', 'center', 'right'."%align)
1388 self._l.SetTextAlign(align)
1389 self._l.SetTextColor(color)
1392 """Draw the text to the current TPad. 1395 options -- For interface compatibility, ignored 1397 Provides interface compatible with ROOT's drawable objects. 1399 self._l.DrawLatex(self.
_x, self.
_y, self.
_text)
1403 """Class for drawing text and a background box.""" 1404 def __init__(self, xmin, ymin, xmax, ymax, lineheight=0.04, fillColor=ROOT.kWhite, transparent=True, **kwargs):
1408 xmin -- X min coordinate of the box (NDC) 1409 ymin -- Y min coordinate of the box (NDC) (if None, deduced automatically) 1410 xmax -- X max coordinate of the box (NDC) 1411 ymax -- Y max coordinate of the box (NDC) 1412 lineheight -- Line height 1413 fillColor -- Fill color of the box 1414 transparent -- Should the box be transparent? (in practive the TPave is not created) 1416 Keyword arguments are forwarded to constructor of PlotText 1428 self._textArgs.update(kwargs)
1433 """Add text to current position""" 1440 def move(self, dx=0, dy=0, dw=0, dh=0):
1441 """Move the box and the contained text objects 1444 dx -- Movement in x (positive is to right) 1445 dy -- Movement in y (positive is to up) 1446 dw -- Increment of width (negative to decrease width) 1447 dh -- Increment of height (negative to decrease height) 1449 dx and dy affect to both box and text objects, dw and dh 1450 affect the box only. 1454 if self.
_ymin is not None:
1459 if self.
_ymin is not None:
1467 """Draw the box and the text to the current TPad. 1470 options -- Forwarded to ROOT.TPave.Draw(), and the Draw() of the contained objects 1475 ymin = self.currenty - 0.01
1476 self.
_pave = ROOT.TPave(self.xmin, self.ymin, self.xmax, self.ymax, 0,
"NDC")
1477 self._pave.SetFillColor(self.fillColor)
1478 self._pave.Draw(options)
1484 if hasattr(src,
"GetLineColor")
and hasattr(dst,
"SetLineColor"):
1485 properties.extend([
"LineColor",
"LineStyle",
"LineWidth"])
1486 if hasattr(src,
"GetFillColor")
and hasattr(dst,
"SetFillColor"):
1487 properties.extend([
"FillColor",
"FillStyle"])
1488 if hasattr(src,
"GetMarkerColor")
and hasattr(dst,
"SetMarkerColor"):
1489 properties.extend([
"MarkerColor",
"MarkerSize",
"MarkerStyle"])
1491 for prop
in properties:
1492 getattr(dst,
"Set"+prop)(getattr(src,
"Get"+prop)())
1495 """Represents one plot, comparing one or more histograms.""" 1500 name -- String for name of the plot, or Efficiency object 1503 fallback -- Dictionary for specifying fallback (default None) 1504 outname -- String for an output name of the plot (default None for the same as 'name') 1505 title -- String for a title of the plot (default None) 1506 xtitle -- String for x axis title (default None) 1507 xtitlesize -- Float for x axis title size (default None) 1508 xtitleoffset -- Float for x axis title offset (default None) 1509 xlabelsize -- Float for x axis label size (default None) 1510 ytitle -- String for y axis title (default None) 1511 ytitlesize -- Float for y axis title size (default None) 1512 ytitleoffset -- Float for y axis title offset (default None) 1513 ztitle -- String for z axis title (default None) 1514 ztitleoffset -- Float for z axis title offset (default None) 1515 xmin -- Float for x axis minimum (default None, i.e. automatic) 1516 xmax -- Float for x axis maximum (default None, i.e. automatic) 1517 ymin -- Float for y axis minimum (default 0) 1518 ymax -- Float for y axis maximum (default None, i.e. automatic) 1519 xlog -- Bool for x axis log status (default False) 1520 ylog -- Bool for y axis log status (default False) 1521 xgrid -- Bool for x axis grid status (default True) 1522 ygrid -- Bool for y axis grid status (default True) 1523 stat -- Draw stat box? (default False) 1524 fit -- Do gaussian fit? (default False) 1525 statx -- Stat box x coordinate (default 0.65) 1526 staty -- Stat box y coordinate (default 0.8) 1527 statyadjust -- List of floats for stat box y coordinate adjustments (default None) 1528 normalizeToUnitArea -- Normalize histograms to unit area? (default False) 1529 normalizeToNumberOfEvents -- Normalize histograms to number of events? If yes, the PlotFolder needs 'numberOfEventsHistogram' set to a histogram filled once per event (default False) 1530 profileX -- Take histograms via ProfileX()? (default False) 1531 fitSlicesY -- Take histograms via FitSlicesY() (default False) 1532 rebinX -- rebin x axis (default None) 1533 scale -- Scale histograms by a number (default None) 1534 xbinlabels -- List of x axis bin labels (if given, default None) 1535 xbinlabelsize -- Size of x axis bin labels (default None) 1536 xbinlabeloption -- Option string for x axis bin labels (default None) 1537 removeEmptyBins -- Bool for removing empty bins, but only if histogram has bin labels (default False) 1538 printBins -- Bool for printing bin values, but only if histogram has bin labels (default False) 1539 drawStyle -- If "hist", draw as line instead of points (default None) 1540 drawCommand -- Deliver this to Draw() (default: None for same as drawStyle) 1541 lineWidth -- If drawStyle=="hist", the width of line (default 2) 1542 legendDx -- Float for moving TLegend in x direction for separate=True (default None) 1543 legendDy -- Float for moving TLegend in y direction for separate=True (default None) 1544 legendDw -- Float for changing TLegend width for separate=True (default None) 1545 legendDh -- Float for changing TLegend height for separate=True (default None) 1546 legend -- Bool to enable/disable legend (default True) 1547 adjustMarginRight -- Float for adjusting right margin (default None) 1548 ratio -- Possibility to disable ratio for this particular plot (default None) 1549 ratioYmin -- Float for y axis minimum in ratio pad (default: list of values) 1550 ratioYmax -- Float for y axis maximum in ratio pad (default: list of values) 1551 ratioFit -- Fit straight line in ratio? (default None) 1552 ratioUncertainty -- Plot uncertainties on ratio? (default True) 1553 ratioCoverageXrange -- Range of x axis values (xmin,xmax) to limit the automatic ratio y axis range calculation to (default None for disabled) 1554 histogramModifier -- Function to be called in create() to modify the histograms (default None) 1558 def _set(attr, default):
1559 setattr(self,
"_"+attr, kwargs.get(attr, default))
1561 _set(
"fallback",
None)
1562 _set(
"outname",
None)
1565 _set(
"xtitle",
None)
1566 _set(
"xtitlesize",
None)
1567 _set(
"xtitleoffset",
None)
1568 _set(
"xlabelsize",
None)
1569 _set(
"ytitle",
None)
1570 _set(
"ytitlesize",
None)
1571 _set(
"ytitleoffset",
None)
1572 _set(
"ztitle",
None)
1573 _set(
"ztitleoffset",
None)
1590 _set(
"statyadjust",
None)
1592 _set(
"normalizeToUnitArea",
False)
1593 _set(
"normalizeToNumberOfEvents",
False)
1594 _set(
"profileX",
False)
1595 _set(
"fitSlicesY",
False)
1596 _set(
"rebinX",
None)
1599 _set(
"xbinlabels",
None)
1600 _set(
"xbinlabelsize",
None)
1601 _set(
"xbinlabeloption",
None)
1602 _set(
"removeEmptyBins",
False)
1603 _set(
"printBins",
False)
1605 _set(
"drawStyle",
"EP")
1606 _set(
"drawCommand",
None)
1607 _set(
"lineWidth", 2)
1609 _set(
"legendDx",
None)
1610 _set(
"legendDy",
None)
1611 _set(
"legendDw",
None)
1612 _set(
"legendDh",
None)
1613 _set(
"legend",
True)
1615 _set(
"adjustMarginRight",
None)
1618 _set(
"ratioYmin", [0, 0.2, 0.5, 0.7, 0.8, 0.9, 0.95])
1619 _set(
"ratioYmax", [1.05, 1.1, 1.2, 1.3, 1.5, 1.8, 2, 2.5, 3, 4, 5])
1620 _set(
"ratioFit",
None)
1621 _set(
"ratioUncertainty",
True)
1622 _set(
"ratioCoverageXrange",
None)
1624 _set(
"histogramModifier",
None)
1629 for name, value
in kwargs.iteritems():
1630 if not hasattr(self,
"_"+name):
1631 raise Exception(
"No attribute '%s'" % name)
1632 setattr(self,
"_"+name, value)
1636 raise Exception(
"Plot can be cloned only before histograms have been created")
1637 cl = copy.copy(self)
1638 cl.setProperties(**kwargs)
1642 """Return number of existing histograms.""" 1646 """Return true if there are no histograms created for the plot""" 1651 if isinstance(h, ROOT.TGraph2D):
1656 if self._ratio
is None:
1658 return ratio
and self._ratio
1661 if self._outname
is not None:
1662 return self._outname
1663 if isinstance(self.
_name, list):
1669 """Return true if the ratio uncertainty should be drawn""" 1670 return self._ratioUncertainty
1673 """Create one histogram from a TDirectory.""" 1678 if isinstance(name, list):
1682 if h
is not None and self._normalizeToNumberOfEvents
and nevents
is not None and nevents != 0:
1683 h.Scale(1.0/nevents)
1686 def create(self, tdirNEvents, requireAllHistograms=False):
1687 """Create histograms from list of TDirectories""" 1688 self.
_histograms = [self.
_createOne(self.
_name, i, tdirNEvent[0], tdirNEvent[1])
for i, tdirNEvent
in enumerate(tdirNEvents)]
1690 if self._fallback
is not None:
1694 self.
_histograms[i] = self.
_createOne(self._fallback[
"name"], i, tdirNEvents[i][0], tdirNEvents[i][1])
1695 profileX[i] = self._fallback.get(
"profileX", self._profileX)
1697 if self._histogramModifier
is not None:
1701 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)))
1706 def _modifyHisto(th1, profileX):
1711 th1 = th1.ProfileX()
1713 if self._fitSlicesY:
1714 ROOT.TH1.AddDirectory(
True)
1716 th1 = ROOT.gDirectory.Get(th1.GetName()+
"_2")
1717 th1.SetDirectory(
None)
1719 ROOT.TH1.AddDirectory(
False)
1721 if self._title
is not None:
1722 th1.SetTitle(self._title)
1724 if self._scale
is not None:
1725 th1.Scale(self._scale)
1729 if self._fallback
is not None:
1733 if requireAllHistograms
and None in self.
_histograms:
1737 """Set stats box.""" 1740 if h
is not None and hasattr(h,
"SetStats"):
1744 def _doStats(h, col, dy):
1749 if self._fit
and h.GetEntries() > 0.5:
1751 f = h.GetListOfFunctions().FindObject(
"gaus")
1759 st = h.GetListOfFunctions().FindObject(
"stats")
1763 st.SetX1NDC(startingX)
1764 st.SetX2NDC(startingX+0.3)
1765 st.SetY1NDC(startingY+dy)
1766 st.SetY2NDC(startingY+dy+0.15)
1767 st.SetTextColor(col)
1770 for i, h
in enumerate(histos):
1771 if self._statyadjust
is not None and i < len(self._statyadjust):
1772 dy += self._statyadjust[i]
1774 _doStats(h, _plotStylesColor[i], dy)
1778 """Normalise histograms to unit area""" 1786 if h.GetSumw2().fN <= 0:
1790 def draw(self, pad, ratio, ratioFactor, nrows):
1791 """Draw the histograms using values for a given algorithm.""" 1802 if self._normalizeToUnitArea:
1805 if self._rebinX
is not None:
1807 h.Rebin(self._rebinX)
1809 def _styleMarker(h, msty, col):
1810 h.SetMarkerStyle(msty)
1811 h.SetMarkerColor(col)
1812 h.SetMarkerSize(0.7)
1816 def _styleHist(h, msty, col):
1817 _styleMarker(h, msty, col)
1819 h.SetLineWidth(self._lineWidth)
1822 style = _styleMarker
1823 if "hist" in self._drawStyle.lower():
1826 if "l" in self._drawStyle.lower():
1834 style(h, _plotStylesMarker[i], _plotStylesColor[i])
1836 if len(histos) == 0:
1838 print "No histograms for plot {name}".
format(name=self.
getName())
1843 histosHaveBinLabels = len(histos[0].GetXaxis().GetBinLabel(1)) > 0
1844 xbinlabels = self._xbinlabels
1845 if xbinlabels
is None:
1846 if histosHaveBinLabels:
1847 xbinlabels = [histos[0].GetXaxis().GetBinLabel(i)
for i
in xrange(1, histos[0].GetNbinsX()+1)]
1849 for h
in histos[1:]:
1850 labels = [h.GetXaxis().GetBinLabel(i)
for i
in xrange(1, h.GetNbinsX()+1)]
1851 diff = difflib.unified_diff(xbinlabels, labels, n=
max(len(xbinlabels), len(labels)))
1855 if item[:2] ==
"@@":
1858 operation.append(item[0])
1860 if lab
in xbinlabels:
1862 ind = xbinlabels.index(lab)
1863 if operation[ind] ==
"-" and operation[-1] ==
"+":
1864 xbinlabels.remove(lab)
1866 elif operation[ind] ==
"+" and operation[-1] ==
"-":
1870 raise Exception(
"This should never happen")
1871 xbinlabels.append(lab)
1874 if len(xbinlabels) == 0:
1879 h_new = h.Clone(h.GetName()+
"_xbinlabels")
1880 h_new.SetBins(len(xbinlabels), h.GetBinLowEdge(1), h.GetBinLowEdge(1)+len(xbinlabels))
1881 for i, label
in enumerate(xbinlabels):
1882 bin = h.GetXaxis().FindFixBin(label)
1884 h_new.SetBinContent(i+1, h.GetBinContent(bin))
1885 h_new.SetBinError(i+1, h.GetBinError(bin))
1887 h_new.SetBinContent(i+1, 0)
1888 h_new.SetBinError(i+1, 0)
1889 histos_new.append(h_new)
1894 if self._removeEmptyBins
and histosHaveBinLabels:
1897 binsToRemove = set()
1898 for b
in xrange(1, histos[0].GetNbinsX()+1):
1901 if h.GetBinContent(b) > 0:
1907 if len(binsToRemove) > 0:
1910 for i
in xrange(len(xbinlabels)):
1911 if (i+1)
not in binsToRemove:
1912 xbinlab_new.append(xbinlabels[i])
1913 xbinlabels = xbinlab_new
1919 for b
in xrange(1, h.GetNbinsX()+1):
1920 if b
not in binsToRemove:
1921 values.append( (h.GetXaxis().GetBinLabel(b), h.GetBinContent(b), h.GetBinError(b)) )
1924 h_new = h.Clone(h.GetName()+
"_empty")
1925 h_new.SetBins(len(values), h.GetBinLowEdge(1), h.GetBinLowEdge(1)+len(values))
1926 for b, (l, v, e)
in enumerate(values):
1927 h_new.GetXaxis().SetBinLabel(b+1, l)
1928 h_new.SetBinContent(b+1, v)
1929 h_new.SetBinError(b+1, e)
1931 histos_new.append(h_new)
1935 if len(histos) == 0:
1937 print "No histograms with non-empty bins for plot {name}".
format(name=self.
getName())
1940 if self._printBins
and histosHaveBinLabels:
1941 print "####################" 1943 width =
max([len(l)
for l
in xbinlabels])
1944 tmp =
"%%-%ds " % width
1945 for b
in xrange(1, histos[0].GetNbinsX()+1):
1946 s = tmp % xbinlabels[b-1]
1948 s +=
"%.3f " % h.GetBinContent(b)
1953 xmin=self._xmin, xmax=self._xmax,
1954 ymin=self._ymin, ymax=self._ymax)
1962 ratioHistos =
filter(
lambda h: h
is not None, [r.getRatio()
for r
in self.
_ratios[1:]])
1964 if len(ratioHistos) > 0:
1965 ratioBoundsY =
_findBoundsY(ratioHistos, ylog=
False, ymin=self._ratioYmin, ymax=self._ratioYmax, coverage=0.68, coverageRange=self._ratioCoverageXrange)
1967 ratioBoundsY = (0.9, 1,1)
1969 if self._ratioFit
is not None:
1970 for i, rh
in enumerate(ratioHistos):
1971 tf_line = ROOT.TF1(
"line%d"%i,
"[0]+x*[1]")
1972 tf_line.SetRange(self._ratioFit[
"rangemin"], self._ratioFit[
"rangemax"])
1973 fitres = rh.Fit(tf_line,
"RINSQ")
1974 tf_line.SetLineColor(rh.GetMarkerColor())
1975 tf_line.SetLineWidth(2)
1976 self._ratioAdditional.append(tf_line)
1977 box =
PlotTextBox(xmin=self._ratioFit.get(
"boxXmin", 0.14), ymin=
None,
1978 xmax=self._ratioFit.get(
"boxXmax", 0.35), ymax=self._ratioFit.get(
"boxYmax", 0.09),
1979 color=rh.GetMarkerColor(), font=43, size=11, lineheight=0.02)
1980 box.move(dx=(box.width()+0.01)*i)
1983 box.addText(
"Const: %.4f#pm%.4f" % (fitres.Parameter(0), fitres.ParError(0)))
1984 box.addText(
"Slope: %.4f#pm%.4f" % (fitres.Parameter(1), fitres.ParError(1)))
1985 self._mainAdditional.append(box)
1995 self.
_setStats(histos, self._statx, self._staty)
1999 frame =
FrameTGraph2D(pad, bounds, histos, ratioOrig, ratioFactor)
2002 ratioBounds = (bounds[0], ratioBoundsY[0], bounds[2], ratioBoundsY[1])
2003 frame =
FrameRatio(pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption)
2005 frame =
Frame(pad, bounds, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption)
2008 frame.setLogx(self._xlog)
2009 frame.setLogy(self._ylog)
2010 frame.setGridx(self._xgrid)
2011 frame.setGridy(self._ygrid)
2016 if self._drawStyle
is not None:
2017 ds = self._drawStyle
2018 if self._drawCommand
is not None:
2019 ds = self._drawCommand
2024 frame.setTitle(histos[0].GetTitle())
2025 if self._xtitle
is not None:
2026 frame.setXTitle(self._xtitle)
2027 if self._xtitlesize
is not None:
2028 frame.setXTitleSize(self._xtitlesize)
2029 if self._xtitleoffset
is not None:
2030 frame.setXTitleOffset(self._xtitleoffset)
2031 if self._xlabelsize
is not None:
2032 frame.setXLabelSize(self._xlabelsize)
2033 if self._ytitle
is not None:
2034 frame.setYTitle(self._ytitle)
2035 if self._ytitlesize
is not None:
2036 frame.setYTitleSize(self._ytitlesize)
2037 if self._ytitleoffset
is not None:
2038 frame.setYTitleOffset(self._ytitleoffset)
2039 if self._ztitle
is not None:
2040 frame.setZTitle(self._ztitle)
2041 if self._ztitleoffset
is not None:
2042 frame.setZTitleOffset(self._ztitleoffset)
2043 if self._adjustMarginRight
is not None:
2044 frame.adjustMarginRight(self._adjustMarginRight)
2046 frame.adjustMarginLeft(0.03)
2047 frame.adjustMarginRight(0.08)
2060 if ratio
and len(histos) > 0:
2061 frame._padRatio.cd()
2062 firstRatio = self.
_ratios[0].getRatio()
2063 if self._ratioUncertainty
and firstRatio
is not None:
2064 firstRatio.SetFillStyle(1001)
2065 firstRatio.SetFillColor(ROOT.kGray)
2066 firstRatio.SetLineColor(ROOT.kGray)
2067 firstRatio.SetMarkerColor(ROOT.kGray)
2068 firstRatio.SetMarkerSize(0)
2070 frame._padRatio.RedrawAxis(
"G")
2081 """Add histograms to a legend. 2085 legendLabels -- List of strings for the legend labels 2087 first = denomUncertainty
2094 self._forLegend.SetFillStyle(1001)
2095 self._forLegend.SetFillColor(ROOT.kGray)
2096 entry = legend.AddEntry(self.
_forLegend, label,
"lpf")
2099 legend.AddEntry(h, label,
"LP")
2102 """Group of plots, results a TCanvas""" 2107 name -- String for name of the TCanvas, used also as the basename of the picture files 2108 plots -- List of Plot objects 2111 ncols -- Number of columns (default 2) 2112 legendDx -- Float for moving TLegend in x direction (default None) 2113 legendDy -- Float for moving TLegend in y direction (default None) 2114 legendDw -- Float for changing TLegend width (default None) 2115 legendDh -- Float for changing TLegend height (default None) 2116 legend -- Bool for disabling legend (default True for legend being enabled) 2117 overrideLegendLabels -- List of strings for legend labels, if given, these are used instead of the ones coming from Plotter (default None) 2118 onlyForPileup -- Plots this group only for pileup samples 2123 def _set(attr, default):
2124 setattr(self,
"_"+attr, kwargs.get(attr, default))
2128 _set(
"legendDx",
None)
2129 _set(
"legendDy",
None)
2130 _set(
"legendDw",
None)
2131 _set(
"legendDh",
None)
2132 _set(
"legend",
True)
2134 _set(
"overrideLegendLabels",
None)
2136 _set(
"onlyForPileup",
False)
2141 for name, value
in kwargs.iteritems():
2142 if not hasattr(self,
"_"+name):
2143 raise Exception(
"No attribute '%s'" % name)
2144 setattr(self,
"_"+name, value)
2153 for i, plot
in enumerate(self.
_plots):
2154 if plot.getName() == name:
2157 raise Exception(
"Did not find Plot '%s' from PlotGroup '%s'" % (name, self.
_name))
2163 self._plots.append(plot)
2167 if plot.getName() == name:
2169 raise Exception(
"No Plot named '%s'" % name)
2172 """Return True if the PlotGroup is intended only for pileup samples""" 2173 return self._onlyForPileup
2175 def create(self, tdirectoryNEvents, requireAllHistograms=False):
2176 """Create histograms from a list of TDirectories. 2179 tdirectoryNEvents -- List of (TDirectory, nevents) pairs 2180 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False) 2183 plot.create(tdirectoryNEvents, requireAllHistograms)
2185 def draw(self, legendLabels, prefix=None, separate=False, saveFormat=".pdf", ratio=True):
2186 """Draw the histograms using values for a given algorithm. 2189 legendLabels -- List of strings for legend labels (corresponding to the tdirectories in create()) 2190 prefix -- Optional string for file name prefix (default None) 2191 separate -- Save the plots of a group to separate files instead of a file per group (default False) 2192 saveFormat -- String specifying the plot format (default '.pdf') 2193 ratio -- Add ratio to the plot (default True) 2196 if self._overrideLegendLabels
is not None:
2197 legendLabels = self._overrideLegendLabels
2200 onlyEmptyPlots =
True 2202 if not plot.isEmpty():
2203 onlyEmptyPlots =
False 2209 return self.
_drawSeparate(legendLabels, prefix, saveFormat, ratio)
2211 cwidth = 500*self._ncols
2212 nrows =
int((len(self.
_plots)+self._ncols-1)/self._ncols)
2213 cheight = 500 * nrows
2220 canvas.Divide(self._ncols, nrows)
2222 for i, plot
in enumerate(self.
_plots):
2223 pad = canvas.cd(i+1)
2227 for i, plot
in enumerate(self.
_plots):
2228 pad = canvas.cd(i+1)
2229 if not plot.isEmpty():
2234 if len(self.
_plots) <= 4:
2244 if self._legendDx
is not None:
2245 lx1 += self._legendDx
2246 lx2 += self._legendDx
2247 if self._legendDy
is not None:
2248 ly1 += self._legendDy
2249 ly2 += self._legendDy
2250 if self._legendDw
is not None:
2251 lx2 += self._legendDw
2252 if self._legendDh
is not None:
2253 ly1 -= self._legendDh
2254 plot =
max(self.
_plots, key=
lambda p: p.getNumberOfHistograms())
2255 denomUnc = sum([p.drawRatioUncertainty()
for p
in self.
_plots]) > 0
2256 legend = self.
_createLegend(plot, legendLabels, lx1, ly1, lx2, ly2,
2257 denomUncertainty=(ratio
and denomUnc))
2259 return self.
_save(canvas, saveFormat, prefix=prefix)
2262 """Internal method to do the drawing to separate files per Plot instead of a file per PlotGroup""" 2270 for c
in [canvas, canvasRatio]:
2271 c.SetTopMargin(0.05)
2272 c.SetBottomMargin(0.13)
2273 c.SetLeftMargin(0.16)
2274 c.SetRightMargin(0.05)
2287 ratioForThisPlot = plot.isRatio(ratio)
2289 if ratioForThisPlot:
2305 if plot._legendDx
is not None:
2306 lx1 += plot._legendDx
2307 lx2 += plot._legendDx
2308 if plot._legendDy
is not None:
2309 ly1 += plot._legendDy
2310 ly2 += plot._legendDy
2311 if plot._legendDw
is not None:
2312 lx2 += plot._legendDw
2313 if plot._legendDh
is not None:
2314 ly1 -= plot._legendDh
2317 legend = self.
_createLegend(plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.03,
2318 denomUncertainty=(ratioForThisPlot
and plot.drawRatioUncertainty))
2320 ret.extend(self.
_save(c, saveFormat, prefix=prefix, postfix=
"_"+plot.getName(), single=
True))
2324 """Internal method to set divide a pad to two for ratio plots""" 2327 def _createLegend(self, plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.016, denomUncertainty=True):
2328 if not self._legend:
2331 l = ROOT.TLegend(lx1, ly1, lx2, ly2)
2332 l.SetTextSize(textSize)
2339 plot.addToLegend(l, legendLabels, denomUncertainty)
2343 def _save(self, canvas, saveFormat, prefix=None, postfix=None, single=False):
2346 if prefix
is not None:
2348 if postfix
is not None:
2352 backup = ROOT.gErrorIgnoreLevel
2353 ROOT.gErrorIgnoreLevel = ROOT.kWarning
2354 canvas.SaveAs(name+saveFormat)
2356 ROOT.gErrorIgnoreLevel = backup
2360 canvas.SetLogx(
False)
2361 canvas.SetLogy(
False)
2365 return [name+saveFormat]
2368 """Represents a collection of PlotGroups, produced from a single folder in a DQM file""" 2373 plotGroups -- List of PlotGroup objects 2376 loopSubFolders -- Should the subfolders be looped over? (default: True) 2377 onlyForPileup -- Plots this folder only for pileup samples 2378 onlyForElectron -- Plots this folder only for electron samples 2379 onlyForConversion -- Plots this folder only for conversion samples 2380 purpose -- html.PlotPurpose member class for the purpose of the folder, used for grouping of the plots to the HTML pages 2381 page -- Optional string for the page in HTML generatin 2382 section -- Optional string for the section within a page in HTML generation 2383 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". 2395 raise Exception(
"Got unexpected keyword arguments: "+
",".
join(kwargs.keys()))
2398 """Return True if the PlotGroups of this folder should be applied to the all subfolders""" 2402 """Return True if the folder is intended only for pileup samples""" 2424 self._plotGroups.append(plotGroup)
2434 if pg.getName() == name:
2436 raise Exception(
"No PlotGroup named '%s'" % name)
2438 def create(self, dirsNEvents, labels, isPileupSample=True, requireAllHistograms=False):
2439 """Create histograms from a list of TFiles. 2442 dirsNEvents -- List of (TDirectory, nevents) pairs 2443 labels -- List of strings for legend labels corresponding the files 2444 isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup) 2445 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False) 2448 if len(dirsNEvents) != len(labels):
2449 raise Exception(
"len(dirsNEvents) should be len(labels), now they are %d and %d" % (len(dirsNEvents), len(labels)))
2454 if pg.onlyForPileup()
and not isPileupSample:
2456 pg.create(dirsNEvents, requireAllHistograms)
2458 def draw(self, prefix=None, separate=False, saveFormat=".pdf", ratio=True):
2459 """Draw and save all plots using settings of a given algorithm. 2462 prefix -- Optional string for file name prefix (default None) 2463 separate -- Save the plots of a group to separate files instead of a file per group (default False) 2464 saveFormat -- String specifying the plot format (default '.pdf') 2465 ratio -- Add ratio to the plot (default True) 2470 ret.extend(pg.draw(self.
_labels, prefix=prefix, separate=separate, saveFormat=saveFormat, ratio=ratio))
2476 """Method called to (possibly) translate a subfolder name to more 'readable' form 2478 The implementation in this (base) class just returns the 2479 argument. The idea is that a deriving class might want to do 2480 something more complex (like trackingPlots.TrackingPlotFolder 2483 return dqmSubFolderName
2486 """Iterate over possible selections name (used in output directory name and legend) from the name of PlotterFolder, and a return value of translateSubFolder""" 2488 if plotFolderName !=
"":
2489 ret +=
"_"+plotFolderName
2490 if translatedDqmSubFolder
is not None:
2491 ret +=
"_"+translatedDqmSubFolder
2495 """Return True if this subfolder should be processed 2498 limitOnlyTo -- List/set/similar containing the translatedDqmSubFolder 2499 translatedDqmSubFolder -- Return value of translateSubFolder 2501 return translatedDqmSubFolder
in limitOnlyTo
2504 """Class to hold the original name and a 'translated' name of a subfolder in the DQM ROOT file""" 2510 """Equality is defined by the 'translated' name""" 2514 """Plotter for one DQM folder. 2516 This class is supposed to be instantiated by the Plotter class (or 2517 PlotterItem, to be more specific), and not used directly by the 2520 def __init__(self, name, possibleDqmFolders, dqmSubFolders, plotFolder, fallbackNames, fallbackDqmSubFolders, tableCreators):
2525 name -- Name of the folder (is used in the output directory naming) 2526 possibleDqmFolders -- List of strings for possible directories of histograms in TFiles 2527 dqmSubFolders -- List of lists of strings for list of subfolders per input file, or None if no subfolders 2528 plotFolder -- PlotFolder object 2529 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. 2530 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. 2531 tableCreators -- List of PlotterTableItem objects for tables to be created from this folder 2537 if dqmSubFolders
is None:
2543 for sf_list
in dqmSubFolders:
2545 sf_translated = self._plotFolder.translateSubFolder(sf)
2546 if sf_translated
is not None and not sf_translated
in subfolders:
2547 subfolders[sf_translated] =
DQMSubFolder(sf, sf_translated)
2550 self._dqmSubFolders.sort(key=
lambda sf: sf.subfolder)
2560 return self._plotFolder.getPurpose()
2563 return self._plotFolder.getPage()
2566 return self._plotFolder.getSection()
2569 return self._plotFolder.onlyForPileup()
2572 return self._plotFolder.onlyForElectron()
2575 return self._plotFolder.onlyForConversion()
2581 """Get list of subfolders, possibly limiting to some of them. 2584 limitOnlyTo -- Object depending on the PlotFolder type for limiting the set of subfolders to be processed 2590 if limitOnlyTo
is None:
2593 return filter(
lambda s: self._plotFolder.limitSubFolder(limitOnlyTo, s.translated), self.
_dqmSubFolders)
2599 """Get a generator for the 'selection name', looping over the name and fallbackNames""" 2601 for selname
in self._plotFolder.iterSelectionName(name, dqmSubFolder.translated
if dqmSubFolder
is not None else None):
2607 def create(self, files, labels, dqmSubFolder, isPileupSample=True, requireAllHistograms=False):
2608 """Create histograms from a list of TFiles. 2610 files -- List of TFiles 2611 labels -- List of strings for legend labels corresponding the files 2612 dqmSubFolder -- DQMSubFolder object for a subfolder (or None for no subfolder) 2613 isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup) 2614 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False) 2617 subfolder = dqmSubFolder.subfolder
if dqmSubFolder
is not None else None 2618 neventsHisto = self._plotFolder.getNumberOfEventsHistogram()
2626 fallback = fallbackFunc(subfolder)
2627 if fallback
is not None:
2631 d = GetDirectoryCode.codesToNone(ret)
2633 if neventsHisto
is not None and tfile
is not None:
2635 if hnev
is not None:
2636 nev = hnev.GetEntries()
2637 dirsNEvents.append( (d, nev) )
2639 self._plotFolder.create(dirsNEvents, labels, isPileupSample, requireAllHistograms)
2642 """Draw and save all plots using settings of a given algorithm.""" 2643 return self._plotFolder.draw(*args, **kwargs)
2647 """Instance of plotter that knows the directory content, holds many folders.""" 2654 if limitSubFoldersOnlyTo
is not None:
2655 limitOnlyTo = limitSubFoldersOnlyTo.get(plotterFolder.getName(),
None)
2657 for dqmSubFolder
in plotterFolder.getDQMSubFolders(limitOnlyTo=limitOnlyTo):
2658 yield plotterFolder, dqmSubFolder
2662 def __init__(self, name, possibleDirs, plotFolder, fallbackNames=[], fallbackDqmSubFolders=[]):
2666 name -- Name of the folder (is used in the output directory naming) 2667 possibleDirs -- List of strings for possible directories of histograms in TFiles 2668 plotFolder -- PlotFolder object 2671 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. 2672 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. 2688 self._tableCreators.append(tc)
2691 """Read available subfolders from the files 2694 files -- List of strings for paths to files, or list of TFiles 2696 For each file, loop over 'possibleDirs', and read the 2697 subfolders of first one that exists. 2699 Returns a PlotterFolder if at least one file for which one of 2700 'possibleDirs' exists. Otherwise, return None to signal that 2701 there is nothing available for this PlotFolder. 2704 if self._plotFolder.loopSubFolders():
2706 possibleDirFound =
False 2711 isOpenFile = isinstance(fname, ROOT.TFile)
2715 tfile = ROOT.TFile.Open(fname)
2719 possibleDirFound =
True 2720 if subFolders
is not None:
2722 for key
in d.GetListOfKeys():
2723 if isinstance(key.ReadObj(), ROOT.TDirectory):
2724 subf.append(key.GetName())
2725 subFolders.append(subf)
2731 if not possibleDirFound:
2741 def create(self, openFiles, legendLabels, dqmSubFolder):
2742 if isinstance(dqmSubFolder, list):
2743 if len(dqmSubFolder) != len(openFiles):
2744 raise Exception(
"When dqmSubFolder is a list, len(dqmSubFolder) should be len(openFiles), now they are %d and %d" % (len(dqmSubFolder), len(openFiles)))
2746 dqmSubFolder = [dqmSubFolder]*len(openFiles)
2747 dqmSubFolder = [sf.subfolder
if sf
is not None else None for sf
in dqmSubFolder]
2750 for f, sf
in zip(openFiles, dqmSubFolder):
2753 if tdir
is not None:
2754 data = self._tableCreator.create(tdir)
2769 for i
in xrange(len(tbl)):
2771 tbl[i] = [
None]*colLen
2773 return html.Table(columnHeaders=legendLabels, rowHeaders=self._tableCreator.headers(), table=tbl,
2774 purpose=self._tableCreator.getPurpose(), page=self._tableCreator.getPage(), section=self._tableCreator.getSection(dqmSubFolder[0]))
2777 """Contains PlotFolders, i.e. the information what plots to do, and creates a helper object to actually produce the plots.""" 2781 ROOT.TH1.AddDirectory(
False)
2784 """Append a plot folder to the plotter. 2786 All arguments are forwarded to the constructor of PlotterItem. 2791 for plotterItem
in self.
_plots:
2792 if plotterItem.getName() == attachToFolder:
2795 raise Exception(
"Did not find plot folder '%s' when trying to attach a table creator to it" % attachToFolder)
2798 """Remove all plot folders and tables""" 2802 return [item.getName()
for item
in self.
_plots]
2805 return [item.getPlotFolder()
for item
in self.
_plots]
2809 if item.getName() == name:
2810 return item.getPlotFolder()
2811 raise Exception(
"No PlotFolder named '%s'" % name)
2814 """Returns PlotterInstance object, which knows how exactly to produce the plots for these files"""
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 _getYmax(obj, limitToNonZeroContent=False)
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 __init__(self, pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ratioYTitle=_ratioYTitle)
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 _getYmin(obj, limitToNonZeroContent=False)
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 draw(name, histos, styles, legendLabels=[], xtitle=None, ytitle=None, drawOpt="HIST", legendDx=0, legendDy=0, legendDw=0, legendDh=0, xmin=None, ymin=0, xmax=None, ymax=None, xlog=False, ylog=False, xgrid=True, ygrid=True, ratio=False, ratioYmin=0.5, ratioYmax=1.5, ratioYTitle=plotting._ratioYTitle)
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)