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> <dt>Saner default plots</dt>
<dd>Matplotlib plots are quite ugly by default, colors are not really <dd>Matplotlib plots are quite ugly by default, colors are not really
suited for optimal black and white print, or ease reading for colorblind 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> <dt>Support <code>with</code> statement</dt>
<dd>Ever got tired of having to start any figure with a call to <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 from replot.helpers import render as render_helpers
PREDEFINED_PALETTES = {
"colorbrewerq9": rpalette.COLORBREWER_Q9,
"colorbrewerq10": rpalette.COLORBREWER_Q10,
"tableau10": rpalette.TABLEAU_10
}
class Figure(): class Figure():
""" """
The main class from :mod:`replot`, representing a figure. Can be used \ The main class from :mod:`replot`, representing a figure. Can be used \
@ -34,7 +41,7 @@ class Figure():
def __init__(self, def __init__(self,
xlabel="", ylabel="", title="", xlabel="", ylabel="", title="",
xrange=None, yrange=None, xrange=None, yrange=None,
palette=rpalette.default, palette=None,
legend=None, savepath=None, grid=None, legend=None, savepath=None, grid=None,
custom_mpl_rc=None): custom_mpl_rc=None):
""" """
@ -53,7 +60,10 @@ class Figure():
:type palette: Either a list of colors (as RGB tuples) or a function \ :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 \ to call with number of plots as parameter and which returns a \
list of colors (as RGB tuples). You can also pass a Seaborn \ 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 \ :param legend: Whether to use a legend or not (optional). Defaults to \
no legend, except if labels are found on provided plots. \ no legend, except if labels are found on provided plots. \
``False`` to disable completely. ``None`` for default \ ``False`` to disable completely. ``None`` for default \
@ -491,20 +501,42 @@ class Figure():
colspan=colspan, colspan=colspan,
rowspan=rowspan) rowspan=rowspan)
# Set the palette for the subplot # 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( axes[symbol].set_prop_cycle(
rpalette.build_cycler_palette(self.palette, rpalette.build_cycler_palette(palette))
len(self.plots[symbol])))
if constants.DEFAULT_GROUP not in axes: if constants.DEFAULT_GROUP not in axes:
# Set the default group axis to None if it is not in the grid # Set the default group axis to None if it is not in the grid
axes[constants.DEFAULT_GROUP] = None axes[constants.DEFAULT_GROUP] = None
else: else:
axis = plt.subplot2grid((1, 1), (0, 0)) axis = plt.subplot2grid((1, 1), (0, 0))
# Set the palette for the subplot # 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( axis.set_prop_cycle(
rpalette.build_cycler_palette( rpalette.build_cycler_palette(palette))
self.palette,
sum([len(i) for i in self.plots.values()]))
)
# Set the axis for every subplot # Set the axis for every subplot
for subplot in self.plots: for subplot in self.plots:
axes[subplot] = axis axes[subplot] = axis

View File

@ -3,8 +3,8 @@ Functions to set custom :mod:`matplotlib` parameters.
""" """
import shutil import shutil
import cycler
import matplotlib as mpl import matplotlib as mpl
import numpy as np import numpy as np
@ -87,10 +87,17 @@ def _rc_axes_style():
""" """
# Use dark gray instead of black for better readability on screen # Use dark gray instead of black for better readability on screen
dark_gray = ".15" 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 = { rc_params = {
# Colors # Colors
"figure.facecolor": "white", "figure.facecolor": "white",
"text.color": dark_gray, "text.color": dark_gray,
"axes.prop_cycle": palette,
# Legend # Legend
"legend.frameon": False, # No frame around legend "legend.frameon": False, # No frame around legend
"legend.numpoints": 1, "legend.numpoints": 1,

View File

@ -5,9 +5,21 @@ import cycler
import palettable 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. number of plots.
:param n: The number of colors in the palette. :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 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. 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. :returns: a cycler object for the palette.
""" """
if hasattr(palette, "__call__"):
return cycler.cycler("color", palette(n))
else:
return cycler.cycler("color", palette) return cycler.cycler("color", palette)