Home | News | Documentation | Download

Change the z-axis scale of log-scaled TH2s

Hi,

when I set the SetLogz() for a canvas with a TH2, I noticed the minimum of the z-axis of the histogram can go much lower than needed. This is pretty bad as it shrinks (from below) the possible color range for the bins. So I wrote a small function that takes a histogram, scans over all bins and finds the one with min bin content (zero content does not count). I’m aware about the GetMinimum() function, but it accounts for non-filled bins and returns 0 in most of my cases. Here is the function:

Double_t getNextToMinimumBinContent(TH2* histo)
{
        Double_t tempMin = 999.;
        if (histo)
        {
                for (Int_t binx = 0; binx<=histo->GetNbinsX(); binx++)
                {
                        for (Int_t biny = 0; biny<=histo->GetNbinsY(); biny++)
                        {
                                if (histo->GetBinContent(binx, biny) <= tempMin && histo->GetBinContent(binx, biny) > 1e-50)
                                        tempMin = histo->GetBinContent(binx, biny);
                        }
                }
        }
        return tempMin;
}

Its usage is trivial:

some_2D_histogram->SetMinimum(getNextToMinimumBinContent(some_2D_histogram));

I think it’d be great if this was the default behaviour.

Do you have some reproducer showing this effect ?

Sure Olivier, here is the reproducer:

void zAxisInLogScale_Reproducer()
{
        TCanvas* canv = new TCanvas("canv", "My canvas", 0, 0, 800, 600);
        canv->SetRightMargin(0.18);
        TH2F* hist1 = new TH2F("hist1", "hist 1;X;Y;Z", 50, 0., 50., 50, 0., 50.);
        for (Int_t i=1; i<=hist1->GetNbinsX(); i++)
                hist1->Fill(i, i, i);
        hist1->Draw("colz");
        canv->SetLogz();
        return;
}

Clearly, all the bins are filled with values >=1. But the z-axis is well below this minimum value (it goes down to 0.05), restricting the colour palette to its upper ~half:

Not at all … Only the diagonale is filled all the rest is 0. Therefore for the Z scale in log scale a minimum value >0 has to be set. Do 'hist1->SetMinimum(1);`an the whole palette will be used.

hist1->SetMinimum(hist1->GetMinimum(0.)); // black magic
1 Like

Yes, and I use my function to figure out what new minimum I should use. It’s 1 for this case clearly, but sometimes it’s not that easy to figure out. Anyway, Wile_E_Coyote suggested a better solution below.

This does exactly what I wanted. I wasn’t aware I could feed the GetMinimum() some parameter. I guess I kind of reimplemented that in my function :man_facepalming:

Yes it is more general and I should have proposed you this solution right away. But anyway it is the same idea. Your histogram is full of 0 and that does not work in log scale.