CombineHarvester
plotting.py
Go to the documentation of this file.
1 from __future__ import absolute_import
2 from __future__ import print_function
3 import ROOT as R
4 import math
5 from array import array
6 import re
7 import json
8 import types
9 import six
10 from six.moves import range
11 
12 COL_STORE = []
13 
14 
19 
20 
21 def SetTDRStyle():
22  """Sets the PubComm recommended style
23 
24  Just a copy of <http://ghm.web.cern.ch/ghm/plots/MacroExample/tdrstyle.C>
25  @sa ModTDRStyle() to use this style with some additional customisation.
26  """
27  # For the canvas:
28  R.gStyle.SetCanvasBorderMode(0)
29  R.gStyle.SetCanvasColor(R.kWhite)
30  R.gStyle.SetCanvasDefH(600) # Height of canvas
31  R.gStyle.SetCanvasDefW(600) # Width of canvas
32  R.gStyle.SetCanvasDefX(0) # POsition on screen
33  R.gStyle.SetCanvasDefY(0)
34 
35  # For the Pad:
36  R.gStyle.SetPadBorderMode(0)
37  # R.gStyle.SetPadBorderSize(Width_t size = 1)
38  R.gStyle.SetPadColor(R.kWhite)
39  R.gStyle.SetPadGridX(False)
40  R.gStyle.SetPadGridY(False)
41  R.gStyle.SetGridColor(0)
42  R.gStyle.SetGridStyle(3)
43  R.gStyle.SetGridWidth(1)
44 
45  # For the frame:
46  R.gStyle.SetFrameBorderMode(0)
47  R.gStyle.SetFrameBorderSize(1)
48  R.gStyle.SetFrameFillColor(0)
49  R.gStyle.SetFrameFillStyle(0)
50  R.gStyle.SetFrameLineColor(1)
51  R.gStyle.SetFrameLineStyle(1)
52  R.gStyle.SetFrameLineWidth(1)
53 
54  # For the histo:
55  # R.gStyle.SetHistFillColor(1)
56  # R.gStyle.SetHistFillStyle(0)
57  R.gStyle.SetHistLineColor(1)
58  R.gStyle.SetHistLineStyle(0)
59  R.gStyle.SetHistLineWidth(1)
60  # R.gStyle.SetLegoInnerR(Float_t rad = 0.5)
61  # R.gStyle.SetNumberContours(Int_t number = 20)
62 
63  R.gStyle.SetEndErrorSize(2)
64  # R.gStyle.SetErrorMarker(20)
65  # R.gStyle.SetErrorX(0.)
66 
67  R.gStyle.SetMarkerStyle(20)
68 
69  # For the fit/function:
70  R.gStyle.SetOptFit(1)
71  R.gStyle.SetFitFormat('5.4g')
72  R.gStyle.SetFuncColor(2)
73  R.gStyle.SetFuncStyle(1)
74  R.gStyle.SetFuncWidth(1)
75 
76  # For the date:
77  R.gStyle.SetOptDate(0)
78  # R.gStyle.SetDateX(Float_t x = 0.01)
79  # R.gStyle.SetDateY(Float_t y = 0.01)
80 
81  # For the statistics box:
82  R.gStyle.SetOptFile(0)
83  R.gStyle.SetOptStat(0)
84  # To display the mean and RMS: SetOptStat('mr')
85  R.gStyle.SetStatColor(R.kWhite)
86  R.gStyle.SetStatFont(42)
87  R.gStyle.SetStatFontSize(0.025)
88  R.gStyle.SetStatTextColor(1)
89  R.gStyle.SetStatFormat('6.4g')
90  R.gStyle.SetStatBorderSize(1)
91  R.gStyle.SetStatH(0.1)
92  R.gStyle.SetStatW(0.15)
93  # R.gStyle.SetStatStyle(Style_t style = 1001)
94  # R.gStyle.SetStatX(Float_t x = 0)
95  # R.gStyle.SetStatY(Float_t y = 0)
96 
97  # Margins:
98  R.gStyle.SetPadTopMargin(0.05)
99  R.gStyle.SetPadBottomMargin(0.13)
100  R.gStyle.SetPadLeftMargin(0.16)
101  R.gStyle.SetPadRightMargin(0.02)
102 
103  # For the Global title:
104  R.gStyle.SetOptTitle(0)
105  R.gStyle.SetTitleFont(42)
106  R.gStyle.SetTitleColor(1)
107  R.gStyle.SetTitleTextColor(1)
108  R.gStyle.SetTitleFillColor(10)
109  R.gStyle.SetTitleFontSize(0.05)
110  # R.gStyle.SetTitleH(0); # Set the height of the title box
111  # R.gStyle.SetTitleW(0); # Set the width of the title box
112  # R.gStyle.SetTitleX(0); # Set the position of the title box
113  # R.gStyle.SetTitleY(0.985); # Set the position of the title box
114  # R.gStyle.SetTitleStyle(Style_t style = 1001)
115  # R.gStyle.SetTitleBorderSize(2)
116 
117  # For the axis titles:
118  R.gStyle.SetTitleColor(1, 'XYZ')
119  R.gStyle.SetTitleFont(42, 'XYZ')
120  R.gStyle.SetTitleSize(0.06, 'XYZ')
121  # Another way to set the size?
122  # R.gStyle.SetTitleXSize(Float_t size = 0.02)
123  # R.gStyle.SetTitleYSize(Float_t size = 0.02)
124  R.gStyle.SetTitleXOffset(0.9)
125  R.gStyle.SetTitleYOffset(1.25)
126  # R.gStyle.SetTitleOffset(1.1, 'Y'); # Another way to set the Offset
127 
128  # For the axis labels:
129 
130  R.gStyle.SetLabelColor(1, 'XYZ')
131  R.gStyle.SetLabelFont(42, 'XYZ')
132  R.gStyle.SetLabelOffset(0.007, 'XYZ')
133  R.gStyle.SetLabelSize(0.05, 'XYZ')
134 
135  # For the axis:
136 
137  R.gStyle.SetAxisColor(1, 'XYZ')
138  R.gStyle.SetStripDecimals(True)
139  R.gStyle.SetTickLength(0.03, 'XYZ')
140  R.gStyle.SetNdivisions(510, 'XYZ')
141  R.gStyle.SetPadTickX(1)
142  R.gStyle.SetPadTickY(1)
143 
144  # Change for log plots:
145  R.gStyle.SetOptLogx(0)
146  R.gStyle.SetOptLogy(0)
147  R.gStyle.SetOptLogz(0)
148 
149  # Postscript options:
150  R.gStyle.SetPaperSize(20., 20.)
151  # R.gStyle.SetLineScalePS(Float_t scale = 3)
152  # R.gStyle.SetLineStyleString(Int_t i, const char* text)
153  # R.gStyle.SetHeaderPS(const char* header)
154  # R.gStyle.SetTitlePS(const char* pstitle)
155 
156  # R.gStyle.SetBarOffset(Float_t baroff = 0.5)
157  # R.gStyle.SetBarWidth(Float_t barwidth = 0.5)
158  # R.gStyle.SetPaintTextFormat(const char* format = 'g')
159  # R.gStyle.SetPalette(Int_t ncolors = 0, Int_t* colors = 0)
160  # R.gStyle.SetTimeOffset(Double_t toffset)
161  # R.gStyle.SetHistMinimumZero(kTRUE)
162 
163  R.gStyle.SetHatchesLineWidth(5)
164  R.gStyle.SetHatchesSpacing(0.05)
165 
166 
167 def ModTDRStyle(width=600, height=600, t=0.06, b=0.12, l=0.16, r=0.04):
168  """Modified version of the tdrStyle
169 
170  Args:
171  width (int): Canvas width in pixels
172  height (int): Canvas height in pixels
173  t (float): Pad top margin [0-1]
174  b (float): Pad bottom margin [0-1]
175  l (float): Pad left margin [0-1]
176  r (float): Pad right margin [0-1]
177  """
178  SetTDRStyle()
179 
180  # Set the default canvas width and height in pixels
181  R.gStyle.SetCanvasDefW(width)
182  R.gStyle.SetCanvasDefH(height)
183 
184  # Set the default margins. These are given as fractions of the pad height
185  # for `Top` and `Bottom` and the pad width for `Left` and `Right`. But we
186  # want to specify all of these as fractions of the shortest length.
187  def_w = float(R.gStyle.GetCanvasDefW())
188  def_h = float(R.gStyle.GetCanvasDefH())
189 
190  scale_h = (def_w / def_h) if (def_h > def_w) else 1.
191  scale_w = (def_h / def_w) if (def_w > def_h) else 1.
192 
193  def_min = def_h if (def_h < def_w) else def_w
194 
195  R.gStyle.SetPadTopMargin(t * scale_h)
196  # default 0.05
197  R.gStyle.SetPadBottomMargin(b * scale_h)
198  # default 0.13
199  R.gStyle.SetPadLeftMargin(l * scale_w)
200  # default 0.16
201  R.gStyle.SetPadRightMargin(r * scale_w)
202  # default 0.02
203  # But note the new CMS style sets these:
204  # 0.08, 0.12, 0.12, 0.04
205 
206  # Set number of axis tick divisions
207  R.gStyle.SetNdivisions(506, 'XYZ') # default 510
208 
209  # Some marker properties not set in the default tdr style
210  R.gStyle.SetMarkerColor(R.kBlack)
211  R.gStyle.SetMarkerSize(1.0)
212 
213  R.gStyle.SetLabelOffset(0.007, 'YZ')
214  # This is an adhoc adjustment to scale the x-axis label
215  # offset when we stretch plot vertically
216  # Will also need to increase if first x-axis label has more than one digit
217  R.gStyle.SetLabelOffset(0.005 * (3. - 2. / scale_h), 'X')
218 
219  # In this next part we do a slightly involved calculation to set the axis
220  # title offsets, depending on the values of the TPad dimensions and
221  # margins. This is to try and ensure that regardless of how these pad
222  # values are set, the axis titles will be located towards the edges of the
223  # canvas and not get pushed off the edge - which can often happen if a
224  # fixed value is used.
225  title_size = 0.05
226  title_px = title_size * def_min
227  label_size = 0.04
228  R.gStyle.SetTitleSize(title_size, 'XYZ')
229  R.gStyle.SetLabelSize(label_size, 'XYZ')
230 
231  R.gStyle.SetTitleXOffset(0.5 * scale_h *
232  (1.2 * (def_h * b * scale_h - 0.6 * title_px)) /
233  title_px)
234  R.gStyle.SetTitleYOffset(0.5 * scale_w *
235  (1.2 * (def_w * l * scale_w - 0.6 * title_px)) /
236  title_px)
237 
238  # Only draw ticks where we have an axis
239  R.gStyle.SetPadTickX(0)
240  R.gStyle.SetPadTickY(0)
241  R.gStyle.SetTickLength(0.02, 'XYZ')
242 
243  R.gStyle.SetLegendBorderSize(0)
244  R.gStyle.SetLegendFont(42)
245  R.gStyle.SetLegendFillColor(0)
246  R.gStyle.SetFillColor(0)
247 
248  R.gROOT.ForceStyle()
249 
250 
252  nRGBs = 9
253  stops = array(
254  'd', [0.0000, 0.1250, 0.2500, 0.3750, 0.5000, 0.6250, 0.7500, 0.8750, 1.0000])
255  red = array(
256  'd', [0.2082, 0.0592, 0.0780, 0.0232, 0.1802, 0.5301, 0.8186, 0.9956, 0.9764])
257  green = array(
258  'd', [0.1664, 0.3599, 0.5041, 0.6419, 0.7178, 0.7492, 0.7328, 0.7862, 0.9832])
259  blue = array(
260  'd', [0.5293, 0.8684, 0.8385, 0.7914, 0.6425, 0.4662, 0.3499, 0.1968, 0.0539])
261  R.TColor.CreateGradientColorTable(nRGBs, stops, red, green, blue, 255, 1)
262 
263 
265  nRGBs = 9
266  stops = array(
267  'd', [0.0000, 0.1250, 0.2500, 0.3750, 0.5000, 0.6250, 0.7500, 0.8750, 1.0000])
268  red = array(
269  'd', reversed([0./255., 9./255., 13./255., 17./255., 24./255., 32./255., 27./255., 25./255., 29./255.]))
270  green = array(
271  'd', reversed([0./255., 0./255., 0./255., 2./255., 37./255., 74./255., 113./255., 160./255., 221./255.]))
272  blue = array(
273  'd', reversed([28./255., 42./255., 59./255., 78./255., 98./255., 129./255., 154./255., 184./255., 221./255.]))
274  R.TColor.CreateGradientColorTable(nRGBs, stops, red, green, blue, 255, 1)
275 
276 
278  R.TColor.CreateGradientColorTable(3,
279  array ("d", [0.00, 0.50, 1.00]),
280  array ("d", [1.00, 1.00, 0.00]),
281  array ("d", [0.70, 1.00, 0.34]),
282  array ("d", [0.00, 1.00, 0.82]),
283  255, 1.0)
284 
285 
286 def CreateTransparentColor(color, alpha):
287  adapt = R.gROOT.GetColor(color)
288  new_idx = R.gROOT.GetListOfColors().GetLast() + 1
289  trans = R.TColor(
290  new_idx, adapt.GetRed(), adapt.GetGreen(), adapt.GetBlue(), '', alpha)
291  COL_STORE.append(trans)
292  trans.SetName('userColor%i' % new_idx)
293  return new_idx
294 
295 
296 def Set(obj, **kwargs):
297  for key, value in six.iteritems(kwargs):
298  if value is None:
299  getattr(obj, 'Set' + key)()
300  elif isinstance(value, (list, tuple)):
301  getattr(obj, 'Set' + key)(*value)
302  else:
303  getattr(obj, 'Set' + key)(value)
304 
305 
306 
307 
308 
313 
314 def OnePad():
315  pad = R.TPad('pad', 'pad', 0., 0., 1., 1.)
316  pad.Draw()
317  pad.cd()
318  result = [pad]
319  return result
320 
321 
322 def TwoPadSplit(split_point, gap_low, gap_high):
323  upper = R.TPad('upper', 'upper', 0., 0., 1., 1.)
324  upper.SetBottomMargin(split_point + gap_high)
325  upper.SetFillStyle(4000)
326  upper.Draw()
327  lower = R.TPad('lower', 'lower', 0., 0., 1., 1.)
328  lower.SetTopMargin(1 - split_point + gap_low)
329  lower.SetFillStyle(4000)
330  lower.Draw()
331  upper.cd()
332  result = [upper, lower]
333  return result
334 
335 def ThreePadSplit(upper_split_point, split_point, gap_low, gap_high):
336  upper2 = R.TPad('upper2', 'upper2', 0., 0., 1., 1.)
337  upper2.SetTopMargin(1 - upper_split_point)
338  upper2.SetBottomMargin(split_point + gap_high)
339  upper2.SetFillStyle(4000)
340  upper2.Draw()
341  upper1 = R.TPad('upper1', 'upper1', 0., 0., 1., 1.)
342  upper1.SetBottomMargin(upper_split_point)
343  upper1.SetFillStyle(4000)
344  upper1.Draw()
345  lower = R.TPad('lower', 'lower', 0., 0., 1., 1.)
346  lower.SetTopMargin(1 - split_point + gap_low)
347  lower.SetFillStyle(4000)
348  lower.Draw()
349  upper1.cd()
350  result = [upper1, lower, upper2]
351  return result
352 
353 def MultiRatioSplit(split_points, gaps_low, gaps_high):
354  """Create a set of TPads split vertically on the TCanvas
355 
356  This is a generalisation of the two pad main/ratio split but for the case
357  of multiple ratio pads.
358 
359  Args:
360 
361  split_points (list[float]): Height of each ratio pad as a fraction of the
362  canvas height. Pads will be created from the bottom of the frame
363  upwards. The final, main pad will occupy however much space remains,
364  therefore the size of this list should be [number of pads] - 1.
365  gaps_low (list[float]): Gaps between ratio pad frames created on the
366  lower pad side at each boundary. Give a list of zeroes for no gap
367  between pad frames. Should be the same length as `split_points`.1
368  gaps_high (list[float]): Gaps between ratio pad frames created on the
369  upper pad side at each boundary. Give a list of zeroes for no gap
370  between pad frames.
371 
372  Returns:
373  list[TPad]: List of TPads, indexed from top to bottom on the canvas.
374  """
375  pads = []
376  for i in range(len(split_points)+1):
377  pad = R.TPad('pad%i'%i, '', 0., 0., 1., 1.)
378  if i > 0:
379  pad.SetBottomMargin(sum(split_points[0:i])+gaps_high[i-1])
380  if i < len(split_points):
381  pad.SetTopMargin(1.-sum(split_points[0:i+1])+gaps_low[i])
382  pad.SetFillStyle(4000)
383  pad.Draw()
384  pads.append(pad)
385  pads.reverse()
386  return pads
387 
388 
389 def TwoPadSplitColumns(split_point, gap_left, gap_right):
390  left = R.TPad('left', 'left', 0., 0., 1., 1.)
391  left.SetRightMargin(1 - split_point + gap_right)
392  left.SetFillStyle(4000)
393  left.Draw()
394  right = R.TPad('right', 'right', 0., 0., 1., 1.)
395  right.SetLeftMargin(split_point + gap_left)
396  right.SetFillStyle(4000)
397  right.Draw()
398  left.cd()
399  result = [left, right]
400  return result
401 
402 
403 def MultiRatioSplitColumns(split_points, gaps_left, gaps_right):
404  pads = []
405  for i in range(len(split_points)+1):
406  pad = R.TPad('pad%i'%i, '', 0., 0., 1., 1.)
407  if i > 0:
408  pad.SetLeftMargin(sum(split_points[0:i])+gaps_left[i-1])
409  if i < len(split_points):
410  pad.SetRightMargin(1.-sum(split_points[0:i+1])+gaps_right[i])
411  pad.SetFillStyle(4000)
412  pad.Draw()
413  pads.append(pad)
414  pads[0].cd()
415  # pads.reverse()
416  return pads
417 
418 
419 def SetupTwoPadSplitAsRatio(pads, upper, lower, y_title, y_centered,
420  y_min, y_max):
421  if lower.GetXaxis().GetTitle() == '':
422  lower.GetXaxis().SetTitle(upper.GetXaxis().GetTitle())
423  upper.GetXaxis().SetTitle("")
424  upper.GetXaxis().SetLabelSize(0)
425  upper_h = 1. - pads[0].GetTopMargin() - pads[0].GetBottomMargin()
426  lower_h = 1. - pads[1].GetTopMargin() - pads[1].GetBottomMargin()
427  lower.GetYaxis().SetTickLength(R.gStyle.GetTickLength() * upper_h / lower_h)
428  pads[1].SetTickx(1)
429  pads[1].SetTicky(1)
430  lower.GetYaxis().SetTitle(y_title)
431  lower.GetYaxis().CenterTitle(y_centered)
432  if y_max > y_min:
433  lower.SetMinimum(y_min)
434  lower.SetMaximum(y_max)
435 
436 
437 def StandardAxes(xaxis, yaxis, var, units, fmt='.1f'):
438  width = xaxis.GetBinWidth(1)
439  w_label = ("%"+fmt) % width
440  if units == "":
441  xaxis.SetTitle(var)
442  yaxis.SetTitle("Events / " + w_label)
443  else:
444  xaxis.SetTitle(var + " (" + units + ")")
445  yaxis.SetTitle("Events / " + w_label + " " + units)
446 
447 
448 
449 
450 
451 
452 
459 
460 def CreateAxisHist(src, at_limits=True):
461  backup = R.gPad
462  tmp = R.TCanvas()
463  tmp.cd()
464  src.Draw('AP')
465  result = src.GetHistogram().Clone('tmp')
466  if (at_limits):
467  min = 0.
468  max = 0.
469  x = R.Double(0.)
470  y = R.Double(0.)
471  src.GetPoint(0, x, y)
472  min = float(x)
473  max = float(x)
474  for i in range(1, src.GetN()):
475  src.GetPoint(i, x, y)
476  if x < min:
477  min = float(x)
478  if x > max:
479  max = float(x)
480  result.GetXaxis().SetLimits(min, max)
481  R.gPad = backup
482  return result
483 
484 
485 def CreateAxisHists(n, src, at_limits):
486  res = []
487  h = CreateAxisHist(src, at_limits)
488  for i in range(n):
489  res.append(h.Clone('tmp%i'%i))
490  return res
491 
492 
493 def GetAxisHist(pad):
494  pad_obs = pad.GetListOfPrimitives()
495  if pad_obs is None:
496  return None
497  obj = None
498  for obj in pad_obs:
499  if obj.InheritsFrom(R.TH1.Class()):
500  return obj
501  if obj.InheritsFrom(R.TMultiGraph.Class()):
502  return obj.GetHistogram()
503  if obj.InheritsFrom(R.TGraph.Class()):
504  return obj.GetHistogram()
505  if obj.InheritsFrom(R.THStack.Class()):
506  return obj.GetHistogram()
507  return None
508 
509 
510 
511 
512 
516 
517 def TFileIsGood(filename):
518  """Performs a series of tests on a TFile to ensure that it can be opened
519  without errors
520 
521  Args:
522  filename: `str` The name of the TFile to check
523 
524  Returns:
525  `bool` True if the file can opened, is not a zombie, and if ROOT did
526  not need to try and recover the contents
527  """
528  fin = R.TFile(filename)
529  if not fin:
530  return False
531  if fin and not fin.IsOpen():
532  return False
533  elif fin and fin.IsOpen() and fin.IsZombie():
534  fin.Close()
535  return False
536  elif fin and fin.IsOpen() and fin.TestBit(R.TFile.kRecovered):
537  fin.Close()
538  # don't consider a recovered file to be OK
539  return False
540  else:
541  fin.Close()
542  return True
543 
544 
545 def MakeTChain(files, tree):
546  chain = R.TChain(tree)
547  for f in files:
548  chain.Add(f)
549  return chain
550 
551 
552 def Get(file, obj):
553  R.TH1.AddDirectory(False)
554  f_in = R.TFile(file)
555  res = R.gDirectory.Get(obj)
556  f_in.Close()
557  return res
558 
559 
560 def ParamFromFilename(filename, param):
561  if len(re.findall(param + '\.\d+\.\d+', filename)):
562  num1 = re.findall(
563  param + '\.\d+\.\d+', filename)[0].replace(param + '.', '')
564  return float(num1)
565  elif len(re.findall(param + '\.\d+', filename)):
566  num1 = re.findall(param + '\.\d+', filename)[0].replace(param + '.', '')
567  return int(num1)
568  else:
569  print("Error: parameter " + param + " not found in filename")
570 
571 
572 
573 
574 
575 
580 
581 def TGraphFromTree(tree, xvar, yvar, selection):
582  tree.Draw(xvar + ':' + yvar, selection, 'goff')
583  gr = R.TGraph(tree.GetSelectedRows(), tree.GetV1(), tree.GetV2())
584  return gr
585 
586 
587 def TGraph2DFromTree(tree, xvar, yvar, zvar, selection):
588  tree.Draw(xvar + ':' + yvar + ':' + zvar, selection, 'goff')
589  gr = R.TGraph2D(
590  tree.GetSelectedRows(), tree.GetV1(), tree.GetV2(), tree.GetV3())
591  return gr
592 
593 
594 def RocCurveFrom1DHists(h_x, h_y, cut_is_greater_than):
595  backup = R.TH1.AddDirectoryStatus()
596  R.TH1.AddDirectory(False)
597  x_den = h_x.Clone()
598  x_num = h_x.Clone()
599  x_err = R.Double(0.)
600  x_int = h_x.IntegralAndError(0, h_x.GetNbinsX() + 1, x_err)
601  for i in range(1, h_x.GetNbinsX() + 1):
602  x_part_err = R.Double(0.)
603  x_part_int = h_x.IntegralAndError(i, h_x.GetNbinsX(
604  ) + 1, x_part_err) if cut_is_greater_than else h_x.IntegralAndError(0, i, x_part_err)
605  x_den.SetBinContent(i, x_int)
606  x_den.SetBinError(i, x_err)
607  x_num.SetBinContent(i, x_part_int)
608  x_num.SetBinError(i, x_part_err)
609  y_den = h_y.Clone()
610  y_num = h_y.Clone()
611  y_err = R.Double(0.)
612  y_int = h_y.IntegralAndError(0, h_y.GetNbinsX() + 1, y_err)
613  for i in range(1, h_y.GetNbinsX() + 1):
614  y_part_err = R.Double(0.)
615  y_part_int = h_y.IntegralAndError(i, h_y.GetNbinsX(
616  ) + 1, y_part_err) if cut_is_greater_than else h_y.IntegralAndError(0, i, y_part_err)
617  y_den.SetBinContent(i, y_int)
618  y_den.SetBinError(i, y_err)
619  y_num.SetBinContent(i, y_part_int)
620  y_num.SetBinError(i, y_part_err)
621  # x_den.Print('all')
622  # x_num.Print('all')
623  # y_den.Print('all')
624  # y_num.Print('all')
625  x_gr = R.TGraphAsymmErrors(x_num, x_den)
626  y_gr = R.TGraphAsymmErrors(y_num, y_den)
627 
628  res = y_gr.Clone()
629  for i in range(0, res.GetN()):
630  res.GetX()[i] = x_gr.GetY()[i]
631  res.GetEXlow()[i] = x_gr.GetEYlow()[i]
632  res.GetEXhigh()[i] = x_gr.GetEYhigh()[i]
633  res.Sort()
634  R.TH1.AddDirectory(backup)
635  return res
636 
637 
638 def TH2FromTGraph2D(graph, method='BinEdgeAligned',
639  force_x_width=None,
640  force_y_width=None):
641  """Build an empty TH2 from the set of points in a TGraph2D
642 
643  There is no unique way to define a TH2 binning given an arbitrary
644  TGraph2D, therefore this function supports multiple named methods:
645 
646  - `BinEdgeAligned` simply takes the sets of x- and y- values in the
647  TGraph2D and uses these as the bin edge arrays in the TH2. The
648  implication of this is that when filling the bin contents interpolation
649  will be required when evaluating the TGraph2D at the bin centres.
650  - `BinCenterAligned` will try to have the TGraph2D points at the bin
651  centers, but this will only work completely correctly when the input
652  point spacing is regular. The algorithm first identifies the bin width
653  as the smallest interval between points on each axis. The start
654  position of the TH2 axis is then defined as the lowest value in the
655  TGraph2D minus half this width, and the axis continues with regular
656  bins until the graph maximum is passed.
657 
658  Args:
659  graph (TGraph2D): Should have at least two unique x and y values,
660  otherwise we can't define any bins
661  method (str): The binning algorithm to use
662  force_x_width (bool): Override the derived x-axis bin width in the
663  CenterAligned method
664  force_y_width (bool): Override the derived y-axis bin width in the
665  CenterAligned method
666 
667  Raises:
668  RuntimeError: If the method name is not recognised
669 
670  Returns:
671  TH2F: The exact binning of the TH2F depends on the chosen method
672  """
673  x_vals = set()
674  y_vals = set()
675 
676  for i in range(graph.GetN()):
677  x_vals.add(graph.GetX()[i])
678  y_vals.add(graph.GetY()[i])
679 
680  x_vals = sorted(x_vals)
681  y_vals = sorted(y_vals)
682  if method == 'BinEdgeAligned':
683  h_proto = R.TH2F('prototype', '',
684  len(x_vals) - 1, array('d', x_vals),
685  len(y_vals) - 1, array('d', y_vals))
686  elif method == 'BinCenterAligned':
687  x_widths = []
688  y_widths = []
689  for i in range(1, len(x_vals)):
690  x_widths.append(x_vals[i] - x_vals[i - 1])
691  for i in range(1, len(y_vals)):
692  y_widths.append(y_vals[i] - y_vals[i - 1])
693  x_min = min(x_widths) if force_x_width is None else force_x_width
694  y_min = min(y_widths) if force_y_width is None else force_y_width
695  x_bins = int(((x_vals[-1] - (x_vals[0] - 0.5 * x_min)) / x_min) + 0.5)
696  y_bins = int(((y_vals[-1] - (y_vals[0] - 0.5 * y_min)) / y_min) + 0.5)
697  print('[TH2FromTGraph2D] x-axis binning: (%i, %g, %g)' % (x_bins, x_vals[0] - 0.5 * x_min, x_vals[0] - 0.5 * x_min + x_bins * x_min))
698  print('[TH2FromTGraph2D] y-axis binning: (%i, %g, %g)' % (y_bins, y_vals[0] - 0.5 * y_min, y_vals[0] - 0.5 * y_min + y_bins * y_min))
699  # Use a number slightly smaller than 0.49999 because the TGraph2D interpolation
700  # is fussy about evaluating on the boundary
701  h_proto = R.TH2F('prototype', '',
702  x_bins, x_vals[
703  0] - 0.49999 * x_min, x_vals[0] - 0.50001 * x_min + x_bins * x_min,
704  y_bins, y_vals[0] - 0.49999 * y_min, y_vals[0] - 0.50001 * y_min + y_bins * y_min)
705  else:
706  raise RuntimeError(
707  '[TH2FromTGraph2D] Method %s not supported' % method)
708  h_proto.SetDirectory(0)
709  return h_proto
710 
711 
712 def MakeErrorBand(LowerGraph, UpperGraph):
713  errorBand = R.TGraphAsymmErrors()
714  lower_list = []
715  upper_list = []
716  for i in range(LowerGraph.GetN()):
717  lower_list.append(
718  (float(LowerGraph.GetX()[i]), float(LowerGraph.GetY()[i])))
719  upper_list.append(
720  (float(UpperGraph.GetX()[i]), float(UpperGraph.GetY()[i])))
721  lower_list = sorted(set(lower_list))
722  upper_list = sorted(set(upper_list))
723  for i in range(LowerGraph.GetN()):
724  errorBand.SetPoint(i, lower_list[i][0], lower_list[i][1])
725  errorBand.SetPointEYlow(i, lower_list[i][1] - lower_list[i][1])
726  errorBand.SetPointEYhigh(i, upper_list[i][1] - lower_list[i][1])
727  return errorBand
728 
729 
730 def LimitTGraphFromJSON(js, label):
731  xvals = []
732  yvals = []
733  for key in js:
734  xvals.append(float(key))
735  yvals.append(js[key][label])
736  graph = R.TGraph(len(xvals), array('d', xvals), array('d', yvals))
737  graph.Sort()
738  return graph
739 
740 
741 def LimitTGraphFromJSONFile(jsfile, label):
742  with open(jsfile) as jsonfile:
743  js = json.load(jsonfile)
744  return LimitTGraphFromJSON(js, label)
745 
746 def ToyTGraphFromJSON(js, label):
747  xvals = []
748  yvals = []
749  if isinstance(label,(str,)):
750  for entry in js[label]:
751  xvals.append(float(entry))
752  yvals.append(1.0)
753  else:
754  if len(label) == 1:
755  return ToyTGraphFromJSON(js,label[0])
756  else:
757  return ToyTGraphFromJSON(js[label[0]],label[1:])
758  graph = R.TGraph(len(xvals), array('d', xvals), array('d', yvals))
759  graph.Sort()
760  return graph
761  # hist = R.TH1F("toy", "toy", 100, min(xvals), max(xvals))
762  # for xval in xvals:
763  # hist.AddBinContent(hist.GetXaxis().FindBin(xval))
764  # return hist
765 
766 
767 
768 def ToyTGraphFromJSONFile(jsfile, label):
769  with open(jsfile) as jsonfile:
770  js = json.load(jsonfile)
771  return ToyTGraphFromJSON(js, label)
772 
773 def LimitBandTGraphFromJSON(js, central, lo, hi):
774  xvals = []
775  yvals = []
776  yvals_lo = []
777  yvals_hi = []
778  for key in js:
779  xvals.append(float(key))
780  yvals.append(js[key][central])
781  yvals_lo.append(js[key][central] - js[key][lo])
782  yvals_hi.append(js[key][hi] - js[key][central])
783  graph = R.TGraphAsymmErrors(len(xvals), array('d', xvals), array('d', yvals), array(
784  'd', [0]), array('d', [0]), array('d', yvals_lo), array('d', yvals_hi))
785  graph.Sort()
786  return graph
787 
788 
789 def StandardLimitsFromJSONFile(json_file, draw=['obs', 'exp0', 'exp1', 'exp2']):
790  graphs = {}
791  data = {}
792  with open(json_file) as jsonfile:
793  data = json.load(jsonfile)
794  if 'obs' in draw:
795  graphs['obs'] = LimitTGraphFromJSON(data, 'obs')
796  if 'exp0' in draw or 'exp' in draw:
797  graphs['exp0'] = LimitTGraphFromJSON(data, 'exp0')
798  if 'exp1' in draw or 'exp' in draw:
799  graphs['exp1'] = LimitBandTGraphFromJSON(data, 'exp0', 'exp-1', 'exp+1')
800  if 'exp2' in draw or 'exp' in draw:
801  graphs['exp2'] = LimitBandTGraphFromJSON(data, 'exp0', 'exp-2', 'exp+2')
802  return graphs
803 
804 
805 def bestFit(tree, x, y, cut):
806  nfind = tree.Draw(y + ":" + x, cut + "deltaNLL == 0")
807  gr0 = R.TGraph(1)
808  if (nfind == 0):
809  gr0.SetPoint(0, -999, -999)
810  else:
811  grc = R.gROOT.FindObject("Graph").Clone()
812  if (grc.GetN() > 1):
813  grc.Set(1)
814  gr0.SetPoint(0, grc.GetXmax(), grc.GetYmax())
815  gr0.SetMarkerStyle(34)
816  gr0.SetMarkerSize(2.0)
817  return gr0
818 
819 
820 def treeToHist2D(t, x, y, name, cut, xmin, xmax, ymin, ymax, xbins, ybins):
821  t.Draw("2*deltaNLL:%s:%s>>%s_prof(%d,%10g,%10g,%d,%10g,%10g)" %
822  (y, x, name, xbins, xmin, xmax, ybins, ymin, ymax), cut + "deltaNLL != 0", "PROF")
823  prof = R.gROOT.FindObject(name + "_prof")
824  h2d = R.TH2D(name, name, xbins, xmin, xmax, ybins, ymin, ymax)
825  for ix in range(1, xbins + 1):
826  for iy in range(1, ybins + 1):
827  z = prof.GetBinContent(ix, iy)
828  if (z != z) or (z > 4294967295): # protect against NANs
829  z = 0
830  h2d.SetBinContent(ix, iy, z)
831  h2d.GetXaxis().SetTitle(x)
832  h2d.GetYaxis().SetTitle(y)
833  h2d.SetDirectory(0)
834  h2d = NewInterpolate(h2d)
835  return h2d
836 
837 
838 def makeHist1D(name, xbins, graph, scaleXrange=1.0, absoluteXrange=None):
839  len_x = graph.GetX()[graph.GetN() - 1] - graph.GetX()[0]
840  binw_x = (len_x * 0.5 / (float(xbins) - 1.)) - 1E-5
841  if absoluteXrange:
842  hist = R.TH1F(name, '', xbins, absoluteXrange[0], absoluteXrange[1])
843  else:
844  hist = R.TH1F(
845  name, '', xbins, graph.GetX()[0], scaleXrange * (graph.GetX()[graph.GetN() - 1] + binw_x))
846  return hist
847 
848 
849 def makeHist2D(name, xbins, ybins, graph2d):
850  len_x = graph2d.GetXmax() - graph2d.GetXmin()
851  binw_x = (len_x * 0.5 / (float(xbins) - 1.)) - 1E-5
852  len_y = graph2d.GetYmax() - graph2d.GetYmin()
853  binw_y = (len_y * 0.5 / (float(ybins) - 1.)) - 1E-5
854  hist = R.TH2F(name, '', xbins, graph2d.GetXmin() - binw_x, graph2d.GetXmax() +
855  binw_x, ybins, graph2d.GetYmin() - binw_y, graph2d.GetYmax() + binw_y)
856  return hist
857 
858 
859 def makeVarBinHist2D(name, xbins, ybins):
860  # create new arrays in which bin low edge is adjusted to make measured
861  # points at the bin centres
862  xbins_new = [None] * (len(xbins) + 1)
863  for i in range(len(xbins) - 1):
864  if i == 0 or i == 1:
865  xbins_new[i] = xbins[i] - ((xbins[i + 1] - xbins[i]) / 2) + 1E-5
866  else:
867  xbins_new[i] = xbins[i] - ((xbins[i + 1] - xbins[i]) / 2)
868  xbins_new[len(xbins) - 1] = xbins[len(xbins) - 2] + \
869  ((xbins[len(xbins) - 2] - xbins[len(xbins) - 3]) / 2)
870  xbins_new[len(xbins)] = xbins[len(xbins) - 1] + \
871  ((xbins[len(xbins) - 1] - xbins[len(xbins) - 2]) / 2) - 1E-5
872 
873  ybins_new = [None] * (len(ybins) + 1)
874  for i in range(len(ybins) - 1):
875  if i == 0 or i == 1:
876  ybins_new[i] = ybins[i] - ((ybins[i + 1] - ybins[i]) / 2) + 1E-5
877  else:
878  ybins_new[i] = ybins[i] - ((ybins[i + 1] - ybins[i]) / 2)
879  ybins_new[len(ybins) - 1] = ybins[len(ybins) - 2] + \
880  ((ybins[len(ybins) - 2] - ybins[len(ybins) - 3]) / 2)
881  ybins_new[len(ybins)] = ybins[len(ybins) - 1] + \
882  ((ybins[len(ybins) - 1] - ybins[len(ybins) - 2]) / 2) - 1E-5
883  hist = R.TH2F(name, '', len(
884  xbins_new) - 1, array('d', xbins_new), len(ybins_new) - 1, array('d', ybins_new))
885  return hist
886 
887 
888 def GraphDifference(graph1,graph2,relative):
889  xvals =[]
890  yvals =[]
891  if graph1.GetN() != graph2.GetN():
892  return graph1
893  for i in range(graph1.GetN()):
894  xvals.append(graph1.GetX()[i])
895  if relative :
896  yvals.append(2*abs(graph1.GetY()[i]-graph2.GetY()[i])/(graph1.GetY()[i]+graph2.GetY()[i]))
897  else:
898  yvals.append(2*(graph1.GetY()[i]-graph2.GetY()[i])/(graph1.GetY()[i]+graph2.GetY()[i]))
899  diff_graph = R.TGraph(len(xvals),array('d',xvals),array('d',yvals))
900  diff_graph.Sort()
901  return diff_graph
902 
903 
904 def GraphDivide(num, den):
905  res = num.Clone()
906  for i in range(num.GetN()):
907  res.GetY()[i] = res.GetY()[i]/den.Eval(res.GetX()[i])
908  if type(res) is R.TGraphAsymmErrors:
909  for i in range(num.GetN()):
910  res.GetEYhigh()[i] = res.GetEYhigh()[i]/den.Eval(res.GetX()[i])
911  res.GetEYlow()[i] = res.GetEYlow()[i]/den.Eval(res.GetX()[i])
912 
913  return res
914 
915 
916 def MakeRatioHist(num, den, num_err, den_err):
917  """Make a new ratio TH1 from numerator and denominator TH1s with optional
918  error propagation
919 
920  Args:
921  num (TH1): Numerator histogram
922  den (TH1): Denominator histogram
923  num_err (bool): Propagate the error in the numerator TH1
924  den_err (bool): Propagate the error in the denominator TH1
925 
926  Returns:
927  TH1: A new TH1 containing the ratio
928  """
929  result = num.Clone()
930  if not num_err:
931  for i in range(1, result.GetNbinsX()+1):
932  result.SetBinError(i, 0.)
933  den_fix = den.Clone()
934  if not den_err:
935  for i in range(1, den_fix.GetNbinsX()+1):
936  den_fix.SetBinError(i, 0.)
937  result.Divide(den_fix)
938  return result
939 
940 
941 
942 
948  i = 0
949  while i < graph.GetN() - 1:
950  if graph.GetX()[i + 1] == graph.GetX()[i]:
951  # print 'Removing duplicate point (%f, %f)' % (graph.GetX()[i+1], graph.GetY()[i+1])
952  graph.RemovePoint(i + 1)
953  else:
954  i += 1
955 
956 
957 def ApplyGraphYOffset(graph, y_off):
958  for i in range(graph.GetN() - 1):
959  graph.GetY()[i] = graph.GetY()[i] + y_off
960 
961 
962 def RemoveGraphYAll(graph, val):
963  for i in range(graph.GetN()):
964  if graph.GetY()[i] == val:
965  print('[RemoveGraphYAll] Removing point (%f, %f)' % (graph.GetX()[i], graph.GetY()[i]))
966  graph.RemovePoint(i)
967  RemoveGraphYAll(graph, val)
968  break
969 
970 
971 def RemoveSmallDelta(graph, val):
972  for i in range(graph.GetN()):
973  diff = abs(graph.GetY()[i])
974  if diff < val:
975  print('[RemoveSmallDelta] Removing point (%f, %f)' % (graph.GetX()[i], graph.GetY()[i]))
976  graph.RemovePoint(i)
977  RemoveSmallDelta(graph, val)
978  break
979 
980 
981 def RemoveGraphYAbove(graph, val):
982  for i in range(graph.GetN()):
983  if graph.GetY()[i] > val:
984  # print 'Removing point (%f, %f)' % (graph.GetX()[i],
985  # graph.GetY()[i])
986  graph.RemovePoint(i)
987  RemoveGraphYAbove(graph, val)
988  break
989 
990 
991 def SetMinToZero(graph):
992  min = 999.
993  minNum = -1
994  for i in range(graph.GetN()):
995  if graph.GetY()[i] < min :
996  min = graph.GetY()[i]
997  minNum = i
998  for i in range(graph.GetN()):
999  graph.SetPoint(i, graph.GetX()[i], graph.GetY()[i]-min)
1000 
1001 
1002 
1003 def ImproveMinimum(graph, func, doIt=False):
1004  fit_x = 0.
1005  fit_y = 999.
1006  fit_i = 0
1007  for i in range(graph.GetN()):
1008  if graph.GetY()[i] < fit_y:
1009  fit_i = i
1010  fit_x = graph.GetX()[i]
1011  fit_y = graph.GetY()[i]
1012  if fit_i == 0 or fit_i == (graph.GetN() - 1):
1013  if doIt:
1014  min_x = graph.GetX()[fit_i]
1015  min_y = graph.GetY()[fit_i]
1016  for i in range(graph.GetN()):
1017  before = graph.GetY()[i]
1018  graph.GetY()[i] -= min_y
1019  after = graph.GetY()[i]
1020  print('Point %i, before=%f, after=%f' % (i, before, after))
1021  return (fit_x, fit_y)
1022  search_min = fit_i - 2 if fit_i >= 2 else fit_i - 1
1023  search_max = fit_i + 2 if fit_i + 2 < graph.GetN() else fit_i + 1
1024  min_x = func.GetMinimumX(graph.GetX()[search_min], graph.GetX()[search_max])
1025  min_y = func.Eval(min_x)
1026  print('[ImproveMinimum] Fit minimum was (%f, %f)' % (fit_x, fit_y))
1027  print('[ImproveMinimum] Better minimum was (%f, %f)' % (min_x, min_y))
1028  if doIt:
1029  for i in range(graph.GetN()):
1030  before = graph.GetY()[i]
1031  graph.GetY()[i] -= min_y
1032  after = graph.GetY()[i]
1033  print('Point %i, before=%f, after=%f' % (i, before, after))
1034  graph.Set(graph.GetN() + 1)
1035  graph.SetPoint(graph.GetN() - 1, min_x, 0)
1036  graph.Sort()
1037  return (min_x, min_y)
1038 
1039 
1040 def FindCrossingsWithSpline(graph, func, yval):
1041  crossings = []
1042  intervals = []
1043  current = None
1044  for i in range(graph.GetN() - 1):
1045  if (graph.GetY()[i] - yval) * (graph.GetY()[i + 1] - yval) < 0.:
1046  cross = func.GetX(yval, graph.GetX()[i], graph.GetX()[i + 1])
1047  if (graph.GetY()[i] - yval) > 0. and current is None:
1048  current = {
1049  'lo': cross,
1050  'hi': graph.GetX()[graph.GetN() - 1],
1051  'valid_lo': True,
1052  'valid_hi': False
1053  }
1054  if (graph.GetY()[i] - yval) < 0. and current is None:
1055  current = {
1056  'lo': graph.GetX()[0],
1057  'hi': cross,
1058  'valid_lo': False,
1059  'valid_hi': True
1060  }
1061  intervals.append(current)
1062  current = None
1063  if (graph.GetY()[i] - yval) < 0. and current is not None:
1064  current['hi'] = cross
1065  current['valid_hi'] = True
1066  intervals.append(current)
1067  current = None
1068  # print 'Crossing between: (%f, %f) -> (%f, %f) at %f' %
1069  # (graph.GetX()[i], graph.GetY()[i], graph.GetX()[i+1],
1070  # graph.GetY()[i+1], cross)
1071  crossings.append(cross)
1072  if current is not None:
1073  intervals.append(current)
1074  if len(intervals) == 0:
1075  current = {
1076  'lo': graph.GetX()[0],
1077  'hi': graph.GetX()[graph.GetN() - 1],
1078  'valid_lo': False,
1079  'valid_hi': False
1080  }
1081  intervals.append(current)
1082  print(intervals)
1083  return intervals
1084  # return crossings
1085 
1086 
1087 def ReZeroTGraph(gr, doIt=False):
1088  fit_x = 0.
1089  fit_y = 0.
1090  for i in range(gr.GetN()):
1091  if gr.GetY()[i] == 0.:
1092  fit_x = gr.GetX()[i]
1093  fit_y = gr.GetY()[i]
1094  break
1095  min_x = 0.
1096  min_y = 0.
1097  for i in range(gr.GetN()):
1098  if gr.GetY()[i] < min_y:
1099  min_y = gr.GetY()[i]
1100  min_x = gr.GetX()[i]
1101  if min_y < fit_y:
1102  print('[ReZeroTGraph] Fit minimum was (%f, %f)' % (fit_x, fit_y))
1103  print('[ReZeroTGraph] Better minimum was (%f, %f)' % (min_x, min_y))
1104  if doIt:
1105  for i in range(gr.GetN()):
1106  before = gr.GetY()[i]
1107  gr.GetY()[i] -= min_y
1108  after = gr.GetY()[i]
1109  # print 'Point %i, before=%f, after=%f' % (i, before, after)
1110  return min_y
1111 
1112 def FilterGraph(gr, n=3):
1113  counter = 0
1114  remove_list = []
1115  for i in range(gr.GetN()):
1116  if gr.GetY()[i] == 0.:
1117  continue
1118  if counter % n < (n - 1):
1119  remove_list.append(i)
1120  counter += 1
1121 
1122  for i in reversed(remove_list):
1123  gr.RemovePoint(i)
1124 
1125 
1126 def RemoveInXRange(gr, xmin=0, xmax=1):
1127  remove_list = []
1128  for i in range(gr.GetN()):
1129  if gr.GetY()[i] == 0.:
1130  continue
1131  if gr.GetX()[i] > xmin and gr.GetX()[i] < xmax:
1132  remove_list.append(i)
1133 
1134  for i in reversed(remove_list):
1135  gr.RemovePoint(i)
1136 
1137 
1138 def RemoveNearMin(graph, val, spacing=None):
1139  # assume graph is sorted:
1140  n = graph.GetN()
1141  if n < 5:
1142  return
1143  if spacing is None:
1144  spacing = (graph.GetX()[n - 1] - graph.GetX()[0]) / float(n - 2)
1145  # print '[RemoveNearMin] Graph has spacing of %.3f' % spacing
1146  bf_i = None
1147  for i in range(graph.GetN()):
1148  if graph.GetY()[i] == 0.:
1149  bf = graph.GetX()[i]
1150  bf_i = i
1151  # print '[RemoveNearMin] Found best-fit at %.3f' % bf
1152  break
1153  if bf_i is None:
1154  print('[RemoveNearMin] No minimum found!')
1155  return
1156  for i in range(graph.GetN()):
1157  if i == bf_i:
1158  continue
1159  if abs(graph.GetX()[i] - bf) < (val * spacing):
1160  print('[RemoveNearMin] Removing point (%f, %f) close to minimum at %f' % (graph.GetX()[i], graph.GetY()[i], bf))
1161  graph.RemovePoint(i)
1162  RemoveNearMin(graph, val, spacing)
1163  break
1164 
1165 
1166 def SortGraph(Graph):
1167  sortedGraph = R.TGraph()
1168  graph_list = []
1169  for i in range(Graph.GetN()):
1170  graph_list.append((float(Graph.GetX()[i]), float(Graph.GetY()[i])))
1171  graph_list = sorted(set(graph_list))
1172  for i in range(Graph.GetN()):
1173  sortedGraph.SetPoint(i, graph_list[i][0], graph_list[i][1])
1174  return sortedGraph
1175 
1176 
1177 
1178 
1179 
1180 
1186 def FixTopRange(pad, fix_y, fraction):
1187  hobj = GetAxisHist(pad)
1188  ymin = hobj.GetMinimum()
1189  hobj.SetMaximum((fix_y - fraction * ymin) / (1. - fraction))
1190  if R.gPad.GetLogy():
1191  if ymin == 0.:
1192  print('Cannot adjust log-scale y-axis range if the minimum is zero!')
1193  return
1194  maxval = (math.log10(fix_y) - fraction * math.log10(ymin)) / \
1195  (1 - fraction)
1196  maxval = math.pow(10, maxval)
1197  hobj.SetMaximum(maxval)
1198 
1199 
1200 def FixBothRanges(pad, fix_y_lo, frac_lo, fix_y_hi, frac_hi):
1201  """Adjusts y-axis range such that a lower and a higher value are located a
1202  fixed fraction of the frame height away from a new minimum and maximum
1203  respectively.
1204 
1205  This function is useful in conjunction with GetPadYMax which returns the
1206  maximum or minimum y value of all histograms and graphs drawn on the pad.
1207 
1208  In the example below, the minimum and maximum values found via this function
1209  are used as the `fix_y_lo` and `fix_y_hi` arguments, and the spacing fractions
1210  as 0.15 and 0.30 respectively.
1211 
1212  @code
1213  FixBothRanges(pad, GetPadYMin(pad), 0.15, GetPadYMax(pad), 0.30)
1214  @endcode
1215 
1216  ![](figures/FixBothRanges.png)
1217 
1218  Args:
1219  pad (TPad): A TPad on which histograms and graphs have already been drawn
1220  fix_y_lo (float): The y value which will end up a fraction `frac_lo` above
1221  the new axis minimum.
1222  frac_lo (float): A fraction of the y-axis height
1223  fix_y_hi (float): The y value which will end up a fraction `frac_hi` below
1224  from the new axis maximum.
1225  frac_hi (float): A fraction of the y-axis height
1226  """
1227  hobj = GetAxisHist(pad)
1228  ymin = fix_y_lo
1229  ymax = fix_y_hi
1230  if R.gPad.GetLogy():
1231  if ymin == 0.:
1232  print('Cannot adjust log-scale y-axis range if the minimum is zero!')
1233  return
1234  ymin = math.log10(ymin)
1235  ymax = math.log10(ymax)
1236  fl = frac_lo
1237  fh = frac_hi
1238 
1239  ymaxn = (
1240  (1. / (1. - (fh*fl/((1.-fl)*(1.-fh))))) *
1241  (1. / (1. - fh)) *
1242  (ymax - fh*ymin)
1243  )
1244  yminn = (ymin - fl*ymaxn) / (1. - fl)
1245  if R.gPad.GetLogy():
1246  yminn = math.pow(10, yminn)
1247  ymaxn = math.pow(10, ymaxn)
1248  hobj.SetMinimum(yminn)
1249  hobj.SetMaximum(ymaxn)
1250 
1251 
1252 def GetPadYMaxInRange(pad, x_min, x_max, do_min=False):
1253  pad_obs = pad.GetListOfPrimitives()
1254  if pad_obs is None:
1255  return 0.
1256  h_max = -99999.
1257  h_min = +99999.
1258  for obj in pad_obs:
1259  if obj.InheritsFrom(R.TH1.Class()):
1260  hobj = obj
1261  for j in range(1, hobj.GetNbinsX()+1):
1262  if (hobj.GetBinLowEdge(j) + hobj.GetBinWidth(j) < x_min or
1263  hobj.GetBinLowEdge(j) > x_max):
1264  continue
1265  if (hobj.GetBinContent(j) + hobj.GetBinError(j) > h_max):
1266  h_max = hobj.GetBinContent(j) + hobj.GetBinError(j)
1267  if (hobj.GetBinContent(j) - hobj.GetBinError(j) < h_min) and not do_min:
1268  # If we're looking for the minimum don't count TH1s
1269  # because we probably only care about graphs
1270  h_min = hobj.GetBinContent(j) - hobj.GetBinError(j)
1271  elif obj.InheritsFrom(R.TGraphAsymmErrors.Class()):
1272  gobj = obj
1273  n = gobj.GetN()
1274  for k in range(0, n):
1275  x = gobj.GetX()[k]
1276  y = gobj.GetY()[k]
1277  if x < x_min or x > x_max:
1278  continue
1279  if (y + gobj.GetEYhigh()[k]) > h_max:
1280  h_max = y + gobj.GetEYhigh()[k]
1281  if (y - gobj.GetEYlow()[k]) < h_min:
1282  h_min = y - gobj.GetEYlow()[k]
1283  elif obj.InheritsFrom(R.TGraphErrors.Class()):
1284  gobj = obj
1285  n = gobj.GetN()
1286  for k in range(0, n):
1287  x = gobj.GetX()[k]
1288  y = gobj.GetY()[k]
1289  if x < x_min or x > x_max:
1290  continue
1291  if (y + gobj.GetEY()[k]) > h_max:
1292  h_max = y + gobj.GetEY()[k]
1293  if (y - gobj.GetEY()[k]) < h_min:
1294  h_min = y - gobj.GetEY()[k]
1295  elif obj.InheritsFrom(R.TGraph.Class()):
1296  gobj = obj
1297  n = gobj.GetN()
1298  for k in range(0, n):
1299  x = gobj.GetX()[k]
1300  y = gobj.GetY()[k]
1301  if x < x_min or x > x_max:
1302  continue
1303  if y > h_max:
1304  h_max = y
1305  if y < h_min:
1306  h_min = y
1307  return h_max if do_min is False else h_min
1308 
1309 
1310 def GetPadYMax(pad, do_min=False):
1311  pad_obs = pad.GetListOfPrimitives()
1312  if pad_obs is None:
1313  return 0.
1314  xmin = GetAxisHist(pad).GetXaxis().GetXmin()
1315  xmax = GetAxisHist(pad).GetXaxis().GetXmax()
1316  return GetPadYMaxInRange(pad, xmin, xmax, do_min)
1317 
1318 
1319 def GetPadYMin(pad):
1320  return GetPadYMax(pad, True)
1321 
1322 
1324  R.gPad.GetFrame().Draw()
1325  R.gPad.RedrawAxis()
1326 
1327 
1328 def FixBoxPadding(pad, box, frac):
1329  # Get the bounds of the box - these are in the normalised
1330  # Pad co-ordinates.
1331  p_x1 = box.GetX1()
1332  p_x2 = box.GetX2()
1333  p_y1 = box.GetY1()
1334 
1335  #Convert to normalised co-ordinates in the frame
1336  f_x1 = (p_x1 - pad.GetLeftMargin()) / (1. - pad.GetLeftMargin() - pad.GetRightMargin())
1337  f_x2 = (p_x2 - pad.GetLeftMargin()) / (1. - pad.GetLeftMargin() - pad.GetRightMargin())
1338  f_y1 = (p_y1 - pad.GetBottomMargin()) / (1. - pad.GetTopMargin() - pad.GetBottomMargin())
1339 
1340  # Extract histogram providing the frame and axes
1341  hobj = GetAxisHist(pad)
1342 
1343  xmin = hobj.GetBinLowEdge(hobj.GetXaxis().GetFirst())
1344  xmax = hobj.GetBinLowEdge(hobj.GetXaxis().GetLast()+1)
1345  ymin = hobj.GetMinimum()
1346  ymax = hobj.GetMaximum()
1347 
1348  # Convert box bounds to x-axis values
1349  a_x1 = xmin + (xmax - xmin) * f_x1
1350  a_x2 = xmin + (xmax - xmin) * f_x2
1351 
1352  # Get the histogram maximum in this range, given as y-axis value
1353  a_max_h = GetPadYMaxInRange(pad, a_x1, a_x2)
1354 
1355  # Convert this to a normalised frame value
1356  f_max_h = (a_max_h - ymin) / (ymax - ymin);
1357  if R.gPad.GetLogy() and f_max_h > 0.:
1358  f_max_h = (math.log10(a_max_h) - math.log10(ymin)) / (math.log10(ymax) - math.log10(ymin))
1359 
1360  if f_y1 - f_max_h < frac:
1361  f_target = 1. - (f_y1 - frac)
1362  FixTopRange(pad, a_max_h, f_target)
1363 
1364 
1365 
1366 
1370 
1371 
1372 def StandardAxes(xaxis, yaxis, var, units):
1373  width = xaxis.GetBinWidth(1)
1374  w_label = "%.1f" % width
1375  if units == "":
1376  xaxis.SetTitle(var)
1377  yaxis.SetTitle("Events / " + w_label)
1378  else:
1379  xaxis.SetTitle(var + " (" + units + ")")
1380  yaxis.SetTitle("Events / " + w_label + " " + units)
1381 
1382 
1383 def DrawCMSLogo(pad, cmsText, extraText, iPosX, relPosX, relPosY, relExtraDY, extraText2='', cmsTextSize=0.8):
1384  """Blah
1385 
1386  Args:
1387  pad (TYPE): Description
1388  cmsText (TYPE): Description
1389  extraText (TYPE): Description
1390  iPosX (TYPE): Description
1391  relPosX (TYPE): Description
1392  relPosY (TYPE): Description
1393  relExtraDY (TYPE): Description
1394  extraText2 (str): Description
1395  cmsTextSize (float): Description
1396 
1397  Returns:
1398  TYPE: Description
1399  """
1400  pad.cd()
1401  cmsTextFont = 62 # default is helvetic-bold
1402 
1403  writeExtraText = len(extraText) > 0
1404  writeExtraText2 = len(extraText2) > 0
1405  extraTextFont = 52
1406 
1407  # text sizes and text offsets with respect to the top frame
1408  # in unit of the top margin size
1409  lumiTextOffset = 0.2
1410  # cmsTextSize = 0.8
1411  # float cmsTextOffset = 0.1; // only used in outOfFrame version
1412 
1413  # ratio of 'CMS' and extra text size
1414  extraOverCmsTextSize = 0.76
1415 
1416  outOfFrame = False
1417  if iPosX / 10 == 0:
1418  outOfFrame = True
1419 
1420  alignY_ = 3
1421  alignX_ = 2
1422  if (iPosX / 10 == 0):
1423  alignX_ = 1
1424  if (iPosX == 0):
1425  alignX_ = 1
1426  if (iPosX == 0):
1427  alignY_ = 1
1428  if (iPosX / 10 == 1):
1429  alignX_ = 1
1430  if (iPosX / 10 == 2):
1431  alignX_ = 2
1432  if (iPosX / 10 == 3):
1433  alignX_ = 3
1434  # if (iPosX == 0): relPosX = 0.14
1435  align_ = 10 * alignX_ + alignY_
1436 
1437  l = pad.GetLeftMargin()
1438  t = pad.GetTopMargin()
1439  r = pad.GetRightMargin()
1440  b = pad.GetBottomMargin()
1441 
1442  latex = R.TLatex()
1443  latex.SetNDC()
1444  latex.SetTextAngle(0)
1445  latex.SetTextColor(R.kBlack)
1446 
1447  extraTextSize = extraOverCmsTextSize * cmsTextSize
1448  pad_ratio = (float(pad.GetWh()) * pad.GetAbsHNDC()) / \
1449  (float(pad.GetWw()) * pad.GetAbsWNDC())
1450  if (pad_ratio < 1.):
1451  pad_ratio = 1.
1452 
1453  if outOfFrame:
1454  latex.SetTextFont(cmsTextFont)
1455  latex.SetTextAlign(11)
1456  latex.SetTextSize(cmsTextSize * t * (1./pad_ratio))
1457  latex.DrawLatex(l, 1 - t + lumiTextOffset * t, cmsText)
1458 
1459  posX_ = 0
1460  if iPosX % 10 <= 1:
1461  posX_ = l + relPosX * (1 - l - r)
1462  elif (iPosX % 10 == 2):
1463  posX_ = l + 0.5 * (1 - l - r)
1464  elif (iPosX % 10 == 3):
1465  posX_ = 1 - r - relPosX * (1 - l - r)
1466 
1467  posY_ = 1 - t - relPosY * (1 - t - b)
1468  if not outOfFrame:
1469  latex.SetTextFont(cmsTextFont)
1470  latex.SetTextSize(cmsTextSize * t * pad_ratio)
1471  latex.SetTextAlign(align_)
1472  latex.DrawLatex(posX_, posY_, cmsText)
1473  if writeExtraText:
1474  latex.SetTextFont(extraTextFont)
1475  latex.SetTextAlign(align_)
1476  latex.SetTextSize(extraTextSize * t * pad_ratio)
1477  latex.DrawLatex(
1478  posX_, posY_ - relExtraDY * cmsTextSize * t, extraText)
1479  if writeExtraText2:
1480  latex.DrawLatex(
1481  posX_, posY_ - 1.8 * relExtraDY * cmsTextSize * t, extraText2)
1482  elif writeExtraText:
1483  if iPosX == 0:
1484  posX_ = l + relPosX * (1 - l - r)
1485  posY_ = 1 - t + lumiTextOffset * t
1486  latex.SetTextFont(extraTextFont)
1487  latex.SetTextSize(extraTextSize * t * (1./pad_ratio))
1488  latex.SetTextAlign(align_)
1489  latex.DrawLatex(posX_, posY_, extraText)
1490 
1491 
1492 def PositionedLegend(width, height, pos, offset, horizontaloffset=None):
1493  o = offset
1494  ho = horizontaloffset
1495  if not ho:
1496  ho = o
1497  w = width
1498  h = height
1499  l = R.gPad.GetLeftMargin()
1500  t = R.gPad.GetTopMargin()
1501  b = R.gPad.GetBottomMargin()
1502  r = R.gPad.GetRightMargin()
1503  if pos == 1:
1504  return R.TLegend(l + ho, 1 - t - o - h, l + ho + w, 1 - t - o, '', 'NBNDC')
1505  if pos == 2:
1506  c = l + 0.5 * (1 - l - r)
1507  return R.TLegend(c - 0.5 * w, 1 - t - o - h, c + 0.5 * w, 1 - t - o, '', 'NBNDC')
1508  if pos == 3:
1509  return R.TLegend(1 - r - ho - w, 1 - t - o - h, 1 - r - ho, 1 - t - o, '', 'NBNDC')
1510  if pos == 4:
1511  return R.TLegend(l + ho, b + o, l + ho + w, b + o + h, '', 'NBNDC')
1512  if pos == 5:
1513  c = l + 0.5 * (1 - l - r)
1514  return R.TLegend(c - 0.5 * w, b + o, c + 0.5 * w, b + o + h, '', 'NBNDC')
1515  if pos == 6:
1516  return R.TLegend(1 - r - ho - w, b + o, 1 - r - ho, b + o + h, '', 'NBNDC')
1517 
1518 
1519 def DrawHorizontalLine(pad, line, yval):
1520  axis = GetAxisHist(pad)
1521  xmin = axis.GetXaxis().GetXmin()
1522  xmax = axis.GetXaxis().GetXmax()
1523  line.DrawLine(xmin, yval, xmax, yval)
1524 
1525 
1526 def DrawVerticalLine(pad, line, xval):
1527  axis = GetAxisHist(pad)
1528  ymin = axis.GetYaxis().GetXmin()
1529  ymax = axis.GetYaxis().GetXmax()
1530  line.DrawLine(xval, ymin, xval, ymax)
1531 
1532 def DrawVerticalBand(pad, box, x1, x2):
1533  axis = GetAxisHist(pad)
1534  ymin = axis.GetYaxis().GetXmin()
1535  ymax = axis.GetYaxis().GetXmax()
1536  box.DrawBox(x1, ymin, x2, ymax)
1537 
1538 
1539 def DrawTitle(pad, text, align, textOffset=0.2,textSize=0.6):
1540  pad_backup = R.gPad
1541  pad.cd()
1542  t = pad.GetTopMargin()
1543  l = pad.GetLeftMargin()
1544  r = pad.GetRightMargin()
1545 
1546  pad_ratio = (float(pad.GetWh()) * pad.GetAbsHNDC()) / \
1547  (float(pad.GetWw()) * pad.GetAbsWNDC())
1548  if pad_ratio < 1.:
1549  pad_ratio = 1.
1550 
1551  latex = R.TLatex()
1552  latex.SetNDC()
1553  latex.SetTextAngle(0)
1554  latex.SetTextColor(R.kBlack)
1555  latex.SetTextFont(42)
1556  latex.SetTextSize(textSize * t * pad_ratio)
1557 
1558  y_off = 1 - t + textOffset * t
1559  if align == 1:
1560  latex.SetTextAlign(11)
1561  if align == 1:
1562  latex.DrawLatex(l, y_off, text)
1563  if align == 2:
1564  latex.SetTextAlign(21)
1565  if align == 2:
1566  latex.DrawLatex(l + (1 - l - r) * 0.5, y_off, text)
1567  if align == 3:
1568  latex.SetTextAlign(31)
1569  if align == 3:
1570  latex.DrawLatex(1 - r, y_off, text)
1571  pad_backup.cd()
1572 
1573 
1574 
1575 
1576 
1582 
1583 def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
1584  return abs(a-b) <= max(abs_tol, rel_tol * max(abs(a),abs(b)))
1585 
1586 def StyleLimitBand(graph_dict, overwrite_style_dict=None):
1587  style_dict = {
1588  'obs' : { 'LineWidth' : 2},
1589  'exp0' : { 'LineWidth' : 2, 'LineColor' : R.kRed},
1590  'exp1' : { 'FillColor' : R.kGreen},
1591  'exp2' : { 'FillColor' : R.kYellow}
1592  }
1593  if overwrite_style_dict is not None:
1594  for key in overwrite_style_dict:
1595  if key in style_dict:
1596  style_dict[key].update(overwrite_style_dict[key])
1597  else:
1598  style_dict[key] = overwrite_style_dict[key]
1599  for key in graph_dict:
1600  Set(graph_dict[key],**style_dict[key])
1601 
1602 def DrawLimitBand(pad, graph_dict, draw=['exp2', 'exp1', 'exp0', 'obs'], draw_legend=None,
1603  legend=None, legend_overwrite=None):
1604  legend_dict = {
1605  'obs' : { 'Label' : 'Observed', 'LegendStyle' : 'LP', 'DrawStyle' : 'PLSAME'},
1606  'exp0' : { 'Label' : 'Expected', 'LegendStyle' : 'L', 'DrawStyle' : 'LSAME'},
1607  'exp1' : { 'Label' : '#pm1#sigma Expected', 'LegendStyle' : 'F', 'DrawStyle' : '3SAME'},
1608  'exp2' : { 'Label' : '#pm2#sigma Expected', 'LegendStyle' : 'F', 'DrawStyle' : '3SAME'}
1609  }
1610  if legend_overwrite is not None:
1611  for key in legend_overwrite:
1612  if key in legend_dict:
1613  legend_dict[key].update(legend_overwrite[key])
1614  else:
1615  legend_dict[key] = legend_overwrite[key]
1616  pad.cd()
1617  for key in draw:
1618  if key in graph_dict:
1619  graph_dict[key].Draw(legend_dict[key]['DrawStyle'])
1620  if legend is not None:
1621  if draw_legend is None:
1622  draw_legend = reversed(draw)
1623  for key in draw_legend:
1624  if key in graph_dict:
1625  legend.AddEntry(graph_dict[key],legend_dict[key]['Label'],legend_dict[key]['LegendStyle'])
1626 
1627 
1628 
1629 
1630 
1631 
1632 
1636 def contourFromTH2(h2in, threshold, minPoints=10, frameValue=1000.):
1637  # // http://root.cern.ch/root/html/tutorials/hist/ContourList.C.html
1638  contoursList = [threshold]
1639  contours = array('d', contoursList)
1640  # if (h2in.GetNbinsX() * h2in.GetNbinsY()) > 10000: minPoints = 50
1641  # if (h2in.GetNbinsX() * h2in.GetNbinsY()) <= 100: minPoints = 10
1642 
1643  h2 = frameTH2D(h2in, threshold, frameValue)
1644 
1645  h2.SetContour(1, contours)
1646 
1647  # Draw contours as filled regions, and Save points
1648  # backup = R.gPad # doesn't work in pyroot, backup behaves like a ref to gPad
1649  canv = R.TCanvas('tmp', 'tmp')
1650  canv.cd()
1651  h2.Draw('CONT Z LIST')
1652  R.gPad.Update() # Needed to force the plotting and retrieve the contours in
1653 
1654  conts = R.gROOT.GetListOfSpecials().FindObject('contours')
1655  contLevel = None
1656 
1657  if conts is None or conts.GetSize() == 0:
1658  print('*** No Contours Were Extracted!')
1659  return None
1660  ret = R.TList()
1661  for i in range(conts.GetSize()):
1662  contLevel = conts.At(i)
1663  print('>> Contour %d has %d Graphs' % (i, contLevel.GetSize()))
1664  for j in range(contLevel.GetSize()):
1665  gr1 = contLevel.At(j)
1666  print('\t Graph %d has %d points' % (j, gr1.GetN()))
1667  if gr1.GetN() > minPoints:
1668  ret.Add(gr1.Clone())
1669  # // break;
1670  # backup.cd()
1671  canv.Close()
1672  return ret
1673 
1674 
1675 def frameTH2D(hist, threshold, frameValue=1000):
1676  # Now supports variable-binned histograms First adds a narrow frame (1% of
1677  # of bin widths) around the outside with same values as the real edge. Then
1678  # adds another frame another frame around this one filled with some chosen
1679  # value that will make the contours close
1680 
1681  # Get lists of the bin edges
1682  x_bins = [hist.GetXaxis().GetBinLowEdge(x)
1683  for x in range(1, hist.GetNbinsX() + 2)]
1684  y_bins = [hist.GetYaxis().GetBinLowEdge(y)
1685  for y in range(1, hist.GetNbinsY() + 2)]
1686 
1687  # New bin edge arrays will need an extra four values
1688  x_new = [0.] * (len(x_bins) + 4)
1689  y_new = [0.] * (len(y_bins) + 4)
1690 
1691  # Calculate bin widths at the edges
1692  xw1 = x_bins[1] - x_bins[0]
1693  xw2 = x_bins[-1] - x_bins[-2]
1694  yw1 = y_bins[1] - y_bins[0]
1695  yw2 = y_bins[-1] - y_bins[-2]
1696 
1697  # Set the edges of the outer framing bins and the adjusted
1698  # edge of the real edge bins
1699  x_new[0] = x_bins[0] - 2 * xw1 * 0.02
1700  x_new[1] = x_bins[0] - 1 * xw1 * 0.02
1701  x_new[-1] = x_bins[-1] + 2 * xw2 * 0.02
1702  x_new[-2] = x_bins[-1] + 1 * xw2 * 0.02
1703  y_new[0] = y_bins[0] - 2 * yw1 * 0.02
1704  y_new[1] = y_bins[0] - 1 * yw1 * 0.02
1705  y_new[-1] = y_bins[-1] + 2 * yw2 * 0.02
1706  y_new[-2] = y_bins[-1] + 1 * yw2 * 0.02
1707 
1708  # Copy the remaining bin edges from the hist
1709  for i in range(0, len(x_bins)):
1710  x_new[i + 2] = x_bins[i]
1711  for i in range(0, len(y_bins)):
1712  y_new[i + 2] = y_bins[i]
1713 
1714  # print x_new
1715  # print y_new
1716 
1717  framed = R.TH2D('%s framed' % hist.GetName(), '%s framed' % hist.GetTitle(), len(
1718  x_new) - 1, array('d', x_new), len(y_new) - 1, array('d', y_new))
1719  framed.SetDirectory(0)
1720 
1721  for x in range(1, framed.GetNbinsX() + 1):
1722  for y in range(1, framed.GetNbinsY() + 1):
1723  if x == 1 or x == framed.GetNbinsX() or y == 1 or y == framed.GetNbinsY():
1724  # This is a a frame bin
1725  framed.SetBinContent(x, y, frameValue)
1726  else:
1727  # adjust x and y if we're in the first frame so as to copy the output
1728  # values from the real TH2
1729  ux = x
1730  uy = y
1731  if x == 2:
1732  ux += 1
1733  elif x == (len(x_new) - 2):
1734  ux -= 1
1735  if y == 2:
1736  uy += 1
1737  elif y == (len(y_new) - 2):
1738  uy -= 1
1739  framed.SetBinContent(x, y, hist.GetBinContent(ux - 2, uy - 2))
1740  return framed
1741 
1742 def fastFillTH2(hist2d, graph, initalValue=99999, interpolateMissing=False):
1743  for x in range(1,hist2d.GetNbinsX()+1):
1744  for y in range(1,hist2d.GetNbinsY()+1):
1745  hist2d.SetBinContent(x,y,initalValue)
1746  # for i in xrange(graph.GetN()):
1747  # hist2d.Fill(graph.GetX()[i],graph.GetY()[i],graph.GetZ()[i])
1748  for i in range(graph.GetN()):
1749  xbin = hist2d.GetXaxis().FindBin(graph.GetX()[i])
1750  ybin = hist2d.GetYaxis().FindBin(graph.GetY()[i])
1751  if isclose(hist2d.GetXaxis().GetBinCenter(xbin), graph.GetX()[i], rel_tol=1e-2) and isclose(hist2d.GetYaxis().GetBinCenter(ybin), graph.GetY()[i], rel_tol=1e-2):
1752  hist2d.SetBinContent(xbin, ybin, graph.GetZ()[i])
1753  interpolated = 0
1754  if interpolateMissing:
1755  for x in range(1,hist2d.GetNbinsX()+1):
1756  for y in range(1,hist2d.GetNbinsY()+1):
1757  if hist2d.GetBinContent(x,y) == initalValue:
1758  interpolated += 1
1759  hist2d.SetBinContent(x, y, graph.Interpolate(hist2d.GetXaxis().GetBinCenter(x),hist2d.GetYaxis().GetBinCenter(y)))
1760 
1761 def fillTH2(hist2d, graph):
1762  for x in range(1, hist2d.GetNbinsX() + 1):
1763  for y in range(1, hist2d.GetNbinsY() + 1):
1764  xc = hist2d.GetXaxis().GetBinCenter(x)
1765  yc = hist2d.GetYaxis().GetBinCenter(y)
1766  val = graph.Interpolate(xc, yc)
1767  hist2d.SetBinContent(x, y, val)
1768 
1769 def fillInvertedTH2(hist2d, graph):
1770  for x in range(1, hist2d.GetNbinsX() + 1):
1771  for y in range(1, hist2d.GetNbinsY() + 1):
1772  xc = hist2d.GetXaxis().GetBinCenter(x)
1773  yc = hist2d.GetYaxis().GetBinCenter(y)
1774  val = graph.Interpolate(xc, yc)
1775  hist2d.SetBinContent(x, y, 1-val)
1776 
1777 
1778 
1779 # Functions 'NewInterpolate' and 'rebin' are taken, translated and modified into python from:
1780 # https://indico.cern.ch/event/256523/contribution/2/attachments/450198/624259/07JUN2013_cawest.pdf
1781 # http://hep.ucsb.edu/people/cawest/interpolation/interpolate.h
1782 def NewInterpolate(hist):
1783  histCopy = hist.Clone()
1784 
1785  # make temporary histograms to store the results of both steps
1786  hist_step1 = histCopy.Clone()
1787  hist_step1.Reset()
1788  hist_step2 = histCopy.Clone()
1789  hist_step2.Reset()
1790 
1791  nBinsX = histCopy.GetNbinsX()
1792  nBinsY = histCopy.GetNbinsY()
1793 
1794  xMin = 1
1795  yMin = 1
1796  xMax = histCopy.GetNbinsX() + 1
1797  yMax = histCopy.GetNbinsY() + 1
1798 
1799  for i in range(1, nBinsX + 1):
1800  for j in range(1, nBinsY + 1):
1801  # do not extrapolate outside the scan
1802  if (i < xMin) or (i > xMax) or (j < yMin) or (j > yMax):
1803  continue
1804  binContent = histCopy.GetBinContent(i, j)
1805  binContentNW = histCopy.GetBinContent(i + 1, j + 1)
1806  binContentSE = histCopy.GetBinContent(i - 1, j - 1)
1807  binContentNE = histCopy.GetBinContent(i + 1, j - 1)
1808  binContentSW = histCopy.GetBinContent(i - 1, j + 1)
1809  binContentUp = histCopy.GetBinContent(i, j + 1)
1810  binContentDown = histCopy.GetBinContent(i, j - 1)
1811  binContentLeft = histCopy.GetBinContent(i - 1, j)
1812  binContentRight = histCopy.GetBinContent(i + 1, j)
1813  nFilled = 0
1814  if(binContentNW > 0):
1815  nFilled += 1
1816  if(binContentSE > 0):
1817  nFilled += 1
1818  if(binContentNE > 0):
1819  nFilled += 1
1820  if(binContentSW > 0):
1821  nFilled += 1
1822  if(binContentUp > 0):
1823  nFilled += 1
1824  if(binContentDown > 0):
1825  nFilled += 1
1826  if(binContentRight > 0):
1827  nFilled += 1
1828  if(binContentLeft > 0):
1829  nFilled += 1
1830  # if we are at an empty bin and there are neighbors
1831  # in specified direction with non-zero entries
1832  if(binContent == 0) and (nFilled > 1):
1833  # average over non-zero entries
1834  binContent = (binContentNW + binContentSE + binContentNE + binContentSW +
1835  binContentUp + binContentDown + binContentRight + binContentLeft) / nFilled
1836  hist_step1.SetBinContent(i, j, binContent)
1837 
1838  # add result of interpolation
1839  histCopy.Add(hist_step1)
1840 
1841  for i in range(1, nBinsX):
1842  for j in range(1, nBinsY):
1843  if(i < xMin) or (i > xMax) or (j < yMin) or (j > yMax):
1844  continue
1845  binContent = histCopy.GetBinContent(i, j)
1846  # get entries for "Swiss Cross" average
1847  binContentUp = histCopy.GetBinContent(i, j + 1)
1848  binContentDown = histCopy.GetBinContent(i, j - 1)
1849  binContentLeft = histCopy.GetBinContent(i - 1, j)
1850  binContentRight = histCopy.GetBinContent(i + 1, j)
1851  nFilled = 0
1852  if(binContentUp > 0):
1853  nFilled += 1
1854  if(binContentDown > 0):
1855  nFilled += 1
1856  if(binContentRight > 0):
1857  nFilled += 1
1858  if(binContentLeft > 0):
1859  nFilled += 1
1860  if(binContent == 0) and (nFilled > 0):
1861  # only average over non-zero entries
1862  binContent = (
1863  binContentUp + binContentDown + binContentRight + binContentLeft) / nFilled
1864  hist_step2.SetBinContent(i, j, binContent)
1865  # add "Swiss Cross" average
1866  histCopy.Add(hist_step2)
1867 
1868  return histCopy
1869 
1870 
1871 def rebin(hist):
1872  histName = hist.GetName()
1873  histName += "_rebin"
1874 
1875  # bin widths are needed so as to not shift histogram by half a bin with each rebinning
1876  # assume constant binning
1877  # binWidthX = hist.GetXaxis().GetBinWidth(1)
1878  # binWidthY = hist.GetYaxis().GetBinWidth(1)
1879 
1880  # histRebinned = R.TH2F(histName, histName, 2*hist.GetNbinsX(), hist.GetXaxis().GetXmin()+binWidthX/4, hist.GetXaxis().GetXmax()+binWidthX/4, 2*hist.GetNbinsY(), hist.GetYaxis().GetXmin()+binWidthY/4, hist.GetYaxis().GetXmax()+binWidthY/4)
1881  histRebinned = R.TH2F(histName, histName, 2 * hist.GetNbinsX() - 1, hist.GetXaxis().GetXmin(),
1882  hist.GetXaxis().GetXmax(), 2 * hist.GetNbinsY() - 1, hist.GetYaxis().GetXmin(), hist.GetYaxis().GetXmax())
1883 
1884  # copy results from previous histogram
1885  for iX in range(1, hist.GetNbinsX() + 1):
1886  for iY in range(1, hist.GetNbinsY() + 1):
1887  binContent = hist.GetBinContent(iX, iY)
1888  histRebinned.SetBinContent(2 * iX - 1, 2 * iY - 1, binContent)
1889  histRebinned.SetMaximum(hist.GetMaximum())
1890  histRebinned.SetMinimum(hist.GetMinimum())
1891 
1892  # use interpolation to re-fill histogram
1893  histRebinnedInterpolated = NewInterpolate(histRebinned)
1894 
1895  return histRebinnedInterpolated
1896 
1897 
1898 def higgsConstraint(model, higgstype):
1899  higgsBand = R.TGraph2D()
1900  masslow = 150
1901  masshigh = 500
1902  massstep = 10
1903  n = 0
1904  for mass in range(masslow, masshigh, massstep):
1905  myfile = open("../../HiggsAnalysis/HiggsToTauTau/data/Higgs125/" +
1906  model + "/higgs_" + str(mass) + ".dat", 'r')
1907  for line in myfile:
1908  tanb = (line.split())[0]
1909  mh = float((line.split())[1])
1910  mH = float((line.split())[3])
1911  if higgstype == "h":
1912  higgsBand.SetPoint(n, mass, float(tanb), mh)
1913  elif higgstype == "H":
1914  higgsBand.SetPoint(n, mass, float(tanb), mH)
1915  n = n + 1
1916  myfile.close()
1917  return higgsBand
1918 
1919 
1920 def getOverlayMarkerAndLegend(legend, entries, options, borderSize=2.0/3, markerStyle="P"):
1921  borderLegend = legend.Clone()
1922  borderLegend.Clear()
1923  graphs = []
1924  for i in range(legend.GetNRows()):
1925  if i in entries:
1926  graph = entries[i].Clone()
1927  options[i]["MarkerSize"] = graph.GetMarkerSize()*borderSize
1928  Set(graph,**options[i])
1929  borderLegend.AddEntry(graph, " ", markerStyle)
1930  graphs.append(graph)
1931  else:
1932  borderLegend.AddEntry("", " ", "")
1933  borderLegend.SetFillStyle(0)
1934  borderLegend.SetFillColor(0)
1935  return (borderLegend,graphs)
python.plotting.SetBirdPalette
def SetBirdPalette()
Definition: plotting.py:251
python.plotting.LimitTGraphFromJSON
def LimitTGraphFromJSON(js, label)
Definition: plotting.py:730
python.plotting.Get
def Get(file, obj)
Definition: plotting.py:552
python.plotting.SetupTwoPadSplitAsRatio
def SetupTwoPadSplitAsRatio(pads, upper, lower, y_title, y_centered, y_min, y_max)
Definition: plotting.py:419
python.plotting.Set
def Set(obj, **kwargs)
Definition: plotting.py:296
python.plotting.makeHist1D
def makeHist1D(name, xbins, graph, scaleXrange=1.0, absoluteXrange=None)
Definition: plotting.py:838
python.plotting.TwoPadSplit
def TwoPadSplit(split_point, gap_low, gap_high)
Definition: plotting.py:322
python.plotting.DrawVerticalBand
def DrawVerticalBand(pad, box, x1, x2)
Definition: plotting.py:1532
python.plotting.SetDeepSeaPalette
def SetDeepSeaPalette()
Definition: plotting.py:264
python.plotting.FindCrossingsWithSpline
def FindCrossingsWithSpline(graph, func, yval)
Definition: plotting.py:1040
python.plotting.FixOverlay
def FixOverlay()
Definition: plotting.py:1323
python.plotting.RemoveGraphYAll
def RemoveGraphYAll(graph, val)
Definition: plotting.py:962
python.plotting.MakeErrorBand
def MakeErrorBand(LowerGraph, UpperGraph)
Definition: plotting.py:712
python.plotting.RemoveInXRange
def RemoveInXRange(gr, xmin=0, xmax=1)
Definition: plotting.py:1126
python.plotting.frameTH2D
def frameTH2D(hist, threshold, frameValue=1000)
Definition: plotting.py:1675
python.plotting.TGraph2DFromTree
def TGraph2DFromTree(tree, xvar, yvar, zvar, selection)
Definition: plotting.py:587
python.plotting.ToyTGraphFromJSON
def ToyTGraphFromJSON(js, label)
Definition: plotting.py:746
python.plotting.fillTH2
def fillTH2(hist2d, graph)
Definition: plotting.py:1761
python.plotting.StyleLimitBand
def StyleLimitBand(graph_dict, overwrite_style_dict=None)
Definition: plotting.py:1586
python.plotting.treeToHist2D
def treeToHist2D(t, x, y, name, cut, xmin, xmax, ymin, ymax, xbins, ybins)
Definition: plotting.py:820
python.plotting.higgsConstraint
def higgsConstraint(model, higgstype)
Definition: plotting.py:1898
python.plotting.contourFromTH2
def contourFromTH2(h2in, threshold, minPoints=10, frameValue=1000.)
Definition: plotting.py:1636
python.plotting.SetTDRStyle
def SetTDRStyle()
Sets the PubComm recommended style.
Definition: plotting.py:26
python.plotting.GetPadYMax
def GetPadYMax(pad, do_min=False)
Definition: plotting.py:1310
python.plotting.ReZeroTGraph
def ReZeroTGraph(gr, doIt=False)
Definition: plotting.py:1087
python.plotting.TGraphFromTree
def TGraphFromTree(tree, xvar, yvar, selection)
Definition: plotting.py:581
python.plotting.ToyTGraphFromJSONFile
def ToyTGraphFromJSONFile(jsfile, label)
Definition: plotting.py:768
python.plotting.FixBothRanges
def FixBothRanges(pad, fix_y_lo, frac_lo, fix_y_hi, frac_hi)
Adjusts y-axis range such that a lower and a higher value are located a fixed fraction of the frame h...
Definition: plotting.py:1226
python.plotting.bestFit
def bestFit(tree, x, y, cut)
Definition: plotting.py:805
python.plotting.DrawCMSLogo
def DrawCMSLogo(pad, cmsText, extraText, iPosX, relPosX, relPosY, relExtraDY, extraText2='', cmsTextSize=0.8)
Blah.
Definition: plotting.py:1399
python.plotting.FilterGraph
def FilterGraph(gr, n=3)
Definition: plotting.py:1112
python.plotting.fastFillTH2
def fastFillTH2(hist2d, graph, initalValue=99999, interpolateMissing=False)
Definition: plotting.py:1742
python.plotting.GetPadYMaxInRange
def GetPadYMaxInRange(pad, x_min, x_max, do_min=False)
Definition: plotting.py:1252
python.plotting.RocCurveFrom1DHists
def RocCurveFrom1DHists(h_x, h_y, cut_is_greater_than)
Definition: plotting.py:594
python.plotting.DrawHorizontalLine
def DrawHorizontalLine(pad, line, yval)
Definition: plotting.py:1519
python.plotting.StandardLimitsFromJSONFile
def StandardLimitsFromJSONFile(json_file, draw=['obs', 'exp0', 'exp1', 'exp2'])
Definition: plotting.py:789
python.plotting.TH2FromTGraph2D
def TH2FromTGraph2D(graph, method='BinEdgeAligned', force_x_width=None, force_y_width=None)
Build an empty TH2 from the set of points in a TGraph2D.
Definition: plotting.py:670
python.plotting.CreateAxisHist
def CreateAxisHist(src, at_limits=True)
Definition: plotting.py:460
python.plotting.GraphDivide
def GraphDivide(num, den)
Definition: plotting.py:904
python.plotting.LimitTGraphFromJSONFile
def LimitTGraphFromJSONFile(jsfile, label)
Definition: plotting.py:741
python.plotting.MakeTChain
def MakeTChain(files, tree)
Definition: plotting.py:545
python.plotting.CreateTransparentColor
def CreateTransparentColor(color, alpha)
Definition: plotting.py:286
python.plotting.ParamFromFilename
def ParamFromFilename(filename, param)
Definition: plotting.py:560
python.plotting.getOverlayMarkerAndLegend
def getOverlayMarkerAndLegend(legend, entries, options, borderSize=2.0/3, markerStyle="P")
Definition: plotting.py:1920
python.plotting.ModTDRStyle
def ModTDRStyle(width=600, height=600, t=0.06, b=0.12, l=0.16, r=0.04)
Modified version of the tdrStyle.
Definition: plotting.py:177
python.plotting.makeVarBinHist2D
def makeVarBinHist2D(name, xbins, ybins)
Definition: plotting.py:859
python.plotting.ApplyGraphYOffset
def ApplyGraphYOffset(graph, y_off)
Definition: plotting.py:957
python.plotting.NewInterpolate
def NewInterpolate(hist)
Definition: plotting.py:1782
python.plotting.ThreePadSplit
def ThreePadSplit(upper_split_point, split_point, gap_low, gap_high)
Definition: plotting.py:335
python.plotting.FixBoxPadding
def FixBoxPadding(pad, box, frac)
Definition: plotting.py:1328
python.plotting.DrawVerticalLine
def DrawVerticalLine(pad, line, xval)
Definition: plotting.py:1526
python.plotting.ImproveMinimum
def ImproveMinimum(graph, func, doIt=False)
Definition: plotting.py:1003
python.plotting.PositionedLegend
def PositionedLegend(width, height, pos, offset, horizontaloffset=None)
Definition: plotting.py:1492
python.plotting.LimitBandTGraphFromJSON
def LimitBandTGraphFromJSON(js, central, lo, hi)
Definition: plotting.py:773
python.plotting.OnePad
def OnePad()
Definition: plotting.py:314
python.plotting.GetPadYMin
def GetPadYMin(pad)
Definition: plotting.py:1319
python.plotting.MultiRatioSplitColumns
def MultiRatioSplitColumns(split_points, gaps_left, gaps_right)
Definition: plotting.py:403
python.plotting.DrawTitle
def DrawTitle(pad, text, align, textOffset=0.2, textSize=0.6)
Definition: plotting.py:1539
python.plotting.FixTopRange
def FixTopRange(pad, fix_y, fraction)
Definition: plotting.py:1186
python.plotting.TFileIsGood
def TFileIsGood(filename)
Performs a series of tests on a TFile to ensure that it can be opened without errors.
Definition: plotting.py:527
python.plotting.RemoveGraphXDuplicates
def RemoveGraphXDuplicates(graph)
Definition: plotting.py:947
python.plotting.RemoveNearMin
def RemoveNearMin(graph, val, spacing=None)
Definition: plotting.py:1138
python.plotting.RemoveGraphYAbove
def RemoveGraphYAbove(graph, val)
Definition: plotting.py:981
python.plotting.isclose
def isclose(a, b, rel_tol=1e-9, abs_tol=0.0)
Definition: plotting.py:1583
python.plotting.CreateAxisHists
def CreateAxisHists(n, src, at_limits)
Definition: plotting.py:485
python.plotting.GraphDifference
def GraphDifference(graph1, graph2, relative)
Definition: plotting.py:888
python.plotting.MakeRatioHist
def MakeRatioHist(num, den, num_err, den_err)
Make a new ratio TH1 from numerator and denominator TH1s with optional error propagation.
Definition: plotting.py:928
python.plotting.SetCorrMatrixPalette
def SetCorrMatrixPalette()
Definition: plotting.py:277
python.plotting.makeHist2D
def makeHist2D(name, xbins, ybins, graph2d)
Definition: plotting.py:849
python.plotting.MultiRatioSplit
def MultiRatioSplit(split_points, gaps_low, gaps_high)
Create a set of TPads split vertically on the TCanvas.
Definition: plotting.py:374
python.plotting.DrawLimitBand
def DrawLimitBand(pad, graph_dict, draw=['exp2', 'exp1', 'exp0', 'obs'], draw_legend=None, legend=None, legend_overwrite=None)
Definition: plotting.py:1602
python.plotting.GetAxisHist
def GetAxisHist(pad)
Definition: plotting.py:493
python.plotting.StandardAxes
def StandardAxes(xaxis, yaxis, var, units, fmt='.1f')
Definition: plotting.py:437
python.plotting.SetMinToZero
def SetMinToZero(graph)
Definition: plotting.py:991
python.plotting.fillInvertedTH2
def fillInvertedTH2(hist2d, graph)
Definition: plotting.py:1769
python.plotting.rebin
def rebin(hist)
Definition: plotting.py:1871
python.plotting.RemoveSmallDelta
def RemoveSmallDelta(graph, val)
Definition: plotting.py:971
python.plotting.TwoPadSplitColumns
def TwoPadSplitColumns(split_point, gap_left, gap_right)
Definition: plotting.py:389
python.plotting.SortGraph
def SortGraph(Graph)
Definition: plotting.py:1166