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

Skip to content

Commit c8f36bc

Browse files
committed
added lasso widget
svn path=/trunk/matplotlib/; revision=2583
1 parent e59c8cd commit c8f36bc

4 files changed

Lines changed: 156 additions & 0 deletions

File tree

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2006-07-19 Added lasso widget and example - JDH
2+
13
2006-07-18 Added blitting for QtAgg backend - CM
24

35
2006-07-17 Fixed bug #1523585: skip nans in semilog plots - DSD

examples/lasso_demo.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
"""
2+
Show how to use a lasso to select a set of points and get the indices
3+
of the selected points. A callback is used to change the color of the
4+
selected points
5+
6+
This is currently a proof-of-concept implementation (though it is
7+
usable as is). There will be some refinement of the API and the
8+
inside polygon detection routine.
9+
"""
10+
from matplotlib.widgets import Lasso
11+
from matplotlib.mlab import inside_poly
12+
from matplotlib.colors import colorConverter
13+
from matplotlib.collections import RegularPolyCollection
14+
15+
from pylab import figure, show, nx
16+
17+
class Datum:
18+
colorin = colorConverter.to_rgba('red')
19+
colorout = colorConverter.to_rgba('green')
20+
def __init__(self, x, y, include=False):
21+
self.x = x
22+
self.y = y
23+
if include: self.color = self.colorin
24+
else: self.color = self.colorout
25+
26+
27+
class LassoManager:
28+
def __init__(self, ax, data):
29+
self.axes = ax
30+
self.canvas = ax.figure.canvas
31+
self.data = data
32+
33+
self.Nxy = len(data)
34+
35+
self.facecolors = [d.color for d in data]
36+
self.xys = [(d.x, d.y) for d in data]
37+
38+
self.collection = RegularPolyCollection(
39+
fig.dpi, 6, sizes=(100,),
40+
facecolors=self.facecolors,
41+
offsets = self.xys,
42+
transOffset = ax.transData)
43+
44+
ax.add_collection(self.collection)
45+
46+
self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
47+
48+
def callback(self, verts):
49+
#print 'all done', verts
50+
ind = inside_poly(self.xys, verts)
51+
52+
for i in range(self.Nxy):
53+
if i in ind:
54+
self.facecolors[i] = Datum.colorin
55+
else:
56+
self.facecolors[i] = Datum.colorout
57+
58+
self.canvas.draw_idle()
59+
60+
def onpress(self, event):
61+
if event.inaxes is None: return
62+
self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback)
63+
64+
data = [Datum(*xy) for xy in nx.mlab.rand(100, 2)]
65+
66+
fig = figure()
67+
ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1), autoscale_on=False)
68+
lman = LassoManager(ax, data)
69+
70+
show()

lib/matplotlib/mlab.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,47 @@ def stineman_interp(xi,x,y,yp=None):
14281428

14291429
return yi
14301430

1431+
def inside_poly(points, verts):
1432+
"""
1433+
points is a sequence of x,y points
1434+
verts is a sequence of x,y vertices of a poygon
1435+
1436+
return value is a sequence on indices into points for the points
1437+
that are inside the polygon
1438+
"""
1439+
xys = nx.asarray(points)
1440+
Nxy = xys.shape[0]
1441+
Nv = len(verts)
1442+
1443+
1444+
def angle(x1, y1, x2, y2):
1445+
twopi = 2*nx.pi
1446+
theta1 = nx.arctan2(y1, x1)
1447+
theta2 = nx.arctan2(y2, x2)
1448+
dtheta = theta2-theta1
1449+
d = dtheta%twopi
1450+
d = nx.where(nx.less(d, 0), twopi + d, d)
1451+
return nx.where(nx.greater(d,nx.pi), d-twopi, d)
1452+
1453+
angles = nx.zeros((Nxy,), nx.Float)
1454+
x1 = nx.zeros((Nxy,), nx.Float)
1455+
y1 = nx.zeros((Nxy,), nx.Float)
1456+
x2 = nx.zeros((Nxy,), nx.Float)
1457+
y2 = nx.zeros((Nxy,), nx.Float)
1458+
x = xys[:,0]
1459+
y = xys[:,1]
1460+
for i in range(Nv):
1461+
thisx, thisy = verts[i]
1462+
x1 = thisx - x
1463+
y1 = thisy - y
1464+
thisx, thisy = verts[(i+1)%Nv]
1465+
x2 = thisx - x
1466+
y2 = thisy - y
1467+
1468+
a = angle(x1, y1, x2, y2)
1469+
angles += a
1470+
return nx.nonzero(nx.greater_equal(nx.absolute(angles), nx.pi))
1471+
14311472
### the following code was written and submitted by Fernando Perez
14321473
### from the ipython numutils package under a BSD license
14331474
# begin fperez functions

lib/matplotlib/widgets.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,3 +1124,46 @@ def onmove(self, event):
11241124
[self.eventpress.ydata, y])
11251125
self.update()
11261126
return False
1127+
1128+
class Lasso(Widget):
1129+
def __init__(self, ax, xy, callback=None, useblit=True):
1130+
self.axes = ax
1131+
self.figure = ax.figure
1132+
self.canvas = self.figure.canvas
1133+
self.useblit = useblit
1134+
if useblit:
1135+
self.background = self.canvas.copy_from_bbox(self.axes.bbox)
1136+
1137+
x, y = xy
1138+
self.verts = [(x,y)]
1139+
self.line = Line2D([x], [y], linestyle='-', color='black', lw=2)
1140+
self.axes.add_line(self.line)
1141+
self.callback = callback
1142+
self.cids = []
1143+
self.cids.append(self.canvas.mpl_connect('button_release_event', self.onrelease))
1144+
self.cids.append(self.canvas.mpl_connect('motion_notify_event', self.onmove))
1145+
1146+
def onrelease(self, event):
1147+
if self.verts is not None:
1148+
self.verts.append((event.xdata, event.ydata))
1149+
if len(self.verts)>2:
1150+
self.callback(self.verts)
1151+
self.axes.lines.remove(self.line)
1152+
self.verts = None
1153+
for cid in self.cids:
1154+
self.canvas.mpl_disconnect(cid)
1155+
1156+
def onmove(self, event):
1157+
if self.verts is None: return
1158+
if event.inaxes != self.axes: return
1159+
if event.button!=1: return
1160+
self.verts.append((event.xdata, event.ydata))
1161+
1162+
self.line.set_data(zip(*self.verts))
1163+
1164+
if self.useblit:
1165+
self.canvas.restore_region(self.background)
1166+
self.axes.draw_artist(self.line)
1167+
self.canvas.blit(self.axes.bbox)
1168+
else:
1169+
self.canvas.draw_idle()

0 commit comments

Comments
 (0)