Setting bins of indentically 0 value to a specific color in a TH2 drawn with COLZ

ROOT Version: 6.32.06
Platform: AlmaLinux9.5
Compiler: GCC 14.2.0


Hi ROOTers,

Suppose I have a TH2 for which I have created a custom palette like so:

const int ncol = 50;
const int nstp = 3;
double red[nstp] = {0.,1.,1.};
double grn[nstp] = {0.,1.,0.};
double blu[nstp] = {1.,1.,0.};
double stp[nstp] = {0,2./27,1};
TColor::CreateGradientColorTable(nstp, stp, red, grn, blu, ncol);

The z-axis range will be from -5 to 25. Suppose also that I want bins with a value of exactly 0 to be black, and that the other values for bins that are not 0 can exceed either side of the z-scale by a large amount, and can also be very close to 0 without being identically 0. Is there a simple way to achieve this?

The best I have thought of is to use something like the solution suggested here by creating a second histogram with the same axis ranges, setting all of the new bins which correspond to the first histogram’s nonzero bins to some arbitrary positive value, and creating a new pallete which is transparent for all of the nonzero bins, and black for the 0 bins, then drawing with ("SAME COLZ"). Is there an easier way before I go to the trouble?

Thanks for any help!

I think the option you mention (a second histogram) is probably the best, if not only, option so far. The “CJUST” draw option (see the posts here and documentation here) might perhaps work if you could define a range of values for “zero”, but not for just one value (exactly zero).

Actually, I’m not sure the solution I suggested works… I don’t see a way to set the transparency to different values for different parts of the scale… Am I misreading the answer I linked?

I don’t know the code you have tried, but in any case, it seems to be complicated (at least the ways I tried), but I managed to get an example working (maybe there’s a simpler way):


void Pal2()
{   // for "black pixels"
  const Int_t nstp = 2;
  const Int_t ncol = 3;
  Double_t stp[nstp] = { 0.0000, 1.0000 };
  Double_t red[nstp] = { 0./255., 1./255. };
  Double_t grn[nstp] = { 0./255., 1./255. };
  Double_t blu[nstp] = { 0./255., 1./255. };
  static Int_t colors[ncol];
  static Bool_t initialized = kFALSE;
  if (!initialized) {
    Int_t FI = TColor::CreateGradientColorTable(nstp, stp, red, grn, blu, ncol);
    for (int i = 0; i < ncol; i++)
      colors[i] = FI + i;
    initialized = kTRUE;
    return;
  }
  gStyle->SetPalette(ncol, colors);
}

void Pal1()
{
  const int ncol = 50;
  const int nstp = 3;
  double red[nstp] = {0.,1.,1.};
  double grn[nstp] = {0.,1.,0.};
  double blu[nstp] = {1.,1.,0.};
  double stp[nstp] = {0,2./27,1};
  static Int_t colors[ncol];
  static Bool_t initialized = kFALSE;
  if (!initialized) {
    Int_t FI = TColor::CreateGradientColorTable(nstp, stp, red, grn, blu, ncol);
    for (int i = 0; i < ncol; i++)
      colors[i] = FI + i;
    initialized = kTRUE;
    return;
  }
  gStyle->SetPalette(ncol, colors);
}


void transp() {
  gStyle->SetCanvasPreferGL(true);
  TCanvas *c1 = new TCanvas("c1","c1",400,0,800,800);
  //c1->SetSupportGL(true);

  auto h = new TH2F("h"," ",5,0,5,5,5,10);
  auto hf = (TH2F*)h->Clone("hf");
  h->SetBit(TH1::kNoStats);
  hf->SetBit(TH1::kNoStats);

  for (int i=1; i<6; ++i) {
    for (int j=1; j<6; ++j) {
      float v = -10+(i+2)*j;
      if (v<-5) v = -5;
      h->SetBinContent(i,j,v);
    }
  }
  hf->SetBinContent(2,1,1);
  hf->SetMaximum(2);

  h->Draw("colz");
  TExec *ex1 = new TExec("ex1", "Pal1();");
  ex1->Draw("same");
  h->Draw("colz same");

  hf->Draw("col same0");
  TExec *ex2 = new TExec("ex2", "Pal2();");
  ex2->Draw();
  hf->Draw("col same0");

  c1->SaveAs("c1.png");
}

which has to be run in batch mode (at least on linux) or the transparency doesn’t work (and gStyle->SetCanvasPreferGL(true) might not be needed, not sure); e.g. root -l -b -q transp.C results in:

I use 2 colour palettes: the one you defined and another for the black bins; to use more than 1 palette, 2 TExecs are needed (taken from some older posts on this forum).
Note also that hf contains the pixels that you want to have in black. If you fill them with zero they are treated as empty, i.e. white, so I filled the bin with 1 and made sure that corresponds to black in its own palette; you would have to do something similar in your case.
Finally, note that hf (the “black” histogram) is drawn with col, not colz, otherwise its palette is superposed on top of h’s.