The RectangleSelector widget in Matplotlib allows you to interactively select rectangular regions within a plot.
This tool is particularly useful for selecting specific regions in scatter plots, zooming into certain areas, or analyzing specific data subsets.
In this tutorial, we’ll cover how to create and use the RectangleSelector widget in Matplotlib, with examples demonstrating different applications, including highlighting, zooming, and data selection.
1. Basic Setup for the Rectangle Selector
The RectangleSelector widget allows you to draw a rectangle on a plot and then returns the coordinates of the selected region. You need to define a callback function that handles the selection event.
Basic Structure of RectangleSelector
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import RectangleSelector # Sample data for a scatter plot x = np.random.rand(100) * 10 y = np.random.rand(100) * 10 # Create a scatter plot fig, ax = plt.subplots() ax.scatter(x, y) plt.xlabel("X-axis") plt.ylabel("Y-axis") # Callback function to handle the selection def onselect(eclick, erelease): print(f"Rectangle selected from ({eclick.xdata:.2f}, {eclick.ydata:.2f}) to ({erelease.xdata:.2f}, {erelease.ydata:.2f})") # Create the RectangleSelector object rectangle_selector = RectangleSelector(ax, onselect, drawtype='box', useblit=True, button=[1]) plt.show()
In this example:
- RectangleSelector is created with onselect as the callback function. This function is triggered when the selection is complete.
- eclick and erelease provide the coordinates where the selection starts and ends.
- drawtype='box' indicates the appearance of the selection outline while drawing.
- button=[1] specifies that the left mouse button is used for selection.
2. Highlighting Selected Points within the Rectangle
Let’s enhance the previous example by highlighting the points that fall within the rectangular selection.
# Create scatter plot with initial data fig, ax = plt.subplots() sc = ax.scatter(x, y) highlight, = ax.plot([], [], 'ro') # Red markers to highlight selected points # Callback function to handle the selection def onselect(eclick, erelease): # Get rectangle bounds x_min, x_max = sorted([eclick.xdata, erelease.xdata]) y_min, y_max = sorted([eclick.ydata, erelease.ydata]) # Find points within the rectangle selected_x, selected_y = [], [] for xi, yi in zip(x, y): if x_min <= xi <= x_max and y_min <= yi <= y_max: selected_x.append(xi) selected_y.append(yi) # Update highlight points highlight.set_data(selected_x, selected_y) plt.draw() # Create the RectangleSelector rectangle_selector = RectangleSelector(ax, onselect, drawtype='box', useblit=True, button=[1]) plt.xlabel("X-axis") plt.ylabel("Y-axis") plt.show()
In this example:
- The selection rectangle's bounds are used to filter points inside the selection.
- Points within the selected rectangular region are highlighted in red.
3. Customizing the Rectangle Selector Appearance
The RectangleSelector’s appearance can be customized using parameters like line color, style, and transparency.
# Create scatter plot fig, ax = plt.subplots() ax.scatter(x, y) # Callback function for selection def onselect(eclick, erelease): x_min, x_max = sorted([eclick.xdata, erelease.xdata]) y_min, y_max = sorted([eclick.ydata, erelease.ydata]) print(f"Selected area from ({x_min:.2f}, {y_min:.2f}) to ({x_max:.2f}, {y_max:.2f})") # Customize RectangleSelector properties rectangle_selector = RectangleSelector( ax, onselect, drawtype='box', useblit=True, button=[1], lineprops=dict(color='purple', linestyle='--', linewidth=2, alpha=0.5), rectprops=dict(facecolor='yellow', edgecolor='purple', alpha=0.3, fill=True) ) plt.xlabel("X-axis") plt.ylabel("Y-axis") plt.show()
In this example:
- lineprops and rectprops customize the outline and fill properties.
- lineprops=dict(color='purple', linestyle='–‘, linewidth=2, alpha=0.5) makes the selection outline purple with a dashed style.
- rectprops=dict(facecolor='yellow', edgecolor='purple', alpha=0.3, fill=True) adds a semi-transparent yellow fill.
4. Zooming into the Selected Region
The RectangleSelector can be used to zoom into the selected area by setting the x and y limits of the plot to the selection bounds.
# Create scatter plot fig, ax = plt.subplots() ax.scatter(x, y) plt.xlabel("X-axis") plt.ylabel("Y-axis") # Zoom function based on selection def zoom_onselect(eclick, erelease): x_min, x_max = sorted([eclick.xdata, erelease.xdata]) y_min, y_max = sorted([eclick.ydata, erelease.ydata]) ax.set_xlim(x_min, x_max) ax.set_ylim(y_min, y_max) plt.draw() # RectangleSelector for zooming rectangle_selector = RectangleSelector(ax, zoom_onselect, drawtype='box', useblit=True, button=[1]) plt.show()
In this example:
- zoom_onselect sets the x and y limits of the plot to match the selected area, effectively zooming into that region.
- plt.draw() immediately refreshes the plot after adjusting the limits.
5. Using Rectangle Selector with Images
RectangleSelector can also be used on images to select and highlight rectangular regions.
import matplotlib.image as mpimg # Load an example image image = mpimg.imread('https://matplotlib.org/stable/_images/stinkbug.png') # Create plot with image fig, ax = plt.subplots() ax.imshow(image) # Function to highlight the selected region def onselect(eclick, erelease): x_min, x_max = sorted([eclick.xdata, erelease.xdata]) y_min, y_max = sorted([eclick.ydata, erelease.ydata]) # Draw a rectangle on the selected region rect = plt.Rectangle((x_min, y_min), x_max - x_min, y_max - y_min, edgecolor='cyan', facecolor='none', linewidth=2) # Remove previous rectangles and add new for artist in ax.findobj(lambda obj: isinstance(obj, plt.Rectangle)): artist.remove() ax.add_patch(rect) plt.draw() # RectangleSelector for image region selection rectangle_selector = RectangleSelector(ax, onselect, drawtype='box', useblit=True, button=[1]) plt.show()
In this example:
- ax.imshow(image) displays an image.
- A Rectangle patch is drawn to highlight the selected area within the image.
6. Advanced Rectangle Selector with Keyboard Controls
You can add keyboard controls to clear the selection or disable the selector, enhancing the interactivity of the RectangleSelector.
# Create scatter plot fig, ax = plt.subplots() ax.scatter(x, y) plt.xlabel("X-axis") plt.ylabel("Y-axis") # Selection function def onselect(eclick, erelease): x_min, x_max = sorted([eclick.xdata, erelease.xdata]) y_min, y_max = sorted([eclick.ydata, erelease.ydata]) print(f"Selected area from ({x_min:.2f}, {y_min:.2f}) to ({x_max:.2f}, {y_max:.2f})") # RectangleSelector with advanced functionality rectangle_selector = RectangleSelector(ax, onselect, drawtype='box', useblit=True, button=[1]) # Key event function def on_key(event): if event.key == 'c': # Clear selection for artist in ax.findobj(lambda obj: isinstance(obj, plt.Rectangle)): artist.remove() plt.draw() elif event.key == 'e': # Enable selector rectangle_selector.set_active(True) elif event.key == 'd': # Disable selector rectangle_selector.set_active(False) # Connect the key press event to the handler fig.canvas.mpl_connect('key_press_event', on_key) plt.show()
In this example:
- Pressing ‘c' clears the selection by removing all Rectangle patches.
- Pressing ‘e' enables the RectangleSelector, allowing selections to be made again if it was disabled.
- Pressing ‘d' disables the RectangleSelector, preventing further selections.
7. Rectangle Selector to Crop and Display Subplot
For image analysis, you can use RectangleSelector to crop and display the selected area in a subplot.
# Load an example image image = mpimg.imread('https://matplotlib.org/stable/_images/stinkbug.png') # Create main plot with image and an empty subplot for the cropped area fig, (ax_main, ax_crop) = plt.subplots(1, 2, figsize=(10, 5)) ax_main.imshow(image) ax_main.set_title("Original Image") ax _crop.set_title("Cropped Region") # Function to crop and display the selected region def onselect(eclick, erelease): x_min, x_max = int(sorted([eclick.xdata, erelease.xdata])[0]), int(sorted([eclick.xdata, erelease.xdata])[1]) y_min, y_max = int(sorted([eclick.ydata, erelease.ydata])[0]), int(sorted([eclick.ydata, erelease.ydata])[1]) # Extract and display the cropped region cropped_image = image[y_min:y_max, x_min:x_max] ax_crop.clear() ax_crop.imshow(cropped_image) ax_crop.set_title("Cropped Region") plt.draw() # RectangleSelector for cropping rectangle_selector = RectangleSelector(ax_main, onselect, drawtype='box', useblit=True, button=[1]) plt.show()
In this example:
- When a rectangular region is selected on the main image, the onselect function crops that region and displays it in a second subplot.
- This approach is useful for analyzing selected parts of an image in detail.
Summary
This tutorial covered several ways to use the RectangleSelector widget in Matplotlib:
- Basic Rectangle Selector with a callback function.
- Highlighting selected points within the rectangle.
- Customizing the appearance of the rectangle selector.
- Zooming into a selected region by adjusting plot limits.
- Using Rectangle Selector with Images to select and highlight regions.
- Advanced keyboard controls to clear, enable, or disable the selector.
- Cropping and displaying a selected region in a subplot.