Histogram contours hide grid if drawn with "SAME"

Dear ROOT experts,

I experience a strange issue when drawing multiple TH2F histograms with contours (draw option "CONT LIST") onto a canvas with grid lines:

  1. I create a canvas with grid lines.

  2. I draw a TH2F histogram via h->Draw("CONT LIST"); clone and manipulate it’s contour lines and draw them

  3. I draw another TH2F histogram via h->Draw("CONT LIST SAME"); clone and manipulate it’s contour lines and draw them

The strange effect is that the contour graphs of the second histogram (drawn with the SAME option) hide the grid lines, while the contour graphs of the first histogram don’t.

Here is a code snipped which reproduces this issue

void drawContours(Style_t style)
{
   gPad->Update();
   TObjArray* contours = (TObjArray*) gROOT->GetListOfSpecials()->FindObject("contours");
   if (!contours) {
      std::cout << "Error: no contours created" << std::endl;
      return;
   }
   if (contours->GetSize() > 1)
      std::cout << "Warning: more that 1 contour created" << std::endl;
   TList* list = (TList*)contours->First();
   if (!list) {
      std::cout << "Error: first contour is empty" << std::endl;
      return;
   }
   for (Int_t i = 0; i < list->GetSize(); ++i) {
      TGraph* graph = (TGraph*)list->At(i);
      if (!graph) continue;
      TGraph* clonedGraph = (TGraph*)graph->Clone();
      clonedGraph->SetLineStyle(style);
      clonedGraph->Draw("L");
   }
}

contourFill()
{
   gStyle->Reset();
   TCanvas *c = new TCanvas("c", "c", 1000, 500);
   c->SetGrid();

   TH2F* h = new TH2F("h", "h", 50, -5, 5, 50, -5, 5);
   h->FillRandom("gaus", 100000);
   h->SetContour(1, new Double_t(1));
   h->Draw("CONT LIST");
   drawContours(1);

   TH2F* h2 = new TH2F("h2", "h2", 50, -5, 5, 50, -5, 5);
   h2->FillRandom("gaus", 100000);
   h2->SetContour(1, new Double_t(10));
   h2->Draw("CONT LIST SAME");
   drawContours(2); // these contours hide the grid
}

How can I forbid the contour graphs to hide the grid lines?

Many thanks in advance,
Alexander Voigt

At the end of your macro, add:

// see: http://root.cern.ch/root/html/TPad.html#TPad:RedrawAxis
gPad->RedrawAxis(); // for "axes"
gPad->RedrawAxis("g"); // for "grid lines"

Thank you very much for you answer, Pepe.

But may I add another a question:

When I fill the graphs via clonedGraph->Draw("LF"); how can I make the filled areas transparent (as far as the fill style allows it)? For example if I set clonedGraph->SetFillStyle(1001); and clonedGraph->SetFillStyle(3003); the lower graph does not shine trough the upper graph. (I know that it is possible because the exclusion graph example in root.cern.ch/root/html/TGraphPainter.html does it.)

Here is a short example:

void drawContours(Style_t style, Style_t fillStyle)
{
   gPad->Update();
   TObjArray* contours = (TObjArray*) gROOT->GetListOfSpecials()->FindObject("contours");
   if (!contours) {
      std::cout << "Error: no contours created" << std::endl;
      return;
   }
   if (contours->GetSize() > 1)
      std::cout << "Warning: more that 1 contour created" << std::endl;
   TList* list = (TList*)contours->First();
   if (!list) {
      std::cout << "Error: first contour is empty" << std::endl;
      return;
   }
   for (Int_t i = 0; i < list->GetSize(); ++i) {
      TGraph* graph = (TGraph*)list->At(i);
      if (!graph) continue;
      TGraph* clonedGraph = (TGraph*)graph->Clone();
      clonedGraph->SetLineStyle(style);
      clonedGraph->SetFillStyle(fillStyle);
      clonedGraph->Draw("LF");
   }
}

