Skip to content

Commit

Permalink
Fix matplotlib#5489: feature for specifying N in color cycle
Browse files Browse the repository at this point in the history
  • Loading branch information
mdboom committed Dec 14, 2015
1 parent c32f05d commit 3780d3b
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 3 deletions.
10 changes: 7 additions & 3 deletions examples/pylab_examples/color_demo.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
"""
matplotlib gives you 4 ways to specify colors,
matplotlib gives you 5 ways to specify colors,
1) as a single letter string, ala MATLAB
Expand All @@ -11,6 +11,10 @@
4) as a string representing a floating point number
from 0 to 1, corresponding to shades of gray.
5) as a string representing the Nth color in the
currently active color cycle, e.g. "[0]"
represents the first color in the color cycle.
See help(colors) for more info.
"""
import matplotlib.pyplot as plt
Expand All @@ -20,8 +24,8 @@
#subplot(111, facecolor='#ababab')
t = np.arange(0.0, 2.0, 0.01)
s = np.sin(2*np.pi*t)
plt.plot(t, s, 'y')
plt.xlabel('time (s)', color='r')
plt.plot(t, s, '[0]')
plt.xlabel('time (s)', color='[0]')
plt.ylabel('voltage (mV)', color='0.5') # grayscale color
plt.title('About as silly as it gets, folks', color='#afeeee')
plt.show()
12 changes: 12 additions & 0 deletions lib/matplotlib/axes/_base.py
Expand Up @@ -10,6 +10,7 @@
import warnings
import math
from operator import itemgetter
import re

import numpy as np
from numpy import ma
Expand Down Expand Up @@ -94,6 +95,17 @@ def _process_plot_format(fmt):
linestyle = 'None'
fmt = fmt.replace(' ', '')

# handle the N-th color in the color cycle
matches = re.findall('\[[0-9]+\]', fmt)
if len(matches) == 1:
color = mcolors.colorConverter._get_nth_color(
int(matches[0][1:-1]))
fmt = fmt.replace(matches[0], '')
elif len(matches) != 0:
if color is not None:
raise ValueError(
'Illegal format string "%s"; two color symbols' % fmt)

chars = [c for c in fmt]

for c in chars:
Expand Down
39 changes: 39 additions & 0 deletions lib/matplotlib/colors.py
Expand Up @@ -31,6 +31,13 @@
- k: black
- w: white
To use the colors that are part of the active color cycle in the
current style, use a string with the color number in square brackets.
For example:
- `[0]`: The first color in the cycle
- `[1]`: The second color in the cycle
Gray shades can be given as a string encoding a float in the 0-1 range, e.g.::
color = '0.75'
Expand Down Expand Up @@ -260,8 +267,36 @@ class ColorConverter(object):
'k': (0.0, 0.0, 0.0),
'w': (1.0, 1.0, 1.0), }

_prop_cycler = None

cache = {}

@classmethod
def _get_nth_color(cls, val):
"""
Get the Nth color in the current color cycle. If N is greater
than the number of colors in the cycle, it is wrapped around.
"""
from matplotlib.rcsetup import cycler
from matplotlib import rcParams

prop_cycler = rcParams['axes.prop_cycle']
if prop_cycler is None and 'axes.color_cycle' in rcParams:
clist = rcParams['axes.color_cycle']
prop_cycler = cycler('color', clist)

cycler = cls._get_property_cycler()
colors = cycler.by_key()['color']
return colors[val % len(colors)]

@classmethod
def _parse_nth_color(cls, val):
match = re.match('^\[[0-9]\]$', val)
if match is not None:
return cls._get_nth_color(int(val[1:-1]))

raise ValueError("Not a color cycle color")

def to_rgb(self, arg):
"""
Returns an *RGB* tuple of three floats from 0-1.
Expand Down Expand Up @@ -299,6 +334,10 @@ def to_rgb(self, arg):
argl = arg.lower()
color = self.colors.get(argl, None)
if color is None:
try:
argl = self._parse_nth_color(argl)
except ValueError:
pass
str1 = cnames.get(argl, argl)
if str1.startswith('#'):
color = hex2color(str1)
Expand Down

0 comments on commit 3780d3b

Please sign in to comment.