When running the initial lasso demo I found that only one lasso event was allowed and other canvas interaction events (e.g. zooming) would not work properly after the lasso event. As such I came up with my own solution to the problem by modifying the example source. The primary addition was a button release event call and a boolean to keep track whether the lasso was the last event to lock the widget from interaction. Anyway, I hope it can help someone else out.
Cheers,
Brian
lasso_test.py (3.04 KB)
···
####################################
“”"
Show how to use a lasso to select a set of points and get the indices
of the selected points. A callback is used to change the color of the
selected points
This is currently a proof-of-concept implementation (though it is
usable as is). There will be some refinement of the API
and the
inside polygon detection routine.
“”"
from matplotlib.widgets import Lasso
import matplotlib.mlab
from matplotlib.nxutils import points_inside_poly
from matplotlib.colors import colorConverter
from matplotlib.collections import RegularPolyCollection
from matplotlib.pyplot import figure, show
from numpy import nonzero
from numpy.random import rand
class Datum:
colorin = colorConverter.to_rgba(‘red’)
colorout = colorConverter.to_rgba(‘green’)
def init(self, x, y, include=False):
self.x = x
self.y = y
if include: self.color = self.colorin
else: self.color = self.colorout
class LassoManager:
def init(self, ax,
data):
self.axes = ax
self.canvas = ax.figure.canvas
self.data = data
#the lasso lock boolean is used to tell whether another
#widget event has priority
self.lassoLock = False
self.Nxy = len(data)
facecolors = [d.color for d in data]
self.xys = [(d.x, d.y) for d in data]
fig = ax.figure
self.collection = RegularPolyCollection(
fig.dpi, 6,
sizes=(100,),
facecolors=facecolors,
offsets = self.xys,
transOffset = ax.transData)
ax.add_collection(self.collection)
self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
self.cidRelease = self.canvas.mpl_connect('button_release_event', self.onrelease)
self.ind = None
def callback(self, verts):
facecolors = self.collection.get_facecolors()
ind = nonzero(points_inside_poly(self.xys,
verts))[0]
for i in range(self.Nxy):
if i in ind:
facecolors[i] = Datum.colorin
else:
facecolors[i] = Datum.colorout
self.canvas.draw_idle()
self.canvas.widgetlock.release(self.lasso)
#del self.lasso
self.ind = ind
def onpress(self, event):
if self.canvas.widgetlock.locked(): return
if
event.inaxes is None: return
self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback)
# acquire a lock on the widget drawing
self.canvas.widgetlock(self.lasso)
# establish boolean that can be used to release the widgetlock
self.lassoLock = True
def onrelease(self, event):
'on release we reset the press data'
# test whether the widgetlock was initiated by the lasso
if self.lassoLock:
self.canvas.widgetlock.release(self.lasso)
self.lassoLock = False
print self.ind
if name == ‘main’:
data = [Datum(*xy) for xy in rand(100, 2)]
fig = figure()
ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1), autoscale_on=False)
lman = LassoManager(ax, data)
show()