The EllipseSelector widget in Matplotlib is a tool that allows you to interactively select an elliptical region within a plot.
This widget is useful for selecting and analyzing specific regions in data, especially in scatter plots, image analysis, or any scenario where you want to focus on a circular or elliptical area.
In this tutorial, we’ll cover how to create and use the EllipseSelector widget in Matplotlib, with examples showing different applications, including how to retrieve data within the selected region.
1. Basic Setup for the Ellipse Selector
The EllipseSelector widget allows you to draw an ellipse on a plot and returns the coordinates of the ellipse's bounding box. It requires defining a callback function that is triggered when the selection is completed.
Basic Structure of EllipseSelector
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import EllipseSelector # 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"Ellipse selected from ({eclick.xdata:.2f}, {eclick.ydata:.2f}) to ({erelease.xdata:.2f}, {erelease.ydata:.2f})") # Create the EllipseSelector object ellipse_selector = EllipseSelector(ax, onselect, drawtype='box', useblit=True, button=[1]) plt.show()
In this example:
- EllipseSelector is created with onselect as the callback function. This function is called when the selection is completed.
- eclick and erelease provide the coordinates where the selection starts and ends.
- drawtype='box' indicates the appearance of the selection outline during drawing.
- button=[1] specifies that the left mouse button is used for selection.
2. Highlighting Selected Points within the Ellipse
Let’s enhance the previous example by highlighting the points that fall within the ellipse after selection.
from matplotlib.patches import Ellipse # 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 # Function to handle the selection def onselect(eclick, erelease): # Calculate the center and width/height of the ellipse x_min, x_max = sorted([eclick.xdata, erelease.xdata]) y_min, y_max = sorted([eclick.ydata, erelease.ydata]) width = x_max - x_min height = y_max - y_min center = ((x_max + x_min) / 2, (y_max + y_min) / 2) # Create an Ellipse patch ellipse = Ellipse(center, width, height, edgecolor='blue', facecolor='none', linewidth=2) # Clear previous highlights and add the new ellipse to the plot for artist in ax.findobj(lambda obj: isinstance(obj, Ellipse)): artist.remove() ax.add_patch(ellipse) # Check which points fall inside the ellipse selected_x, selected_y = [], [] for xi, yi in zip(x, y): if ((xi - center[0])**2 / (width/2)**2 + (yi - center[1])**2 / (height/2)**2) <= 1: selected_x.append(xi) selected_y.append(yi) # Update the highlight points highlight.set_data(selected_x, selected_y) plt.draw() # Create the EllipseSelector ellipse_selector = EllipseSelector(ax, onselect, drawtype='box', useblit=True, button=[1]) plt.xlabel("X-axis") plt.ylabel("Y-axis") plt.show()
In this example:
- An Ellipse patch is created to visually indicate the selected area.
- Points within the selected elliptical region are calculated using the ellipse equation (x−h)2/a2+(y−k)2/b2≤1(x – h)^2 / a^2 + (y – k)^2 / b^2 \leq 1, where (h,k)(h, k) is the center, and aa and bb are half the width and height, respectively.
- Points inside the ellipse are highlighted in red.
3. Adjusting Ellipse Selector Properties
You can customize the appearance of the selection outline and other properties to make the interaction more intuitive. Here’s how you can modify the line style, color, and make the selection persistent.
# 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 EllipseSelector properties ellipse_selector = EllipseSelector( 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 are dictionaries that customize the appearance of the selection outline and background fill.
- lineprops=dict(color='purple', linestyle='–‘, linewidth=2, alpha=0.5) sets the line to purple with a dashed style and partial transparency.
- rectprops=dict(facecolor='yellow', edgecolor='purple', alpha=0.3, fill=True) provides a semi-transparent yellow fill inside the ellipse selection.
4. Using Ellipse Selector to Zoom into Selected Region
You can use the EllipseSelector to zoom into a specific region of a plot by setting the x and y limits of the plot to the bounding box of the selected ellipse.
# 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() # EllipseSelector for zooming ellipse_selector = EllipseSelector(ax, zoom_onselect, drawtype='box', useblit=True, button=[1]) plt.show()
In this example:
- The zoom_onselect function sets the x and y limits of the plot to match the bounds of the selected ellipse, effectively zooming into that region.
- plt.draw() is called to immediately refresh the plot after adjusting the limits.
5. Interactive Selection on Images with Ellipse Selector
The EllipseSelector is also useful for selecting regions in images. Here’s an example where we use it to select and highlight elliptical regions within an image.
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]) width = x_max - x_min height = y_max - y_min center = ((x_max + x_min) / 2, (y_max + y_min) / 2) # Draw ellipse on the selected region ellipse = Ellipse(center, width, height, edgecolor='cyan', facecolor='none', linewidth=2) for artist in ax.findobj(lambda obj: isinstance(obj, Ellipse)): artist.remove() ax.add_patch(ellipse) plt.draw() # EllipseSelector for image region selection ellipse_selector = EllipseSelector(ax, onselect, drawtype='box', useblit=True, button=[1]) plt.show()
In this example:
- ax.imshow(image) displays an image in the plot.
- When an elliptical region is selected, an Ellipse patch is drawn on the image to highlight the selected area.
6. Advanced Ellipse Selector with Keyboard Controls
You can further enhance the interactivity of the EllipseSelector by adding keyboard controls to clear the selection or disable the selector temporarily.
# 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})") # EllipseSelector with advanced functionality ellipse_selector = EllipseSelector(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, Ellipse)): artist.remove() plt.draw() elif event.key == 'e': # Enable selector ellipse_selector.set_active(True) elif event.key == 'd': # Disable selector ellipse_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 Ellipse patches.
- Pressing ‘e' enables the EllipseSelector, allowing selection again if it was disabled.
- Pressing ‘d' disables the EllipseSelector, preventing any new selections.
Summary
In this tutorial, we covered several ways to use the EllipseSelector widget in Matplotlib:
- Basic Ellipse Selector with a simple callback function.
- Highlighting selected points within the ellipse.
- Customizing appearance of the ellipse selection.
- Zooming into a selected region using the ellipse’s bounding box.
- Selecting regions on images with an elliptical highlight.
- Advanced keyboard controls to clear or enable/disable the selector.