Bug when using TExec for many palettes when compiling macro

I’m making some 2D event displays and have come across an issue when trying to use different palettes in the same canvas over many iterations.

I use TExec to apply different palettes to different pads within a single canvas, as described in multipalette.C. There are many events and I call TExec each time I plot a new event. Each event is plotted on a canvas using 2D histograms, which is then added to a pdf, so at the end all events are saved in a single pdf.

I find that the palette colours disappear after a few events. They then reappear but are mixed together incorrectly.

This only happens when compiling the macro. I’ve tried a non-compiled macro and it was fine, but I need to compile the macro as it is using several libraries and headers from elsewhere.

Here is a minimal example of my problem (remember it needs compiling):

// function to generate red palette
#include <TH2D.h>
#include <TCanvas.h>
#include <TStyle.h>
#include <TColor.h>
#include <TExec.h>

int main(int argc, char *argv[])
{
  // set up TExec commands to apply palettes to different pads
  // unable to define these in separate functions when compiling macro
  TExec* ex1 = new TExec("ex1", "static Int_t colors[100];\
   Double_t Red[2]    = { 0.20, 1.00};\
   Double_t Green[2]  = { 0.00, 0.00};\
   Double_t Blue[2]   = { 0.00, 0.00};\
   Double_t Length[2] = { 0.00, 1.00};\
   Int_t FI = TColor::CreateGradientColorTable(2,Length,Red,Green,Blue,100);\
   for (int i=0; i<100; i++) colors[i] = FI+i;\
   gStyle->SetPalette(100,colors);");
  TExec* ex2 = new TExec("ex2", "static Int_t colors[100];\
   Double_t Red[2]    = { 0.00, 0.00};\
   Double_t Green[2]  = { 1.00, 0.00};\
   Double_t Blue[2]   = { 1.00, 0.50};\
   Double_t Length[2] = { 0.00, 1.00};\
   Int_t FI = TColor::CreateGradientColorTable(2,Length,Red,Green,Blue,100);\
   for (int i=0; i<100; i++) colors[i] = FI+i;\
   gStyle->SetPalette(100,colors);");
  TExec* ex3 = new TExec("ex3", "static Int_t colors[100];\
   Double_t Red[2]    = { 0.00, 0.00};\
   Double_t Green[2]  = { 0.20, 1.00};\
   Double_t Blue[2]   = { 0.00, 0.00};\
   Double_t Length[2] = { 0.00, 1.00};\
   Int_t FI = TColor::CreateGradientColorTable(2,Length,Red,Green,Blue,100);\
   for (int i=0; i<100; i++) colors[i] = FI+i;\
   gStyle->SetPalette(100,colors);");

  // some random 2D histograms
  TH2D* h1 = new TH2D("h1","",4,0,4,4,0,4);
  TH2D* h2 = new TH2D("h2","",4,0,4,4,0,4);
  TH2D* h3 = new TH2D("h3","",4,0,4,4,0,4);
  TH2D* h4 = new TH2D("h4","",4,0,4,4,0,4);
  TH2D* h5 = new TH2D("h5","",4,0,4,4,0,4);
  TH2D* h6 = new TH2D("h6","",4,0,4,4,0,4);
  h1->Fill(2,2);
  h2->Fill(1,3);
  h3->Fill(1,3);
  h4->Fill(1,0);
  h5->Fill(2,3);
  h6->Fill(4,3);

  // generate canvas with multiple pads
  TCanvas* c1 = new TCanvas();
  c1->Divide(2,3);
  // iterate through plot code and save each plot to same pdf
  for (Int_t i=0; i<100; i++)
  {
    c1->cd(1);
    h1->Draw("a");
    ex1->Draw();
    h1->Draw("colz same");
    gPad->Update();
    c1->cd(2);
    h2->Draw("a");
    ex1->Draw();
    h2->Draw("colz same");
    gPad->Update();
    c1->cd(3);
    h3->Draw("a");
    ex2->Draw();
    h3->Draw("colz same");
    gPad->Update();
    c1->cd(4);
    h4->Draw("a");
    ex2->Draw();
    h4->Draw("colz same");
    gPad->Update();
    c1->cd(5);
    h5->Draw("a");
    ex3->Draw();
    h5->Draw("colz same");
    gPad->Update();
    c1->cd(6);
    h6->Draw("a");
    ex3->Draw();
    h6->Draw("colz same");
    gPad->Update();
    c1->Print("plots.pdf(");
  }
  c1->Print("plots.pdf]");

  return 0;
}

(sorry, new user so can’t just link the file).

The example outputs the file plots.pdf. You can see in plots.pdf that the colour palettes from the histograms disappear after page 27, although the histograms are still filled with data.

