ATLAS Offline Software
Loading...
Searching...
No Matches
PlotUtils.py
Go to the documentation of this file.
1# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3#!/usr/bin/env python
4import ROOT, math, os
5from array import array
6
8 Out = In
9 NotWantedChars = ["{", "}", "[", "]", "#", "^", ")", "(", "'", " ", "-"]
10 ReplaceChars = [".", ","]
11 for C in NotWantedChars:
12 Out = Out.replace(C, "")
13 for C in ReplaceChars:
14 Out = Out.replace(C, "_")
15 return Out
16
17
19 def __init__(self, name = "",
20 axis_title = "",
21 bins = -1,
22 bmin = 0.,
23 bmax = -1.e9,
24 bin_width = -1,
25 bdir = None,
26 log_binning = False):
27 self.__name = name
28 self.__xTitle = axis_title
29 self.__min = bmin
30 self.__width = bin_width
31 self.__entries = 0
32 self.__content = {}
33 self.__error = {}
34 self.__TH1 = None
35 self.__TDir = bdir
36
37 self.__log_binning = log_binning
38 if bins > 0 and not log_binning:
39 self.__width = (bmax-bmin)/ bins
40 self.__TH1 = ROOT.TH1D(name, "Diagnostic histogram", bins, bmin, bmax)
41 self.__TH1.SetDirectory(bdir)
42 elif bins > 0:
43 log_start = math.log(bmin)
44 log_end = math.log(bmax)
45 log_step = (log_end -log_start) / bins
46 binning = array("f", [math.exp(log_start +n*log_step) for n in range(bins+1)])
47 self.__TH1 = ROOT.TH1D(name, "Diagnostic histogram", bins, binning)
48 self.__TH1.SetDirectory(bdir)
49
50 def has_log_binnnig(self): return self.__log_binning
51 def name(self): return self.__name
52 def TH1(self): return self.__TH1
53 def fill(self, value, weight=1.):
54 self.__entries +=1
55 if self.__TH1: self.__TH1.Fill(value, weight)
56 else:
57 rng = self.__getInterval(value)
58 try: self.__content[rng] += weight
59 except: self.__content[rng] = weight
60 try: self.__error[rng] += weight**2
61 except: self.__error[rng] = weight**2
62 def __getInterval(self,value):
63 i = math.ceil( (value - self.__min) / self.__width)
64 return (self.__min +self.__width*(i-1), self.__min+ self.__width*i)
65 def write(self):
66 self.fixHisto()
67 if not self.__TH1: return
68 self.__TH1.GetXaxis().SetTitle(self.__xTitle)
69
70 self.TH1().SetBinContent(self.TH1().GetNbinsX(),self.TH1().GetBinContent(self.TH1().GetNbinsX()+1) + self.TH1().GetBinContent(self.TH1().GetNbinsX()))
71 self.TH1().SetBinError(self.TH1().GetNbinsX(), math.sqrt( (self.TH1().GetBinError(self.TH1().GetNbinsX()+1) + self.TH1().GetBinError(self.TH1().GetNbinsX()))**2))
72
73 self.TH1().SetBinContent(1,self.TH1().GetBinContent(0) + self.TH1().GetBinContent(1))
74 self.TH1().SetBinError(1, math.sqrt( (self.TH1().GetBinError(0) + self.TH1().GetBinError(1))**2))
75
76 self.__TH1.SetEntries(self.__entries)
77 if self.__TDir: self.__TDir.WriteObject(self.__TH1, self.__name)
78 def max(self):
79 try: return sorted(self.__content.iterkeys(), key=lambda Rng: Rng[1])[-1][1]
80 except: return float('nan')
81 def min(self):
82 try: return sorted(self.__content.iterkeys(), key=lambda Rng: Rng[0])[0][1]
83 except: return float('nan')
84 def setMinimum(self, minimum): self.__min = minimum
85 def setMaximum(self, maximum): self.__max = maximum
86 def fixHisto(self):
87 if self.__TH1: return
88 bins = min (int((self.__max - self.__min) / self.__width), 10000)
89 self.__TH1 = ROOT.TH1D(self.name(), "Diagnostic histogram", bins, self.__min, self.__max)
90 self.__TH1.SetDirectory(self.__TDir)
91
92 for rng in self.__content.iterkeys():
93 bin = self.__TH1.FindBin((rng[1] + rng[0])/2.)
94 self.__TH1.SetBinContent(bin, self.__content[rng])
95 self.__TH1.SetBinError(bin, math.sqrt(self.__error[rng]))
96
98 def __init__(self, size=18, status="Internal", lumi=1., sqrts="13", normalizedToUnity=False):
99 self.__Status = status
100 self.__Size = size
101 self.__Lumi = lumi # in fb^-1
102 self.__SqrtS = sqrts
104 self.__Canvas = None
105 self.__Pad1 = None
106 self.__Pad2 = None
107 self.__Styling = None
108 self.__RatStyling = None
109 self.__Legend = None
110 self.__NLegEnt = 0
111 self.__normalizedToUnity = normalizedToUnity
112 self.__Objects = []
113
114 def DrawTLatex(self, x, y, text, size=18, font=43, align=11, ndc=True, color=-1):
115 tex = ROOT.TLatex()
116 tex.SetTextAlign(align)
117 tex.SetTextSize(size)
118 tex.SetTextFont(font)
119 if ndc: tex.SetNDC()
120 if color > -1: tex.SetTextColor(color)
121 self.__Objects.append(tex)
122 tex.DrawLatex(x, y, text)
123
124 def GetStatus(self):
125 return self.__Status
126
127 def GetLumi(self):
128 return self.__Lumi
129
130 def DrawAtlas(self, x, y, align=11):
131 # print "Size is %.2f"%self.__Size
132 self.DrawTLatex(x, y, "#font[72]{ATLAS} %s" % self.__Status, self.__Size, 43, align)
133
134 def DrawLumiSqrtS(self, x, y, align=11, lumi=1.):
135 if self.__normalizedToUnity: self.DrawTLatex(x, y, "#sqrt{s} = %s TeV" % (self.__SqrtS), self.__Size, 43, align)
136 elif self.__Lumi >= 999999999: self.DrawTLatex(x, y, "#sqrt{s} = %s TeV, ?? pb^{-1}" % (self.__SqrtS), self.__Size, 43, align)
137 elif self.__Lumi < 1.e-6:
138 lumiToPrint = "%.0f" % (self.__Lumi * 1e6)
139 self.DrawTLatex(x, y, "#sqrt{s} = %s TeV, %s nb^{-1}" % (self.__SqrtS, lumiToPrint), self.__Size, 43, align)
140 elif self.__Lumi < 1.e-3:
141 lumiToPrint = "%.0f" % (self.__Lumi * 1e3)
142 self.DrawTLatex(x, y, "#sqrt{s} = %s TeV, %s pb^{-1}" % (self.__SqrtS, lumiToPrint), self.__Size, 43, align)
143 else:
144 lumiToPrint = "%.1f" % (self.__Lumi)
145 self.DrawTLatex(x, y, "#sqrt{s} = %s TeV, %s fb^{-1}" % (self.__SqrtS, lumiToPrint), self.__Size, 43, align)
146
147 def DrawSqrtS(self, x, y, align=11):
148 self.DrawTLatex(x, y, "#sqrt{s} = %s TeV" % (self.__SqrtS), self.__Size, 43, align)
149
150
151 def CreateLegend(self, x1, y1, x2, y2, textsize=22):
152 if self.__Legend:
153 print "WARNING: There already exists a legend. Will delete the old one"
154 del self.__Legend
155 self.__Legend = ROOT.TLegend(x1, y1, x2, y2)
156 self.__Legend.SetFillStyle(0)
157 self.__Legend.SetBorderSize(0)
158 self.__Legend.SetTextFont(43)
159 self.__Legend.SetTextSize(textsize)
160 return self.__Legend
161
162 def GetLegend(self, x1=0, y1=1., x2=1., y2=1.):
163 if not self.__Legend: return CreateLegend(x1, y1, x2, y2)
164 return self.__Legend
165
166 def AddToLegend(self, Items, Style="FL"):
167 if isinstance(Items, list):
168 for I in Items:
169 self.__AddItemToLegend(I, Style)
170 else:
171 self.__AddItemToLegend(Items, Style)
172
173 def __AddItemToLegend(self, Item, Style):
174 try:
175 self.__Legend.AddEntry(Item, Item.GetTitle(), Style)
176 except:
177 self.__Legend.AddEntry(Item.get(), Item.GetTitle(), Style)
178
179 self.__NLegEnt += 1
180
181 def DrawLegend(self, NperCol=3):
182 if not self.__Legend:
183 print "No legend has been defined yet"
184 return
185 N = self.__NLegEnt
186 Col = int((N - N % NperCol) / NperCol + (N % NperCol > 0))
187 if Col < 1: Col = 1
188 self.__Legend.SetNColumns(Col)
189 self.__Legend.Draw()
190
191 def DrawSource(self, probe, x, y, align=11):
192 self.DrawTLatex(x, y, self.ProbeName(probe), self.__Size, 43, align)
193
194 def Prepare1PadCanvas(self, cname, width=800, height=600, isQuad=False):
195 if isQuad: height = width
196 if self.__Canvas:
197 if self.__Canvas.GetName() != cname: self.__Canvas = None
198 else:
199 print "INFO Already found a canvas named: " + cname
200 return self.__Canvas
201 self.__Canvas = ROOT.TCanvas(cname, cname, width, height)
202 self.__Canvas.cd()
203
204 def GetCanvas(self):
205 if not self.__Canvas: print "WARNING: No Canvas has been created yet. Please call CreateXPadCanvas() before"
206 return self.__Canvas
207
208 def Prepare2PadCanvas(self, cname, width=800, height=600, isQuad=False, DoLogX=False):
209 self.Prepare1PadCanvas(cname, width, height, isQuad)
210
211 self.__Pad1 = ROOT.TPad(cname+"Pad1", cname, 0.0, self.__VerticalCanvasSplit - 0.03, 1.0, 1.0)
212 self.__Pad2 = ROOT.TPad(cname+"Pad2", cname, 0.0, 0.0, 1.0, self.__VerticalCanvasSplit - 0.03)
213 if DoLogX:
214 self.__Pad1.SetLogx()
215 self.__Pad2.SetLogx()
216 self.__Pad1.SetBottomMargin(0.03) # set to 0 for space between top and bottom pad
217 self.__Pad1.SetTopMargin(0.09)
218 self.__Pad1.Draw()
219 self.__Pad2.SetTopMargin(0.01) # set to 0 for space between top and bottom pad
220 self.__Pad2.SetBottomMargin(0.35)
221 self.__Pad2.SetGridy()
222 self.__Pad2.Draw()
223
224 def GetTopPad(self):
225 return self.__Pad1
226 def GetBottomPad(self):
227 return self.__Pad2
228 def AdaptLabelsTopPad(self, histos):
229 labelscalefact = 1. / (1. - self.__VerticalCanvasSplit)
230 for hist in histos:
231 hist.GetXaxis().SetTitleSize(labelscalefact * hist.GetXaxis().GetTitleSize())
232 hist.GetYaxis().SetTitleSize(labelscalefact * hist.GetYaxis().GetTitleSize())
233 hist.GetXaxis().SetLabelSize(labelscalefact * hist.GetXaxis().GetLabelSize())
234 hist.GetYaxis().SetLabelSize(labelscalefact * hist.GetYaxis().GetLabelSize())
235 hist.GetXaxis().SetTitleOffset(1. / labelscalefact * hist.GetXaxis().GetTitleOffset())
236 hist.GetYaxis().SetTitleOffset(1. / labelscalefact * hist.GetYaxis().GetTitleOffset())
237
238 def AdaptLabelsBottomPad(self, histos, scale=1.):
239 if self.__VerticalCanvasSplit == 0:
240 labelscalefact = 1.
241 else:
242 labelscalefact = 1. / (scale * self.__VerticalCanvasSplit)
243 for hist in histos:
244 hist.GetXaxis().SetTitleSize(labelscalefact * hist.GetXaxis().GetTitleSize())
245 hist.GetYaxis().SetTitleSize(labelscalefact * hist.GetYaxis().GetTitleSize())
246 hist.GetXaxis().SetLabelSize(labelscalefact * hist.GetXaxis().GetLabelSize())
247 hist.GetYaxis().SetLabelSize(labelscalefact * hist.GetYaxis().GetLabelSize())
248 hist.GetXaxis().SetTitleOffset(2.2 / labelscalefact * hist.GetXaxis().GetTitleOffset())
249 hist.GetYaxis().SetTitleOffset(1.05 / labelscalefact * hist.GetYaxis().GetTitleOffset())
250
251 def drawStyling(self, Template, ymin, ymax, TopPad=True, RemoveLabel=False):
252 self.__Styling = Template.Clone("Style" + Template.GetName())
253 self.__Styling.SetMinimum(ymin)
254 self.__Styling.SetMaximum(ymax)
255
256 if RemoveLabel == True: self.__Styling.GetXaxis().SetLabelOffset(10.)
257 if TopPad: self.AdaptLabelsTopPad([self.__Styling])
258 self.__Styling.Draw("AXIS")
259
260 def addValuesInText(self, histo, on_top=True, off_set_y=0.005):
261 plot_range_x = (histo.GetXaxis().GetBinUpEdge(histo.GetNbinsX()) - histo.GetXaxis().GetBinLowEdge(1)) / (
262 (1 - self.GetCanvas().GetRightMargin()) - self.GetCanvas().GetLeftMargin())
263 plot_range_y = (histo.GetMaximum() - histo.GetMinimum())
264
265 left_margin = self.GetCanvas().GetLeftMargin()
266 bottom_margin = 0
267 if on_top and self.__Pad1:
268 plot_range_y /= (1 - self.__Pad1.GetTopMargin() - self.__Pad1.GetBottomMargin())
269 bottom_margin = self.__Pad1.GetBottomMargin()
270
271 elif on_top and self.GetCanvas():
272 plot_range_y /= (1 - self.GetCanvas().GetTopMargin() - self.GetCanvas().GetBottomMargin())
273 bottom_margin = self.GetCanvas().GetBottomMargin()
274 elif not on_top and self.__Pad2:
275 plot_range_y /= (1 - self.__Pad2.GetTopMargin() - self.__Pad2.GetBottomMargin())
276 bottom_margin = self.__Pad2.GetBottomMargin()
277
278 for i in range(1, histo.GetNbinsX() + 1):
279 tex = self.DrawTLatex(
280 left_margin + ((histo.GetBinCenter(i) - histo.GetXaxis().GetBinLowEdge(1)) / plot_range_x),
281 bottom_margin + (histo.GetBinContent(i) + off_set_y - histo.GetMinimum()) / plot_range_y,
282 "%.3f" % (histo.GetBinContent(i)),
283 size=10,
284 align=21,
285 color=histo.GetLineColor(),
286 )
287 def saveHisto(self, name, outputfiletypes):
288 Path = RemoveSpecialChars(name)
289 if Path.find("/") != -1:
290 dir_name = Path[ : Path.rfind("/") ]
291 os.system("mkdir -p %s"%(dir_name))
292 if "png" in outputfiletypes:
293 # need a 'pdf' file for using 'convert' to create a 'png'
294 if not "pdf" in outputfiletypes:
295 outputfiletypes.append("pdf")
296 a, b = outputfiletypes.index('pdf'), outputfiletypes.index('png')
297 outputfiletypes[b], outputfiletypes[a] = outputfiletypes[a], outputfiletypes[b]
298 if self.GetBottomPad(): self.GetBottomPad().RedrawAxis()
299 if self.GetTopPad(): self.GetTopPad().RedrawAxis()
300
301 for otype in outputfiletypes:
302 if otype != "png":
303 self.__Canvas.SaveAs("%s.%s" % (Path, otype))
304 else:
305 # due to problems in png creation, convert pdfs to pngs manually
306 os.system("convert -density 300 %s.pdf %s.png" % (Path, Path))
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
__init__(self, name="", axis_title="", bins=-1, bmin=0., bmax=-1.e9, bin_width=-1, bdir=None, log_binning=False)
Definition PlotUtils.py:26
__getInterval(self, value)
Definition PlotUtils.py:62
fill(self, value, weight=1.)
Definition PlotUtils.py:53
setMinimum(self, minimum)
Definition PlotUtils.py:84
setMaximum(self, maximum)
Definition PlotUtils.py:85
int __entries
Pull back the overflow.
Definition PlotUtils.py:31
self.__TH1.Fill(value, weight) __TH1
Definition PlotUtils.py:34
Prepare2PadCanvas(self, cname, width=800, height=600, isQuad=False, DoLogX=False)
Definition PlotUtils.py:208
DrawSource(self, probe, x, y, align=11)
Definition PlotUtils.py:191
CreateLegend(self, x1, y1, x2, y2, textsize=22)
Definition PlotUtils.py:151
Prepare1PadCanvas(self, cname, width=800, height=600, isQuad=False)
Definition PlotUtils.py:194
GetLegend(self, x1=0, y1=1., x2=1., y2=1.)
Definition PlotUtils.py:162
AdaptLabelsBottomPad(self, histos, scale=1.)
Definition PlotUtils.py:238
float __VerticalCanvasSplit
Definition PlotUtils.py:103
self.DrawTLatex(x, y, %(self.__SqrtS), self.__Size, 43, align) __normalizedToUnity
Definition PlotUtils.py:111
__AddItemToLegend(self, Item, Style)
Definition PlotUtils.py:173
DrawLumiSqrtS(self, x, y, align=11, lumi=1.)
Definition PlotUtils.py:134
drawStyling(self, Template, ymin, ymax, TopPad=True, RemoveLabel=False)
Definition PlotUtils.py:251
DrawSqrtS(self, x, y, align=11)
Definition PlotUtils.py:147
AddToLegend(self, Items, Style="FL")
Definition PlotUtils.py:166
DrawLegend(self, NperCol=3)
Definition PlotUtils.py:181
DrawAtlas(self, x, y, align=11)
Definition PlotUtils.py:130
addValuesInText(self, histo, on_top=True, off_set_y=0.005)
Definition PlotUtils.py:260
AdaptLabelsTopPad(self, histos)
Definition PlotUtils.py:228
__init__(self, size=18, status="Internal", lumi=1., sqrts="13", normalizedToUnity=False)
Definition PlotUtils.py:98
DrawTLatex(self, x, y, text, size=18, font=43, align=11, ndc=True, color=-1)
Definition PlotUtils.py:114
saveHisto(self, name, outputfiletypes)
Definition PlotUtils.py:287
return CreateLegend(x1, y1, x2, y2) __Legend
Definition PlotUtils.py:109
STL class.
RemoveSpecialChars(In)
Definition PlotUtils.py:7