contourFill2()
{
   gStyle->Reset();
   TCanvas *c = new TCanvas("c", "c", 1000, 500);
   c->SetGrid();

   TH2F* h = new TH2F("h", "h", 50, -5, 5, 50, -5, 5);
   h->FillRandom("gaus", 100000);
   h->SetContour(1, new Double_t(1));
   h->Draw("CONT LIST");
   drawContours(1, 1001);

   TH2F* h2 = new TH2F("h2", "h2", 50, -5, 5, 50, -5, 5);
   h2->FillRandom("gaus", 100000);
   h2->SetContour(1, new Double_t(1));
   h2->Draw("CONT LIST SAME");
   drawContours(2, 3003);
}

Try maybe:

// see: http://root.cern.ch/root/html/TAttFill.html
gStyle->SetHatchesSpacing(0.5);
gStyle->SetHatchesLineWidth(0.25);
// ...
drawContours(1, 3354);
// ...
drawContours(2, 3345);

Thank you, Pepe, for your answer, but this does not solve the issue. I probably did not explain the problem well.

Please consider this small script, which draws 2 filled contour graphs from a histogram:

void drawContours(Style_t lineStyle, Style_t fillStyle, Color_t color)
{
   gPad->Update();
   TObjArray* contours = (TObjArray*) gROOT->GetListOfSpecials()->FindObject("contours");
   if (!contours) {
      std::cout << "Error: no contours created" << std::endl;
      return;
   }
   if (contours->GetSize() > 1)
      std::cout << "Warning: more that 1 contour created" << std::endl;
   TList* list = (TList*)contours->First();
   if (!list) {
      std::cout << "Error: first contour is empty" << std::endl;
      return;
   }
   for (Int_t i = 0; i < list->GetSize(); ++i) {
      TGraph* graph = (TGraph*)list->At(i);
      if (!graph) continue;
      TGraph* clonedGraph = (TGraph*)graph->Clone();
      clonedGraph->SetLineStyle(lineStyle);
      clonedGraph->SetFillStyle(fillStyle);
      clonedGraph->SetFillColor(color);
      clonedGraph->Draw("LF");
   }
}

main()
{
   gStyle->Reset();
   TCanvas *c = new TCanvas("c", "c", 500, 500);
   c->SetGrid();

   gStyle->SetHatchesSpacing(0.5);
   gStyle->SetHatchesLineWidth(0.25);

   TH2F* h  = new TH2F("h" , "h" , 50, -5, 5, 50, -5, 5);
   TH2F* h2 = new TH2F("h2", "h2", 50, -5, 5, 50, -5, 5);
   TRandom* rand = new TRandom();
   for (int i = 0; i < 10000; ++i) {
      Float_t x = rand->Gaus();
      Float_t y = rand->Gaus();
      h->Fill(x, y);
      x = rand->Gaus();
      y = rand->Gaus();
      h2->Fill(x, y);
   }
   h->SetContour(1, new Double_t(1));
   h->Draw("CONT LIST");
   drawContours(1, 3354, kRed);

   h2->SetContour(1, new Double_t(3));
   h2->Draw("CONT LIST SAME");
   drawContours(2, 3345, kBlue);
}

You can see, that the red area (= filled contour graph from histogram h) does not shine through the blue area (= filled contour graph from histogram h2).

How can I let the red region shine through the blue region, just like demonstrated in the third picture in root.cern.ch/root/html/TGraphPainter.html . (I find it very strange that the contour graphs do not behave like this per default.)

Many thanks in advance,
Alexander

A brutal fix:

#include <iostream>

#include "TROOT.h"
#include "TStyle.h"
#include "TPad.h"
#include "TCanvas.h"
#include "TObjArray.h"
#include "TList.h"
#include "TH2.h"
#include "TGraph.h"
#include "TRandom3.h"

