Package Biskit :: Module ColorSpectrum
[hide private]
[frames] | no frames]

Source Code for Module Biskit.ColorSpectrum

  1  ## Automatically adapted for numpy.oldnumeric Mar 26, 2007 by alter_code1.py 
  2   
  3  ## 
  4  ## Biskit, a toolkit for the manipulation of macromolecular structures 
  5  ## Copyright (C) 2004-2006 Raik Gruenberg & Johan Leckner 
  6  ## 
  7  ## This program is free software; you can redistribute it and/or 
  8  ## modify it under the terms of the GNU General Public License as 
  9  ## published by the Free Software Foundation; either version 2 of the 
 10  ## License, or any later version. 
 11  ## 
 12  ## This program is distributed in the hope that it will be useful, 
 13  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 15  ## General Public License for more details. 
 16  ## 
 17  ## You find a copy of the GNU General Public License in the file 
 18  ## license.txt along with this program; if not, write to the Free 
 19  ## Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 20   
 21  ## last $Author: graik $ 
 22  ## last $Date: 2007/04/06 10:16:06 $ 
 23  ## $Revision: 2.10 $ 
 24  ## 
 25  ## Contributions: 
 26  ## mostly copied over from the MatrixPlot class of Wolfgang Rieping 
 27  """ 
 28  Create color scales. 
 29  """ 
 30   
 31  import numpy.oldnumeric as N 
 32   
 33  from Errors import BiskitError 
 34   
 35   
