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