Updated Lasso Demo

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()

+1 for including Brian's changes in the shipping example.

Brian, You might also be interested in an alternate, polygon-based
lasso I developed a while back. Though it meets my needs, beware of
backend-specific problems with idle events that I never resolved.

-Eric

http://www.nabble.com/Alternate-lasso:-click-to-form-polygon-td18724261.html

···

On Sun, Dec 7, 2008 at 10:24 AM, B Clowers <clowersb@...9...> wrote:

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

####################################
"""
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()

------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you. Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users