CMS 3D CMS Logo

plotting.py
Go to the documentation of this file.
1 from __future__ import print_function
2 from __future__ import absolute_import
3 from builtins import range
4 import os
5 import sys
6 import math
7 import copy
8 import array
9 import difflib
10 import collections
11 
12 import six
13 import ROOT
14 ROOT.gROOT.SetBatch(True)
15 ROOT.PyConfig.IgnoreCommandLineOptions = True
16 
17 from . import html
18 
19 verbose=False
20 _ratioYTitle = "Ratio"
21 
22 def _setStyle():
23  _absoluteSize = True
24  if _absoluteSize:
25  font = 43
26  titleSize = 22
27  labelSize = 22
28  statSize = 14
29  else:
30  font = 42
31  titleSize = 0.05
32  labelSize = 0.05
33  statSize = 0.025
34 
35  ROOT.gROOT.SetStyle("Plain")
36  ROOT.gStyle.SetPadRightMargin(0.07)
37  ROOT.gStyle.SetPadLeftMargin(0.13)
38  ROOT.gStyle.SetTitleFont(font, "XYZ")
39  ROOT.gStyle.SetTitleSize(titleSize, "XYZ")
40  ROOT.gStyle.SetTitleOffset(1.2, "Y")
41  #ROOT.gStyle.SetTitleFontSize(0.05)
42  ROOT.gStyle.SetLabelFont(font, "XYZ")
43  ROOT.gStyle.SetLabelSize(labelSize, "XYZ")
44  ROOT.gStyle.SetTextSize(labelSize)
45  ROOT.gStyle.SetStatFont(font)
46  ROOT.gStyle.SetStatFontSize(statSize)
47 
48  ROOT.TGaxis.SetMaxDigits(4)
49 
50 def _getObject(tdirectory, name):
51  obj = tdirectory.Get(name)
52  if not obj:
53  if verbose:
54  print("Did not find {obj} from {dir}".format(obj=name, dir=tdirectory.GetPath()))
55  return None
56  return obj
57 
58 def _getOrCreateObject(tdirectory, nameOrCreator):
59  if hasattr(nameOrCreator, "create"):
60  return nameOrCreator.create(tdirectory)
61  return _getObject(tdirectory, nameOrCreator)
62 
64  class FileNotExist: pass
66  class SubDirNotExist: pass
67 
68  @staticmethod
69  def codesToNone(code):
71  return None
72  return code
73 
74 def _getDirectoryDetailed(tfile, possibleDirs, subDir=None):
75  """Get TDirectory from TFile."""
76  if tfile is None:
78  for pdf in possibleDirs:
79  d = tfile.Get(pdf)
80  if d:
81  if subDir is not None:
82  # Pick associator if given
83  d = d.Get(subDir)
84  if d:
85  return d
86  else:
87  if verbose:
88  print("Did not find subdirectory '%s' from directory '%s' in file %s" % (subDir, pdf, tfile.GetName()))
89 # if "Step" in subDir:
90 # raise Exception("Foo")
92  else:
93  return d
94  if verbose:
95  print("Did not find any of directories '%s' from file %s" % (",".join(possibleDirs), tfile.GetName()))
97 
98 def _getDirectory(*args, **kwargs):
99  return GetDirectoryCode.codesToNone(_getDirectoryDetailed(*args, **kwargs))
100 
101 def _th1ToOrderedDict(th1, renameBin=None):
102  values = collections.OrderedDict()
103  for i in range(1, th1.GetNbinsX()+1):
104  binLabel = th1.GetXaxis().GetBinLabel(i)
105  if renameBin is not None:
106  binLabel = renameBin(binLabel)
107  values[binLabel] = (th1.GetBinContent(i), th1.GetBinError(i))
108  return values
109 
110 def _createCanvas(name, width, height):
111  # silence warning of deleting canvas with the same name
112  if not verbose:
113  backup = ROOT.gErrorIgnoreLevel
114  ROOT.gErrorIgnoreLevel = ROOT.kError
115  canvas = ROOT.TCanvas(name, name, width, height)
116  if not verbose:
117  ROOT.gErrorIgnoreLevel = backup
118  return canvas
119 
120 def _modifyPadForRatio(pad, ratioFactor):
121  pad.Divide(1, 2)
122 
123  divisionPoint = 1-1/ratioFactor
124 
125  topMargin = pad.GetTopMargin()
126  bottomMargin = pad.GetBottomMargin()
127  divisionPoint += (1-divisionPoint)*bottomMargin # correct for (almost-)zeroing bottom margin of pad1
128  divisionPointForPad1 = 1-( (1-divisionPoint) / (1-0.02) ) # then correct for the non-zero bottom margin, but for pad1 only
129 
130  # Set the lower point of the upper pad to divisionPoint
131  pad1 = pad.cd(1)
132  yup = 1.0
133  ylow = divisionPointForPad1
134  xup = 1.0
135  xlow = 0.0
136  pad1.SetPad(xlow, ylow, xup, yup)
137  pad1.SetFillStyle(4000) # transparent
138  pad1.SetBottomMargin(0.02) # need some bottom margin here for eps/pdf output (at least in ROOT 5.34)
139 
140  # Set the upper point of the lower pad to divisionPoint
141  pad2 = pad.cd(2)
142  yup = divisionPoint
143  ylow = 0.0
144  pad2.SetPad(xlow, ylow, xup, yup)
145  pad2.SetFillStyle(4000) # transparent
146  pad2.SetTopMargin(0.0)
147  pad2.SetBottomMargin(bottomMargin/(ratioFactor*divisionPoint))
148 
149 def _calculateRatios(histos, ratioUncertainty=False):
150  """Calculate the ratios for a list of histograms"""
151 
152  def _divideOrZero(numerator, denominator):
153  if denominator == 0:
154  return 0
155  return numerator/denominator
156 
157  def equal(a, b):
158  if a == 0. and b == 0.:
159  return True
160  return abs(a-b)/max(abs(a),abs(b)) < 1e-3
161 
162  def findBins(wrap, bins_xvalues):
163  ret = []
164  currBin = wrap.begin()
165  i = 0
166  while i < len(bins_xvalues) and currBin < wrap.end():
167  (xcenter, xlow, xhigh) = bins_xvalues[i]
168  xlowEdge = xcenter-xlow
169  xupEdge = xcenter+xhigh
170 
171  (curr_center, curr_low, curr_high) = wrap.xvalues(currBin)
172  curr_lowEdge = curr_center-curr_low
173  curr_upEdge = curr_center+curr_high
174 
175  if equal(xlowEdge, curr_lowEdge) and equal(xupEdge, curr_upEdge):
176  ret.append(currBin)
177  currBin += 1
178  i += 1
179  elif curr_upEdge <= xlowEdge:
180  currBin += 1
181  elif curr_lowEdge >= xupEdge:
182  ret.append(None)
183  i += 1
184  else:
185  ret.append(None)
186  currBin += 1
187  i += 1
188  if len(ret) != len(bins_xvalues):
189  ret.extend([None]*( len(bins_xvalues) - len(ret) ))
190  return ret
191 
192  # Define wrappers for TH1/TGraph/TGraph2D to have uniform interface
193  # TODO: having more global wrappers would make some things simpler also elsewhere in the code
194  class WrapTH1:
195  def __init__(self, th1, uncertainty):
196  self._th1 = th1
197  self._uncertainty = uncertainty
198 
199  xaxis = th1.GetXaxis()
200  xaxis_arr = xaxis.GetXbins()
201  if xaxis_arr.GetSize() > 0: # unequal binning
202  lst = [xaxis_arr[i] for i in range(0, xaxis_arr.GetSize())]
203  arr = array.array("d", lst)
204  self._ratio = ROOT.TH1F("foo", "foo", xaxis.GetNbins(), arr)
205  else:
206  self._ratio = ROOT.TH1F("foo", "foo", xaxis.GetNbins(), xaxis.GetXmin(), xaxis.GetXmax())
207  _copyStyle(th1, self._ratio)
208  self._ratio.SetStats(0)
209  self._ratio.SetLineColor(ROOT.kBlack)
210  self._ratio.SetLineWidth(1)
211  def draw(self, style=None):
212  st = style
213  if st is None:
214  if self._uncertainty:
215  st = "EP"
216  else:
217  st = "HIST P"
218  self._ratio.Draw("same "+st)
219  def begin(self):
220  return 1
221  def end(self):
222  return self._th1.GetNbinsX()+1
223  def xvalues(self, bin):
224  xval = self._th1.GetBinCenter(bin)
225  xlow = xval-self._th1.GetXaxis().GetBinLowEdge(bin)
226  xhigh = self._th1.GetXaxis().GetBinUpEdge(bin)-xval
227  return (xval, xlow, xhigh)
228  def yvalues(self, bin):
229  yval = self._th1.GetBinContent(bin)
230  yerr = self._th1.GetBinError(bin)
231  return (yval, yerr, yerr)
232  def y(self, bin):
233  return self._th1.GetBinContent(bin)
234  def divide(self, bin, scale):
235  self._ratio.SetBinContent(bin, _divideOrZero(self._th1.GetBinContent(bin), scale))
236  self._ratio.SetBinError(bin, _divideOrZero(self._th1.GetBinError(bin), scale))
237  def makeRatio(self):
238  pass
239  def getRatio(self):
240  return self._ratio
241 
242  class WrapTGraph:
243  def __init__(self, gr, uncertainty):
244  self._gr = gr
245  self._uncertainty = uncertainty
246  self._xvalues = []
247  self._xerrslow = []
248  self._xerrshigh = []
249  self._yvalues = []
250  self._yerrshigh = []
251  self._yerrslow = []
252  def draw(self, style=None):
253  if self._ratio is None:
254  return
255  st = style
256  if st is None:
257  if self._uncertainty:
258  st = "PZ"
259  else:
260  st = "PX"
261  self._ratio.Draw("same "+st)
262  def begin(self):
263  return 0
264  def end(self):
265  return self._gr.GetN()
266  def xvalues(self, bin):
267  return (self._gr.GetX()[bin], self._gr.GetErrorXlow(bin), self._gr.GetErrorXhigh(bin))
268  def yvalues(self, bin):
269  return (self._gr.GetY()[bin], self._gr.GetErrorYlow(bin), self._gr.GetErrorYhigh(bin))
270  def y(self, bin):
271  return self._gr.GetY()[bin]
272  def divide(self, bin, scale):
273  # Ignore bin if denominator is zero
274  if scale == 0:
275  return
276  # No more items in the numerator
277  if bin >= self._gr.GetN():
278  return
279  # denominator is missing an item
280  xvals = self.xvalues(bin)
281  xval = xvals[0]
282 
283  self._xvalues.append(xval)
284  self._xerrslow.append(xvals[1])
285  self._xerrshigh.append(xvals[2])
286  yvals = self.yvalues(bin)
287  self._yvalues.append(yvals[0] / scale)
288  if self._uncertainty:
289  self._yerrslow.append(yvals[1] / scale)
290  self._yerrshigh.append(yvals[2] / scale)
291  else:
292  self._yerrslow.append(0)
293  self._yerrshigh.append(0)
294  def makeRatio(self):
295  if len(self._xvalues) == 0:
296  self._ratio = None
297  return
298  self._ratio = ROOT.TGraphAsymmErrors(len(self._xvalues), array.array("d", self._xvalues), array.array("d", self._yvalues),
299  array.array("d", self._xerrslow), array.array("d", self._xerrshigh),
300  array.array("d", self._yerrslow), array.array("d", self._yerrshigh))
301  _copyStyle(self._gr, self._ratio)
302  def getRatio(self):
303  return self._ratio
304  class WrapTGraph2D(WrapTGraph):
305  def __init__(self, gr, uncertainty):
306  WrapTGraph.__init__(self, gr, uncertainty)
307  def xvalues(self, bin):
308  return (self._gr.GetX()[bin], self._gr.GetErrorX(bin), self._gr.GetErrorX(bin))
309  def yvalues(self, bin):
310  return (self._gr.GetY()[bin], self._gr.GetErrorY(bin), self._gr.GetErrorY(bin))
311 
312  def wrap(o):
313  if isinstance(o, ROOT.TH1) and not isinstance(o, ROOT.TH2):
314  return WrapTH1(o, ratioUncertainty)
315  elif isinstance(o, ROOT.TGraph):
316  return WrapTGraph(o, ratioUncertainty)
317  elif isinstance(o, ROOT.TGraph2D):
318  return WrapTGraph2D(o, ratioUncertainty)
319 
320  wrappers = [wrap(h) for h in histos if wrap(h) is not None]
321  if len(wrappers) < 1:
322  return []
323  ref = wrappers[0]
324 
325  wrappers_bins = []
326  ref_bins = [ref.xvalues(b) for b in range(ref.begin(), ref.end())]
327  for w in wrappers:
328  wrappers_bins.append(findBins(w, ref_bins))
329 
330  for i, bin in enumerate(range(ref.begin(), ref.end())):
331  (scale, ylow, yhigh) = ref.yvalues(bin)
332  for w, bins in zip(wrappers, wrappers_bins):
333  if bins[i] is None:
334  continue
335  w.divide(bins[i], scale)
336 
337  for w in wrappers:
338  w.makeRatio()
339 
340  return wrappers
341 
342 
343 def _getXmin(obj, limitToNonZeroContent=False):
344  if isinstance(obj, ROOT.TH1):
345  xaxis = obj.GetXaxis()
346  if limitToNonZeroContent:
347  for i in range(1, obj.GetNbinsX()+1):
348  if obj.GetBinContent(i) != 0:
349  return xaxis.GetBinLowEdge(i)
350  # None for all bins being zero
351  return None
352  else:
353  return xaxis.GetBinLowEdge(xaxis.GetFirst())
354  elif isinstance(obj, ROOT.TGraph) or isinstance(obj, ROOT.TGraph2D):
355  m = min([obj.GetX()[i] for i in range(0, obj.GetN())])
356  return m*0.9 if m > 0 else m*1.1
357  raise Exception("Unsupported type %s" % str(obj))
358 
359 def _getXmax(obj, limitToNonZeroContent=False):
360  if isinstance(obj, ROOT.TH1):
361  xaxis = obj.GetXaxis()
362  if limitToNonZeroContent:
363  for i in range(obj.GetNbinsX(), 0, -1):
364  if obj.GetBinContent(i) != 0:
365  return xaxis.GetBinUpEdge(i)
366  # None for all bins being zero
367  return None
368  else:
369  return xaxis.GetBinUpEdge(xaxis.GetLast())
370  elif isinstance(obj, ROOT.TGraph) or isinstance(obj, ROOT.TGraph2D):
371  m = max([obj.GetX()[i] for i in range(0, obj.GetN())])
372  return m*1.1 if m > 0 else m*0.9
373  raise Exception("Unsupported type %s" % str(obj))
374 
375 def _getYmin(obj, limitToNonZeroContent=False):
376  if isinstance(obj, ROOT.TH2):
377  yaxis = obj.GetYaxis()
378  return yaxis.GetBinLowEdge(yaxis.GetFirst())
379  elif isinstance(obj, ROOT.TH1):
380  if limitToNonZeroContent:
381  lst = [obj.GetBinContent(i) for i in range(1, obj.GetNbinsX()+1) if obj.GetBinContent(i) != 0 ]
382  return min(lst) if len(lst) != 0 else 0
383  else:
384  return obj.GetMinimum()
385  elif isinstance(obj, ROOT.TGraph) or isinstance(obj, ROOT.TGraph2D):
386  m = min([obj.GetY()[i] for i in range(0, obj.GetN())])
387  return m*0.9 if m > 0 else m*1.1
388  raise Exception("Unsupported type %s" % str(obj))
389 
390 def _getYmax(obj, limitToNonZeroContent=False):
391  if isinstance(obj, ROOT.TH2):
392  yaxis = obj.GetYaxis()
393  return yaxis.GetBinUpEdge(yaxis.GetLast())
394  elif isinstance(obj, ROOT.TH1):
395  if limitToNonZeroContent:
396  lst = [obj.GetBinContent(i) for i in range(1, obj.GetNbinsX()+1) if obj.GetBinContent(i) != 0 ]
397  return max(lst) if len(lst) != 0 else 0
398  else:
399  return obj.GetMaximum()
400  elif isinstance(obj, ROOT.TGraph) or isinstance(obj, ROOT.TGraph2D):
401  m = max([obj.GetY()[i] for i in range(0, obj.GetN())])
402  return m*1.1 if m > 0 else m*0.9
403  raise Exception("Unsupported type %s" % str(obj))
404 
406  return max([th1.GetBinContent(i)+th1.GetBinError(i) for i in range(1, th1.GetNbinsX()+1)])
407 
409  yvals = sorted([n for n in [th1.GetBinContent(i) for i in range(1, th1.GetNbinsX()+1)] if n>0])
410  if len(yvals) == 0:
411  return th1.GetMinimum()
412  if len(yvals) == 1:
413  return yvals[0]
414 
415  # Define outlier as being x10 less than minimum of the 95 % of the non-zero largest values
416  ind_min = len(yvals)-1 - int(len(yvals)*0.95)
417  min_val = yvals[ind_min]
418  for i in range(0, ind_min):
419  if yvals[i] > 0.1*min_val:
420  return yvals[i]
421 
422  return min_val
423 
424 def _getYminMaxAroundMedian(obj, coverage, coverageRange=None):
425  inRange = lambda x: True
426  inRange2 = lambda xmin,xmax: True
427  if coverageRange:
428  inRange = lambda x: coverageRange[0] <= x <= coverageRange[1]
429  inRange2 = lambda xmin,xmax: coverageRange[0] <= xmin and xmax <= coverageRange[1]
430 
431  if isinstance(obj, ROOT.TH1):
432  yvals = [obj.GetBinContent(i) for i in range(1, obj.GetNbinsX()+1) if inRange2(obj.GetXaxis().GetBinLowEdge(i), obj.GetXaxis().GetBinUpEdge(i))]
433  yvals = [x for x in yvals if x != 0]
434  elif isinstance(obj, ROOT.TGraph) or isinstance(obj, ROOT.TGraph2D):
435  yvals = [obj.GetY()[i] for i in range(0, obj.GetN()) if inRange(obj.GetX()[i])]
436  else:
437  raise Exception("Unsupported type %s" % str(obj))
438  if len(yvals) == 0:
439  return (0, 0)
440  if len(yvals) == 1:
441  return (yvals[0], yvals[0])
442  if len(yvals) == 2:
443  return (yvals[0], yvals[1])
444 
445  yvals.sort()
446  nvals = int(len(yvals)*coverage)
447  if nvals < 2:
448  # Take median and +- 1 values
449  if len(yvals) % 2 == 0:
450  half = len(yvals)/2
451  return ( yvals[half-1], yvals[half] )
452  else:
453  middle = len(yvals)/2
454  return ( yvals[middle-1], yvals[middle+1] )
455  ind_min = (len(yvals)-nvals)/2
456  ind_max = len(yvals)-1 - ind_min
457 
458  return (yvals[ind_min], yvals[ind_max])
459 
460 def _findBounds(th1s, ylog, xmin=None, xmax=None, ymin=None, ymax=None):
461  """Find x-y axis boundaries encompassing a list of TH1s if the bounds are not given in arguments.
462 
463  Arguments:
464  th1s -- List of TH1s
465  ylog -- Boolean indicating if y axis is in log scale or not (affects the automatic ymax)
466 
467  Keyword arguments:
468  xmin -- Minimum x value; if None, take the minimum of TH1s
469  xmax -- Maximum x value; if None, take the maximum of TH1s
470  ymin -- Minimum y value; if None, take the minimum of TH1s
471  ymax -- Maximum y value; if None, take the maximum of TH1s
472  """
473 
474  (ymin, ymax) = _findBoundsY(th1s, ylog, ymin, ymax)
475 
476  if xmin is None or xmax is None or isinstance(xmin, list) or isinstance(max, list):
477  xmins = []
478  xmaxs = []
479  for th1 in th1s:
480  xmins.append(_getXmin(th1, limitToNonZeroContent=isinstance(xmin, list)))
481  xmaxs.append(_getXmax(th1, limitToNonZeroContent=isinstance(xmax, list)))
482 
483  # Filter out cases where histograms have zero content
484  xmins = [h for h in xmins if h is not None]
485  xmaxs = [h for h in xmaxs if h is not None]
486 
487  if xmin is None:
488  xmin = min(xmins)
489  elif isinstance(xmin, list):
490  if len(xmins) == 0: # all histograms zero
491  xmin = min(xmin)
492  if verbose:
493  print("Histogram is zero, using the smallest given value for xmin from", str(xmin))
494  else:
495  xm = min(xmins)
496  xmins_below = [x for x in xmin if x<=xm]
497  if len(xmins_below) == 0:
498  xmin = min(xmin)
499  if xm < xmin:
500  if verbose:
501  print("Histogram minimum x %f is below all given xmin values %s, using the smallest one" % (xm, str(xmin)))
502  else:
503  xmin = max(xmins_below)
504 
505  if xmax is None:
506  xmax = max(xmaxs)
507  elif isinstance(xmax, list):
508  if len(xmaxs) == 0: # all histograms zero
509  xmax = max(xmax)
510  if verbose:
511  print("Histogram is zero, using the smallest given value for xmax from", str(xmin))
512  else:
513  xm = max(xmaxs)
514  xmaxs_above = [x for x in xmax if x>xm]
515  if len(xmaxs_above) == 0:
516  xmax = max(xmax)
517  if xm > xmax:
518  if verbose:
519  print("Histogram maximum x %f is above all given xmax values %s, using the maximum one" % (xm, str(xmax)))
520  else:
521  xmax = min(xmaxs_above)
522 
523  for th1 in th1s:
524  th1.GetXaxis().SetRangeUser(xmin, xmax)
525 
526  return (xmin, ymin, xmax, ymax)
527 
528 def _findBoundsY(th1s, ylog, ymin=None, ymax=None, coverage=None, coverageRange=None):
529  """Find y axis boundaries encompassing a list of TH1s if the bounds are not given in arguments.
530 
531  Arguments:
532  th1s -- List of TH1s
533  ylog -- Boolean indicating if y axis is in log scale or not (affects the automatic ymax)
534 
535  Keyword arguments:
536  ymin -- Minimum y value; if None, take the minimum of TH1s
537  ymax -- Maximum y value; if None, take the maximum of TH1s
538  coverage -- If set, use only values within the 'coverage' part around the median are used for min/max (useful for ratio)
539  coverageRange -- If coverage and this are set, use only the x axis specified by an (xmin,xmax) pair for the coverage
540  """
541  if coverage is not None or isinstance(th1s[0], ROOT.TH2):
542  # the only use case for coverage for now is ratio, for which
543  # the scalings are not needed (actually harmful), so let's
544  # just ignore them if 'coverage' is set
545  #
546  # Also for TH2 do not adjust automatic y bounds
547  y_scale_max = lambda y: y
548  y_scale_min = lambda y: y
549  else:
550  if ylog:
551  y_scale_max = lambda y: y*1.5
552  else:
553  y_scale_max = lambda y: y*1.05
554  y_scale_min = lambda y: y*0.9 # assuming log
555 
556  if ymin is None or ymax is None or isinstance(ymin, list) or isinstance(ymax, list):
557  ymins = []
558  ymaxs = []
559  for th1 in th1s:
560  if coverage is not None:
561  (_ymin, _ymax) = _getYminMaxAroundMedian(th1, coverage, coverageRange)
562  else:
563  if ylog and isinstance(ymin, list):
564  _ymin = _getYminIgnoreOutlier(th1)
565  else:
566  _ymin = _getYmin(th1, limitToNonZeroContent=isinstance(ymin, list))
567  _ymax = _getYmax(th1, limitToNonZeroContent=isinstance(ymax, list))
568 # _ymax = _getYmaxWithError(th1)
569 
570  ymins.append(_ymin)
571  ymaxs.append(_ymax)
572 
573  if ymin is None:
574  ymin = min(ymins)
575  elif isinstance(ymin, list):
576  ym_unscaled = min(ymins)
577  ym = y_scale_min(ym_unscaled)
578  ymins_below = [y for y in ymin if y<=ym]
579  if len(ymins_below) == 0:
580  ymin = min(ymin)
581  if ym_unscaled < ymin:
582  if verbose:
583  print("Histogram minimum y %f is below all given ymin values %s, using the smallest one" % (ym, str(ymin)))
584  else:
585  ymin = max(ymins_below)
586 
587  if ymax is None:
588  # in case ymax is automatic, ymin is set by list, and the
589  # histograms are zero, ensure here that ymax > ymin
590  ymax = y_scale_max(max(ymaxs+[ymin]))
591  elif isinstance(ymax, list):
592  ym_unscaled = max(ymaxs)
593  ym = y_scale_max(ym_unscaled)
594  ymaxs_above = [y for y in ymax if y>ym]
595  if len(ymaxs_above) == 0:
596  ymax = max(ymax)
597  if ym_unscaled > ymax:
598  if verbose:
599  print("Histogram maximum y %f is above all given ymax values %s, using the maximum one" % (ym_unscaled, str(ymax)))
600  else:
601  ymax = min(ymaxs_above)
602 
603  for th1 in th1s:
604  th1.GetYaxis().SetRangeUser(ymin, ymax)
605 
606  return (ymin, ymax)
607 
608 def _th1RemoveEmptyBins(histos, xbinlabels):
609  binsToRemove = set()
610  for b in range(1, histos[0].GetNbinsX()+1):
611  binEmpty = True
612  for h in histos:
613  if h.GetBinContent(b) > 0:
614  binEmpty = False
615  break
616  if binEmpty:
617  binsToRemove.add(b)
618 
619  if len(binsToRemove) > 0:
620  # filter xbinlabels
621  xbinlab_new = []
622  for i in range(len(xbinlabels)):
623  if (i+1) not in binsToRemove:
624  xbinlab_new.append(xbinlabels[i])
625  xbinlabels = xbinlab_new
626 
627  # filter histogram bins
628  histos_new = []
629  for h in histos:
630  values = []
631  for b in range(1, h.GetNbinsX()+1):
632  if b not in binsToRemove:
633  values.append( (h.GetXaxis().GetBinLabel(b), h.GetBinContent(b), h.GetBinError(b)) )
634 
635  if len(values) > 0:
636  h_new = h.Clone(h.GetName()+"_empty")
637  h_new.SetBins(len(values), h.GetBinLowEdge(1), h.GetBinLowEdge(1)+len(values))
638  for b, (l, v, e) in enumerate(values):
639  h_new.GetXaxis().SetBinLabel(b+1, l)
640  h_new.SetBinContent(b+1, v)
641  h_new.SetBinError(b+1, e)
642 
643  histos_new.append(h_new)
644  histos = histos_new
645 
646  return (histos, xbinlabels)
647 
648 def _th2RemoveEmptyBins(histos, xbinlabels, ybinlabels):
649  xbinsToRemove = set()
650  ybinsToRemove = set()
651  for ih, h in enumerate(histos):
652  for bx in range(1, h.GetNbinsX()+1):
653  binEmpty = True
654  for by in range(1, h.GetNbinsY()+1):
655  if h.GetBinContent(bx, by) > 0:
656  binEmpty = False
657  break
658  if binEmpty:
659  xbinsToRemove.add(bx)
660  elif ih > 0:
661  xbinsToRemove.discard(bx)
662 
663  for by in range(1, h.GetNbinsY()+1):
664  binEmpty = True
665  for bx in range(1, h.GetNbinsX()+1):
666  if h.GetBinContent(bx, by) > 0:
667  binEmpty = False
668  break
669  if binEmpty:
670  ybinsToRemove.add(by)
671  elif ih > 0:
672  ybinsToRemove.discard(by)
673 
674  if len(xbinsToRemove) > 0 or len(ybinsToRemove) > 0:
675  xbinlabels_new = []
676  xbins = []
677  for b in range(1, len(xbinlabels)+1):
678  if b not in xbinsToRemove:
679  xbinlabels_new.append(histos[0].GetXaxis().GetBinLabel(b))
680  xbins.append(b)
681  xbinlabels = xbinlabels_new
682  ybinlabels_new = []
683  ybins = []
684  for b in range(1, len(ybinlabels)+1):
685  if b not in ybinsToRemove:
686  ybinlabels.append(histos[0].GetYaxis().GetBinLabel(b))
687  ybins.append(b)
688  ybinlabels = xbinlabels_new
689 
690  histos_new = []
691  if len(xbinlabels) == 0 or len(ybinlabels) == 0:
692  return (histos_new, xbinlabels, ybinlabels)
693  for h in histos:
694  h_new = ROOT.TH2F(h.GetName()+"_empty", h.GetTitle(), len(xbinlabels),0,len(xbinlabels), len(ybinlabels),0,len(ybinlabels))
695  for b, l in enumerate(xbinlabels):
696  h_new.GetXaxis().SetBinLabel(b+1, l)
697  for b, l in enumerate(ybinlabels):
698  h_new.GetYaxis().SetBinLabel(b+1, l)
699 
700  for ix, bx in enumerate(xbins):
701  for iy, by in enumerate(ybins):
702  h_new.SetBinContent(ix+1, iy+1, h.GetBinContent(bx, by))
703  h_new.SetBinError(ix+1, iy+1, h.GetBinError(bx, by))
704  histos_new.append(h_new)
705  histos = histos_new
706  return (histos, xbinlabels, ybinlabels)
707 
708 def _mergeBinLabelsX(histos):
709  return _mergeBinLabels([[h.GetXaxis().GetBinLabel(i) for i in range(1, h.GetNbinsX()+1)] for h in histos])
710 
711 def _mergeBinLabelsY(histos):
712  return _mergeBinLabels([[h.GetYaxis().GetBinLabel(i) for i in range(1, h.GetNbinsY()+1)] for h in histos])
713 
714 def _mergeBinLabels(labelsAll):
715  labels_merged = labelsAll[0]
716  for labels in labelsAll[1:]:
717  diff = difflib.unified_diff(labels_merged, labels, n=max(len(labels_merged), len(labels)))
718  labels_merged = []
719  operation = []
720  for item in diff: # skip the "header" lines
721  if item[:2] == "@@":
722  break
723  for item in diff:
724  operation.append(item[0])
725  lab = item[1:]
726  if lab in labels_merged:
727  # pick the last addition of the bin
728  ind = labels_merged.index(lab)
729  if operation[ind] == "-" and operation[-1] == "+":
730  labels_merged.remove(lab)
731  del operation[ind] # to keep xbinlabels and operation indices in sync
732  elif operation[ind] == "+" and operation[-1] == "-":
733  del operation[-1] # to keep xbinlabels and operation indices in sync
734  continue
735  else:
736  raise Exception("This should never happen")
737  labels_merged.append(lab)
738  # unified_diff returns empty diff if labels_merged and labels are equal
739  # so if labels_merged is empty here, it can be just set to labels
740  if len(labels_merged) == 0:
741  labels_merged = labels
742 
743  return labels_merged
744 
745 def _th1IncludeOnlyBins(histos, xbinlabels):
746  histos_new = []
747  for h in histos:
748  h_new = h.Clone(h.GetName()+"_xbinlabels")
749  h_new.SetBins(len(xbinlabels), h.GetBinLowEdge(1), h.GetBinLowEdge(1)+len(xbinlabels))
750  for i, label in enumerate(xbinlabels):
751  bin = h.GetXaxis().FindFixBin(label)
752  if bin >= 0:
753  h_new.SetBinContent(i+1, h.GetBinContent(bin))
754  h_new.SetBinError(i+1, h.GetBinError(bin))
755  else:
756  h_new.SetBinContent(i+1, 0)
757  h_new.SetBinError(i+1, 0)
758  histos_new.append(h_new)
759  return histos_new
760 
761 
762 class Subtract:
763  """Class for subtracting two histograms"""
764  def __init__(self, name, nameA, nameB, title=""):
765  """Constructor
766 
767  Arguments:
768  name -- String for name of the resulting histogram (A-B)
769  nameA -- String for A histogram
770  nameB -- String for B histogram
771 
772  Keyword arguments:
773  title -- String for a title of the resulting histogram (default "")
774 
775  Uncertainties are calculated with the assumption that B is a
776  subset of A, and the histograms contain event counts.
777  """
778  self._name = name
779  self._nameA = nameA
780  self._nameB = nameB
781  self._title = title
782 
783  def __str__(self):
784  """String representation, returns the name"""
785  return self._name
786 
787  def create(self, tdirectory):
788  """Create and return the fake+duplicate histogram from a TDirectory"""
789  histoA = _getObject(tdirectory, self._nameA)
790  histoB = _getObject(tdirectory, self._nameB)
791 
792  if not histoA or not histoB:
793  return None
794 
795  ret = histoA.Clone(self._name)
796  ret.SetTitle(self._title)
797 
798  # Disable canExtend if it is set, otherwise setting the
799  # overflow bin will extend instead, possibly causing weird
800  # effects downstream
801  ret.SetCanExtend(False)
802 
803  for i in range(0, histoA.GetNbinsX()+2): # include under- and overflow too
804  val = histoA.GetBinContent(i)-histoB.GetBinContent(i)
805  ret.SetBinContent(i, val)
806  ret.SetBinError(i, math.sqrt(val))
807 
808  return ret
809 
810 class Transform:
811  """Class to transform bin contents in an arbitrary way."""
812  def __init__(self, name, histo, func, title=""):
813  """Constructor.
814 
815  Argument:
816  name -- String for name of the resulting histogram
817  histo -- String for a source histogram (needs to be cumulative)
818  func -- Function to operate on the bin content
819  """
820  self._name = name
821  self._histo = histo
822  self._func = func
823  self._title = title
824 
825  def __str__(self):
826  """String representation, returns the name"""
827  return self._name
828 
829  def create(self, tdirectory):
830  """Create and return the transformed histogram from a TDirectory"""
831  histo = _getOrCreateObject(tdirectory, self._histo)
832  if not histo:
833  return None
834 
835  ret = histo.Clone(self._name)
836  ret.SetTitle(self._title)
837 
838  # Disable canExtend if it is set, otherwise setting the
839  # overflow bin will extend instead, possibly causing weird
840  # effects downstream
841  ret.SetCanExtend(False)
842 
843  for i in range(0, histo.GetNbinsX()+2):
844  ret.SetBinContent(i, self._func(histo.GetBinContent(i)))
845  return ret
846 
848  """Class to calculate the fake+duplicate rate"""
849  def __init__(self, name, assoc, dup, reco, title=""):
850  """Constructor.
851 
852  Arguments:
853  name -- String for the name of the resulting efficiency histogram
854  assoc -- String for the name of the "associated" histogram
855  dup -- String for the name of the "duplicates" histogram
856  reco -- String for the name of the "reco" (denominator) histogram
857 
858  Keyword arguments:
859  title -- String for a title of the resulting histogram (default "")
860 
861  The result is calculated as 1 - (assoc - dup) / reco
862  """
863  self._name = name
864  self._assoc = assoc
865  self._dup = dup
866  self._reco = reco
867  self._title = title
868 
869  def __str__(self):
870  """String representation, returns the name"""
871  return self._name
872 
873  def create(self, tdirectory):
874  """Create and return the fake+duplicate histogram from a TDirectory"""
875  # Get the numerator/denominator histograms
876  hassoc = _getObject(tdirectory, self._assoc)
877  hdup = _getObject(tdirectory, self._dup)
878  hreco = _getObject(tdirectory, self._reco)
879 
880  # Skip if any of them does not exist
881  if not hassoc or not hdup or not hreco:
882  return None
883 
884  hfakedup = hreco.Clone(self._name)
885  hfakedup.SetTitle(self._title)
886 
887  for i in range(1, hassoc.GetNbinsX()+1):
888  numerVal = hassoc.GetBinContent(i) - hdup.GetBinContent(i)
889  denomVal = hreco.GetBinContent(i)
890 
891  fakedupVal = (1 - numerVal / denomVal) if denomVal != 0.0 else 0.0
892  errVal = math.sqrt(fakedupVal*(1-fakedupVal)/denomVal) if (denomVal != 0.0 and fakedupVal <= 1) else 0.0
893 
894  hfakedup.SetBinContent(i, fakedupVal)
895  hfakedup.SetBinError(i, errVal)
896 
897  return hfakedup
898 
900  """Class for making a cut efficiency histograms.
901 
902  N after cut
903  eff = -----------
904  N total
905  """
906  def __init__(self, name, histo, title=""):
907  """Constructor
908 
909  Arguments:
910  name -- String for name of the resulting histogram
911  histo -- String for a source histogram (needs to be cumulative)
912  """
913  self._name = name
914  self._histo = histo
915  self._title = title
916 
917  def __str__(self):
918  """String representation, returns the name"""
919  return self._name
920 
921  def create(self, tdirectory):
922  """Create and return the cut efficiency histogram from a TDirectory"""
923  histo = _getOrCreateObject(tdirectory, self._histo)
924  if not histo:
925  return None
926 
927  # infer cumulative direction from the under/overflow bins
928  ascending = histo.GetBinContent(0) < histo.GetBinContent(histo.GetNbinsX())
929  if ascending:
930  n_tot = histo.GetBinContent(histo.GetNbinsX())
931  else:
932  n_tot = histo.GetBinContent(0)
933 
934  if n_tot == 0:
935  return histo
936 
937  ret = histo.Clone(self._name)
938  ret.SetTitle(self._title)
939 
940  # calculate efficiency
941  for i in range(1, histo.GetNbinsX()+1):
942  n = histo.GetBinContent(i)
943  val = n/n_tot
944  errVal = math.sqrt(val*(1-val)/n_tot)
945  ret.SetBinContent(i, val)
946  ret.SetBinError(i, errVal)
947  return ret
948 
950  """Class to create a histogram by aggregating bins of another histogram to a bin of the resulting histogram."""
951  def __init__(self, name, histoName, mapping, normalizeTo=None, scale=None, renameBin=None, ignoreMissingBins=False, minExistingBins=None, originalOrder=False, reorder=None):
952  """Constructor.
953 
954  Arguments:
955  name -- String for the name of the resulting histogram
956  histoName -- String for the name of the source histogram
957  mapping -- Dictionary for mapping the bins (see below)
958 
959  Keyword arguments:
960  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.
961  scale -- Optional number for scaling the histogram (passed to ROOT.TH1.Scale())
962  renameBin -- Optional function (string -> string) to rename the bins of the input histogram
963  originalOrder -- Boolean for using the order of bins in the histogram (default False)
964  reorder -- Optional function to reorder the bins
965 
966  Mapping structure (mapping):
967 
968  Dictionary (you probably want to use collections.OrderedDict)
969  should be a mapping from the destination bin label to a list
970  of source bin labels ("dst -> [src]").
971  """
972  self._name = name
973  self._histoName = histoName
974  self._mapping = mapping
975  self._normalizeTo = normalizeTo
976  self._scale = scale
977  self._renameBin = renameBin
978  self._ignoreMissingBins = ignoreMissingBins
979  self._minExistingBins = minExistingBins
980  self._originalOrder = originalOrder
981  self._reorder = reorder
982  if self._originalOrder and self._reorder is not None:
983  raise Exception("reorder is not None and originalOrder is True, please set only one of them")
984 
985  def __str__(self):
986  """String representation, returns the name"""
987  return self._name
988 
989  def create(self, tdirectory):
990  """Create and return the histogram from a TDirectory"""
991  th1 = _getOrCreateObject(tdirectory, self._histoName)
992  if th1 is None:
993  return None
994 
995  binLabels = [""]*len(self._mapping)
996  binValues = [None]*len(self._mapping)
997 
998  # TH1 can't really be used as a map/dict, so convert it here:
999  values = _th1ToOrderedDict(th1, self._renameBin)
1000 
1001  binIndexOrder = [] # for reordering bins if self._originalOrder is True
1002  for i, (key, labels) in enumerate(six.iteritems(self._mapping)):
1003  sumTime = 0.
1004  sumErrorSq = 0.
1005  nsum = 0
1006  for l in labels:
1007  try:
1008  sumTime += values[l][0]
1009  sumErrorSq += values[l][1]**2
1010  nsum += 1
1011  except KeyError:
1012  pass
1013 
1014  if nsum > 0:
1015  binValues[i] = (sumTime, math.sqrt(sumErrorSq))
1016  binLabels[i] = key
1017 
1018  ivalue = len(values)+1
1019  if len(labels) > 0:
1020  # first label doesn't necessarily exist (especially for
1021  # the iteration timing plots), so let's test them all
1022  for lab in labels:
1023  if lab in values:
1024  ivalue = values.keys().index(lab)
1025  break
1026  binIndexOrder.append( (ivalue, i) )
1027 
1028  if self._originalOrder:
1029  binIndexOrder.sort(key=lambda t: t[0])
1030  tmpVal = []
1031  tmpLab = []
1032  for i in range(0, len(binValues)):
1033  fromIndex = binIndexOrder[i][1]
1034  tmpVal.append(binValues[fromIndex])
1035  tmpLab.append(binLabels[fromIndex])
1036  binValues = tmpVal
1037  binLabels = tmpLab
1038  if self._reorder is not None:
1039  order = self._reorder(tdirectory, binLabels)
1040  binValues = [binValues[i] for i in order]
1041  binLabels = [binLabels[i] for i in order]
1042 
1043  if self._minExistingBins is not None and (len(binValues)-binValues.count(None)) < self._minExistingBins:
1044  return None
1045 
1046  if self._ignoreMissingBins:
1047  for i, val in enumerate(binValues):
1048  if val is None:
1049  binLabels[i] = None
1050  binValues = [v for v in binValues if v is not None]
1051  binLabels = [v for v in binLabels if v is not None]
1052  if len(binValues) == 0:
1053  return None
1054 
1055  result = ROOT.TH1F(self._name, self._name, len(binValues), 0, len(binValues))
1056  for i, (value, label) in enumerate(zip(binValues, binLabels)):
1057  if value is not None:
1058  result.SetBinContent(i+1, value[0])
1059  result.SetBinError(i+1, value[1])
1060  result.GetXaxis().SetBinLabel(i+1, label)
1061 
1062  if self._normalizeTo is not None:
1063  bin = th1.GetXaxis().FindBin(self._normalizeTo)
1064  if bin <= 0:
1065  print("Trying to normalize {name} to {binlabel}, which does not exist".format(name=self._name, binlabel=self._normalizeTo))
1066  sys.exit(1)
1067  value = th1.GetBinContent(bin)
1068  if value != 0:
1069  result.Scale(1/value)
1070 
1071  if self._scale is not None:
1072  result.Scale(self._scale)
1073 
1074  return result
1075 
1077  """Class to create a histogram by aggregaging integrals of another histoggrams."""
1078  def __init__(self, name, mapping, normalizeTo=None):
1079  """Constructor.
1080 
1081  Arguments:
1082  name -- String for the name of the resulting histogram
1083  mapping -- Dictionary for mapping the bin label to a histogram name
1084 
1085  Keyword arguments:
1086  normalizeTo -- Optional string for a histogram. If given, all bins of the resulting histograqm are divided by the integral of this histogram.
1087  """
1088  self._name = name
1089  self._mapping = mapping
1090  self._normalizeTo = normalizeTo
1091 
1092  def __str__(self):
1093  """String representation, returns the name"""
1094  return self._name
1095 
1096  def create(self, tdirectory):
1097  """Create and return the histogram from a TDirectory"""
1098  result = []
1099  for key, histoName in six.iteritems(self._mapping):
1100  th1 = _getObject(tdirectory, histoName)
1101  if th1 is None:
1102  continue
1103  result.append( (key, th1.Integral(0, th1.GetNbinsX()+1)) ) # include under- and overflow bins
1104  if len(result) == 0:
1105  return None
1106 
1107  res = ROOT.TH1F(self._name, self._name, len(result), 0, len(result))
1108 
1109  for i, (name, count) in enumerate(result):
1110  res.SetBinContent(i+1, count)
1111  res.GetXaxis().SetBinLabel(i+1, name)
1112 
1113  if self._normalizeTo is not None:
1114  th1 = _getObject(tdirectory, self._normalizeTo)
1115  if th1 is None:
1116  return None
1117  scale = th1.Integral(0, th1.GetNbinsX()+1)
1118  res.Scale(1/scale)
1119 
1120  return res
1121 
1122 class ROC:
1123  """Class to construct a ROC curve (e.g. efficiency vs. fake rate) from two histograms"""
1124  def __init__(self, name, xhistoName, yhistoName, zaxis=False):
1125  """Constructor.
1126 
1127  Arguments:
1128  name -- String for the name of the resulting histogram
1129  xhistoName -- String for the name of the x-axis histogram (or another "creator" object)
1130  yhistoName -- String for the name of the y-axis histogram (or another "creator" object)
1131 
1132  Keyword arguments:
1133  zaxis -- If set to True (default False), create a TGraph2D with z axis showing the cut value (recommended drawStyle 'pcolz')
1134  """
1135  self._name = name
1136  self._xhistoName = xhistoName
1137  self._yhistoName = yhistoName
1138  self._zaxis = zaxis
1139 
1140  def __str__(self):
1141  """String representation, returns the name"""
1142  return self._name
1143 
1144  def create(self, tdirectory):
1145  """Create and return the histogram from a TDirectory"""
1146  xhisto = _getOrCreateObject(tdirectory, self._xhistoName)
1147  yhisto = _getOrCreateObject(tdirectory, self._yhistoName);
1148  if xhisto is None or yhisto is None:
1149  return None
1150 
1151  x = []
1152  xerrup = []
1153  xerrdown = []
1154  y = []
1155  yerrup = []
1156  yerrdown = []
1157  z = []
1158 
1159  for i in range(1, xhisto.GetNbinsX()+1):
1160  x.append(xhisto.GetBinContent(i))
1161  xerrup.append(xhisto.GetBinError(i))
1162  xerrdown.append(xhisto.GetBinError(i))
1163 
1164  y.append(yhisto.GetBinContent(i))
1165  yerrup.append(yhisto.GetBinError(i))
1166  yerrdown.append(yhisto.GetBinError(i))
1167 
1168  z.append(xhisto.GetXaxis().GetBinUpEdge(i))
1169 
1170  # If either axis has only zeroes, no graph makes no point
1171  if x.count(0.0) == len(x) or y.count(0.0) == len(y):
1172  return None
1173 
1174  arr = lambda v: array.array("d", v)
1175  gr = None
1176  if self._zaxis:
1177  gr = ROOT.TGraph2D(len(x), arr(x), arr(y), arr(z))
1178  else:
1179  gr = ROOT.TGraphAsymmErrors(len(x), arr(x), arr(y), arr(xerrdown), arr(xerrup), arr(yerrdown), arr(yerrup))
1180  gr.SetTitle("")
1181  return gr
1182 
1183 
1184 # Plot styles
1185 _plotStylesColor = [4, 2, ROOT.kBlack, ROOT.kOrange+7, ROOT.kMagenta-3, ROOT.kGreen+2]
1186 _plotStylesMarker = [21, 20, 22, 34, 33, 23]
1187 
1188 def _drawFrame(pad, bounds, zmax=None, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ybinlabels=None, suffix=""):
1189  """Function to draw a frame
1190 
1191  Arguments:
1192  pad -- TPad to where the frame is drawn
1193  bounds -- List or 4-tuple for (xmin, ymin, xmax, ymax)
1194 
1195  Keyword arguments:
1196  zmax -- Maximum Z, needed for TH2 histograms
1197  xbinlabels -- Optional list of strings for x axis bin labels
1198  xbinlabelsize -- Optional number for the x axis bin label size
1199  xbinlabeloption -- Optional string for the x axis bin options (passed to ROOT.TH1.LabelsOption())
1200  suffix -- Optional string for a postfix of the frame name
1201  """
1202  if xbinlabels is None and ybinlabels is None:
1203  frame = pad.DrawFrame(*bounds)
1204  else:
1205  # Special form needed if want to set x axis bin labels
1206  nbins = len(xbinlabels)
1207  if ybinlabels is None:
1208  frame = ROOT.TH1F("hframe"+suffix, "", nbins, bounds[0], bounds[2])
1209  frame.SetMinimum(bounds[1])
1210  frame.SetMaximum(bounds[3])
1211  frame.GetYaxis().SetLimits(bounds[1], bounds[3])
1212  else:
1213  ybins = len(ybinlabels)
1214  frame = ROOT.TH2F("hframe"+suffix, "", nbins,bounds[0],bounds[2], ybins,bounds[1],bounds[3])
1215  frame.SetMaximum(zmax)
1216 
1217  frame.SetBit(ROOT.TH1.kNoStats)
1218  frame.SetBit(ROOT.kCanDelete)
1219  frame.Draw("")
1220 
1221  xaxis = frame.GetXaxis()
1222  for i in range(nbins):
1223  xaxis.SetBinLabel(i+1, xbinlabels[i])
1224  if xbinlabelsize is not None:
1225  xaxis.SetLabelSize(xbinlabelsize)
1226  if xbinlabeloption is not None:
1227  frame.LabelsOption(xbinlabeloption)
1228 
1229  if ybinlabels is not None:
1230  yaxis = frame.GetYaxis()
1231  for i, lab in enumerate(ybinlabels):
1232  yaxis.SetBinLabel(i+1, lab)
1233  if xbinlabelsize is not None:
1234  yaxis.SetLabelSize(xbinlabelsize)
1235  if xbinlabeloption is not None:
1236  frame.LabelsOption(xbinlabeloption, "Y")
1237 
1238  return frame
1239 
1240 class Frame:
1241  """Class for creating and managing a frame for a simple, one-pad plot"""
1242  def __init__(self, pad, bounds, zmax, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ybinlabels=None):
1243  self._pad = pad
1244  self._frame = _drawFrame(pad, bounds, zmax, xbinlabels, xbinlabelsize, xbinlabeloption, ybinlabels)
1245 
1246  yoffsetFactor = 1
1247  xoffsetFactor = 1
1248  if nrows == 2:
1249  yoffsetFactor *= 2
1250  xoffsetFactor *= 2
1251  elif nrows >= 5:
1252  yoffsetFactor *= 1.5
1253  xoffsetFactor *= 1.5
1254  elif nrows >= 3:
1255  yoffsetFactor *= 4
1256  xoffsetFactor *= 3
1257 
1258  self._frame.GetYaxis().SetTitleOffset(self._frame.GetYaxis().GetTitleOffset()*yoffsetFactor)
1259  self._frame.GetXaxis().SetTitleOffset(self._frame.GetXaxis().GetTitleOffset()*xoffsetFactor)
1260 
1261 
1262  def setLogx(self, log):
1263  self._pad.SetLogx(log)
1264 
1265  def setLogy(self, log):
1266  self._pad.SetLogy(log)
1267 
1268  def setGridx(self, grid):
1269  self._pad.SetGridx(grid)
1270 
1271  def setGridy(self, grid):
1272  self._pad.SetGridy(grid)
1273 
1274  def adjustMarginLeft(self, adjust):
1275  self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1276  # Need to redraw frame after adjusting the margin
1277  self._pad.cd()
1278  self._frame.Draw("")
1279 
1280  def adjustMarginRight(self, adjust):
1281  self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1282  # Need to redraw frame after adjusting the margin
1283  self._pad.cd()
1284  self._frame.Draw("")
1285 
1286  def setTitle(self, title):
1287  self._frame.SetTitle(title)
1288 
1289  def setXTitle(self, title):
1290  self._frame.GetXaxis().SetTitle(title)
1291 
1292  def setXTitleSize(self, size):
1293  self._frame.GetXaxis().SetTitleSize(size)
1294 
1295  def setXTitleOffset(self, offset):
1296  self._frame.GetXaxis().SetTitleOffset(offset)
1297 
1298  def setXLabelSize(self, size):
1299  self._frame.GetXaxis().SetLabelSize(size)
1300 
1301  def setYTitle(self, title):
1302  self._frame.GetYaxis().SetTitle(title)
1303 
1304  def setYTitleSize(self, size):
1305  self._frame.GetYaxis().SetTitleSize(size)
1306 
1307  def setYTitleOffset(self, offset):
1308  self._frame.GetYaxis().SetTitleOffset(offset)
1309 
1310  def redrawAxis(self):
1311  self._pad.RedrawAxis()
1312 
1314  """Class for creating and managing a frame for a ratio plot with two subpads"""
1315  def __init__(self, pad, bounds, zmax, ratioBounds, ratioFactor, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ratioYTitle=_ratioYTitle):
1316  self._parentPad = pad
1317  self._pad = pad.cd(1)
1318  if xbinlabels is not None:
1319  self._frame = _drawFrame(self._pad, bounds, zmax, [""]*len(xbinlabels))
1320  else:
1321  self._frame = _drawFrame(self._pad, bounds, zmax)
1322  self._padRatio = pad.cd(2)
1323  self._frameRatio = _drawFrame(self._padRatio, ratioBounds, zmax, xbinlabels, xbinlabelsize, xbinlabeloption)
1324 
1325  self._frame.GetXaxis().SetLabelSize(0)
1326  self._frame.GetXaxis().SetTitleSize(0)
1327 
1328  yoffsetFactor = ratioFactor
1329  divisionPoint = 1-1/ratioFactor
1330  xoffsetFactor = 1/divisionPoint #* 0.6
1331 
1332  if nrows == 1:
1333  xoffsetFactor *= 0.6
1334  elif nrows == 2:
1335  yoffsetFactor *= 2
1336  xoffsetFactor *= 1.5
1337  elif nrows == 3:
1338  yoffsetFactor *= 4
1339  xoffsetFactor *= 2.3
1340  elif nrows >= 4:
1341  yoffsetFactor *= 5
1342  xoffsetFactor *= 3
1343 
1344  self._frame.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
1345  self._frameRatio.GetYaxis().SetLabelSize(int(self._frameRatio.GetYaxis().GetLabelSize()*0.8))
1346  self._frameRatio.GetYaxis().SetTitleOffset(self._frameRatio.GetYaxis().GetTitleOffset()*yoffsetFactor)
1347  self._frameRatio.GetXaxis().SetTitleOffset(self._frameRatio.GetXaxis().GetTitleOffset()*xoffsetFactor)
1348 
1349  self._frameRatio.GetYaxis().SetNdivisions(4, 5, 0)
1350 
1351  self._frameRatio.GetYaxis().SetTitle(ratioYTitle)
1352 
1353  def setLogx(self, log):
1354  self._pad.SetLogx(log)
1355  self._padRatio.SetLogx(log)
1356 
1357  def setLogy(self, log):
1358  self._pad.SetLogy(log)
1359 
1360  def setGridx(self, grid):
1361  self._pad.SetGridx(grid)
1362  self._padRatio.SetGridx(grid)
1363 
1364  def setGridy(self, grid):
1365  self._pad.SetGridy(grid)
1366  self._padRatio.SetGridy(grid)
1367 
1368  def adjustMarginLeft(self, adjust):
1369  self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1370  self._padRatio.SetLeftMargin(self._padRatio.GetLeftMargin()+adjust)
1371  # Need to redraw frame after adjusting the margin
1372  self._pad.cd()
1373  self._frame.Draw("")
1374  self._padRatio.cd()
1375  self._frameRatio.Draw("")
1376 
1377  def adjustMarginRight(self, adjust):
1378  self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1379  self._padRatio.SetRightMargin(self._padRatio.GetRightMargin()+adjust)
1380  # Need to redraw frames after adjusting the margin
1381  self._pad.cd()
1382  self._frame.Draw("")
1383  self._padRatio.cd()
1384  self._frameRatio.Draw("")
1385 
1386  def setTitle(self, title):
1387  self._frame.SetTitle(title)
1388 
1389  def setXTitle(self, title):
1390  self._frameRatio.GetXaxis().SetTitle(title)
1391 
1392  def setXTitleSize(self, size):
1393  self._frameRatio.GetXaxis().SetTitleSize(size)
1394 
1395  def setXTitleOffset(self, offset):
1396  self._frameRatio.GetXaxis().SetTitleOffset(offset)
1397 
1398  def setXLabelSize(self, size):
1399  self._frameRatio.GetXaxis().SetLabelSize(size)
1400 
1401  def setYTitle(self, title):
1402  self._frame.GetYaxis().SetTitle(title)
1403 
1404  def setYTitleRatio(self, title):
1405  self._frameRatio.GetYaxis().SetTitle(title)
1406 
1407  def setYTitleSize(self, size):
1408  self._frame.GetYaxis().SetTitleSize(size)
1409  self._frameRatio.GetYaxis().SetTitleSize(size)
1410 
1411  def setYTitleOffset(self, offset):
1412  self._frame.GetYaxis().SetTitleOffset(offset)
1413  self._frameRatio.GetYaxis().SetTitleOffset(offset)
1414 
1415  def redrawAxis(self):
1416  self._padRatio.RedrawAxis()
1417  self._pad.RedrawAxis()
1418 
1419  self._parentPad.cd()
1420 
1421  # pad to hide the lowest y axis label of the main pad
1422  xmin=0.065
1423  ymin=0.285
1424  xmax=0.128
1425  ymax=0.33
1426  self._coverPad = ROOT.TPad("coverpad", "coverpad", xmin, ymin, xmax, ymax)
1427  self._coverPad.SetBorderMode(0)
1428  self._coverPad.Draw()
1429 
1430  self._pad.cd()
1431  self._pad.Pop() # Move the first pad on top
1432 
1434  """Class for creating and managing a frame for a plot from TGraph2D"""
1435  def __init__(self, pad, bounds, histos, ratioOrig, ratioFactor):
1436  self._pad = pad
1437  if ratioOrig:
1438  self._pad = pad.cd(1)
1439 
1440  # adjust margins because of not having the ratio, we want
1441  # the same bottom margin, so some algebra gives this
1442  (xlow, ylow, width, height) = (self._pad.GetXlowNDC(), self._pad.GetYlowNDC(), self._pad.GetWNDC(), self._pad.GetHNDC())
1443  xup = xlow+width
1444  yup = ylow+height
1445 
1446  bottomMargin = self._pad.GetBottomMargin()
1447  bottomMarginNew = ROOT.gStyle.GetPadBottomMargin()
1448 
1449  ylowNew = yup - (1-bottomMargin)/(1-bottomMarginNew) * (yup-ylow)
1450  topMarginNew = self._pad.GetTopMargin() * (yup-ylow)/(yup-ylowNew)
1451 
1452  self._pad.SetPad(xlow, ylowNew, xup, yup)
1453  self._pad.SetTopMargin(topMarginNew)
1454  self._pad.SetBottomMargin(bottomMarginNew)
1455 
1456  self._xtitleoffset = 1.8
1457  self._ytitleoffset = 2.3
1458 
1459  self._firstHisto = histos[0]
1460 
1461  def setLogx(self, log):
1462  pass
1463 
1464  def setLogy(self, log):
1465  pass
1466 
1467  def setGridx(self, grid):
1468  pass
1469 
1470  def setGridy(self, grid):
1471  pass
1472 
1473  def adjustMarginLeft(self, adjust):
1474  self._pad.SetLeftMargin(self._pad.GetLeftMargin()+adjust)
1475  self._pad.cd()
1476 
1477  def adjustMarginRight(self, adjust):
1478  self._pad.SetRightMargin(self._pad.GetRightMargin()+adjust)
1479  self._pad.cd()
1480 
1481  def setTitle(self, title):
1482  pass
1483 
1484  def setXTitle(self, title):
1485  self._xtitle = title
1486 
1487  def setXTitleSize(self, size):
1488  self._xtitlesize = size
1489 
1490  def setXTitleOffset(self, size):
1491  self._xtitleoffset = size
1492 
1493  def setXLabelSize(self, size):
1494  self._xlabelsize = size
1495 
1496  def setYTitle(self, title):
1497  self._ytitle = title
1498 
1499  def setYTitleSize(self, size):
1500  self._ytitlesize = size
1501 
1502  def setYTitleOffset(self, offset):
1503  self._ytitleoffset = offset
1504 
1505  def setZTitle(self, title):
1506  self._firstHisto.GetZaxis().SetTitle(title)
1507 
1508  def setZTitleOffset(self, offset):
1509  self._firstHisto.GetZaxis().SetTitleOffset(offset)
1510 
1511  def redrawAxis(self):
1512  # set top view
1513  epsilon = 1e-7
1514  self._pad.SetPhi(epsilon)
1515  self._pad.SetTheta(90+epsilon)
1516 
1517  self._firstHisto.GetXaxis().SetTitleOffset(self._xtitleoffset)
1518  self._firstHisto.GetYaxis().SetTitleOffset(self._ytitleoffset)
1519 
1520  if hasattr(self, "_xtitle"):
1521  self._firstHisto.GetXaxis().SetTitle(self._xtitle)
1522  if hasattr(self, "_xtitlesize"):
1523  self._firstHisto.GetXaxis().SetTitleSize(self._xtitlesize)
1524  if hasattr(self, "_xlabelsize"):
1525  self._firstHisto.GetXaxis().SetLabelSize(self._labelsize)
1526  if hasattr(self, "_ytitle"):
1527  self._firstHisto.GetYaxis().SetTitle(self._ytitle)
1528  if hasattr(self, "_ytitlesize"):
1529  self._firstHisto.GetYaxis().SetTitleSize(self._ytitlesize)
1530  if hasattr(self, "_ytitleoffset"):
1531  self._firstHisto.GetYaxis().SetTitleOffset(self._ytitleoffset)
1532 
1533 class PlotText:
1534  """Abstraction on top of TLatex"""
1535  def __init__(self, x, y, text, size=None, bold=True, align="left", color=ROOT.kBlack, font=None):
1536  """Constructor.
1537 
1538  Arguments:
1539  x -- X coordinate of the text (in NDC)
1540  y -- Y coordinate of the text (in NDC)
1541  text -- String to draw
1542  size -- Size of text (None for the default value, taken from gStyle)
1543  bold -- Should the text be bold?
1544  align -- Alignment of text (left, center, right)
1545  color -- Color of the text
1546  font -- Specify font explicitly
1547  """
1548  self._x = x
1549  self._y = y
1550  self._text = text
1551 
1552  self._l = ROOT.TLatex()
1553  self._l.SetNDC()
1554  if not bold:
1555  self._l.SetTextFont(self._l.GetTextFont()-20) # bold -> normal
1556  if font is not None:
1557  self._l.SetTextFont(font)
1558  if size is not None:
1559  self._l.SetTextSize(size)
1560  if isinstance(align, str):
1561  if align.lower() == "left":
1562  self._l.SetTextAlign(11)
1563  elif align.lower() == "center":
1564  self._l.SetTextAlign(21)
1565  elif align.lower() == "right":
1566  self._l.SetTextAlign(31)
1567  else:
1568  raise Exception("Error: Invalid option '%s' for text alignment! Options are: 'left', 'center', 'right'."%align)
1569  else:
1570  self._l.SetTextAlign(align)
1571  self._l.SetTextColor(color)
1572 
1573  def Draw(self, options=None):
1574  """Draw the text to the current TPad.
1575 
1576  Arguments:
1577  options -- For interface compatibility, ignored
1578 
1579  Provides interface compatible with ROOT's drawable objects.
1580  """
1581  self._l.DrawLatex(self._x, self._y, self._text)
1582 
1583 
1585  """Class for drawing text and a background box."""
1586  def __init__(self, xmin, ymin, xmax, ymax, lineheight=0.04, fillColor=ROOT.kWhite, transparent=True, **kwargs):
1587  """Constructor
1588 
1589  Arguments:
1590  xmin -- X min coordinate of the box (NDC)
1591  ymin -- Y min coordinate of the box (NDC) (if None, deduced automatically)
1592  xmax -- X max coordinate of the box (NDC)
1593  ymax -- Y max coordinate of the box (NDC)
1594  lineheight -- Line height
1595  fillColor -- Fill color of the box
1596  transparent -- Should the box be transparent? (in practive the TPave is not created)
1597 
1598  Keyword arguments are forwarded to constructor of PlotText
1599  """
1600  # ROOT.TPave Set/GetX1NDC() etc don't seem to work as expected.
1601  self._xmin = xmin
1602  self._xmax = xmax
1603  self._ymin = ymin
1604  self._ymax = ymax
1605  self._lineheight = lineheight
1606  self._fillColor = fillColor
1607  self._transparent = transparent
1608  self._texts = []
1609  self._textArgs = {}
1610  self._textArgs.update(kwargs)
1611 
1612  self._currenty = ymax
1613 
1614  def addText(self, text):
1615  """Add text to current position"""
1616  self._currenty -= self._lineheight
1617  self._texts.append(PlotText(self._xmin+0.01, self._currenty, text, **self._textArgs))
1618 
1619  def width(self):
1620  return self._xmax-self._xmin
1621 
1622  def move(self, dx=0, dy=0, dw=0, dh=0):
1623  """Move the box and the contained text objects
1624 
1625  Arguments:
1626  dx -- Movement in x (positive is to right)
1627  dy -- Movement in y (positive is to up)
1628  dw -- Increment of width (negative to decrease width)
1629  dh -- Increment of height (negative to decrease height)
1630 
1631  dx and dy affect to both box and text objects, dw and dh
1632  affect the box only.
1633  """
1634  self._xmin += dx
1635  self._xmax += dx
1636  if self._ymin is not None:
1637  self._ymin += dy
1638  self._ymax += dy
1639 
1640  self._xmax += dw
1641  if self._ymin is not None:
1642  self._ymin -= dh
1643 
1644  for t in self._texts:
1645  t._x += dx
1646  t._y += dy
1647 
1648  def Draw(self, options=""):
1649  """Draw the box and the text to the current TPad.
1650 
1651  Arguments:
1652  options -- Forwarded to ROOT.TPave.Draw(), and the Draw() of the contained objects
1653  """
1654  if not self._transparent:
1655  ymin = self.ymin
1656  if ymin is None:
1657  ymin = self.currenty - 0.01
1658  self._pave = ROOT.TPave(self.xmin, self.ymin, self.xmax, self.ymax, 0, "NDC")
1659  self._pave.SetFillColor(self.fillColor)
1660  self._pave.Draw(options)
1661  for t in self._texts:
1662  t.Draw(options)
1663 
1664 def _copyStyle(src, dst):
1665  properties = []
1666  if hasattr(src, "GetLineColor") and hasattr(dst, "SetLineColor"):
1667  properties.extend(["LineColor", "LineStyle", "LineWidth"])
1668  if hasattr(src, "GetFillColor") and hasattr(dst, "SetFillColor"):
1669  properties.extend(["FillColor", "FillStyle"])
1670  if hasattr(src, "GetMarkerColor") and hasattr(dst, "SetMarkerColor"):
1671  properties.extend(["MarkerColor", "MarkerSize", "MarkerStyle"])
1672 
1673  for prop in properties:
1674  getattr(dst, "Set"+prop)(getattr(src, "Get"+prop)())
1675 
1677  """Denotes an empty place in a group."""
1678  def __init__(self):
1679  pass
1680 
1681  def getName(self):
1682  return None
1683 
1685  return False
1686 
1687  def create(self, *args, **kwargs):
1688  pass
1689 
1690  def isEmpty(self):
1691  return True
1692 
1694  return 0
1695 
1696 class Plot:
1697  """Represents one plot, comparing one or more histograms."""
1698  def __init__(self, name, **kwargs):
1699  """ Constructor.
1700 
1701  Arguments:
1702  name -- String for name of the plot, or Efficiency object
1703 
1704  Keyword arguments:
1705  fallback -- Dictionary for specifying fallback (default None)
1706  outname -- String for an output name of the plot (default None for the same as 'name')
1707  title -- String for a title of the plot (default None)
1708  xtitle -- String for x axis title (default None)
1709  xtitlesize -- Float for x axis title size (default None)
1710  xtitleoffset -- Float for x axis title offset (default None)
1711  xlabelsize -- Float for x axis label size (default None)
1712  ytitle -- String for y axis title (default None)
1713  ytitlesize -- Float for y axis title size (default None)
1714  ytitleoffset -- Float for y axis title offset (default None)
1715  ztitle -- String for z axis title (default None)
1716  ztitleoffset -- Float for z axis title offset (default None)
1717  xmin -- Float for x axis minimum (default None, i.e. automatic)
1718  xmax -- Float for x axis maximum (default None, i.e. automatic)
1719  ymin -- Float for y axis minimum (default 0)
1720  ymax -- Float for y axis maximum (default None, i.e. automatic)
1721  xlog -- Bool for x axis log status (default False)
1722  ylog -- Bool for y axis log status (default False)
1723  xgrid -- Bool for x axis grid status (default True)
1724  ygrid -- Bool for y axis grid status (default True)
1725  stat -- Draw stat box? (default False)
1726  fit -- Do gaussian fit? (default False)
1727  statx -- Stat box x coordinate (default 0.65)
1728  staty -- Stat box y coordinate (default 0.8)
1729  statyadjust -- List of floats for stat box y coordinate adjustments (default None)
1730  normalizeToUnitArea -- Normalize histograms to unit area? (default False)
1731  normalizeToNumberOfEvents -- Normalize histograms to number of events? If yes, the PlotFolder needs 'numberOfEventsHistogram' set to a histogram filled once per event (default False)
1732  profileX -- Take histograms via ProfileX()? (default False)
1733  fitSlicesY -- Take histograms via FitSlicesY() (default False)
1734  rebinX -- rebin x axis (default None)
1735  scale -- Scale histograms by a number (default None)
1736  xbinlabels -- List of x axis bin labels (if given, default None)
1737  xbinlabelsize -- Size of x axis bin labels (default None)
1738  xbinlabeloption -- Option string for x axis bin labels (default None)
1739  removeEmptyBins -- Bool for removing empty bins, but only if histogram has bin labels (default False)
1740  printBins -- Bool for printing bin values, but only if histogram has bin labels (default False)
1741  drawStyle -- If "hist", draw as line instead of points (default None)
1742  drawCommand -- Deliver this to Draw() (default: None for same as drawStyle)
1743  lineWidth -- If drawStyle=="hist", the width of line (default 2)
1744  legendDx -- Float for moving TLegend in x direction for separate=True (default None)
1745  legendDy -- Float for moving TLegend in y direction for separate=True (default None)
1746  legendDw -- Float for changing TLegend width for separate=True (default None)
1747  legendDh -- Float for changing TLegend height for separate=True (default None)
1748  legend -- Bool to enable/disable legend (default True)
1749  adjustMarginLeft -- Float for adjusting left margin (default None)
1750  adjustMarginRight -- Float for adjusting right margin (default None)
1751  ratio -- Possibility to disable ratio for this particular plot (default None)
1752  ratioYmin -- Float for y axis minimum in ratio pad (default: list of values)
1753  ratioYmax -- Float for y axis maximum in ratio pad (default: list of values)
1754  ratioFit -- Fit straight line in ratio? (default None)
1755  ratioUncertainty -- Plot uncertainties on ratio? (default True)
1756  ratioCoverageXrange -- Range of x axis values (xmin,xmax) to limit the automatic ratio y axis range calculation to (default None for disabled)
1757  histogramModifier -- Function to be called in create() to modify the histograms (default None)
1758  """
1759  self._name = name
1760 
1761  def _set(attr, default):
1762  setattr(self, "_"+attr, kwargs.get(attr, default))
1763 
1764  _set("fallback", None)
1765  _set("outname", None)
1766 
1767  _set("title", None)
1768  _set("xtitle", None)
1769  _set("xtitlesize", None)
1770  _set("xtitleoffset", None)
1771  _set("xlabelsize", None)
1772  _set("ytitle", None)
1773  _set("ytitlesize", None)
1774  _set("ytitleoffset", None)
1775  _set("ztitle", None)
1776  _set("ztitleoffset", None)
1777 
1778  _set("xmin", None)
1779  _set("xmax", None)
1780  _set("ymin", 0.)
1781  _set("ymax", None)
1782 
1783  _set("xlog", False)
1784  _set("ylog", False)
1785  _set("xgrid", True)
1786  _set("ygrid", True)
1787 
1788  _set("stat", False)
1789  _set("fit", False)
1790 
1791  _set("statx", 0.65)
1792  _set("staty", 0.8)
1793  _set("statyadjust", None)
1794 
1795  _set("normalizeToUnitArea", False)
1796  _set("normalizeToNumberOfEvents", False)
1797  _set("profileX", False)
1798  _set("fitSlicesY", False)
1799  _set("rebinX", None)
1800 
1801  _set("scale", None)
1802  _set("xbinlabels", None)
1803  _set("xbinlabelsize", None)
1804  _set("xbinlabeloption", None)
1805  _set("removeEmptyBins", False)
1806  _set("printBins", False)
1807 
1808  _set("drawStyle", "EP")
1809  _set("drawCommand", None)
1810  _set("lineWidth", 2)
1811 
1812  _set("legendDx", None)
1813  _set("legendDy", None)
1814  _set("legendDw", None)
1815  _set("legendDh", None)
1816  _set("legend", True)
1817 
1818  _set("adjustMarginLeft", None)
1819  _set("adjustMarginRight", None)
1820 
1821  _set("ratio", None)
1822  _set("ratioYmin", [0, 0.2, 0.5, 0.7, 0.8, 0.9, 0.95])
1823  _set("ratioYmax", [1.05, 1.1, 1.2, 1.3, 1.5, 1.8, 2, 2.5, 3, 4, 5])
1824  _set("ratioFit", None)
1825  _set("ratioUncertainty", True)
1826  _set("ratioCoverageXrange", None)
1827 
1828  _set("histogramModifier", None)
1829 
1830  self._histograms = []
1831 
1832  def setProperties(self, **kwargs):
1833  for name, value in six.iteritems(kwargs):
1834  if not hasattr(self, "_"+name):
1835  raise Exception("No attribute '%s'" % name)
1836  setattr(self, "_"+name, value)
1837 
1838  def clone(self, **kwargs):
1839  if not self.isEmpty():
1840  raise Exception("Plot can be cloned only before histograms have been created")
1841  cl = copy.copy(self)
1842  cl.setProperties(**kwargs)
1843  return cl
1844 
1846  """Return number of existing histograms."""
1847  return len([h for h in self._histograms if h is not None])
1848 
1849  def isEmpty(self):
1850  """Return true if there are no histograms created for the plot"""
1851  return self.getNumberOfHistograms() == 0
1852 
1853  def isTGraph2D(self):
1854  for h in self._histograms:
1855  if isinstance(h, ROOT.TGraph2D):
1856  return True
1857  return False
1858 
1859  def isRatio(self, ratio):
1860  if self._ratio is None:
1861  return ratio
1862  return ratio and self._ratio
1863 
1864  def setName(self, name):
1865  self._name = name
1866 
1867  def getName(self):
1868  if self._outname is not None:
1869  return self._outname
1870  if isinstance(self._name, list):
1871  return str(self._name[0])
1872  else:
1873  return str(self._name)
1874 
1876  """Return true if the ratio uncertainty should be drawn"""
1877  return self._ratioUncertainty
1878 
1879  def _createOne(self, name, index, tdir, nevents):
1880  """Create one histogram from a TDirectory."""
1881  if tdir == None:
1882  return None
1883 
1884  # If name is a list, pick the name by the index
1885  if isinstance(name, list):
1886  name = name[index]
1887 
1888  h = _getOrCreateObject(tdir, name)
1889  if h is not None and self._normalizeToNumberOfEvents and nevents is not None and nevents != 0:
1890  h.Scale(1.0/nevents)
1891  return h
1892 
1893  def create(self, tdirNEvents, requireAllHistograms=False):
1894  """Create histograms from list of TDirectories"""
1895  self._histograms = [self._createOne(self._name, i, tdirNEvent[0], tdirNEvent[1]) for i, tdirNEvent in enumerate(tdirNEvents)]
1896 
1897  if self._fallback is not None:
1898  profileX = [self._profileX]*len(self._histograms)
1899  for i in range(0, len(self._histograms)):
1900  if self._histograms[i] is None:
1901  self._histograms[i] = self._createOne(self._fallback["name"], i, tdirNEvents[i][0], tdirNEvents[i][1])
1902  profileX[i] = self._fallback.get("profileX", self._profileX)
1903 
1904  if self._histogramModifier is not None:
1905  self._histograms = self._histogramModifier(self._histograms)
1906 
1907  if len(self._histograms) > len(_plotStylesColor):
1908  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)))
1909 
1910  # Modify histograms here in case self._name returns numbers
1911  # and self._histogramModifier creates the histograms from
1912  # these numbers
1913  def _modifyHisto(th1, profileX):
1914  if th1 is None:
1915  return None
1916 
1917  if profileX:
1918  th1 = th1.ProfileX()
1919 
1920  if self._fitSlicesY:
1921  ROOT.TH1.AddDirectory(True)
1922  th1.FitSlicesY()
1923  th1 = ROOT.gDirectory.Get(th1.GetName()+"_2")
1924  th1.SetDirectory(None)
1925  #th1.SetName(th1.GetName()+"_ref")
1926  ROOT.TH1.AddDirectory(False)
1927 
1928  if self._title is not None:
1929  th1.SetTitle(self._title)
1930 
1931  if self._scale is not None:
1932  th1.Scale(self._scale)
1933 
1934  return th1
1935 
1936  if self._fallback is not None:
1937  self._histograms = map(_modifyHisto, self._histograms, profileX)
1938  else:
1939  self._histograms = map(lambda h: _modifyHisto(h, self._profileX), self._histograms)
1940  if requireAllHistograms and None in self._histograms:
1941  self._histograms = [None]*len(self._histograms)
1942 
1943  def _setStats(self, histos, startingX, startingY):
1944  """Set stats box."""
1945  if not self._stat:
1946  for h in histos:
1947  if h is not None and hasattr(h, "SetStats"):
1948  h.SetStats(0)
1949  return
1950 
1951  def _doStats(h, col, dy):
1952  if h is None:
1953  return
1954  h.SetStats(True)
1955 
1956  if self._fit and h.GetEntries() > 0.5:
1957  h.Fit("gaus", "Q")
1958  f = h.GetListOfFunctions().FindObject("gaus")
1959  if f == None:
1960  h.SetStats(0)
1961  return
1962  f.SetLineColor(col)
1963  f.SetLineWidth(1)
1964  h.Draw()
1965  ROOT.gPad.Update()
1966  st = h.GetListOfFunctions().FindObject("stats")
1967  if self._fit:
1968  st.SetOptFit(0o010)
1969  st.SetOptStat(1001)
1970  st.SetOptStat(1110)
1971  st.SetX1NDC(startingX)
1972  st.SetX2NDC(startingX+0.3)
1973  st.SetY1NDC(startingY+dy)
1974  st.SetY2NDC(startingY+dy+0.12)
1975  st.SetTextColor(col)
1976 
1977  dy = 0.0
1978  for i, h in enumerate(histos):
1979  if self._statyadjust is not None and i < len(self._statyadjust):
1980  dy += self._statyadjust[i]
1981 
1982  _doStats(h, _plotStylesColor[i], dy)
1983  dy -= 0.16
1984 
1985  def _normalize(self):
1986  """Normalise histograms to unit area"""
1987 
1988  for h in self._histograms:
1989  if h is None:
1990  continue
1991  i = h.Integral()
1992  if i == 0:
1993  continue
1994  if h.GetSumw2().fN <= 0: # to suppress warning
1995  h.Sumw2()
1996  h.Scale(1.0/i)
1997 
1998  def draw(self, pad, ratio, ratioFactor, nrows):
1999  """Draw the histograms using values for a given algorithm."""
2000 # if len(self._histograms) == 0:
2001 # print "No histograms for plot {name}".format(name=self._name)
2002 # return
2003 
2004  isTGraph2D = self.isTGraph2D()
2005  if isTGraph2D:
2006  # Ratios for the TGraph2Ds is not that interesting
2007  ratioOrig = ratio
2008  ratio = False
2009 
2010  if self._normalizeToUnitArea:
2011  self._normalize()
2012 
2013  if self._rebinX is not None:
2014  for h in self._histograms:
2015  h.Rebin(self._rebinX)
2016 
2017  def _styleMarker(h, msty, col):
2018  h.SetMarkerStyle(msty)
2019  h.SetMarkerColor(col)
2020  h.SetMarkerSize(0.7)
2021  h.SetLineColor(1)
2022  h.SetLineWidth(1)
2023 
2024  def _styleHist(h, msty, col):
2025  _styleMarker(h, msty, col)
2026  h.SetLineColor(col)
2027  h.SetLineWidth(self._lineWidth)
2028 
2029  # Use marker or hist style
2030  style = _styleMarker
2031  if "hist" in self._drawStyle.lower():
2032  style = _styleHist
2033  if len(self._histograms) > 0 and isinstance(self._histograms[0], ROOT.TGraph):
2034  if "l" in self._drawStyle.lower():
2035  style = _styleHist
2036 
2037  # Apply style to histograms, filter out Nones
2038  histos = []
2039  for i, h in enumerate(self._histograms):
2040  if h is None:
2041  continue
2042  style(h, _plotStylesMarker[i], _plotStylesColor[i])
2043  histos.append(h)
2044  if len(histos) == 0:
2045  if verbose:
2046  print("No histograms for plot {name}".format(name=self.getName()))
2047  return
2048 
2049  # Extract x bin labels, make sure that only bins with same
2050  # label are compared with each other
2051  histosHaveBinLabels = len(histos[0].GetXaxis().GetBinLabel(1)) > 0
2052  xbinlabels = self._xbinlabels
2053  ybinlabels = None
2054  if xbinlabels is None:
2055  if histosHaveBinLabels:
2056  xbinlabels = _mergeBinLabelsX(histos)
2057  if isinstance(histos[0], ROOT.TH2):
2058  ybinlabels = _mergeBinLabelsY(histos)
2059 
2060  if len(histos) > 1: # don't bother if only one histogram
2061  # doing this for TH2 is pending for use case, for now there is only 1 histogram/plot for TH2
2062  histos = _th1IncludeOnlyBins(histos, xbinlabels)
2063  self._tmp_histos = histos # need to keep these in memory too ...
2064 
2065  # Remove empty bins, but only if histograms have bin labels
2066  if self._removeEmptyBins and histosHaveBinLabels:
2067  # at this point, all histograms have been "equalized" by their x binning and labels
2068  # therefore remove bins which are empty in all histograms
2069  if isinstance(histos[0], ROOT.TH2):
2070  (histos, xbinlabels, ybinlabels) = _th2RemoveEmptyBins(histos, xbinlabels, ybinlabels)
2071  else:
2072  (histos, xbinlabels) = _th1RemoveEmptyBins(histos, xbinlabels)
2073  self._tmp_histos = histos # need to keep these in memory too ...
2074  if len(histos) == 0:
2075  if verbose:
2076  print("No histograms with non-empty bins for plot {name}".format(name=self.getName()))
2077  return
2078 
2079  if self._printBins and histosHaveBinLabels:
2080  print("####################")
2081  print(self._name)
2082  width = max([len(l) for l in xbinlabels])
2083  tmp = "%%-%ds " % width
2084  for b in range(1, histos[0].GetNbinsX()+1):
2085  s = tmp % xbinlabels[b-1]
2086  for h in histos:
2087  s += "%.3f " % h.GetBinContent(b)
2088  print(s)
2089  print()
2090 
2091  bounds = _findBounds(histos, self._ylog,
2092  xmin=self._xmin, xmax=self._xmax,
2093  ymin=self._ymin, ymax=self._ymax)
2094  zmax = None
2095  if isinstance(histos[0], ROOT.TH2):
2096  zmax = max([h.GetMaximum() for h in histos])
2097 
2098  # need to keep these in memory
2101 
2102  if ratio:
2103  self._ratios = _calculateRatios(histos, self._ratioUncertainty) # need to keep these in memory too ...
2104  ratioHistos = [h for h in [r.getRatio() for r in self._ratios[1:]] if h is not None]
2105 
2106  if len(ratioHistos) > 0:
2107  ratioBoundsY = _findBoundsY(ratioHistos, ylog=False, ymin=self._ratioYmin, ymax=self._ratioYmax, coverage=0.68, coverageRange=self._ratioCoverageXrange)
2108  else:
2109  ratioBoundsY = (0.9, 1,1) # hardcoded default in absence of valid ratio calculations
2110 
2111  if self._ratioFit is not None:
2112  for i, rh in enumerate(ratioHistos):
2113  tf_line = ROOT.TF1("line%d"%i, "[0]+x*[1]")
2114  tf_line.SetRange(self._ratioFit["rangemin"], self._ratioFit["rangemax"])
2115  fitres = rh.Fit(tf_line, "RINSQ")
2116  tf_line.SetLineColor(rh.GetMarkerColor())
2117  tf_line.SetLineWidth(2)
2118  self._ratioAdditional.append(tf_line)
2119  box = PlotTextBox(xmin=self._ratioFit.get("boxXmin", 0.14), ymin=None, # None for automatix
2120  xmax=self._ratioFit.get("boxXmax", 0.35), ymax=self._ratioFit.get("boxYmax", 0.09),
2121  color=rh.GetMarkerColor(), font=43, size=11, lineheight=0.02)
2122  box.move(dx=(box.width()+0.01)*i)
2123  #box.addText("Const: %.4f" % fitres.Parameter(0))
2124  #box.addText("Slope: %.4f" % fitres.Parameter(1))
2125  box.addText("Const: %.4f#pm%.4f" % (fitres.Parameter(0), fitres.ParError(0)))
2126  box.addText("Slope: %.4f#pm%.4f" % (fitres.Parameter(1), fitres.ParError(1)))
2127  self._mainAdditional.append(box)
2128 
2129 
2130  # Create bounds before stats in order to have the
2131  # SetRangeUser() calls made before the fit
2132  #
2133  # stats is better to be called before frame, otherwise get
2134  # mess in the plot (that frame creation cleans up)
2135  if ratio:
2136  pad.cd(1)
2137  self._setStats(histos, self._statx, self._staty)
2138 
2139  # Create frame
2140  if isTGraph2D:
2141  frame = FrameTGraph2D(pad, bounds, histos, ratioOrig, ratioFactor)
2142  else:
2143  if ratio:
2144  ratioBounds = (bounds[0], ratioBoundsY[0], bounds[2], ratioBoundsY[1])
2145  frame = FrameRatio(pad, bounds, zmax, ratioBounds, ratioFactor, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption)
2146  else:
2147  frame = Frame(pad, bounds, zmax, nrows, xbinlabels, self._xbinlabelsize, self._xbinlabeloption, ybinlabels=ybinlabels)
2148 
2149  # Set log and grid
2150  frame.setLogx(self._xlog)
2151  frame.setLogy(self._ylog)
2152  frame.setGridx(self._xgrid)
2153  frame.setGridy(self._ygrid)
2154 
2155  # Construct draw option string
2156  opt = "sames" # s for statbox or something?
2157  ds = ""
2158  if self._drawStyle is not None:
2159  ds = self._drawStyle
2160  if self._drawCommand is not None:
2161  ds = self._drawCommand
2162  if len(ds) > 0:
2163  opt += " "+ds
2164 
2165  # Set properties of frame
2166  frame.setTitle(histos[0].GetTitle())
2167  if self._xtitle == 'Default':
2168  frame.setXTitle( histos[0].GetXaxis().GetTitle() )
2169  elif self._xtitle is not None:
2170  frame.setXTitle(self._xtitle)
2171  if self._xtitlesize is not None:
2172  frame.setXTitleSize(self._xtitlesize)
2173  if self._xtitleoffset is not None:
2174  frame.setXTitleOffset(self._xtitleoffset)
2175  if self._xlabelsize is not None:
2176  frame.setXLabelSize(self._xlabelsize)
2177  if self._ytitle == 'Default':
2178  frame.setYTitle( histos[0].GetYaxis().GetTitle() )
2179  elif self._ytitle is not None:
2180  frame.setYTitle(self._ytitle)
2181  if self._ytitlesize is not None:
2182  frame.setYTitleSize(self._ytitlesize)
2183  if self._ytitleoffset is not None:
2184  frame.setYTitleOffset(self._ytitleoffset)
2185  if self._ztitle is not None:
2186  frame.setZTitle(self._ztitle)
2187  if self._ztitleoffset is not None:
2188  frame.setZTitleOffset(self._ztitleoffset)
2189  if self._adjustMarginLeft is not None:
2190  frame.adjustMarginLeft(self._adjustMarginLeft)
2191  if self._adjustMarginRight is not None:
2192  frame.adjustMarginRight(self._adjustMarginRight)
2193  elif "z" in opt:
2194  frame.adjustMarginLeft(0.03)
2195  frame.adjustMarginRight(0.08)
2196 
2197  # Draw histograms
2198  if ratio:
2199  frame._pad.cd()
2200 
2201  for i, h in enumerate(histos):
2202  o = opt
2203  if isTGraph2D and i == 0:
2204  o = o.replace("sames", "")
2205  h.Draw(o)
2206 
2207  for addl in self._mainAdditional:
2208  addl.Draw("same")
2209 
2210  # Draw ratios
2211  if ratio and len(self._ratios) > 0:
2212  frame._padRatio.cd()
2213  firstRatio = self._ratios[0].getRatio()
2214  if self._ratioUncertainty and firstRatio is not None:
2215  firstRatio.SetFillStyle(1001)
2216  firstRatio.SetFillColor(ROOT.kGray)
2217  firstRatio.SetLineColor(ROOT.kGray)
2218  firstRatio.SetMarkerColor(ROOT.kGray)
2219  firstRatio.SetMarkerSize(0)
2220  self._ratios[0].draw("E2")
2221  frame._padRatio.RedrawAxis("G") # redraw grid on top of the uncertainty of denominator
2222  for r in self._ratios[1:]:
2223  r.draw()
2224 
2225  for addl in self._ratioAdditional:
2226  addl.Draw("same")
2227 
2228  frame.redrawAxis()
2229  self._frame = frame # keep the frame in memory for sure
2230 
2231  def addToLegend(self, legend, legendLabels, denomUncertainty):
2232  """Add histograms to a legend.
2233 
2234  Arguments:
2235  legend -- TLegend
2236  legendLabels -- List of strings for the legend labels
2237  """
2238  first = denomUncertainty
2239  for h, label in zip(self._histograms, legendLabels):
2240  if h is None:
2241  first = False
2242  continue
2243  if first:
2244  self._forLegend = h.Clone()
2245  self._forLegend.SetFillStyle(1001)
2246  self._forLegend.SetFillColor(ROOT.kGray)
2247  entry = legend.AddEntry(self._forLegend, label, "lpf")
2248  first = False
2249  else:
2250  legend.AddEntry(h, label, "LP")
2251 
2253  """Group of plots, results a TCanvas"""
2254  def __init__(self, name, plots, **kwargs):
2255  """Constructor.
2256 
2257  Arguments:
2258  name -- String for name of the TCanvas, used also as the basename of the picture files
2259  plots -- List of Plot objects
2260 
2261  Keyword arguments:
2262  ncols -- Number of columns (default 2)
2263  legendDx -- Float for moving TLegend in x direction (default None)
2264  legendDy -- Float for moving TLegend in y direction (default None)
2265  legendDw -- Float for changing TLegend width (default None)
2266  legendDh -- Float for changing TLegend height (default None)
2267  legend -- Bool for disabling legend (default True for legend being enabled)
2268  overrideLegendLabels -- List of strings for legend labels, if given, these are used instead of the ones coming from Plotter (default None)
2269  onlyForPileup -- Plots this group only for pileup samples
2270  """
2271  super(PlotGroup, self).__init__()
2272 
2273  self._name = name
2274  self._plots = plots
2275 
2276  def _set(attr, default):
2277  setattr(self, "_"+attr, kwargs.get(attr, default))
2278 
2279  _set("ncols", 2)
2280 
2281  _set("legendDx", None)
2282  _set("legendDy", None)
2283  _set("legendDw", None)
2284  _set("legendDh", None)
2285  _set("legend", True)
2286 
2287  _set("overrideLegendLabels", None)
2288 
2289  _set("onlyForPileup", False)
2290 
2291  self._ratioFactor = 1.25
2292 
2293  def setProperties(self, **kwargs):
2294  for name, value in six.iteritems(kwargs):
2295  if not hasattr(self, "_"+name):
2296  raise Exception("No attribute '%s'" % name)
2297  setattr(self, "_"+name, value)
2298 
2299  def getName(self):
2300  return self._name
2301 
2302  def getPlots(self):
2303  return self._plots
2304 
2305  def remove(self, name):
2306  for i, plot in enumerate(self._plots):
2307  if plot.getName() == name:
2308  del self._plots[i]
2309  return
2310  raise Exception("Did not find Plot '%s' from PlotGroup '%s'" % (name, self._name))
2311 
2312  def clear(self):
2313  self._plots = []
2314 
2315  def append(self, plot):
2316  self._plots.append(plot)
2317 
2318  def getPlot(self, name):
2319  for plot in self._plots:
2320  if plot.getName() == name:
2321  return plot
2322  raise Exception("No Plot named '%s'" % name)
2323 
2324  def onlyForPileup(self):
2325  """Return True if the PlotGroup is intended only for pileup samples"""
2326  return self._onlyForPileup
2327 
2328  def create(self, tdirectoryNEvents, requireAllHistograms=False):
2329  """Create histograms from a list of TDirectories.
2330 
2331  Arguments:
2332  tdirectoryNEvents -- List of (TDirectory, nevents) pairs
2333  requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False)
2334  """
2335  for plot in self._plots:
2336  plot.create(tdirectoryNEvents, requireAllHistograms)
2337 
2338  def draw(self, legendLabels, prefix=None, separate=False, saveFormat=".pdf", ratio=True, directory=""):
2339  """Draw the histograms using values for a given algorithm.
2340 
2341  Arguments:
2342  legendLabels -- List of strings for legend labels (corresponding to the tdirectories in create())
2343  prefix -- Optional string for file name prefix (default None)
2344  separate -- Save the plots of a group to separate files instead of a file per group (default False)
2345  saveFormat -- String specifying the plot format (default '.pdf')
2346  ratio -- Add ratio to the plot (default True)
2347  directory -- Directory where to save the file (default "")
2348  """
2349 
2350  if self._overrideLegendLabels is not None:
2351  legendLabels = self._overrideLegendLabels
2352 
2353  # Do not draw the group if it would be empty
2354  onlyEmptyPlots = True
2355  for plot in self._plots:
2356  if not plot.isEmpty():
2357  onlyEmptyPlots = False
2358  break
2359  if onlyEmptyPlots:
2360  return []
2361 
2362  if separate:
2363  return self._drawSeparate(legendLabels, prefix, saveFormat, ratio, directory)
2364 
2365  cwidth = 500*self._ncols
2366  nrows = int((len(self._plots)+self._ncols-1)/self._ncols) # this should work also for odd n
2367  cheight = 500 * nrows
2368 
2369  if ratio:
2370  cheight = int(cheight*self._ratioFactor)
2371 
2372  canvas = _createCanvas(self._name, cwidth, cheight)
2373 
2374  canvas.Divide(self._ncols, nrows)
2375  if ratio:
2376  for i, plot in enumerate(self._plots):
2377  pad = canvas.cd(i+1)
2378  self._modifyPadForRatio(pad)
2379 
2380  # Draw plots to canvas
2381  for i, plot in enumerate(self._plots):
2382  pad = canvas.cd(i+1)
2383  if not plot.isEmpty():
2384  plot.draw(pad, ratio, self._ratioFactor, nrows)
2385 
2386  # Setup legend
2387  canvas.cd()
2388  if len(self._plots) <= 4:
2389  lx1 = 0.2
2390  lx2 = 0.9
2391  ly1 = 0.48
2392  ly2 = 0.53
2393  else:
2394  lx1 = 0.1
2395  lx2 = 0.9
2396  ly1 = 0.64
2397  ly2 = 0.67
2398  if self._legendDx is not None:
2399  lx1 += self._legendDx
2400  lx2 += self._legendDx
2401  if self._legendDy is not None:
2402  ly1 += self._legendDy
2403  ly2 += self._legendDy
2404  if self._legendDw is not None:
2405  lx2 += self._legendDw
2406  if self._legendDh is not None:
2407  ly1 -= self._legendDh
2408  plot = max(self._plots, key=lambda p: p.getNumberOfHistograms())
2409  denomUnc = sum([p.drawRatioUncertainty() for p in self._plots]) > 0
2410  legend = self._createLegend(plot, legendLabels, lx1, ly1, lx2, ly2,
2411  denomUncertainty=(ratio and denomUnc))
2412 
2413  return self._save(canvas, saveFormat, prefix=prefix, directory=directory)
2414 
2415  def _drawSeparate(self, legendLabels, prefix, saveFormat, ratio, directory):
2416  """Internal method to do the drawing to separate files per Plot instead of a file per PlotGroup"""
2417  width = 500
2418  height = 500
2419 
2420  lx1def = 0.6
2421  lx2def = 0.95
2422  ly1def = 0.85
2423  ly2def = 0.95
2424 
2425  ret = []
2426 
2427  for plot in self._plots:
2428  if plot.isEmpty():
2429  continue
2430 
2431  canvas = _createCanvas(self._name+"Single", width, height)
2432  canvasRatio = _createCanvas(self._name+"SingleRatio", width, int(height*self._ratioFactor))
2433 
2434  # from TDRStyle
2435  for c in [canvas, canvasRatio]:
2436  c.SetTopMargin(0.05)
2437  c.SetBottomMargin(0.13)
2438  c.SetLeftMargin(0.16)
2439  c.SetRightMargin(0.05)
2440 
2441  ratioForThisPlot = plot.isRatio(ratio)
2442  c = canvas
2443  if ratioForThisPlot:
2444  c = canvasRatio
2445  c.cd()
2446  self._modifyPadForRatio(c)
2447 
2448  # Draw plot to canvas
2449  c.cd()
2450  plot.draw(c, ratioForThisPlot, self._ratioFactor, 1)
2451 
2452  if plot._legend:
2453  # Setup legend
2454  lx1 = lx1def
2455  lx2 = lx2def
2456  ly1 = ly1def
2457  ly2 = ly2def
2458 
2459  if plot._legendDx is not None:
2460  lx1 += plot._legendDx
2461  lx2 += plot._legendDx
2462  if plot._legendDy is not None:
2463  ly1 += plot._legendDy
2464  ly2 += plot._legendDy
2465  if plot._legendDw is not None:
2466  lx2 += plot._legendDw
2467  if plot._legendDh is not None:
2468  ly1 -= plot._legendDh
2469 
2470  c.cd()
2471  legend = self._createLegend(plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.03,
2472  denomUncertainty=(ratioForThisPlot and plot.drawRatioUncertainty))
2473 
2474  ret.extend(self._save(c, saveFormat, prefix=prefix, postfix="/"+plot.getName(), single=True, directory=directory))
2475  return ret
2476 
2477  def _modifyPadForRatio(self, pad):
2478  """Internal method to set divide a pad to two for ratio plots"""
2479  _modifyPadForRatio(pad, self._ratioFactor)
2480 
2481  def _createLegend(self, plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.016, denomUncertainty=True):
2482  if not self._legend:
2483  return None
2484 
2485  l = ROOT.TLegend(lx1, ly1, lx2, ly2)
2486  l.SetTextSize(textSize)
2487  l.SetLineColor(1)
2488  l.SetLineWidth(1)
2489  l.SetLineStyle(1)
2490  l.SetFillColor(0)
2491  l.SetMargin(0.07)
2492 
2493  plot.addToLegend(l, legendLabels, denomUncertainty)
2494  l.Draw()
2495  return l
2496 
2497  def _save(self, canvas, saveFormat, prefix=None, postfix=None, single=False, directory=""):
2498  # Save the canvas to file and clear
2499  name = self._name
2500  if not os.path.exists(directory+'/'+name):
2501  os.makedirs(directory+'/'+name)
2502  if prefix is not None:
2503  name = prefix+name
2504  if postfix is not None:
2505  name = name+postfix
2506  name = os.path.join(directory, name)
2507 
2508  if not verbose: # silence saved file printout
2509  backup = ROOT.gErrorIgnoreLevel
2510  ROOT.gErrorIgnoreLevel = ROOT.kWarning
2511  canvas.SaveAs(name+saveFormat)
2512  if not verbose:
2513  ROOT.gErrorIgnoreLevel = backup
2514 
2515  if single:
2516  canvas.Clear()
2517  canvas.SetLogx(False)
2518  canvas.SetLogy(False)
2519  else:
2520  canvas.Clear("D") # keep subpads
2521 
2522  return [name+saveFormat]
2523 
2525  """Resembles DQM GUI's "On side" layout.
2526 
2527  Like PlotGroup, but has only a description of a single plot. The
2528  plot is drawn separately for each file. Useful for 2D histograms."""
2529 
2530  def __init__(self, name, plot, ncols=2, onlyForPileup=False):
2531  super(PlotOnSideGroup, self).__init__(name, [], ncols=ncols, legend=False, onlyForPileup=onlyForPileup)
2532  self._plot = plot
2533  self._plot.setProperties(ratio=False)
2534 
2535  def append(self, *args, **kwargs):
2536  raise Exception("PlotOnSideGroup.append() is not implemented")
2537 
2538  def create(self, tdirectoryNEvents, requireAllHistograms=False):
2539  self._plots = []
2540  for i, element in enumerate(tdirectoryNEvents):
2541  pl = self._plot.clone()
2542  pl.create([element], requireAllHistograms)
2543  pl.setName(pl.getName()+"_"+str(i))
2544  self._plots.append(pl)
2545 
2546  def draw(self, *args, **kwargs):
2547  kargs = copy.copy(kwargs)
2548  kargs["ratio"] = False
2549  return super(PlotOnSideGroup, self).draw(*args, **kargs)
2550 
2552 
2553  """Represents a collection of PlotGroups, produced from a single folder in a DQM file"""
2554  def __init__(self, *plotGroups, **kwargs):
2555  """Constructor.
2556 
2557  Arguments:
2558  plotGroups -- List of PlotGroup objects
2559 
2560  Keyword arguments
2561  loopSubFolders -- Should the subfolders be looped over? (default: True)
2562  onlyForPileup -- Plots this folder only for pileup samples
2563  onlyForElectron -- Plots this folder only for electron samples
2564  onlyForConversion -- Plots this folder only for conversion samples
2565  onlyForBHadron -- Plots this folder only for B-hadron samples
2566  purpose -- html.PlotPurpose member class for the purpose of the folder, used for grouping of the plots to the HTML pages
2567  page -- Optional string for the page in HTML generatin
2568  section -- Optional string for the section within a page in HTML generation
2569  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".
2570  """
2571  self._plotGroups = list(plotGroups)
2572  self._loopSubFolders = kwargs.pop("loopSubFolders", True)
2573  self._onlyForPileup = kwargs.pop("onlyForPileup", False)
2574  self._onlyForElectron = kwargs.pop("onlyForElectron", False)
2575  self._onlyForConversion = kwargs.pop("onlyForConversion", False)
2576  self._onlyForBHadron = kwargs.pop("onlyForBHadron", False)
2577  self._purpose = kwargs.pop("purpose", None)
2578  self._page = kwargs.pop("page", None)
2579  self._section = kwargs.pop("section", None)
2580  self._numberOfEventsHistogram = kwargs.pop("numberOfEventsHistogram", None)
2581  if len(kwargs) > 0:
2582  raise Exception("Got unexpected keyword arguments: "+ ",".join(kwargs.keys()))
2583 
2584  def loopSubFolders(self):
2585  """Return True if the PlotGroups of this folder should be applied to the all subfolders"""
2586  return self._loopSubFolders
2587 
2588  def onlyForPileup(self):
2589  """Return True if the folder is intended only for pileup samples"""
2590  return self._onlyForPileup
2591 
2592  def onlyForElectron(self):
2593  return self._onlyForElectron
2594 
2596  return self._onlyForConversion
2597 
2598  def onlyForBHadron(self):
2599  return self._onlyForBHadron
2600 
2601  def getPurpose(self):
2602  return self._purpose
2603 
2604  def getPage(self):
2605  return self._page
2606 
2607  def getSection(self):
2608  return self._section
2609 
2611  return self._numberOfEventsHistogram
2612 
2613  def append(self, plotGroup):
2614  self._plotGroups.append(plotGroup)
2615 
2616  def set(self, plotGroups):
2617  self._plotGroups = plotGroups
2618 
2619  def getPlotGroups(self):
2620  return self._plotGroups
2621 
2622  def getPlotGroup(self, name):
2623  for pg in self._plotGroups:
2624  if pg.getName() == name:
2625  return pg
2626  raise Exception("No PlotGroup named '%s'" % name)
2627 
2628  def create(self, dirsNEvents, labels, isPileupSample=True, requireAllHistograms=False):
2629  """Create histograms from a list of TFiles.
2630 
2631  Arguments:
2632  dirsNEvents -- List of (TDirectory, nevents) pairs
2633  labels -- List of strings for legend labels corresponding the files
2634  isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup)
2635  requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False)
2636  """
2637 
2638  if len(dirsNEvents) != len(labels):
2639  raise Exception("len(dirsNEvents) should be len(labels), now they are %d and %d" % (len(dirsNEvents), len(labels)))
2640 
2641  self._labels = labels
2642 
2643  for pg in self._plotGroups:
2644  if pg.onlyForPileup() and not isPileupSample:
2645  continue
2646  pg.create(dirsNEvents, requireAllHistograms)
2647 
2648  def draw(self, prefix=None, separate=False, saveFormat=".pdf", ratio=True, directory=""):
2649  """Draw and save all plots using settings of a given algorithm.
2650 
2651  Arguments:
2652  prefix -- Optional string for file name prefix (default None)
2653  separate -- Save the plots of a group to separate files instead of a file per group (default False)
2654  saveFormat -- String specifying the plot format (default '.pdf')
2655  ratio -- Add ratio to the plot (default True)
2656  directory -- Directory where to save the file (default "")
2657  """
2658  ret = []
2659 
2660  for pg in self._plotGroups:
2661  ret.extend(pg.draw(self._labels, prefix=prefix, separate=separate, saveFormat=saveFormat, ratio=ratio, directory=directory))
2662  return ret
2663 
2664 
2665  # These are to be overridden by derived classes for customisation
2666  def translateSubFolder(self, dqmSubFolderName):
2667  """Method called to (possibly) translate a subfolder name to more 'readable' form
2668 
2669  The implementation in this (base) class just returns the
2670  argument. The idea is that a deriving class might want to do
2671  something more complex (like trackingPlots.TrackingPlotFolder
2672  does)
2673  """
2674  return dqmSubFolderName
2675 
2676  def iterSelectionName(self, plotFolderName, translatedDqmSubFolder):
2677  """Iterate over possible selections name (used in output directory name and legend) from the name of PlotterFolder, and a return value of translateSubFolder"""
2678  ret = ""
2679  if plotFolderName != "":
2680  ret += "_"+plotFolderName
2681  if translatedDqmSubFolder is not None:
2682  ret += "_"+translatedDqmSubFolder
2683  yield ret
2684 
2685  def limitSubFolder(self, limitOnlyTo, translatedDqmSubFolder):
2686  """Return True if this subfolder should be processed
2687 
2688  Arguments:
2689  limitOnlyTo -- List/set/similar containing the translatedDqmSubFolder
2690  translatedDqmSubFolder -- Return value of translateSubFolder
2691  """
2692  return translatedDqmSubFolder in limitOnlyTo
2693 
2695  """Class to hold the original name and a 'translated' name of a subfolder in the DQM ROOT file"""
2696  def __init__(self, subfolder, translated):
2697  self.subfolder = subfolder
2698  self.translated = translated
2699 
2700  def equalTo(self, other):
2701  """Equality is defined by the 'translated' name"""
2702  return self.translated == other.translated
2703 
2705  """Plotter for one DQM folder.
2706 
2707  This class is supposed to be instantiated by the Plotter class (or
2708  PlotterItem, to be more specific), and not used directly by the
2709  user.
2710  """
2711  def __init__(self, name, possibleDqmFolders, dqmSubFolders, plotFolder, fallbackNames, fallbackDqmSubFolders, tableCreators):
2712  """
2713  Constructor
2714 
2715  Arguments:
2716  name -- Name of the folder (is used in the output directory naming)
2717  possibleDqmFolders -- List of strings for possible directories of histograms in TFiles
2718  dqmSubFolders -- List of lists of strings for list of subfolders per input file, or None if no subfolders
2719  plotFolder -- PlotFolder object
2720  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.
2721  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.
2722  tableCreators -- List of PlotterTableItem objects for tables to be created from this folder
2723  """
2724  self._name = name
2725  self._possibleDqmFolders = possibleDqmFolders
2726  self._plotFolder = plotFolder
2727  #self._dqmSubFolders = [map(lambda sf: DQMSubFolder(sf, self._plotFolder.translateSubFolder(sf)), lst) for lst in dqmSubFolders]
2728  if dqmSubFolders is None:
2729  self._dqmSubFolders = None
2730  else:
2731  # Match the subfolders between files in case the lists differ
2732  # equality is by the 'translated' name
2733  subfolders = {}
2734  for sf_list in dqmSubFolders:
2735  for sf in sf_list:
2736  sf_translated = self._plotFolder.translateSubFolder(sf)
2737  if sf_translated is not None and not sf_translated in subfolders:
2738  subfolders[sf_translated] = DQMSubFolder(sf, sf_translated)
2739 
2740  self._dqmSubFolders = subfolders.values()
2741  self._dqmSubFolders.sort(key=lambda sf: sf.subfolder)
2742 
2743  self._fallbackNames = fallbackNames
2744  self._fallbackDqmSubFolders = fallbackDqmSubFolders
2745  self._tableCreators = tableCreators
2746 
2747  def getName(self):
2748  return self._name
2749 
2750  def getPurpose(self):
2751  return self._plotFolder.getPurpose()
2752 
2753  def getPage(self):
2754  return self._plotFolder.getPage()
2755 
2756  def getSection(self):
2757  return self._plotFolder.getSection()
2758 
2759  def onlyForPileup(self):
2760  return self._plotFolder.onlyForPileup()
2761 
2762  def onlyForElectron(self):
2763  return self._plotFolder.onlyForElectron()
2764 
2766  return self._plotFolder.onlyForConversion()
2767 
2768  def onlyForBHadron(self):
2769  return self._plotFolder.onlyForBHadron()
2770 
2772  return self._possibleDqmFolders
2773 
2774  def getDQMSubFolders(self, limitOnlyTo=None):
2775  """Get list of subfolders, possibly limiting to some of them.
2776 
2777  Keyword arguments:
2778  limitOnlyTo -- Object depending on the PlotFolder type for limiting the set of subfolders to be processed
2779  """
2780 
2781  if self._dqmSubFolders is None:
2782  return [None]
2783 
2784  if limitOnlyTo is None:
2785  return self._dqmSubFolders
2786 
2787  return [s for s in self._dqmSubFolders if self._plotFolder.limitSubFolder(limitOnlyTo, s.translated)]
2788 
2789  def getTableCreators(self):
2790  return self._tableCreators
2791 
2792  def getSelectionNameIterator(self, dqmSubFolder):
2793  """Get a generator for the 'selection name', looping over the name and fallbackNames"""
2794  for name in [self._name]+self._fallbackNames:
2795  for selname in self._plotFolder.iterSelectionName(name, dqmSubFolder.translated if dqmSubFolder is not None else None):
2796  yield selname
2797 
2798  def getSelectionName(self, dqmSubFolder):
2799  return next(self.getSelectionNameIterator(dqmSubFolder))
2800 
2801  def create(self, files, labels, dqmSubFolder, isPileupSample=True, requireAllHistograms=False):
2802  """Create histograms from a list of TFiles.
2803  Arguments:
2804  files -- List of TFiles
2805  labels -- List of strings for legend labels corresponding the files
2806  dqmSubFolder -- DQMSubFolder object for a subfolder (or None for no subfolder)
2807  isPileupSample -- Is sample pileup (some PlotGroups may limit themselves to pileup)
2808  requireAllHistograms -- If True, a plot is produced if histograms from all files are present (default: False)
2809  """
2810 
2811  subfolder = dqmSubFolder.subfolder if dqmSubFolder is not None else None
2812  neventsHisto = self._plotFolder.getNumberOfEventsHistogram()
2813  dirsNEvents = []
2814 
2815  for tfile in files:
2816  ret = _getDirectoryDetailed(tfile, self._possibleDqmFolders, subfolder)
2817  # If file and any of possibleDqmFolders exist but subfolder does not, try the fallbacks
2819  for fallbackFunc in self._fallbackDqmSubFolders:
2820  fallback = fallbackFunc(subfolder)
2821  if fallback is not None:
2822  ret = _getDirectoryDetailed(tfile, self._possibleDqmFolders, fallback)
2823  if ret is not GetDirectoryCode.SubDirNotExist:
2824  break
2825  d = GetDirectoryCode.codesToNone(ret)
2826  nev = None
2827  if neventsHisto is not None and tfile is not None:
2828  hnev = _getObject(tfile, neventsHisto)
2829  if hnev is not None:
2830  nev = hnev.GetEntries()
2831  dirsNEvents.append( (d, nev) )
2832 
2833  self._plotFolder.create(dirsNEvents, labels, isPileupSample, requireAllHistograms)
2834 
2835  def draw(self, *args, **kwargs):
2836  """Draw and save all plots using settings of a given algorithm."""
2837  return self._plotFolder.draw(*args, **kwargs)
2838 
2839 
2841  """Instance of plotter that knows the directory content, holds many folders."""
2842  def __init__(self, folders):
2843  self._plotterFolders = [f for f in folders if f is not None]
2844 
2845  def iterFolders(self, limitSubFoldersOnlyTo=None):
2846  for plotterFolder in self._plotterFolders:
2847  limitOnlyTo = None
2848  if limitSubFoldersOnlyTo is not None:
2849  limitOnlyTo = limitSubFoldersOnlyTo.get(plotterFolder.getName(), None)
2850 
2851  for dqmSubFolder in plotterFolder.getDQMSubFolders(limitOnlyTo=limitOnlyTo):
2852  yield plotterFolder, dqmSubFolder
2853 
2854 # Helper for Plotter
2856  def __init__(self, name, possibleDirs, plotFolder, fallbackNames=[], fallbackDqmSubFolders=[]):
2857  """ Constructor
2858 
2859  Arguments:
2860  name -- Name of the folder (is used in the output directory naming)
2861  possibleDirs -- List of strings for possible directories of histograms in TFiles
2862  plotFolder -- PlotFolder object
2863 
2864  Keyword arguments
2865  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.
2866  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.
2867  """
2868  self._name = name
2869  self._possibleDirs = possibleDirs
2870  self._plotFolder = plotFolder
2871  self._fallbackNames = fallbackNames
2872  self._fallbackDqmSubFolders = fallbackDqmSubFolders
2873  self._tableCreators = []
2874 
2875  def getName(self):
2876  return self._name
2877 
2878  def getPlotFolder(self):
2879  return self._plotFolder
2880 
2881  def appendTableCreator(self, tc):
2882  self._tableCreators.append(tc)
2883 
2884  def readDirs(self, files):
2885  """Read available subfolders from the files
2886 
2887  Arguments:
2888  files -- List of strings for paths to files, or list of TFiles
2889 
2890  For each file, loop over 'possibleDirs', and read the
2891  subfolders of first one that exists.
2892 
2893  Returns a PlotterFolder if at least one file for which one of
2894  'possibleDirs' exists. Otherwise, return None to signal that
2895  there is nothing available for this PlotFolder.
2896  """
2897  subFolders = None
2898  if self._plotFolder.loopSubFolders():
2899  subFolders = []
2900  possibleDirFound = False
2901  for fname in files:
2902  if fname is None:
2903  continue
2904 
2905  isOpenFile = isinstance(fname, ROOT.TFile)
2906  if isOpenFile:
2907  tfile = fname
2908  else:
2909  tfile = ROOT.TFile.Open(fname)
2910  for pd in self._possibleDirs:
2911  d = tfile.Get(pd)
2912  if d:
2913  possibleDirFound = True
2914  if subFolders is not None:
2915  subf = []
2916  for key in d.GetListOfKeys():
2917  if isinstance(key.ReadObj(), ROOT.TDirectory):
2918  subf.append(key.GetName())
2919  subFolders.append(subf)
2920  break
2921  else:
2922  print("Did not find directory '%s' from file %s" % (pd, tfile.GetName()))
2923 
2924  if not isOpenFile:
2925  tfile.Close()
2926 
2927  if not possibleDirFound:
2928  return None
2929 
2930  return PlotterFolder(self._name, self._possibleDirs, subFolders, self._plotFolder, self._fallbackNames, self._fallbackDqmSubFolders, self._tableCreators)
2931 
2933  def __init__(self, possibleDirs, tableCreator):
2934  self._possibleDirs = possibleDirs
2935  self._tableCreator = tableCreator
2936 
2937  def create(self, openFiles, legendLabels, dqmSubFolder):
2938  if isinstance(dqmSubFolder, list):
2939  if len(dqmSubFolder) != len(openFiles):
2940  raise Exception("When dqmSubFolder is a list, len(dqmSubFolder) should be len(openFiles), now they are %d and %d" % (len(dqmSubFolder), len(openFiles)))
2941  else:
2942  dqmSubFolder = [dqmSubFolder]*len(openFiles)
2943  dqmSubFolder = [sf.subfolder if sf is not None else None for sf in dqmSubFolder]
2944 
2945  tbl = []
2946  for f, sf in zip(openFiles, dqmSubFolder):
2947  data = None
2948  tdir = _getDirectory(f, self._possibleDirs, sf)
2949  if tdir is not None:
2950  data = self._tableCreator.create(tdir)
2951  tbl.append(data)
2952 
2953  # Check if we have any content
2954  allNones = True
2955  colLen = 0
2956  for col in tbl:
2957  if col is not None:
2958  allNones = False
2959  colLen = len(col)
2960  break
2961  if allNones:
2962  return None
2963 
2964  # Replace all None columns with lists of column length
2965  for i in range(len(tbl)):
2966  if tbl[i] is None:
2967  tbl[i] = [None]*colLen
2968 
2969  return html.Table(columnHeaders=legendLabels, rowHeaders=self._tableCreator.headers(), table=tbl,
2970  purpose=self._tableCreator.getPurpose(), page=self._tableCreator.getPage(), section=self._tableCreator.getSection(dqmSubFolder[0]))
2971 
2972 class Plotter:
2973  """Contains PlotFolders, i.e. the information what plots to do, and creates a helper object to actually produce the plots."""
2974  def __init__(self):
2975  self._plots = []
2976  _setStyle()
2977  ROOT.TH1.AddDirectory(False)
2978 
2979  def append(self, *args, **kwargs):
2980  """Append a plot folder to the plotter.
2981 
2982  All arguments are forwarded to the constructor of PlotterItem.
2983  """
2984  self._plots.append(PlotterItem(*args, **kwargs))
2985 
2986  def appendTable(self, attachToFolder, *args, **kwargs):
2987  for plotterItem in self._plots:
2988  if plotterItem.getName() == attachToFolder:
2989  plotterItem.appendTableCreator(PlotterTableItem(*args, **kwargs))
2990  return
2991  raise Exception("Did not find plot folder '%s' when trying to attach a table creator to it" % attachToFolder)
2992 
2993  def clear(self):
2994  """Remove all plot folders and tables"""
2995  self._plots = []
2996 
2998  return [item.getName() for item in self._plots]
2999 
3000  def getPlotFolders(self):
3001  return [item.getPlotFolder() for item in self._plots]
3002 
3003  def getPlotFolder(self, name):
3004  for item in self._plots:
3005  if item.getName() == name:
3006  return item.getPlotFolder()
3007  raise Exception("No PlotFolder named '%s'" % name)
3008 
3009  def readDirs(self, *files):
3010  """Returns PlotterInstance object, which knows how exactly to produce the plots for these files"""
3011  return PlotterInstance([plotterItem.readDirs(files) for plotterItem in self._plots])
plotting.FrameTGraph2D.__init__
def __init__(self, pad, bounds, histos, ratioOrig, ratioFactor)
Definition: plotting.py:1435
plotting.PlotterFolder.getPage
def getPage(self)
Definition: plotting.py:2753
plotting.GetDirectoryCode
Definition: plotting.py:63
plotting._getYminIgnoreOutlier
def _getYminIgnoreOutlier(th1)
Definition: plotting.py:408
plotting.PlotGroup.remove
def remove(self, name)
Definition: plotting.py:2305
plotting.PlotFolder._plotGroups
_plotGroups
Definition: plotting.py:2571
plotting.GetDirectoryCode.SubDirNotExist
Definition: plotting.py:66
plotting.PlotGroup.draw
def draw(self, legendLabels, prefix=None, separate=False, saveFormat=".pdf", ratio=True, directory="")
Definition: plotting.py:2338
FastTimerService_cff.range
range
Definition: FastTimerService_cff.py:34
plotting.Plot.isRatio
def isRatio(self, ratio)
Definition: plotting.py:1859
plotting.Plot
Definition: plotting.py:1696
plotting.PlotterFolder.draw
def draw(self, *args, **kwargs)
Definition: plotting.py:2835
plotting.GetDirectoryCode.PossibleDirsNotExist
Definition: plotting.py:65
resolutioncreator_cfi.object
object
Definition: resolutioncreator_cfi.py:4
plotting.PlotFolder
Definition: plotting.py:2551
plotting.AggregateBins.__init__
def __init__(self, name, histoName, mapping, normalizeTo=None, scale=None, renameBin=None, ignoreMissingBins=False, minExistingBins=None, originalOrder=False, reorder=None)
Definition: plotting.py:951
plotting.FakeDuplicate
Definition: plotting.py:847
plotting.PlotGroup.getPlots
def getPlots(self)
Definition: plotting.py:2302
plotting._drawFrame
def _drawFrame(pad, bounds, zmax=None, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ybinlabels=None, suffix="")
Definition: plotting.py:1188
plotting.FrameTGraph2D.setXTitleSize
def setXTitleSize(self, size)
Definition: plotting.py:1487
plotting._mergeBinLabelsX
def _mergeBinLabelsX(histos)
Definition: plotting.py:708
plotting.Plotter.clear
def clear(self)
Definition: plotting.py:2993
plotting.PlotText._text
_text
Definition: plotting.py:1550
plotting.Plotter._plots
_plots
Definition: plotting.py:2975
plotting.PlotterTableItem._tableCreator
_tableCreator
Definition: plotting.py:2935
plotting.FrameTGraph2D._xtitlesize
_xtitlesize
Definition: plotting.py:1488
plotting._getYminMaxAroundMedian
def _getYminMaxAroundMedian(obj, coverage, coverageRange=None)
Definition: plotting.py:424
plotting.PlotterInstance
Definition: plotting.py:2840
plotting.PlotFolder._numberOfEventsHistogram
_numberOfEventsHistogram
Definition: plotting.py:2580
plotting.FrameTGraph2D.setLogy
def setLogy(self, log)
Definition: plotting.py:1464
plotting.FrameRatio
Definition: plotting.py:1313
plotting._th2RemoveEmptyBins
def _th2RemoveEmptyBins(histos, xbinlabels, ybinlabels)
Definition: plotting.py:648
plotting.PlotGroup.getPlot
def getPlot(self, name)
Definition: plotting.py:2318
plotting.FakeDuplicate.__init__
def __init__(self, name, assoc, dup, reco, title="")
Definition: plotting.py:849
plotting.PlotTextBox.Draw
def Draw(self, options="")
Definition: plotting.py:1648
plotting.FrameRatio.setXTitleSize
def setXTitleSize(self, size)
Definition: plotting.py:1392
plotting.FrameRatio.setYTitleRatio
def setYTitleRatio(self, title)
Definition: plotting.py:1404
plotting.Transform._title
_title
Definition: plotting.py:823
min
T min(T a, T b)
Definition: MathUtil.h:58
plotting.PlotTextBox._textArgs
_textArgs
Definition: plotting.py:1609
plotting.Frame.adjustMarginRight
def adjustMarginRight(self, adjust)
Definition: plotting.py:1280
plotting.FrameRatio._frameRatio
_frameRatio
Definition: plotting.py:1323
plotting.Frame._frame
_frame
Definition: plotting.py:1244
plotting.PlotFolder._labels
_labels
Definition: plotting.py:2641
plotting._calculateRatios
def _calculateRatios(histos, ratioUncertainty=False)
Definition: plotting.py:149
plotting.PlotTextBox._fillColor
_fillColor
Definition: plotting.py:1606
plotting._getYmin
def _getYmin(obj, limitToNonZeroContent=False)
Definition: plotting.py:375
plotting.FrameRatio.adjustMarginRight
def adjustMarginRight(self, adjust)
Definition: plotting.py:1377
plotting.FrameTGraph2D.setZTitleOffset
def setZTitleOffset(self, offset)
Definition: plotting.py:1508
plotting.Frame.setXLabelSize
def setXLabelSize(self, size)
Definition: plotting.py:1298
plotting.PlotFolder.getPlotGroup
def getPlotGroup(self, name)
Definition: plotting.py:2622
plotting.AggregateBins._histoName
_histoName
Definition: plotting.py:973
join
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
plotting.DQMSubFolder.subfolder
subfolder
Definition: plotting.py:2697
plotting.AggregateHistos._normalizeTo
_normalizeTo
Definition: plotting.py:1090
plotting.PlotGroup.onlyForPileup
def onlyForPileup(self)
Definition: plotting.py:2324
plotting.Plot.create
def create(self, tdirNEvents, requireAllHistograms=False)
Definition: plotting.py:1893
ntuplePlotting.draw
def draw(name, histos, styles=_defaultStyles, legendLabels=[], **kwargs)
Definition: ntuplePlotting.py:25
plotting.FrameTGraph2D._ytitleoffset
_ytitleoffset
Definition: plotting.py:1457
plotting.FrameRatio.setLogy
def setLogy(self, log)
Definition: plotting.py:1357
plotting._setStyle
def _setStyle()
Definition: plotting.py:22
plotting.Plot.setProperties
def setProperties(self, **kwargs)
Definition: plotting.py:1832
plotting.Plot.addToLegend
def addToLegend(self, legend, legendLabels, denomUncertainty)
Definition: plotting.py:2231
plotting.PlotText.Draw
def Draw(self, options=None)
Definition: plotting.py:1573
plotting.FrameTGraph2D.adjustMarginRight
def adjustMarginRight(self, adjust)
Definition: plotting.py:1477
plotting.Plot.drawRatioUncertainty
def drawRatioUncertainty(self)
Definition: plotting.py:1875
plotting.Frame.setGridy
def setGridy(self, grid)
Definition: plotting.py:1271
plotting.CutEfficiency
Definition: plotting.py:899
plotting.PlotOnSideGroup
Definition: plotting.py:2524
plotting.PlotFolder.translateSubFolder
def translateSubFolder(self, dqmSubFolderName)
Definition: plotting.py:2666
plotting.PlotFolder._purpose
_purpose
Definition: plotting.py:2577
plotting.PlotOnSideGroup.create
def create(self, tdirectoryNEvents, requireAllHistograms=False)
Definition: plotting.py:2538
plotting.FrameTGraph2D._firstHisto
_firstHisto
Definition: plotting.py:1459
plotting.PlotterTableItem._possibleDirs
_possibleDirs
Definition: plotting.py:2934
plotting.PlotTextBox.addText
def addText(self, text)
Definition: plotting.py:1614
plotting.FrameRatio.setGridy
def setGridy(self, grid)
Definition: plotting.py:1364
plotting.PlotterInstance._plotterFolders
_plotterFolders
Definition: plotting.py:2843
plotting.Subtract.__str__
def __str__(self)
Definition: plotting.py:783
plotting.CutEfficiency.create
def create(self, tdirectory)
Definition: plotting.py:921
plotting.PlotFolder._onlyForBHadron
_onlyForBHadron
Definition: plotting.py:2576
plotting.PlotEmpty.drawRatioUncertainty
def drawRatioUncertainty(self)
Definition: plotting.py:1684
plotting.FakeDuplicate.create
def create(self, tdirectory)
Definition: plotting.py:873
plotting._getDirectory
def _getDirectory(*args, **kwargs)
Definition: plotting.py:98
plotting.AggregateHistos.__str__
def __str__(self)
Definition: plotting.py:1092
plotting._findBounds
def _findBounds(th1s, ylog, xmin=None, xmax=None, ymin=None, ymax=None)
Definition: plotting.py:460
plotting.Frame.setXTitleSize
def setXTitleSize(self, size)
Definition: plotting.py:1292
plotting.Plot.isEmpty
def isEmpty(self)
Definition: plotting.py:1849
plotting.PlotGroup._ratioFactor
_ratioFactor
Definition: plotting.py:2291
plotting.AggregateBins.create
def create(self, tdirectory)
Definition: plotting.py:989
plotting.PlotterInstance.__init__
def __init__(self, folders)
Definition: plotting.py:2842
plotting.PlotFolder.getPurpose
def getPurpose(self)
Definition: plotting.py:2601
plotting.PlotGroup._modifyPadForRatio
def _modifyPadForRatio(self, pad)
Definition: plotting.py:2477
getRunAppsInfo.headers
headers
Definition: getRunAppsInfo.py:65
plotting.PlotOnSideGroup._plot
_plot
Definition: plotting.py:2532
plotting.PlotTextBox.move
def move(self, dx=0, dy=0, dw=0, dh=0)
Definition: plotting.py:1622
plotting.FrameRatio.setXTitleOffset
def setXTitleOffset(self, offset)
Definition: plotting.py:1395
plotting.PlotGroup._plots
_plots
Definition: plotting.py:2274
plotting.Plot._normalize
def _normalize(self)
Definition: plotting.py:1985
plotting.PlotFolder._onlyForElectron
_onlyForElectron
Definition: plotting.py:2574
plotting.PlotFolder.onlyForPileup
def onlyForPileup(self)
Definition: plotting.py:2588
plotting.FrameTGraph2D.setYTitleSize
def setYTitleSize(self, size)
Definition: plotting.py:1499
plotting.Plot.isTGraph2D
def isTGraph2D(self)
Definition: plotting.py:1853
plotting.PlotTextBox
Definition: plotting.py:1584
plotting.Plot._ratioAdditional
_ratioAdditional
Definition: plotting.py:2100
plotting.PlotFolder.getPage
def getPage(self)
Definition: plotting.py:2604
plotting.Frame.__init__
def __init__(self, pad, bounds, zmax, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ybinlabels=None)
Definition: plotting.py:1242
plotting.Frame.setYTitleOffset
def setYTitleOffset(self, offset)
Definition: plotting.py:1307
plotting.AggregateBins._originalOrder
_originalOrder
Definition: plotting.py:980
plotting.PlotTextBox._lineheight
_lineheight
Definition: plotting.py:1605
plotting.FakeDuplicate._name
_name
Definition: plotting.py:863
plotting.AggregateHistos.__init__
def __init__(self, name, mapping, normalizeTo=None)
Definition: plotting.py:1078
plotting.FrameTGraph2D.setXTitleOffset
def setXTitleOffset(self, size)
Definition: plotting.py:1490
plotting.PlotGroup._createLegend
def _createLegend(self, plot, legendLabels, lx1, ly1, lx2, ly2, textSize=0.016, denomUncertainty=True)
Definition: plotting.py:2481
plotting.ROC.__init__
def __init__(self, name, xhistoName, yhistoName, zaxis=False)
Definition: plotting.py:1124
plotting._mergeBinLabels
def _mergeBinLabels(labelsAll)
Definition: plotting.py:714
html.Table
Definition: html.py:294
plotting.PlotTextBox._xmax
_xmax
Definition: plotting.py:1602
plotting.FrameRatio.setYTitleSize
def setYTitleSize(self, size)
Definition: plotting.py:1407
plotting.FakeDuplicate._assoc
_assoc
Definition: plotting.py:864
plotting.FrameTGraph2D._ytitlesize
_ytitlesize
Definition: plotting.py:1500
plotting.FakeDuplicate._reco
_reco
Definition: plotting.py:866
plotting.AggregateBins._minExistingBins
_minExistingBins
Definition: plotting.py:979
plotting.Frame.setLogy
def setLogy(self, log)
Definition: plotting.py:1265
plotting.FrameTGraph2D
Definition: plotting.py:1433
plotting.CutEfficiency.__str__
def __str__(self)
Definition: plotting.py:917
plotting.PlotTextBox._texts
_texts
Definition: plotting.py:1608
plotting.Plotter.readDirs
def readDirs(self, *files)
Definition: plotting.py:3009
plotting.PlotterFolder._dqmSubFolders
_dqmSubFolders
Definition: plotting.py:2729
plotting.PlotOnSideGroup.append
def append(self, *args, **kwargs)
Definition: plotting.py:2535
plotting.PlotterFolder.getSelectionNameIterator
def getSelectionNameIterator(self, dqmSubFolder)
Definition: plotting.py:2792
clone
TEveGeoShape * clone(const TEveElement *element, TEveElement *parent)
Definition: eve_macros.cc:135
plotting.PlotterFolder.getName
def getName(self)
Definition: plotting.py:2747
plotting._modifyPadForRatio
def _modifyPadForRatio(pad, ratioFactor)
Definition: plotting.py:120
plotting._th1IncludeOnlyBins
def _th1IncludeOnlyBins(histos, xbinlabels)
Definition: plotting.py:745
plotting.FrameTGraph2D.setYTitle
def setYTitle(self, title)
Definition: plotting.py:1496
plotting._createCanvas
def _createCanvas(name, width, height)
Definition: plotting.py:110
plotting.FrameTGraph2D._xtitleoffset
_xtitleoffset
Definition: plotting.py:1456
plotting.FrameTGraph2D._xtitle
_xtitle
Definition: plotting.py:1485
plotting.CutEfficiency._title
_title
Definition: plotting.py:915
edm::convertException::wrap
auto wrap(F iFunc) -> decltype(iFunc())
Definition: ConvertException.h:19
plotting._getXmax
def _getXmax(obj, limitToNonZeroContent=False)
Definition: plotting.py:359
plotting.Plot.__init__
def __init__(self, name, **kwargs)
Definition: plotting.py:1698
plotting.PlotFolder.append
def append(self, plotGroup)
Definition: plotting.py:2613
plotting.FrameRatio.setYTitleOffset
def setYTitleOffset(self, offset)
Definition: plotting.py:1411
plotting.GetDirectoryCode.codesToNone
def codesToNone(code)
Definition: plotting.py:69
plotting.Plot._ytitle
_ytitle
Definition: plotting.py:2177
plotting.PlotEmpty.getNumberOfHistograms
def getNumberOfHistograms(self)
Definition: plotting.py:1693
mps_fire.end
end
Definition: mps_fire.py:242
plotting.CutEfficiency._histo
_histo
Definition: plotting.py:914
plotting.PlotFolder.onlyForBHadron
def onlyForBHadron(self)
Definition: plotting.py:2598
plotting.PlotFolder.create
def create(self, dirsNEvents, labels, isPileupSample=True, requireAllHistograms=False)
Definition: plotting.py:2628
plotting.PlotFolder._loopSubFolders
_loopSubFolders
Definition: plotting.py:2572
plotting.Transform._name
_name
Definition: plotting.py:820
plotting.Frame.setXTitle
def setXTitle(self, title)
Definition: plotting.py:1289
plotting.AggregateBins._name
_name
Definition: plotting.py:972
plotting.PlotFolder.getSection
def getSection(self)
Definition: plotting.py:2607
str
#define str(s)
Definition: TestProcessor.cc:52
plotting.PlotGroup._name
_name
Definition: plotting.py:2273
plotting.PlotGroup.append
def append(self, plot)
Definition: plotting.py:2315
plotting.PlotterFolder.getTableCreators
def getTableCreators(self)
Definition: plotting.py:2789
plotting.DQMSubFolder.equalTo
def equalTo(self, other)
Definition: plotting.py:2700
plotting.FrameRatio._parentPad
_parentPad
Definition: plotting.py:1316
plotting.PlotGroup._drawSeparate
def _drawSeparate(self, legendLabels, prefix, saveFormat, ratio, directory)
Definition: plotting.py:2415
plotting.PlotterItem.getPlotFolder
def getPlotFolder(self)
Definition: plotting.py:2878
plotting.ROC._yhistoName
_yhistoName
Definition: plotting.py:1137
plotting.PlotterItem.readDirs
def readDirs(self, files)
Definition: plotting.py:2884
plotting.AggregateBins._reorder
_reorder
Definition: plotting.py:981
plotting.Frame.setYTitleSize
def setYTitleSize(self, size)
Definition: plotting.py:1304
plotting.PlotFolder.onlyForConversion
def onlyForConversion(self)
Definition: plotting.py:2595
plotting.Plotter.__init__
def __init__(self)
Definition: plotting.py:2974
plotting.PlotFolder._onlyForPileup
_onlyForPileup
Definition: plotting.py:2573
plotting.FrameTGraph2D.setZTitle
def setZTitle(self, title)
Definition: plotting.py:1505
plotting.PlotTextBox._currenty
_currenty
Definition: plotting.py:1612
plotting.FrameRatio._frame
_frame
Definition: plotting.py:1319
plotting.Transform.__str__
def __str__(self)
Definition: plotting.py:825
plotting.PlotTextBox._pave
_pave
Definition: plotting.py:1658
plotting.Frame.setYTitle
def setYTitle(self, title)
Definition: plotting.py:1301
plotting.Plot._forLegend
_forLegend
Definition: plotting.py:2244
plotting.PlotterTableItem
Definition: plotting.py:2932
plotting.PlotterItem._fallbackNames
_fallbackNames
Definition: plotting.py:2871
plotting._th1RemoveEmptyBins
def _th1RemoveEmptyBins(histos, xbinlabels)
Definition: plotting.py:608
plotting.PlotTextBox._xmin
_xmin
Definition: plotting.py:1601
style
Definition: style.py:1
plotting.PlotGroup.__init__
def __init__(self, name, plots, **kwargs)
Definition: plotting.py:2254
plotting.Plot._frame
_frame
Definition: plotting.py:2229
plotting.FrameTGraph2D.setGridx
def setGridx(self, grid)
Definition: plotting.py:1467
plotting.PlotTextBox._transparent
_transparent
Definition: plotting.py:1607
plotting.PlotterFolder.getSection
def getSection(self)
Definition: plotting.py:2756
plotting.Plotter.getPlotFolder
def getPlotFolder(self, name)
Definition: plotting.py:3003
plotting.Frame.setXTitleOffset
def setXTitleOffset(self, offset)
Definition: plotting.py:1295
plotting.ROC._name
_name
Definition: plotting.py:1135
plotting.Plot._createOne
def _createOne(self, name, index, tdir, nevents)
Definition: plotting.py:1879
plotting.Plotter
Definition: plotting.py:2972
plotting.PlotterFolder.create
def create(self, files, labels, dqmSubFolder, isPileupSample=True, requireAllHistograms=False)
Definition: plotting.py:2801
plotting.FrameRatio.setXTitle
def setXTitle(self, title)
Definition: plotting.py:1389
plotting.FrameRatio.setLogx
def setLogx(self, log)
Definition: plotting.py:1353
plotting.PlotFolder.getNumberOfEventsHistogram
def getNumberOfEventsHistogram(self)
Definition: plotting.py:2610
plotting.Frame.setGridx
def setGridx(self, grid)
Definition: plotting.py:1268
plotting.PlotterFolder.getDQMSubFolders
def getDQMSubFolders(self, limitOnlyTo=None)
Definition: plotting.py:2774
plotting.PlotText._x
_x
Definition: plotting.py:1548
plotting.PlotFolder.iterSelectionName
def iterSelectionName(self, plotFolderName, translatedDqmSubFolder)
Definition: plotting.py:2676
plotting.Subtract
Definition: plotting.py:762
plotting.Plot._xtitle
_xtitle
Definition: plotting.py:2167
plotting.Subtract.create
def create(self, tdirectory)
Definition: plotting.py:787
print
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
Definition: Utilities.cc:46
SiStripPI::max
Definition: SiStripPayloadInspectorHelper.h:169
plotting.PlotFolder._page
_page
Definition: plotting.py:2578
plotting._getYmax
def _getYmax(obj, limitToNonZeroContent=False)
Definition: plotting.py:390
plotting.AggregateBins._scale
_scale
Definition: plotting.py:976
plotting.DQMSubFolder.translated
translated
Definition: plotting.py:2698
plotting.PlotOnSideGroup.draw
def draw(self, *args, **kwargs)
Definition: plotting.py:2546
jetUpdater_cfi.sort
sort
Definition: jetUpdater_cfi.py:29
Exception
plotting.Frame.adjustMarginLeft
def adjustMarginLeft(self, adjust)
Definition: plotting.py:1274
plotting.PlotterItem._plotFolder
_plotFolder
Definition: plotting.py:2870
plotting.Plotter.append
def append(self, *args, **kwargs)
Definition: plotting.py:2979
mps_setup.append
append
Definition: mps_setup.py:85
plotting.Plot.clone
def clone(self, **kwargs)
Definition: plotting.py:1838
plotting.Plotter.getPlotFolderNames
def getPlotFolderNames(self)
Definition: plotting.py:2997
plotting.FakeDuplicate._dup
_dup
Definition: plotting.py:865
plotting.Plot.getName
def getName(self)
Definition: plotting.py:1867
plotting.PlotterFolder.getPurpose
def getPurpose(self)
Definition: plotting.py:2750
plotting.FrameRatio.setXLabelSize
def setXLabelSize(self, size)
Definition: plotting.py:1398
plotting.Subtract.__init__
def __init__(self, name, nameA, nameB, title="")
Definition: plotting.py:764
plotting.PlotTextBox.__init__
def __init__(self, xmin, ymin, xmax, ymax, lineheight=0.04, fillColor=ROOT.kWhite, transparent=True, **kwargs)
Definition: plotting.py:1586
plotting.PlotterTableItem.create
def create(self, openFiles, legendLabels, dqmSubFolder)
Definition: plotting.py:2937
plotting.AggregateBins._normalizeTo
_normalizeTo
Definition: plotting.py:975
createfilelist.int
int
Definition: createfilelist.py:10
plotting._mergeBinLabelsY
def _mergeBinLabelsY(histos)
Definition: plotting.py:711
plotting.DQMSubFolder.__init__
def __init__(self, subfolder, translated)
Definition: plotting.py:2696
plotting.PlotText.__init__
def __init__(self, x, y, text, size=None, bold=True, align="left", color=ROOT.kBlack, font=None)
Definition: plotting.py:1535
plotting.PlotGroup._save
def _save(self, canvas, saveFormat, prefix=None, postfix=None, single=False, directory="")
Definition: plotting.py:2497
plotting.FakeDuplicate.__str__
def __str__(self)
Definition: plotting.py:869
plotting.FrameTGraph2D.setXTitle
def setXTitle(self, title)
Definition: plotting.py:1484
plotting.FrameRatio._padRatio
_padRatio
Definition: plotting.py:1322
plotting.AggregateBins._ignoreMissingBins
_ignoreMissingBins
Definition: plotting.py:978
plotting.Plot._name
_name
Definition: plotting.py:1759
plotting.PlotTextBox._ymax
_ymax
Definition: plotting.py:1604
plotting.PlotterFolder.onlyForPileup
def onlyForPileup(self)
Definition: plotting.py:2759
plotting.PlotterFolder.getPossibleDQMFolders
def getPossibleDQMFolders(self)
Definition: plotting.py:2771
plotting.PlotterItem._name
_name
Definition: plotting.py:2868
plotting.ROC._zaxis
_zaxis
Definition: plotting.py:1138
plotting.Transform.create
def create(self, tdirectory)
Definition: plotting.py:829
plotting.Plot._histograms
_histograms
Definition: plotting.py:1830
plotting.PlotterFolder._tableCreators
_tableCreators
Definition: plotting.py:2745
plotting.FrameRatio.adjustMarginLeft
def adjustMarginLeft(self, adjust)
Definition: plotting.py:1368
plotting.PlotterFolder._possibleDqmFolders
_possibleDqmFolders
Definition: plotting.py:2725
plotting.AggregateHistos._mapping
_mapping
Definition: plotting.py:1089
plotting.AggregateHistos
Definition: plotting.py:1076
plotting._getDirectoryDetailed
def _getDirectoryDetailed(tfile, possibleDirs, subDir=None)
Definition: plotting.py:74
plotting.AggregateHistos.create
def create(self, tdirectory)
Definition: plotting.py:1096
plotting.FrameTGraph2D.adjustMarginLeft
def adjustMarginLeft(self, adjust)
Definition: plotting.py:1473
plotting.ROC.create
def create(self, tdirectory)
Definition: plotting.py:1144
plotting.PlotterFolder.onlyForElectron
def onlyForElectron(self)
Definition: plotting.py:2762
plotting.FrameRatio.redrawAxis
def redrawAxis(self)
Definition: plotting.py:1415
ComparisonHelper::zip
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
Definition: L1TStage2CaloLayer1.h:41
plotting.PlotTextBox._ymin
_ymin
Definition: plotting.py:1603
plotting.ROC
Definition: plotting.py:1122
plotting._getXmin
def _getXmin(obj, limitToNonZeroContent=False)
Definition: plotting.py:343
plotting.PlotterFolder.__init__
def __init__(self, name, possibleDqmFolders, dqmSubFolders, plotFolder, fallbackNames, fallbackDqmSubFolders, tableCreators)
Definition: plotting.py:2711
plotting.PlotText
Definition: plotting.py:1533
plotting._getOrCreateObject
def _getOrCreateObject(tdirectory, nameOrCreator)
Definition: plotting.py:58
plotting.Transform
Definition: plotting.py:810
plotting.FrameTGraph2D.setXLabelSize
def setXLabelSize(self, size)
Definition: plotting.py:1493
plotting.PlotGroup.getName
def getName(self)
Definition: plotting.py:2299
plotting.DQMSubFolder
Definition: plotting.py:2694
plotting.GetDirectoryCode.FileNotExist
Definition: plotting.py:64
plotting.Plot.setName
def setName(self, name)
Definition: plotting.py:1864
plotting.FrameTGraph2D.redrawAxis
def redrawAxis(self)
Definition: plotting.py:1511
plotting.PlotterTableItem.__init__
def __init__(self, possibleDirs, tableCreator)
Definition: plotting.py:2933
plotting.PlotGroup.setProperties
def setProperties(self, **kwargs)
Definition: plotting.py:2293
plotting.CutEfficiency._name
_name
Definition: plotting.py:913
plotting.Frame
Definition: plotting.py:1240
plotting.PlotFolder._onlyForConversion
_onlyForConversion
Definition: plotting.py:2575
plotting.AggregateBins
Definition: plotting.py:949
plotting.PlotEmpty.__init__
def __init__(self)
Definition: plotting.py:1678
plotting.PlotFolder.onlyForElectron
def onlyForElectron(self)
Definition: plotting.py:2592
plotting.Subtract._nameA
_nameA
Definition: plotting.py:779
plotting.PlotFolder._section
_section
Definition: plotting.py:2579
plotting.Subtract._name
_name
Definition: plotting.py:778
plotting.PlotEmpty.create
def create(self, *args, **kwargs)
Definition: plotting.py:1687
plotting.FrameTGraph2D._ytitle
_ytitle
Definition: plotting.py:1497
plotting.FrameRatio._coverPad
_coverPad
Definition: plotting.py:1426
plotting.PlotterItem
Definition: plotting.py:2855
plotting.PlotterItem.getName
def getName(self)
Definition: plotting.py:2875
plotting.FrameRatio._pad
_pad
Definition: plotting.py:1317
plotting.PlotterItem.appendTableCreator
def appendTableCreator(self, tc)
Definition: plotting.py:2881
plotting.FrameRatio.setGridx
def setGridx(self, grid)
Definition: plotting.py:1360
plotting.PlotFolder.limitSubFolder
def limitSubFolder(self, limitOnlyTo, translatedDqmSubFolder)
Definition: plotting.py:2685
plotting.PlotFolder.__init__
def __init__(self, *plotGroups, **kwargs)
Definition: plotting.py:2554
plotting.PlotOnSideGroup.__init__
def __init__(self, name, plot, ncols=2, onlyForPileup=False)
Definition: plotting.py:2530
plotting.PlotFolder.getPlotGroups
def getPlotGroups(self)
Definition: plotting.py:2619
plotting.Transform._histo
_histo
Definition: plotting.py:821
format
plotting.Frame.setTitle
def setTitle(self, title)
Definition: plotting.py:1286
plotting.PlotFolder.draw
def draw(self, prefix=None, separate=False, saveFormat=".pdf", ratio=True, directory="")
Definition: plotting.py:2648
plotting.FakeDuplicate._title
_title
Definition: plotting.py:867
plotting.PlotFolder.set
def set(self, plotGroups)
Definition: plotting.py:2616
plotting._getObject
def _getObject(tdirectory, name)
Definition: plotting.py:50
plotting.FrameTGraph2D._pad
_pad
Definition: plotting.py:1436
plotting.Frame._pad
_pad
Definition: plotting.py:1243
plotting.PlotEmpty.getName
def getName(self)
Definition: plotting.py:1681
plotting._th1ToOrderedDict
def _th1ToOrderedDict(th1, renameBin=None)
Definition: plotting.py:101
plotting.PlotGroup.clear
def clear(self)
Definition: plotting.py:2312
plotting.AggregateHistos._name
_name
Definition: plotting.py:1088
AlignmentPI::index
index
Definition: AlignmentPayloadInspectorHelper.h:46
plotting._copyStyle
def _copyStyle(src, dst)
Definition: plotting.py:1664
plotting.PlotEmpty
Definition: plotting.py:1676
hippyaddtobaddatafiles.cd
def cd(newdir)
Definition: hippyaddtobaddatafiles.py:40
plotting.Plot.getNumberOfHistograms
def getNumberOfHistograms(self)
Definition: plotting.py:1845
plotting.FrameRatio.__init__
def __init__(self, pad, bounds, zmax, ratioBounds, ratioFactor, nrows, xbinlabels=None, xbinlabelsize=None, xbinlabeloption=None, ratioYTitle=_ratioYTitle)
Definition: plotting.py:1315
plotting.Plot._setStats
def _setStats(self, histos, startingX, startingY)
Definition: plotting.py:1943
plotting.AggregateBins._renameBin
_renameBin
Definition: plotting.py:977
plotting.PlotterFolder._fallbackDqmSubFolders
_fallbackDqmSubFolders
Definition: plotting.py:2744
plotting.PlotGroup.create
def create(self, tdirectoryNEvents, requireAllHistograms=False)
Definition: plotting.py:2328
plotting._findBoundsY
def _findBoundsY(th1s, ylog, ymin=None, ymax=None, coverage=None, coverageRange=None)
Definition: plotting.py:528
plotting.Subtract._nameB
_nameB
Definition: plotting.py:780
plotting.PlotFolder.loopSubFolders
def loopSubFolders(self)
Definition: plotting.py:2584
funct::abs
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
plotting.PlotterItem._tableCreators
_tableCreators
Definition: plotting.py:2873
genParticles_cff.map
map
Definition: genParticles_cff.py:11
divide
void divide(dqm::legacy::MonitorElement *eff, const dqm::legacy::MonitorElement *numerator, const dqm::legacy::MonitorElement *denominator)
Function to fill an efficiency histograms with binomial errors.
Definition: Histograms.h:20
plotting.Transform._func
_func
Definition: plotting.py:822
plotting.PlotTextBox.width
def width(self)
Definition: plotting.py:1619
plotting.PlotterItem._fallbackDqmSubFolders
_fallbackDqmSubFolders
Definition: plotting.py:2872
plotting.PlotterFolder.onlyForConversion
def onlyForConversion(self)
Definition: plotting.py:2765
plotting.FrameTGraph2D.setLogx
def setLogx(self, log)
Definition: plotting.py:1461
plotting.AggregateBins.__str__
def __str__(self)
Definition: plotting.py:985
hgcalPlots.loopSubFolders
loopSubFolders
Definition: hgcalPlots.py:2669
plotting.Plot._ratios
_ratios
Definition: plotting.py:2103
plotting.PlotText._y
_y
Definition: plotting.py:1549
plotting.FrameRatio.setYTitle
def setYTitle(self, title)
Definition: plotting.py:1401
plotting.ROC.__str__
def __str__(self)
Definition: plotting.py:1140
plotting.ROC._xhistoName
_xhistoName
Definition: plotting.py:1136
plotting.AggregateBins._mapping
_mapping
Definition: plotting.py:974
plotting.FrameTGraph2D.setYTitleOffset
def setYTitleOffset(self, offset)
Definition: plotting.py:1502
plotting.Frame.redrawAxis
def redrawAxis(self)
Definition: plotting.py:1310
plotting._getYmaxWithError
def _getYmaxWithError(th1)
Definition: plotting.py:405
plotting.FrameRatio.setTitle
def setTitle(self, title)
Definition: plotting.py:1386
plotting.PlotterInstance.iterFolders
def iterFolders(self, limitSubFoldersOnlyTo=None)
Definition: plotting.py:2845
cond::serialization::equal
bool equal(const T &first, const T &second)
Definition: Equal.h:32
plotting.Frame.setLogx
def setLogx(self, log)
Definition: plotting.py:1262
plotting.PlotterFolder.onlyForBHadron
def onlyForBHadron(self)
Definition: plotting.py:2768
plotting.Plot._mainAdditional
_mainAdditional
Definition: plotting.py:2099
plotting.PlotterItem.__init__
def __init__(self, name, possibleDirs, plotFolder, fallbackNames=[], fallbackDqmSubFolders=[])
Definition: plotting.py:2856
plotting.PlotText._l
_l
Definition: plotting.py:1552
plotting.Plotter.appendTable
def appendTable(self, attachToFolder, *args, **kwargs)
Definition: plotting.py:2986
plotting.CutEfficiency.__init__
def __init__(self, name, histo, title="")
Definition: plotting.py:906
plotting.PlotterFolder
Definition: plotting.py:2704
plotting.FrameTGraph2D._xlabelsize
_xlabelsize
Definition: plotting.py:1494
plotting.PlotEmpty.isEmpty
def isEmpty(self)
Definition: plotting.py:1690
plotting.PlotGroup
Definition: plotting.py:2252
plotting.Subtract._title
_title
Definition: plotting.py:781
plotting.Plot._tmp_histos
_tmp_histos
Definition: plotting.py:2063
plotting.PlotterFolder._plotFolder
_plotFolder
Definition: plotting.py:2726
plotting.FrameTGraph2D.setTitle
def setTitle(self, title)
Definition: plotting.py:1481
plotting.PlotterFolder._fallbackNames
_fallbackNames
Definition: plotting.py:2743
update
#define update(a, b)
Definition: TrackClassifier.cc:10
plotting.PlotterFolder._name
_name
Definition: plotting.py:2724
plotting.FrameTGraph2D.setGridy
def setGridy(self, grid)
Definition: plotting.py:1470
plotting.PlotterFolder.getSelectionName
def getSelectionName(self, dqmSubFolder)
Definition: plotting.py:2798
GetRecoTauVFromDQM_MC_cff.next
next
Definition: GetRecoTauVFromDQM_MC_cff.py:31
plotting.Transform.__init__
def __init__(self, name, histo, func, title="")
Definition: plotting.py:812
plotting.Plotter.getPlotFolders
def getPlotFolders(self)
Definition: plotting.py:3000
plotting.PlotterItem._possibleDirs
_possibleDirs
Definition: plotting.py:2869
plotting.Plot.draw
def draw(self, pad, ratio, ratioFactor, nrows)
Definition: plotting.py:1998