4 Miscellaneous utilities for PyROOT.
6 __author__ =
'Juerg Beringer'
7 __version__ =
'$Id: ROOTUtils.py 759047 2016-07-01 00:45:13Z beringer $'
12 protectedObjectList = []
15 """Utility function to prevent ROOT objects from being garbage-collected,
16 (thus disappearing from plots) when they go out of scope."""
17 protectedObjectList.append(obj)
22 myCanvasSizes = {
'default': (700, 500),
23 'default2d': (545, 500),
26 'slide2text': (400,500),
30 'landscape': (1600,1000),
32 'extrawide': (1500,500),
38 """Class MyCanvas is a ROOT TCanvas that allows choosing one of
39 several typically used canvas sizes. It can automatically save
40 the canvas in different formats upon destruction provided the
41 user makes sure that all histograms still exist."""
44 saveAsList = [
'.gif' ]
45 autoSaveOnExit =
False
46 autoName =
'%s.autosave%s'
48 def __init__(self,name='MyCanvas', size='default', xdivs=1, ydivs=1, saveAsList=None, autoSaveOnExit=None):
51 if saveAsList
is not None:
55 if autoSaveOnExit
is not None:
60 self.Divide(xdivs,ydivs)
75 """PlotLibrary is a base class that can be used to manage a set of
76 plots. Each individual plot should be created as a method of a
77 derived class. Other methods of the derived class that do not
78 generate plots should either have names starting with
79 underscore, or should be declared when calling __init__ of the
82 def __init__(self, name = 'MyPlots', otherMethods=[]):
83 """Constructor. otherMethods specifies a list of methods of the derived
84 class that are not creating plots and should not be called by plot()."""
99 """Protect ROOT object from garbage collection."""
103 def plot(self, plotName='',*args):
104 """Make one or all (if plotName=='') plots."""
106 self.__class__.__dict__[plotName](self,*args)
108 for i
in self.__class__.__dict__:
109 if i[0]==
'_':
continue
111 self.__class__.__dict__[i](self,*args)
113 def genPlot(self,what='ALL',code='plot',labels=[],*args):
114 """Make plots using a general code. genPlot makes either a single plot defined
115 by argument what, or all plots (if what=''). The plots made in the latter
116 case are specified by whatList. A canvas that is subdivided if necessary
117 is created before the plotting code is called."""
118 if what==
'' or what.upper()==
'ALL':
126 self.__class__.__dict__[code](self,w,*args)
128 self.__class__.__bases__[0].__dict__[code](self,w,*args)
133 ROOT.gPad.SaveAs(
'%s-%s-%s%s' % (self.
name,code,w,o))
147 print (
"ERROR: can't add labels unless we have an empty pad to use. Ignoring labels.")
151 c.SaveAs(
'%s-%s-%s%s' % (self.
name,code,what,o))
158 self.__class__.__dict__[code](self,what,*args)
160 self.__class__.__bases__[0].__dict__[code](self,what,*args)
164 c.SaveAs(
'%s-%s-%s%s' % (self.
name,code,what,o))
169 """StyleFactory is a helper class for assigning marker styles, line styles,
170 and colors in ROOT plots."""
172 markerSequence = [ 8, 21, 22, 23, 29, 4, 25, 26, 27, 28, 30, 2, 3, 6]
173 lineSequence = [ 1, 2, 3, 4]
174 colorSequence = [ 1, 2, 4, 6, 8]
176 def __init__(self,incMarker=True,incLine=True,incColor=True):
185 """Get next style cycling through markers, lines and colors as specified by
186 the flags in the constructor. Returns a triplet of (marker,line,color) styles."""
190 return (StyleFactory.markerSequence[self.
idMarker % len(StyleFactory.markerSequence)],
191 StyleFactory.lineSequence[self.
idLine % len(StyleFactory.lineSequence)],
192 StyleFactory.colorSequence[self.
idColor % len(StyleFactory.colorSequence)])
195 """Get next marker style."""
197 return StyleFactory.markerSequence[self.
idMarker % len(StyleFactory.markerSequence)]
200 """Get next line style."""
202 return StyleFactory.lineSequence[self.
idLine % len(StyleFactory.lineSequence)]
205 """Get next color."""
207 return StyleFactory.colorSequence[self.
idColor % len(StyleFactory.colorSequence)]
210 def drawAxisFrame(xmin,xmax,ymin,ymax,title='',xTitleOffset=None,yTitleOffset=None,doPlot=True,protectFrame=True):
211 frame = ROOT.TH2F(
'axisFrame',title,100,xmin,xmax,100,ymin,ymax)
212 frame.SetStats(
False)
213 if xTitleOffset
is not None:
214 frame.GetXaxis().SetTitleOffset(xTitleOffset)
215 if yTitleOffset
is not None:
216 frame.GetYaxis().SetTitleOffset(yTitleOffset)
225 """Draw a horizontal band of width +-ywidth. Nice colors are 19 and 33."""
226 b = ROOT.TH1F(
'band',
'band',1,xmin,xmax)
228 b.SetBinError(1,ywidth)
229 b.SetFillColor(color)
230 b.SetMarkerColor(color)
231 b.SetMarkerSize(0.01)
240 def drawText(x=0.74,y=0.87,dy=0.06,text='',font=62,color=1,align=11,linesep=';'):
241 """Draw a variable number of lines of text."""
245 t.SetTextColor(color)
246 t.SetTextAlign(align)
247 t.SetTextSize(dy/1.2)
248 for line
in text.split(linesep):
249 t.DrawLatex(x,y,line)
256 def drawLegend(x1,y1,x2,y2,legendList=[],fillColor=0,lineColor=0,textSize=None,protectLegend=True):
257 """Draw a legend with one or more entries. legendList is a list of lists,
258 where each inner list defines the object, text and option of a legend entry.
259 NOTE: Must store returned TLegend, otherwise legend will disappear!"""
260 nlines = len(legendList)
262 print (
"ERROR: drawLegend called w/o any legend entries")
267 l = ROOT.TLegend(x1,y1,x2,y2)
268 l.SetFillColor(fillColor)
269 l.SetLineColor(lineColor)
270 l.SetShadowColor(lineColor)
272 l.SetTextSize(textSize)
274 l.AddEntry(e[0],e[1],e[2])
285 st = h.GetListOfFunctions().FindObject(
'stats')
287 print (
'ERROR: No stats found - cannot move it')
289 st.SetTextColor(h.GetLineColor())
290 st.SetX1NDC(st.GetX1NDC()+dx)
291 st.SetY1NDC(st.GetY1NDC()+dy)
292 st.SetX2NDC(st.GetX2NDC()+xw
if xw!=0
else st.GetX2NDC()+dx)
293 st.SetY2NDC(st.GetY2NDC()+yw
if yw!=0
else st.GetY2NDC()+dy)
300 def atlasLabel(x,y,isPreliminary=False,color=1,offset=0.115,isForApproval=False,energy=8,customstring="",size=0.05):
301 if x
is None or y
is None:
302 print (
"Must set (x,y) position using --atlasx and --atlasy to add labels. No ATLAS labels created.")
304 offset = offset/0.05*size
309 l.SetTextColor(color)
310 l.DrawLatex(x,y,
"ATLAS")
316 p.SetTextColor(color)
318 if customstring !=
"":
319 p.DrawLatex(x+offset,y,customstring)
322 p.DrawLatex(x+offset,y,
"Preliminary")
325 p.DrawLatex(x+offset,y,
"Internal")
329 p.DrawLatex(x, y-(0.07/0.05*size),
"#sqrt{s} = %s TeV" % energy)
331 p.DrawLatex(x, y-(0.07/0.05*size),
"#sqrt{s} = %s GeV" % energy)
336 s = ROOT.TStyle(
'ATLAS',
'ATLAS Style V2.02')
340 s.SetFrameBorderMode(icol)
341 s.SetFrameFillColor(icol)
342 s.SetCanvasBorderMode(icol)
343 s.SetCanvasColor(icol)
344 s.SetPadBorderMode(icol)
350 s.SetPaperSize(20,26)
351 s.SetPadTopMargin(0.05)
352 s.SetPadRightMargin(0.05)
353 s.SetPadBottomMargin(0.16)
354 s.SetPadLeftMargin(0.16)
357 s.SetTitleXOffset(1.4)
358 s.SetTitleYOffset(1.4)
367 s.SetLabelFont(font,
"x")
368 s.SetTitleFont(font,
"x")
369 s.SetLabelFont(font,
"y")
370 s.SetTitleFont(font,
"y")
371 s.SetLabelFont(font,
"z")
372 s.SetTitleFont(font,
"z")
374 s.SetLabelSize(tsize,
"x")
375 s.SetTitleSize(tsize,
"x")
376 s.SetLabelSize(tsize,
"y")
377 s.SetTitleSize(tsize,
"y")
378 s.SetLabelSize(tsize,
"z")
379 s.SetTitleSize(tsize,
"z")
384 s.SetHistLineWidth(2)
385 s.SetLineStyleString(2,
"[12 12]")
391 s.SetEndErrorSize(0.)
413 print (
'\nApplying style %s (%s) ...\n' % (style.GetName(),style.GetTitle()))
414 ROOT.gROOT.SetStyle(style.GetName())
415 ROOT.gROOT.ForceStyle()