You are here

How to reuse a color palette ?

Each time TColor::CreateGradientColorTable is called it tries to find new space for the new color palette. Therefore if an application tries to switch between several palettes, it will becomes slower and slower each time TColor::CreateGradientColorTable is called.

The right way to proceed is to define the palette(s) once, save them into integer arrays and use these arrays to swap from a palette to an other. The following macro shows how to proceed. Using this technique each loop's iteration takes the same time. Calling TColor::CreateGradientColorTable in the loop would make the macro very slow after a few iterations.

const Int_t NCont = 999;

Int_t define_palette() {
   const Int_t NRGBs = 3;

   Double_t stops[NRGBs] = { 0.00, 0.50, 1.00};
   Double_t red[NRGBs]   = { 0.90, 0.10, 1.00};
   Double_t green[NRGBs] = { 0.50, 1.00, 0.00};
   Double_t blue[NRGBs]  = { 1.00, 0.50, 0.00};

   Int_t ind = TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);

   gStyle->SetNumberContours(NCont);

   return ind;
}

void palette_reuse() {
   Int_t i, Niter = 50;
   Int_t pal[NCont];

   Int_t ind = define_palette();

   for (i = 0; i < NCont; i++) pal[i] = ind+i;

   for (i = 0; i < Niter; i++) {
      TStopwatch * stopwatch = new TStopwatch();
      stopwatch->Start();

      // Reuse the palette previously defined. With this function call each
      // iteration takes the same time. If instead we call directly
      // define_palette() each iteration becomes slower because it is more and
      // more difficult to find the space for each new palette of 999 elements.

      gStyle->SetPalette(NCont, pal); 

      TCanvas *c = new TCanvas();
      TH2D *h = new TH2D("h", "", 100, -3, 3, 100, 0, 1);
      h->FillRandom("gaus",100000);
      h->Draw("colz");
      c->SaveAs(TString::Format("pic%03d.png", i));
      delete h;
      delete c;

      cout << "Time for iteration #" << i << ": "<< fixed 
             << stopwatch->RealTime() << "s" <<endl;
   }
}