Not plotting zero bins in TH2 with negative entries

Hi,

I’m using the “COLZ” option to plot a TH2D that has both positive and negative entries. Many entries are also zero. I would like to plot only nonzero entries and have empty bins show up as white. This is the default behavior for histograms with only non-negative entries. I’m hoping there is an easy way to get this behavior also for histograms with some negative entries.

Messing around with color palettes and SetContour hasn’t gotten my anywhere because the histograms are such that I can’t assume much about the entries. In particular, they are not symmetric around zero. I also tried calling gPad->PaintBox() to manually paint empty regions white like I saw it done in THistPainter::PaintColorLevels(), but my calls to PaintBox don’t seem to do anything. My attempt at a function to “whiteout” empty bins for a histogram that was just plotted is attached. Perhaps someone can tell me what’s wrong with it.

I’m using ROOT 5.34. Thanks in advance!

//
Anders
whiteOut.cpp (648 Bytes)

Have you considered using Ttree? i think you just need an if statement like:

TH2D* Hh1;
.
.
.
{fChain->GetTree()->GetEntry(entry);
if(x=!0){
Hh1->Fill(x,y);}
Hh1->Draw();
return kTRUE;}

else way just try an if statement with
SetMarkerColor(kWhite);

Sincerely
Stylianos Nikas

Did you try COLZ0 ?

Stellos:
I’m afraid I don’t understand your solution. The marker color or fill method should have no impact as far as I’m aware.

couet:
Drawing with “COLZ0” yields the same result as drawing with “COLZ”. A minimal working example is shown below. I want bin 3 (the empty one) to appear white. Can this be done? Again, it happens automatically if I don’t put any begative entries in the histogram.

#include "TH2D.h"
#include "TCanvas.h"

void colorTest() {
	TH2D* hist = new TH2D("test", "test", 4, 0., 4., 1, 0., 1.);
	hist->Fill(0., 0., 2); //Bins 1-4 contain 2, 1, 0 and -1
	hist->Fill(1., 0., 1); //I want the empty bin to appear white
	hist->Fill(3., 0., -1);

	new TCanvas();
	hist->Draw("COLZ"); //Using COLZ0 doesn't change anything
}

The empty bins are not drawn only if zmin>=0. If zmin<0 an bin with content 0 might be not empty.

I understand the rationale for drawing bins with content == 0. For my particular application, however, I would like to not draw them. Is this possible?

The answer is “No”, regarding the way it is coded now in THistPainter.

Looking at THistPainter::PaintColorLevels(), it seems that the function iterates though each bin of the histogram and finds the color appropriate for the corresponding “pixel” of the pad. My idea with the whiteout function attached to the first post was to do more or less the same thing - Iterate though the histogram that was just drawn and re-paint the pixels corresponding to bins with content == 0 as white. However, for reasons that I do not understand, the function does nothing. Can you spot the error, or perhaps correct it so that it works as intended?

… not “pixels”… but bin

can I see it ?

Hi,

although I do not have a proper solution for your problem I can offer you a hack.
The attached macro creates a histogram that can “mask” out the zero boxes with
“almost” white. Example:

.L maskHist.C 
TH2D *foo = new TH2D("test","",5,0,1,5,0,1);
foo->Fill(0.,0.,-1.);
foo->Fill(0.5,0.5,1.);
foo->Draw("COL")
TH2D *bar = getZeroMask(foo);
bar->SetFillColor(TColor::GetColor(253,253,253));
bar->Draw("BOX same");

You may have to fiddle around a bit with the axis, as they seem to get partially
overdrawn by the draw-call of “bar”.

Cheers,
Jochen
maskHist.C (407 Bytes)

couet:
It is attached to the first post.

jkerdels:
Your hack did the trick! Simply redrawing the axes restores them. Here’s a working version of the “whiteout” function in case anyone else has this problem in the future.

void whiteout(TH2D* hist) {
	TH2D* copy = dynamic_cast<TH2D*>(hist->Clone());
	copy->Reset();
	copy->SetFillColor(TColor::GetColor(253,253,253));
	Int_t bin = 0;
	Double_t maxVal = hist->GetMaximum();
	for(Int_t i = 1; i <= hist->GetNbinsX(); ++i) {
		for(Int_t j = 1; j <= hist->GetNbinsY(); ++j) {
			bin = hist->GetBin(i, j);
			if(!hist->GetBinContent(bin)) copy->SetBinContent(bin, maxVal);
		}
	}
	copy->Draw("BOX SAME");
	hist->Draw("AXIS SAME");
}

//
Anders

Turns out that the histograms look fine when viewed in a TCanvas, but when saving the plots to pdf or eps, faint lines appear at the bin borders. I ended up hacking THistPainter::PaintColorLevels() to never paint empty bins at all by changing the line

if (z == 0 && (zmin >= 0 || Hoption.Logz)) continue;

to

if (z == 0) continue;

After recompiling ROOT (which took seconds since I only changed this one detail), it works the way I want. This is clearly not a general solution, though. An option to skip plotting empty bins would be a nice addition for future versions of ROOT.

//
Anders

This was fixed. Very likely you are using an old ROOT version.

Yes

Now implemented in the master:

Using the COL option with histograms having some negative bins; the empty bins
(containing 0) are drawn. In some cases one wants to not draw empty bins
(containing 0) of histograms having a negative minimum. The option 1, used with
the option COL, allows to do that.