"""
plotting utilities
"""
import numpy as np
import matplotlib.pyplot as plt
colors=['k','mediumblue','red','darkgreen','lime','magenta', 'blueviolet','orange','yellow','cyan','olivedrab','salmon','saddlebrown','dodgerblue','tomato','tan']
# plot as separated segments
# dx: distance at which to break up data
# *args, **kwargs sent to plt.plot()
# dbreak keyword to set break distance
[docs]def breakplot(x, y, *args, **kwargs):
if 'yerr' in kwargs:
yerr = kwargs.pop('yerr')
else:
yerr = None
i2 = np.arange(len(x))
dx = np.diff(x)
# some logic to set clustering, balance clustering against number of segments
if 'dbreak' not in kwargs:
dbreak=0.5
isplit = np.nonzero(np.abs(dx) > dbreak)[0]
if len(isplit) > 0:
isplit += 1
for i3 in np.split(i2, isplit):
if yerr is not None:
plt.errorbar(x[i3], y[i3], yerr[i3], *args, **kwargs)
else:
plt.plot(x[i3], y[i3], *args, **kwargs)
# remove lines across gaps in data
# this appears to stop working for N>=1000, probably due to lines.py:706 in matplotlib 2.0.0
[docs]def rmgaps(dbreakx=2., dbreaky=None):
if dbreaky == None:
dbreaky = 1e12
for line in plt.gca().get_lines():
codes = np.full(len(line._path.vertices[:,0]), 2, dtype=np.uint8)
dx = np.hstack(([dbreakx+1.], np.abs(np.diff(line._path.vertices[:,0]))))
dy = np.hstack(([dbreaky+1.], np.abs(np.diff(line._path.vertices[:,1]))))
codes[(dx > dbreakx) | (dy > dbreaky)] = 1
line._path.codes = codes
plt.draw()
# remove lines across gaps in data
def rmgaps2(dbreak=2.):
for line in plt.gca().get_lines():
# this is not the right output tuple for cleaned() -- don't remember why I started this 2nd function..
# v, c = line._path.cleaned()
codes = np.full(len(line._path.vertices[:,0]), 2, dtype=np.uint8)
dx = np.hstack(([dbreak+1.], np.abs(np.diff(line._path.vertices[:,0]))))
codes[dx > dbreak] = 1
line._path.codes = codes
plt.draw()
# remove lines across gaps in data -- or this one
[docs]def rmgaps2(dbreak=2.):
for line in plt.gca().get_lines():
None
# tag a plot using fake "legend"
# note: this is probably unnecessary now, you can use loc with anchored text
# however this is still useful if you want loc="best"
# http://stackoverflow.com/questions/7045729/automatically-position-text-box-in-matplotlib
[docs]def tag(tagstr, **kwargs):
from matplotlib.legend import Legend
ax = plt.gca()
h, = ax.plot(np.NaN, np.NaN, '-', color='none') # empty line for legend
leg = Legend(ax, (h,), (tagstr,), handlelength=0, handletextpad=0, **kwargs)
for item in leg.legendHandles:
item.set_visible(False)
ax.add_artist(leg)
[docs]def figsize(width, height):
plt.setp(plt.gcf(), figwidth=width, figheight=height)
# set y0 to something between 0 and 1 so that ylog plots work, w=weight
[docs]def stepcdf(ranks, x0=0, y0=0.1, w=1.0, **kwargs):
if type(w) is int or type(w) is float:
w = w * np.ones_like(ranks)
sidx = np.argsort(ranks)
srank = ranks[sidx] # ranks from small to big
wtot = np.sum(w)
count = np.empty(len(w) + 1)
count[0] = wtot
count[1:] = wtot - np.cumsum(w[sidx]) # counts # of events between rank and previous rank
count[-1] += w[sidx[-1]]*y0 # some slob so that logscale plots do not get eaten instead of zero
ypt = np.vstack((count, count)).T.ravel()[:-1]
xpt = np.hstack((x0, np.vstack((srank, srank)).T.ravel()))
plt.plot(xpt, ypt, **kwargs)
# confidence interval for one-sided Gaussian RV
[docs]def normconfidence(maxval=10.):
from scipy.stats import norm
xx = np.linspace(0, maxval, 200)
sf = nomm.sf(xx)
[docs]def multline(xs, fun=plt.axvline):
for x in xs: fun(x, alpha=0.25, ls='--', color='k')
[docs]def wide(w=8, h=3): plt.setp(plt.gcf(), figwidth=w, figheight=h); \
plt.tight_layout()