Reverse log axis in TH2F

Please provide the following information:


ROOT Version : 6.12/02
Platform : CentOS 7.3 on lxplus7
compiler : gcc6.2


Dear co-rooters,

I am trying to invert the y-axis on a TH2F and at the same time to set it to log.
To do that I have the following macro

#include "TROOT.h"
#include "TH2.h"
#include "TMath.h"
#include "TRandom.h"
#include "TString.h"
#include "TRandom.h"
#include "TGaxis.h"
#include "TPad.h"
#include "TCanvas.h"

void ReverseYAxis (TH2 *h, bool logAxis)
{
   // Remove the current axis
   h->GetYaxis()->SetLabelOffset(999);
   h->GetYaxis()->SetTickLength(0);

   // Redraw the new axis
   gPad->Update();
   TGaxis *newaxis = new TGaxis(gPad->GetUxmin(),
                                gPad->GetUymax(),
                                gPad->GetUxmin()-0.001,
                                gPad->GetUymin(),
                                h->GetYaxis()->GetXmin(),
                                h->GetYaxis()->GetXmax(),
                                510,"+");
   //newaxis->SetLabelOffset(-0.03);
   if (logAxis)
   		gPad->SetLogy(1);
   newaxis->Draw();
}

void test ()
{
   TH2F *hpxpy  = new TH2F("hpxpy","py vs px",40,-4,4,400,1,1000);
   Float_t px, py;
   TRandom r;
   for (Int_t i = 0; i < 25000; i++) {
      r.Rannor(px,py);
      hpxpy->Fill(px,py);
   }
   TCanvas *c1 = new TCanvas("c1");
   hpxpy->Draw("colz");

   ReverseYAxis(hpxpy, 1);
}

The problem is that although the axis is set to log and is indeed inverted, the axis labels are not in logarithmic.
Any idea why and how to solve it?

A sample output id the following

https://imgur.com/8smTli4

You need to add the option “G” in the TGaxis option.

Thank you very much for your reply!
The thing is that I don’t necessarily need to always have logarithmic axis, that is why I used a boolean variable.

Yes but the TGaxis class is the painter for axis. it works via the option only.
Keep the boolean an make and change the string option accordingly .

I changed the function to

void ReverseYAxis (TH2 *h, bool logAxis)
{
   // Remove the current axis
   h->GetYaxis()->SetLabelOffset(999);
   h->GetYaxis()->SetTickLength(0);

	TString draw_option;
	if (logAxis)  draw_option = "G";
	else          draw_option = "+";
	
   // Redraw the new axis
   gPad->Update();
   TGaxis *newaxis = new TGaxis(gPad->GetUxmin(),
                                gPad->GetUymax(),
                                gPad->GetUxmin()-0.001,
                                gPad->GetUymin(),
                                h->GetYaxis()->GetXmin(),
                                h->GetYaxis()->GetXmax(),
                                510, draw_option);
   newaxis->SetLabelOffset(-0.03);
   newaxis->Draw();
}

and I am calling it via

ReverseYAxis(histo, 1);

but the axis doesn’t seem to change…

Any idea?

Seems ok for me:

$ root
   -------------------------------------------------------------------
  | Welcome to ROOT 6.13/03                       http://root.cern.ch |
  |                                      (c) 1995-2017, The ROOT Team |
  | Built for macosx64                                                |
  | From heads/master@v6-13-02-705-g4a2dbe2795, Apr 26 2018, 10:45:03 |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'        |
   -------------------------------------------------------------------

root [0] TH2D *h2 = new TH2D("h2","h2",10, 0.1, 1000, 10, 0.1, 1000)
(TH2D *) 0x7fa31b9ffc00
root [1] h2->Draw()
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
root [2] .x ReverseYAxis.C(h2, true);

Hmmm…

The problem is that although the axis is in log the distribution in the Y-axis is not…

https://imgur.com/gWNDnpK

Yes this is purely graphics … just drawing an extra reverse graphical axis will not change the way the distribution is drawn. You will need to make a temporary histogram inverting the distribution and draw that one instead of the original one. I know this is painful but ROOT was originally designed for HEP where axis are most of the time drawn bottom up.

There is a workaround but I am not sure if it’s the most efficient but it works…

void ReverseYAxis (TH2 *h, bool logAxis)
{
   // Remove the current axis
   h->GetYaxis()->SetLabelOffset(999);
   h->GetYaxis()->SetTickLength(0);

	TString draw_option;
	if (logAxis)  draw_option = "G";
	else          draw_option = "+";
	
   // Redraw the new axis
   gPad->Update();
   TGaxis *newaxis = new TGaxis(gPad->GetUxmin(),
                                gPad->GetUymax(),
                                gPad->GetUxmin()-0.001,
                                gPad->GetUymin(),
                                h->GetYaxis()->GetXmin(),
                                h->GetYaxis()->GetXmax(),
                                510, draw_option);
   newaxis->SetLabelOffset(1);
   
   if (logAxis)
   		gPad->SetLogy(1);
   
   newaxis->Draw();
}

Is there a more efficient or elegant way?

No it does not work… Your bin are not invited along the Y axis …

I don’t understand why you are saying that…

To me it seems that it works.

https://imgur.com/ujVKxCH

I did it by adding the following lines

if (logAxis)
    gPad->SetLogy(1);

When you create your histogram the Y axis goes bottom up from ymin to ymax. xmax is on top and ymin on the bottom of the plot. The bins are ordered this way on the Y axis. If you invert the Y axis, the bins should be also inverted (he top left bin should be drawn bottom left and vice versa) otherwise the value you see on the Y axis will not correspond to the correct bin.

In my case I used SetBinContent() to take into account the inverse of the axis since the reverseAxis() function is a graphical inversion, unless there is something that I miss.

So the bin contents are correct and are insensitive to inverting or no the axis.

Am I missing something?

Ah ok … So you do the bin inversion yourself already. It was not clear in the previous posts That’s fine in that case.