Skip to content

Commit

Permalink
Merge pull request #12598 from anntzer/cn
Browse files Browse the repository at this point in the history
Support Cn colors with n>=10.
  • Loading branch information
jklymak committed Nov 5, 2018
2 parents a5901fa + aa96f2d commit e2625d0
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 39 deletions.
12 changes: 12 additions & 0 deletions 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")``.
10 changes: 5 additions & 5 deletions examples/color/color_demo.py
Expand Up @@ -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;
Expand All @@ -15,10 +15,10 @@
5) a X11/CSS4 ("html") color name, e.g. ``"blue"``;
6) a name from the `xkcd color survey <https://xkcd.com/color/rgb/>`__,
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
Expand Down
52 changes: 28 additions & 24 deletions lib/matplotlib/axes/_axes.py
Expand Up @@ -1526,32 +1526,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**
Expand Down Expand Up @@ -1596,11 +1578,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 = []

Expand Down
10 changes: 5 additions & 5 deletions lib/matplotlib/colors.py
Expand Up @@ -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.
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/tests/test_colors.py
Expand Up @@ -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'])

Expand Down
3 changes: 1 addition & 2 deletions lib/matplotlib/tests/test_rcparams.py
Expand Up @@ -306,15 +306,14 @@ 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
((0, 1, 0, 1), (0, 1, 0, 1)), # non-string version
('(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
Expand Down
6 changes: 3 additions & 3 deletions tutorials/colors/colors.py
Expand Up @@ -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
Expand Down

0 comments on commit e2625d0

Please sign in to comment.