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