Hi,

I wanted to be able to select a rectangular region from the graph as one part of a script so I combined BlockingInput and RectangleSelector to create BlockingRectangleSelector, and the pylab style interface function, ginput_rect

This serves my immediate needs and I'm unlikely to develop it further.

Before adding it to matplotlib a couple of changes are needed::

* Other kinds of selectors, such as span, line and lasso should be possible

* Selectors such as RectangularSelector can be added to a set of axes but not removed. Removing them requires unhooking the mpl_connect callbacks, but the cid is not being saved.

* The graph wasn't always drawn before selection in ipython or before a subsequent show() so I forced it with explicit draw_idle() calls. This may lead to unnecessary redraws.

- Paul

# This program is public domain
# Author: Paul Kienzle
"""
Select a region of the graph.

ginput_rect(ax) selects a region from the axes and continues the script.

s = BlockingRectangleSelector(ax) adds a rectangle selector to the axes and
lets the script call s.select() whenever a new region is needed.

demo() shows the selector in action.
"""
from matplotlib.pyplot import gca
from matplotlib.widgets import RectangleSelector
from matplotlib.blocking_input import BlockingInput

class BlockingRectangleSelector:
    """
    Blocking rectangle selector selects once then continues with script.
    """
    def __init__(self, ax=None):
        if ax is None: ax=gca()
        self.ax = ax

        # drawtype is 'box' or 'line' or 'none'
        self.selector = RectangleSelector(self.ax, self._callback,
                               drawtype='box',useblit=True,
                               minspanx=5,minspany=5,spancoords='pixels')
        self.selector.set_active(False)
        self.block = BlockingInput(self.ax.figure)

    def _callback(self, event1, event2):
        """
        Selection callback.  event1 and event2 are the press and release events
        """
        x1, y1 = event1.xdata, event1.ydata
        x2, y2 = event2.xdata, event2.ydata
        if x1>x2: x1,x2 = x2,x1
        if y1>y2: y1,y2 = y2,y1
        self.x1,self.x2,self.y1,self.y2 = x1,x2,y1,y2
        self.ax.figure.canvas.stop_event_loop()

    def select(self):
        """
        Wait for box to be selected on the axes.
        """

        # Make sure the graph is drawn before select.
        # This appears to be needed for ipython.
        self.ax.figure.canvas.draw_idle()

        # Wait for selector to complete
        self.selector.set_active(True)
        self.block()
        self.selector.set_active(False)

        # Force redraw, otherwise next show() doesn't
        # update the graph.
        #self.ax.figure.canvas.draw_idle()

    def remove(self):
        """
        Remove the selector from the axes.

        Note: this currently does nothing since matplotlib doesn't allow
        widgets to be removed from axes.
        """
        pass  # rectangle widget can't be removed from axes

def ginput_rect(ax=None):
    """
    Wait for user to select a region on the axes.
    
    Returns x1,x2,y1,y2
    """
    s = BlockingRectangleSelector(ax=ax)
    s.select()
    s.remove()
    return s.x1,s.x2,s.y1,s.y2

def demo():
    # Example comes from matplotlib/examples/rectangle_selector.py
    from numpy import arange, sin, cos, pi
    from pylab import subplot, plot, axis, show

    subplot(111)
    # If N is large one can see improvement by blitting!
    N=100000                                   
    x=10.0*arange(N)/(N-1)

    plot(x,sin(.2*pi*x),lw=3,c='b',alpha=.7)
    plot(x,cos(.2*pi*x),lw=3.5,c='r',alpha=.5)
    plot(x,-sin(.2*pi*x),lw=3.5,c='g',alpha=.3)
    print "\n      click  -->  release"

    x1,x2,y1,y2 = ginput_rect()
    print "(%3.2f, %3.2f) --> (%3.2f, %3.2f)"%(x1,y1,x2,y2)

    # Zoom in to the selected rectangle
    axis([x1, x2, y1, y2])
    show()
    

if __name__ == "__main__":
    demo()



------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay 
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to