From 44d71277fa3bf56ee4b3c8dee0c28e4ff90d7bc1 Mon Sep 17 00:00:00 2001 From: Truong Pham Date: Mon, 24 Oct 2016 22:42:06 -0700 Subject: [PATCH 1/2] Adding names to the color in the new Vega10 color cycle --- doc/users/colors.rst | 3 +++ lib/matplotlib/_color_data.py | 17 +++++++++++++++++ lib/matplotlib/colors.py | 7 ++++--- lib/matplotlib/tests/test_colors.py | 3 ++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/doc/users/colors.rst b/doc/users/colors.rst index 18a5756f0ab5..94fe23ad0cbd 100644 --- a/doc/users/colors.rst +++ b/doc/users/colors.rst @@ -17,6 +17,9 @@ it can be provided as: * a name from the `xkcd color survey `__ prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``) * one of ``{'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'}`` +* one of ``{'vega:blue', 'vega:orange', 'vega:green', + 'vega:red', 'vega:purple', 'vega:brown', 'vega:pink', + 'vega:gray', 'vega:olive', 'vega:cyan'}`` All string specifications of color are case-insensitive. diff --git a/lib/matplotlib/_color_data.py b/lib/matplotlib/_color_data.py index 11a538f34722..d6244e1863f5 100644 --- a/lib/matplotlib/_color_data.py +++ b/lib/matplotlib/_color_data.py @@ -15,6 +15,23 @@ 'w': (1, 1, 1)} +VEGA_COLORS = { + 'blue': '#1f77b4', + 'orange': '#ff7f0e', + 'green': '#2ca02c', + 'red': '#d62728', + 'purple': '#9467bd', + 'brown': '#8c564b', + 'pink': '#e377c2', + 'gray': '#7f7f7f', + 'olive': '#bcbd22', + 'cyan': '#17becf'} + + +# Normalize name to "vega10:" to avoid name collisions. +VEGA_COLORS = {'vega:' + name: value for name, value in VEGA_COLORS.items()} + + # This mapping of color names -> hex values is taken from # a survey run by Randel Monroe see: # http://blog.xkcd.com/2010/05/03/color-survey-results/ diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 2825c33fe97f..b2cbb9509a24 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -66,7 +66,7 @@ import numpy as np from numpy import ma import matplotlib.cbook as cbook -from ._color_data import BASE_COLORS, CSS4_COLORS, XKCD_COLORS +from ._color_data import BASE_COLORS, VEGA_COLORS, CSS4_COLORS, XKCD_COLORS class _ColorMapping(dict): @@ -87,6 +87,7 @@ def __delitem__(self, key, value): # Set by reverse priority order. _colors_full_map.update(XKCD_COLORS) _colors_full_map.update(CSS4_COLORS) +_colors_full_map.update(VEGA_COLORS) _colors_full_map.update(BASE_COLORS) _colors_full_map = _ColorMapping(_colors_full_map) @@ -253,7 +254,7 @@ def to_hex(c, keep_alpha=False): ### Backwards-compatible color-conversion API cnames = CSS4_COLORS -COLOR_NAMES = {'xkcd': XKCD_COLORS, 'css4': CSS4_COLORS} +COLOR_NAMES = {'xkcd': XKCD_COLORS, 'css4': CSS4_COLORS, 'vega': VEGA_COLORS} hexColorPattern = re.compile("\A#[a-fA-F0-9]{6}\Z") @@ -404,7 +405,7 @@ class Colormap(object): """ def __init__(self, name, N=256): - r""" + """ Parameters ---------- name : str diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 4f9c44c16ccf..8edce82abe3f 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -571,9 +571,10 @@ def angled_plane(azimuth, elevation, angle, x, y): assert_array_almost_equal(h, np.cos(np.radians(angle))) -def test_xkcd(): +def test_color_names(): assert mcolors.to_hex("blue") == "#0000ff" assert mcolors.to_hex("xkcd:blue") == "#0343df" + assert mcolors.to_hex("vega:blue") == "#1f77b4" def _sph2cart(theta, phi): From 317eaff7dfb0b01f02e9b0c8857b392658e3e3ae Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 18 Dec 2016 16:19:10 -0500 Subject: [PATCH 2/2] API/DOC: change color name to tab from vega - change naming to tab - credit Tableau for developing the colors - support both spellings of grey an Tableau&xkcd colors - add tests of grey/gray equivalence and tableau order - use more explicit internal names + add comment --- doc/users/colors.rst | 7 +++--- doc/users/dflt_style_changes.rst | 9 ++++++-- lib/matplotlib/_color_data.py | 34 ++++++++++++++--------------- lib/matplotlib/colors.py | 12 +++++++--- lib/matplotlib/tests/test_colors.py | 19 +++++++++++++++- 5 files changed, 55 insertions(+), 26 deletions(-) diff --git a/doc/users/colors.rst b/doc/users/colors.rst index 94fe23ad0cbd..d08861bccec0 100644 --- a/doc/users/colors.rst +++ b/doc/users/colors.rst @@ -17,9 +17,10 @@ it can be provided as: * a name from the `xkcd color survey `__ prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``) * one of ``{'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9'}`` -* one of ``{'vega:blue', 'vega:orange', 'vega:green', - 'vega:red', 'vega:purple', 'vega:brown', 'vega:pink', - 'vega:gray', 'vega:olive', 'vega:cyan'}`` +* one of ``{'tab:blue', 'tab:orange', 'tab:green', + 'tab:red', 'tab:purple', 'tab:brown', 'tab:pink', + 'tab:gray', 'tab:olive', 'tab:cyan'}`` which are the Tableau Colors from the + 'T10' categorical palette (which is the default color cycle). All string specifications of color are case-insensitive. diff --git a/doc/users/dflt_style_changes.rst b/doc/users/dflt_style_changes.rst index 125a95892f7e..34aaddaf02c5 100644 --- a/doc/users/dflt_style_changes.rst +++ b/doc/users/dflt_style_changes.rst @@ -32,8 +32,13 @@ Colors in default property cycle -------------------------------- The colors in the default property cycle have been changed from -``['b', 'g', 'r', 'c', 'm', 'y', 'k']`` to the `Vega category10 palette -`__ +``['b', 'g', 'r', 'c', 'm', 'y', 'k']`` to the category10 +color palette used by `Vega +`__ and +`d3 +`__ +originally developed at Tableau. + .. plot:: diff --git a/lib/matplotlib/_color_data.py b/lib/matplotlib/_color_data.py index d6244e1863f5..7c47eca30378 100644 --- a/lib/matplotlib/_color_data.py +++ b/lib/matplotlib/_color_data.py @@ -1,6 +1,6 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) - +from collections import OrderedDict import six @@ -15,22 +15,23 @@ 'w': (1, 1, 1)} -VEGA_COLORS = { - 'blue': '#1f77b4', - 'orange': '#ff7f0e', - 'green': '#2ca02c', - 'red': '#d62728', - 'purple': '#9467bd', - 'brown': '#8c564b', - 'pink': '#e377c2', - 'gray': '#7f7f7f', - 'olive': '#bcbd22', - 'cyan': '#17becf'} - - -# Normalize name to "vega10:" to avoid name collisions. -VEGA_COLORS = {'vega:' + name: value for name, value in VEGA_COLORS.items()} +# These colors are from Tableau +TABLEAU_COLORS = OrderedDict(( + ('blue', '#1f77b4'), + ('orange', '#ff7f0e'), + ('green', '#2ca02c'), + ('red', '#d62728'), + ('purple', '#9467bd'), + ('brown', '#8c564b'), + ('pink', '#e377c2'), + ('gray', '#7f7f7f'), + ('olive', '#bcbd22'), + ('cyan', '#17becf')) +) +# Normalize name to "tab:" to avoid name collisions. +TABLEAU_COLORS = OrderedDict( + ('tab:' + name, value) for name, value in TABLEAU_COLORS.items()) # This mapping of color names -> hex values is taken from # a survey run by Randel Monroe see: @@ -990,7 +991,6 @@ 'green': '#15b01a', 'purple': '#7e1e9c'} - # Normalize name to "xkcd:" to avoid name collisions. XKCD_COLORS = {'xkcd:' + name: value for name, value in XKCD_COLORS.items()} diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index b2cbb9509a24..ee1b41e17757 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -66,7 +66,7 @@ import numpy as np from numpy import ma import matplotlib.cbook as cbook -from ._color_data import BASE_COLORS, VEGA_COLORS, CSS4_COLORS, XKCD_COLORS +from ._color_data import BASE_COLORS, TABLEAU_COLORS, CSS4_COLORS, XKCD_COLORS class _ColorMapping(dict): @@ -86,8 +86,14 @@ def __delitem__(self, key, value): _colors_full_map = {} # Set by reverse priority order. _colors_full_map.update(XKCD_COLORS) +_colors_full_map.update({k.replace('grey', 'gray'): v + for k, v in XKCD_COLORS.items() + if 'grey' in k}) _colors_full_map.update(CSS4_COLORS) -_colors_full_map.update(VEGA_COLORS) +_colors_full_map.update(TABLEAU_COLORS) +_colors_full_map.update({k.replace('gray', 'grey'): v + for k, v in TABLEAU_COLORS.items() + if 'gray' in k}) _colors_full_map.update(BASE_COLORS) _colors_full_map = _ColorMapping(_colors_full_map) @@ -254,7 +260,7 @@ def to_hex(c, keep_alpha=False): ### Backwards-compatible color-conversion API cnames = CSS4_COLORS -COLOR_NAMES = {'xkcd': XKCD_COLORS, 'css4': CSS4_COLORS, 'vega': VEGA_COLORS} +COLOR_NAMES = {'xkcd': XKCD_COLORS, 'css4': CSS4_COLORS, 'tc': TABLEAU_COLORS} hexColorPattern = re.compile("\A#[a-fA-F0-9]{6}\Z") diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 8edce82abe3f..233616ccb65e 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -574,7 +574,7 @@ def angled_plane(azimuth, elevation, angle, x, y): def test_color_names(): assert mcolors.to_hex("blue") == "#0000ff" assert mcolors.to_hex("xkcd:blue") == "#0343df" - assert mcolors.to_hex("vega:blue") == "#1f77b4" + assert mcolors.to_hex("tab:blue") == "#1f77b4" def _sph2cart(theta, phi): @@ -644,6 +644,23 @@ def test_conversions(): hex_color) +def test_grey_gray(): + color_mapping = mcolors._colors_full_map + for k in color_mapping.keys(): + if 'grey' in k: + assert color_mapping[k] == color_mapping[k.replace('grey', 'gray')] + if 'gray' in k: + assert color_mapping[k] == color_mapping[k.replace('gray', 'grey')] + + +def test_tableau_order(): + dflt_cycle = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', + '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', + '#bcbd22', '#17becf'] + + assert list(mcolors.TABLEAU_COLORS.values()) == dflt_cycle + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s', '--with-doctest'], exit=False)