Warning, /include/Geant4/tools/sg/colormap is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_sg_colormap
0005 #define tools_sg_colormap
0006
0007 #include "../colorf"
0008 #include "../mathf"
0009 #include "../scast"
0010 #include "style_parser"
0011
0012 #include <string>
0013 #include <cfloat> //FLT_MAX
0014
0015 namespace tools {
0016 namespace sg {
0017
0018 class base_colormap {
0019 #ifdef TOOLS_MEM
0020 static const std::string& s_class() {
0021 static const std::string s_v("tools::sg::base_colormap");
0022 return s_v;
0023 }
0024 #endif
0025 public:
0026 virtual void get_color(float,colorf&) const = 0;
0027 virtual void* cast(const std::string&) const = 0;
0028 public:
0029 base_colormap(){
0030 #ifdef TOOLS_MEM
0031 mem::increment(s_class().c_str());
0032 #endif
0033 }
0034 base_colormap(const base_colormap& aFrom)
0035 :m_values(aFrom.m_values),m_colors(aFrom.m_colors){
0036 #ifdef TOOLS_MEM
0037 mem::increment(s_class().c_str());
0038 #endif
0039 }
0040 base_colormap& operator=(const base_colormap& aFrom){
0041 m_values = aFrom.m_values;
0042 m_colors = aFrom.m_colors;
0043 return *this;
0044 }
0045 virtual ~base_colormap(){
0046 #ifdef TOOLS_MEM
0047 mem::decrement(s_class().c_str());
0048 #endif
0049 }
0050 public:
0051 size_t colorn() const {return m_colors.size();}
0052 size_t valn() const {return m_values.size();}
0053 colorf color(size_t a_index) const {
0054 size_t n = m_colors.size();
0055 if(a_index>=n) return colorf(0.5F,0.5F,0.5F);
0056 return m_colors[a_index];
0057 }
0058 float value(size_t a_index) const {
0059 size_t n = m_values.size();
0060 if(a_index>=n) return 0;
0061 return m_values[a_index];
0062 }
0063 public:
0064 // helper :
0065 void set_colors(void(*aGet)(float,colorf&),size_t a_ncell) {
0066 m_colors.clear();
0067 m_colors.resize(a_ncell);
0068 if(!a_ncell) return;
0069 float d = 1.0F/(a_ncell-1);
0070 for(size_t index=0;index<a_ncell;index++) {
0071 aGet(d*index,m_colors[index]);
0072 }
0073 }
0074
0075 void set_PAW_coloring() {
0076 size_t _valn = m_values.size();
0077 if(_valn==1) {
0078 m_values[0] = take_log(m_values[0]);
0079 } else if(_valn>=2) {
0080 //CERN/PAW coloring :
0081 if(m_values[0]==0) m_values[0] = 10e-5F;
0082 float vmin = take_log(m_values[0]);
0083 float vmax = take_log(m_values[_valn-1]);
0084 float dv = (vmax-vmin)/(_valn-1);
0085 for(size_t count=0;count<_valn;count++) {
0086 m_values[count] = vmin + dv * count;
0087 }
0088 }
0089 }
0090
0091 protected:
0092 static float take_log(float aVal){
0093 if(aVal<=0) {
0094 return -FLT_MAX;
0095 } else {
0096 return flog10(aVal);
0097 }
0098 }
0099
0100 protected:
0101 std::vector<float> m_values;
0102 std::vector<colorf> m_colors;
0103 };
0104
0105 class by_value_colormap : public base_colormap {
0106 public:
0107 TOOLS_SCLASS(tools::sg::by_value_colormap)
0108 public:
0109 virtual void get_color(float a_value,colorf& a_col) const{
0110 get_by_value(a_value,m_values,m_colors,a_col);
0111 }
0112 virtual void* cast(const std::string& a_class) const {
0113 if(void* p = cmp_cast<by_value_colormap>(this,a_class)) {return p;}
0114 else return 0;
0115 }
0116 public:
0117 by_value_colormap(std::ostream& a_out,
0118 const sg::cmaps_t& a_cmaps,
0119 const std::string& aString){
0120 set_by_value(a_out,a_cmaps,aString,m_values,m_colors);
0121 }
0122 by_value_colormap(const by_value_colormap& aFrom):base_colormap(aFrom){}
0123 by_value_colormap& operator=(const by_value_colormap& aFrom){
0124 base_colormap::operator=(aFrom);
0125 return *this;
0126 }
0127 virtual ~by_value_colormap(){}
0128 protected:
0129 static void set_by_value(std::ostream& a_out,
0130 const sg::cmaps_t& a_cmaps,
0131 const std::string& aString,
0132 std::vector<float>& aValues,
0133 std::vector<colorf>& aColors) {
0134 // The given string is of the format :
0135 // [<color name> <value>] <color name>
0136 // or :
0137 // [<value> <color name>] <value>
0138 // For example :
0139 // black 10 cyan 50 green 100 orange 200 blue 300 pink 400 red
0140 std::vector<std::string> ws;
0141 words(aString," ",false,ws);
0142 size_t wordn = ws.size();
0143 size_t number = wordn/2;
0144 if(number<=0) {
0145 aValues.clear();
0146 aColors.clear();
0147 } else if((2*number+1)!=wordn) {
0148 a_out << "by_value_colormap::set_by_value :"
0149 << " An odd number (" << wordn
0150 << " given) of words is expected in " << sout(aString) << "."
0151 << std::endl;
0152 aValues.clear();
0153 aColors.clear();
0154 } else {
0155 // look if :
0156 // <col> <num> <col> ... <num> <col>
0157 // or :
0158 // <num> <col> <num> ... <col> <num>
0159 // FIXME : case of <col> being three floats ?
0160 colorf c;
0161 if(sg::find_color(a_cmaps,ws[0],c)) {
0162 // <col> <num> <col> ... <num> <col>
0163 aValues.resize(number);
0164 aColors.resize(number+1);
0165 for(size_t count=0;count<number;count++) {
0166 {const std::string& word = ws[2*count];
0167 if(!sg::find_color(a_cmaps,word,aColors[count])) {
0168 a_out << "by_value_colormap::set_by_value :"
0169 << " in " << sout(aString)
0170 << ", " << word << " not a color."
0171 << std::endl;
0172 aValues.clear();
0173 aColors.clear();
0174 return;
0175 }}
0176 {const std::string& word = ws[2*count+1];
0177 if(!to(word,aValues[count])) {
0178 a_out << "by_value_colormap::set_by_value :"
0179 << " in " << sout(aString)
0180 << ", " << word << " not a number."
0181 << std::endl;
0182 aValues.clear();
0183 aColors.clear();
0184 return;
0185 }}
0186 }
0187 const std::string& word = ws[wordn-1];
0188 if(!sg::find_color(a_cmaps,word,aColors[number])) {
0189 a_out << "by_value_colormap::set_by_value :"
0190 << " in " << sout(aString)
0191 << ", " << word << " not a color."
0192 << std::endl;
0193 aValues.clear();
0194 aColors.clear();
0195 }
0196 } else {
0197 // <num> <col> <num> ... <col> <num>
0198 aValues.resize(number+1);
0199 aColors.resize(number);
0200 for(size_t count=0;count<number;count++) {
0201 {const std::string& word = ws[2*count];
0202 if(!to(word,aValues[count])) {
0203 a_out << "by_value_colormap::set_by_value :"
0204 << " in " << sout(aString)
0205 << ", " << word << " not a number."
0206 << std::endl;
0207 aValues.clear();
0208 aColors.clear();
0209 return;
0210 }}
0211 {const std::string& word = ws[2*count+1];
0212 if(!sg::find_color(a_cmaps,word,aColors[count])) {
0213 a_out << "by_value_colormap::set_by_value :"
0214 << " in " << sout(aString)
0215 << ", " << word << " not a color."
0216 << std::endl;
0217 aValues.clear();
0218 aColors.clear();
0219 return;
0220 }}
0221 }
0222 {const std::string& word = ws[wordn-1];
0223 if(!to(word,aValues[number])) {
0224 a_out << "by_value_colormap::set_by_value :"
0225 << " in " << sout(aString)
0226 << ", " << word << " not a number."
0227 << std::endl;
0228 aValues.clear();
0229 aColors.clear();
0230 return;
0231 }}
0232 }
0233 }
0234 }
0235
0236 static void get_by_value(float aValue,
0237 const std::vector<float>& aValues,
0238 const std::vector<colorf>& aColors,
0239 colorf& a_col){
0240 // There are aValuen (n) entries in aValues and (n+1) aColors
0241 // aColors[0] aValues[0] aColors[1] aValues[1]...
0242 // aValues[n-2] aColors[n-1] aValues[n-1] aColors[n]
0243 // black 10 cyan 50 green 100 orange 200 blue 300 pink 400 red
0244 // valuen = 6
0245 // values[0] 10
0246 // values[1] 50
0247 // values[2] 100
0248 // values[3] 200
0249 // values[4] 300
0250 // values[5] 400
0251 //
0252 // colors[0] black
0253 // colors[1] cyan
0254 // colors[2] green
0255 // colors[3] orange
0256 // colors[4] blue
0257 // colors[5] pink
0258 // colors[6] red
0259 size_t _valn = aValues.size();
0260 if(!_valn) {a_col = colorf_black();return;}
0261 if(aColors.size()==(_valn+1)) {
0262 // col0 val0 col1 val1 col2 val2 col3
0263 if(aValue<aValues[0]) {
0264 a_col = aColors[0];
0265 } else {
0266 for(int count=0;count<=int(_valn-2);count++) {
0267 if( (aValues[count]<=aValue) && (aValue<aValues[count+1]) ) {
0268 a_col = aColors[count+1];
0269 return;
0270 }
0271 }
0272 a_col = aColors[_valn];
0273 }
0274 } else if((aColors.size()+1)==_valn) {
0275 // val0 col0 val1 col1 val2 col2 val3
0276 for(int count=0;count<=int(_valn-2);count++) {
0277 if( (aValues[count]<=aValue) && (aValue<aValues[count+1]) ) {
0278 a_col = aColors[count];
0279 return;
0280 }
0281 }
0282 if(aValue<aValues[0]) {a_col = aColors[0];return;}
0283 if(aValue>=aValues[_valn-1]) {a_col = aColors[aColors.size()-1];return;}
0284 a_col = colorf_black();
0285 } else {
0286 a_col = colorf_black();
0287 }
0288 }
0289
0290 };
0291
0292 class grey_scale_colormap : public base_colormap {
0293 public:
0294 TOOLS_SCLASS(tools::sg::grey_scale_colormap)
0295 public:
0296 virtual void get_color(float a_value,colorf& a_col) const { //a_value in [0,1]
0297 get_grey(a_value,a_col);
0298 }
0299 virtual void* cast(const std::string& a_class) const {
0300 if(void* p = cmp_cast<grey_scale_colormap>(this,a_class)) {return p;}
0301 else return 0;
0302 }
0303 public:
0304 grey_scale_colormap() {} //if not drawn in sg::plotter.
0305 grey_scale_colormap(float a_min,float a_max,size_t a_ncell){
0306 //note : a_min, a_max, a_ncell (and then m_colors, m_values) are used by sg::plotter::update_cmap().
0307 m_values.resize(2);
0308 m_values[0] = a_min;
0309 m_values[1] = a_max;
0310 set_colors(get_grey,a_ncell);
0311 }
0312 grey_scale_colormap(const grey_scale_colormap& aFrom):base_colormap(aFrom){}
0313 grey_scale_colormap& operator=(const grey_scale_colormap& aFrom){
0314 base_colormap::operator=(aFrom);
0315 return *this;
0316 }
0317 virtual ~grey_scale_colormap(){}
0318 protected:
0319 static void get_grey(float a_ratio,colorf& a_col) {
0320 if(a_ratio<0.0F) a_ratio = 0;
0321 if(a_ratio>1.0F) a_ratio = 1;
0322 a_col.set_value(a_ratio,a_ratio,a_ratio,1);
0323 }
0324 };
0325
0326 class grey_scale_inverse_colormap : public base_colormap {
0327 public:
0328 TOOLS_SCLASS(tools::sg::grey_scale_inverse_colormap)
0329 public:
0330 virtual void get_color(float a_value,colorf& a_col) const { //a_value in [0,1]
0331 get_grey_inverse(a_value,a_col);
0332 }
0333 virtual void* cast(const std::string& a_class) const {
0334 if(void* p = cmp_cast<grey_scale_inverse_colormap>(this,a_class)) {return p;}
0335 else return 0;
0336 }
0337 public:
0338 grey_scale_inverse_colormap() {} //if not drawn in sg::plotter.
0339 grey_scale_inverse_colormap(float a_min,float a_max,size_t a_ncell){
0340 //note : a_min, a_max, a_ncell (and then m_colors, m_values) are used by sg::plotter::update_cmap().
0341 m_values.resize(2);
0342 m_values[0] = a_min;
0343 m_values[1] = a_max;
0344 set_colors(get_grey_inverse,a_ncell);
0345 }
0346 grey_scale_inverse_colormap(const grey_scale_inverse_colormap& aFrom):base_colormap(aFrom){}
0347 grey_scale_inverse_colormap& operator=(const grey_scale_inverse_colormap& aFrom){
0348 base_colormap::operator=(aFrom);
0349 return *this;
0350 }
0351 virtual ~grey_scale_inverse_colormap(){}
0352 protected:
0353 static void get_grey_inverse(float a_ratio,colorf& a_col){
0354 if(a_ratio<0.0F) a_ratio = 0;
0355 if(a_ratio>1.0F) a_ratio = 1;
0356 a_ratio = 1 - a_ratio;
0357 a_col.set_value(a_ratio,a_ratio,a_ratio,1);
0358 }
0359 };
0360
0361 class violet_to_red_colormap : public base_colormap {
0362 public:
0363 TOOLS_SCLASS(tools::sg::violet_to_red_colormap)
0364 public:
0365 virtual void get_color(float a_value,colorf& a_col) const { //a_value in [0,1]
0366 get_violet_to_red(a_value,a_col);
0367 }
0368 virtual void* cast(const std::string& a_class) const {
0369 if(void* p = cmp_cast<violet_to_red_colormap>(this,a_class)) {return p;}
0370 else return 0;
0371 }
0372 public:
0373 violet_to_red_colormap() {} //if not drawn in sg::plotter.
0374 violet_to_red_colormap(float a_min,float a_max,size_t a_ncell){
0375 //note : a_min, a_max, a_ncell (and then m_colors, m_values) are used by sg::plotter::update_cmap().
0376 set(a_min,a_max,a_ncell);
0377 }
0378 violet_to_red_colormap(const violet_to_red_colormap& aFrom):base_colormap(aFrom){}
0379 violet_to_red_colormap& operator=(const violet_to_red_colormap& aFrom){
0380 base_colormap::operator=(aFrom);
0381 return *this;
0382 }
0383 virtual ~violet_to_red_colormap(){}
0384 public:
0385 void set(float a_min,float a_max,size_t a_ncell){
0386 m_values.resize(2);
0387 m_values[0] = a_min;
0388 m_values[1] = a_max;
0389 set_colors(get_violet_to_red,a_ncell);
0390 }
0391 protected:
0392 static void get_violet_to_red(float a_ratio,colorf& a_col){
0393 if(a_ratio<0.0F) a_ratio = 0;
0394 if(a_ratio>1.0F) a_ratio = 1;
0395 // a_ratio in [0,1]
0396 // From ROOT pretty palette.
0397 // Initialize with the spectrum Violet->Red
0398 // The color model used here is based on the HLS model which
0399 // is much more suitable for creating palettes than RGB.
0400 // Fixing the saturation and lightness we can scan through the
0401 // spectrum of visible light by using "hue" alone.
0402 // In Root hue takes values from 0 to 360.
0403 float saturation = 1;
0404 float lightness = 0.5;
0405 float hue_mn = 0;
0406 float hue_mx = 280;
0407 float hue = hue_mx - a_ratio * (hue_mx-hue_mn);
0408 float r,g,b;
0409 hls_to_rgb(hue,lightness,saturation,r,g,b);
0410 a_col.set_value(r,g,b,1);
0411 }
0412
0413 };
0414
0415 class const_colormap : public base_colormap {
0416 public:
0417 TOOLS_SCLASS(tools::sg::const_colormap)
0418 public:
0419 virtual void get_color(float,colorf& a_col) const { //a_value in [0,1]
0420 a_col = m_colors[0];
0421 }
0422 virtual void* cast(const std::string& a_class) const {
0423 if(void* p = cmp_cast<const_colormap>(this,a_class)) {return p;}
0424 else return 0;
0425 }
0426 public:
0427 const_colormap(const colorf& aColor){m_colors.push_back(aColor);}
0428 const_colormap(const const_colormap& aFrom):base_colormap(aFrom){}
0429 const_colormap& operator=(const const_colormap& aFrom){
0430 base_colormap::operator=(aFrom);
0431 return *this;
0432 }
0433 virtual ~const_colormap(){}
0434 };
0435
0436 }}
0437
0438 #endif