ATLAS Offline Software
Loading...
Searching...
No Matches
PlotHelpers.py
Go to the documentation of this file.
1# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
2
3from ROOT import *
4from array import array
5from math import fabs,exp,log,log10
6import sys
7import re
8import os
9import AtlasStyleMacro
10
11gROOT.SetBatch(True)
13
14def GetKeyNames(self,dir=""):
15 self.cd(dir)
16 return [key.GetName() for key in gDirectory.GetListOfKeys()]
17TFile.GetKeyNames = GetKeyNames
18
19def GetNameNoDir(self):
20 return os.path.basename(self.GetName())
21
22TFile.GetNameNoDir = GetNameNoDir
23
24# Set the palette
25def 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
81def 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
89def 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
98doDrawText.tex = None
99
100
101def 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)
197SetAxisRange.forceOneSided = False
198SetAxisRange.relativeAxis = False
199SetAxisRange.invertAxisColour = False
200
201
202
203def 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
219def 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)
239DrawGrid.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
256def 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
301DetermineStatValues.tex = None
302DetermineStatValues.minInsteadOfMax = False
303
304
305
306
307
308
constexpr int pow(int base, int exp) noexcept
STL class.
SetAxisRange(histo, oneSided=True, lowBound=-1e10, highBound=1e10)
SetAxisLabels(histo, xValues, yValues, labelString)
DrawGrid(histo, xValues, yValues)
set_style(style="Plain")
DetermineStatValues(histo, xValues, yValues, lowBound=-1e10, highBound=1e10, percent=True)
doDrawText(xPos, yPos, text)
set_palette(name="palette", ncontours=999)