ATLAS Offline Software
PlotHelpers.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
2 
3 from ROOT import *
4 from array import array
5 from math import fabs,exp,log,log10
6 import sys
7 import re
8 import os
9 import AtlasStyleMacro
10 
11 gROOT.SetBatch(True)
13 
14 def GetKeyNames(self,dir=""):
15  self.cd(dir)
16  return [key.GetName() for key in gDirectory.GetListOfKeys()]
17 TFile.GetKeyNames = GetKeyNames
18 
19 def GetNameNoDir(self):
20  return os.path.basename(self.GetName())
21 
22 TFile.GetNameNoDir = GetNameNoDir
23 
24 # Set the palette
25 def set_palette(name="palette", ncontours=999):
26  #"""Set a color palette from a given RGB list
27  #stops, red, green and blue should all be lists of the same length
28  #see set_decent_colors for an example"""
29  if name == "gray" or name == "grayscale":
30  stops = [0.00, 0.34, 0.61, 0.84, 1.00]
31  red = [1.00, 0.84, 0.61, 0.34, 0.00]
32  green = [1.00, 0.84, 0.61, 0.34, 0.00]
33  blue = [1.00, 0.84, 0.61, 0.34, 0.00]
34  elif name == "Sophie":
35  ncontours=18
36  stops = [0.00, 0.50, 0.75, 1.00]
37  red = [1.00, 0.20, 0.00, 0.20]
38  green = [0.00, 0.20, 1.00, 1.00]
39  blue = [1.00, 1.00, 1.00, 0.20]
40  elif name == "SophieInverse":
41  ncontours=18
42  stops = [0.00, 0.50, 0.75, 1.00]
43  red = [0.20, 0.00, 0.20, 1.00]
44  green = [1.00, 1.00, 0.20, 0.00]
45  blue = [0.20, 1.00, 1.00, 1.00]
46  elif name == "Steven":
47  ncontours=50
48  stops = [0.00, 0.50, 1.00]
49  red = [0.70, 0.00, 0.20]#[1.00, 0.00, 0.20]
50  green = [0.00, 0.50, 1.00]#[0.00, 0.50, 1.00]
51  blue = [0.00, 0.70, 0.20]#[0.00, 0.70, 0.20]
52  elif name == "StevenInverse":
53  ncontours=50
54  stops = [0.00, 0.50, 1.00]
55  red = [0.20, 0.00, 0.70]
56  green = [1.00, 0.50, 0.00]
57  blue = [0.20, 0.70, 0.00]
58  elif name == "StevenCentred":
59  ncontours=50
60  stops = [0.00, 0.15, 0.50, 0.85, 1.00]
61  red = [0.00, 0.00, 0.20, 0.70, 1.00]
62  green = [0.00, 0.50, 1.00, 0.00, 0.00]
63  blue = [1.00, 0.70, 0.20, 0.00, 0.00]
64  else:
65  # default palette, looks cool
66  stops = [0.00, 0.34, 0.61, 0.84, 1.00]
67  red = [0.00, 0.00, 0.87, 1.00, 0.51]
68  green = [0.00, 0.81, 1.00, 0.20, 0.00]
69  blue = [0.51, 1.00, 0.12, 0.00, 0.00]
70 
71  s = array('d', stops)
72  r = array('d', red)
73  g = array('d', green)
74  b = array('d', blue)
75 
76  npoints = len(s)
77  TColor.CreateGradientColorTable(npoints, s, r, g, b, ncontours)
78  gStyle.SetNumberContours(ncontours)
79 
80 # Set the style
81 def set_style(style="Plain"):
82  gROOT.SetStyle(style)
83  gStyle.SetPaintTextFormat("0.3g")
84  gStyle.SetOptStat(0)
85  gStyle.SetPadTickX(1)
86  gStyle.SetPadTickY(1)
87 
88 
89 def doDrawText(xPos,yPos,text):
90  if not doDrawText.tex:
91  doDrawText.tex = TLatex()
92  doDrawText.tex.SetNDC()
93  doDrawText.tex.SetTextFont(42)
94  doDrawText.tex.SetTextSize(0.040)
95 
96  doDrawText.tex.DrawLatex(xPos,yPos,text)
97 
98 doDrawText.tex = None
99 
100 
101 def SetAxisRange(histo,oneSided=True,lowBound=-1e10,highBound=1e10):
102  max = -100
103  min = 100
104  for binX in range(1,histo.GetNbinsX()+1):
105  for binY in range(1,histo.GetNbinsY()+1):
106  value = histo.GetBinContent(binX,binY)
107  if value > lowBound and value < highBound:
108  if value > max: max = value
109  if value < min: min = value
110 
111  # Check if this is ~ one-sided
112  # Allow up to 10% relative magnitude
113  actuallyOneSided = True
114  if oneSided:
115  # Only relevant if the min and max are opposite signs or around 1 if relative
116  if not SetAxisRange.relativeAxis:
117  if max > 0 and min < 0:
118  balanceFrac = fabs(min/max) if max != 0 else 100
119  if balanceFrac < 25 and balanceFrac > 0.25:
120  # Within 25% of relative magnitude
121  actuallyOneSided = False
122  else:
123  if max > 1 and min < 1:
124  balanceFrac = fabs((1-min)/(max-1)) if max != 1 else 100
125  if balanceFrac < 25 and balanceFrac > 0.25:
126  # Within 25% of relative magnitude
127  actuallyOneSided = False
128  if not actuallyOneSided and not SetAxisRange.forceOneSided:
129  print "Warning: Ignoring one-sided axis request due to magnitudes of min and max (|min/max| = |%f/%f| = %f)"%(min,max,balanceFrac)
130  print "This can be overridden using SetAxisRange.forceOneSided = True"
131  oneSided = False
132 
133  if oneSided:
134  if not SetAxisRange.relativeAxis:
135  isPositiveSide = True if max > 0 and max > fabs(min) else False
136  else:
137  isPositiveSide = True if max > 1 and (max > 1/min if min < 1 else max > min) else False
138 
139  # Warn when one-sided assumption is not strictly true
140  if isPositiveSide:
141  if not SetAxisRange.relativeAxis:
142  if min < -1.e-4:
143  print "Warning: Ignoring min of %f and setting min to 0"%(min)
144  else:
145  if min-1 < -1.e-4:
146  print "Warning: Ignoring min of %f and setting min to 1"%(min)
147 
148  # Round to nearest 5% beyond the max
149  #set_palette("SophieInverse")
150  set_palette("StevenInverse" if not SetAxisRange.invertAxisColour else "Steven")
151 
152  if not SetAxisRange.relativeAxis:
153  histo.GetZaxis().SetRangeUser(-1.e-4,int(max*20+1)/20.)
154  else:
155  histo.GetZaxis().SetRangeUser(1-1.e-4,int(max*20+1)/20.)
156 
157  elif not isPositiveSide:
158  if not SetAxisRange.relativeAxis:
159  if max > 1.e-4:
160  print "Warning: Ignoring max of %f and setting max to 0"%(max)
161  else:
162  if max-1 > 1.e-4:
163  print "Warning: Ignoring max of %f and setting max to 1"%(max)
164 
165  # Round to nearest 5% beyond the min
166  #set_palette("Sophie")
167  set_palette("Steven" if not SetAxisRange.invertAxisColour else "StevenInverse")
168 
169  if not SetAxisRange.relativeAxis:
170  histo.GetZaxis().SetRangeUser(-int(fabs(min)*20+1)/20.,1.e-4)
171  else:
172  histo.GetZaxis().SetRangeUser(int(min*20-1)/20.,1+1.e-4)
173 
174  else:
175  if not SetAxisRange.relativeAxis:
176  extremeVal = 0
177  if fabs(max) > fabs(min):
178  extremeVal = fabs(max)
179  else:
180  extremeVal = fabs(min)
181 
182  # Round to nearest 5% beyond the extreme
183  set_palette("default")
184  histo.GetZaxis().SetRangeUser(-int(extremeVal*20+1)/20.,int(extremeVal*20+1)/20.)
185  else:
186  set_palette("StevenCentred")
187  #histo.GetZaxis().SetRangeUser(0,int(max*20+1)/20.)
188  # Want the middle in log-scale to be 1
189  # If min is the extremum, then min = 10^{-X}, X = -log(min)
190  # If max is the extremum, then max = 10^{X}, X = log(max)
191  if min*max < 1:
192  # Minimum dominates
193  histo.GetZaxis().SetRangeUser(min,pow(10,-log10(min)))
194  else:
195  # Maximum dominates
196  histo.GetZaxis().SetRangeUser(pow(10,-log10(max)),max)
197 SetAxisRange.forceOneSided = False
198 SetAxisRange.relativeAxis = False
199 SetAxisRange.invertAxisColour = False
200 
201 
202 
203 def SetAxisLabels(histo,xValues,yValues,labelString):
204  factorX = histo.GetNbinsX()/len(xValues)
205  factorY = histo.GetNbinsY()/len(yValues)
206 
207  for index in range(1,len(xValues)+1):
208  histo.GetXaxis().SetBinLabel(int(factorX*(index-0.5)),labelString%(xValues[index-1]))
209  for index in range(1,len(yValues)+1):
210  histo.GetYaxis().SetBinLabel(int(factorY*(index-0.5)),labelString%(yValues[index-1]))
211 
212  histo.GetXaxis().LabelsOption("h")
213  histo.GetYaxis().LabelsOption("h")
214 
215  histo.GetXaxis().SetTickLength(0)
216  histo.GetYaxis().SetTickLength(0)
217 
218 
219 def DrawGrid(histo,xValues,yValues):
220  DrawGrid.lines = []
221 
222  factorX = histo.GetNbinsX()/len(xValues)
223  factorY = histo.GetNbinsY()/len(yValues)
224 
225  for index in range(1,len(xValues)):
226  line = TLine()
227  line.SetLineWidth(2)
228  line.SetLineColor(kBlack)
229  line.SetLineStyle(1)
230  line.DrawLine(int(factorX*index),histo.GetYaxis().GetBinLowEdge(1),int(factorX*index),histo.GetYaxis().GetBinLowEdge(histo.GetNbinsY()+1))
231  DrawGrid.lines.append(line)
232  for index in range(1,len(yValues)):
233  line = TLine()
234  line.SetLineWidth(2)
235  line.SetLineColor(kBlack)
236  line.SetLineStyle(1)
237  line.DrawLine(histo.GetXaxis().GetBinLowEdge(1),int(factorY*index),histo.GetXaxis().GetBinLowEdge(histo.GetNbinsX()+1),int(factorY*index))
238  DrawGrid.lines.append(line)
239 DrawGrid.lines = []
240 
241 #def DrawStatValues(histo,maxVals,meanVals,xValues,yValues,percent=True):
242 # if not DrawStatValues.tex:
243 # DrawStatValues.tex = TLatex()
244 # DrawStatValues.tex.SetTextSize(0.02)
245 # DrawStatValues.tex.SetTextFont(42)
246 # DrawStatValues.tex.SetTextColor(kBlack)
247 #
248 # factorX = histo.GetNbinsX()/len(xValues)
249 # factorY = histo.GetNbinsY()/len(yValues)
250 # for maxVal in maxVals:
251 # DrawStatValues.tex.DrawLatex(int(factorX*(maxVal[0]+0.4)),int(factorY*(maxVal[1]+0.60)),"%.f"%(maxVal[2]*100))
252 # for meanVal in meanVals:
253 # DrawStatValues.tex.DrawLatex(int(factorX*(meanVal[0]+0.4)),int(factorY*(meanVal[1]+0.40)),"%.f"%(meanVal[2]*100))
254 #DrawStatValues.tex = None
255 
256 def DetermineStatValues(histo,xValues,yValues,lowBound=-1e10,highBound=1e10,percent=True):
257 
258  if not DetermineStatValues.tex:
259  DetermineStatValues.tex = TLatex()
260  DetermineStatValues.tex.SetTextSize(0.025)
261  DetermineStatValues.tex.SetTextFont(42)
262  DetermineStatValues.tex.SetTextColor(kBlack)
263 
264  # Proceed region by region
265  overallMax = 0
266  maxAvg = 0
267  for indexX in range(0,len(xValues)):
268  factorX = int(histo.GetNbinsX()/len(xValues))
269  lowX = indexX*factorX+1
270  highX = (indexX+1)*factorX
271  for indexY in range(0,len(yValues)):
272  factorY = int(histo.GetNbinsY()/len(yValues))
273  lowY = indexY*factorY+1
274  highY = (indexY+1)*factorY
275 
276  # Stat info
277  extremeVal = 0
278  meanVal = 0
279  numValid = 0
280 
281  # Now loop
282  for binX in range(lowX,highX):
283  for binY in range(lowY,highY):
284  binValue = histo.GetBinContent(binX,binY)
285  if binValue > lowBound and binValue < highBound:
286  numValid += 1
287  meanVal += binValue
288  if not DetermineStatValues.minInsteadOfMax and fabs(binValue) > fabs(extremeVal):
289  extremeVal = binValue
290  elif DetermineStatValues.minInsteadOfMax and fabs(binValue) < fabs(extremeVal):
291  extremeVal = binValue
292  if fabs(extremeVal) > fabs(overallMax) :
293  overallMax = extremeVal
294 
295  meanVal /= numValid
296  if fabs(meanVal) > fabs(maxAvg) :
297  maxAvg = meanVal
298  DetermineStatValues.tex.DrawLatex(int(factorX*(indexX+0.4)),int(factorY*(indexY+0.70)),"%.f"%(extremeVal*100) if percent else "%.1f"%(extremeVal))
299  DetermineStatValues.tex.DrawLatex(int(factorX*(indexX+0.4)),int(factorY*(indexY+0.30)),"%.f"%(meanVal*100) if percent else "%.1f"%(meanVal))
300  return overallMax,maxAvg
301 DetermineStatValues.tex = None
302 DetermineStatValues.minInsteadOfMax = False
303 
304 
305 
306 
307 
308 
PlotHelpers.set_style
def set_style(style="Plain")
Definition: PlotHelpers.py:81
PlotHelpers.SetAxisRange
def SetAxisRange(histo, oneSided=True, lowBound=-1e10, highBound=1e10)
Definition: PlotHelpers.py:101
PlotHelpers.set_palette
def set_palette(name="palette", ncontours=999)
Definition: PlotHelpers.py:25
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
PlotHelpers.SetAxisLabels
def SetAxisLabels(histo, xValues, yValues, labelString)
Definition: PlotHelpers.py:203
PlotHelpers.DetermineStatValues
def DetermineStatValues(histo, xValues, yValues, lowBound=-1e10, highBound=1e10, percent=True)
Definition: PlotHelpers.py:256
PlotHelpers.GetNameNoDir
def GetNameNoDir(self)
Definition: PlotHelpers.py:19
PlotHelpers.GetKeyNames
def GetKeyNames(self, dir="")
Definition: PlotHelpers.py:14
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
AtlasStyleMacro.SetAtlasStyle
def SetAtlasStyle()
Definition: AtlasStyleMacro.py:9
array
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
PlotHelpers.doDrawText
def doDrawText(xPos, yPos, text)
Definition: PlotHelpers.py:89
PlotHelpers.DrawGrid
def DrawGrid(histo, xValues, yValues)
Definition: PlotHelpers.py:219