7 ROOT.gROOT.SetBatch(
True)
8 ROOT.PyConfig.IgnoreCommandLineOptions =
True
15 obj = tdirectory.Get(name)
18 print "Did not find {obj} from {dir}".
format(obj=name, dir=tdirectory.GetPath())
23 if hasattr(nameOrCreator,
"create"):
24 return nameOrCreator.create(tdirectory)
39 """Get TDirectory from TFile."""
42 for pdf
in possibleDirs:
45 if subDir
is not None:
52 print "Did not find subdirectory '%s' from directory '%s' in file %s" % (subDir, pdf, tfile.GetName())
59 print "Did not find any of directories '%s' from file %s" % (
",".
join(possibleDirs), tfile.GetName())
68 backup = ROOT.gErrorIgnoreLevel
69 ROOT.gErrorIgnoreLevel = ROOT.kError
70 canvas = ROOT.TCanvas(name, name, width, height)
72 ROOT.gErrorIgnoreLevel = backup
76 def _getXmin(obj, limitToNonZeroContent=False):
77 if isinstance(obj, ROOT.TH1):
78 xaxis = obj.GetXaxis()
79 if limitToNonZeroContent:
80 for i
in xrange(1, obj.GetNbinsX()+1):
81 if obj.GetBinContent(i) != 0:
82 return xaxis.GetBinLowEdge(i)
83 return xaxis.GetBinLowEdge(xaxis.GetLast())
85 return xaxis.GetBinLowEdge(xaxis.GetFirst())
86 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
87 return min([obj.GetX()[i]
for i
in xrange(0, obj.GetN())])*0.9
88 raise Exception(
"Unsupported type %s" % str(obj))
90 def _getXmax(obj, limitToNonZeroContent=False):
91 if isinstance(obj, ROOT.TH1):
92 xaxis = obj.GetXaxis()
93 if limitToNonZeroContent:
94 for i
in xrange(obj.GetNbinsX(), 0, -1):
95 if obj.GetBinContent(i) != 0:
96 return xaxis.GetBinUpEdge(i)
97 return xaxis.GetBinUpEdge(xaxis.GetFirst())
99 return xaxis.GetBinUpEdge(xaxis.GetLast())
100 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
101 return max([obj.GetX()[i]
for i
in xrange(0, obj.GetN())])*1.02
102 raise Exception(
"Unsupported type %s" % str(obj))
105 if isinstance(obj, ROOT.TH1):
106 return obj.GetMinimum()
107 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
108 return min([obj.GetY()[i]
for i
in xrange(0, obj.GetN())])
109 raise Exception(
"Unsupported type %s" % str(obj))
112 if isinstance(obj, ROOT.TH1):
113 return obj.GetMaximum()
114 elif isinstance(obj, ROOT.TGraph)
or isinstance(obj, ROOT.TGraph2D):
115 return max([obj.GetY()[i]
for i
in xrange(0, obj.GetN())])
116 raise Exception(
"Unsupported type %s" % str(obj))
119 return max([th1.GetBinContent(i)+th1.GetBinError(i)
for i
in xrange(1, th1.GetNbinsX()+1)])
122 yvals =
filter(
lambda n: n>0, [th1.GetBinContent(i)
for i
in xrange(1, th1.GetNbinsX()+1)])
125 return th1.GetMinimum()
130 ind_min = len(yvals)-1 - int(len(yvals)*0.95)
131 min_val = yvals[ind_min]
132 for i
in xrange(0, ind_min):
133 if yvals[i] > 0.1*min_val:
138 def _findBounds(th1s, ylog, xmin=None, xmax=None, ymin=None, ymax=None):
139 """Find x-y axis boundaries encompassing a list of TH1s if the bounds are not given in arguments.
143 ylog -- Boolean indicating if y axis is in log scale or not (affects the automatic ymax)
146 xmin -- Minimum x value; if None, take the minimum of TH1s
147 xmax -- Maximum x value; if None, take the maximum of TH1s
148 xmin -- Minimum y value; if None, take the minimum of TH1s
149 xmax -- Maximum y value; if None, take the maximum of TH1s
161 if xmin
is None or xmax
is None or ymin
is None or ymax
is None or \
162 isinstance(xmin, list)
or isinstance(max, list)
or isinstance(ymin, list)
or isinstance(ymax, list):
168 xmins.append(
_getXmin(th1, limitToNonZeroContent=isinstance(xmin, list)))
169 xmaxs.append(
_getXmax(th1, limitToNonZeroContent=isinstance(xmax, list)))
170 if ylog
and isinstance(ymin, list):
179 elif isinstance(xmin, list):
181 xmins_below =
filter(
lambda x: x<=xm, xmin)
182 if len(xmins_below) == 0:
186 print "Histogram minimum x %f is below all given xmin values %s, using the smallest one" % (xm, str(xmin))
188 xmin =
max(xmins_below)
192 elif isinstance(xmax, list):
194 xmaxs_above =
filter(
lambda x: x>xm, xmax)
195 if len(xmaxs_above) == 0:
199 print "Histogram maximum x %f is above all given xmax values %s, using the maximum one" % (xm, str(xmax))
201 xmax =
min(xmaxs_above)
205 elif isinstance(ymin, list):
206 ym_unscaled =
min(ymins)
207 ym = y_scale_min(ym_unscaled)
208 ymins_below =
filter(
lambda y: y<=ym, ymin)
209 if len(ymins_below) == 0:
211 if ym_unscaled < ymin:
213 print "Histogram minimum y %f is below all given ymin values %s, using the smallest one" % (ym, str(ymin))
215 ymin =
max(ymins_below)
218 ymax = y_scale_max(
max(ymaxs))
219 elif isinstance(ymax, list):
220 ym_unscaled =
max(ymaxs)
221 ym = y_scale_max(ym_unscaled)
222 ymaxs_above =
filter(
lambda y: y>ym, ymax)
223 if len(ymaxs_above) == 0:
225 if ym_unscaled > ymax:
227 print "Histogram maximum y %f is above all given ymax values %s, using the maximum one" % (ym_unscaled, str(ymax))
229 ymax =
min(ymaxs_above)
232 th1.GetXaxis().SetRangeUser(xmin, xmax)
233 th1.GetYaxis().SetRangeUser(ymin, ymax)
235 return (xmin, ymin, xmax, ymax)
238 """Class for subtracting two histograms"""
243 name -- String for name of the resulting histogram (A-B)
244 nameA -- String for A histogram
245 nameB -- String for B histogram
248 title -- String for a title of the resulting histogram (default "")
250 Uncertainties are calculated with the assumption that B is a
251 subset of A, and the histograms contain event counts.
259 """String representation, returns the name"""
263 """Create and return the fake+duplicate histogram from a TDirectory"""
267 if not histoA
or not histoB:
270 ret = histoA.Clone(self.
_name)
273 for i
in xrange(1, histoA.GetNbinsX()+1):
274 val = histoA.GetBinContent(i)-histoB.GetBinContent(i)
275 ret.SetBinContent(i, val)
276 ret.SetBinError(i, math.sqrt(val))
281 """Class to calculate the fake+duplicate rate"""
282 def __init__(self, name, assoc, dup, reco, title=""):
286 name -- String for the name of the resulting efficiency histogram
287 assoc -- String for the name of the "associated" histogram
288 dup -- String for the name of the "duplicates" histogram
289 reco -- String for the name of the "reco" (denominator) histogram
292 title -- String for a title of the resulting histogram (default "")
294 The result is calculated as 1 - (assoc - dup) / reco
303 """String representation, returns the name"""
307 """Create and return the fake+duplicate histogram from a TDirectory"""
314 if not hassoc
or not hdup
or not hreco:
317 hfakedup = hreco.Clone(self.
_name)
318 hfakedup.SetTitle(self.
_title)
320 for i
in xrange(1, hassoc.GetNbinsX()+1):
321 numerVal = hassoc.GetBinContent(i) - hdup.GetBinContent(i)
322 denomVal = hreco.GetBinContent(i)
324 fakedupVal = (1 - numerVal / denomVal)
if denomVal != 0.0
else 0.0
325 errVal = math.sqrt(fakedupVal*(1-fakedupVal)/denomVal)
if (denomVal != 0.0
and fakedupVal <= 1)
else 0.0
327 hfakedup.SetBinContent(i, fakedupVal)
328 hfakedup.SetBinError(i, errVal)
333 """Class to create a histogram by aggregating bins of another histogram to a bin of the resulting histogram."""
334 def __init__(self, name, histoName, mapping, normalizeTo=None, scale=None, renameBin=None, ignoreMissingBins=False, minExistingBins=None):
338 name -- String for the name of the resulting histogram
339 histoName -- String for the name of the source histogram
340 mapping -- Dictionary or list for mapping the bins (see below)
343 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.
344 scale -- Optional number for scaling the histogram (passed to ROOT.TH1.Scale())
345 renameBin -- Optional function (string -> string) to rename the bins of the input histogram
347 Mapping structure (mapping):
349 Dictionary (you probably want to use collections.OrderedDict)
350 should be a mapping from the destination bin label to a list
351 of source bin labels ("dst -> [src]").
353 If the mapping is a list, it should only contain the source
354 bin labels. In this case, the resulting histogram contains a
355 subset of the bins of the source histogram.
367 """String representation, returns the name"""
371 """Create and return the histogram from a TDirectory"""
377 binValues = [
None]*len(self.
_mapping)
381 for i
in xrange(1, th1.GetNbinsX()+1):
382 binLabel = th1.GetXaxis().GetBinLabel(i)
385 values[binLabel] = (th1.GetBinContent(i), th1.GetBinError(i))
388 for i, label
in enumerate(self.
_mapping):
390 binValues[i] = values[label]
395 for i, (key, labels)
in enumerate(self._mapping.iteritems()):
401 sumTime += values[l][0]
402 sumErrorSq += values[l][1]**2
408 binValues[i] = (sumTime, math.sqrt(sumErrorSq))
415 for i, val
in enumerate(binValues):
418 binValues =
filter(
lambda v: v
is not None, binValues)
419 binLabels =
filter(
lambda v: v
is not None, binLabels)
420 if len(binValues) == 0:
423 result = ROOT.TH1F(self.
_name, self.
_name, len(binValues), 0, len(binValues))
424 for i, (value, label)
in enumerate(zip(binValues, binLabels)):
425 if value
is not None:
426 result.SetBinContent(i+1, value[0])
427 result.SetBinError(i+1, value[1])
428 result.GetXaxis().SetBinLabel(i+1, label)
433 print "Trying to normalize {name} to {binlabel}, which does not exist".
format(name=self.
_name, binlabel=self.
_normalizeTo)
435 value = th1.GetBinContent(bin)
437 result.Scale(1/value)
439 if self.
_scale is not None:
445 """Class to create a histogram by aggregaging integrals of another histoggrams."""
446 def __init__(self, name, mapping, normalizeTo=None):
450 name -- String for the name of the resulting histogram
451 mapping -- Dictionary for mapping the bin label to a histogram name
454 normalizeTo -- Optional string for a histogram. If given, all bins of the resulting histograqm are divided by the integral of this histogram.
461 """String representation, returns the name"""
465 """Create and return the histogram from a TDirectory"""
467 for key, histoName
in self._mapping.iteritems():
471 result.append( (key, th1.Integral(0, th1.GetNbinsX()+1)) )
475 res = ROOT.TH1F(self.
_name, self.
_name, len(result), 0, len(result))
477 for i, (name, count)
in enumerate(result):
478 res.SetBinContent(i+1, count)
479 res.GetXaxis().SetBinLabel(i+1, name)
485 scale = th1.Integral(0, th1.GetNbinsX()+1)
491 """Class to construct a ROC curve (e.g. efficiency vs. fake rate) from two histograms"""
492 def __init__(self, name, xhistoName, yhistoName, zaxis=False):
496 name -- String for the name of the resulting histogram
497 xhistoName -- String for the name of the x-axis histogram (or another "creator" object)
498 yhistoName -- String for the name of the y-axis histogram (or another "creator" object)
501 zaxis -- If set to True (default False), create a TGraph2D with z axis showing the cut value (recommended drawStyle 'pcolz')
509 """String representation, returns the name"""
513 """Create and return the histogram from a TDirectory"""
516 if xhisto
is None or yhisto
is None:
527 for i
in xrange(1, xhisto.GetNbinsX()+1):
528 x.append(xhisto.GetBinContent(i))
529 xerrup.append(xhisto.GetBinError(i))
530 xerrdown.append(xhisto.GetBinError(i))
532 y.append(yhisto.GetBinContent(i))
533 yerrup.append(yhisto.GetBinError(i))
534 yerrdown.append(yhisto.GetBinError(i))
536 z.append(xhisto.GetXaxis().GetBinUpEdge(i))
539 if x.count(0.0) == len(x)
or y.count(0.0) == len(y):
542 arr =
lambda v: array.array(
"d", v)
545 gr = ROOT.TGraph2D(len(x), arr(x), arr(y), arr(z))
547 gr = ROOT.TGraphAsymmErrors(len(x), arr(x), arr(y), arr(xerrdown), arr(xerrup), arr(yerrdown), arr(yerrup))
553 _plotStylesColor = [4, 2, ROOT.kBlack, ROOT.kOrange+7, ROOT.kMagenta-3]
554 _plotStylesMarker = [21, 20, 22, 34, 33]
556 def _drawFrame(pad, bounds, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, suffix=""):
557 """Function to draw a frame
560 pad -- TPad to where the frame is drawn
561 bounds -- List or 4-tuple for (xmin, ymin, xmax, ymax)
564 xbinlabels -- Optional list of strings for x axis bin labels
565 xbinlabelsize -- Optional number for the x axis bin label size
566 xbinlabeloption -- Optional string for the x axis bin options (passed to ROOT.TH1.LabelsOption())
567 suffix -- Optional string for a postfix of the frame name
569 if xbinlabels
is None:
570 frame = pad.DrawFrame(*bounds)
573 nbins = len(xbinlabels)
574 frame = ROOT.TH1F(
"hframe"+suffix,
"", nbins, bounds[0], bounds[2])
575 frame.SetBit(ROOT.TH1.kNoStats)
576 frame.SetBit(ROOT.kCanDelete)
577 frame.SetMinimum(bounds[1])
578 frame.SetMaximum(bounds[3])
579 frame.GetYaxis().SetLimits(bounds[1], bounds[3])
582 xaxis = frame.GetXaxis()
583 for i
in xrange(nbins):
584 xaxis.SetBinLabel(i+1, xbinlabels[i])
585 if xbinlabelsize
is not None:
586 xaxis.SetLabelSize(xbinlabelsize)
587 if xbinlabeloption
is not None:
588 frame.LabelsOption(xbinlabeloption)
593 """Class for creating and managing a frame for a simple, one-pad plot"""
594 def __init__(self, pad, bounds, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None):
607 self._frame.GetYaxis().SetTitleOffset(self._frame.GetYaxis().GetTitleOffset()*yoffsetFactor)
608 self._frame.GetXaxis().SetTitleOffset(self._frame.GetXaxis().GetTitleOffset()*xoffsetFactor)
612 self._pad.SetLogx(log)
615 self._pad.SetLogy(log)
618 self._pad.SetGridx(grid)
621 self._pad.SetGridy(grid)
624 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
630 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
636 self._frame.SetTitle(title)
639 self._frame.GetXaxis().SetTitle(title)
642 self._frame.GetXaxis().SetTitleSize(size)
645 self._frame.GetXaxis().SetTitleOffset(offset)
648 self._frame.GetXaxis().SetLabelSize(size)
651 self._frame.GetYaxis().SetTitle(title)
654 self._frame.GetYaxis().SetTitleSize(size)
657 self._frame.GetYaxis().SetTitleOffset(offset)
660 self._pad.RedrawAxis()
663 """Class for creating and managing a frame for a ratio plot with two subpads"""
664 def __init__(self, pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None):
667 if xbinlabels
is not None:
674 self._frame.GetXaxis().SetLabelSize(0)
675 self._frame.GetXaxis().SetTitleSize(0)
677 yoffsetFactor = ratioFactor
678 divisionPoint = 1-1/ratioFactor
679 xoffsetFactor = 1/divisionPoint
693 self._frame.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
694 self._frameRatio.GetYaxis().SetLabelSize(int(self._frameRatio.GetYaxis().GetLabelSize()*0.8))
695 self._frameRatio.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
696 self._frameRatio.GetXaxis().SetTitleOffset(self._frameRatio.GetXaxis().GetTitleOffset()*xoffsetFactor)
698 self._frameRatio.GetYaxis().SetNdivisions(4, 5, 0)
700 self._frameRatio.GetYaxis().SetTitle(
"Ratio")
703 self._pad.SetLogx(log)
704 self._padRatio.SetLogx(log)
707 self._pad.SetLogy(log)
710 self._pad.SetGridx(grid)
711 self._padRatio.SetGridx(grid)
714 self._pad.SetGridy(grid)
715 self._padRatio.SetGridy(grid)
718 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
719 self._padRatio.SetLeftMargin(self._padRatio.GetLeftMargin()+adjust)
724 self._frameRatio.Draw(
"")
727 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
728 self._padRatio.SetRightMargin(self._padRatio.GetRightMargin()+adjust)
733 self._frameRatio.Draw(
"")
736 self._frame.SetTitle(title)
739 self._frameRatio.GetXaxis().SetTitle(title)
742 self._frameRatio.GetXaxis().SetTitleSize(size)
745 self._frameRatio.GetXaxis().SetTitleOffset(offset)
748 self._frameRatio.GetXaxis().SetLabelSize(size)
751 self._frame.GetYaxis().SetTitle(title)
754 self._frameRatio.GetYaxis().SetTitle(title)
757 self._frame.GetYaxis().SetTitleSize(size)
758 self._frameRatio.GetYaxis().SetTitleSize(size)
761 self._frame.GetYaxis().SetTitleOffset(offset)
762 self._frameRatio.GetYaxis().SetTitleOffset(offset)
765 self._padRatio.RedrawAxis()
766 self._pad.RedrawAxis()
775 self.
_coverPad = ROOT.TPad(
"coverpad",
"coverpad", xmin, ymin, xmax, ymax)
776 self._coverPad.SetBorderMode(0)
777 self._coverPad.Draw()
783 """Class for creating and managing a frame for a plot from TGraph2D"""
784 def __init__(self, pad, bounds, histos, ratioOrig, ratioFactor):
787 self.
_pad = pad.cd(1)
791 (xlow, ylow, width, height) = (self._pad.GetXlowNDC(), self._pad.GetYlowNDC(), self._pad.GetWNDC(), self._pad.GetHNDC())
795 bottomMargin = self._pad.GetBottomMargin()
796 bottomMarginNew = ROOT.gStyle.GetPadBottomMargin()
798 ylowNew = yup - (1-bottomMargin)/(1-bottomMarginNew) * (yup-ylow)
799 topMarginNew = self._pad.GetTopMargin() * (yup-ylow)/(yup-ylowNew)
801 self._pad.SetPad(xlow, ylowNew, xup, yup)
802 self._pad.SetTopMargin(topMarginNew)
803 self._pad.SetBottomMargin(bottomMarginNew)
805 self.
_view = ROOT.TView.CreateView()
806 self._view.SetRange(bounds[0], bounds[1], 0, bounds[2], bounds[3], 20)
808 self._view.ShowAxis()
828 self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
832 self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
860 self._firstHisto.GetZaxis().SetTitle(title)
863 self._firstHisto.GetZaxis().SetTitleOffset(offset)
867 ROOT.TAxis3D.ToggleRulers()
868 ROOT.TAxis3D.ToggleRulers()
869 axis = ROOT.TAxis3D.GetPadAxis()
870 axis.SetLabelColor(ROOT.kBlack);
871 axis.SetAxisColor(ROOT.kBlack);
876 if hasattr(self,
"_xtitle"):
877 axis.GetXaxis().SetTitle(self.
_xtitle)
878 if hasattr(self,
"_xtitlesize"):
880 if hasattr(self,
"_xlabelsize"):
881 axis.GetXaxis().SetLabelSize(self._labelsize)
882 if hasattr(self,
"_ytitle"):
883 axis.GetYaxis().SetTitle(self.
_ytitle)
884 if hasattr(self,
"_ytitlesize"):
886 if hasattr(self,
"_ytitleoffset"):
891 if hasattr(src,
"GetLineColor")
and hasattr(dst,
"SetLineColor"):
892 properties.extend([
"LineColor",
"LineStyle",
"LineWidth"])
893 if hasattr(src,
"GetFillColor")
and hasattr(dst,
"SetFillColor"):
894 properties.extend([
"FillColor",
"FillStyle"])
895 if hasattr(src,
"GetMarkerColor")
and hasattr(dst,
"SetMarkerColor"):
896 properties.extend([
"MarkerColor",
"MarkerSize",
"MarkerStyle"])
898 for prop
in properties:
899 getattr(dst,
"Set"+prop)(getattr(src,
"Get"+prop)())
902 """Represents one plot, comparing one or more histograms."""
907 name -- String for name of the plot, or Efficiency object
910 fallback -- Dictionary for specifying fallback (default None)
911 title -- String for a title of the plot (default None)
912 xtitle -- String for x axis title (default None)
913 xtitlesize -- Float for x axis title size (default None)
914 xtitleoffset -- Float for x axis title offset (default None)
915 xlabelsize -- Float for x axis label size (default None)
916 ytitle -- String for y axis title (default None)
917 ytitlesize -- Float for y axis title size (default None)
918 ytitleoffset -- Float for y axis title offset (default None)
919 ztitle -- String for z axis title (default None)
920 ztitleoffset -- Float for z axis title offset (default None)
921 xmin -- Float for x axis minimum (default None, i.e. automatic)
922 xmax -- Float for x axis maximum (default None, i.e. automatic)
923 ymin -- Float for y axis minimum (default 0)
924 ymax -- Float for y axis maximum (default None, i.e. automatic)
925 xlog -- Bool for x axis log status (default False)
926 ylog -- Bool for y axis log status (default False)
927 xgrid -- Bool for x axis grid status (default True)
928 ygrid -- Bool for y axis grid status (default True)
929 stat -- Draw stat box? (default False)
930 fit -- Do gaussian fit? (default False)
931 statx -- Stat box x coordinate (default 0.65)
932 staty -- Stat box y coordinate (default 0.8)
933 statyadjust -- List of floats for stat box y coordinate adjustments (default None)
934 normalizeToUnitArea -- Normalize histograms to unit area? (default False)
935 profileX -- Take histograms via ProfileX()? (default False)
936 fitSlicesY -- Take histograms via FitSlicesY() (default False)
937 rebinX -- rebin x axis (default None)
938 scale -- Scale histograms by a number (default None)
939 xbinlabels -- List of x axis bin labels (if given, default None)
940 xbinlabelsize -- Size of x axis bin labels (default None)
941 xbinlabeloption -- Option string for x axis bin labels (default None)
942 drawStyle -- If "hist", draw as line instead of points (default None)
943 drawCommand -- Deliver this to Draw() (default: None for same as drawStyle)
944 lineWidth -- If drawStyle=="hist", the width of line (default 2)
945 legendDx -- Float for moving TLegend in x direction for separate=True (default None)
946 legendDy -- Float for moving TLegend in y direction for separate=True (default None)
947 legendDw -- Float for changing TLegend width for separate=True (default None)
948 legendDh -- Float for changing TLegend height for separate=True (default None)
949 adjustMarginRight -- Float for adjusting right margin (default None)
950 ratioYmin -- Float for y axis minimum in ratio pad (default 0.9)
951 ratioYmax -- Float for y axis maximum in ratio pad (default 1.1)
952 ratioUncertainty -- Plot uncertainties on ratio? (default True)
953 histogramModifier -- Function to be called in create() to modify the histograms (default None)
957 def _set(attr, default):
958 setattr(self,
"_"+attr, kwargs.get(attr, default))
960 _set(
"fallback",
None)
964 _set(
"xtitlesize",
None)
965 _set(
"xtitleoffset",
None)
966 _set(
"xlabelsize",
None)
968 _set(
"ytitlesize",
None)
969 _set(
"ytitleoffset",
None)
971 _set(
"ztitleoffset",
None)
988 _set(
"statyadjust",
None)
990 _set(
"normalizeToUnitArea",
False)
991 _set(
"profileX",
False)
992 _set(
"fitSlicesY",
False)
996 _set(
"xbinlabels",
None)
997 _set(
"xbinlabelsize",
None)
998 _set(
"xbinlabeloption",
None)
1000 _set(
"drawStyle",
"EP")
1001 _set(
"drawCommand",
None)
1002 _set(
"lineWidth", 2)
1004 _set(
"legendDx",
None)
1005 _set(
"legendDy",
None)
1006 _set(
"legendDw",
None)
1007 _set(
"legendDh",
None)
1009 _set(
"adjustMarginRight",
None)
1011 _set(
"ratioYmin", 0.9)
1012 _set(
"ratioYmax", 1.1)
1013 _set(
"ratioUncertainty",
True)
1015 _set(
"histogramModifier",
None)
1020 for name, value
in kwargs.iteritems():
1021 if not hasattr(self,
"_"+name):
1022 raise Exception(
"No attribute '%s'" % name)
1023 setattr(self,
"_"+name, value)
1026 """Return number of existing histograms."""
1030 """Return true if there are no histograms created for the plot"""
1035 if isinstance(h, ROOT.TGraph2D):
1040 if isinstance(self.
_name, list):
1041 return str(self.
_name[0])
1043 return str(self.
_name)
1046 """Return true if the ratio uncertainty should be drawn"""
1047 return self._ratioUncertainty
1050 """Create one histogram from a TDirectory."""
1055 if isinstance(name, list):
1060 def create(self, tdirs, requireAllHistograms=False):
1061 """Create histograms from list of TDirectories"""
1064 if self._fallback
is not None:
1069 profileX[i] = self._fallback.get(
"profileX", self._profileX)
1071 if self._histogramModifier
is not None:
1075 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)))
1080 def _modifyHisto(th1, profileX):
1085 th1 = th1.ProfileX()
1087 if self._fitSlicesY:
1088 ROOT.TH1.AddDirectory(
True)
1090 th1 = ROOT.gDirectory.Get(th1.GetName()+
"_2")
1091 th1.SetDirectory(
None)
1093 ROOT.TH1.AddDirectory(
False)
1095 if self._title
is not None:
1096 th1.SetTitle(self._title)
1098 if self._scale
is not None:
1099 th1.Scale(self._scale)
1103 if self._fallback
is not None:
1107 if requireAllHistograms
and None in self.
_histograms:
1111 """Set stats box."""
1114 if h
is not None and hasattr(h,
"SetStats"):
1118 def _doStats(h, col, dy):
1123 if self._fit
and h.GetEntries() > 0.5:
1125 f = h.GetListOfFunctions().FindObject(
"gaus")
1133 st = h.GetListOfFunctions().FindObject(
"stats")
1137 st.SetX1NDC(startingX)
1138 st.SetX2NDC(startingX+0.3)
1139 st.SetY1NDC(startingY+dy)
1140 st.SetY2NDC(startingY+dy+0.15)
1141 st.SetTextColor(col)
1144 for i, h
in enumerate(histos):
1145 if self._statyadjust
is not None and i < len(self._statyadjust):
1146 dy += self._statyadjust[i]
1148 _doStats(h, _plotStylesColor[i], dy)
1152 """Normalise histograms to unit area"""
1163 def draw(self, pad, ratio, ratioFactor, nrows):
1164 """Draw the histograms using values for a given algorithm."""
1175 if self._normalizeToUnitArea:
1178 if self._rebinX
is not None:
1180 h.Rebin(self._rebinX)
1182 def _styleMarker(h, msty, col):
1183 h.SetMarkerStyle(msty)
1184 h.SetMarkerColor(col)
1185 h.SetMarkerSize(0.7)
1189 def _styleHist(h, msty, col):
1190 _styleMarker(h, msty, col)
1192 h.SetLineWidth(self._lineWidth)
1195 style = _styleMarker
1196 if "hist" in self._drawStyle.lower():
1199 if "l" in self._drawStyle.lower():
1207 style(h, _plotStylesMarker[i], _plotStylesColor[i])
1209 if len(histos) == 0:
1211 print "No histograms for plot {name}".
format(name=self.
getName())
1216 xbinlabels = self._xbinlabels
1217 if xbinlabels
is None:
1218 if len(histos[0].GetXaxis().GetBinLabel(1)) > 0:
1219 xbinlabels = [histos[0].GetXaxis().GetBinLabel(i)
for i
in xrange(1, histos[0].GetNbinsX()+1)]
1221 for h
in histos[1:]:
1222 labels = [h.GetXaxis().GetBinLabel(i)
for i
in xrange(1, h.GetNbinsX()+1)]
1223 diff = difflib.ndiff(xbinlabels, labels)
1226 xbinlabels.append(item[2:])
1230 h_new = h.Clone(h.GetName()+
"_xbinlabels")
1231 h_new.SetBins(len(xbinlabels), h.GetBinLowEdge(1), h.GetBinLowEdge(1)+len(xbinlabels))
1232 for i, label
in enumerate(xbinlabels):
1233 bin = h.GetXaxis().FindFixBin(label)
1235 h_new.SetBinContent(i+1, h.GetBinContent(bin))
1236 h_new.SetBinError(i+1, h.GetBinError(bin))
1238 h_new.SetBinContent(i+1, 0)
1239 h_new.SetBinError(i+1, 0)
1240 histos_new.append(h_new)
1245 xmin=self._xmin, xmax=self._xmax,
1246 ymin=self._ymin, ymax=self._ymax)
1255 self.
_setStats(histos, self._statx, self._staty)
1259 frame =
FrameTGraph2D(pad, bounds, histos, ratioOrig, ratioFactor)
1262 ratioBounds = (bounds[0], self._ratioYmin, bounds[2], self._ratioYmax)
1263 frame =
FrameRatio(pad, bounds, ratioBounds, ratioFactor, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption)
1265 frame =
Frame(pad, bounds, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption)
1268 frame.setLogx(self._xlog)
1269 frame.setLogy(self._ylog)
1270 frame.setGridx(self._xgrid)
1271 frame.setGridy(self._ygrid)
1276 if self._drawStyle
is not None:
1277 ds = self._drawStyle
1278 if self._drawCommand
is not None:
1279 ds = self._drawCommand
1284 frame.setTitle(histos[0].GetTitle())
1285 if self._xtitle
is not None:
1286 frame.setXTitle(self._xtitle)
1287 if self._xtitlesize
is not None:
1288 frame.setXTitleSize(self._xtitlesize)
1289 if self._xtitleoffset
is not None:
1290 frame.setXTitleOffset(self._xtitleoffset)
1291 if self._xlabelsize
is not None:
1292 frame.setXLabelSize(self._xlabelsize)
1293 if self._ytitle
is not None:
1294 frame.setYTitle(self._ytitle)
1295 if self._ytitlesize
is not None:
1296 frame.setYTitleSize(self._ytitlesize)
1297 if self._ytitleoffset
is not None:
1298 frame.setYTitleOffset(self._ytitleoffset)
1299 if self._ztitle
is not None:
1300 frame.setZTitle(self._ztitle)
1301 if self._ztitleoffset
is not None:
1302 frame.setZTitleOffset(self._ztitleoffset)
1303 if self._adjustMarginRight
is not None:
1304 frame.adjustMarginRight(self._adjustMarginRight)
1306 frame.adjustMarginLeft(0.03)
1307 frame.adjustMarginRight(0.08)
1317 if ratio
and len(histos) > 0:
1318 frame._padRatio.cd()
1320 if self._ratioUncertainty
and self.
_ratios[0]._ratio
is not None:
1321 self.
_ratios[0]._ratio.SetFillStyle(1001)
1322 self.
_ratios[0]._ratio.SetFillColor(ROOT.kGray)
1323 self.
_ratios[0]._ratio.SetLineColor(ROOT.kGray)
1324 self.
_ratios[0]._ratio.SetMarkerColor(ROOT.kGray)
1325 self.
_ratios[0]._ratio.SetMarkerSize(0)
1327 frame._padRatio.RedrawAxis(
"G")
1335 """Add histograms to a legend.
1339 legendLabels -- List of strings for the legend labels
1341 first = denomUncertainty
1342 for h, label
in zip(self.
_histograms, legendLabels):
1348 self._forLegend.SetFillStyle(1001)
1349 self._forLegend.SetFillColor(ROOT.kGray)
1350 entry = legend.AddEntry(self.
_forLegend, label,
"lpf")
1353 legend.AddEntry(h, label,
"LP")
1356 """Calculate the ratios for a list of histograms"""
1358 def _divideOrZero(numerator, denominator):
1359 if denominator == 0:
1361 return numerator/denominator
1364 if a == 0.
and b == 0.:
1368 def findBins(wrap, bins_xvalues):
1370 currBin = wrap.begin()
1372 while i < len(bins_xvalues)
and currBin < wrap.end():
1373 (xcenter, xlow, xhigh) = bins_xvalues[i]
1374 xlowEdge = xcenter-xlow
1375 xupEdge = xcenter+xhigh
1377 (curr_center, curr_low, curr_high) = wrap.xvalues(currBin)
1378 curr_lowEdge = curr_center-curr_low
1379 curr_upEdge = curr_center+curr_high
1381 if equal(xlowEdge, curr_lowEdge)
and equal(xupEdge, curr_upEdge):
1385 elif curr_upEdge <= xlowEdge:
1387 elif curr_lowEdge >= xupEdge:
1394 if len(ret) != len(bins_xvalues):
1395 ret.extend([
None]*( len(bins_xvalues) - len(ret) ))
1401 def __init__(self, th1, uncertainty):
1405 xaxis = th1.GetXaxis()
1406 xaxis_arr = xaxis.GetXbins()
1407 if xaxis_arr.GetSize() > 0:
1408 lst = [xaxis_arr[i]
for i
in xrange(0, xaxis_arr.GetSize())]
1409 arr = array.array(
"d", lst)
1410 self.
_ratio = ROOT.TH1F(
"foo",
"foo", xaxis.GetNbins(), arr)
1412 self.
_ratio = ROOT.TH1F(
"foo",
"foo", xaxis.GetNbins(), xaxis.GetXmin(), xaxis.GetXmax())
1414 self._ratio.SetStats(0)
1415 self._ratio.SetLineColor(ROOT.kBlack)
1416 self._ratio.SetLineWidth(1)
1417 def draw(self, style=None):
1424 self._ratio.Draw(
"same "+st)
1428 return self._th1.GetNbinsX()+1
1429 def xvalues(self, bin):
1430 xval = self._th1.GetBinCenter(bin)
1431 xlow = xval-self._th1.GetXaxis().GetBinLowEdge(bin)
1432 xhigh = self._th1.GetXaxis().GetBinUpEdge(bin)-xval
1433 return (xval, xlow, xhigh)
1434 def yvalues(self, bin):
1435 yval = self._th1.GetBinContent(bin)
1436 yerr = self._th1.GetBinError(bin)
1437 return (yval, yerr, yerr)
1439 return self._th1.GetBinContent(bin)
1440 def divide(self, bin, scale):
1441 self._ratio.SetBinContent(bin, _divideOrZero(self._th1.GetBinContent(bin), scale))
1442 self._ratio.SetBinError(bin, _divideOrZero(self._th1.GetBinError(bin), scale))
1443 def makeRatio(self):
1447 def __init__(self, gr, uncertainty):
1456 def draw(self, style=None):
1465 self._ratio.Draw(
"same "+st)
1469 return self._gr.GetN()
1470 def xvalues(self, bin):
1471 return (self._gr.GetX()[bin], self._gr.GetErrorXlow(bin), self._gr.GetErrorXhigh(bin))
1472 def yvalues(self, bin):
1473 return (self._gr.GetY()[bin], self._gr.GetErrorYlow(bin), self._gr.GetErrorYhigh(bin))
1475 return self._gr.GetY()[bin]
1476 def divide(self, bin, scale):
1481 if bin >= self._gr.GetN():
1484 xvals = self.xvalues(bin)
1487 self._xvalues.append(xval)
1488 self._xerrslow.append(xvals[1])
1489 self._xerrshigh.append(xvals[2])
1490 yvals = self.yvalues(bin)
1491 self._yvalues.append(yvals[0] / scale)
1493 self._yerrslow.append(yvals[1] / scale)
1494 self._yerrshigh.append(yvals[2] / scale)
1496 self._yerrslow.append(0)
1497 self._yerrshigh.append(0)
1498 def makeRatio(self):
1506 class WrapTGraph2D(WrapTGraph):
1507 def __init__(self, gr, uncertainty):
1508 WrapTGraph.__init__(self, gr, uncertainty)
1509 def xvalues(self, bin):
1510 return (self._gr.GetX()[bin], self._gr.GetErrorX(bin), self._gr.GetErrorX(bin))
1511 def yvalues(self, bin):
1512 return (self._gr.GetY()[bin], self._gr.GetErrorY(bin), self._gr.GetErrorY(bin))
1515 if isinstance(o, ROOT.TH1):
1516 return WrapTH1(o, self._ratioUncertainty)
1517 elif isinstance(o, ROOT.TGraph):
1518 return WrapTGraph(o, self._ratioUncertainty)
1519 elif isinstance(o, ROOT.TGraph2D):
1520 return WrapTGraph2D(o, self._ratioUncertainty)
1522 wrappers = [
wrap(h)
for h
in histos]
1526 ref_bins = [ref.xvalues(b)
for b
in xrange(ref.begin(), ref.end())]
1528 wrappers_bins.append(findBins(w, ref_bins))
1530 for i, bin
in enumerate(xrange(ref.begin(), ref.end())):
1531 (scale, ylow, yhigh) = ref.yvalues(bin)
1532 for w, bins
in zip(wrappers, wrappers_bins):
1535 w.divide(bins[i], scale)
1543 """Group of plots, results a TCanvas"""
1548 name -- String for name of the TCanvas, used also as the basename of the picture files
1549 plots -- List of Plot objects
1552 ncols -- Number of columns (default 2)
1553 legendDx -- Float for moving TLegend in x direction (default None)
1554 legendDy -- Float for moving TLegend in y direction (default None)
1555 legendDw -- Float for changing TLegend width (default None)
1556 legendDh -- Float for changing TLegend height (default None)
1557 legend -- Bool for disabling legend (default True for legend being enabled)
1558 overrideLegendLabels -- List of strings for legend labels, if given, these are used instead of the ones coming from Plotter (default None)
1559 onlyForPileup -- Plots this group only for pileup samples
1564 def _set(attr, default):
1565 setattr(self,
"_"+attr, kwargs.get(attr, default))
1569 _set(
"legendDx",
None)
1570 _set(
"legendDy",
None)
1571 _set(
"legendDw",
None)
1572 _set(
"legendDh",
None)
1573 _set(
"legend",
True)
1575 _set(
"overrideLegendLabels",
None)
1577 _set(
"onlyForPileup",
False)
1588 for i, plot
in enumerate(self.
_plots):
1589 if plot.getName() == name:
1592 raise Exception(
"Did not find Plot '%s' from PlotGroup '%s'" % (name, self.
_name))
1595 self._plots.append(plot)
1599 if plot.getName() == name:
1601 raise Exception(
"No Plot named '%s'" % name)
1604 """Return True if the PlotGroup is intended only for pileup samples"""
1605 return self._onlyForPileup
1607 def create(self, tdirectories, requireAllHistograms=False):
1608 """Create histograms from a list of TDirectories.
1611 tdirectories -- List of TDirectory objects
1612 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False)
1615 plot.create(tdirectories, requireAllHistograms)
1617 def draw(self, legendLabels, prefix=None, separate=False, saveFormat=".pdf", ratio=False):
1618 """Draw the histograms using values for a given algorithm.
1621 legendLabels -- List of strings for legend labels (corresponding to the tdirectories in create())
1622 prefix -- Optional string for file name prefix (default None)
1623 separate -- Save the plots of a group to separate files instead of a file per group (default False)
1624 saveFormat -- String specifying the plot format (default '.pdf')
1625 ratio -- Add ratio to the plot (default False)
1628 if self._overrideLegendLabels
is not None:
1629 legendLabels = self._overrideLegendLabels
1632 onlyEmptyPlots =
True
1634 if not plot.isEmpty():
1635 onlyEmptyPlots =
False
1641 return self.
_drawSeparate(legendLabels, prefix, saveFormat, ratio)
1643 cwidth = 500*self._ncols
1644 nrows = int((len(self.
_plots)+self._ncols-1)/self._ncols)
1645 cheight = 500 * nrows
1652 canvas.Divide(self._ncols, nrows)
1654 for i
in xrange(0, len(self.
_plots)):
1655 pad = canvas.cd(i+1)
1659 for i, plot
in enumerate(self.
_plots):
1660 pad = canvas.cd(i+1)
1661 if not plot.isEmpty():
1666 if len(self.
_plots) <= 4:
1676 if self._legendDx
is not None:
1677 lx1 += self._legendDx
1678 lx2 += self._legendDx
1679 if self._legendDy
is not None:
1680 ly1 += self._legendDy
1681 ly2 += self._legendDy
1682 if self._legendDw
is not None:
1683 lx2 += self._legendDw
1684 if self._legendDh
is not None:
1685 ly1 -= self._legendDh
1686 plot =
max(self.
_plots, key=
lambda p: p.getNumberOfHistograms())
1687 denomUnc = sum([p.drawRatioUncertainty()
for p
in self.
_plots]) > 0
1688 legend = self.
_createLegend(plot, legendLabels, lx1, ly1, lx2, ly2,
1689 denomUncertainty=(ratio
and denomUnc))
1691 return self.
_save(canvas, saveFormat, prefix=prefix)
1694 """Internal method to do the drawing to separate files per Plot instead of a file per PlotGroup"""
1702 canvas.SetTopMargin(0.05)
1703 canvas.SetBottomMargin(0.13)
1704 canvas.SetLeftMargin(0.16)
1705 canvas.SetRightMargin(0.05)
1733 if plot._legendDx
is not None:
1734 lx1 += plot._legendDx
1735 lx2 += plot._legendDx
1736 if plot._legendDy
is not None:
1737 ly1 += plot._legendDy
1738 ly2 += plot._legendDy
1739 if plot._legendDw
is not None:
1740 lx2 += plot._legendDw
1741 if plot._legendDh
is not None:
1742 ly1 -= plot._legendDh
1745 legend = self.
_createLegend(plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.03,
1746 denomUncertainty=(ratio
and plot.drawRatioUncertainty))
1748 ret.extend(self.
_save(canvas, saveFormat, prefix=prefix, postfix=
"_"+plot.getName(), single=
True))
1752 """Internal method to set divide a pad to two for ratio plots"""
1757 topMargin = pad.GetTopMargin()
1758 bottomMargin = pad.GetBottomMargin()
1759 divisionPoint += (1-divisionPoint)*bottomMargin
1760 divisionPointForPad1 = 1-( (1-divisionPoint) / (1-0.02) )
1765 ylow = divisionPointForPad1
1768 pad1.SetPad(xlow, ylow, xup, yup)
1769 pad1.SetFillStyle(4000)
1770 pad1.SetBottomMargin(0.02)
1776 pad2.SetPad(xlow, ylow, xup, yup)
1777 pad2.SetFillStyle(4000)
1778 pad2.SetTopMargin(0.0)
1779 pad2.SetBottomMargin(bottomMargin/(self.
_ratioFactor*divisionPoint))
1781 def _createLegend(self, plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.016, denomUncertainty=True):
1782 if not self._legend:
1785 l = ROOT.TLegend(lx1, ly1, lx2, ly2)
1786 l.SetTextSize(textSize)
1793 plot.addToLegend(l, legendLabels, denomUncertainty)
1797 def _save(self, canvas, saveFormat, prefix=None, postfix=None, single=False):
1800 if prefix
is not None:
1802 if postfix
is not None:
1806 backup = ROOT.gErrorIgnoreLevel
1807 ROOT.gErrorIgnoreLevel = ROOT.kWarning
1808 canvas.SaveAs(name+saveFormat)
1810 ROOT.gErrorIgnoreLevel = backup
1814 canvas.SetLogx(
False)
1815 canvas.SetLogy(
False)
1819 return [name+saveFormat]
1822 """Represents a collection of PlotGroups, produced from a single folder in a DQM file"""
1827 plotGroups -- List of PlotGroup objects
1830 loopSubFolders -- Should the subfolders be looped over? (default: True)
1831 onlyForPileup -- Plots this folder only for pileup samples
1832 purpose -- html.PlotPurpose member class for the purpose of the folder, used for grouping of the plots to the HTML pages
1833 page -- Optional string for the page in HTML generatin
1834 section -- Optional string for the section within a page in HTML generation
1843 raise Exception(
"Got unexpected keyword arguments: "+
",".
join(kwargs.keys()))
1846 """Return True if the PlotGroups of this folder should be applied to the all subfolders"""
1850 """Return True if the folder is intended only for pileup samples"""
1863 self._plotGroups.append(plotGroup)
1873 if pg.getName() == name:
1875 raise Exception(
"No PlotGroup named '%s'" % name)
1877 def create(self, dirs, labels, isPileupSample=True, requireAllHistograms=False):
1878 """Create histograms from a list of TFiles.
1881 dirs -- List of TDirectories
1882 labels -- List of strings for legend labels corresponding the files
1883 isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup)
1884 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False)
1887 if len(dirs) != len(labels):
1888 raise Exception(
"len(files) should be len(labels), now they are %d and %d" % (len(files), len(labels)))
1893 if pg.onlyForPileup()
and not isPileupSample:
1895 pg.create(dirs, requireAllHistograms)
1897 def draw(self, prefix=None, separate=False, saveFormat=".pdf", ratio=False):
1898 """Draw and save all plots using settings of a given algorithm.
1901 prefix -- Optional string for file name prefix (default None)
1902 separate -- Save the plots of a group to separate files instead of a file per group (default False)
1903 saveFormat -- String specifying the plot format (default '.pdf')
1904 ratio -- Add ratio to the plot (default False)
1909 ret.extend(pg.draw(self.
_labels, prefix=prefix, separate=separate, saveFormat=saveFormat, ratio=ratio))
1915 """Method called to (possibly) translate a subfolder name to more 'readable' form
1917 The implementation in this (base) class just returns the
1918 argument. The idea is that a deriving class might want to do
1919 something more complex (like trackingPlots.TrackingPlotFolder
1922 return dqmSubFolderName
1925 """Iterate over possible selections name (used in output directory name and legend) from the name of PlotterFolder, and a return value of translateSubFolder"""
1927 if plotFolderName !=
"":
1928 ret +=
"_"+plotFolderName
1929 if translatedDqmSubFolder
is not None:
1930 ret +=
"_"+translatedDqmSubFolder
1934 """Return True if this subfolder should be processed
1937 limitOnlyTo -- List/set/similar containing the translatedDqmSubFolder
1938 translatedDqmSubFolder -- Return value of translateSubFolder
1940 return translatedDqmSubFolder
in limitOnlyTo
1943 """Class to hold the original name and a 'translated' name of a subfolder in the DQM ROOT file"""
1949 """Equality is defined by the 'translated' name"""
1953 """Plotter for one DQM folder.
1955 This class is supposed to be instantiated by the Plotter class (or
1956 PlotterItem, to be more specific), and not used directly by the
1959 def __init__(self, name, possibleDqmFolders, dqmSubFolders, plotFolder, fallbackNames, fallbackDqmSubFolders, tableCreators):
1964 name -- Name of the folder (is used in the output directory naming)
1965 possibleDqmFolders -- List of strings for possible directories of histograms in TFiles
1966 dqmSubFolders -- List of lists of strings for list of subfolders per input file, or None if no subfolders
1967 plotFolder -- PlotFolder object
1968 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.
1969 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.
1970 tableCreators -- List of PlotterTableItem objects for tables to be created from this folder
1976 if dqmSubFolders
is None:
1982 for sf_list
in dqmSubFolders:
1984 sf_translated = self._plotFolder.translateSubFolder(sf)
1985 if sf_translated
is not None and not sf_translated
in subfolders:
1986 subfolders[sf_translated] =
DQMSubFolder(sf, sf_translated)
1989 self._dqmSubFolders.sort(key=
lambda sf: sf.subfolder)
1999 return self._plotFolder.getPurpose()
2002 return self._plotFolder.getPage()
2005 return self._plotFolder.getSection()
2008 return self._plotFolder.onlyForPileup()
2014 """Get list of subfolders, possibly limiting to some of them.
2017 limitOnlyTo -- Object depending on the PlotFolder type for limiting the set of subfolders to be processed
2023 if limitOnlyTo
is None:
2026 return filter(
lambda s: self._plotFolder.limitSubFolder(limitOnlyTo, s.translated), self.
_dqmSubFolders)
2032 """Get a generator for the 'selection name', looping over the name and fallbackNames"""
2034 for selname
in self._plotFolder.iterSelectionName(name, dqmSubFolder.translated
if dqmSubFolder
is not None else None):
2040 def create(self, files, labels, dqmSubFolder, isPileupSample=True, requireAllHistograms=False):
2041 """Create histograms from a list of TFiles.
2043 files -- List of TFiles
2044 labels -- List of strings for legend labels corresponding the files
2045 dqmSubFolder -- DQMSubFolder object for a subfolder (or None for no subfolder)
2046 isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup)
2047 requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False)
2050 subfolder = dqmSubFolder.subfolder
if dqmSubFolder
is not None else None
2058 fallback = fallbackFunc(subfolder)
2059 if fallback
is not None:
2063 dirs.append(GetDirectoryCode.codesToNone(ret))
2065 self._plotFolder.create(dirs, labels, isPileupSample, requireAllHistograms)
2068 """Draw and save all plots using settings of a given algorithm."""
2069 return self._plotFolder.draw(*args, **kwargs)
2073 """Instance of plotter that knows the directory content, holds many folders."""
2080 if limitSubFoldersOnlyTo
is not None:
2081 limitOnlyTo = limitSubFoldersOnlyTo.get(plotterFolder.getName(),
None)
2083 for dqmSubFolder
in plotterFolder.getDQMSubFolders(limitOnlyTo=limitOnlyTo):
2084 yield plotterFolder, dqmSubFolder
2088 def __init__(self, name, possibleDirs, plotFolder, fallbackNames=[], fallbackDqmSubFolders=[]):
2092 name -- Name of the folder (is used in the output directory naming)
2093 possibleDirs -- List of strings for possible directories of histograms in TFiles
2094 plotFolder -- PlotFolder object
2097 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.
2098 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.
2114 self._tableCreators.append(tc)
2117 """Read available subfolders from the files
2120 files -- List of strings for paths to files, or list of TFiles
2122 For each file, loop over 'possibleDirs', and read the
2123 subfolders of first one that exists.
2125 Returns a PlotterFolder if at least one file for which one of
2126 'possibleDirs' exists. Otherwise, return None to signal that
2127 there is nothing available for this PlotFolder.
2130 if self._plotFolder.loopSubFolders():
2132 possibleDirFound =
False
2134 isOpenFile = isinstance(fname, ROOT.TFile)
2138 tfile = ROOT.TFile.Open(fname)
2142 possibleDirFound =
True
2143 if subFolders
is not None:
2145 for key
in d.GetListOfKeys():
2146 if isinstance(key.ReadObj(), ROOT.TDirectory):
2147 subf.append(key.GetName())
2148 subFolders.append(subf)
2154 if not possibleDirFound:
2164 def create(self, openFiles, legendLabels, dqmSubFolder):
2165 if isinstance(dqmSubFolder, list):
2166 if len(dqmSubFolder) != len(openFiles):
2167 raise Exception(
"When dqmSubFolder is a list, len(dqmSubFolder) should be len(openFiles), now they are %d and %d" % (len(dqmSubFolder), len(openFiles)))
2169 dqmSubFolder = [dqmSubFolder]*len(openFiles)
2170 dqmSubFolder = [sf.subfolder
if sf
is not None else None for sf
in dqmSubFolder]
2173 for f, sf
in zip(openFiles, dqmSubFolder):
2176 if tdir
is not None:
2177 data = self._tableCreator.create(tdir)
2192 for i
in xrange(len(tbl)):
2194 tbl[i] = [
None]*colLen
2196 return html.Table(columnHeaders=legendLabels, rowHeaders=self._tableCreator.headers(), table=tbl,
2197 purpose=self._tableCreator.getPurpose(), page=self._tableCreator.getPage(), section=self._tableCreator.getSection(dqmSubFolder[0]))
2200 """Contains PlotFolders, i.e. the information what plots to do, and creates a helper object to actually produce the plots."""
2204 _absoluteSize =
True
2216 ROOT.gROOT.SetStyle(
"Plain")
2217 ROOT.gStyle.SetPadRightMargin(0.07)
2218 ROOT.gStyle.SetPadLeftMargin(0.13)
2219 ROOT.gStyle.SetTitleFont(font,
"XYZ")
2220 ROOT.gStyle.SetTitleSize(titleSize,
"XYZ")
2221 ROOT.gStyle.SetTitleOffset(1.2,
"Y")
2223 ROOT.gStyle.SetLabelFont(font,
"XYZ")
2224 ROOT.gStyle.SetLabelSize(labelSize,
"XYZ")
2225 ROOT.gStyle.SetTextSize(labelSize)
2226 ROOT.gStyle.SetStatFont(font)
2227 ROOT.gStyle.SetStatFontSize(statSize)
2229 ROOT.TH1.AddDirectory(
False)
2230 ROOT.TGaxis.SetMaxDigits(4)
2233 """Append a plot folder to the plotter.
2235 All arguments are forwarded to the constructor of PlotterItem.
2240 for plotterItem
in self.
_plots:
2241 if plotterItem.getName() == attachToFolder:
2244 raise Exception(
"Did not find plot folder '%s' when trying to attach a table creator to it" % attachToFolder)
2247 """Remove all plot folders and tables"""
2251 return [item.getName()
for item
in self.
_plots]
2254 return [item.getPlotFolder()
for item
in self.
_plots]
2258 if item.getName() == name:
2259 return item.getPlotFolder()
2260 raise Exception(
"No PlotFolder named '%s'" % name)
2263 """Returns PlotterInstance object, which knows how exactly to produce the plots for these files"""
def getSelectionNameIterator
def getPossibleDQMFolders
def _getYminIgnoreOutlier
bool equal(const T &first, const T &second)
Abs< T >::type abs(const T &t)
static std::string join(char **cmd)
def getNumberOfHistograms
def _getDirectoryDetailed
auto wrap(F iFunc) -> decltype(iFunc())
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