From 3220bb2048ba98b984673c1e7fe4aac686cedf47 Mon Sep 17 00:00:00 2001 From: ImportanceOfBeingErnest Date: Mon, 3 Sep 2018 04:19:33 +0200 Subject: [PATCH] Introduce new Tableau colors --- .../introduce-new-tableau-colors.rst | 24 ++++ examples/color/color_demo.py | 31 +++-- examples/color/colormap_reference.py | 2 +- examples/color/named_colors.py | 106 ++++++++++-------- lib/matplotlib/_cm.py | 49 ++++++++ lib/matplotlib/_color_data.py | 17 +++ lib/matplotlib/colors.py | 28 +++-- tutorials/colors/colormaps.py | 3 +- tutorials/colors/colors.py | 21 +++- 9 files changed, 212 insertions(+), 69 deletions(-) create mode 100644 doc/users/next_whats_new/introduce-new-tableau-colors.rst diff --git a/doc/users/next_whats_new/introduce-new-tableau-colors.rst b/doc/users/next_whats_new/introduce-new-tableau-colors.rst new file mode 100644 index 000000000000..72737cb07607 --- /dev/null +++ b/doc/users/next_whats_new/introduce-new-tableau-colors.rst @@ -0,0 +1,24 @@ +:orphan: + +Introduce new Tableau colors +---------------------------- + +In its version 10, Tableau `introduced a new palette of categorical colors +`__. +Those are now available in matplotlib with the prefix ``tabx:``: +``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan', 'tabx:green', +'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown', 'tabx:grey'}`` + +Those colors are also provided as a new ``tabx10`` colormap. An additional +``tabx20`` colormap with is added. + +In general those colors are a little less saturated than those from the default +color cycle. Replacing the default color cycler with those colors can e.g. be +achieved via + +:: + + cols = plt.cm.tabx10.colors + plt.rcParams["axes.prop_cycle"] = plt.cycler("color", cols)} + + diff --git a/examples/color/color_demo.py b/examples/color/color_demo.py index d366f0a1b959..b3d4d85fdd20 100644 --- a/examples/color/color_demo.py +++ b/examples/color/color_demo.py @@ -3,7 +3,7 @@ Color Demo ========== -Matplotlib gives you 8 ways to specify colors, +Matplotlib gives you 7 ways to specify colors, 1) an RGB or RGBA tuple of float values in ``[0, 1]`` (e.g. ``(0.1, 0.2, 0.5)`` or ``(0.1, 0.2, 0.5, 0.3)``). RGBA is short for Red, Green, Blue, Alpha; @@ -13,16 +13,25 @@ 4) a single letter string, i.e. one of ``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``; 5) a X11/CSS4 ("html") color name, e.g. ``"blue"``; -6) a name from the `xkcd color survey `__, - prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``); +6) a color name from a palette, prefixed with the palette's name: + + a. a name from the `xkcd color survey `__; + prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``); + b. 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); + c. one of ``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan', + 'tabx:green', 'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown', + 'tabx:gray' }`` which are the colors from the + `new Tableau10 categorical palette + `__; + 7) a "Cn" color spec, i.e. `'C'` followed by a single digit, which is an index into the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``); the indexing occurs at artist creation time and defaults to black if the cycle does not include color. -8) 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 - 'tab10' categorical palette (which is the default color cycle); For more information on colors in matplotlib see @@ -47,12 +56,14 @@ ax.set_xlabel('time (s)', color='c') # 5) a named color: ax.set_ylabel('voltage (mV)', color='peachpuff') -# 6) a named xkcd color: +# 6a) a named xkcd color: ax.plot(t, s, 'xkcd:crimson') +# 6b) tab notation: +ax.tick_params(axis="x", labelcolor='tab:orange') +# 6c) tabx notation: +ax.tick_params(axis="y", labelcolor='tabx:yellow') # 7) Cn notation: ax.plot(t, .7*s, color='C4', linestyle='--') -# 8) tab notation: -ax.tick_params(labelcolor='tab:orange') plt.show() diff --git a/examples/color/colormap_reference.py b/examples/color/colormap_reference.py index afb578ffad1b..a41bb97d8a09 100644 --- a/examples/color/colormap_reference.py +++ b/examples/color/colormap_reference.py @@ -33,7 +33,7 @@ ('Qualitative', [ 'Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2', 'Set1', 'Set2', 'Set3', - 'tab10', 'tab20', 'tab20b', 'tab20c']), + 'tab10', 'tab20', 'tab20b', 'tab20c', 'tabx10', 'tabx20']), ('Miscellaneous', [ 'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern', 'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', diff --git a/examples/color/named_colors.py b/examples/color/named_colors.py index 5a16c2d813f1..b35ed4a1e160 100644 --- a/examples/color/named_colors.py +++ b/examples/color/named_colors.py @@ -12,52 +12,70 @@ * the :doc:`/gallery/color/color_demo`. """ -import matplotlib.pyplot as plt -from matplotlib import colors as mcolors - - -colors = dict(mcolors.BASE_COLORS, **mcolors.CSS4_COLORS) - -# Sort colors by hue, saturation, value and name. -by_hsv = sorted((tuple(mcolors.rgb_to_hsv(mcolors.to_rgba(color)[:3])), name) - for name, color in colors.items()) -sorted_names = [name for hsv, name in by_hsv] - -n = len(sorted_names) -ncols = 4 -nrows = n // ncols - -fig, ax = plt.subplots(figsize=(9, 8)) -# Get height and width -X, Y = fig.get_dpi() * fig.get_size_inches() -h = Y / (nrows + 1) -w = X / ncols - -for i, name in enumerate(sorted_names): - row = i % nrows - col = i // nrows - y = Y - (row * h) - h - - xi_line = w * (col + 0.05) - xf_line = w * (col + 0.25) - xi_text = w * (col + 0.3) - - ax.text(xi_text, y, name, fontsize=(h * 0.5), - horizontalalignment='left', - verticalalignment='center') - - ax.hlines(y + h * 0.1, xi_line, xf_line, - color=colors[name], linewidth=(h * 0.6)) - -ax.set_xlim(0, X) -ax.set_ylim(0, Y) -ax.set_axis_off() +import matplotlib.pyplot as plt +import matplotlib.colors as mcolors + + +def plot_colortable(colors, title, sort_colors=True, emptycols=0): + + cell_width = 185 + cell_height = 24 + swatch_width = 38 + margin = 10 + topmargin = 30 + + # Sort colors by hue, saturation, value and name. + by_hsv = ((tuple(mcolors.rgb_to_hsv(mcolors.to_rgba(color)[:3])), name) + for name, color in colors.items()) + if sort_colors is True: + by_hsv = sorted(by_hsv) + names = [name for hsv, name in by_hsv] + + n = len(names) + ncols = 4 - emptycols + nrows = n // ncols + int(n % ncols > 0) + + width = cell_width * 4 + 2 * margin + height = cell_height * nrows + margin + topmargin + dpi = 72 + + fig, ax = plt.subplots(figsize=(width / dpi, height / dpi), dpi=dpi) + fig.subplots_adjust(margin/width, margin/height, + (width-margin)/width, (height-topmargin)/height) + ax.set_xlim(0, cell_width * 4) + ax.set_ylim(cell_height * (nrows-0.5), -cell_height/2.) + ax.yaxis.set_visible(False) + ax.xaxis.set_visible(False) + ax.set_axis_off() + ax.set_title(title, fontsize=20, loc="left") + + for i, name in enumerate(names): + row = i % nrows + col = i // nrows + y = row * cell_height + + swatch_start_x = cell_width * col + swatch_end_x = cell_width * col + swatch_width + text_pos_x = cell_width * col + swatch_width + 5 + + ax.text(text_pos_x, y, name, fontsize=12, + horizontalalignment='left', + verticalalignment='center') + + ax.hlines(y, swatch_start_x, swatch_end_x, + color=colors[name], linewidth=18) + plt.show() + +plot_colortable(mcolors.BASE_COLORS, "Base Colors", + sort_colors=False, emptycols=1) +plot_colortable(mcolors.TABLEAU_COLORS, "Tableau Palette", + sort_colors=False, emptycols=1) +plot_colortable(mcolors.TABLEAUX_COLORS, "New Tableau Palette", + sort_colors=False, emptycols=1) +#sphinx_gallery_thumbnail_number = 4 +plot_colortable(mcolors.CSS4_COLORS, "CSS Colors") -fig.subplots_adjust(left=0, right=1, - top=1, bottom=0, - hspace=0, wspace=0) -plt.show() ############################################################################# # diff --git a/lib/matplotlib/_cm.py b/lib/matplotlib/_cm.py index bfc1d64d312a..6b079452749e 100644 --- a/lib/matplotlib/_cm.py +++ b/lib/matplotlib/_cm.py @@ -1346,6 +1346,53 @@ def _gist_yarg(x): return 1 - x ) +_tabx10colors = [ + "#4e79a7", # blue + "#f28e2b", # orange + "#e15759", # red + "#76b7b2", # cyan + "#59a14f", # green + "#edc948", # yellow + "#b07aa1", # purple + "#ff9da7", # pink + "#9c755f", # brown + "#bab0ac", # grey + ] + +_tabx20colors = [ + "#4e79a7", # blue + "#a0cbe8", + "#f28e2b", # orange + "#ffbe7d", + "#59a14f", # green + "#8cd17d", + "#b6992d", # yellow # is different from tabx10 + "#f1ce63", + "#499894", # cyan # is different from tabx10 + "#86bcb6", + "#e15759", # red + "#ff9d9a", + "#79706e", # grey # is different from tabx10 + "#bab0ac", + "#d37295", # pink # is different from tabx10 + "#fabfd2", + "#b07aa1", # purple # is different from tabx10 + "#d4a6c8", + "#9d7660", # brown # is different from tabx10 + "#d7b5a6", + ] + +_tabx10_data = [] +for c in _tabx10colors: + d = [int(s, 16)/255. for s in list(map(''.join, zip(*[iter(c[1:])]*2)))] + _tabx10_data.append(d) + +_tabx20_data = [] +for c in _tabx20colors: + d = [int(s, 16)/255. for s in list(map(''.join, zip(*[iter(c[1:])]*2)))] + _tabx20_data.append(d) + + datad = { 'Blues': _Blues_data, 'BrBG': _BrBG_data, @@ -1423,4 +1470,6 @@ def _gist_yarg(x): return 1 - x 'tab20': {'listed': _tab20_data}, 'tab20b': {'listed': _tab20b_data}, 'tab20c': {'listed': _tab20c_data}, + 'tabx10': {'listed': _tabx10_data}, + 'tabx20': {'listed': _tabx20_data}, } diff --git a/lib/matplotlib/_color_data.py b/lib/matplotlib/_color_data.py index 973f4a2f2435..b0e70d2bb81d 100644 --- a/lib/matplotlib/_color_data.py +++ b/lib/matplotlib/_color_data.py @@ -30,6 +30,23 @@ TABLEAU_COLORS = OrderedDict( ('tab:' + name, value) for name, value in TABLEAU_COLORS) +# These colors are from Tableau Version 10 +TABLEAUX_COLORS = ( + ("blue", "#4e79a7"), + ("orange", "#f28e2b"), + ("red", "#e15759"), + ("cyan", "#76b7b2"), + ("green", "#59a14f"), + ("yellow", "#edc948"), + ("purple", "#b07aa1"), + ("pink", "#ff9da7"), + ("brown", "#9c755f"), + ("gray", "#bab0ac") +) +# Normalize name to "tabx:" to avoid name collisions. +TABLEAUX_COLORS = OrderedDict( + ('tabx:' + name, value) for name, value in TABLEAUX_COLORS) + # 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 75ac1a85e098..6d8aa6916a71 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -41,12 +41,21 @@ level (e.g., ``'0.5'``); * one of ``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``; * a X11/CSS4 color name; -* a name from the `xkcd color survey `__; - prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``); -* 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); +* a color name from a palette, prefixed with the palette's name: + + * a name from the `xkcd color survey `__; + prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``); + * 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); + * one of ``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan', + 'tabx:green', 'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown', + 'tabx:gray' }`` which are the colors from the + `new Tableau10 categorical palette + `__; + * a "CN" color spec, i.e. `'C'` followed by a single digit, which is an index into the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``); the indexing occurs at artist creation time and defaults to black if the @@ -61,7 +70,8 @@ import numpy as np import matplotlib.cbook as cbook -from ._color_data import BASE_COLORS, TABLEAU_COLORS, CSS4_COLORS, XKCD_COLORS +from ._color_data import (BASE_COLORS, TABLEAU_COLORS, TABLEAUX_COLORS, + CSS4_COLORS, XKCD_COLORS) class _ColorMapping(dict): @@ -89,6 +99,10 @@ def __delitem__(self, key): _colors_full_map.update({k.replace('gray', 'grey'): v for k, v in TABLEAU_COLORS.items() if 'gray' in k}) +_colors_full_map.update(TABLEAUX_COLORS) +_colors_full_map.update({k.replace('gray', 'grey'): v + for k, v in TABLEAUX_COLORS.items() + if 'gray' in k}) _colors_full_map.update(BASE_COLORS) _colors_full_map = _ColorMapping(_colors_full_map) diff --git a/tutorials/colors/colormaps.py b/tutorials/colors/colormaps.py index 4a04c5eaf595..c923187768ab 100644 --- a/tutorials/colors/colormaps.py +++ b/tutorials/colors/colormaps.py @@ -160,7 +160,8 @@ cmaps['Qualitative'] = ['Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2', 'Set1', 'Set2', 'Set3', - 'tab10', 'tab20', 'tab20b', 'tab20c'] + 'tab10', 'tab20', 'tab20b', 'tab20c', + 'tabx10', 'tabx20'] ############################################################################### # Miscellaneous diff --git a/tutorials/colors/colors.py b/tutorials/colors/colors.py index 5721cb6b0b5a..83be76c100b9 100644 --- a/tutorials/colors/colors.py +++ b/tutorials/colors/colors.py @@ -12,12 +12,21 @@ level (e.g., ``'0.5'``); * one of ``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``; * a X11/CSS4 color name; -* a name from the `xkcd color survey `__; - prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``); -* 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); +* a color name from a palette, prefixed with the palette's name: + + * a name from the `xkcd color survey `__; + prefixed with ``'xkcd:'`` (e.g., ``'xkcd:sky blue'``); + * 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); + * one of ``{'tabx:blue', 'tabx:orange', 'tabx:red', 'tabx:cyan', + 'tabx:green', 'tabx:yellow', 'tabx:purple', 'tabx:pink', 'tabx:brown', + 'tabx:gray'}`` which are the colors from the + `new Tableau10 categorical palette + `__; + * a "CN" color spec, i.e. `'C'` followed by a single digit, which is an index into the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``); the indexing occurs at artist creation time and defaults to black if the pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy