Package topo :: Package plotting :: Module palette
[hide private]
[frames] | no frames]

Source Code for Module topo.plotting.palette

  1  """ 
  2  Palette class hierarchy, for constructing an RGB color out of a scalar value. 
  3   
  4  $Id: palette.py 11313 2010-07-27 17:18:26Z ceball $ 
  5  """ 
  6  __version__='$Revision: 11313 $' 
  7   
  8  import param 
  9   
 10  import plot 
 11   
 12  # CEBALERT: is this file usable? 
 13  # 
 14  # topo/plotting/palette.py:10: 'plot' imported but unused 
 15  # topo/plotting/palette.py:177: undefined name 'array' 
 16  # topo/plotting/palette.py:185: undefined name 'interpolate' 
 17  # topo/plotting/palette.py:185: undefined name 'color' 
 18  # topo/plotting/palette.py:185: undefined name 'color' 
 19  # topo/plotting/palette.py:188: undefined name 'interpolate' 
 20  # topo/plotting/palette.py:188: undefined name 'color' 
 21  # topo/plotting/palette.py:188: undefined name 'color' 
 22   
 23   
 24   
 25  ### JABALERT: Should be able to construct a Palette automatically by 
 26  ### accepting a string specification whose characters each stand for 
 27  ### colors between which to interpolate. 
 28  ### 
 29  ### We'd like to support a string interface like: 
 30  ### colormap(somestring), where somestring is a list of characters 
 31  ### corresponding to colors between which to interpolate. 
 32  ### (Interpolation is performed linearly in RGB space.)  Available 
 33  ### colors include: 
 34  ###  
 35  ###   R Red 
 36  ###   Y Yellow 
 37  ###   G Green 
 38  ###   C Cyan 
 39  ###   B Blue 
 40  ###   M Magenta 
 41  ###   K Black 
 42  ###   W White 
 43  ###  
 44  ### Use a lowercase letter to indicate that a color should use half intensity. 
 45  ### For instance, a <colorspec> of 'KgYW' would map the level range 0.0->1.0 
 46  ### to the color range black->dark green->yellow->white, with smooth 
 47  ### interpolation between the specified colors. 
 48  ### 
 49  ### In addition to these string-specified palettes (the basic 
 50  ### necessity), we would like to support classes for other methods for 
 51  ### constructing palettes based on the hue, saturation, and value: 
 52  ###  
 53  ### Hue [saturation [value]] 
 54  ###   Useful for plotting cyclic quantities, such as orientation. 
 55  ###   The hue is computed from the level, and is combined with the given fixed 
 56  ###   saturation and value (default '1.0 1.0') to determine the color.  The hue 
 57  ###   wraps around at each end of the range (e.g. red->yellow->green->blue->magenta 
 58  ###   ->red), and thus is usually appropriate only when the quantity plotted has 
 59  ###   that same property.  For the defaults, nearly identical to RYGCBMR. 
 60  ###  
 61  ### Saturation [hue [value]] 
 62  ###   Usually SpecifiedHue is used instead of specifying this type directly. 
 63  ###   The saturation is computed from the level, and is combined with the given 
 64  ###   fixed hue and value (default '0.0 1.0') to determine the color. 
 65  ###  
 66  ### Value [hue [saturation]] 
 67  ###   Usually Grayscale is used instead of specifying this type directly. 
 68  ###   The value is computed from the level, and is combined with the given fixed 
 69  ###   hue and saturation (default '0.0 0.0') to determine the color.  The defaults 
 70  ###   result in a range of grayscale values from black to white; the optional 
 71  ###   arguments allow other colors to be used instead of gray. 
 72  ###   For the defaults, nearly identical to KW. 
 73  ###  
 74  ### Grayscale [hue [saturation]] 
 75  ###   Useful for monochrome displays or printers, or to show photographs. 
 76  ###   Same as Value but the scale is flipped when ppm_paper_based_colors=True. 
 77  ###   This makes the most-active areas show up with the intensity that is most 
 78  ###   visible for the given medium (video or paper).  For the defaults, nearly 
 79  ###   identical to KW, or WK for ppm_paper_based_colors. 
 80  ###  
 81  ### SpecifiedHue [hue [confidence]] 
 82  ###   Useful for color-coding a plot with a specific hue visible on the default 
 83  ###   background. For paper_based_colors=False, same as ValueColorLookup; 
 84  ###   the confidence is used as the saturation.  Such a plot works well for 
 85  ###   showing color on a black background.  For paper_based_colors==True, 
 86  ###   returns the specified hue masked by the specified confidence, such 
 87  ###   that low values produce white, and high values produce black for low 
 88  ###   confidences and the specified hue for high confidences.  Such a plot 
 89  ###   is good for showing colors on light backgrounds. 
 90  ###  
 91  ### MapSpecifiesHue [nameofhuemap [nameofconfidencemap]] 
 92  ###   Neural-region-specific variant of SpecifiedHue where these colorspec 
 93  ###   arguments specify not the actual hue and confidence, but the names of 
 94  ###   registered maps (as in define_plot) in which to look up the hue and 
 95  ###   confidence when plotting.  This colorspec can be used by plot_unit or 
 96  ###   plot_unit_range to colorize a plot based on some property of a unit; 
 97  ###   it is not supported in other contexts.  Examples: 
 98  ###   Region::Eye0::Afferent0::colorspec='MapSpecifiesHue OrientationPreference OrientationSelectivity' 
 99  ###   Region::Ganglia*::Afferent*::colorspec='MapSpecifiesHue OrientationPreference OrientationSelectivity 
100  ###  
101  ### SpecifiedColor [hue [saturation [value]]] 
102  ###   Used to turn off color ranges, e.g. for a plot whose shape is more 
103  ###   important than the intensity of each pixel, such as a histogram.  Ignores 
104  ###   the level, and always returns the single given fixed color.  The default 
105  ###   color is a medium gray: '0.0 0.0 0.5'.  For the defaults, nearly identical 
106  ###   to 'w'. 
107  ###  
108  ###  
109  ###  
110  ### Notes on implementing the string-based palette construction, taken 
111  ### from lissom/src/colorlookup.h: 
112  ###  
113  ###    Might consider making the numcolors odd and adding a special 
114  ###    entry for the top of the range to make the range inclusive. 
115  ###    This might be more intuitive and would make plotting 
116  ###    inversely-scaled items (with a reversed color order) match 
117  ###    regularly-scaled ones. 
118  ### 
119  ###  StringBasedPalette 
120  ###  def __init__(spec,numcolors=0,scale=default_scale): 
121  ###    steps     = spec.length() 
122  ###    stepsize  = size_t(colors.size()/(steps>1 ? (steps-1) : 1)) 
123  ###    start,i 
124  ###    for (i=0,start=0; i<steps-1; i++,start+=stepsize) 
125  ###      interpolate(start, start+stepsize,color(spec[i]), color(spec[i+1])) 
126  ###    interpolate(start, colors.size(),color(spec[i]), color(spec[steps-1])) 
127  ### 
128  ###  def interpolate(start, finish, startcolor, finishcolor): 
129  ###    """ 
130  ###    Fill the lookup table (or a portion of it) with linear 
131  ###    interpolations between two colors.  The upper array index  
132  ###    and finishcolor are exclusive. 
133  ###    """ 
134  ###    assert (start<=finish); 
135  ###     
136  ###    num_vals = int(finish-start) 
137  ###    division = (num_vals!=0 ? 1.0/num_vals : 0) 
138  ###     
139  ###    rs       = startcolor.red() 
140  ###    gs       = startcolor.green() 
141  ###    bs       = startcolor.blue() 
142  ###     
143  ###    rinc     = division*(finishcolor.red()   - startcolor.red()) 
144  ###    ginc     = division*(finishcolor.green() - startcolor.green()) 
145  ###    binc     = division*(finishcolor.blue()  - startcolor.blue()) 
146  ###     
147  ###    for(i=0; i<num_vals; i++) 
148  ###      colors[start+i]=PixelType(rs+rinc*i,gs+ginc*i,bs+binc*i) 
149  ### 
150  ###  def color(char): 
151  ###    """ 
152  ###    Returns a color given a one-character name.  Uppercase is full-strength, 
153  ###    lowercase is half-strength. 
154  ###    """ 
155  ###    h=0.5 
156  ###    switch (char) 
157  ###    case 'R': p=PixelType(1,0,0); break;   case 'r': p=PixelType(h,0,0); break;  /* Red     */ 
158  ###    case 'Y': p=PixelType(1,1,0); break;   case 'y': p=PixelType(h,h,0); break;       /* Yellow  */ 
159  ###    case 'G': p=PixelType(0,1,0); break;   case 'g': p=PixelType(0,h,0); break;       /* Green   */ 
160  ###    case 'C': p=PixelType(0,1,1); break;   case 'c': p=PixelType(0,h,h); break;       /* Cyan    */ 
161  ###    case 'B': p=PixelType(0,0,1); break;   case 'b': p=PixelType(0,0,h); break;       /* Blue    */ 
162  ###    case 'M': p=PixelType(1,0,1); break;   case 'm': p=PixelType(h,0,h); break;       /* Magenta */ 
163  ###    case 'W': p=PixelType(1,1,1); break;   case 'w': p=PixelType(h,h,h); break;       /* White   */ 
164  ###    case 'K': p=PixelType(0,0,0); break;   case 'k': p=PixelType(0,0,0); break;       /* Black   */ 
165  ###    return p 
166   
167   
168   
169  # Supported background types, used for such things as determining 
170  # what color to be used for outlines, fills, etc. 
171  BLACK_BACKGROUND = 0 
172  WHITE_BACKGROUND = 1 
173   
174   
175   
176  ########################  JC: starting new implementation ############# 
177  from numpy.oldnumeric import zeros 
178   
179 -class StringBasedPalette(param.Parameterized):
180 181 ### JCALERT: What is the default scale?
182 - def __init__(spec="KRYW",num_colors=0,scale=1.0):
183 184 steps = len(spec) 185 ### JCALERT! I am not sure about that... 186 ### I have to check again with the C++ code 187 if num_colors>0: 188 colors = zeros(num_colors,'O') 189 else: 190 colors = array(252,'O') 191 192 if steps>1: 193 stepsize = len(colors)/(steps-1) 194 else: 195 stepsize = len(colors) 196 197 for i,start in zip(range(steps-1),range(0,(steps-1)*stepsize,stepsize)): 198 interpolate(start,start+stepsize,color(spec[i]),color(spec[i+1])) 199 200 ### JCALERT! I do not really understand the last line 201 interpolate(start,len(colors),color(spec[steps-1]),color(spec[steps-1]))
202 203 ### start,i 204 ### for (i=0,start=0; i<steps-1; i++,start+=stepsize) 205 ### interpolate(start, start+stepsize,color(spec[i]), color(spec[i+1])) 206 ### interpolate(start, colors.size(),color(spec[i]), color(spec[steps-1])) 207 208 209 # CB: lazy hack around the lambda that was in Palette.colors_
210 -class F(object):
211 - def __call__(self):
212 return [(i,i,i) for i in range(256)]
213 214 ### JABHACKALERT: Needs significant cleanup -- should be much more 215 ### straightforward, taking some specification and immediately 216 ### constructing a usable object (without e.g. requiring set() to be 217 ### called).
218 -class Palette(param.Parameterized):
219 """ 220 Each palette has 3*256 values that are keyed by an index. 221 This base class takes in a list of 256 triples. 222 223 A Palette object has 256 triples of RGB values ranging from 0 224 ... 255. The purpose of the class is to maintain an accurate 225 palette conversion between a number (0..255) and an RGB triple 226 even as the background of the plots change. If the background is 227 Black, then the 0 intensity should often be 0, but if the 228 background of the Plot should be white, then the 0 intensity 229 should probably be 255. This automatic updating is possible 230 through the use of Dynamic Parameters, and lambda functions. 231 232 This class stores a passed in variable named colors. If the 233 variable is a lambda function that gives the 256 triples, then it 234 will evaluate the lambda each time a datarequest is made. If it 235 is a static list, then the palette is fixed. It may be possible 236 to make Palette a 'pure' Dynamic parameter, with different types 237 of palettes setting the lambda. More power to you if you do that. 238 239 """ 240 background = param.Dynamic(default=BLACK_BACKGROUND) 241 colors_ = param.Dynamic(default=F()) #(lambda:[(i,i,i) for i in range(256)]) 242
243 - def __init__(self,**params):
244 """ 245 Does not fill in the colors, must call with a set 246 function call preferably from a subclass of Palette 247 """ 248 super(Palette,self).__init__(**params)
249
250 - def set(self, colors):
251 """ 252 Colors is a list of 256 triples, each with a 0..255 RGB value 253 or a lambda function that generates the list. Lambdas will be 254 necessary for dynamic shifts in black or white background 255 changes. 256 """ 257 self.colors_ = colors
258
259 - def flat(self):
260 """ 261 Return the palette in a flat form of 768 numbers. If the 262 colors parameter is a callable object, call it for the 263 list of values. 264 """ 265 c = self.colors_ 266 return_list = [] 267 if callable(c): 268 self.warning('Callable Parameter value returned, ', callable(c)) 269 c = c() 270 for each in c: 271 return_list.extend(list(each)) 272 return return_list
273
274 - def color(self, pos):
275 """ 276 Return the tuple of RGB color found at pos in color list 277 """ 278 c = self.colors_ 279 if callable(c): 280 self.warning('Callable Parameter value returned, ', callable(c)) 281 c = c() 282 return c[pos]
283
284 - def colors(self):
285 """ 286 Return the complete list of palette colors in tuple form 287 """ 288 c = self.colors_ 289 if callable(c): 290 self.warning('Callable Parameter value returned, ', callable(c)) 291 c = c() 292 return c
293 294 295 ### JABALERT: There is probably no reason to have this class; this 296 ### functionality is likely to be a special case of many other 297 ### classes.
298 -class Monochrome(Palette):
299 """ 300 Color goes from Black to White if background is Black. It goes 301 from White to Black if background is set to White. By using 302 a Dynamic Parameter, it should be able to update the palette 303 automatically if the plot background color changes. 304 """ 305
306 - def __init__(self,**params):
307 """ 308 Set a lambda function to the colors list which switches 309 if the background switches. This makes the accessors in 310 the parent class rather slow since it has to do a list 311 comprehension each time it accesses the list. 312 """ 313 super(Monochrome,self).__init__(**params) 314 self.colors = lambda: self.__mono_palette__()
315
316 - def __mono_palette__(self):
317 """ 318 Function to be passed as a lambda to the Parameter 319 """ 320 if self.background == BLACK_BACKGROUND: 321 set_ = [(i,i,i) for i in range(256)] 322 else: # Reverse the order 255 ... 0 323 set_ = [(i,i,i) for i in range(255,-1,-1)] 324 return set_
325