1

I've defined a custom color cycler in a text file, and am invoking it via plt.style.context(). The cycle I've defined has 12 colors. When annotating the plot, if I try to access my custom cycler colors using color strings, 'C0' through 'C9' work but 'C10' throws ValueError: Invalid RGBA argument: 'C10'. All 12 values are definitely in there. Contents of style file style.yaml:

axes.prop_cycle : cycler('color', ['332288', 'CC6677', 'DDCC77', '117733', '88CCEE', 'AA4499', '44AA99', '999933', '882255', '661100', '6699CC', 'AA4466'])

Test script:

import numpy as np
import matplotlib.pyplot as plt
data = np.c_[np.zeros(13), np.arange(13)].T
labels = list('abcdefghijklm')

with plt.style.context('style.yaml'):
    # just to prove that the colors are loading correctly:
    cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']
    print('{} colors: {}'.format(len(cycle), cycle))
    # now the actual plotting:
    fig, ax = plt.subplots()
    ax.plot(data)
    for ix in range(data.shape[1]):
        ax.text(x=1, y=data[1, ix], s=labels[ix], color='C{}'.format(ix))

The result (notwithstanding the ValueError that stops it plotting after 10 labels) is that the lines follow my custom cycler colors, but the text labels use the matplotlib default cycler colors (see screenshot). How can I get the text to appear using the custom cycler colors defined in the external YAML file?

screenshot of example plot

drammock
  • 2,373
  • 29
  • 40

1 Answers1

2

First, you can only access the first 10 colors of the colorcycle via the "CN"-notation. As matplotlib states it:

To access these colors outside of the property cycling the notation for colors 'CN', where N takes values 0-9, was added to denote the first 10 colors in mpl.rcParams['axes.prop_cycle']

Second, the values of CN are not updated within the style context and hence cannot be used for such cases.

However, you can of course use the colors from the cycler directly:
(Note that I'm ignoring the yaml part of the question here.)

import numpy as np
import matplotlib.pyplot as plt
from cycler import cycler
data = np.c_[np.zeros(13), np.arange(13)].T
labels = list('abcdefghijklm')

plt.rcParams["axes.prop_cycle"] = cycler('color', 
                    ['#332288', '#CC6677', '#DDCC77', '#117733', '#88CCEE', '#AA4499', 
                     '#44AA99', '#999933', '#882255', '#661100', '#6699CC', '#AA4466'])

cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']

fig, ax = plt.subplots()
ax.plot(data)
for ix in range(data.shape[1]):
    ax.text(x=1, y=data[1, ix], s=labels[ix], color=cycle[ix%len(cycle)])

plt.show()

A different method may be to cycle through the cycler with next:

import numpy as np
import matplotlib.pyplot as plt
from cycler import cycler

data = np.c_[np.zeros(13), np.arange(13)].T
labels = list('abcdefghijklm')

plt.rcParams["axes.prop_cycle"] = cycler('color', 
                    ['#332288', '#CC6677', '#DDCC77', '#117733', '#88CCEE', '#AA4499', 
                     '#44AA99', '#999933', '#882255', '#661100', '#6699CC', '#AA4466'])


fig, ax = plt.subplots()
ax.plot(data)

ax.set_prop_cycle(None)
cycler = ax._get_lines.prop_cycler
plt.gca().set_prop_cycle(None)
for ix in range(data.shape[1]):
    ax.text(x=1, y=data[1, ix], s=labels[ix], color=next(cycler)['color']) 

plt.show()

Both codes produce the following plot:

enter image description here

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • thanks; I was looking [in the wrong place](http://matplotlib.org/cycler/) for the documentation of the `Cn` notation. – drammock Sep 11 '17 at 22:08