36 -class ColorError( BiskitError ):
37 pass
38
39 -class ColorSpectrum:
40 """ 41 Translate a range of numeric values into a range of color codes. 42 43 Example:: 44 >>> p = ColorSpectrum( 'grey', 1, 500 ) 45 >>> single_color= p.color( 250 ) 46 >>> color_range = p.colors( range(25,250), resetLimits=0 ) 47 48 Available palettes are: 49 * grey 50 * plasma 51 * plasma2 (default) 52 * sausage (seems to have a discontinuity at 50%, see example below) 53 """ 54 55 MAX_COL = {'grey': 3 * 255, 56 'plasma': 3 * 255, 57 'plasma2': 3 * 255, 58 'sausage': 2 * 255} 59 60
61 - def __init__(self, palette="plasma2", vmin=0., vmax=1. ):
62 """ 63 Create a new palette of given type and value range. 64 65 @param palette: palette type (grey, sausage, plasma, plasma2) 66 (default: plasma2) 67 @type palette: str 68 @param vmin: smallest value covered by the color range (default: 0.) 69 @type vmin: float 70 @param vmax: largest value covered by the color range (default: 1.) 71 @type vmax: float 72 73 @raise ColorError: if palette unknown 74 """ 75 76 try: 77 self.col_func = eval( 'self._ColorSpectrum__' + palette ) 78 79 self.vmin = vmin * 1.0 80 self.vmax = vmax * 1.0 81 self.col_max = self.MAX_COL[ palette ] 82 83 except AttributeError: 84 raise ColorError, 'Unknown palette: ' + str(palette) 85 86 except IndexError, why: 87 raise ColorError, 'Undefined palette: ' + str(why)
88 89
90 - def __make_col(self, red, green, blue):
91 """ 92 Create color. 93 94 @param red: rgb color, 0-255 95 @type red: int 96 @param green: rgb color, 0-255 97 @type green: int 98 @param blue: rgb color, 0-255 99 @type blue: int 100 101 @return: color 102 @rtype: int 103 """ 104 return ((red << 16) + (green << 8) + blue)
105 106
107 - def __normalize( self, value ):
108 """ 109 Normalize values 110 111 @param value: normalization value 112 @type value: float 113 114 @return: normalized color 115 @rtype: int 116 """ 117 if self.vmax == self.vmin: 118 return self.col_max 119 return (value - self.vmin) / ( self.vmax - self.vmin ) * self.col_max
120 121
122 - def color(self, value ):
123 """ 124 Translate a single value into a color. 125 126 @param value: value to be translated into color 127 @type value: float 128 @return: color code for value 129 @rtype: int 130 """ 131 r = self.__make_col( *self.col_func(self.__normalize(value)) ) 132 133 return r
134 135
136 - def colors( self, values, resetLimits=1 ):
137 """ 138 Translate a list of values into a list of colors. 139 140 @param values: values to be translated into colors 141 @type values: [float] 142 @param resetLimits: re-define color range on max and min of values 143 (default: 1) 144 @type resetLimits: 1|0 145 146 @return: color codes 147 @rtype: [int] 148 """ 149 if resetLimits: 150 self.vmax = max( values ) * 1. 151 self.vmin = min( values ) * 1. 152 153 return [ self.color(v) for v in values ]
154 155
156 - def color_array( self, a, resetLimits=1 ):
157 """ 158 @param a: array of float 159 @type a: array of float 160 @param resetLimits: re-define color range on max and min of values 161 (default: 1) 162 @type resetLimits: 1|0 163 164 @return: matrix of color codes with same dimensions as a 165 @rtype: array of float 166 """ 167 s = N.shape( a ) 168 v = N.ravel( a ) 169 170 r = self.colors( v, resetLimits=resetLimits ) 171 172 r = N.reshape( r, s ) 173 174 return r
175 176
177 - def legend( self ):
178 """ 179 @return: color mapping for each color 180 @rtype: [ (float,int) ], value 181 """ 182 r = [] 183 step = (self.vmax - self.vmin) / self.col_max 184 185 for i in range( self.col_max ): 186 187 v = i*step + self.vmin 188 c = self.color( v ) 189 190 r.append( (v,c) ) 191 192 return r
193
194 - def __map(self, x):
195 return int(min(255, round(x)))
196 197 ## 198 ## Available color palettes 199 ## 200
201 - def __grey(self, x):
202 x = self.__map(255 * x / self.col_max) 203 return x, x, x
204
205 - def __plasma2(self, x):
206 207 blue_range = 150 208 red_range = 255 209 green_range = 255 210 211 if x <= blue_range: 212 red = 0 213 green = self.__map(x) 214 blue = self.__map(blue_range - x) 215 216 elif x <= 255: 217 red = 0 218 blue = 0 219 green = self.__map(x) 220 221 elif x > 255 + green_range: 222 x -= 255 + green_range 223 blue = 0 224 red = 255 225 green = self.__map(255 - x) 226 else: 227 x -= 255 228 blue = 0 229 red = self.__map(x) 230 green = 255 231 232 return red, green, blue
233
234 - def __plasma(self, x):
235 236 blue_range = 255 237 red_range = 255 238 green_range = 255 239 240 if x <= blue_range: 241 red = 0 242 green = self.__map(x) 243 blue = self.__map(blue_range - x) 244 245 elif x > 255 + green_range: 246 x -= 255 + green_range 247 blue = 0 248 red = 255 249 green = self.__map(255 - x) 250 else: 251 x -= 255 252 blue = 0 253 red = self.__map(x) 254 green = 255 255 256 return red, green, blue
257
258 - def __sausage(self, x):
259 260 first_half = 255 261 262 if x <= first_half: 263 red = self.__map(x) 264 green = 0 265 blue = self.__map(first_half - x) 266 267 else: 268 x -= 255 269 red = 255 270 green = self.__map(x) 271 blue = int(0.3 * 255) 272 273 return red, green, blue
274 275
276 -def colorRange( nColors, palette='plasma2' ):
277 """Quick access to a range of colors. 278 279 @param nColors: number of colors needed 280 @type nColors: int 281 @param palette: type of color spectrum 282 @type palette: str 283 @return: a range of color values 284 @rtype: [ int ] 285 """ 286 c = ColorSpectrum( palette=palette, vmin=0, vmax=1. ) 287 288 r = 1. * N.arange( 0, nColors ) / nColors 289 290 return c.colors( r )
291 292 293 294 ############# 295 ## TESTING 296 ############# 297 import Biskit.test as BT 298
299 -class Test(BT.BiskitTest):
300 """ColorSpectrum test""" 301
302 - def test_ColorSpectrum( self ):
303 """ColorSpectrum test""" 304 import biggles as B 305 306 c_grey = ColorSpectrum( 'grey', 0, 100 ) 307 c_sausage = ColorSpectrum( 'sausage', 0, 100 ) 308 c_plasma = ColorSpectrum( 'plasma', 0, 100 ) 309 c_plasma2 = ColorSpectrum( 'plasma2', 0, 100 ) 310 311 self.p = B.FramedPlot() 312 313 ## old_spectrum = tools.colorSpectrum( 100 ) 314 315 self.result = [] 316 for i in range( 100 ): 317 318 x = (i, i+1 ) 319 self.p.add( B.FillBelow( x, (1., 1.), 320 color = c_grey.color( i ) ) ) 321 self.result += [ c_grey.color( i ) ] 322 323 self.p.add( B.FillBelow( x, (0.75, 0.75), 324 color = c_sausage.color( i ) ) ) 325 self.p.add( B.FillBelow( x, (0.5, 0.5), 326 color = c_plasma.color( i ) ) ) 327 self.p.add( B.FillBelow( x, (0.25, 0.25), 328 color = c_plasma2.color( i ) ) ) 329 330 ## self.p.add( B.FillBelow( x, (0., 0.), 331 ## color = old_spectrum[i] )) 332 333 self.p.add( B.Curve( (0,100), (1.,1.)) ) 334 self.p.add( B.Curve( (0,100), (.75,.75)) ) 335 self.p.add( B.Curve( (0,100), (.5,.5) )) 336 self.p.add( B.Curve( (0,100), (0.25, 0.25)) ) 337 self.p.add( B.Curve( (0,100), (0.0, 0.0)) ) 338 339 self.p.add( B.PlotLabel( 0.5 ,0.9, 'grey') ) 340 self.p.add( B.PlotLabel( 0.5 ,0.65, 'sausage') ) 341 self.p.add( B.PlotLabel( 0.5 ,0.4, 'plasma') ) 342 self.p.add( B.PlotLabel( 0.5 ,0.15, 'plasma2') ) 343 344 if self.local or self.VERBOSITY > 2: 345 self.p.show() 346 347 self.assertEqual(self.result, self.EXPECTED)
348 349 350 EXPECTED = [0, 197379, 328965, 526344, 657930, 855309, 986895, 1184274, 1315860, 1513239, 1710618, 1842204, 2039583, 2171169, 2368548, 2500134, 2697513, 2829099, 3026478, 3158064, 3355443, 3552822, 3684408, 3881787, 4013373, 4210752, 4342338, 4539717, 4671303, 4868682, 5066061, 5197647, 5395026, 5526612, 5723991, 5855577, 6052956, 6184542, 6381921, 6513507, 6710886, 6908265, 7039851, 7237230, 7368816, 7566195, 7697781, 7895160, 8026746, 8224125, 8421504, 8553090, 8750469, 8882055, 9079434, 9211020, 9408399, 9539985, 9737364, 9868950, 10066329, 10263708, 10395294, 10592673, 10724259, 10921638, 11053224, 11250603, 11382189, 11579568, 11776947, 11908533, 12105912, 12237498, 12434877, 12566463, 12763842, 12895428, 13092807, 13224393, 13421772, 13619151, 13750737, 13948116, 14079702, 14277081, 14408667, 14606046, 14737632, 14935011, 15132390, 15263976, 15461355, 15592941, 15790320, 15921906, 16119285, 16250871, 16448250, 16579836]
351 352 if __name__ == '__main__': 353 354 BT.localTest() 355