Skip to content

Instantly share code, notes, and snippets.

@Nepomuk
Last active August 29, 2015 14:17
Show Gist options
  • Save Nepomuk/859fef81a912a9fe425e to your computer and use it in GitHub Desktop.
Save Nepomuk/859fef81a912a9fe425e to your computer and use it in GitHub Desktop.
Tableau20 Colors for ROOT
/**
* @file tableau_colors.cpp
* @Author André Goerres ([email protected])
* @date 2015
* @brief Tableau color scheme for ROOT
*
* This file adds predefined colors according to the tableau color palette. Two
* different namespaces are offered providing 20 nicely balanced colors or 10
* colors color blind people can savely distinguish.
* -André
*/
#include <utility>
#include "TROOT.h"
#include "TSystem.h"
#include "TColor.h"
#include "TString.h"
namespace tableau {
/**
* @brief Returns a color out of the Tableau20 set
* @details Uses a numerical index to determine which color to return
*
* @param index 0-19 for the different colors
* @return Int_t Reference to the ROOT color number
*/
Int_t getTableau20Color( Int_t index ) {
switch ( index ) {
case 0: return TColor::GetColor( 31, 119, 180);
case 1: return TColor::GetColor(174, 199, 232);
case 2: return TColor::GetColor(255, 127, 14);
case 3: return TColor::GetColor(255, 187, 120);
case 4: return TColor::GetColor( 44, 160, 44);
case 5: return TColor::GetColor(152, 223, 138);
case 6: return TColor::GetColor(214, 39, 40);
case 7: return TColor::GetColor(255, 152, 150);
case 8: return TColor::GetColor(148, 103, 189);
case 9: return TColor::GetColor(197, 176, 213);
case 10: return TColor::GetColor(140, 86, 75);
case 11: return TColor::GetColor(196, 156, 148);
case 12: return TColor::GetColor(227, 119, 194);
case 13: return TColor::GetColor(247, 182, 210);
case 14: return TColor::GetColor(127, 127, 127);
case 15: return TColor::GetColor(199, 199, 199);
case 16: return TColor::GetColor(188, 189, 34);
case 17: return TColor::GetColor(219, 219, 141);
case 18: return TColor::GetColor( 23, 190, 207);
case 19: return TColor::GetColor(158, 218, 229);
default: return kBlack;
}
}
/**
* @brief Returns a color out of the Tableau20 set
* @details Uses a string representation to determine which color to return
* to increase readability of the code. Names represent similar colors from
* LaTeX' xcolor package with svgnames.
*
* @param name Name of the color
* @return Int_t Reference to the ROOT color number
*/
Int_t getTableau20Color( TString name ) {
if ( name == "SteelBlue" ) return getTableau20Color(0);
else if ( name == "LightSteelBlue" ) return getTableau20Color(1);
else if ( name == "DarkOrange" ) return getTableau20Color(2);
else if ( name == "PeachPuff" ) return getTableau20Color(3);
else if ( name == "Green" ) return getTableau20Color(4);
else if ( name == "LightGreen" ) return getTableau20Color(5);
else if ( name == "Crimson" ) return getTableau20Color(6);
else if ( name == "LightCoral" ) return getTableau20Color(7);
else if ( name == "MediumPurple" ) return getTableau20Color(8);
else if ( name == "Thistle" ) return getTableau20Color(9);
else if ( name == "SaddleBrown" ) return getTableau20Color(10);
else if ( name == "RosyBrown" ) return getTableau20Color(11);
else if ( name == "Orchid" ) return getTableau20Color(12);
else if ( name == "LightPink" ) return getTableau20Color(13);
else if ( name == "Gray" ) return getTableau20Color(14);
else if ( name == "LightGray" ) return getTableau20Color(15);
else if ( name == "Olive" ) return getTableau20Color(16);
else if ( name == "PaleGoldenrod" ) return getTableau20Color(17);
else if ( name == "MediumTurquoise" ) return getTableau20Color(18);
else if ( name == "PaleTurquoise" ) return getTableau20Color(19);
else return kBlack;
}
/**
* @brief Gets a pair of Tableau20 colors
* @details Tableau20 colors are grouped together in pairs of intense and
* light colors. This function returns this pair.
*
* @param name Name of the intense color
* @return pair A std::pair<Int_t, Int_t> to the ROOT colorIDs
*/
std::pair<Int_t, Int_t> getTableau20ColorPair( TString name ) {
std::pair<Int_t, Int_t> colorPair;
if ( name == "SteelBlue" ) {
colorPair.first = getTableau20Color(0);
colorPair.second = getTableau20Color(1);
}
else if ( name == "DarkOrange" ) {
colorPair.first = getTableau20Color(2);
colorPair.second = getTableau20Color(3);
}
else if ( name == "Green" ) {
colorPair.first = getTableau20Color(4);
colorPair.second = getTableau20Color(5);
}
else if ( name == "Crimson" ) {
colorPair.first = getTableau20Color(6);
colorPair.second = getTableau20Color(7);
}
else if ( name == "MediumPurple" ) {
colorPair.first = getTableau20Color(8);
colorPair.second = getTableau20Color(9);
}
else if ( name == "SaddleBrown" ) {
colorPair.first = getTableau20Color(10);
colorPair.second = getTableau20Color(11);
}
else if ( name == "Orchid" ) {
colorPair.first = getTableau20Color(12);
colorPair.second = getTableau20Color(13);
}
else if ( name == "Gray" ) {
colorPair.first = getTableau20Color(14);
colorPair.second = getTableau20Color(15);
}
else if ( name == "Olive" ) {
colorPair.first = getTableau20Color(16);
colorPair.second = getTableau20Color(17);
}
else if ( name == "MediumTurquoise" ) {
colorPair.first = getTableau20Color(18);
colorPair.second = getTableau20Color(19);
}
else {
colorPair.first = kBlack;
colorPair.second = kGray;
}
return colorPair;
}
/**
* @brief Returns a color out of the Tableau color blind set
* @details Uses a numerical index to determine which color to return
*
* @param index 0-9 for the different colors
* @return Int_t Reference to the ROOT color number
*/
Int_t getTableau10BlindColor( Int_t index ) {
switch ( index ) {
case 0: return TColor::GetColor( 0, 107, 164);
case 1: return TColor::GetColor(255, 128, 14);
case 2: return TColor::GetColor(171, 171, 171);
case 3: return TColor::GetColor( 89, 89, 89);
case 4: return TColor::GetColor( 95, 158, 209);
case 5: return TColor::GetColor(200, 82, 0);
case 6: return TColor::GetColor(137, 137, 137);
case 7: return TColor::GetColor(163, 200, 236);
case 8: return TColor::GetColor(255, 188, 121);
case 9: return TColor::GetColor(207, 207, 207);
default: return kBlack;
}
}
/**
* @brief Returns a color out of the Tableau color blind set
* @details Uses a string representation to determine which color to return
* to increase readability of the code. Names represent similar colors from
* LaTeX' xcolor package with svgnames or x11names (if there is a number at
* end of the name).
*
* @param name Name of the color
* @return Int_t Reference to the ROOT color number
*/
Int_t getTableau10BlindColor( TString name ) {
if ( name == "DeepSkyBlue4" ) return getTableau10BlindColor(0);
else if ( name == "DarkOrange1" ) return getTableau10BlindColor(1);
else if ( name == "DarkGray" ) return getTableau10BlindColor(2);
else if ( name == "DimGray" ) return getTableau10BlindColor(3);
else if ( name == "SkyBlue3" ) return getTableau10BlindColor(4);
else if ( name == "Chocolate3" ) return getTableau10BlindColor(5);
else if ( name == "Gray" ) return getTableau10BlindColor(6);
else if ( name == "SlateGray1" ) return getTableau10BlindColor(7);
else if ( name == "SandyBrown" ) return getTableau10BlindColor(8);
else if ( name == "LightGray" ) return getTableau10BlindColor(9);
else return kBlack;
}
/**
* @brief Generate a palette for color blinds
* @details Use the tableau 10 blind palette to generate a palette for
* ROOT's 2D histograms.
*
* @param const int Number of steps to generate
* @param Int_t * Pointer to the array storing the palette colors
*/
void getTableau10BlindColorPalette( const int nSteps, Int_t *palette ) {
// define the colors
const int nColors = 4;
TColor * col[nColors] = {
gROOT->GetColor(getTableau10BlindColor("SlateGray1")),
gROOT->GetColor(getTableau10BlindColor("DeepSkyBlue4")),
gROOT->GetColor(getTableau10BlindColor("SandyBrown")),
gROOT->GetColor(getTableau20Color("Crimson"))
};
Double_t stop[nColors] = {0., .25, .65, 1.0};
// get color values
Double_t r[nColors], g[nColors], b[nColors];
for ( int c = 0; c < nColors; c++ ) {
r[c] = col[c]->GetRed();
g[c] = col[c]->GetGreen();
b[c] = col[c]->GetBlue();
}
// generate palette
Int_t FI = TColor::CreateGradientColorTable(nColors, stop, r, g, b, nSteps);
for ( int i = 0; i < nSteps; i++ ) palette[i] = FI+i;
}
/**
* @brief Generate a palette using tableau20 colors
* @details Use the tableau20 palette to generate a palette for ROOT's
* 2D histograms.
*
* @param const int Number of steps to generate
* @param Int_t * Pointer to the array storing the palette colors
*/
void getTableau20ColorPalette( const int nSteps, Int_t *palette ) {
// define the colors
const int nColors = 5;
TColor * col[nColors] = {
gROOT->GetColor(getTableau20Color("LightSteelBlue")),
gROOT->GetColor(getTableau20Color("SteelBlue")),
gROOT->GetColor(getTableau20Color("Olive")),
gROOT->GetColor(getTableau20Color("DarkOrange")),
gROOT->GetColor(getTableau20Color("Crimson"))
};
Double_t stop[nColors] = {0., .22, .53, .79, 1.0};
// get color values
Double_t r[nColors], g[nColors], b[nColors];
for ( int c = 0; c < nColors; c++ ) {
r[c] = col[c]->GetRed();
g[c] = col[c]->GetGreen();
b[c] = col[c]->GetBlue();
}
// generate palette
Int_t FI = TColor::CreateGradientColorTable(nColors, stop, r, g, b, nSteps);
for ( int i = 0; i < nSteps; i++ ) palette[i] = FI+i;
}
/**
* @brief Modifies the brightness of a color
* @details The intensity defines the severeness of brightness change,
* 0 is no change at all. Positive values of intensity will increase
* brightness, negative will decrease.
*
* @param index Index of ROOT color
* @param intensity Factor for brightness adjustment
* @return Int_t Reference to the ROOT color number
*/
Int_t getBrightColor( Int_t colorID, Float_t intensity = 1 ) {
// get the color from the global index
TColor * color = (TColor *)gROOT->GetColor(colorID);
if ( 0x0 == color ) return colorID;
// now modify the saturation
Float_t h = color->GetHue();
Float_t l = color->GetLight();
Float_t s = color->GetSaturation();
if ( intensity > 0 ) {
l += intensity * (1 - color->GetLight()) / 2;
s -= intensity * color->GetLight() / 1.7;
} else {
l += intensity * color->GetLight() / 2;
s -= intensity * (1 - color->GetLight()) / 1.7;
}
// check for maximum allowed range
if ( l < 0 ) l = 0;
if ( l > 1 ) l = 1;
if ( s < 0 ) s = 0;
if ( s > 1 ) s = 1;
// define the new color and return it's index
Float_t r,g,b;
TColor::HLS2RGB(h,l,s, r,g,b);
return TColor::GetColor(r,g,b);
}
Int_t getTableau20ColorBright( Int_t index, Float_t intensity = 1 ) {
Int_t colorID = getTableau20Color(index);
return getBrightColor( colorID, intensity );
}
Int_t getTableau20ColorBright( TString name, Float_t intensity = 1 ) {
Int_t colorID = getTableau20Color(name);
return getBrightColor( colorID, intensity );
}
Int_t getTableau10BlindColorBright( Int_t index, Float_t intensity = 1 ) {
Int_t colorID = getTableau10BlindColor(index);
return getBrightColor( colorID, intensity );
}
Int_t getTableau10BlindColorBright( TString name, Float_t intensity = 1 ) {
Int_t colorID = getTableau10BlindColor(name);
return getBrightColor( colorID, intensity );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment