Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/sg/colormap

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  2 // See the file tools.license for terms.
  3 
  4 #ifndef tools_sg_colormap
  5 #define tools_sg_colormap
  6 
  7 #include "../colorf"
  8 #include "../mathf"
  9 #include "../scast"
 10 #include "style_parser"
 11 
 12 #include <string>
 13 #include <cfloat> //FLT_MAX
 14 
 15 namespace tools {
 16 namespace sg {
 17 
 18 class base_colormap {
 19 #ifdef TOOLS_MEM
 20   static const std::string& s_class() {
 21     static const std::string s_v("tools::sg::base_colormap");
 22     return s_v;
 23   }
 24 #endif
 25 public:
 26   virtual void get_color(float,colorf&) const = 0;
 27   virtual void* cast(const std::string&) const = 0;
 28 public:
 29   base_colormap(){
 30 #ifdef TOOLS_MEM
 31     mem::increment(s_class().c_str());
 32 #endif
 33   }
 34   base_colormap(const base_colormap& aFrom)
 35   :m_values(aFrom.m_values),m_colors(aFrom.m_colors){
 36 #ifdef TOOLS_MEM
 37     mem::increment(s_class().c_str());
 38 #endif
 39   }
 40   base_colormap& operator=(const base_colormap& aFrom){
 41     m_values = aFrom.m_values;
 42     m_colors = aFrom.m_colors;
 43     return *this;
 44   }
 45   virtual ~base_colormap(){
 46 #ifdef TOOLS_MEM
 47     mem::decrement(s_class().c_str());
 48 #endif
 49   }
 50 public:
 51   size_t colorn() const {return m_colors.size();}
 52   size_t valn() const {return m_values.size();}
 53   colorf color(size_t a_index) const {
 54     size_t n = m_colors.size();
 55     if(a_index>=n) return colorf(0.5F,0.5F,0.5F);
 56     return m_colors[a_index];
 57   }
 58   float value(size_t a_index) const {
 59     size_t n = m_values.size();
 60     if(a_index>=n) return 0;
 61     return m_values[a_index];
 62   }
 63 public:
 64   // helper :
 65   void set_colors(void(*aGet)(float,colorf&),size_t a_ncell) {
 66     m_colors.clear();
 67     m_colors.resize(a_ncell);
 68     if(!a_ncell) return;
 69     float d = 1.0F/(a_ncell-1);
 70     for(size_t index=0;index<a_ncell;index++) {
 71       aGet(d*index,m_colors[index]);
 72     }
 73   }
 74 
 75   void set_PAW_coloring() {
 76     size_t _valn = m_values.size();
 77     if(_valn==1) {
 78       m_values[0] = take_log(m_values[0]);
 79     } else if(_valn>=2) {
 80       //CERN/PAW coloring :
 81       if(m_values[0]==0) m_values[0] = 10e-5F;
 82       float vmin = take_log(m_values[0]);
 83       float vmax = take_log(m_values[_valn-1]);
 84       float dv = (vmax-vmin)/(_valn-1);
 85       for(size_t count=0;count<_valn;count++) {
 86         m_values[count] = vmin + dv * count;
 87       }
 88     }
 89   }
 90 
 91 protected:
 92   static float take_log(float aVal){
 93     if(aVal<=0) {
 94       return -FLT_MAX;
 95     } else {
 96       return flog10(aVal);
 97     }
 98   }
 99 
100 protected:
101   std::vector<float> m_values;
102   std::vector<colorf> m_colors;
103 };
104 
105 class by_value_colormap : public base_colormap {
106 public:
107   TOOLS_SCLASS(tools::sg::by_value_colormap)
108 public:
109   virtual void get_color(float a_value,colorf& a_col) const{
110     get_by_value(a_value,m_values,m_colors,a_col);
111   }
112   virtual void* cast(const std::string& a_class) const {
113     if(void* p = cmp_cast<by_value_colormap>(this,a_class)) {return p;}
114     else return 0;
115   }
116 public:
117   by_value_colormap(std::ostream& a_out,
118                     const sg::cmaps_t& a_cmaps,
119                     const std::string& aString){
120     set_by_value(a_out,a_cmaps,aString,m_values,m_colors);
121   }
122   by_value_colormap(const by_value_colormap& aFrom):base_colormap(aFrom){}
123   by_value_colormap& operator=(const by_value_colormap& aFrom){
124     base_colormap::operator=(aFrom);
125     return *this;
126   }
127   virtual ~by_value_colormap(){}
128 protected:
129   static void set_by_value(std::ostream& a_out,
130                            const sg::cmaps_t& a_cmaps,
131                            const std::string& aString,
132                            std::vector<float>& aValues,
133                            std::vector<colorf>& aColors) {
134     //  The given string is of the format :
135     //      [<color name> <value>] <color name>
136     //  or :
137     //      [<value> <color name>] <value>
138     //  For example :
139     //      black 10 cyan 50 green 100 orange 200 blue 300 pink 400 red
140     std::vector<std::string> ws;
141     words(aString," ",false,ws);
142     size_t wordn = ws.size();
143     size_t number = wordn/2;
144     if(number<=0) {
145       aValues.clear();
146       aColors.clear();
147     } else if((2*number+1)!=wordn) {
148       a_out << "by_value_colormap::set_by_value :"
149             << " An odd number (" << wordn
150             << " given) of words is expected in " << sout(aString) << "."
151             << std::endl;
152       aValues.clear();
153       aColors.clear();
154     } else {
155       // look if :
156       //   <col> <num> <col> ... <num> <col>
157       // or :
158       //   <num> <col> <num> ... <col> <num>
159       // FIXME : case of <col> being three floats ?
160       colorf c;
161       if(sg::find_color(a_cmaps,ws[0],c)) {
162         // <col> <num> <col> ... <num> <col>
163         aValues.resize(number);
164         aColors.resize(number+1);
165         for(size_t count=0;count<number;count++) {
166          {const std::string& word = ws[2*count];
167           if(!sg::find_color(a_cmaps,word,aColors[count])) {
168             a_out << "by_value_colormap::set_by_value :"
169                   << " in " << sout(aString)
170                   << ", " << word << " not a color."
171                   << std::endl;
172             aValues.clear();
173             aColors.clear();
174             return;
175           }}
176          {const std::string& word = ws[2*count+1];
177           if(!to(word,aValues[count]))  {
178             a_out << "by_value_colormap::set_by_value :"
179                   << " in " << sout(aString)
180                   << ", " << word << " not a number."
181                   << std::endl;
182             aValues.clear();
183             aColors.clear();
184             return;
185           }}
186         }
187         const std::string& word = ws[wordn-1];
188         if(!sg::find_color(a_cmaps,word,aColors[number])) {
189           a_out << "by_value_colormap::set_by_value :"
190                 << " in " << sout(aString)
191                 << ", " << word << " not a color."
192                 << std::endl;
193           aValues.clear();
194           aColors.clear();
195         }
196       } else {
197         // <num> <col> <num> ... <col> <num>
198         aValues.resize(number+1);
199         aColors.resize(number);
200         for(size_t count=0;count<number;count++) {
201          {const std::string& word = ws[2*count];
202           if(!to(word,aValues[count]))  {
203             a_out << "by_value_colormap::set_by_value :"
204                   << " in " << sout(aString)
205                   << ", " << word << " not a number."
206                   << std::endl;
207             aValues.clear();
208             aColors.clear();
209             return;
210           }}
211          {const std::string& word = ws[2*count+1];
212           if(!sg::find_color(a_cmaps,word,aColors[count])) {
213             a_out << "by_value_colormap::set_by_value :"
214                   << " in " << sout(aString)
215                   << ", " << word << " not a color."
216                   << std::endl;
217             aValues.clear();
218             aColors.clear();
219             return;
220           }}
221         }
222        {const std::string& word = ws[wordn-1];
223         if(!to(word,aValues[number]))  {
224           a_out << "by_value_colormap::set_by_value :"
225                 << " in " << sout(aString)
226                 << ", " << word << " not a number."
227                 << std::endl;
228           aValues.clear();
229           aColors.clear();
230           return;
231         }}
232       }
233     }
234   }
235 
236   static void get_by_value(float aValue,
237                            const std::vector<float>& aValues,
238                            const std::vector<colorf>& aColors,
239                            colorf& a_col){
240     // There are aValuen (n) entries in aValues and (n+1) aColors
241     //  aColors[0] aValues[0] aColors[1] aValues[1]...
242     //                 aValues[n-2] aColors[n-1] aValues[n-1] aColors[n]
243     //      black 10 cyan 50 green 100 orange 200 blue 300 pink 400 red
244     // valuen = 6
245     // values[0] 10
246     // values[1] 50
247     // values[2] 100
248     // values[3] 200
249     // values[4] 300
250     // values[5] 400
251     //
252     // colors[0] black
253     // colors[1] cyan
254     // colors[2] green
255     // colors[3] orange
256     // colors[4] blue
257     // colors[5] pink
258     // colors[6] red
259     size_t _valn = aValues.size();
260     if(!_valn) {a_col = colorf_black();return;}
261     if(aColors.size()==(_valn+1)) {
262       // col0 val0 col1 val1 col2 val2 col3
263       if(aValue<aValues[0]) {
264         a_col = aColors[0];
265       } else {
266         for(int count=0;count<=int(_valn-2);count++) {
267           if( (aValues[count]<=aValue) && (aValue<aValues[count+1]) ) {
268             a_col = aColors[count+1];
269             return;
270           }
271         }
272         a_col = aColors[_valn];
273       }
274     } else if((aColors.size()+1)==_valn) {
275       // val0 col0 val1 col1 val2 col2 val3
276       for(int count=0;count<=int(_valn-2);count++) {
277         if( (aValues[count]<=aValue) && (aValue<aValues[count+1]) ) {
278           a_col = aColors[count];
279           return;
280         }
281       }
282       if(aValue<aValues[0]) {a_col = aColors[0];return;}
283       if(aValue>=aValues[_valn-1]) {a_col = aColors[aColors.size()-1];return;}
284       a_col = colorf_black();
285     } else {
286       a_col = colorf_black();
287     }
288   }
289 
290 };
291 
292 class grey_scale_colormap : public base_colormap {
293 public:
294   TOOLS_SCLASS(tools::sg::grey_scale_colormap)
295 public:
296   virtual void get_color(float a_value,colorf& a_col) const { //a_value in [0,1]
297     get_grey(a_value,a_col);
298   }
299   virtual void* cast(const std::string& a_class) const {
300     if(void* p = cmp_cast<grey_scale_colormap>(this,a_class)) {return p;}
301     else return 0;
302   }
303 public:
304   grey_scale_colormap() {}  //if not drawn in sg::plotter.
305   grey_scale_colormap(float a_min,float a_max,size_t a_ncell){
306     //note : a_min, a_max, a_ncell (and then m_colors, m_values) are used by sg::plotter::update_cmap().
307     m_values.resize(2);
308     m_values[0] = a_min;
309     m_values[1] = a_max;
310     set_colors(get_grey,a_ncell);
311   }
312   grey_scale_colormap(const grey_scale_colormap& aFrom):base_colormap(aFrom){}
313   grey_scale_colormap& operator=(const grey_scale_colormap& aFrom){
314     base_colormap::operator=(aFrom);
315     return *this;
316   }
317   virtual ~grey_scale_colormap(){}
318 protected:
319   static void get_grey(float a_ratio,colorf& a_col) {
320     if(a_ratio<0.0F) a_ratio = 0;
321     if(a_ratio>1.0F) a_ratio = 1;
322     a_col.set_value(a_ratio,a_ratio,a_ratio,1);
323   }
324 };
325 
326 class grey_scale_inverse_colormap : public base_colormap {
327 public:
328   TOOLS_SCLASS(tools::sg::grey_scale_inverse_colormap)
329 public:
330   virtual void get_color(float a_value,colorf& a_col) const { //a_value in [0,1]
331     get_grey_inverse(a_value,a_col);
332   }
333   virtual void* cast(const std::string& a_class) const {
334     if(void* p = cmp_cast<grey_scale_inverse_colormap>(this,a_class)) {return p;}
335     else return 0;
336   }
337 public:
338   grey_scale_inverse_colormap() {}  //if not drawn in sg::plotter.
339   grey_scale_inverse_colormap(float a_min,float a_max,size_t a_ncell){
340     //note : a_min, a_max, a_ncell (and then m_colors, m_values) are used by sg::plotter::update_cmap().
341     m_values.resize(2);
342     m_values[0] = a_min;
343     m_values[1] = a_max;
344     set_colors(get_grey_inverse,a_ncell);
345   }
346   grey_scale_inverse_colormap(const grey_scale_inverse_colormap& aFrom):base_colormap(aFrom){}
347   grey_scale_inverse_colormap& operator=(const grey_scale_inverse_colormap& aFrom){
348     base_colormap::operator=(aFrom);
349     return *this;
350   }
351   virtual ~grey_scale_inverse_colormap(){}
352 protected:
353   static void get_grey_inverse(float a_ratio,colorf& a_col){
354     if(a_ratio<0.0F) a_ratio = 0;
355     if(a_ratio>1.0F) a_ratio = 1;
356     a_ratio = 1 - a_ratio;
357     a_col.set_value(a_ratio,a_ratio,a_ratio,1);
358   }
359 };
360 
361 class violet_to_red_colormap : public base_colormap {
362 public:
363   TOOLS_SCLASS(tools::sg::violet_to_red_colormap)
364 public:
365   virtual void get_color(float a_value,colorf& a_col) const { //a_value in [0,1]
366     get_violet_to_red(a_value,a_col);
367   }
368   virtual void* cast(const std::string& a_class) const {
369     if(void* p = cmp_cast<violet_to_red_colormap>(this,a_class)) {return p;}
370     else return 0;
371   }
372 public:
373   violet_to_red_colormap() {}  //if not drawn in sg::plotter.
374   violet_to_red_colormap(float a_min,float a_max,size_t a_ncell){
375     //note : a_min, a_max, a_ncell (and then m_colors, m_values) are used by sg::plotter::update_cmap().
376     set(a_min,a_max,a_ncell);
377   }
378   violet_to_red_colormap(const violet_to_red_colormap& aFrom):base_colormap(aFrom){}
379   violet_to_red_colormap& operator=(const violet_to_red_colormap& aFrom){
380     base_colormap::operator=(aFrom);
381     return *this;
382   }
383   virtual ~violet_to_red_colormap(){}
384 public:
385   void set(float a_min,float a_max,size_t a_ncell){
386     m_values.resize(2);
387     m_values[0] = a_min;
388     m_values[1] = a_max;
389     set_colors(get_violet_to_red,a_ncell);
390   }
391 protected:
392   static void get_violet_to_red(float a_ratio,colorf& a_col){
393     if(a_ratio<0.0F) a_ratio = 0;
394     if(a_ratio>1.0F) a_ratio = 1;
395     // a_ratio in [0,1]
396     // From ROOT pretty palette.
397     // Initialize with the spectrum Violet->Red
398     // The color model used here is based on the HLS model which
399     // is much more suitable for creating palettes than RGB.
400     // Fixing the saturation and lightness we can scan through the
401     // spectrum of visible light by using "hue" alone.
402     // In Root hue takes values from 0 to 360.
403     float saturation = 1;
404     float lightness = 0.5;
405     float hue_mn = 0;
406     float hue_mx = 280;
407     float hue = hue_mx - a_ratio * (hue_mx-hue_mn);
408     float r,g,b;
409     hls_to_rgb(hue,lightness,saturation,r,g,b);
410     a_col.set_value(r,g,b,1);
411   }
412 
413 };
414 
415 class const_colormap : public base_colormap {
416 public:
417   TOOLS_SCLASS(tools::sg::const_colormap)
418 public:
419   virtual void get_color(float,colorf& a_col) const { //a_value in [0,1]
420     a_col = m_colors[0];
421   }
422   virtual void* cast(const std::string& a_class) const {
423     if(void* p = cmp_cast<const_colormap>(this,a_class)) {return p;}
424     else return 0;
425   }
426 public:
427   const_colormap(const colorf& aColor){m_colors.push_back(aColor);}
428   const_colormap(const const_colormap& aFrom):base_colormap(aFrom){}
429   const_colormap& operator=(const const_colormap& aFrom){
430     base_colormap::operator=(aFrom);
431     return *this;
432   }
433   virtual ~const_colormap(){}
434 };
435 
436 }}
437 
438 #endif