From: Srinath A. <sr...@fa...> - 2004-04-16 22:16:49
|
Hello all! I just recently downloaded Matplotlib and love it so far :) A hopefully quick question. In all the demo examples, the navigation bar has buttons for incremental +/- zoom in the X/Y directions, but no way to directly choose a rectange within the figure window to zoom to like in matlab. It gets very tedious the way it is if a lot of zooming and panning is involved. I found that I could draw a rectange in the axes and update its coordinates on an motion_notify_event. The problem is I do not know how to link the event.get_pointer() coordinates to the coordinates within the axes. Therefore I cannot set the coordinates of the rectangle correctly. The following code which is slightly modified from embed_gtk2.py demonstrates what I am trying to do... Thanks, -- Srinath from matplotlib.numerix import arange, sin, cos, pi import matplotlib matplotlib.use('GTK') from matplotlib.backends.backend_gtk import FigureCanvasGTK from matplotlib.axes import Subplot from matplotlib.figure import Figure import gtk class MyApp: def __init__(self): self.win = gtk.Window() self.win.set_name("Embedding in GTK") self.win.connect("destroy", gtk.mainquit) self.win.set_border_width(5) self.vbox = gtk.VBox(spacing=3) self.win.add(self.vbox) self.vbox.show() self.fig = Figure(figsize=(5,4), dpi=100) self.ax = Subplot(self.fig, 111) self.recth = 0.2 self.ylast = 0 x = [0,0.5,0.5,0,0] y = [0,0,self.recth,self.recth,0] t = [0,1] r = [0,1] self.h = self.ax.plot(x,y,t,r) self.fig.add_axis(self.ax) self.canvas = FigureCanvasGTK(self.fig) # a gtk.DrawingArea self.canvas.show() self.canvas.connect('motion_notify_event', self.findClick) self.vbox.pack_start(self.canvas) self.win.show() def findClick(self, widget, event): ynow = event.get_coords()[1] if ynow < self.ylast: self.recth += 0.01 elif ynow > self.ylast: self.recth -= 0.01 self.h[0].set_ydata([0,0,self.recth,self.recth,0]) self.ylast = ynow self.canvas.draw() if __name__=='__main__': app = MyApp() gtk.mainloop() |
From: John H. <jdh...@ac...> - 2004-04-16 22:21:49
|
>>>>> "Srinath" == Srinath Avadhanula <sr...@fa...> writes: Srinath> Hello all! I just recently downloaded Matplotlib and Srinath> love it so far :) Thanks! Srinath> A hopefully quick question. In all the demo examples, the Srinath> navigation bar has buttons for incremental +/- zoom in Srinath> the X/Y directions, but no way to directly choose a Srinath> rectange within the figure window to zoom to like in Srinath> matlab. It gets very tedious the way it is if a lot of Srinath> zooming and panning is involved. Srinath> I found that I could draw a rectange in the axes and Srinath> update its coordinates on an motion_notify_event. The Srinath> problem is I do not know how to link the Srinath> event.get_pointer() coordinates to the coordinates within Srinath> the axes. Therefore I cannot set the coordinates of the Srinath> rectangle correctly. The following code which is slightly Srinath> modified from embed_gtk2.py demonstrates what I am trying Srinath> to do... Yes, this would be a very nive feature. When you implement it, please send it back to the list. Here is an example that shows you how to connect to the events and more importantly for you, convert to user coords """ An example of how to interact with the plotting canvas by connecting to move and click events """ from matplotlib.matlab import * t = arange(0.0, 1.0, 0.01) s = sin(2*pi*t) ax = subplot(111) ax.plot(t,s) canvas = get_current_fig_manager().canvas def on_move(widget, event): # get the x and y coords, flip y from top to bottom height = canvas.figure.bbox.y.interval() x, y = event.x, height-event.y if ax.in_axes(x, y): # transData transforms data coords to display coords. Use the # inverse method to transform back t = ax.xaxis.transData.inverse_positions(x) val = ax.yaxis.transData.inverse_positions(y) print t, val def on_click(widget, event): # get the x and y coords, flip y from top to bottom height = canvas.figure.bbox.y.interval() x, y = event.x, height-event.y if event.button==1: if ax.in_axes(x, y): # transData transforms data coords to display coords. Use the # inverse method to transform back t = ax.xaxis.transData.inverse_positions(x) val = ax.yaxis.transData.inverse_positions(y) print t, val #canvas.connect('motion_notify_event', on_move) canvas.connect('button_press_event', on_click) show() |
From: Srinath A. <sr...@fa...> - 2004-04-17 08:22:22
|
On Fri, 16 Apr 2004, John Hunter wrote: > Yes, this would be a very nive feature. When you implement it, please > send it back to the list. Here is an example that shows you how to > connect to the events and more importantly for you, convert to user > coords > Here's a very preliminary implementation. Its not really very elegant, but it seems to work. A couple of questions. Is there a remove_line or equivalent for axes? As of now, I make the rectangle which shows the zoom window dissapear by setting its xdata and ydata to [], but it might be elegant to just remove the line from the axis completely. Also I seem to trigger a matplotlib bug if I toggle the zoom button and then start the button press event outside the axes. I have yet to delve into the matplotlib source itself and maybe I am not the best person to do it. The best place to add this would be to extend the axes class with a .zoom() method which would work like the ZoomButtonPressed() function below (It basically makes the next button press trigger the ZoomStart() function which in turn calls ZoomContinue() on the "motion_notify_event"). ZoomStart() will have to be modified to account for more than one axes belonging to a figure. We'll have to check whether the user presses the mouse in the axes whos .zoom() function has been called. Thanks again for all the help :) I think I am almost ready to get things working with matplotlib. -- Srinath from matplotlib.numerix import arange, sin, cos, pi import matplotlib matplotlib.use('GTK') from matplotlib.backends.backend_gtk import FigureCanvasGTK from matplotlib.axes import Subplot from matplotlib.figure import Figure import gtk class MyApp: def __init__(self): self.win = gtk.Window() self.win.set_name("Embedding in GTK") self.win.connect("destroy", gtk.mainquit) self.win.set_border_width(5) self.vbox = gtk.VBox(spacing=3) self.win.add(self.vbox) self.vbox.show() self.fig = Figure(figsize=(5,4), dpi=100) self.ax = Subplot(self.fig, 111) self.ax.plot([0,1], [0,1]) self.fig.add_axis(self.ax) self.canvas = FigureCanvasGTK(self.fig) # a gtk.DrawingArea self.canvas.show() self.canvas.connect('motion_notify_event', self.setAxisCursorLocation) self.vbox.pack_start(self.canvas) buttonZoom = gtk.ToggleButton('Toggle Zoom') buttonZoom.connect('button_press_event', self.ZoomButtonPressed) buttonZoom.show() self.vbox.pack_start(buttonZoom) self.win.show() def setAxisCursorLocation(self, widget, event): height = self.canvas.figure.bbox.y.interval() x, y = event.x, height-event.y t = self.ax.xaxis.transData.inverse_positions(x) val = self.ax.yaxis.transData.inverse_positions(y) self.cursorLocation = (t, val) def getAxisCursorLocation(self): if not hasattr(self, 'cursorLocation'): return None return self.cursorLocation def ZoomButtonPressed(self, widget, event): if not widget.get_active(): self.zoomStartEventHandle = self.canvas.connect('button_press_event', self.ZoomStart) else: if hasattr(self, 'zoomStartEventHandle'): self.canvas.disconnect(self.zoomStartEventHandle) def ZoomStart(self, widget, event): self.zoomStartPosition = self.getAxisCursorLocation() x, y = self.zoomStartPosition if hasattr(self, 'zoomRectangle'): self.zoomRectangle.set_xdata([x,x,x,x,x]) self.zoomRectangle.set_ydata([y,y,y,y,y]) else: self.zoomRectangle = self.ax.plot([x,x,x,x,x], [y,y,y,y,y], 'k:')[0] self.zoomContinueEventHandle = self.canvas.connect_after('motion_notify_event', self.ZoomContinue) self.zoomStopEventHandle = self.canvas.connect('button_release_event', self.ZoomStop) def ZoomContinue(self, widget, event): xs, ys = self.zoomStartPosition x, y = self.getAxisCursorLocation() self.zoomRectangle.set_xdata([xs, x, x, xs, xs]) self.zoomRectangle.set_ydata([ys, ys, y, y, ys]) self.canvas.draw() def ZoomStop(self, widget, event): self.canvas.disconnect(self.zoomContinueEventHandle) self.canvas.disconnect(self.zoomStopEventHandle) self.zoomRectangle.set_xdata([]) self.zoomRectangle.set_ydata([]) xs, ys = self.zoomStartPosition x, y = self.getAxisCursorLocation() self.ax.set_xlim([min([xs,x]), max([xs,x])]) self.ax.set_ylim([min([ys,y]), max([ys,y])]) self.canvas.draw() if __name__=='__main__': app = MyApp() gtk.mainloop() |