How to set color with `gStyle->SetPalette` for first bin and last bin? may be bugs


_ROOT Version:6.33.01
_Platform:Mac os 14.5


Hi all,
I’ve try to set Palette color with below.

  const int n = 6;
  Int_t MyPalette[n];
  Double_t Red[]    = {0.8, 1.0, 1.0, 0.0, 1.0, 1.0};
  Double_t Green[]  = {0.8, 0.0, 0.5, 1.0, 0.0, 0.0};
  Double_t Blue[]   = {0.8, 1.0, 0.0, 0.0, 0.0, 0.0};
  Double_t Length[] = {0.0, 1./6., 2./6., 3./6., 4./6., 5./6.};
  Int_t FI = TColor::CreateGradientColorTable(n, Length, Red, Green, Blue, n);
  for (int i = 0; i < n; i++)
    MyPalette[i] = FI + i;
  gStyle->SetPalette(n, MyPalette);  // NOLINT
  gStyle->SetNumberContours(n);

it seems the first bin is yellow, the rgb is not set by my color array.
How can I set the first bin color of z axis?

Length should go from 0 to 1, e.g.

 Double_t Length[] = {0.0, 1.2/6., 2.4/6., 3.6/6., 4.8/6., 1.};
1 Like

after set length from 0->1

  const int n = 6;
  Int_t MyPalette[n];  // NOLINT
  Double_t Red[]    = {0.8, 1.0, 1.0, 0.0, 0.0, 1.0};  // NOLINT
  Double_t Green[]  = {0.8, 0.0, 0.5, 0.0, 1.0, 0.0};  // NOLINT
  Double_t Blue[]   = {0.8, 1.0, 0.0, 1.0, 0.0, 0.0};  // NOLINT
  Double_t Length[] = {0.0, 1.2/6., 2.4/6., 3.6/6., 4.8/6., 1.};  // NOLINT
  Int_t FI = TColor::CreateGradientColorTable(n, Length, Red, Green, Blue, n);  // NOLINT
  for (int i = 0; i < n; i++)
    MyPalette[i] = FI + i;
  gStyle->SetPalette(n, MyPalette);  // NOLINT
  gStyle->SetNumberContours(n);

截屏2024-05-25 12.49.37

the last bin is set (1,0,0) but showing not red, why?
I want the last bin to be Red

Without the rest of the code and data I don’t know, but one guess can be that the bin contents don’t reach the maximum you are probably setting somewhere (6000).

here is an example:


#include <TStyle.h>
#include <TFile.h>
#include <TH2F.h>

void p3_draw() {
 
  const int n = 6;
  Int_t MyPalette[n];
  Double_t Red[]    = {0.8, 1.0, 1.0, 0.0, 0.0, 1.0};  // NOLINT
  Double_t Green[]  = {0.8, 0.0, 0.5, 0.0, 1.0, 0.0};  // NOLINT
  Double_t Blue[]   = {0.8, 1.0, 0.0, 1.0, 0.0, 0.0};  // NOLINT
  Double_t Length[] = {0.0, 1.2/6., 2.4/6., 3.6/6., 4.8/6., 1.};  // NOLINT
  Int_t FI = TColor::CreateGradientColorTable(n, Length, Red, Green, Blue, n);  // NOLINT
  for (int i = 0; i < n; i++)
    MyPalette[i] = FI + i;
  gStyle->SetPalette(n, MyPalette); 
  gStyle->SetNumberContours(n);
  gStyle->SetOptStat(0);
  TH2F* h2 = new TH2F("h2", "skymap", 100, -180, 180, 100, -90, 90);
  h2->Fill(0., 0., 100.0);
  h2->Fill(10, 100, -9100);
  h2->Fill(20, -100, 10000);
  h2->Fill(-20, 30.0, 6000);
  h2->Fill(-60., 0., 1000);
  h2->GetZaxis()->SetRangeUser(0, 6000);
  h2->Draw("colz");
}

截屏2024-05-25 13.38.06

I need the last been to be color red.
comment SetRangeUser(0, 6000); do not change the color.

Create a text file (e.g. “mycolours.txt”) with the RGB values (one colour per line, R G B separated by space) and use TColor::CreateColorTableFromFile

#include <TStyle.h>
#include <TFile.h>
#include <TH2F.h>

void p3_draw() {
 
  const int n = 6;
  Int_t MyPalette[n];

  Int_t FI = TColor::CreateColorTableFromFile("mycolours.txt");

  for (int i = 0; i < n; i++)
    MyPalette[i] = FI + i;
  gStyle->SetPalette(n, MyPalette); 
  gStyle->SetNumberContours(n);
  gStyle->SetOptStat(0);
  TH2F* h2 = new TH2F("h2", "skymap", 100, -180, 180, 100, -90, 90);
  h2->Fill(0., 0., 100.0);
  h2->Fill(10, 100, -9100);
  h2->Fill(20, -100, 10000);
  h2->Fill(-20, 30.0, 6000);
  h2->Fill(-60., 0., 1000);
  h2->GetZaxis()->SetRangeUser(0, 6000);
  h2->Draw("colz");
}
$  cat mycolours.txt
0.8 0.8 0.8
1.0 0.0 1.0
1.0 0.5 0.0
0.0 0.0 1.0
0.0 1.0 0.0
1.0 0.0 0.0

It works thanks.

So is that an error of LENGTH parameter?

I think it’s the method used.
CreateGradientColorTable() does some interpolation between points (the Documentation says “The table is constructed by tracing lines between the given points in RGB space…”), and looks like it works ok when you have many colours (since the last “bin” is not very different from the few last ones), but doesn’t work well for few NColours with “many” Stops and big colour jumps from one to the next --and in your case you have Stops = NColors; in your case the last colour is in the middle between green and red.
Looking at the code for CreateGradientColorTable, there is this loop:

   for (g = 1; g < Number; g++) {
      // create the colors...
      nColorsGradient = (Int_t) (floor(NColors*Stops[g]) - floor(NColors*Stops[g-1]));
   //...

If we have, as in your case,

root [0] int NColors = 6;
root [1] Double_t Stops[] = {0.0, 1.2/6., 2.4/6., 3.6/6., 4.8/6., 1.};
root [2] for (int g = 1; g < NColors; g++) cout << (Int_t) (floor(NColors*Stops[g]) - floor(NColors*Stops[g-1]))<<endl;
1
1
1
1
2
root [3]

the last bin has 2 colours, which are interpolated and we don’t get the pure red. For that, the second to last value in Stops would need to be 5/6, but since Stops has to go from 0 to 1, leaving 4 available values out of the 6, at least one value (from 1 to 5) will always be missing and thus there will be a bin with 2 colours. So, it’s a limitation of the method used.
On the other hand, CreateColorTableFromFile() will use the exact colours you define in the file (so you have to define all the colours you want to use, one by one).

1 Like

thanks for explanation

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