Back to home page

EIC code displayed by LXR

 
 

    


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