Rework colorscheme, use Colorbrewer Q10 palette by default. Closes #8.

This commit is contained in:
Lucas Verney 2016-04-30 11:22:42 +02:00
parent 0dd58cb7b5
commit 1af5fef254
5 changed files with 7431 additions and 8161 deletions

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,9 @@ design in the API, or required feature!
<dt>Saner default plots</dt>
<dd>Matplotlib plots are quite ugly by default, colors are not really
suited for optimal black and white print, or ease reading for colorblind
people. This module defines a clean default colorscheme to solve it.</dd>
people. This module defines a clean default colorscheme to solve it (based
on Colorbrewer Q10 palette). It also provides direct access to the
Tableau10 and Colorbrewer Q9 palettes.</dd>
<dt>Support <code>with</code> statement</dt>
<dd>Ever got tired of having to start any figure with a call to

View File

@ -26,6 +26,13 @@ from replot.helpers import plot as plot_helpers
from replot.helpers import render as render_helpers
PREDEFINED_PALETTES = {
"colorbrewerq9": rpalette.COLORBREWER_Q9,
"colorbrewerq10": rpalette.COLORBREWER_Q10,
"tableau10": rpalette.TABLEAU_10
}
class Figure():
"""
The main class from :mod:`replot`, representing a figure. Can be used \
@ -34,7 +41,7 @@ class Figure():
def __init__(self,
xlabel="", ylabel="", title="",
xrange=None, yrange=None,
palette=rpalette.default,
palette=None,
legend=None, savepath=None, grid=None,
custom_mpl_rc=None):
"""
@ -53,7 +60,10 @@ class Figure():
:type palette: Either a list of colors (as RGB tuples) or a function \
to call with number of plots as parameter and which returns a \
list of colors (as RGB tuples). You can also pass a Seaborn \
palette directly, or use a Palettable Palette.mpl_colors.
palette directly, or use a Palettable ``Palette.mpl_colors``. \
You can also use ``colorbrewerq10`` (default), \
``colorbrewerq9`` or ``tableau10`` to use any of these \
predefined palettes.
:param legend: Whether to use a legend or not (optional). Defaults to \
no legend, except if labels are found on provided plots. \
``False`` to disable completely. ``None`` for default \
@ -491,20 +501,42 @@ class Figure():
colspan=colspan,
rowspan=rowspan)
# Set the palette for the subplot
palette = None
if self.palette is not None:
if hasattr(self.palette, "__call__"):
palette = self.palette(len(self.plots[symbol]))
elif isinstance(self.palette, str):
if self.palette in PREDEFINED_PALETTES:
palette = PREDEFINED_PALETTES[self.palette]
else:
palette = None
else:
palette = self.palette
if palette is not None:
axes[symbol].set_prop_cycle(
rpalette.build_cycler_palette(self.palette,
len(self.plots[symbol])))
rpalette.build_cycler_palette(palette))
if constants.DEFAULT_GROUP not in axes:
# Set the default group axis to None if it is not in the grid
axes[constants.DEFAULT_GROUP] = None
else:
axis = plt.subplot2grid((1, 1), (0, 0))
# Set the palette for the subplot
palette = None
if self.palette is not None:
if hasattr(self.palette, "__call__"):
palette = self.palette(
sum(
[len(i) for i in self.plots.values()]))
elif isinstance(self.palette, str):
if self.palette in PREDEFINED_PALETTES:
palette = PREDEFINED_PALETTES[self.palette]
else:
palette = None
else:
palette = self.palette
if palette is not None:
axis.set_prop_cycle(
rpalette.build_cycler_palette(
self.palette,
sum([len(i) for i in self.plots.values()]))
)
rpalette.build_cycler_palette(palette))
# Set the axis for every subplot
for subplot in self.plots:
axes[subplot] = axis

View File

@ -3,8 +3,8 @@ Functions to set custom :mod:`matplotlib` parameters.
"""
import shutil
import cycler
import matplotlib as mpl
import numpy as np
@ -87,10 +87,17 @@ def _rc_axes_style():
"""
# Use dark gray instead of black for better readability on screen
dark_gray = ".15"
# Use ColorBrewer-Q10 palette as default one TODO
palette = cycler.cycler(
"color", [
"#1f78b4", "#33a02c", "#e31a1c", "#ff7f00", "#6a3d9a",
"#a6cee3", "#b2df8a", "#fb9a99", "#fdbf6f", "#cab2d6"
])
rc_params = {
# Colors
"figure.facecolor": "white",
"text.color": dark_gray,
"axes.prop_cycle": palette,
# Legend
"legend.frameon": False, # No frame around legend
"legend.numpoints": 1,

View File

@ -5,9 +5,21 @@ import cycler
import palettable
def default(n):
COLORBREWER_Q10 = [
"#1f78b4", "#33a02c", "#e31a1c", "#ff7f00", "#6a3d9a",
"#a6cee3", "#b2df8a", "#fb9a99", "#fdbf6f", "#cab2d6"]
COLORBREWER_Q9 = [
"#e41a1c", "#377eb8", "#4daf4a", "#984ea3",
"#ff7f00", "#ffff33", "#a65628", "#f781bf", "#999999"]
TABLEAU_10 = [
"#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"]
def cubehelix(n):
"""
Default palette is a CubeHelix perceptual rainbow palette with length the
Builds a CubeHelix perceptual rainbow palette with length the
number of plots.
:param n: The number of colors in the palette.
@ -18,14 +30,12 @@ def default(n):
min_light=0.3, max_light=0.8, gamma=.9, n=n).mpl_colors
def build_cycler_palette(palette, n):
def build_cycler_palette(palette):
"""
Build a cycler palette for the selected subplot.
:param n: number of colors in the palette.
:param palette: A list of colors in a format understable by \
matplotlib.
:returns: a cycler object for the palette.
"""
if hasattr(palette, "__call__"):
return cycler.cycler("color", palette(n))
else:
return cycler.cycler("color", palette)