python - matplotlib: update position of patches (or: set_xy for circles) -
inspired this example i'm trying write little matplotlib program allows user drag , drop datapoints in scatter plot dynamically. in contrast example uses bar plot (and allows dragging of rectangles) goal achieve same other patches, instance circle (any patch more scatter-plot-compatible rectangle do). i'm stuck @ point of updating position of patch. while rectangle
provides function set_xy
cannot find direct analog cirlce
or ellipse
. obtaining position of circle less straightforward rectangle, possible via obtaining bounding box. missing piece find way update position of patch. hint on how achieve great! current minimal working example this:
import numpy np import matplotlib.pyplot plt import matplotlib.patches patches class draggablepatch: def __init__(self, patch): self.patch = patch self.storedposition = none self.connect() def getposofpatch(self, marker): ext = marker.get_extents().get_points() x0 = ext[0,0] y0 = ext[0,1] x1 = ext[1,0] y1 = ext[1,1] return 0.5*(x0+x1), 0.5*(y0+y1) def connect(self): 'connect events need' self.cidpress = self.patch.figure.canvas.mpl_connect('button_press_event', self.onpress) self.cidmotion = self.patch.figure.canvas.mpl_connect('motion_notify_event', self.onmove) def onpress(self, event): 'on button press see if mouse on , store data' contains, attrd = self.patch.contains(event) if contains: self.storedposition = self.getposofpatch(self.patch), event.xdata, event.ydata def onmove(self, event): 'how update circle?!' contains, attrd = self.patch.contains(event) if contains , self.storedposition not none: oldpos, oldeventxdata, oldeventydata = self.storedposition dx = event.xdata - oldeventxdata dy = event.ydata - oldeventydata newx = oldpos[0] + dx newy = oldpos[1] + dy print "now move patch to", newx, newy def mypatch(x,y): return patches.circle((x,y), radius=.05, alpha=0.5) n = 10 x = np.random.random(n) y = np.random.random(n) patches = [mypatch(x[i], y[i]) in range(n)] fig = plt.figure() ax = fig.add_subplot(111) drs = [] patch in patches: ax.add_patch(patch) dr = draggablepatch(patch) drs.append(dr) plt.show()
it's bit annoying it's inconsistent, update position of circle, set circ.center = new_x, new_y
.
as simple (non-draggable) example:
import matplotlib.pyplot plt matplotlib.patches import circle class interactivecircle(object): def __init__(self): self.fig, self.ax = plt.subplots() self.ax.axis('equal') self.circ = circle((0.5, 0.5), 0.1) self.ax.add_artist(self.circ) self.ax.set_title('click move circle') self.fig.canvas.mpl_connect('button_press_event', self.on_click) def on_click(self, event): if event.inaxes none: return self.circ.center = event.xdata, event.ydata self.fig.canvas.draw() def show(self): plt.show() interactivecircle().show()
Comments
Post a Comment