20160509

More colors for Matplotlib

 
The default Matplotlib color scheme is not good. While searching for something better for my thesis, I stumbled upon Bridget Riley's painting "Gather" in the RISD museum. Is uses five colors: white, black, ochre, blue, turquoise, and a rust-colored red. But, from a distance they combine to create something far more vibrant. The blue and the turquoise hues are similar, so perhaps not the best to combine in a plot, but the others form an attractive and distinct pallet:

White #f1f0e9
Black #44525c
Rust #eb7a59
Ochre #eea300
Azure #5aa0df
Turquoise #00bac9

Surprisingly, when I ran this through a color-blindness simulator , some colors become even more distinct, so it is fairly color-blind friendly. I added colors to expand the pallet, to handle gradients and plots with extra lines.

Yellow #efcd2b
Moss #77ae64
Mauve #b56ab6
Magenta #cc79a7
Violet #8d5ccd
Indigo #606ec3
Viridian #11be8d
Chartreuse #b59f1a

These are less distinct, and not all combinations are color-blind friendly. Here's a bit of Python to define and tests these colors:

from pylab import *
from matplotlib import patches

WHITE = mpl.colors.to_rgb('#f1f0e9') RUST = mpl.colors.to_rgb('#eb7a59') OCHRE = mpl.colors.to_rgb('#eea300') AZURE = mpl.colors.to_rgb('#5aa0df') TURQUOISE = mpl.colors.to_rgb('#00bac9') BLACK = mpl.colors.to_rgb('#44525c') YELLOW = mpl.colors.to_rgb('#efcd2b') INDIGO = mpl.colors.to_rgb('#606ec3') VIOLET = mpl.colors.to_rgb('#8d5ccd') MAUVE = mpl.colors.to_rgb('#b56ab6') MAGENTA = mpl.colors.to_rgb('#cc79a7') CHARTREUSE = mpl.colors.to_rgb('#b59f1a') MOSS = mpl.colors.to_rgb('#77ae64') VIRIDIAN = mpl.colors.to_rgb('#11be8d')

GATHER = [WHITE,RUST,OCHRE,AZURE,TURQUOISE,BLACK] COLORS = [BLACK,WHITE,YELLOW,OCHRE,CHARTREUSE,MOSS,VIRIDIAN,TURQUOISE,AZURE,INDIGO,VIOLET,MAUVE,MAGENTA,RUST] CYCLE = [BLACK,RUST,AZURE,OCHRE,TURQUOISE,MAUVE,YELLOW,INDIGO] mpl.rcParams['axes.prop_cycle'] = mpl.cycler(color=CYCLE)

def test_panel(COLORS): ax = gca() NCOLORS = len(COLORS) axis('off') xlim(0,NCOLORS) ylim(NCOLORS,0) for j in range(NCOLORS): for i in range(NCOLORS): ax.add_patch(patches.Rectangle((i,j),1,1,linewidth=1, edgecolor='none',facecolor=COLORS[i])) ax.add_patch(patches.Rectangle((i+.25,j+.25),.5,.5,linewidth=1, edgecolor='none',facecolor=COLORS[j])) axis('equal')

figure(figsize=(6,3),dpi=200) subplots_adjust(0,0,1,1,0.1,0) subplot(111) test_panel(COLORS) savefig('colorblind_test_panel.png',bbox_inches='tight',pad_inches=0) </pre></div>

Two squences form decent color maps. They aren't perceptually uniform, but pass the color blindness simulator tests. Adding violet, mauve, and moss, to the original Gather pallet creates a hue wheel. This one flunks color-blindness test (see Crameri et al. ). Here they are in python:

riley2 = matplotlib.colors.LinearSegmentedColormap.from_list('riley2',
    [INDIGO,VIOLET,MAUVE,MAGENTA,RUST,OCHRE])

riley3 = matplotlib.colors.LinearSegmentedColormap.from_list('riley3', [OCHRE,CHARTREUSE,MOSS,VIRIDIAN,TURQUOISE,AZURE])

# Smoothed out mauve, violet, rust, ochre, moss, turquoise, azure, in a loop hues = ['#8c62cc', '#9560c8', '#9e62c3', '#a765be', '#b068b6', '#bb6caa', '#c66f98', '#d27384', '#dd7670', '#e67c5c', '#ea8348', '#ec8b34', '#ec9421', '#e99c13', '#dea212', '#c9a620', '#b0a934', '#96ab4a', '#7cae60', '#62b076', '#48b38c', '#2eb5a2', '#1ab7b6', '#12b6c5', '#1cb2ce', '#2dadd4', '#41a7d8', '#529fdb', '#6194db', '#6d86d8', '#7977d4', '#836ad0'] riley = matplotlib.colors.LinearSegmentedColormap.from_list('riley',hues)

# Make new maps behave like native Matplotlib maps plt.register_cmap(name='riley2',cmap=riley2) plt.register_cmap(name='riley3',cmap=riley3) plt.register_cmap(name='riley' ,cmap=riley )

# Show as figure figure(figsize=(5,1),dpi=300) subplot(311) imshow([linspace(0,1,256)],cmap='riley2',aspect='auto') axis('off'); tight_layout() subplot(312) imshow([linspace(0,1,256)],cmap='riley3',aspect='auto') axis('off'); tight_layout() subplot(313) imshow([linspace(0,1,256)],cmap='riley',aspect='auto') axis('off'); tight_layout() subplots_adjust(hspace=0.3) savefig('moremaps.png') </pre></div>