Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 05dce88

Browse files
committed
Cleanup demo_agg_filter.
1 parent 2cc5d8d commit 05dce88

File tree

2 files changed

+75
-132
lines changed

2 files changed

+75
-132
lines changed

examples/misc/demo_agg_filter.py

Lines changed: 46 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,97 +4,81 @@
44
===============
55
66
"""
7-
import matplotlib.pyplot as plt
87

9-
import numpy as np
108
import matplotlib.cm as cm
9+
import matplotlib.pyplot as plt
1110
import matplotlib.transforms as mtransforms
1211
from matplotlib.colors import LightSource
1312
from matplotlib.artist import Artist
13+
import numpy as np
1414

1515

1616
def smooth1d(x, window_len):
1717
# copied from http://www.scipy.org/Cookbook/SignalSmooth
18-
1918
s = np.r_[2*x[0] - x[window_len:1:-1], x, 2*x[-1] - x[-1:-window_len:-1]]
2019
w = np.hanning(window_len)
2120
y = np.convolve(w/w.sum(), s, mode='same')
2221
return y[window_len-1:-window_len+1]
2322

2423

2524
def smooth2d(A, sigma=3):
26-
27-
window_len = max(int(sigma), 3)*2 + 1
28-
A1 = np.array([smooth1d(x, window_len) for x in np.asarray(A)])
29-
A2 = np.transpose(A1)
30-
A3 = np.array([smooth1d(x, window_len) for x in A2])
31-
A4 = np.transpose(A3)
32-
33-
return A4
25+
window_len = max(int(sigma), 3) * 2 + 1
26+
A = np.apply_along_axis(smooth1d, 0, A, window_len)
27+
A = np.apply_along_axis(smooth1d, 1, A, window_len)
28+
return A
3429

3530

3631
class BaseFilter:
37-
def prepare_image(self, src_image, dpi, pad):
38-
ny, nx, depth = src_image.shape
39-
# tgt_image = np.zeros([pad*2+ny, pad*2+nx, depth], dtype="d")
40-
padded_src = np.zeros([pad*2 + ny, pad*2 + nx, depth], dtype="d")
41-
padded_src[pad:-pad, pad:-pad, :] = src_image[:, :, :]
42-
43-
return padded_src # , tgt_image
4432

4533
def get_pad(self, dpi):
4634
return 0
4735

36+
def process_image(padded_src, dpi):
37+
raise NotImplementedError("Should be overridden by subclasses")
38+
4839
def __call__(self, im, dpi):
4940
pad = self.get_pad(dpi)
50-
padded_src = self.prepare_image(im, dpi, pad)
41+
padded_src = np.pad(im, [(pad, pad), (pad, pad), (0, 0)], "constant")
5142
tgt_image = self.process_image(padded_src, dpi)
5243
return tgt_image, -pad, -pad
5344

5445

5546
class OffsetFilter(BaseFilter):
56-
def __init__(self, offsets=None):
57-
if offsets is None:
58-
self.offsets = (0, 0)
59-
else:
60-
self.offsets = offsets
47+
48+
def __init__(self, offsets=(0, 0)):
49+
self.offsets = offsets
6150

6251
def get_pad(self, dpi):
63-
return int(max(*self.offsets)/72.*dpi)
52+
return int(max(self.offsets) / 72 * dpi)
6453

6554
def process_image(self, padded_src, dpi):
6655
ox, oy = self.offsets
67-
a1 = np.roll(padded_src, int(ox/72.*dpi), axis=1)
68-
a2 = np.roll(a1, -int(oy/72.*dpi), axis=0)
69-
return a2
56+
return np.roll(padded_src, (-int(oy / 72 * dpi), int(ox / 72 * dpi)),
57+
axis=(0, 1))
7058

7159

7260
class GaussianFilter(BaseFilter):
73-
"simple gauss filter"
61+
"""Simple Gaussian filter."""
7462

75-
def __init__(self, sigma, alpha=0.5, color=None):
63+
def __init__(self, sigma, alpha=0.5, color=(0, 0, 0)):
7664
self.sigma = sigma
7765
self.alpha = alpha
78-
if color is None:
79-
self.color = (0, 0, 0)
80-
else:
81-
self.color = color
66+
self.color = color
8267

8368
def get_pad(self, dpi):
84-
return int(self.sigma*3/72.*dpi)
69+
return int(self.sigma*3 / 72 * dpi)
8570

8671
def process_image(self, padded_src, dpi):
87-
# offsetx, offsety = int(self.offsets[0]), int(self.offsets[1])
88-
tgt_image = np.zeros_like(padded_src)
89-
aa = smooth2d(padded_src[:, :, -1]*self.alpha,
90-
self.sigma/72.*dpi)
91-
tgt_image[:, :, -1] = aa
92-
tgt_image[:, :, :-1] = self.color
72+
tgt_image = np.empty_like(padded_src)
73+
tgt_image[:, :, :3] = self.color
74+
tgt_image[:, :, 3] = smooth2d(padded_src[:, :, 3] * self.alpha,
75+
self.sigma / 72 * dpi)
9376
return tgt_image
9477

9578

9679
class DropShadowFilter(BaseFilter):
97-
def __init__(self, sigma, alpha=0.3, color=None, offsets=None):
80+
81+
def __init__(self, sigma, alpha=0.3, color=(0, 0, 0), offsets=(0, 0)):
9882
self.gauss_filter = GaussianFilter(sigma, alpha, color)
9983
self.offset_filter = OffsetFilter(offsets)
10084

@@ -109,7 +93,6 @@ def process_image(self, padded_src, dpi):
10993

11094

11195
class LightFilter(BaseFilter):
112-
"simple gauss filter"
11396

11497
def __init__(self, sigma, fraction=0.5):
11598
self.gauss_filter = GaussianFilter(sigma, alpha=1)
@@ -123,47 +106,36 @@ def process_image(self, padded_src, dpi):
123106
t1 = self.gauss_filter.process_image(padded_src, dpi)
124107
elevation = t1[:, :, 3]
125108
rgb = padded_src[:, :, :3]
126-
109+
alpha = padded_src[:, :, 3:]
127110
rgb2 = self.light_source.shade_rgb(rgb, elevation,
128111
fraction=self.fraction)
129-
130-
tgt = np.empty_like(padded_src)
131-
tgt[:, :, :3] = rgb2
132-
tgt[:, :, 3] = padded_src[:, :, 3]
133-
134-
return tgt
112+
return np.concatenate([rgb2, alpha], -1)
135113

136114

137115
class GrowFilter(BaseFilter):
138-
"enlarge the area"
116+
"""Enlarge the area."""
139117

140-
def __init__(self, pixels, color=None):
118+
def __init__(self, pixels, color=(1, 1, 1)):
141119
self.pixels = pixels
142-
if color is None:
143-
self.color = (1, 1, 1)
144-
else:
145-
self.color = color
120+
self.color = color
146121

147122
def __call__(self, im, dpi):
148-
ny, nx, depth = im.shape
149-
alpha = np.pad(im[..., -1], self.pixels, "constant")
150-
alpha2 = np.clip(smooth2d(alpha, self.pixels/72.*dpi) * 5, 0, 1)
123+
alpha = np.pad(im[..., 3], self.pixels, "constant")
124+
alpha2 = np.clip(smooth2d(alpha, self.pixels / 72 * dpi) * 5, 0, 1)
151125
new_im = np.empty((*alpha2.shape, 4))
152-
new_im[:, :, -1] = alpha2
153-
new_im[:, :, :-1] = self.color
126+
new_im[:, :, :3] = self.color
127+
new_im[:, :, 3] = alpha2
154128
offsetx, offsety = -self.pixels, -self.pixels
155129
return new_im, offsetx, offsety
156130

157131

158132
class FilteredArtistList(Artist):
159-
"""
160-
A simple container to draw filtered artist.
161-
"""
133+
"""A simple container to filter multiple artists at once."""
162134

163135
def __init__(self, artist_list, filter):
136+
super().__init__()
164137
self._artist_list = artist_list
165138
self._filter = filter
166-
Artist.__init__(self)
167139

168140
def draw(self, renderer):
169141
renderer.start_rasterizing()
@@ -188,15 +160,13 @@ def filtered_text(ax):
188160

189161
# draw
190162
ax.imshow(Z, interpolation='bilinear', origin='lower',
191-
cmap=cm.gray, extent=(-3, 3, -2, 2))
163+
cmap=cm.gray, extent=(-3, 3, -2, 2), aspect='auto')
192164
levels = np.arange(-1.2, 1.6, 0.2)
193165
CS = ax.contour(Z, levels,
194166
origin='lower',
195167
linewidths=2,
196168
extent=(-3, 3, -2, 2))
197169

198-
ax.set_aspect("auto")
199-
200170
# contour label
201171
cl = ax.clabel(CS, levels[1::2], # label every second level
202172
inline=1,
@@ -223,17 +193,14 @@ def drop_shadow_line(ax):
223193
# copied from examples/misc/svg_filter_line.py
224194

225195
# draw lines
226-
l1, = ax.plot([0.1, 0.5, 0.9], [0.1, 0.9, 0.5], "bo-",
227-
mec="b", mfc="w", lw=5, mew=3, ms=10, label="Line 1")
228-
l2, = ax.plot([0.1, 0.5, 0.9], [0.5, 0.2, 0.7], "ro-",
229-
mec="r", mfc="w", lw=5, mew=3, ms=10, label="Line 1")
196+
l1, = ax.plot([0.1, 0.5, 0.9], [0.1, 0.9, 0.5], "bo-")
197+
l2, = ax.plot([0.1, 0.5, 0.9], [0.5, 0.2, 0.7], "ro-")
230198

231199
gauss = DropShadowFilter(4)
232200

233201
for l in [l1, l2]:
234202

235203
# draw shadows with same lines with slight offset.
236-
237204
xx = l.get_xdata()
238205
yy = l.get_ydata()
239206
shadow, = ax.plot(xx, yy)
@@ -288,7 +255,6 @@ def light_filter_pie(ax):
288255
fracs = [15, 30, 45, 10]
289256
explode = (0, 0.05, 0, 0)
290257
pies = ax.pie(fracs, explode=explode)
291-
ax.patch.set_visible(True)
292258

293259
light_filter = LightFilter(9)
294260
for p in pies[0]:
@@ -305,21 +271,12 @@ def light_filter_pie(ax):
305271

306272
if __name__ == "__main__":
307273

308-
plt.figure(figsize=(6, 6))
309-
plt.subplots_adjust(left=0.05, right=0.95)
310-
311-
ax = plt.subplot(221)
312-
filtered_text(ax)
313-
314-
ax = plt.subplot(222)
315-
drop_shadow_line(ax)
316-
317-
ax = plt.subplot(223)
318-
drop_shadow_patches(ax)
274+
fix, axs = plt.subplots(2, 2)
319275

320-
ax = plt.subplot(224)
321-
ax.set_aspect(1)
322-
light_filter_pie(ax)
323-
ax.set_frame_on(True)
276+
filtered_text(axs[0, 0])
277+
drop_shadow_line(axs[0, 1])
278+
drop_shadow_patches(axs[1, 0])
279+
light_filter_pie(axs[1, 1])
280+
axs[1, 1].set_frame_on(True)
324281

325282
plt.show()

lib/matplotlib/tests/test_agg.py

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -81,93 +81,80 @@ def test_long_path():
8181
@image_comparison(['agg_filter.png'], remove_text=True)
8282
def test_agg_filter():
8383
def smooth1d(x, window_len):
84-
s = np.r_[2*x[0] - x[window_len:1:-1],
85-
x,
86-
2*x[-1] - x[-1:-window_len:-1]]
84+
# copied from http://www.scipy.org/Cookbook/SignalSmooth
85+
s = np.r_[
86+
2*x[0] - x[window_len:1:-1], x, 2*x[-1] - x[-1:-window_len:-1]]
8787
w = np.hanning(window_len)
8888
y = np.convolve(w/w.sum(), s, mode='same')
8989
return y[window_len-1:-window_len+1]
9090

9191
def smooth2d(A, sigma=3):
92-
window_len = max(int(sigma), 3)*2 + 1
93-
A1 = np.array([smooth1d(x, window_len) for x in np.asarray(A)])
94-
A2 = np.transpose(A1)
95-
A3 = np.array([smooth1d(x, window_len) for x in A2])
96-
A4 = np.transpose(A3)
97-
98-
return A4
92+
window_len = max(int(sigma), 3) * 2 + 1
93+
A = np.apply_along_axis(smooth1d, 0, A, window_len)
94+
A = np.apply_along_axis(smooth1d, 1, A, window_len)
95+
return A
9996

10097
class BaseFilter:
101-
def prepare_image(self, src_image, dpi, pad):
102-
ny, nx, depth = src_image.shape
103-
padded_src = np.zeros([pad*2 + ny, pad*2 + nx, depth], dtype="d")
104-
padded_src[pad:-pad, pad:-pad, :] = src_image[:, :, :]
105-
106-
return padded_src # , tgt_image
10798

10899
def get_pad(self, dpi):
109100
return 0
110101

102+
def process_image(padded_src, dpi):
103+
raise NotImplementedError("Should be overridden by subclasses")
104+
111105
def __call__(self, im, dpi):
112106
pad = self.get_pad(dpi)
113-
padded_src = self.prepare_image(im, dpi, pad)
107+
padded_src = np.pad(im, [(pad, pad), (pad, pad), (0, 0)], "constant")
114108
tgt_image = self.process_image(padded_src, dpi)
115109
return tgt_image, -pad, -pad
116110

117111
class OffsetFilter(BaseFilter):
118-
def __init__(self, offsets=None):
119-
if offsets is None:
120-
self.offsets = (0, 0)
121-
else:
122-
self.offsets = offsets
112+
113+
def __init__(self, offsets=(0, 0)):
114+
self.offsets = offsets
123115

124116
def get_pad(self, dpi):
125-
return int(max(*self.offsets)/72.*dpi)
117+
return int(max(self.offsets) / 72 * dpi)
126118

127119
def process_image(self, padded_src, dpi):
128120
ox, oy = self.offsets
129-
a1 = np.roll(padded_src, int(ox/72.*dpi), axis=1)
130-
a2 = np.roll(a1, -int(oy/72.*dpi), axis=0)
131-
return a2
121+
return np.roll(padded_src, (-int(oy / 72 * dpi), int(ox / 72 * dpi)),
122+
axis=(0, 1))
132123

133124
class GaussianFilter(BaseFilter):
134-
"simple gauss filter"
125+
"""Simple Gaussian filter."""
135126

136-
def __init__(self, sigma, alpha=0.5, color=None):
127+
def __init__(self, sigma, alpha=0.5, color=(0, 0, 0)):
137128
self.sigma = sigma
138129
self.alpha = alpha
139-
if color is None:
140-
self.color = (0, 0, 0)
141-
else:
142-
self.color = color
130+
self.color = color
143131

144132
def get_pad(self, dpi):
145-
return int(self.sigma*3/72.*dpi)
133+
return int(self.sigma*3 / 72 * dpi)
146134

147135
def process_image(self, padded_src, dpi):
148-
tgt_image = np.zeros_like(padded_src)
149-
aa = smooth2d(padded_src[:, :, -1]*self.alpha,
150-
self.sigma/72.*dpi)
151-
tgt_image[:, :, -1] = aa
152-
tgt_image[:, :, :-1] = self.color
136+
tgt_image = np.empty_like(padded_src)
137+
tgt_image[:, :, :3] = self.color
138+
tgt_image[:, :, 3] = smooth2d(padded_src[:, :, 3] * self.alpha,
139+
self.sigma / 72 * dpi)
153140
return tgt_image
154141

155142
class DropShadowFilter(BaseFilter):
156-
def __init__(self, sigma, alpha=0.3, color=None, offsets=None):
143+
144+
def __init__(self, sigma, alpha=0.3, color=(0, 0, 0), offsets=(0, 0)):
157145
self.gauss_filter = GaussianFilter(sigma, alpha, color)
158146
self.offset_filter = OffsetFilter(offsets)
159147

160148
def get_pad(self, dpi):
161149
return max(self.gauss_filter.get_pad(dpi),
162-
self.offset_filter.get_pad(dpi))
150+
self.offset_filter.get_pad(dpi))
163151

164152
def process_image(self, padded_src, dpi):
165153
t1 = self.gauss_filter.process_image(padded_src, dpi)
166154
t2 = self.offset_filter.process_image(t1, dpi)
167155
return t2
168156

169-
fig = plt.figure()
170-
ax = fig.add_subplot(111)
157+
fig, ax = plt.subplots()
171158

172159
# draw lines
173160
l1, = ax.plot([0.1, 0.5, 0.9], [0.1, 0.9, 0.5], "bo-",
@@ -180,7 +167,6 @@ def process_image(self, padded_src, dpi):
180167
for l in [l1, l2]:
181168

182169
# draw shadows with same lines with slight offset.
183-
184170
xx = l.get_xdata()
185171
yy = l.get_ydata()
186172
shadow, = ax.plot(xx, yy)

0 commit comments

Comments
 (0)