Beispiel #1
0
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()
Beispiel #2
0
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
Beispiel #3
0
    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
Beispiel #4
0
    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