Ticket #5601: trac_5601-builtin_colors_v7.patch

File trac_5601-builtin_colors_v7.patch, 60.5 KB (added by mpatel, 3 years ago)

Doctest fixes. Combined patch rebased vs. 4.3.3.alpha1. Apply only this patch.

  • doc/en/reference/plotting.rst

    # HG changeset patch
    # User Mitesh Patel <qed777@gmail.com>
    # Date 1266799815 28800
    # Node ID acd77172d948d4410ee5aa7b09f3b3a2330db96d
    # Parent  3556723da60080b9d67ae4cbe39f5bc74a141f59
    #5601: CSS3/SVG colors, lighter/darker, HSV/HSL/HLS, mpl cmaps.  Jason Grout
    * * *
    [mq]: trac-5601-blending.patch
    
    diff --git a/doc/en/reference/plotting.rst b/doc/en/reference/plotting.rst
    a b 2D Graphics 
    2323   sage/plot/primitive 
    2424   sage/plot/scatter_plot 
    2525   sage/plot/text 
     26   sage/plot/colors 
  • sage/plot/all.py

    diff --git a/sage/plot/all.py b/sage/plot/all.py
    a b from animate import Animation as animate 
    2525 
    2626from plot3d.tachyon import Tachyon 
    2727 
    28 from colors import Color, hue, rainbow 
     28from colors import Color, hue, rainbow, colors, colormaps 
    2929 
    3030from step import plot_step_function 
  • sage/plot/colors.py

    diff --git a/sage/plot/colors.py b/sage/plot/colors.py
    a b  
     1""" 
     2Colors 
     3 
     4This module defines a :class:`Color` object and helper functions (see, 
     5e.g., :func:`hue`, :func:`rainbow`), as well as a set of 
     6:data:`colors` and :data:`colormaps` to use with 
     7:class:`sage.plot.plot.Graphics` objects in Sage. 
     8 
     9For a list of pre-defined colors in Sage, evaluate:: 
     10 
     11    sage: sorted(colors) 
     12    ['aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'automatic', ...] 
     13 
     14Apart from 'automatic' which just an alias for 'lightblue', this list 
     15comprises the "official" W3C CSS3_ / SVG_ colors. 
     16 
     17.. _CSS3: http://www.w3.org/TR/css3-color/#svg-color 
     18.. _SVG: http://www.w3.org/TR/SVG/types.html#ColorKeywords 
     19 
     20For a list of color maps in Sage, evaluate:: 
     21 
     22    sage: sorted(colormaps) 
     23    ['Accent', 'Accent_r', 'Blues', 'Blues_r', 'BrBG', 'BrBG_r', ...] 
     24 
     25These are imported from matplotlib's cm_ module. 
     26 
     27.. _cm: http://matplotlib.sourceforge.net/api/cm_api.html 
     28""" 
     29 
    130#***************************************************************************** 
    231#  Distributed under the terms of the GNU General Public License (GPL) 
    332# 
     
    1140#                  http://www.gnu.org/licenses/ 
    1241#***************************************************************************** 
    1342 
    14 from colorsys import hsv_to_rgb 
    15 from math import modf 
     43import math 
     44import collections 
     45from colorsys import hsv_to_rgb, hls_to_rgb, rgb_to_hsv, rgb_to_hls 
    1646 
    17 colors = { 
    18     "red"   : (1.0,0.0,0.0), 
    19     "orange": (1.0,.5,0.0), 
    20     "yellow": (1.0,1.0,0.0), 
    21     "green" : (0,1.0,0.0), 
    22     "blue"  : (0.0,0.0,1.0), 
    23     "purple": (.5,0.0,1.0), 
    24     "white" : (1.0,1.0,1.0), 
    25     "black" : (0.0,0.0,0.0), 
    26     'brown': (0.65, 0.165, 0.165), 
    27     "grey"  : (.5,.5,.5), 
    28     "gray"  : (.5,.5,.5), 
    29     "lightblue" : (0.4,0.4,1.0), 
    30     "automatic": (0.4,0.4,1.0) 
     47# matplotlib color maps, loaded on-demand 
     48cm = None 
     49 
     50 
     51colors_dict = { 
     52    'automatic'              : '#add8e6',     # 173, 216, 230 
     53    'aliceblue'              : '#f0f8ff',     # 240, 248, 255 
     54    'antiquewhite'           : '#faebd7',     # 250, 235, 215 
     55    'aqua'                   : '#00ffff',     #   0, 255, 255 
     56    'aquamarine'             : '#7fffd4',     # 127, 255, 212 
     57    'azure'                  : '#f0ffff',     # 240, 255, 255 
     58    'beige'                  : '#f5f5dc',     # 245, 245, 220 
     59    'bisque'                 : '#ffe4c4',     # 255, 228, 196 
     60    'black'                  : '#000000',     #   0,   0,   0 
     61    'blanchedalmond'         : '#ffebcd',     # 255, 235, 205 
     62    'blue'                   : '#0000ff',     #   0,   0, 255 
     63    'blueviolet'             : '#8a2be2',     # 138,  43, 226 
     64    'brown'                  : '#a52a2a',     # 165,  42,  42 
     65    'burlywood'              : '#deb887',     # 222, 184, 135 
     66    'cadetblue'              : '#5f9ea0',     #  95, 158, 160 
     67    'chartreuse'             : '#7fff00',     # 127, 255,   0 
     68    'chocolate'              : '#d2691e',     # 210, 105,  30 
     69    'coral'                  : '#ff7f50',     # 255, 127,  80 
     70    'cornflowerblue'         : '#6495ed',     # 100, 149, 237 
     71    'cornsilk'               : '#fff8dc',     # 255, 248, 220 
     72    'crimson'                : '#dc143c',     # 220,  20,  60 
     73    'cyan'                   : '#00ffff',     #   0, 255, 255 
     74    'darkblue'               : '#00008b',     #   0,   0, 139 
     75    'darkcyan'               : '#008b8b',     #   0, 139, 139 
     76    'darkgoldenrod'          : '#b8860b',     # 184, 134,  11 
     77    'darkgray'               : '#a9a9a9',     # 169, 169, 169 
     78    'darkgreen'              : '#006400',     #   0, 100,   0 
     79    'darkgrey'               : '#a9a9a9',     # 169, 169, 169 
     80    'darkkhaki'              : '#bdb76b',     # 189, 183, 107 
     81    'darkmagenta'            : '#8b008b',     # 139,   0, 139 
     82    'darkolivegreen'         : '#556b2f',     #  85, 107,  47 
     83    'darkorange'             : '#ff8c00',     # 255, 140,   0 
     84    'darkorchid'             : '#9932cc',     # 153,  50, 204 
     85    'darkred'                : '#8b0000',     # 139,   0,   0 
     86    'darksalmon'             : '#e9967a',     # 233, 150, 122 
     87    'darkseagreen'           : '#8fbc8f',     # 143, 188, 143 
     88    'darkslateblue'          : '#483d8b',     #  72,  61, 139 
     89    'darkslategray'          : '#2f4f4f',     #  47,  79,  79 
     90    'darkslategrey'          : '#2f4f4f',     #  47,  79,  79 
     91    'darkturquoise'          : '#00ced1',     #   0, 206, 209 
     92    'darkviolet'             : '#9400d3',     # 148,   0, 211 
     93    'deeppink'               : '#ff1493',     # 255,  20, 147 
     94    'deepskyblue'            : '#00bfff',     #   0, 191, 255 
     95    'dimgray'                : '#696969',     # 105, 105, 105 
     96    'dimgrey'                : '#696969',     # 105, 105, 105 
     97    'dodgerblue'             : '#1e90ff',     #  30, 144, 255 
     98    'firebrick'              : '#b22222',     # 178,  34,  34 
     99    'floralwhite'            : '#fffaf0',     # 255, 250, 240 
     100    'forestgreen'            : '#228b22',     #  34, 139,  34 
     101    'fuchsia'                : '#ff00ff',     # 255,   0, 255 
     102    'gainsboro'              : '#dcdcdc',     # 220, 220, 220 
     103    'ghostwhite'             : '#f8f8ff',     # 248, 248, 255 
     104    'gold'                   : '#ffd700',     # 255, 215,   0 
     105    'goldenrod'              : '#daa520',     # 218, 165,  32 
     106    'gray'                   : '#808080',     # 128, 128, 128 
     107    'green'                  : '#008000',     #   0, 128,   0 
     108    'greenyellow'            : '#adff2f',     # 173, 255,  47 
     109    'grey'                   : '#808080',     # 128, 128, 128 
     110    'honeydew'               : '#f0fff0',     # 240, 255, 240 
     111    'hotpink'                : '#ff69b4',     # 255, 105, 180 
     112    'indianred'              : '#cd5c5c',     # 205,  92,  92 
     113    'indigo'                 : '#4b0082',     #  75,   0, 130 
     114    'ivory'                  : '#fffff0',     # 255, 255, 240 
     115    'khaki'                  : '#f0e68c',     # 240, 230, 140 
     116    'lavender'               : '#e6e6fa',     # 230, 230, 250 
     117    'lavenderblush'          : '#fff0f5',     # 255, 240, 245 
     118    'lawngreen'              : '#7cfc00',     # 124, 252,   0 
     119    'lemonchiffon'           : '#fffacd',     # 255, 250, 205 
     120    'lightblue'              : '#add8e6',     # 173, 216, 230 
     121    'lightcoral'             : '#f08080',     # 240, 128, 128 
     122    'lightcyan'              : '#e0ffff',     # 224, 255, 255 
     123    'lightgoldenrodyellow'   : '#fafad2',     # 250, 250, 210 
     124    'lightgray'              : '#d3d3d3',     # 211, 211, 211 
     125    'lightgreen'             : '#90ee90',     # 144, 238, 144 
     126    'lightgrey'              : '#d3d3d3',     # 211, 211, 211 
     127    'lightpink'              : '#ffb6c1',     # 255, 182, 193 
     128    'lightsalmon'            : '#ffa07a',     # 255, 160, 122 
     129    'lightseagreen'          : '#20b2aa',     #  32, 178, 170 
     130    'lightskyblue'           : '#87cefa',     # 135, 206, 250 
     131    'lightslategray'         : '#778899',     # 119, 136, 153 
     132    'lightslategrey'         : '#778899',     # 119, 136, 153 
     133    'lightsteelblue'         : '#b0c4de',     # 176, 196, 222 
     134    'lightyellow'            : '#ffffe0',     # 255, 255, 224 
     135    'lime'                   : '#00ff00',     #   0, 255,   0 
     136    'limegreen'              : '#32cd32',     #  50, 205,  50 
     137    'linen'                  : '#faf0e6',     # 250, 240, 230 
     138    'magenta'                : '#ff00ff',     # 255,   0, 255 
     139    'maroon'                 : '#800000',     # 128,   0,   0 
     140    'mediumaquamarine'       : '#66cdaa',     # 102, 205, 170 
     141    'mediumblue'             : '#0000cd',     #   0,   0, 205 
     142    'mediumorchid'           : '#ba55d3',     # 186,  85, 211 
     143    'mediumpurple'           : '#9370db',     # 147, 112, 219 
     144    'mediumseagreen'         : '#3cb371',     #  60, 179, 113 
     145    'mediumslateblue'        : '#7b68ee',     # 123, 104, 238 
     146    'mediumspringgreen'      : '#00fa9a',     #   0, 250, 154 
     147    'mediumturquoise'        : '#48d1cc',     #  72, 209, 204 
     148    'mediumvioletred'        : '#c71585',     # 199,  21, 133 
     149    'midnightblue'           : '#191970',     #  25,  25, 112 
     150    'mintcream'              : '#f5fffa',     # 245, 255, 250 
     151    'mistyrose'              : '#ffe4e1',     # 255, 228, 225 
     152    'moccasin'               : '#ffe4b5',     # 255, 228, 181 
     153    'navajowhite'            : '#ffdead',     # 255, 222, 173 
     154    'navy'                   : '#000080',     #   0,   0, 128 
     155    'oldlace'                : '#fdf5e6',     # 253, 245, 230 
     156    'olive'                  : '#808000',     # 128, 128,   0 
     157    'olivedrab'              : '#6b8e23',     # 107, 142,  35 
     158    'orange'                 : '#ffa500',     # 255, 165,   0 
     159    'orangered'              : '#ff4500',     # 255,  69,   0 
     160    'orchid'                 : '#da70d6',     # 218, 112, 214 
     161    'palegoldenrod'          : '#eee8aa',     # 238, 232, 170 
     162    'palegreen'              : '#98fb98',     # 152, 251, 152 
     163    'paleturquoise'          : '#afeeee',     # 175, 238, 238 
     164    'palevioletred'          : '#db7093',     # 219, 112, 147 
     165    'papayawhip'             : '#ffefd5',     # 255, 239, 213 
     166    'peachpuff'              : '#ffdab9',     # 255, 218, 185 
     167    'peru'                   : '#cd853f',     # 205, 133,  63 
     168    'pink'                   : '#ffc0cb',     # 255, 192, 203 
     169    'plum'                   : '#dda0dd',     # 221, 160, 221 
     170    'powderblue'             : '#b0e0e6',     # 176, 224, 230 
     171    'purple'                 : '#800080',     # 128,   0, 128 
     172    'red'                    : '#ff0000',     # 255,   0,   0 
     173    'rosybrown'              : '#bc8f8f',     # 188, 143, 143 
     174    'royalblue'              : '#4169e1',     #  65, 105, 225 
     175    'saddlebrown'            : '#8b4513',     # 139,  69,  19 
     176    'salmon'                 : '#fa8072',     # 250, 128, 114 
     177    'sandybrown'             : '#f4a460',     # 244, 164,  96 
     178    'seagreen'               : '#2e8b57',     #  46, 139,  87 
     179    'seashell'               : '#fff5ee',     # 255, 245, 238 
     180    'sienna'                 : '#a0522d',     # 160,  82,  45 
     181    'silver'                 : '#c0c0c0',     # 192, 192, 192 
     182    'skyblue'                : '#87ceeb',     # 135, 206, 235 
     183    'slateblue'              : '#6a5acd',     # 106,  90, 205 
     184    'slategray'              : '#708090',     # 112, 128, 144 
     185    'slategrey'              : '#708090',     # 112, 128, 144 
     186    'snow'                   : '#fffafa',     # 255, 250, 250 
     187    'springgreen'            : '#00ff7f',     #   0, 255, 127 
     188    'steelblue'              : '#4682b4',     #  70, 130, 180 
     189    'tan'                    : '#d2b48c',     # 210, 180, 140 
     190    'teal'                   : '#008080',     #   0, 128, 128 
     191    'thistle'                : '#d8bfd8',     # 216, 191, 216 
     192    'tomato'                 : '#ff6347',     # 255,  99,  71 
     193    'turquoise'              : '#40e0d0',     #  64, 224, 208 
     194    'violet'                 : '#ee82ee',     # 238, 130, 238 
     195    'wheat'                  : '#f5deb3',     # 245, 222, 179 
     196    'white'                  : '#ffffff',     # 255, 255, 255 
     197    'whitesmoke'             : '#f5f5f5',     # 245, 245, 245 
     198    'yellow'                 : '#ffff00',     # 255, 255,   0 
     199    'yellowgreen'            : '#9acd32'      # 154, 205,  50 
    31200} 
    32201 
    33 def to_mpl_color(c): 
     202 
     203def mod_one(x): 
    34204    """ 
    35     Convert a tuple or string to a matplotlib rgb color tuple. 
     205    Reduce a number modulo 1. 
    36206 
    37207    INPUT: 
    38208 
    39     -  ``c`` - a string or 3-tuple 
     209    - ``x`` - an instance of Integer, int, RealNumber, etc.; the 
     210      number to reduce 
    40211 
    41     OUTPUT: a 3-tuple of floats between 0 and 1. 
     212    OUTPUT: 
     213 
     214    - a float 
    42215 
    43216    EXAMPLES:: 
    44217 
    45         sage: from sage.plot.colors import to_mpl_color 
    46         sage: to_mpl_color('#fa0') 
     218        sage: from sage.plot.colors import mod_one 
     219        sage: mod_one(1) 
     220        1.0 
     221        sage: mod_one(7.0) 
     222        0.0 
     223        sage: mod_one(-11/7) 
     224        0.4285714285714286 
     225        sage: mod_one(pi) + mod_one(-pi) 
     226        1.0 
     227    """ 
     228    x = float(x) 
     229    if x != 1: 
     230        x = math.modf(x)[0] 
     231        if x < 0: 
     232            x += 1 
     233    return x 
     234 
     235 
     236def html_to_float(c): 
     237    """ 
     238    Convert a HTML hex color to a Red-Green-Blue (RGB) tuple. 
     239 
     240    INPUT: 
     241 
     242    - ``c`` - a string; a valid HTML hex color 
     243 
     244    OUTPUT: 
     245 
     246    - a RGB 3-tuple of floats in the interval [0.0, 1.0] 
     247 
     248    EXAMPLES:: 
     249 
     250        sage: from sage.plot.colors import html_to_float 
     251        sage: html_to_float('#fff') 
     252        (1.0, 1.0, 1.0) 
     253        sage: html_to_float('#abcdef') 
     254        (0.6705882352941176, 0.80392156862745101, 0.93725490196078431) 
     255        sage: html_to_float('#123xyz') 
     256        Traceback (most recent call last): 
     257        ... 
     258        ValueError: invalid literal for int() with base 16: '3x' 
     259    """ 
     260    if not len(c) or c[0] != '#': 
     261        raise ValueError("'%s' must be a valid HTML hex color (e.g., '#f07' or '#d6e7da')" % c) 
     262    h = c[1:] 
     263    if len(h) == 3: 
     264        h = '%s%s%s%s%s%s' % (h[0], h[0], h[1], h[1], h[2], h[2]) 
     265    elif len(h) != 6: 
     266        raise ValueError("color hex string (= '%s') must have length 3 or 6" % h) 
     267    return tuple([int(h[i:i + 2], base=16) / float(255) for i in [0, 2, 4]]) 
     268 
     269 
     270def rgbcolor(c, space='rgb'): 
     271    """ 
     272    Convert a color (string, tuple, list, or :class:`Color`) to a 
     273    mod-one reduced (see :func:`mod_one`) valid Red-Green-Blue (RGB) 
     274    tuple.  The returned tuple is also a valid matplotlib RGB color. 
     275 
     276    INPUT: 
     277 
     278    - ``c`` - a :class:`Color` instance, string (name or HTML hex), 
     279      3-tuple, or 3-list; the color to convert 
     280 
     281    - ``space`` - a string (default: 'rgb'); the color space 
     282      coordinate system (other choices are 'hsl', 'hls', and 'hsv') in 
     283      which to interpret a 3-tuple or 3-list 
     284 
     285    OUTPUT: 
     286 
     287    - a RGB 3-tuple of floats in the interval [0.0, 1.0] 
     288 
     289    EXAMPLES:: 
     290 
     291        sage: from sage.plot.colors import rgbcolor 
     292        sage: rgbcolor(Color(0.25, 0.4, 0.9)) 
     293        (0.25, 0.40000000000000002, 0.90000000000000002) 
     294        sage: rgbcolor('purple') 
     295        (0.50196078431372548, 0.0, 0.50196078431372548) 
     296        sage: rgbcolor('#fa0') 
    47297        (1.0, 0.66666666666666663, 0.0) 
    48         sage: to_mpl_color('#ffffe1') 
    49         (1.0, 1.0, 0.88235294117647056) 
    50         sage: to_mpl_color('blue') 
    51         (0.0, 0.0, 1.0) 
    52         sage: to_mpl_color([1,1/2,1/3]) 
     298        sage: rgbcolor('#ffffff') 
     299        (1.0, 1.0, 1.0) 
     300        sage: rgbcolor((1,1/2,1/3)) 
    53301        (1.0, 0.5, 0.33333333333333331) 
    54         sage: to_mpl_color([1,2,255])   # WARNING -- numbers are reduced mod 1!! 
     302        sage: rgbcolor([1,1/2,1/3]) 
     303        (1.0, 0.5, 0.33333333333333331) 
     304        sage: rgbcolor((1,1,1), space='hsv') 
    55305        (1.0, 0.0, 0.0) 
     306        sage: rgbcolor((0.5,0.75,1), space='hls') 
     307        (0.5, 0.99999999999999989, 1.0) 
     308        sage: rgbcolor((0.5,1.0,0.75), space='hsl') 
     309        (0.5, 0.99999999999999989, 1.0) 
     310        sage: rgbcolor([1,2,255])   # WARNING -- numbers are reduced mod 1!! 
     311        (1.0, 0.0, 0.0) 
     312        sage: rgbcolor('#abcd') 
     313        Traceback (most recent call last): 
     314        ... 
     315        ValueError: color hex string (= 'abcd') must have length 3 or 6 
     316        sage: rgbcolor('fff') 
     317        Traceback (most recent call last): 
     318        ... 
     319        ValueError: unknown color 'fff' 
     320        sage: rgbcolor(1) 
     321        Traceback (most recent call last): 
     322        ... 
     323        TypeError: '1' must be a Color, list, tuple, or string 
     324        sage: rgbcolor((0.2,0.8,1), space='grassmann') 
     325        Traceback (most recent call last): 
     326        ... 
     327        ValueError: space must be one of 'rgb', 'hsv', 'hsl', 'hls' 
     328        sage: rgbcolor([0.4, 0.1]) 
     329        Traceback (most recent call last): 
     330        ... 
     331        ValueError: color list or tuple '[0.400000000000000, 0.100000000000000]' must have 3 entries, one for each RGB, HSV, HLS, or HSL channel 
    56332    """ 
    57333    if isinstance(c, Color): 
    58         c = c.rgb() 
     334        return c.rgb() 
    59335 
    60336    if isinstance(c, str): 
    61337        if len(c) > 0 and c[0] == '#': 
    62             # it is some sort of html like color, e.g, #00ffff or #ab0 
    63             h = c[1:] 
    64             if len(h) == 3: 
    65                 h = '%s%s%s%s%s%s'%(h[0],h[0], h[1],h[1], h[2],h[2]) 
    66             elif len(h) != 6: 
    67                 raise ValueError, "color hex string (= '%s') must have length 3 or 6"%h 
    68             return tuple([eval('0x%s'%h[i:i+2])/float(255) for i in [0,2,4]]) 
     338            # Assume an HTML-like color, e.g., #00ffff or #ab0. 
     339            return html_to_float(c) 
    69340        else: 
    70341            try: 
    71                 return colors[c] 
     342                return colors[c].rgb() 
    72343            except KeyError: 
    73                 raise ValueError, "unknown color '%s'"%c 
     344                raise ValueError("unknown color '%s'" % c) 
    74345 
    75346    elif isinstance(c, (list, tuple)): 
    76         c = list(c) 
    77347        if len(c) != 3: 
    78             raise ValueError, "color tuple must have 3 entries, one for each RGB channel" 
    79         for i in range(len(c)): 
    80             s = float(c[i]) 
    81             if s != 1: 
    82                 s = modf(s)[0] 
    83                 if s < 0: 
    84                     s += 1 
    85             c[i] = s 
     348            raise ValueError("color list or tuple '%s' must have 3 entries, one for each RGB, HSV, HLS, or HSL channel" % (c, )) 
     349        c = map(mod_one, list(c)) 
     350        if space == 'rgb': 
     351            return tuple(c) 
     352        elif space == 'hsv': 
     353            return tuple(map(float, hsv_to_rgb(*c))) 
     354        elif space == 'hls': 
     355            return tuple(map(float, hls_to_rgb(*c))) 
     356        elif space == 'hsl': 
     357            return tuple(map(float, hls_to_rgb(c[0], c[2], c[1]))) 
     358        else: 
     359            raise ValueError("space must be one of 'rgb', 'hsv', 'hsl', 'hls'") 
    86360 
    87     else: 
    88         raise TypeError, "c must be a list, tuple, or string" 
     361    raise TypeError("'%s' must be a Color, list, tuple, or string" % c) 
    89362 
    90     return tuple(c) 
    91363 
    92 # If you change what this accepts, remember to change the documentation  
     364# For backward compatibility. 
     365to_mpl_color = rgbcolor 
     366 
     367 
     368class Color(object): 
     369    def __init__(self, r='#0000ff', g=None, b=None, space='rgb'): 
     370        """ 
     371        An Red-Green-Blue (RGB) color model color object.  For most 
     372        consumer-grade devices (e.g., CRTs, LCDs, and printers), as 
     373        well as internet applications, this is a point in the sRGB 
     374        absolute color space.  The Hue-Saturation-Lightness (HSL), 
     375        Hue-Lightness-Saturation (HLS), and Hue-Saturation-Value (HSV) 
     376        spaces are useful alternate representations, or coordinate 
     377        transformations, of this space.  Coordinates in all of these 
     378        spaces are floating point values in the interval [0.0, 1.0]. 
     379 
     380        .. note:: All instantiations of :class:`Color` are converted 
     381                  to an internal RGB floating point 3-tuple.  This is 
     382                  likely to degrade precision. 
     383 
     384        INPUT: 
     385 
     386        -  ``r,g,b`` - either a triple of floats between 0 and 1, 
     387           OR ``r`` - a color name string or HTML color hex string 
     388 
     389        - ``space`` - a string (default: 'rgb'); the coordinate system 
     390          (other choices are 'hsl', 'hls', and 'hsv') in which to 
     391          interpret a triple of floats 
     392 
     393        EXAMPLES:: 
     394 
     395            sage: Color('purple') 
     396            RGB color (0.50196078431372548, 0.0, 0.50196078431372548) 
     397            sage: Color('#8000ff') 
     398            RGB color (0.50196078431372548, 0.0, 1.0) 
     399            sage: Color(0.5,0,1) 
     400            RGB color (0.5, 0.0, 1.0) 
     401            sage: Color(0.5, 1.0, 1, space='hsv') 
     402            RGB color (0.0, 1.0, 1.0) 
     403            sage: Color(0.25, 0.5, 0.5, space='hls') 
     404            RGB color (0.50000000000000011, 0.75, 0.25) 
     405            sage: Color(1, 0, 1/3, space='hsl') 
     406            RGB color (0.33333333333333331, 0.33333333333333331, 0.33333333333333331) 
     407            sage: from sage.plot.colors import chocolate 
     408            sage: Color(chocolate) 
     409            RGB color (0.82352941176470584, 0.41176470588235292, 0.11764705882352941) 
     410        """ 
     411        if g is None and b is None: 
     412            self.__rgb = rgbcolor(r) 
     413        else: 
     414            self.__rgb = rgbcolor((r, g, b), space=space) 
     415 
     416    def __repr__(self): 
     417        """ 
     418        Return a string representation of this color. 
     419 
     420        OUTPUT: 
     421 
     422        - a string 
     423 
     424        EXAMPLES:: 
     425 
     426            sage: Color('#8000ff').__repr__() 
     427            'RGB color (0.50196078431372548, 0.0, 1.0)' 
     428            sage: Color(1, 0.5, 1/16, space='hsl').__repr__() 
     429            'RGB color (0.09375, 0.03125, 0.03125)' 
     430        """ 
     431        return "RGB color %s" % (self.__rgb, ) 
     432 
     433    def blend(self, color, fraction=0.5): 
     434        """ 
     435        Return a color blended with the given ``color`` by a given 
     436        ``fraction``.  The algorithm interpolates linearly between the 
     437        colors' corresponding R, G, and B coordinates. 
     438 
     439        INPUT: 
     440 
     441        - ``color`` - a :class:`Color` instance or float-convertible 
     442          3-tuple/list; the color with which to blend this color 
     443 
     444        - ``fraction`` - a float-convertible number; the fraction of 
     445          ``color`` to blend with this color 
     446 
     447        OUTPUT: 
     448 
     449        - a **new** :class:`Color` instance 
     450 
     451        EXAMPLES:: 
     452 
     453            sage: from sage.plot.colors import red, blue, lime 
     454            sage: red.blend(blue) 
     455            RGB color (0.5, 0.0, 0.5) 
     456            sage: red.blend(blue, fraction=0.0) 
     457            RGB color (1.0, 0.0, 0.0) 
     458            sage: red.blend(blue, fraction=1.0) 
     459            RGB color (0.0, 0.0, 1.0) 
     460            sage: lime.blend((0.3, 0.5, 0.7)) 
     461            RGB color (0.14999999999999999, 0.75, 0.34999999999999998) 
     462            sage: blue.blend(blue) 
     463            RGB color (0.0, 0.0, 1.0) 
     464            sage: red.blend(lime, fraction=0.3) 
     465            RGB color (0.69999999999999996, 0.29999999999999999, 0.0) 
     466            sage: blue.blend((0.0, 0.9, 0.2), fraction=0.2) 
     467            RGB color (0.0, 0.18000000000000002, 0.84000000000000008) 
     468            sage: red.blend(0.2) 
     469            Traceback (most recent call last): 
     470            ... 
     471            TypeError: 0.200000000000000 must be a Color or float-convertible 3-tuple/list 
     472        """ 
     473        fraction = float(fraction) 
     474        if isinstance(color, Color): 
     475            color = color.__rgb 
     476        if isinstance(color, (list, tuple)) and len(color) == 3: 
     477            color = map(float, color) 
     478            return Color(rgbcolor([(1 - fraction) * a + fraction * b 
     479                                   for a, b in zip(self.__rgb, color)])) 
     480        raise TypeError("%s must be a Color or float-convertible 3-tuple/list" % (color, )) 
     481 
     482    def __add__(self, right): 
     483        """ 
     484        Return a color "added" on the right to another color, with 
     485        :meth:`blend`. 
     486 
     487        INPUT: 
     488 
     489        - ``right`` - a :class:`Color` instance or float-convertible 
     490          3-tuple/list 
     491 
     492        OUTPUT: 
     493 
     494        - a **new** :class:`Color` instance 
     495 
     496        EXAMPLES:: 
     497 
     498            sage: from sage.plot.colors import red, blue, lime 
     499            sage: red + blue + lime 
     500            RGB color (0.25, 0.5, 0.25) 
     501            sage: from sage.plot.colors import cyan, magenta, yellow 
     502            sage: cyan + magenta + yellow 
     503            RGB color (0.75, 0.75, 0.5) 
     504            sage: c1 = Color(0.1, 0.5, 0.8); c2 = Color(0.2, 0.4, 0.7, space='hsv') 
     505            sage: c1 + 0.1 
     506            Traceback (most recent call last): 
     507            ... 
     508            TypeError: 0.100000000000000 must be a Color or float-convertible 3-tuple/list 
     509            sage: c2 + [0.5, 0.2, 0.9] 
     510            RGB color (0.57199999999999995, 0.44999999999999996, 0.66000000000000003) 
     511            sage: c1.__add__(red).__add__((0.9, 0.2, 1/3)) 
     512            RGB color (0.72500000000000009, 0.22500000000000001, 0.3666666666666667) 
     513            sage: c1 + c2 
     514            RGB color (0.37199999999999994, 0.59999999999999998, 0.60999999999999999) 
     515        """ 
     516        return self.blend(right) 
     517 
     518    def __radd__(self, left): 
     519        """ 
     520        Return a color "added" on the left to another color, with 
     521        :meth:`blend`. 
     522 
     523        INPUT: 
     524 
     525        - ``left`` - a :class:`Color` instance or float-convertible 
     526          3-tuple/list 
     527 
     528        OUTPUT: 
     529 
     530        - a **new** :class:`Color` instance 
     531 
     532        EXAMPLES:: 
     533 
     534            sage: from sage.plot.colors import olive, orchid 
     535            sage: olive + orchid 
     536            RGB color (0.67843137254901964, 0.47058823529411764, 0.41960784313725491) 
     537            sage: d1 = Color(0.1, 0.5, 0.8, space='hls'); d2 = Color(0.2, 0.4, 0.7) 
     538            sage: [0.5, 0.2, 0.9] + d2 
     539            RGB color (0.34999999999999998, 0.30000000000000004, 0.80000000000000004) 
     540            sage: 0.1 + d1 
     541            Traceback (most recent call last): 
     542            ... 
     543            TypeError: 0.100000000000000 must be a Color or float-convertible 3-tuple/list 
     544            sage: d2.__radd__(Color('brown')).__radd__((0.9, 0.2, 1/3)) 
     545            RGB color (0.66176470588235303, 0.2411764705882353, 0.38284313725490193) 
     546        """ 
     547        return self + left 
     548 
     549    def __mul__(self, right): 
     550        """ 
     551        Return a color whose RGB coordinates are this color's 
     552        coordinates multiplied on the right by a scalar. 
     553 
     554        INPUT: 
     555 
     556        - ``right`` - a float-convertible number 
     557 
     558        OUTPUT: 
     559 
     560        - a **new** :class:`Color` instance 
     561 
     562        EXAMPLES:: 
     563 
     564            sage: Color('yellow') * 0.5 
     565            RGB color (0.5, 0.5, 0.0) 
     566            sage: Color('yellow') * (9.0 / 8.0)   # reduced modulo 1.0 
     567            RGB color (0.125, 0.125, 0.0) 
     568            sage: from sage.plot.colors import cyan, grey, indianred 
     569            sage: cyan * 0.3 + grey * 0.1 + indianred * 0.6 
     570            RGB color (0.25372549019607843, 0.19578431372549021, 0.19578431372549021) 
     571            sage: indianred.__mul__(42) 
     572            RGB color (0.76470588235294201, 0.15294117647058769, 0.15294117647058769) 
     573        """ 
     574        right = float(right) 
     575        return Color([x * right for x in self.__rgb]) 
     576 
     577    def __rmul__(self, left): 
     578        """ 
     579        Return a color whose RGB coordinates are this color's 
     580        coordinates multiplied on the left by a scalar. 
     581 
     582        INPUT: 
     583 
     584        - ``left`` - a float-convertible number 
     585 
     586        OUTPUT: 
     587 
     588        - a **new** :class:`Color` instance 
     589 
     590        EXAMPLES:: 
     591 
     592            sage: from sage.plot.colors import aqua, cornsilk, tomato 
     593            sage: 0.3 * aqua 
     594            RGB color (0.0, 0.29999999999999999, 0.29999999999999999) 
     595            sage: Color('indianred').__rmul__(42) 
     596            RGB color (0.76470588235294201, 0.15294117647058769, 0.15294117647058769) 
     597        """ 
     598        return self * left 
     599 
     600    def __div__(self, right): 
     601        """ 
     602        Return a color whose RGB coordinates are this color's 
     603        coordinates divided by a scalar.  This method is called for 
     604        "classic division." 
     605 
     606        INPUT: 
     607 
     608        - ``right`` - a float-convertible, non-zero number 
     609 
     610        OUTPUT: 
     611 
     612        - a **new** instance of :class:`Color` 
     613 
     614        EXAMPLES:: 
     615 
     616            sage: from sage.plot.colors import papayawhip, yellow 
     617            sage: yellow / 4 
     618            RGB color (0.25, 0.25, 0.0) 
     619            sage: yellow.__div__(4) 
     620            RGB color (0.25, 0.25, 0.0) 
     621            sage: (papayawhip + Color(0.5, 0.5, 0.1) + yellow) / 3.0 
     622            RGB color (0.29166666666666663, 0.28643790849673201, 0.077941176470588236) 
     623            sage: vector((papayawhip / 2).rgb()) == vector((papayawhip * 0.5).rgb()) 
     624            True 
     625            sage: yellow.__div__(1/4) 
     626            RGB color (0.0, 0.0, 0.0) 
     627            sage: Color('black') / 0.0 
     628            Traceback (most recent call last): 
     629            ... 
     630            ZeroDivisionError: float division 
     631            sage: papayawhip / yellow 
     632            Traceback (most recent call last): 
     633            ... 
     634            TypeError: float() argument must be a string or a number 
     635        """ 
     636        return self * (float(1.0) / float(right)) 
     637 
     638    def __truediv__(self, right): 
     639        """ 
     640        Return a color whose RGB coordinates are this color's 
     641        coordinates divided by a scalar.  This method is called for 
     642        "true division." 
     643 
     644        INPUT: 
     645 
     646        - ``right`` - a float-convertible, non-zero number 
     647 
     648        OUTPUT: 
     649 
     650        - a **new** instance of :class:`Color` 
     651 
     652        EXAMPLES:: 
     653 
     654            sage: from __future__ import division 
     655            sage: from sage.plot.colors import yellow, gold 
     656            sage: yellow / 4 
     657            RGB color (0.25, 0.25, 0.0) 
     658            sage: yellow.__truediv__(4) 
     659            RGB color (0.25, 0.25, 0.0) 
     660            sage: gold / pi + yellow * e 
     661            RGB color (0.51829585732141792, 0.49333037605210095, 0.0) 
     662        """ 
     663        return self.__div__(right) 
     664 
     665    def __hex__(self): 
     666        """ 
     667        Return a hexadecimal string representation of this color. 
     668        This is just the color's HTML hex representation without the 
     669        leading '#'. 
     670 
     671        OUTPUT: 
     672 
     673        - a string of length 6 
     674 
     675        EXAMPLES:: 
     676 
     677            sage: from sage.plot.colors import whitesmoke 
     678            sage: hex(whitesmoke) 
     679            'f5f5f5' 
     680            sage: whitesmoke.html_color() == '#' + hex(whitesmoke) 
     681            True 
     682            sage: hex(Color(0.5, 1.0, 1.0, space='hsv')) 
     683            '00ffff' 
     684            sage: set([len(hex(Color(t, 1-t, t * t))) for t in srange(0, 1, 0.1)]) 
     685            set([6]) 
     686        """ 
     687        return self.html_color()[1:] 
     688 
     689    def __iter__(self): 
     690        """ 
     691        Return an iterator over the RGB coordinates of this color. 
     692 
     693        OUTPUT: 
     694 
     695        - a tupleiterator 
     696 
     697        EXAMPLES:: 
     698 
     699            sage: from sage.plot.colors import dodgerblue, maroon 
     700            sage: r, g, b = dodgerblue 
     701            sage: r 
     702            0.11764705882352941 
     703            sage: g 
     704            0.56470588235294117 
     705            sage: b 
     706            1.0 
     707            sage: vector(maroon) == vector(Color(maroon)) == vector(Color('maroon')) 
     708            True 
     709        """ 
     710        return iter(self.__rgb) 
     711 
     712    def __getitem__(self, i): 
     713        """ 
     714        Return the Red (0th), Green (1st), or Blue (2nd) coordinate of this 
     715        color via index access. 
     716 
     717        INPUT: 
     718 
     719        - ``i`` - an integer; the 0-based coordinate to retrieve 
     720 
     721        OUTPUT: 
     722 
     723        - a float 
     724 
     725        EXAMPLES:: 
     726 
     727            sage: from sage.plot.colors import crimson, midnightblue 
     728            sage: Color('#badfad')[0] 
     729            0.72941176470588232 
     730            sage: (crimson[0], crimson[1], crimson[2]) == crimson.rgb() 
     731            True 
     732            sage: midnightblue[2] == midnightblue[-1] 
     733            True 
     734            sage: midnightblue[3] 
     735            Traceback (most recent call last): 
     736            ... 
     737            IndexError: tuple index out of range 
     738        """ 
     739        return self.__rgb[i] 
     740 
     741    def rgb(self): 
     742        """ 
     743        Return the underlying Red-Green-Blue (RGB) coordinates of this 
     744        color. 
     745 
     746        OUTPUT: 
     747 
     748        - a 3-tuple of floats 
     749 
     750        EXAMPLES:: 
     751 
     752            sage: Color(0.3, 0.5, 0.7).rgb() 
     753            (0.29999999999999999, 0.5, 0.69999999999999996) 
     754            sage: Color('#8000ff').rgb() 
     755            (0.50196078431372548, 0.0, 1.0) 
     756            sage: from sage.plot.colors import orange 
     757            sage: orange.rgb() 
     758            (1.0, 0.6470588235294118, 0.0) 
     759            sage: Color('magenta').rgb() 
     760            (1.0, 0.0, 1.0) 
     761            sage: Color(1, 0.7, 0.9, space='hsv').rgb() 
     762            (0.90000000000000002, 0.27000000000000007, 0.27000000000000007) 
     763        """ 
     764        return self.__rgb 
     765 
     766    def hls(self): 
     767        """ 
     768        Return the Hue-Lightness-Saturation (HLS) coordinates of this 
     769        color. 
     770 
     771        OUTPUT: 
     772 
     773        - a 3-tuple of floats 
     774 
     775        EXAMPLES:: 
     776 
     777            sage: Color(0.3, 0.5, 0.7, space='hls').hls() 
     778            (0.30000000000000004, 0.5, 0.69999999999999996) 
     779            sage: Color(0.3, 0.5, 0.7, space='hsl').hls() 
     780            (0.30000000000000004, 0.69999999999999996, 0.50000000000000011) 
     781            sage: Color('#aabbcc').hls() 
     782            (0.58333333333333337, 0.73333333333333339, 0.25000000000000017) 
     783            sage: from sage.plot.colors import orchid 
     784            sage: orchid.hls() 
     785            (0.83962264150943389, 0.64705882352941169, 0.58888888888888891) 
     786        """ 
     787        return tuple(map(float, rgb_to_hls(*self.__rgb))) 
     788 
     789    def hsl(self): 
     790        """ 
     791        Return the Hue-Saturation-Lightness (HSL) coordinates of this 
     792        color. 
     793 
     794        OUTPUT: 
     795 
     796        - a 3-tuple of floats 
     797 
     798        EXAMPLES:: 
     799 
     800            sage: Color(1,0,0).hsl() 
     801            (0.0, 1.0, 0.5) 
     802            sage: from sage.plot.colors import orchid 
     803            sage: orchid.hsl() 
     804            (0.83962264150943389, 0.58888888888888891, 0.64705882352941169) 
     805            sage: Color('#aabbcc').hsl() 
     806            (0.58333333333333337, 0.25000000000000017, 0.73333333333333339) 
     807        """ 
     808        h, l, s = tuple(map(float, rgb_to_hls(*self.__rgb))) 
     809        return (h, s, l) 
     810 
     811    def hsv(self): 
     812        """ 
     813        Return the Hue-Saturation-Value (HSV) coordinates of this 
     814        color. 
     815 
     816        OUTPUT: 
     817 
     818        - a 3-tuple of floats 
     819 
     820        EXAMPLES:: 
     821 
     822            sage: from sage.plot.colors import red 
     823            sage: red.hsv() 
     824            (0.0, 1.0, 1.0) 
     825            sage: Color(1,1,1).hsv() 
     826            (0.0, 0.0, 1.0) 
     827            sage: Color('gray').hsv() 
     828            (0.0, 0.0, 0.50196078431372548) 
     829        """ 
     830        return tuple(map(float, rgb_to_hsv(*self.__rgb))) 
     831 
     832    def html_color(self): 
     833        """ 
     834        Return a HTML hex representation for this color. 
     835 
     836        OUTPUT: 
     837 
     838        - a string of length 7. 
     839 
     840        EXAMPLES:: 
     841 
     842            sage: Color('yellow').html_color() 
     843            '#ffff00' 
     844            sage: Color('#fedcba').html_color() 
     845            '#fedcba' 
     846            sage: Color(0.0, 1.0, 0.0).html_color() 
     847            '#00ff00' 
     848            sage: from sage.plot.colors import honeydew 
     849            sage: honeydew.html_color() 
     850            '#f0fff0' 
     851        """ 
     852        return float_to_html(*self.__rgb) 
     853 
     854    def lighter(self, fraction=1.0/3.0): 
     855        """ 
     856        Return a lighter "shade" of this RGB color by 
     857        :meth:`blend`-ing it with white.  This is **not** an inverse 
     858        of :meth:`darker`. 
     859 
     860        INPUT: 
     861 
     862        - ``fraction`` - a float (default: 1.0/3.0); blending fraction 
     863          to apply 
     864 
     865        OUTPUT: 
     866 
     867        - a **new** instance of :class:`Color` 
     868 
     869        EXAMPLES:: 
     870 
     871            sage: from sage.plot.colors import khaki 
     872            sage: khaki.lighter() 
     873            RGB color (0.96078431372549034, 0.934640522875817, 0.69934640522875824) 
     874            sage: Color('white').lighter().darker() 
     875            RGB color (0.66666666666666674, 0.66666666666666674, 0.66666666666666674) 
     876            sage: Color('#abcdef').lighter(1/4) 
     877            RGB color (0.75294117647058822, 0.85294117647058831, 0.95294117647058818) 
     878            sage: Color(1, 0, 8/9, space='hsv').lighter() 
     879            RGB color (0.92592592592592604, 0.92592592592592604, 0.92592592592592604) 
     880        """ 
     881        return self.blend((1.0, 1.0, 1.0), fraction) 
     882 
     883    def darker(self, fraction=1.0/3.0): 
     884        """ 
     885        Return a darker "shade" of this RGB color by :meth:`blend`-ing 
     886        it with black.  This is **not** an inverse of :meth:`lighter`. 
     887 
     888        INPUT: 
     889 
     890        - ``fraction`` - a float (default: 1.0/3.0); blending fraction 
     891          to apply 
     892 
     893        OUTPUT: 
     894 
     895        - a new instance of :class:`Color` 
     896 
     897        EXAMPLES:: 
     898 
     899            sage: from sage.plot.colors import black 
     900            sage: vector(black.darker().rgb()) == vector(black.rgb()) 
     901            True 
     902            sage: Color(0.4, 0.6, 0.8).darker(0.1) 
     903            RGB color (0.36000000000000004, 0.54000000000000004, 0.72000000000000008) 
     904            sage: Color(.1,.2,.3,space='hsl').darker() 
     905            RGB color (0.24000000000000002, 0.20800000000000002, 0.16) 
     906        """ 
     907        return self.blend((0.0, 0.0, 0.0), fraction) 
     908 
     909 
     910class ColorsDict(dict): 
     911    """ 
     912    A dict-like collection of colors, accessible via key or attribute. 
     913    For a list of color names, evaluate:: 
     914 
     915        sage: sorted(colors) 
     916        ['aliceblue', 'antiquewhite', 'aqua', 'aquamarine', ...] 
     917    """ 
     918    def __init__(self): 
     919        """ 
     920        Constructs a dict-like collection of colors.  The keys are the 
     921        color names (i.e., strings) and the values are RGB 3-tuples of 
     922        floats. 
     923 
     924        EXAMPLES:: 
     925 
     926            sage: from sage.plot.colors import ColorsDict 
     927            sage: cols = ColorsDict() 
     928            sage: set([(type(c), type(cols[c])) for c in cols]) 
     929            set([(<type 'str'>, <class 'sage.plot.colors.Color'>)]) 
     930            sage: sorted(cols) 
     931            ['aliceblue', 'antiquewhite', 'aqua', 'aquamarine', ...] 
     932            sage: len(cols) 
     933            148 
     934        """ 
     935        # Convert the colors_dict defined above to Color instances. 
     936        for k in colors_dict: 
     937            self[k] = Color(colors_dict[k]) 
     938 
     939    def __getattr__(self, name): 
     940        """ 
     941        Gets a color via attribute access. 
     942 
     943        INPUT: 
     944 
     945        - ``name`` - a string; the name of the color to return 
     946 
     947        OUTPUT: 
     948 
     949        - a RGB 3-tuple of floats 
     950 
     951        EXAMPLES:: 
     952 
     953            sage: from sage.plot.colors import ColorsDict, blue 
     954            sage: cols = ColorsDict() 
     955            sage: cols.blue 
     956            RGB color (0.0, 0.0, 1.0) 
     957            sage: cols['blue'] 
     958            RGB color (0.0, 0.0, 1.0) 
     959            sage: blue 
     960            RGB color (0.0, 0.0, 1.0) 
     961        """ 
     962        return self.__getitem__(name) 
     963 
     964    def __dir__(self): 
     965        """ 
     966        Returns an approximate list of attribute names, including the 
     967        color names. 
     968 
     969        OUTPUT: 
     970 
     971        - a list of strings 
     972 
     973        EXAMPLES:: 
     974 
     975            sage: from sage.plot.colors import ColorsDict 
     976            sage: cols = ColorsDict() 
     977            sage: 'green' in dir(cols) 
     978            True 
     979        """ 
     980        methods = ['__dir__', '__getattr__'] 
     981        return dir(super(ColorsDict, self)) + methods + self.keys() 
     982 
     983colors = ColorsDict() 
     984 
     985# Add convenient module-scope colors.  These are Color instances. 
     986for c in colors: 
     987    vars()[c] = colors[c] 
     988 
     989 
     990def hue(h, s=1, v=1): 
     991    r""" 
     992    Convert a Hue-Saturation-Value (HSV) color tuple to a valid 
     993    Red-Green-Blue (RGB) tuple.  All three inputs should lie in the 
     994    interval [0.0, 1.0]; otherwise, they are reduced modulo 1 (see 
     995    :func:`mod_one`).  In particular ``h=0`` and ``h=1`` yield red, 
     996    with the intermediate hues orange, yellow, green, cyan, blue, and 
     997    violet as ``h`` increases. 
     998 
     999    This function makes it easy to sample a broad range of colors for 
     1000    graphics:: 
     1001 
     1002        sage: p = Graphics() 
     1003        sage: for phi in xsrange(0, 2 * pi, 1 / pi): 
     1004        ...       p += plot(sin(x + phi), (x, -7, 7), rgbcolor = hue(phi)) 
     1005        sage: p 
     1006 
     1007    INPUT: 
     1008 
     1009    - ``h`` - a number; the color's hue 
     1010 
     1011    - ``s`` - a number (default: 1); the color's saturation 
     1012 
     1013    - ``v`` - a number (default: 1); the color's value 
     1014 
     1015    OUTPUT: 
     1016 
     1017    - a RGB 3-tuple of floats in the interval [0.0, 1.0] 
     1018 
     1019    EXAMPLES:: 
     1020 
     1021        sage: hue(0.6) 
     1022        (0.0, 0.40000000000000036, 1.0) 
     1023        sage: from sage.plot.colors import royalblue 
     1024        sage: royalblue 
     1025        RGB color (0.25490196078431371, 0.41176470588235292, 0.88235294117647056) 
     1026        sage: hue(*royalblue.hsv()) 
     1027        (0.25490196078431371, 0.41176470588235292, 0.88235294117647056) 
     1028 
     1029    .. note :: The HSV to RGB coordinate transformation itself is 
     1030               given in the source code for the Python library's 
     1031               :mod:`colorsys` module:: 
     1032 
     1033                   sage: from colorsys import hsv_to_rgb    # not tested 
     1034                   sage: hsv_to_rgb??                       # not tested 
     1035    """ 
     1036    return tuple(map(float, hsv_to_rgb(mod_one(h), mod_one(s), mod_one(v)))) 
     1037 
     1038 
     1039def float_to_html(r, g, b): 
     1040    """ 
     1041    Converts a Red-Green-Blue (RGB) color tuple to a HTML hex color. 
     1042    Each input value should be in the interval [0.0, 1.0]; otherwise, 
     1043    the values are first reduced modulo one (see :func:`mod_one`). 
     1044 
     1045    INPUT: 
     1046 
     1047    - ``r`` - a number; the RGB color's "red" intensity 
     1048 
     1049    - ``g`` - a number; the RGB color's "green" intensity 
     1050 
     1051    - ``b`` - a number; the RGB color's "blue" intensity 
     1052 
     1053    OUTPUT: 
     1054 
     1055    - a string of length 7, starting with '#' 
     1056 
     1057    EXAMPLES:: 
     1058 
     1059        sage: from sage.plot.colors import float_to_html 
     1060        sage: float_to_html(1.,1.,0.) 
     1061        '#ffff00' 
     1062        sage: float_to_html(.03,.06,.02) 
     1063        '#070f05' 
     1064        sage: float_to_html(*Color('brown').rgb()) 
     1065        '#a52a2a' 
     1066        sage: float_to_html((0.2, 0.6, 0.8)) 
     1067        Traceback (most recent call last): 
     1068        ... 
     1069        TypeError: float_to_html() takes exactly 3 arguments (1 given) 
     1070    """ 
     1071    # TODO: figure out why this is necessary 
     1072    from sage.rings.integer import Integer 
     1073    from math import floor 
     1074 
     1075    r, g, b = map(mod_one, (r, g, b)) 
     1076    rr = Integer(int(floor(r * 255))).str(base = 16) 
     1077    gg = Integer(int(floor(g * 255))).str(base = 16) 
     1078    bb = Integer(int(floor(b * 255))).str(base = 16) 
     1079 
     1080    rr = '0' * (2 - len(rr)) + rr 
     1081    gg = '0' * (2 - len(gg)) + gg 
     1082    bb = '0' * (2 - len(bb)) + bb 
     1083 
     1084    return '#' + rr + gg + bb 
     1085 
     1086 
     1087def rainbow(n, format='hex'): 
     1088    """ 
     1089    Returns a list of colors sampled at equal intervals over the 
     1090    spectrum, from Hue-Saturation-Value (HSV) coordinates (0, 1, 1) to 
     1091    (1, 1, 1).  This range is red at the extremes, but it covers 
     1092    orange, yellow, green, cyan, blue, violet, and many other hues in 
     1093    between.  This function is particularly useful for representing 
     1094    vertex partitions on graphs. 
     1095 
     1096    INPUT: 
     1097 
     1098    - ``n`` - a number; the length of the list 
     1099 
     1100    - ``format`` - a string (default: 'hex'); the output format for 
     1101      each color in the list; the other choice is 'rgbtuple' 
     1102 
     1103    OUTPUT: 
     1104 
     1105    - a list of strings or RGB 3-tuples of floats in the interval 
     1106      [0.0, 1.0] 
     1107 
     1108    EXAMPLES:: 
     1109 
     1110        sage: from sage.plot.colors import rainbow 
     1111        sage: rainbow(7) 
     1112        ['#ff0000', '#ffda00', '#48ff00', '#00ff91', '#0091ff', '#4800ff', '#ff00da'] 
     1113        sage: rainbow(7, 'rgbtuple') 
     1114        [(1.0, 0.0, 0.0), (1.0, 0.8571428571428571, 0.0), (0.28571428571428581, 1.0, 0.0), (0.0, 1.0, 0.57142857142857117), (0.0, 0.57142857142857162, 1.0), (0.2857142857142847, 0.0, 1.0), (1.0, 0.0, 0.85714285714285765)] 
     1115 
     1116    AUTHORS: 
     1117 
     1118    - Robert L. Miller 
     1119 
     1120    - Karl-Dieter Crisman (directly use :func:`hsv_to_rgb` for hues) 
     1121    """ 
     1122    from sage.rings.integer import Integer 
     1123    n = Integer(n) # In case n is a Python int and i/n below would give 0! 
     1124    R = [] 
     1125 
     1126    for i in range(n): 
     1127        R.append(tuple(map(float, hsv_to_rgb(i / n, 1, 1)))) 
     1128 
     1129    if format == 'rgbtuple': 
     1130        return R 
     1131    elif format == 'hex': 
     1132        for j in range(len(R)): 
     1133            R[j] = float_to_html(*R[j]) 
     1134        return R 
     1135 
     1136 
     1137# If you change what this accepts, remember to change the documentation 
    931138# about cmap where it is used and to test these classes. 
    941139def get_cmap(cmap): 
    951140    r""" 
    96     Returns the colormap corresponding to cmap. 
     1141    Returns a color map (actually, a matplotlib :class:`Colormap` 
     1142    object), given its name or a [mixed] list/tuple of RGB list/tuples 
     1143    and color names.  For a list of map names, evaluate:: 
     1144 
     1145        sage: sorted(colormaps) 
     1146        ['Accent', 'Accent_r', 'Blues', 'Blues_r', ...] 
     1147 
     1148    See :func:`rgbcolor` for valid list/tuple element formats. 
    971149 
    981150    INPUT: 
    991151 
    100     -  ``cmap`` - a colormap description (type ``import  
    101         matplotlib.cm; matplotlib.cm.datad.keys()`` for valid names) 
     1152    - ``cmap`` - a string, list, tuple, or 
     1153      :class:`matplotlib.colors.Colormap`; a string must be a valid 
     1154      color map name 
     1155 
     1156    OUTPUT: 
     1157 
     1158    - a :class:`matplotlib.colors.Colormap` instance 
    1021159 
    1031160    EXAMPLES:: 
    1041161 
    def get_cmap(cmap): 
    1091166        <matplotlib.colors.ListedColormap instance at 0x...> 
    1101167        sage: get_cmap(['green', 'lightblue', 'blue']) 
    1111168        <matplotlib.colors.ListedColormap instance at 0x...> 
     1169        sage: get_cmap(((0.5, 0.3, 0.2), [1.0, 0.0, 0.5], 'purple', Color(0.5,0.5,1, space='hsv'))) 
     1170        <matplotlib.colors.ListedColormap instance at 0x...> 
    1121171        sage: get_cmap('jolies') 
    1131172        Traceback (most recent call last): 
    1141173        ... 
    def get_cmap(cmap): 
    1181177        ... 
    1191178        RuntimeError: Color map mpl not known (type import matplotlib.cm; matplotlib.cm.datad.keys() for valid names) 
    1201179    """ 
    121     #cm is the matplotlib color map module 
    122     from matplotlib import cm 
     1180    # matplotlib color maps 
     1181    global cm 
     1182    if not cm: 
     1183        from matplotlib import cm 
    1231184    from matplotlib.colors import ListedColormap, Colormap 
     1185 
    1241186    if isinstance(cmap, Colormap): 
    1251187        return cmap 
     1188 
    1261189    elif isinstance(cmap, str): 
    1271190        if not cmap in cm.datad.keys(): 
    128             raise RuntimeError, "Color map %s not known (type import matplotlib.cm; matplotlib.cm.datad.keys() for valid names)"%cmap 
     1191            raise RuntimeError("Color map %s not known (type import matplotlib.cm; matplotlib.cm.datad.keys() for valid names)" % cmap) 
    1291192        return cm.__dict__[cmap] 
     1193 
    1301194    elif isinstance(cmap, (list, tuple)): 
    1311195        cmap = map(rgbcolor, cmap) 
    1321196        return ListedColormap(cmap) 
    1331197 
    1341198 
    135 def hue(h, s=1, v=1): 
     1199class Colormaps(collections.MutableMapping): 
    1361200    """ 
    137     hue(h,s=1,v=1) where ``h`` stands for hue, ``s`` stands for saturation, 
    138     ``v`` stands for value. hue returns a tuple of rgb intensities (r, g, 
    139     b).  All values are in the range 0 to 1.  Inputs ``h=0`` and ``h=1``  
    140     yield red, while intermediate values yield orange, yellow, etc. with 
    141     increasing input. 
     1201    A dict-like collection of lazily-loaded matplotlib color maps. 
     1202    For a list of map names, evaluate:: 
    1421203 
    143     The specifics of how hue, saturation, and value turn into an RGB 
    144     color can be accessed from the source code of ``hsv_to_rgb`` by 
    145     entering first ``from colorsys import hsv_to_rgb`` and then  
    146     ``hsv_to_rgb??``. 
     1204        sage: sorted(colormaps) 
     1205        ['Accent', 'Accent_r', 'Blues', 'Blues_r', ...] 
     1206    """ 
     1207    def __init__(self): 
     1208        """ 
     1209        Constructs an empty mutable collection of color maps. 
    1471210 
    148     INPUT: 
     1211        EXAMPLES:: 
    1491212 
    150     -  ``h, s, v`` - real numbers between 0 and 1. Note that if any are 
    151        not in this range they are automatically normalized to be in  
    152        this range by reducing them modulo 1.     
     1213            sage: from sage.plot.colors import Colormaps 
     1214            sage: maps = Colormaps() 
     1215            sage: len(maps.maps) 
     1216            0 
     1217        """ 
     1218        self.maps = {} 
    1531219 
    154     OUTPUT: A valid RGB tuple. 
    155      
    156     EXAMPLES:: 
    157      
    158         sage: hue(0.6) 
    159         (0.0, 0.40000000000000036, 1.0) 
    160      
    161     ``hue`` is an easy way of getting a broader range of colors for 
    162     graphics:: 
    163      
    164         sage: plot(sin, -2, 2, rgbcolor=hue(0.6)) 
    165     """ 
    166     h = float(h); s = float(s); v = float(v) 
    167     if h != 1: 
    168         h = modf(h)[0] 
    169         if h < 0: 
    170             h += 1 
    171     if s != 1: 
    172         s = modf(s)[0] 
    173         if s < 0: 
    174             s += 1 
    175     if v != 1: 
    176         v = modf(v) 
    177         if v < 0: 
    178             v += 1 
    179     c = hsv_to_rgb(h, s, v) 
    180     return (float(c[0]),float(c[1]),float(c[2])) 
     1220    def load_maps(self): 
     1221        """ 
     1222        If it's necessary, loads matplotlib's color maps and adds them 
     1223        to the collection. 
    1811224 
    182 def float_to_html(r, g, b): 
    183     """ 
    184     This is a function to present tuples of RGB floats as HTML-happy 
    185     hex for matplotlib. The input values should each be between 0 and 1. 
     1225        EXAMPLES:: 
    1861226 
    187     This may not seem necessary, but there are some  odd cases where 
    188     matplotlib is just plain schizophrenic -- for an example, do 
    189      
    190     EXAMPLES:: 
    191      
    192         sage: vertex_colors = {(1.0, 0.8571428571428571, 0.0): [4, 5, 6], (0.28571428571428559, 0.0, 1.0): [14, 15, 16], (1.0, 0.0, 0.0): [0, 1, 2, 3], (0.0, 0.57142857142857162, 1.0): [12, 13], (1.0, 0.0, 0.85714285714285676): [17, 18, 19], (0.0, 1.0, 0.57142857142857162): [10, 11], (0.28571428571428581, 1.0, 0.0): [7, 8, 9]} 
    193         sage: graphs.DodecahedralGraph().show(vertex_colors=vertex_colors) 
    194      
    195     Notice how the colors don't respect the partition at all..... 
     1227            sage: from sage.plot.colors import Colormaps 
     1228            sage: maps = Colormaps() 
     1229            sage: len(maps.maps) 
     1230            0 
     1231            sage: maps.load_maps() 
     1232            sage: len(maps.maps) 
     1233            116 
     1234        """ 
     1235        global cm 
     1236        if not cm: 
     1237            from matplotlib import cm 
     1238        if not self.maps: 
     1239            for cmap in cm.datad.keys(): 
     1240                self.maps[cmap] = cm.__getattribute__(cmap) 
    1961241 
    197     :: 
     1242    def __dir__(self): 
     1243        """ 
     1244        Returns an approximate list of attribute names, including the 
     1245        color map names. 
    1981246 
    199         sage: from sage.plot.colors import float_to_html 
    200         sage: float_to_html(1.,1.,0.) 
    201         '#ffff00' 
    202         sage: float_to_html(.03,.06,.02) 
    203         '#070f05' 
    204     """ # TODO: figure out why this is necessary 
    205     from sage.rings.integer import Integer 
    206     from math import floor 
    207     rr = Integer(int(floor(r*255))).str(base=16) 
    208     gg = Integer(int(floor(g*255))).str(base=16) 
    209     bb = Integer(int(floor(b*255))).str(base=16) 
    210     rr = '0'*(2-len(rr)) + rr 
    211     gg = '0'*(2-len(gg)) + gg 
    212     bb = '0'*(2-len(bb)) + bb 
    213     return '#' + rr\ 
    214                + gg\ 
    215                + bb 
    216                 
    217 def rainbow(n, format='hex'): 
    218     """ 
    219     Given an integer `n`, returns a list of colors, represented 
    220     in HTML hex, that changes smoothly in hue from one end of the 
    221     spectrum to the other. Written in order to easily represent vertex 
    222     partitions on graphs, but useful elsewhere as well. 
    223      
    224     AUTHORS: 
     1247        OUTPUT: 
    2251248 
    226     - Robert L. Miller 
     1249        - a list of strings 
    2271250 
    228     - Karl-Dieter Crisman (directly use hsv_to_rgb for hues)  
     1251        EXAMPLES:: 
    2291252 
    230     INPUT: 
     1253            sage: from sage.plot.colors import Colormaps 
     1254            sage: maps = Colormaps() 
     1255            sage: 'Accent' in dir(maps) 
     1256            True 
     1257        """ 
     1258        self.load_maps() 
     1259        methods = ['load_maps', '__dir__', '__len__', '__iter__', 
     1260                   '__contains__', '__getitem__', '__getattr__', 
     1261                   '__setitem__', '__delitem__'] 
     1262        return dir(super(Colormaps, self)) + methods + self.keys() 
    2311263 
    232     -  ``n`` - how many colors in the list of colors  
    233      
    234     -  ``format`` - optional argument for what format to return the list of   
    235        colors in (``hex`` or ``rgbtuple``) 
     1264    def __len__(self): 
     1265        """ 
     1266        Returns the number of color maps. 
    2361267 
    237     OUTPUT: A list of ``n`` colors, in either HTML hex or as RGB tuples. 
    238      
    239     EXAMPLE:: 
    240      
    241         sage: from sage.plot.colors import rainbow 
    242         sage: rainbow(7) 
    243         ['#ff0000', '#ffda00', '#48ff00', '#00ff91', '#0091ff', '#4800ff', '#ff00da'] 
    244         sage: rainbow(7, 'rgbtuple') 
    245         [(1, 0.0, 0.0), (1, 0.8571428571428571, 0.0), (0.28571428571428581, 1, 0.0), (0.0, 1, 0.57142857142857117), (0.0, 0.57142857142857162, 1), (0.2857142857142847, 0.0, 1), (1, 0.0, 0.85714285714285765)] 
    246     """ 
    247     from sage.rings.integer import Integer 
    248     n = Integer(n) # In case n is a Python int and i/n below would give 0! 
    249     R = [] 
    250     for i in range(n): 
    251         R.append(hsv_to_rgb(i/n,1,1)) 
    252     if format == 'rgbtuple': 
    253         return R 
    254     elif format == 'hex': 
    255         for j in range(len(R)): 
    256             R[j]=float_to_html(*R[j]) 
    257         return R 
     1268        OUTPUT: 
    2581269 
    259 def rgbcolor(c): 
    260     """ 
    261     Return the rgbcolor corresponding to c, which can be a Color, an 
    262     RGB tuple, or a string. 
     1270        - an int 
    2631271 
    264     INPUT: 
     1272        EXAMPLES:: 
    2651273 
    266     -  ``c`` - a Color, 3-tuple, or string (HTML hex color). 
     1274            sage: from sage.plot.colors import Colormaps 
     1275            sage: maps = Colormaps() 
     1276            sage: len(maps) 
     1277            116 
     1278        """ 
     1279        self.load_maps() 
     1280        return len(self.maps) 
    2671281 
    268     OUTPUT: rgb tuple of floats between 0 and 1. 
     1282    def __iter__(self): 
     1283        """ 
     1284        Returns an iterator over the color map collection. 
    2691285 
    270     EXAMPLES:: 
     1286        OUTPUT: 
    2711287 
    272         sage: from sage.plot.colors import rgbcolor 
    273         sage: rgbcolor('purple') 
    274         (0.5, 0.0, 1.0) 
    275         sage: rgbcolor('#0033ea') 
    276         (0.0, 0.20..., 0.917...) 
    277         sage: rgbcolor((1,1/2,1/3)) 
    278         (1.0, 0.5, 0.33333333333333331) 
    279     """ 
    280     if isinstance(c, Color): 
    281         return c.rgb() 
    282     if isinstance(c, tuple): 
    283         return (float(c[0]), float(c[1]), float(c[2])) 
    284     if isinstance(c, str): 
    285         if len(c) == 7 and c[0] == '#':  # html hex color 
    286             # we use Integer instead of 0x eval for security reasons 
    287             return tuple([int(c[i:i+2], base=16)/float(255) for i in [1,3,5]]) 
    288         try: 
    289             return colors[c] 
    290         except KeyError: 
    291             pass 
    292          
    293     raise ValueError, "unknown color '%s'"%c 
     1288        - a dictionary key iterator instance 
    2941289 
     1290        EXAMPLES:: 
    2951291 
    296 class Color: 
    297     def __init__(self, r='#0000ff', g=None, b=None): 
     1292            sage: from sage.plot.colors import Colormaps 
     1293            sage: maps = Colormaps() 
     1294            sage: count = 0 
     1295            sage: for m in maps: count += 1 
     1296            sage: count == len(maps) 
     1297            True 
    2981298        """ 
    299         A color object. 
     1299        self.load_maps() 
     1300        return iter(self.maps) 
     1301 
     1302    def __contains__(self, name): 
     1303        """ 
     1304        Returns whether a map is in the color maps collection. 
    3001305 
    3011306        INPUT: 
    3021307 
    303         -  ``r,g,b`` - either a triple of floats between 0 and 1, 
    304            OR ``r`` - a color string or HTML color hex string 
     1308        - ``name`` - a string; the name of the map to query 
     1309 
     1310        OUTPUT: 
     1311 
     1312        - a boolean 
    3051313 
    3061314        EXAMPLES:: 
    3071315 
    308             sage: Color('purple') 
    309             RGB color (0.5, 0.0, 1.0) 
    310             sage: Color(0.5,0,1) 
    311             RGB color (0.5, 0.0, 1.0) 
    312             sage: Color('#8000ff') 
    313             RGB color (0.50..., 0.0, 1.0) 
     1316            sage: from sage.plot.colors import Colormaps 
     1317            sage: maps = Colormaps() 
     1318            sage: 'summer' in maps 
     1319            True 
     1320            sage: 'not really a color map' in maps 
     1321            False 
    3141322        """ 
    315         if g is None and b is None: 
    316             self.__rgb = rgbcolor(r) 
    317         else: 
    318             self.__rgb = (float(r),float(g),float(b)) 
     1323        self.load_maps() 
     1324        return name in self.maps 
     1325 
     1326    def __getitem__(self, name): 
     1327        """ 
     1328        Gets a color map from the collection via key access. 
     1329 
     1330        INPUT: 
     1331 
     1332        - ``name`` - a string; the name of the map return 
     1333 
     1334        OUTPUT: 
     1335 
     1336        - an instance of :class:`matplotlib.colors.Colormap` 
     1337 
     1338        EXAMPLES:: 
     1339 
     1340            sage: from sage.plot.colors import Colormaps 
     1341            sage: maps = Colormaps() 
     1342            sage: maps.get('Oranges') 
     1343            <matplotlib.colors.LinearSegmentedColormap instance at ...> 
     1344            sage: maps['copper'] 
     1345            <matplotlib.colors.LinearSegmentedColormap instance at ...> 
     1346            sage: maps.get('not a color map') 
     1347            sage: maps['not a color map'] 
     1348            Traceback (most recent call last): 
     1349            ... 
     1350            KeyError: "no colormap with name 'not a color map'" 
     1351        """ 
     1352        self.load_maps() 
     1353        try: 
     1354            return self.maps[name] 
     1355        except KeyError: 
     1356            raise KeyError("no colormap with name '%s'" % name) 
     1357 
     1358    def __getattr__(self, name): 
     1359        """ 
     1360        Gets a color map from the collection via attribute access. 
     1361 
     1362        INPUT: 
     1363 
     1364        - ``name`` - a string; the name of the map to return 
     1365 
     1366        OUTPUT: 
     1367 
     1368        - an instance of :class:`matplotlib.colors.Colormap` 
     1369 
     1370        EXAMPLES:: 
     1371 
     1372            sage: from sage.plot.colors import Colormaps 
     1373            sage: maps = Colormaps() 
     1374            sage: maps.pink 
     1375            <matplotlib.colors.LinearSegmentedColormap instance at ...> 
     1376            sage: maps.punk 
     1377            Traceback (most recent call last): 
     1378            ... 
     1379            KeyError: "no colormap with name 'punk'" 
     1380            sage: maps['bone'] == maps.bone 
     1381            True 
     1382        """ 
     1383        return self.__getitem__(name) 
    3191384 
    3201385    def __repr__(self): 
    3211386        """ 
    322         Return string representation of this RGB color. 
     1387        Returns a string representation of the color map collection. 
     1388 
     1389        OUTPUT: 
     1390 
     1391        - a string 
    3231392 
    3241393        EXAMPLES:: 
    3251394 
    326             sage: Color('#8000ff').__repr__() 
    327             'RGB color (0.50..., 0.0, 1.0)' 
     1395            sage: from sage.plot.colors import Colormaps 
     1396            sage: maps = Colormaps() 
     1397            sage: maps 
     1398            {...} 
     1399            sage: type(repr(maps)) 
     1400            <type 'str'> 
    3281401        """ 
    329         return "RGB color %s"%(self.__rgb,) 
     1402        self.load_maps() 
     1403        return repr(self.maps) 
    3301404 
    331     def rgb(self): 
     1405    def __setitem__(self, name, colormap): 
    3321406        """ 
    333         Return underlying RGB tuple. 
     1407        Adds a color map to the collection. 
    3341408 
    335         OUTPUT: 3-tuple 
     1409        INPUT: 
     1410 
     1411        - ``name`` - a string; the name of the map to add 
     1412 
     1413        - ``colormap`` - an instance of 
     1414          :class:`matplotlib.colors.Colormap`; the color map to add 
    3361415 
    3371416        EXAMPLES:: 
    3381417 
    339             sage: Color('#8000ff').rgb() 
    340             (0.50..., 0.0, 1.0) 
     1418            sage: from sage.plot.colors import Colormaps, get_cmap 
     1419            sage: maps = Colormaps() 
     1420            sage: count = len(maps) 
     1421            sage: my_map = get_cmap(['chartreuse', '#007', (1.0, 0.0, 0.0)]) 
     1422            sage: maps['my_map'] = my_map 
     1423            sage: 'my_map' in maps 
     1424            True 
     1425            sage: count + 1 == len(maps) 
     1426            True 
    3411427        """ 
    342         return self.__rgb 
     1428        self.load_maps() 
     1429        self.maps[name] = colormap 
    3431430 
    344     def html_color(self): 
     1431    def __delitem__(self, name): 
    3451432        """ 
    346         Return color formatted as an HTML hex color. 
     1433        Removes a color map from the collection. 
    3471434 
    348         OUTPUT: string of length 7. 
     1435        INPUT: 
     1436 
     1437        - ``name`` - a string; the name of the map to remove 
    3491438 
    3501439        EXAMPLES:: 
    3511440 
    352             sage: Color('yellow').html_color() 
    353             '#ffff00' 
     1441            sage: from sage.plot.colors import Colormaps 
     1442            sage: maps = Colormaps() 
     1443            sage: count = len(maps) 
     1444            sage: maps.popitem() 
     1445            ('Spectral', <matplotlib.colors.LinearSegmentedColormap instance at ...>) 
     1446            sage: count - 1 == len(maps) 
     1447            True 
    3541448        """ 
    355         s = '#' 
    356         for z in self.__rgb: 
    357             h = '%x'%int(z*256) 
    358             if len(h) > 2: 
    359                 h = 'ff' 
    360             elif len(h) == 1: 
    361                 h = '0' + h 
    362             s += h 
    363         return s 
     1449        self.load_maps() 
     1450        del self.maps[name] 
     1451 
     1452colormaps = Colormaps() 
  • sage/plot/plot3d/base.pyx

    diff --git a/sage/plot/plot3d/base.pyx b/sage/plot/plot3d/base.pyx
    a b end_scene""" % (render_params.antialiasi 
    755755            set([]) 
    756756 
    757757            sage: G = tetrahedron(color='red') + tetrahedron(color='yellow') + tetrahedron(color='red', opacity=0.5) 
    758             sage: [t for t in G.texture_set() if t.color == (1, 0, 0)] # we should have two red textures 
     758            sage: [t for t in G.texture_set() if t.color == colors.red] # we should have two red textures 
    759759            [Texture(texture..., red, ff0000), Texture(texture..., red, ff0000)] 
    760             sage: [t for t in G.texture_set() if t.color == (1, 1, 0)] # ...and one yellow 
     760            sage: [t for t in G.texture_set() if t.color == colors.yellow] # ...and one yellow 
    761761            [Texture(texture..., yellow, ffff00)] 
    762762        """ 
    763763        return set() 
    class Graphics3dGroup(Graphics3d): 
    13921392        EXAMPLES:: 
    13931393 
    13941394            sage: G = sphere(color='red') + sphere(color='yellow') 
    1395             sage: [t for t in G.texture_set() if t.color == (1, 0, 0)] # one red texture 
     1395            sage: [t for t in G.texture_set() if t.color == colors.red] # one red texture 
    13961396            [Texture(texture..., red, ff0000)] 
    1397             sage: [t for t in G.texture_set() if t.color == (1, 1, 0)] # one yellow texture 
     1397            sage: [t for t in G.texture_set() if t.color == colors.yellow] # one yellow texture 
    13981398            [Texture(texture..., yellow, ffff00)]  
    13991399 
    14001400            sage: T = sage.plot.plot3d.texture.Texture('blue'); T