If I understand your post correctly, you only need to create a single
polygon, the one around the lasso region, and thus you should use a
matplotlib.patch.Polygon, not a RegularPolyCollection, which as the
name suggests is for multiple regular polygons. The
RegPolygonCollection in the lasso demo code is used to draw the many
polygons you are selecting but is not the right way to construct a
single polygon.
Also, in the future, it will help us if you post complete examples
that we can run, rather than snippets.
The following code does what I think you want::
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.patches import Polygon
from pylab import figure, show, nx
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
self.Nxy = len(data)
self.facecolors = [d.color for d in data]
self.xys = [(d.x, d.y) for d in data]
self.collection = RegularPolyCollection(
fig.dpi, 6, sizes=(100,),
facecolors=self.facecolors,
offsets = self.xys,
transOffset = ax.transData)
ax.add_collection(self.collection)
self.cid = self.canvas.mpl_connect('button_press_event', self.onpress)
def callback(self, verts):
#print 'all done', verts
#ind = matplotlib.mlab._inside_poly_deprecated(self.xys, verts)
ind = nx.nonzero(points_inside_poly(self.xys, verts))
for i in range(self.Nxy):
if i in ind:
self.facecolors[i] = Datum.colorin
else:
self.facecolors[i] = Datum.colorout
self.canvas.draw_idle()
self.canvas.widgetlock.release(self.lasso)
rect = Polygon(verts, facecolor='red', alpha=0.5)
self.axes.add_patch(rect)
self.canvas.draw_idle()
del self.lasso
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)
data = [Datum(*xy) for xy in nx.mlab.rand(100, 2)]
fig = figure()
ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1), autoscale_on=False)
lman = LassoManager(ax, data)
show()
JDH
Reply Forward
Reply
Reply to all Reply to allForward Forward Print Add JJ to Contacts list
Delete this message Report phishing Show original Message text
garbled?
JJ
to me
show details
1:28 pm (2 minutes ago)
Hello John
Thanks much for the help. It was just what I needed.
I do have another question for you though, if you have
a moment. When using the demo, if you click on the
plot but do not drag the mouse, the callback function
does not get called and a lock stays on the lasso.
Can you explain why the callback function does not
execute? (see code below)
Secondly, the callback function executes after the
last line of code in the onpress function. I would
have expected it to execute directly after being
called in the self.lasso = Lasso(...) line. Can you
explain why this is so? (see code below)
Thanks again for your assistance.
John
import os
from numpy import *
import glob
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.patches import Polygon
import pdb
- Show quoted text -
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
self.Nxy = len(data)
self.facecolors = [d.color for d in data]
self.xys = [(d.x, d.y) for d in data]
self.collection = RegularPolyCollection(
fig.dpi, 6, sizes=(100,),
facecolors=self.facecolors,
offsets = self.xys,
transOffset = ax.transData)
ax.add_collection(self.collection)
self.cid =
self.canvas.mpl_connect('button_press_event',
self.onpress)
def callback(self, verts):
print "in callback A:
",self.canvas.widgetlock.locked()
ind = nx.nonzero(points_inside_poly(self.xys,
verts))
for i in range(self.Nxy):
if i in ind:
self.facecolors[i] = Datum.colorin
else:
self.facecolors[i] = Datum.colorout
self.canvas.draw_idle()
self.canvas.widgetlock.release(self.lasso)
print "in callback B:
",self.canvas.widgetlock.locked()
# draw polygon
xyo=list()
for i in ind:
xyo.append(self.xys[i])
rect = Polygon(xyo, facecolor='red', alpha=0.5)
self.axes.add_patch(rect)
self.canvas.draw_idle()
del self.lasso
def onpress(self, event):
print "\n in
onpress",self.canvas.widgetlock.locked()
#pdb.set_trace()
if (event.button == 3) &
self.canvas.widgetlock.locked():
print "button 3:", event.button
self.canvas.widgetlock.release(self.lasso)
print self.canvas.widgetlock.locked()
if self.canvas.widgetlock.locked():
print "widget locked"
return
if event.inaxes is None:
print "inaxes is none"
return
print event.inaxes, (event.xdata, event.ydata)
self.lasso = Lasso(event.inaxes,(event.xdata,
event.ydata), self.callback)
# acquire a lock on the widget drawing
print "A: ",self.canvas.widgetlock.locked()
self.canvas.widgetlock(self.lasso)
print "B: ",self.canvas.widgetlock.locked()
data = [Datum(*xy) for xy in nx.mlab.rand(100,2)]
fig = figure()
ax = fig.add_subplot(111, xlim=(0,1), ylim=(0,1),
autoscale_on=False)
lman = LassoManager(ax, data)
show()
···
On 2/4/07, JJ <josh8912@...9...> wrote:
Hello.
I am new at matplotlib and am trying to modify the
lasso demo so that a line is drawn aound the polygon
made of selected points, and so that this polygon area
is shaded. Ive added the following code to the
callback function but receive the error: CXX : Error
creating object of type N2Py7SeqBaseINS_6ObjectEEE.
Im sure this is a simple modification. Can anyone
offer suggestions?