void drawContours(Style_t lineStyle, Style_t fillStyle, Color_t color)
{
  TObjArray *contours = (TObjArray*) gROOT->GetListOfSpecials()->FindObject("contours");
  if (!contours) {
    std::cout << "Error: no contours created" << std::endl;
    return;
  }
  if (contours->GetSize() > 1)
    std::cout << "Warning: more that 1 contour created" << std::endl;
  TList *list = (TList*)contours->First();
  if (!list) {
    std::cout << "Error: first contour is empty" << std::endl;
    return;
  }
  for (Int_t i = 0; i < list->GetSize(); ++i) {
    TGraph *graph = (TGraph*)list->At(i);
    if (!graph) continue;
    TGraph *clonedGraph = (TGraph*)graph->Clone();
    clonedGraph->SetLineStyle(lineStyle);
    clonedGraph->SetLineColor(color);
    clonedGraph->SetFillStyle(fillStyle);
    clonedGraph->SetFillColor(color);
    clonedGraph->Draw("F SAME");
    clonedGraph->Draw("L SAME");
  }
}

int contourFill() // don't call it "main" unless it's a standalone application
{
  gStyle->Reset();
  gROOT->SetStyle("Plain");
  gStyle->SetHatchesSpacing(1.0);
  gStyle->SetHatchesLineWidth(0.25);
  
  // see: http://root.cern.ch/root/html/TRandom3.html#TRandom3:SetSeed
  gRandom->SetSeed(0);
  
  TH2F *h  = new TH2F("h" , "h" , 50, -5, 5, 50, -5, 5);
  TH2F *h2 = new TH2F("h2", "h2", 50, -5, 5, 50, -5, 5);
  for (int i = 0; i < 10000; ++i) {
    Float_t x = gRandom->Gaus();
    Float_t y = gRandom->Gaus();
    h->Fill(x, y);
    x = gRandom->Gaus();
    y = gRandom->Gaus();
    h2->Fill(x, y);
  }
  
  TCanvas *c = new TCanvas("c", "c", 500, 500);
  c->SetGrid();
  
  TCanvas *c_tmp = new TCanvas("c_tmp", "c_tmp", 500, 500);
  
  h->SetContour(1, new Double_t(1));
  
#if 0 /* 0 or 1 */
  c->cd();
  h->Draw("CONT LIST"); // draw it in "c" (create "h" contours)
  gPad->Update(); // make sure it's really drawn
#else /* 0 or 1 */
  c->cd();
  h->Draw("AXIS"); // draw it in "c"
  gPad->Update(); // make sure it's really drawn
  c_tmp->cd();
  h->Draw("CONT LIST"); // draw it in "c_tmp" (create "h" contours)
  gPad->Update(); // make sure it's really drawn
#endif /* 0 or 1 */
  
  c->cd();
  drawContours(2, 3354, kRed); // draw "h" contours in "c"
  gPad->Update(); // make sure it's really drawn
  
  h2->SetContour(1, new Double_t(3));
  
  c_tmp->cd();
  h2->Draw("CONT LIST"); // draw it in "c_tmp" (create "h2" contours)
  gPad->Update(); // make sure it's really drawn
  
  delete c_tmp; // no longer needed
  
  c->cd();
  drawContours(2, 3345, kBlue); // draw "h2" contours in "c"
  gPad->Update(); // make sure it's really drawn
  
  c->cd();
  gPad->RedrawAxis();
  gPad->RedrawAxis("g");
  gPad->Update(); // make sure it's really drawn
  
  return 0;
}

Dear Pepe,

thanks a lot, this fixes the issue. I have to admit, your trick to draw the contours of the second histogram into a separate canvas is brillian!

Kind regards,
Alexander

Actually, if you look carefully, the code draws BOTH histograms (“h” and “h2”) in the “separate temporary canvas” and then, in both cases, only the “created contours” are drawn where you really want them to have (change “#if 0” into “#if 1” if you want to try the other behavior).
I took the idea of a “separate temporary canvas” from the example shown in the "LIST" option description: http://root.cern.ch/root/html/THistPainter.html#HP16a

Greetings from 2023.
It helped me with the same issue. Thank you.