Matplotlib: draw a selection area in the shape of a rectangle with the mouse

matplotlib, matplotlib-basemap, mouse, python, selection

Solution

Matplotlib provides its own `RectangleSelector`. There is an example on the matplotlib page, which you may adapt to your needs.

A simplified version would look something like this:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.widgets  import RectangleSelector

xdata = np.linspace(0,9*np.pi, num=301)
ydata = np.sin(xdata)

fig, ax = plt.subplots()
line, = ax.plot(xdata, ydata)


def line_select_callback(eclick, erelease):
    x1, y1 = eclick.xdata, eclick.ydata
    x2, y2 = erelease.xdata, erelease.ydata

    rect = plt.Rectangle( (min(x1,x2),min(y1,y2)), np.abs(x1-x2), np.abs(y1-y2) )
    ax.add_patch(rect)


rs = RectangleSelector(ax, line_select_callback,
                       drawtype='box', useblit=False, button=[1], 
                       minspanx=5, minspany=5, spancoords='pixels', 
                       interactive=True)

plt.show()

Problem

I want to be able to draw a selection area on a matplotlib plot with a mouse event. I didn't find information on how to do it with python. In the end, I want to be able to draw a region of interest with my mouse on a map created with matplotlib basemap and retrieve the corner coordinates. Anyone has an idea, example, references? Thanks, Greg ``` class Annotate(object): def __init__(self): self.ax = plt.gca() self.rect = Rectangle((0,0), 1, 1, facecolor='None', edgecolor='green') self.x0 = None self.y0 = None self.x1 = None self.y1 = None self.ax.add_patch(self.rect) self.ax.figure.canvas.mpl_connect('button_press_event', self.on_press) self.ax.figure.canvas.mpl_connect('button_release_event', self.on_release) self.ax.figure.canvas.mpl_connect('motion_notify_event', self.on_motion) def on_press(self, event): print 'press' self.x0 = event.xdata self.y0 = event.ydata self.x1 = event.xdata self.y1 = event.ydata self.rect.set_width(self.x1 - self.x0) self.rect.set_height(self.y1 - self.y0) self.rect.set_xy((self.x0, self.y0)) self.rect.set_linestyle('dashed') self.ax.figure.canvas.draw() def on_motion(self,event): if self.on_press is True: return self.x1 = event.xdata self.y1 = event.ydata self.rect.set_width(self.x1 - self.x0) self.rect.set_height(self.y1 - self.y0) self.rect.set_xy((self.x0, self.y0)) self.rect.set_linestyle('dashed') self.ax.figure.canvas.draw() def on_release(self, event): print 'release' self.x1 = event.xdata self.y1 = event.ydata self.rect.set_width(self.x1 - self.x0) self.rect.set_height(self.y1 - self.y0) self.rect.set_xy((self.x0, self.y0)) self.rect.set_linestyle('solid') self.ax.figure.canvas.draw() print self.x0,self.x1,self.y0,self.y1 return [self.x0,self.x1,self.y0,self.y1] ```

Original source