Legend drawn over by axis

I have a TStack on top of which I want to draw some points with errors bars (TH1F) and then draw a TLegend.

The stack, legend, and data hist all get made a head of time and are returned other functions. Then I create a new canvas and draw each of them in turn:

PyROOT:

canvas = ROOT.TCanvas('can')
stack.Draw('hist')
fake_data_hist.Draw('sameAEPZ')
legend.AddEntry(fake_data_hist, '100 pb^{-1} \"data\"', 'LP')
legend.Draw()
canvas.Update()
canvas.SaveAs('%s.eps' % 'fake_data')
canvas.SaveAs('%s.png' % 'fake_data')

But, unforunately the legend is drawn over by the axis. I am certain that the legend’s fill style is solid and not hollow. You can also tell by the tick marks, that the axis is indeed drawn over the legend labels. See attached figure.

I’ve tried to insert a legend.Pop() command before or after the Draw, with no effect. If I do not Draw the fake_data_hist and only draw the stack, then there is no problem. Any ideas what is wrong? Thanks the help.


With the following macro the legend background is solid… nothing special is done. Do you have a small macro showing the problem ?

{
   TCanvas *c1 = new TCanvas("c1","c1",600,500);
   gStyle->SetOptStat(0);

   TH1F *h1 = new TH1F("h1","TLegend Example",200,-10,10);
   h1->FillRandom("gaus",30000);
   h1->SetFillColor(kGreen);
   h1->SetFillStyle(3003);
   h1->Draw();

   TF1 *f1=new TF1("f1","1000*TMath::Abs(sin(x)/x)",-10,10);
   f1->SetLineColor(kBlue);
   f1->SetLineWidth(4);
   f1->Draw("same");

   const Int_t n = 20;
   Double_t x[n], y[n], ex[n], ey[n];
   for (Int_t i=0;i<n;i++) {
      x[i]  = i*0.1;
      y[i]  = 1000*sin(x[i]+0.2);
      x[i]  = 17.8*x[i]-8.9;
      ex[i] = 1.0;
      ey[i] = 10.*i;
   }
   TGraphErrors *gr = new TGraphErrors(n,x,y,ex,ey);
   gr->SetLineColor(kRed);
   gr->SetLineWidth(2);
   gr->SetMarkerStyle(21);
   gr->SetMarkerSize(1.5);
   gr->SetMarkerColor(7);
   gr->Draw("P");



   leg = new TLegend(0.1,0.7,0.48,0.9);
   leg->SetHeader("The Legend Title");
   leg->AddEntry(h1,"Histogram filled with random numbers","f");
   leg->AddEntry("f1","Function abs(#frac{sin(x)}{x})","l");
   leg->AddEntry(gr,"Graph with error bars","lp");
   leg->Draw();

   return c1;
}

In my real script, I collect the histograms from several root files, and then format them in functions. But to help you debug, I have created a simplified script that creates histograms at random and gives the same behavior.

I include a rootlogon.py file, and I believe I’ve found that the lines

ROOT.gStyle.SetPadTickX(1)
ROOT.gStyle.SetPadTickY(1)

are the ones causing the trouble. Also, note that if I comment out the fake_data_hist.Draw call, the problem goes away. Attached are my script, my rootlogon.py, and the output figure.

I’ve also had a problem with pad ticks before when I have string bin labels. For some reason, setting the ticks on puts the bin labels on both sides of the plot. See attached.

Finally, note that if you import my rootlogon.py, something is causing the white histogram to be drawn as light blue.



rootlogon.py (2 KB)
plot_fake_data.py (1.9 KB)

Ok, that’s python … I am not using it usually. Give me a bit of time.

Is there something missing ? with your script I get:

pcphsft55> python plot_fake_data.py
Traceback (most recent call last):
  File "plot_fake_data.py", line 7, in ?
    import MetaROOT
ImportError: No module named MetaROOT
pcphsft55>

Yes, I appologize. I sent you the version of the script where my histograms are drawn by another module and returned.

I have made a simplified version of the script that, generates random histograms, so you don’t need my data or other modules. It is attached.

I see the bug, that the legend is drawn over by the axis in ROOT 5.22, but if I switch to ROOT 5.20, the problem goes away. Could you confirm?

For the ease of reading it on the forum, the script is also here:

#!/usr/bin/env python

#------------------------------------------------------------------------------

import sys
if not sys.argv.count('-i') and not sys.argv.count('-b'):
    sys.argv.append('-b')
import ROOT
#import rootlogon
ROOT.gStyle.SetPadTickX(1)
ROOT.gStyle.SetPadTickY(1)

#----------------------------------------------
# create some random histograms
#----------------------------------------------
rand2 = ROOT.TRandom()
hists = []
for i in xrange(4):
    h = ROOT.TH1F('h%s' % i, '', 40, 0., 200.)
    for j in xrange(100):
        h.Fill(rand2.Gaus(80, 30), rand2.Poisson(6-i))
    hists.append(h)
    
#----------------------------------------------------------
# create stack and legend
#----------------------------------------------------------
stack = ROOT.THStack('fake_data_stack', '100 pb^{-1}')
for i, h in enumerate(hists):
    h.SetFillColor(i)
    h.SetStats(0)
    stack.Add(h)

legend = ROOT.TLegend(0.7, 0.6, 0.99, 0.99)
for i, h in enumerate(hists):
    legend.AddEntry(h, str(i), 'F')
    
#----------------------------------------------------------
# create data points by drawing randomly from sum of stack
#----------------------------------------------------------
nbins = hists[0].GetNbinsX()
fake_data_hist = ROOT.TH1F('fake_data_hist', '', 40, 0., 200.)
fake_data_hist.SetStats(0)
rand = ROOT.TRandom()
for i in xrange(nbins):
    y = 0.0
    for h in hists:
        y += h.GetBinContent(i+1)
    fake_data_hist.Fill(hists[0].GetBinCenter(i+1), rand.Poisson(y))

#----------------------------------------------------------
# draw and save
#----------------------------------------------------------
canvas = ROOT.TCanvas('can')
stack.Draw('hist')
fake_data_hist.Draw('sameAEPZ')
legend.AddEntry(fake_data_hist, '100 pb^{-1} \"data\"', 'LP')
legend.Draw()
canvas.Update()
canvas.SaveAs('%s.eps' % 'fake_data')
canvas.SaveAs('%s.png' % 'fake_data')

plot_fake_data_simplified.py (1.85 KB)

fake_data_hist->Draw(“same E”);
redraws the ticks on top of the legend. I have not find a solution yet except putting the legend away from the axis.

Could you confirm that this behavior does not happen in 5.20?

I have not checked that yet. But it might be an axis redrawing added to redisplay correctly the axis when the option same is used. So, going backward might not be possible… I do not know … I need to check.
Is it a big deal for you to move the Legend ?

Having the legend in the top right, for many plots is best such that it obscures as little as possible. If there is something that changed between 5.20 and 5.22 that could be fixed, that would be nice.

In fact this effect was introduced by this fix:
root.cern.ch/viewvc?view=rev&revision=25536
But If I reverse it, the problem it is fixing is reintroduced.
A fix applying for both problem should be found.

This problem is now fixed in the SVN trunk.