diff --git a/doc/api/next_api_changes/2018-10-23-AL.rst b/doc/api/next_api_changes/2018-10-23-AL.rst new file mode 100644 index 000000000000..b39b5c9b4e80 --- /dev/null +++ b/doc/api/next_api_changes/2018-10-23-AL.rst @@ -0,0 +1,12 @@ +``Cn`` colors now support ``n>=10`` +``````````````````````````````````` + +It is now possible to go beyond the tenth color in the property cycle using +``Cn`` syntax, e.g. ``plt.plot([1, 2], color="C11")`` now uses the 12th color +in the cycle. + +Note that previously, a construct such as ``plt.plot([1, 2], "C11")`` would be +interpreted as a request to use color ``C1`` and marker ``1`` (an "inverted Y"). +To obtain such a plot, one should now use ``plt.plot([1, 2], "1C1")`` (so that +the first "1" gets correctly interpreted as a marker specification), or, more +explicitly, ``plt.plot([1, 2], marker="1", color="C1")``. diff --git a/examples/color/color_demo.py b/examples/color/color_demo.py index d366f0a1b959..58c0341247f5 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 recognizes the following formats to specify a color: 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; @@ -15,10 +15,10 @@ 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'``); -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. +7) a "Cn" color spec, i.e. `'C'` followed by a number, which is an index into + the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``); the + indexing is intended to occur at rendering 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 diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 0d79ea223d20..24fb1ae71f2d 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -1517,32 +1517,14 @@ def plot(self, *args, scalex=True, scaley=True, **kwargs): A format string consists of a part for color, marker and line:: - fmt = '[color][marker][line]' + fmt = '[marker][line][color]' Each of them is optional. If not provided, the value from the style cycle is used. Exception: If ``line`` is given, but no ``marker``, the data will be a line without markers. - **Colors** - - The following color abbreviations are supported: - - ============= =============================== - character color - ============= =============================== - ``'b'`` blue - ``'g'`` green - ``'r'`` red - ``'c'`` cyan - ``'m'`` magenta - ``'y'`` yellow - ``'k'`` black - ``'w'`` white - ============= =============================== - - If the color is the only part of the format string, you can - additionally use any `matplotlib.colors` spec, e.g. full names - (``'green'``) or hex strings (``'#008000'``). + Other combinations such as ``[color][marker][line]`` are also + supported, but note that their parsing may be ambiguous. **Markers** @@ -1587,11 +1569,33 @@ def plot(self, *args, scalex=True, scaley=True, **kwargs): Example format strings:: 'b' # blue markers with default shape - 'ro' # red circles - 'g-' # green solid line + 'or' # red circles + '-g' # green solid line '--' # dashed line with default color - 'k^:' # black triangle_up markers connected by a dotted line + '^k:' # black triangle_up markers connected by a dotted line + **Colors** + + The supported color abbreviations are the single letter codes + + ============= =============================== + character color + ============= =============================== + ``'b'`` blue + ``'g'`` green + ``'r'`` red + ``'c'`` cyan + ``'m'`` magenta + ``'y'`` yellow + ``'k'`` black + ``'w'`` white + ============= =============================== + + and the ``'CN'`` colors that index into the default property cycle. + + If the color is the only part of the format string, you can + additionally use any `matplotlib.colors` spec, e.g. full names + (``'green'``) or hex strings (``'#008000'``). """ lines = [] diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index a06bee6fc070..54931030ab2b 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -49,9 +49,9 @@ '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 "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 +* a "CN" color spec, i.e. `'C'` followed by a number, which is an index into + the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``); the + indexing is intended to occur at rendering time, and defaults to black if the cycle does not include color. All string specifications of color, other than "CN", are case-insensitive. @@ -115,7 +115,7 @@ def _sanitize_extrema(ex): def _is_nth_color(c): """Return whether *c* can be interpreted as an item in the color cycle.""" - return isinstance(c, str) and re.match(r"\AC[0-9]\Z", c) + return isinstance(c, str) and re.match(r"\AC[0-9]+\Z", c) def is_color_like(c): @@ -169,7 +169,7 @@ def to_rgba(c, alpha=None): from matplotlib import rcParams prop_cycler = rcParams['axes.prop_cycle'] colors = prop_cycler.by_key().get('color', ['k']) - c = colors[int(c[1]) % len(colors)] + c = colors[int(c[1:]) % len(colors)] try: rgba = _colors_full_map.cache[c, alpha] except (KeyError, TypeError): # Not in cache, or unhashable. diff --git a/lib/matplotlib/tests/test_colors.py b/lib/matplotlib/tests/test_colors.py index 2f221f07d036..5c4e3a375bca 100644 --- a/lib/matplotlib/tests/test_colors.py +++ b/lib/matplotlib/tests/test_colors.py @@ -637,6 +637,8 @@ def test_cn(): ['xkcd:blue', 'r']) assert mcolors.to_hex("C0") == '#0343df' assert mcolors.to_hex("C1") == '#ff0000' + assert mcolors.to_hex("C10") == '#0343df' + assert mcolors.to_hex("C11") == '#ff0000' matplotlib.rcParams['axes.prop_cycle'] = cycler('color', ['8e4585', 'r']) diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index 96cbb49473b7..3380308d7d81 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -306,7 +306,7 @@ def generate_validator_testcases(valid): ('AABBCC', '#AABBCC'), # RGB hex code ('AABBCC00', '#AABBCC00'), # RGBA hex code ('tab:blue', 'tab:blue'), # named color - ('C0', 'C0'), # color from cycle + ('C12', 'C12'), # color from cycle ('(0, 1, 0)', [0.0, 1.0, 0.0]), # RGB tuple ((0, 1, 0), (0, 1, 0)), # non-string version ('(0, 1, 0, 1)', [0.0, 1.0, 0.0, 1.0]), # RGBA tuple @@ -314,7 +314,6 @@ def generate_validator_testcases(valid): ('(0, 1, "0.5")', [0.0, 1.0, 0.5]), # unusual but valid ), 'fail': (('tab:veryblue', ValueError), # invalid name - ('C123', ValueError), # invalid RGB(A) code and cycle index ('(0, 1)', ValueError), # tuple with length < 3 ('(0, 1, 0, 1, 0)', ValueError), # tuple with length > 4 ('(0, 1, none)', ValueError), # cannot cast none to float diff --git a/tutorials/colors/colors.py b/tutorials/colors/colors.py index 75a80081b43a..89108548ca86 100644 --- a/tutorials/colors/colors.py +++ b/tutorials/colors/colors.py @@ -18,9 +18,9 @@ '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 "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 +* a "CN" color spec, i.e. `'C'` followed by a number, which is an index into + the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``); the + indexing is intended to occur at rendering time, and defaults to black if the cycle does not include color. "Red", "Green" and "Blue", are the intensities of those colors, the combination