"""
Pylab plotting utilities.
"""
from __future__ import division
__all__ = ["auto_shift",
"coordinated_colors", "dhsv", "next_color",
"plot_quantiles", "form_quantiles"]
[docs]
def auto_shift(offset):
"""
Return a y-offset coordinate transform for the current axes.
Each call to auto_shift increases the y-offset for the next line by
the given number of points (with 72 points per inch).
Example::
from matplotlib import pyplot as plt
from bumps.plotutil import auto_shift
trans = auto_shift(plt.gca())
plot(x, y, trans=trans)
"""
from matplotlib.transforms import ScaledTranslation
import pylab
ax = pylab.gca()
if ax.lines and hasattr(ax, '_auto_shift'):
ax._auto_shift += offset
else:
ax._auto_shift = 0
trans = pylab.gca().transData
if ax._auto_shift:
trans += ScaledTranslation(0, ax._auto_shift/72.,
pylab.gcf().dpi_scale_trans)
return trans
# ======== Color functions ========
[docs]
def next_color():
"""
Return the next color in the plot color cycle.
Example::
from matplotlib import pyplot as plt
from bumps.plotutil import next_color, dhsv
color = next_color()
plt.errorbar(x, y, yerr=dy, fmt='.', color=color)
# Draw the theory line with the same color as the data, but darker
plt.plot(x, y, '-', color=dhsv(color, dv=-0.2))
"""
import pylab
lines = pylab.gca()._get_lines
try:
base = lines.get_next_color()
except Exception:
try: # Cruft 1.7 - 3.7?
base = next(lines.prop_cycler)['color']
except Exception:
try: # Cruft 1.4-1.6?
base = next(lines.color_cycle)
except Exception: # Cruft 1.3 and earlier
base = lines._get_next_cycle_color()
base = next(lines.prop_cycler)['color']
except Exception:
try: # Cruft 1.4-1.6?
base = next(lines.color_cycle)
except Exception: # Cruft 1.3 and earlier
base = lines._get_next_cycle_color()
return base
[docs]
def coordinated_colors(base=None):
"""
Return a set of coordinated colors as c['base|light|dark'].
If *base* is not provided, use the next color in the color cycle as
the base. Light is bright and pale, dark is dull and saturated.
"""
if base is None:
base = next_color()
return dict(base=base,
light=dhsv(base, dv=+0.3, ds=-0.2),
dark=dhsv(base, dv=-0.25, ds=+0.35),
)
[docs]
def dhsv(color, dh=0., ds=0., dv=0., da=0.):
"""
Modify color on hsv scale.
*dv* change intensity, e.g., +0.1 to brighten, -0.1 to darken.
*dh* change hue
*ds* change saturation
*da* change transparency
Color can be any valid matplotlib color. The hsv scale is [0,1] in
each dimension. Saturation, value and alpha scales are clipped to [0,1]
after changing. The hue scale wraps between red to violet.
:Example:
Make sea green 10% darker:
>>> from bumps.plotutil import dhsv
>>> darker = dhsv('seagreen', dv=-0.1)
>>> print([int(v*255) for v in darker])
[37, 113, 71, 255]
"""
from matplotlib.colors import colorConverter
from colorsys import rgb_to_hsv, hsv_to_rgb
from numpy import clip, array, fmod
r, g, b, a = colorConverter.to_rgba(color)
# print "from color",r,g,b,a
h, s, v = rgb_to_hsv(r, g, b)
s, v, a = [clip(val, 0., 1.) for val in (s + ds, v + dv, a + da)]
h = fmod(h + dh, 1.)
r, g, b = hsv_to_rgb(h, s, v)
# print "to color",r,g,b,a
return array((r, g, b, a))
# ==== Specialized plotters =====
[docs]
def plot_quantiles(x, y, contours, color, alpha=None):
"""
Plot quantile curves for a set of lines.
*x* is the x coordinates for all lines.
*y* is the y coordinates, one row for each line.
*contours* is a list of confidence intervals expressed as percents.
*color* is the color to use for the quantiles. Quantiles are draw as
a filled region with alpha transparency. Higher probability regions
will be covered with multiple contours, which will make them lighter
and more saturated.
*alpha* is the transparency level to use for all fill regions. The
default value, alpha=2./(#contours+1), works pretty well.
"""
_, q = form_quantiles(y, contours)
_plot_quantiles(x, q, color, alpha)
def _plot_quantiles(x, q, color, alpha):
import pylab
# print "p",p
# print "q",q[:,:,0]
# print "y",y[:,0]
if alpha is None:
alpha = 2. / (len(q) + 1)
edgecolor = dhsv(color, ds=-(1 - alpha), dv=(1 - alpha))
for lo, hi in q:
pylab.fill_between(x, lo, hi,
facecolor=color, edgecolor=edgecolor,
alpha=alpha)
def _convert_contours_to_probabilities(contours):
"""
Given confidence intervals [a, b,...] as percents, return probability
in [0,1] for each interval as [a_low, a_high, b_low, b_high, ...].
"""
from numpy import hstack
# lower quantile for ci in percent = (100 - ci)/2
# upper quantile = 100 - lower quantile = 100 - (100-ci)/2 = (100 + ci)/2
# divide by an additional 100 to get proportion from 0 to 1
return hstack([(100.0 - p, 100.0 + p) for p in contours]) / 200.0