Things work fine if I don’t use TExec and stick with the default palette, but using different palettes for the histograms would make things much clearer in the display.

I’ve also tried saving the canvases to a root file but the same problem occurs.

Any help on this would be much appreciated.

This is with ROOT 6.26/10 on centOS 8 with gcc 8.5.0. Also tested on macOS ARM64 with ROOT 6.26/10 and clang 14 compiler with the same result.

Welcome to the ROOT forum.
I will check asap

With your code you create a new palette each time TExec is instentiated. You should create your palettes once otherwise you exhaust the colors memory after a while. The following example using precreated palete works fine:

void hake()
{
  // set up TExec commands to apply palettes to different pads
  // unable to define these in separate functions when compiling macro
  TExec* ex1 = new TExec("ex1", "gStyle->SetPalette(kRainBow);");
  TExec* ex2 = new TExec("ex2", "gStyle->SetPalette(kBird);");
  TExec* ex3 = new TExec("ex3", "gStyle->SetPalette(kDeepSea);");

  // some random 2D histograms
  TH2D* h1 = new TH2D("h1","",4,0,4,4,0,4);
  TH2D* h2 = new TH2D("h2","",4,0,4,4,0,4);
  TH2D* h3 = new TH2D("h3","",4,0,4,4,0,4);
  TH2D* h4 = new TH2D("h4","",4,0,4,4,0,4);
  TH2D* h5 = new TH2D("h5","",4,0,4,4,0,4);
  TH2D* h6 = new TH2D("h6","",4,0,4,4,0,4);
  h1->Fill(2,2);
  h2->Fill(1,3);
  h3->Fill(1,3);
  h4->Fill(1,0);
  h5->Fill(2,3);
  h6->Fill(4,3);

  // generate canvas with multiple pads
  TCanvas* c1 = new TCanvas();
  c1->Divide(2,3);
  // iterate through plot code and save each plot to same pdf
  for (Int_t i=0; i<100; i++)
  {
    c1->cd(1);
    h1->Draw("a");
    ex1->Draw();
    h1->Draw("colz same");
    gPad->Update();
    c1->cd(2);
    h2->Draw("a");
    ex1->Draw();
    h2->Draw("colz same");
    gPad->Update();
    c1->cd(3);
    h3->Draw("a");
    ex2->Draw();
    h3->Draw("colz same");
    gPad->Update();
    c1->cd(4);
    h4->Draw("a");
    ex2->Draw();
    h4->Draw("colz same");
    gPad->Update();
    c1->cd(5);
    h5->Draw("a");
    ex3->Draw();
    h5->Draw("colz same");
    gPad->Update();
    c1->cd(6);
    h6->Draw("a");
    ex3->Draw();
    h6->Draw("colz same");
    gPad->Update();
    c1->Print("plots.pdf(");
  }
  c1->Print("plots.pdf]");

}

Ah ok. That makes total sense. I’ll try that and see if it works out. Thank you!

Is there any way to create a custom palette outside of the TExec function and use it in the function? I would like to use my own palette rather than the predefined ones but I’m having issues.

I tried this at the start of my example code:

  static Int_t blues[100], reds[100];
  Double_t Red[2]    = { 0.00, 0.00};
  Double_t Green[2]  = { 1.00, 0.00};
  Double_t Blue[2]   = { 1.00, 0.50};
  Double_t Red2[2]    = { 0.20, 1.00};
  Double_t Green2[2]  = { 0.00, 0.00};
  Double_t Blue2[2]   = { 0.00, 0.00};
  Double_t Length[2] = { 0.00, 1.00};
  Int_t FI = TColor::CreateGradientColorTable(2,Length,Red,Green,Blue,100);
  for (int i=0; i<100; i++) blues[i] = FI+i;
  FI = TColor::CreateGradientColorTable(2,Length,Red2,Green2,Blue2,100);
  for (int i=0; i<100; i++) reds[i] = FI+i;
  // command to create palette for energy plots
  TExec *ex1 = new TExec("ex1","gStyle->SetPalette(100,reds);");
  // command to create palette for hit time plots
  TExec *ex2 = new TExec("ex2","gStyle->SetPalette(100,blues);");
  ...

but that results in errors saying reds and blues are undeclared identifiers when executing.

I see you would like to define your own palette, and assign it an index to access it later on. That’s done for the predefined palettes, but I am not sure that’s foreseen for the user-defined palettes. I need to check. If it is not foressen an extension will be needed.

Right now only the predefined palettes can be accessed by number as you can see in TColor::SetPalette. A special data structure allows us to reuse them once they have been defined. As you want to define own own "predefined palettes’ I guess one way will be to overwrite the existing predefined palettes.

Ok I will try that. Thanks.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.