def checklatex(texts, tag=""): """Check legend entries: colors, titles, ...""" # https://root.cern.ch/doc/master/classTPaveText.html LOG.header("checklegend" + tag.replace('_', ' ')) output = ensuredir('plots') fname = "%s/testLatex%s" % (output, tag) xdim = 500 ydim = 50 * (len(texts) + 2.5) print ">>> Canvas: %sx%s (nlines=%d)" % (xdim, ydim, len(texts)) canvas = TCanvas('canvas', 'canvas', xdim, int(ydim)) #pave1 = TPaveText(0.0,0,0.5,1,'ARC') #,'BR') pave2 = TPaveText(0.04, 0.04, 0.96, 0.96) #'ARC') #,'BR') #pave1.SetBorderSize(0) pave2.SetBorderSize(0) #pave1.SetTextAlign(12) pave2.SetTextAlign(12) #pave1.SetTextFont(42) pave2.SetTextFont(42) #pave1.SetFillColor(0) pave2.SetFillColor(0) #pave1.SetCornerRadius(0.05) #pave2.SetCornerRadius(0.05) #pave1.SetMargin(0.12) #pave1.SetTextSize(tsize) #pave2.Copy(pave1) for line in texts: latex = makelatex(line) print ">>> %r -> %r" % (line, latex) #pave1.AddText(line) pave2.AddText(latex) #pave1.Draw() pave2.Draw() canvas.SaveAs(fname + ".png") #canvas.SaveAs(fname+".pdf") canvas.Close()
def gettitle(sample,default=None,**kwargs): """Get title for some sample name.""" if sample in sample_titles: LOG.verb("SampleStyle.gettitle: Found title %s for %r!"%(sample_titles[sample],sample),kwargs,level=3) sample = sample_titles[sample] elif default: sample = default else: LOG.warning("SampleStyle.gettitle: Could not find title for %r! Returning %r..."%(sample,sample)) if kwargs.get('latex',False): sample = makelatex(sample) return sample
def setaxes(self, *args, **kwargs): """Make axis.""" verbosity = LOG.getverbosity(self, kwargs) hists = [] binning = [] for arg in args[:]: if hasattr(arg, 'GetXaxis'): hists.append(arg) elif isinstance(arg, Ratio): hists.append(arg.frame) elif isnumber(arg): binning.append(arg) if not hists: LOG.warning( "Plot.setaxes: No objects (TH1, TGraph, ...) given in args %s to set axis..." % (args)) return 0, 0, 100, 100 frame = hists[0] if len(binning) >= 2: xmin, xmax = binning[:2] else: xmin, xmax = frame.GetXaxis().GetXmin(), frame.GetXaxis().GetXmax() nbins = frame.GetXaxis().GetNbins() binwidth = float(xmax - xmin) / nbins xmin = kwargs.get('xmin', xmin) xmax = kwargs.get('xmax', xmax) ymin = kwargs.get('ymin', None) ymax = kwargs.get('ymax', None) ratiorange = kwargs.get('rrange', None) binlabels = kwargs.get('binlabels', None) intbins = kwargs.get('intbins', True) # allow integer binning logx = kwargs.get('logx', False) logy = kwargs.get('logy', False) ymargin = kwargs.get('ymargin', None) or ( 1.3 if logy else 1.2) # margin between hist maximum and plot's top logyrange = kwargs.get( 'logyrange', None) or 3 # log(y) range from hist maximum to ymin negativey = kwargs.get('negativey', True) # allow negative y values xtitle = kwargs.get('xtitle', frame.GetTitle()) ytitle = kwargs.get('ytitle', None) latex = kwargs.get('latex', True) # automatically format strings as LaTeX grid = kwargs.get('grid', False) ycenter = kwargs.get('center', False) nxdivisions = kwargs.get('nxdiv', 510) nydivisions = kwargs.get('nydiv', 510) main = kwargs.get('main', False) # main panel of ratio plot scale = 600. / min(gPad.GetWh() * gPad.GetHNDC(), gPad.GetWw() * gPad.GetWNDC()) xtitlesize = kwargs.get('xtitlesize', _tsize) * scale ytitlesize = kwargs.get('ytitlesize', _tsize) * scale xlabelsize = kwargs.get('xlabelsize', _lsize) * scale ylabelsize = kwargs.get('ylabelsize', _lsize) * scale ytitleoffset = kwargs.get('ytitleoffset', 1.0) * 1.26 / scale xtitleoffset = kwargs.get('xtitleoffset', 1.0) * 1.00 xlabeloffset = kwargs.get('xlabeloffset', 0.007) if main: xtitlesize = 0.0 xlabelsize = 0.0 if latex: xtitle = makelatex(xtitle) LOG.verb("Plot.setaxes: Binning (%s,%.1f,%.1f)" % (nbins, xmin, xmax), verbosity, 2) if ratiorange: ymin, ymax = 1 - ratiorange, 1 + ratiorange if intbins and nbins < 15 and int(xmin) == xmin and int( xmax) == xmax and binwidth == 1: LOG.verb( "Plot.setaxes: Setting integer binning for (%r,%s,%d,%d)!" % (xtitle, nbins, xmin, xmax), verbosity, 1) binlabels = [str(i) for i in range(int(xmin), int(xmax) + 1)] xlabelsize *= 1.6 xlabeloffset *= 0.88 * scale if logy: ylabelsize *= 1.08 if binlabels: nxdivisions = 15 # GET HIST MAX hmaxs = [] hmins = [0] if isinstance(frame, THStack): hmaxs.append(frame.GetMaximum()) #frame = frame.GetStack().Last() for hist in hists: hmaxs.append( getTGraphYRange(hist)[1] if isinstance(hist, TGraph) else hist.GetMaximum()) else: for hist in hists: ymin1, ymax1 = getTGraphYRange(hist) if isinstance( hist, TGraph) else hist.GetMinimum(), hist.GetMaximum() if negativey: hmins.append(ymin1) hmaxs.append(ymax1) if ymin == None: ymin = min(hmins) * (1.1 if ymin > 0 else 0.9) hmax = max(hmaxs) hmin = min(hmins) # SET AXES RANGES if ymin == None: ymin = 0 if logy: if not ymin or ymin <= 0: # avoid zero or negative ymin for log plots ymin = 10**(magnitude(hmax) - logyrange ) #max(0.1,10**(magnitude(ymax)-3)) LOG.verb( "Plot.setaxes: logy=%s, hmax=%6.6g, magnitude(hmax)=%s, logyrange=%s, ymin=%.6g" % (logy, hmax, magnitude(hmax), logyrange, ymin), verbosity, 2) if ymax == None: if hmax > ymin > 0: span = abs(log10(hmax / ymin)) * ymargin ymax = ymin * (10**span) LOG.verb( "Plot.setaxes: log10(hmax/ymin)=%6.6g, span=%6.6g, ymax=%.6g" % (log10(hmax / ymin), span, ymax), verbosity, 2) else: ymax = hmax * ymargin gPad.Update() gPad.SetLogy() elif ymax == None: ymax = hmax * ymargin if logx: if not xmin: xmin = 0.1 xmax *= 0.9999999999999 gPad.Update() gPad.SetLogx() if grid: gPad.SetGrid() frame.GetXaxis().SetRangeUser(xmin, xmax) frame.SetMinimum(ymin) frame.SetMaximum(ymax) if ytitle == None: #ytitle = "Events" if "multiplicity" in xtitle.lower(): ytitle = "Events" elif hmax < 1.: ytitle = "A.U." else: binwidth = frame.GetXaxis().GetBinWidth(0) binwidstr = ("%.3f" % binwidth).rstrip('0').rstrip('.') units = re.findall(r' \[(.+)\]', xtitle) #+ re.findall(r' (.+)',xtitle) if frame.GetXaxis().IsVariableBinSize(): if units: ytitle = "Events / " + units[-1] else: ytitle = "Events / bin size" elif units: if binwidth != 1: ytitle = "Events / %s %s" % (binwidstr, units[-1]) else: ytitle = "Events / " + units[-1] elif binwidth != 1: ytitle = "Events / " + binwidstr else: ytitle = "Events" LOG.verb( "Plot.setaxes: ytitle=%r, units=%s, binwidth=%s, binwidstr=%r" % (ytitle, units, binwidth, binwidstr), verbosity, 2) # alphanumerical bin labels if binlabels: if len(binlabels) < nbins: LOG.warning("Plot.setaxes: len(binlabels)=%d < %d=nbins" % (len(binlabels), nbins)) for i, binlabel in zip(range(1, nbins + 1), binlabels): frame.GetXaxis().SetBinLabel(i, binlabel) #frame.GetXaxis().LabelsOption('h') # X axis frame.GetXaxis().SetTitleSize(xtitlesize) frame.GetXaxis().SetTitleOffset(xtitleoffset) frame.GetXaxis().SetLabelSize(xlabelsize) frame.GetXaxis().SetLabelOffset(xlabeloffset) frame.GetXaxis().SetNdivisions(nxdivisions) frame.GetXaxis().SetTitle(xtitle) # Y axis if ymax >= 1e4: ylabelsize *= 0.95 if ycenter: frame.GetYaxis().CenterTitle(True) frame.GetYaxis().SetTitleSize(ytitlesize) frame.GetYaxis().SetTitleOffset(ytitleoffset) frame.GetYaxis().SetLabelSize(ylabelsize) frame.GetYaxis().SetNdivisions(nydivisions) frame.GetYaxis().SetTitle(ytitle) if verbosity >= 1: print ">>> Plot.setaxes: xtitle=%r, [hmin,hmax] = [%.6g,%.6g], [xmin,xmax] = [%.6g,%.6g], [ymin,ymax] = [%.6g,%.6g]" % ( xtitle, hmin, hmax, xmin, xmax, ymin, ymax) elif verbosity >= 2: print ">>> Plot.setaxes: frame=%s" % (frame) print ">>> Plot.setaxes: hists=%s" % (hists) print ">>> Plot.setaxes: [hmin,hmax] = [%.6g,%.6g], [xmin,xmax] = [%.6g,%.6g], [ymin,ymax] = [%.6g,%.6g]" % ( hmin, hmax, xmin, xmax, ymin, ymax) print ">>> Plot.setaxes: xtitlesize=%4.4g, xlabelsize=%4.4g, xtitleoffset=%4.4g, xtitle=%r" % ( xtitlesize, xlabelsize, xtitleoffset, xtitle) print ">>> Plot.setaxes: ytitlesize=%4.4g, ylabelsize=%4.4g, ytitleoffset=%4.4g, ytitle=%r" % ( ytitlesize, ylabelsize, ytitleoffset, ytitle) print ">>> Plot.setaxes: scale=%4.4g, nxdivisions=%s, nydivisions=%s, ymargin=%.3f, logyrange=%.3f" % ( scale, nxdivisions, nydivisions, ymargin, logyrange) if main: #if any(a!=None and a!=b for a, b in [(self.xmin,xmin),(self.xmax,xmax)]): # LOG.warning("Plot.setaxes: x axis range changed: [xmin,xmax] = [%6.6g,%6.6g] -> [%6.6g,%6.6g]"%( # self.xmin,self.xmax,xmin,xmax)) #if any(a!=None and a!=b for a, b in [(self.ymin,ymin),(self.ymax,ymax)]): # LOG.warning("Plot.setaxes: y axis range changed: [ymin,ymax] = [%6.6g,%6.6g] -> [%6.6g,%6.6g]"%( # self.ymin,self.ymax,ymin,ymax)) self.xmin, self.xmax = xmin, xmax self.ymin, self.ymax = ymin, ymax return xmin, xmax, ymin, ymax
def drawtext(self, *texts, **kwargs): """ Draw TLaTeX text in the corner. drawtext(str text) drawtext(str text, str text, ...) drawtext(list texts) Text position can be controlled in several ways drawlegend(text,position=position) where position is a string which can contain the horizontal position, e.g. 'left', 'center', 'right', 'L', 'C', or 'R' The position string can also contain the vertical position as e.g. 'top', 'middle', 'bottom', 'T', 'M', or 'B' Instead of the strings, the exact coordinates can be controlled with the keywords x and y: drawtext(x=0.2,y=0.8) These floats are normalized to the axis frame, ignoring the canvas margins: x=0 is the left, x=1 is the right, y=0 is the bottom and y=1 is the top side. Values less than 0, or larger than 1, will put the text outside the frame. """ verbosity = LOG.getverbosity(self, kwargs) position = kwargs.get('pos', 'topleft') position = kwargs.get('position', position) #.lower() tsize = kwargs.get('tsize', _lsize) # text size theight = kwargs.get('theight', None) or 1 bold = kwargs.get('bold', False) # bold text dolatex = kwargs.get('latex', False) # automatically format strings as LaTeX xuser = kwargs.get('x', None) # horizontal position yuser = kwargs.get('y', None) # vertical position align_user = kwargs.get('align', None) # text line panel = kwargs.get('panel', 1) # panel (top=1, bottom=2) texts = unwraplistargs(texts) if not any(t != "" for t in texts): return None # CHECK LOG.insist(self.canvas, "Canvas does not exist!") self.canvas.cd(panel) scale = 485. / min(gPad.GetWh() * gPad.GetHNDC(), gPad.GetWw() * gPad.GetWNDC()) tsize *= scale # text size # POSITION font = 62 if bold else 42 align = 13 position = position.replace('left', 'L').replace( 'center', 'C').replace('right', 'R').replace( #.lower() 'top', 'T').replace('middle', 'M').replace('bottom', 'B') if 'R' in position: x, align = 0.95, 30 # right if 'C' in position: x, align = 0.50, 20 # center else: x, align = 0.05, 10 # left if 'B' in position: y = 0.05 align += 1 # bottom if 'M' in position: y = 0.50 align += 2 # middle else: y = 0.95 align += 3 # top #x1 = float(re.findall(r"x=(\d\.\d+)",position)[0]) #y2 = float(re.findall(r"y=(\d\.\d+)",position)[0]); if xuser != None: x = xuser if yuser != None: y = yuser if align_user != None: align = align_user L, R = gPad.GetLeftMargin(), gPad.GetRightMargin() T, B = gPad.GetTopMargin(), gPad.GetBottomMargin() x = L + (1 - L - R) * x # convert frame to canvas coordinates y = B + (1 - T - B) * y # convert frame to canvas coordinates # LATEX latex = TLatex() latex.SetTextSize(tsize) latex.SetTextAlign(align) latex.SetTextFont(font) #latex.SetTextColor(kRed) latex.SetNDC(True) for i, line in enumerate(texts): if dolatex: line = makelatex(line) yline = y - i * theight * 1.2 * tsize latex.DrawLatex(x, yline, line) LOG.verb( "Plot.drawcornertext: i=%d, x=%d, y=%d, text=%r" % (i, x, yline, line), verbosity, 2) self.texts.append(latex) return latex