Home | News | Documentation | Download

TH2 colz obscures the top frame

When I draw a 2D histogram containing data in the uppermost bins with “col” or “colz” option, the top axis becomes obscured. This can be demonstrated with the following example code:

/**
 * Run with
 * root -l -q -b -n test.cpp+O
 */

#include <TCanvas.h>
#include <TH2D.h>
#include <TPad.h>
#include <TStyle.h>
#include <TLine.h>

using namespace std;

void test() {
  gStyle->SetOptStat(0);
  TCanvas * c = new TCanvas();
  TH2D * h = new TH2D("h", "", 2, 0, 2, 2, 0, 2);
  h->SetBinContent(1, 1, 1);
  h->SetBinContent(1, 2, 2);
  h->SetBinContent(2, 1, 3);
  h->Draw("colz");
  
//   gPad->RedrawAxis("");  //this doesn't help
//   h->Draw("sameaxis"); //neither this
  
//   TLine tl(0, 2, 2, 2);
//   tl.Draw(); //this does help
  
  c->SaveAs("c.png");
  c->SaveAs("c.pdf");
  delete c;
  delete h;
}

The result looks as follows:



As you can see the green area is drawn on top of the top frame. If you generate the pdf and zoom it, you can see that actually only half of the width of the line is covered, but it still doesn’t look good:

I tried adding gPad->RedrawAxis(""); or h->Draw(“sameaxis”); but it didn’t help. Finally I fix the issue by manually drawing TLine where the axis should be. The results look good, but I don’t know how to automatically get the limits of the axis if they were changed by SetRangeUser().

Am I doing something wrong? Is there some easier method to avoid this behaviour?

In fact RedrawAxis redraws the axis only, not the frame. Drawing the TLine is a good way to redraw this line.

To make your macro more general you can do:

{
   gStyle->SetOptStat(0);
   TCanvas * c = new TCanvas();
   TH2D * h = new TH2D("h", "", 2, 0, 2, 2, 0, 2);
   h->SetBinContent(1, 1, 1);
   h->SetBinContent(1, 2, 2);
   h->SetBinContent(2, 1, 3);
   h->Draw("colz");
   gPad->Update();
   TLine *tl = new TLine(gPad->GetUxmin(), gPad->GetUymax(),
                         gPad->GetUxmax(), gPad->GetUymax());
   tl->Draw(); //this does help
}

That way you can use SetRangeUser.

Yes, this works. Thank you!

Hi Olivier,

In the spirit of your recent improvements in TGaxis::SetExponentOffset :
The above is “a horrible solution” (*).
A good solution would be to solve the bug in drawing the “col” option that overwrites the borders, or simply to automatically redraw the borders as the final step of drawing the “col” option.
Hopefully you’re still in a bug-fixing mood…

(*) because:

  • the users will have run into this problem and have to find a solution over and over again
  • the users will have to repeat this code over and over again
  • the line doesn’t always align perfectly with the frame. In my current use case, it’s a bit too low and is a little bit too short on the right.

cheers,
Amnon

I do not see how this two things are related, but I can have another look…

As usual what appears a good solution at a first glance can be a bug in some other situations. Just think of the case somebody wants to draw a color plot on top of something else with no border … That’s just a thought and very likely there are other situations, I am not thinking about right now, where drawing automatically the border after the color boxes drawing can be considered as a bug. Therefore I think having the control with a special option might be a better solution than the automatic drawing you suggest.

I do not think bug fixing is a matter of mood…