.. _pylab_examples-demo_agg_filter: pylab_examples example code: demo_agg_filter.py =============================================== .. plot:: /home/tcaswell/source/p/matplotlib/doc/mpl_examples/pylab_examples/demo_agg_filter.py :: import matplotlib.pyplot as plt import numpy as np import matplotlib.cm as cm import matplotlib.mlab as mlab def smooth1d(x, window_len): # copied from http://www.scipy.org/Cookbook/SignalSmooth s = np.r_[2*x[0] - x[window_len:1:-1], x, 2*x[-1] - x[-1:-window_len:-1]] w = np.hanning(window_len) y = np.convolve(w/w.sum(), s, mode='same') return y[window_len-1:-window_len+1] def smooth2d(A, sigma=3): window_len = max(int(sigma), 3)*2 + 1 A1 = np.array([smooth1d(x, window_len) for x in np.asarray(A)]) A2 = np.transpose(A1) A3 = np.array([smooth1d(x, window_len) for x in A2]) A4 = np.transpose(A3) return A4 class BaseFilter(object): def prepare_image(self, src_image, dpi, pad): ny, nx, depth = src_image.shape #tgt_image = np.zeros([pad*2+ny, pad*2+nx, depth], dtype="d") padded_src = np.zeros([pad*2 + ny, pad*2 + nx, depth], dtype="d") padded_src[pad:-pad, pad:-pad, :] = src_image[:, :, :] return padded_src # , tgt_image def get_pad(self, dpi): return 0 def __call__(self, im, dpi): pad = self.get_pad(dpi) padded_src = self.prepare_image(im, dpi, pad) tgt_image = self.process_image(padded_src, dpi) return tgt_image, -pad, -pad class OffsetFilter(BaseFilter): def __init__(self, offsets=None): if offsets is None: self.offsets = (0, 0) else: self.offsets = offsets def get_pad(self, dpi): return int(max(*self.offsets)/72.*dpi) def process_image(self, padded_src, dpi): ox, oy = self.offsets a1 = np.roll(padded_src, int(ox/72.*dpi), axis=1) a2 = np.roll(a1, -int(oy/72.*dpi), axis=0) return a2 class GaussianFilter(BaseFilter): "simple gauss filter" def __init__(self, sigma, alpha=0.5, color=None): self.sigma = sigma self.alpha = alpha if color is None: self.color = (0, 0, 0) else: self.color = color def get_pad(self, dpi): return int(self.sigma*3/72.*dpi) def process_image(self, padded_src, dpi): #offsetx, offsety = int(self.offsets[0]), int(self.offsets[1]) tgt_image = np.zeros_like(padded_src) aa = smooth2d(padded_src[:, :, -1]*self.alpha, self.sigma/72.*dpi) tgt_image[:, :, -1] = aa tgt_image[:, :, :-1] = self.color return tgt_image class DropShadowFilter(BaseFilter): def __init__(self, sigma, alpha=0.3, color=None, offsets=None): self.gauss_filter = GaussianFilter(sigma, alpha, color) self.offset_filter = OffsetFilter(offsets) def get_pad(self, dpi): return max(self.gauss_filter.get_pad(dpi), self.offset_filter.get_pad(dpi)) def process_image(self, padded_src, dpi): t1 = self.gauss_filter.process_image(padded_src, dpi) t2 = self.offset_filter.process_image(t1, dpi) return t2 from matplotlib.colors import LightSource class LightFilter(BaseFilter): "simple gauss filter" def __init__(self, sigma, fraction=0.5): self.gauss_filter = GaussianFilter(sigma, alpha=1) self.light_source = LightSource() self.fraction = fraction def get_pad(self, dpi): return self.gauss_filter.get_pad(dpi) def process_image(self, padded_src, dpi): t1 = self.gauss_filter.process_image(padded_src, dpi) elevation = t1[:, :, 3] rgb = padded_src[:, :, :3] rgb2 = self.light_source.shade_rgb(rgb, elevation, fraction=self.fraction) tgt = np.empty_like(padded_src) tgt[:, :, :3] = rgb2 tgt[:, :, 3] = padded_src[:, :, 3] return tgt class GrowFilter(BaseFilter): "enlarge the area" def __init__(self, pixels, color=None): self.pixels = pixels if color is None: self.color = (1, 1, 1) else: self.color = color def __call__(self, im, dpi): pad = self.pixels ny, nx, depth = im.shape new_im = np.empty([pad*2 + ny, pad*2 + nx, depth], dtype="d") alpha = new_im[:, :, 3] alpha.fill(0) alpha[pad:-pad, pad:-pad] = im[:, :, -1] alpha2 = np.clip(smooth2d(alpha, self.pixels/72.*dpi) * 5, 0, 1) new_im[:, :, -1] = alpha2 new_im[:, :, :-1] = self.color offsetx, offsety = -pad, -pad return new_im, offsetx, offsety from matplotlib.artist import Artist class FilteredArtistList(Artist): """ A simple container to draw filtered artist. """ def __init__(self, artist_list, filter): self._artist_list = artist_list self._filter = filter Artist.__init__(self) def draw(self, renderer): renderer.start_rasterizing() renderer.start_filter() for a in self._artist_list: a.draw(renderer) renderer.stop_filter(self._filter) renderer.stop_rasterizing() import matplotlib.transforms as mtransforms def filtered_text(ax): # mostly copied from contour_demo.py # prepare image delta = 0.025 x = np.arange(-3.0, 3.0, delta) y = np.arange(-2.0, 2.0, delta) X, Y = np.meshgrid(x, y) Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) # difference of Gaussians Z = 10.0 * (Z2 - Z1) # draw im = ax.imshow(Z, interpolation='bilinear', origin='lower', cmap=cm.gray, extent=(-3, 3, -2, 2)) levels = np.arange(-1.2, 1.6, 0.2) CS = ax.contour(Z, levels, origin='lower', linewidths=2, extent=(-3, 3, -2, 2)) ax.set_aspect("auto") # contour label cl = ax.clabel(CS, levels[1::2], # label every second level inline=1, fmt='%1.1f', fontsize=11) # change clable color to black from matplotlib.patheffects import Normal for t in cl: t.set_color("k") # to force TextPath (i.e., same font in all backends) t.set_path_effects([Normal()]) # Add white glows to improve visibility of labels. white_glows = FilteredArtistList(cl, GrowFilter(3)) ax.add_artist(white_glows) white_glows.set_zorder(cl[0].get_zorder() - 0.1) ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) def drop_shadow_line(ax): # copied from examples/misc/svg_filter_line.py # draw lines l1, = ax.plot([0.1, 0.5, 0.9], [0.1, 0.9, 0.5], "bo-", mec="b", mfc="w", lw=5, mew=3, ms=10, label="Line 1") l2, = ax.plot([0.1, 0.5, 0.9], [0.5, 0.2, 0.7], "ro-", mec="r", mfc="w", lw=5, mew=3, ms=10, label="Line 1") gauss = DropShadowFilter(4) for l in [l1, l2]: # draw shadows with same lines with slight offset. xx = l.get_xdata() yy = l.get_ydata() shadow, = ax.plot(xx, yy) shadow.update_from(l) # offset transform ot = mtransforms.offset_copy(l.get_transform(), ax.figure, x=4.0, y=-6.0, units='points') shadow.set_transform(ot) # adjust zorder of the shadow lines so that it is drawn below the # original lines shadow.set_zorder(l.get_zorder() - 0.5) shadow.set_agg_filter(gauss) shadow.set_rasterized(True) # to support mixed-mode renderers ax.set_xlim(0., 1.) ax.set_ylim(0., 1.) ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) def drop_shadow_patches(ax): # copyed from barchart_demo.py N = 5 menMeans = (20, 35, 30, 35, 27) ind = np.arange(N) # the x locations for the groups width = 0.35 # the width of the bars rects1 = ax.bar(ind, menMeans, width, color='r', ec="w", lw=2) womenMeans = (25, 32, 34, 20, 25) rects2 = ax.bar(ind + width + 0.1, womenMeans, width, color='y', ec="w", lw=2) #gauss = GaussianFilter(1.5, offsets=(1,1), ) gauss = DropShadowFilter(5, offsets=(1, 1), ) shadow = FilteredArtistList(rects1 + rects2, gauss) ax.add_artist(shadow) shadow.set_zorder(rects1[0].get_zorder() - 0.1) ax.set_xlim(ind[0] - 0.5, ind[-1] + 1.5) ax.set_ylim(0, 40) ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) def light_filter_pie(ax): fracs = [15, 30, 45, 10] explode = (0, 0.05, 0, 0) pies = ax.pie(fracs, explode=explode) ax.patch.set_visible(True) light_filter = LightFilter(9) for p in pies[0]: p.set_agg_filter(light_filter) p.set_rasterized(True) # to support mixed-mode renderers p.set(ec="none", lw=2) gauss = DropShadowFilter(9, offsets=(3, 4), alpha=0.7) shadow = FilteredArtistList(pies[0], gauss) ax.add_artist(shadow) shadow.set_zorder(pies[0][0].get_zorder() - 0.1) if 1: plt.figure(1, figsize=(6, 6)) plt.subplots_adjust(left=0.05, right=0.95) ax = plt.subplot(221) filtered_text(ax) ax = plt.subplot(222) drop_shadow_line(ax) ax = plt.subplot(223) drop_shadow_patches(ax) ax = plt.subplot(224) ax.set_aspect(1) light_filter_pie(ax) ax.set_frame_on(True) plt.show() Keywords: python, matplotlib, pylab, example, codex (see :ref:`how-to-search-examples`)