How to add a cursor to a curve in Matplotlib?

Adding a cursor to a curve in Matplotlib allows users to interactively explore data points by hovering over the plot. This is achieved by creating a custom cursor class that responds to mouse events and updates visual elements in real-time.

Creating the Cursor Class

First, we need to create a cursor class that handles the visual elements and mouse interactions ?

import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["figure.figsize"] = [7.50, 3.50]
plt.rcParams["figure.autolayout"] = True

class CursorClass(object):
    def __init__(self, ax, x, y):
        self.ax = ax
        self.ly = ax.axvline(color='yellow', alpha=0.5)  # Vertical line
        self.marker, = ax.plot([0], [0], marker="o", color="red", zorder=3)  # Point marker
        self.x = x
        self.y = y
        self.txt = ax.text(0.7, 0.9, '')  # Text display
    
    def mouse_event(self, event):
        if event.inaxes:
            x, y = event.xdata, event.ydata
            indx = np.searchsorted(self.x, [x])[0]
            x = self.x[indx]
            y = self.y[indx]
            self.ly.set_xdata(x)
            self.marker.set_data([x], [y])
            self.txt.set_text('x=%1.2f, y=%1.2f' % (x, y))
            self.txt.set_position((x, y))
            self.ax.figure.canvas.draw_idle()

# Generate sample data
t = np.arange(0.0, 1.0, 0.01)
s = np.sin(2 * 2 * np.pi * t)

# Create plot
fig, ax = plt.subplots()

# Initialize cursor and connect mouse event
cursor = CursorClass(ax, t, s)
cid = fig.canvas.mpl_connect('motion_notify_event', cursor.mouse_event)

# Plot the curve
ax.plot(t, s, lw=2, color='green')
plt.axis([0, 1, -1, 1])

plt.show()

How It Works

The cursor implementation consists of three main components:

  • Vertical line − Shows the current x-position using axvline()
  • Point marker − Highlights the exact data point with a red circle
  • Text display − Shows the coordinates of the current point

Enhanced Cursor with Crosshairs

You can create a more sophisticated cursor with both horizontal and vertical lines ?

import matplotlib.pyplot as plt
import numpy as np

class CrosshairCursor:
    def __init__(self, ax, x, y):
        self.ax = ax
        self.x = x
        self.y = y
        
        # Create crosshair lines
        self.horizontal_line = ax.axhline(color='red', alpha=0.7, linestyle='--')
        self.vertical_line = ax.axvline(color='red', alpha=0.7, linestyle='--')
        
        # Create point marker
        self.point, = ax.plot([], [], marker='o', color='blue', markersize=8, zorder=10)
        
        # Text annotation
        self.annotation = ax.annotate('', xy=(0,0), xytext=(20,20), 
                                    textcoords="offset points",
                                    bbox=dict(boxstyle="round", fc="w"),
                                    arrowprops=dict(arrowstyle="->"))
    
    def on_mouse_move(self, event):
        if event.inaxes != self.ax:
            return
        
        # Find nearest point
        x_mouse = event.xdata
        idx = np.argmin(np.abs(self.x - x_mouse))
        x_point = self.x[idx]
        y_point = self.y[idx]
        
        # Update crosshair
        self.horizontal_line.set_ydata([y_point])
        self.vertical_line.set_xdata([x_point])
        
        # Update point
        self.point.set_data([x_point], [y_point])
        
        # Update annotation
        self.annotation.xy = (x_point, y_point)
        self.annotation.set_text(f'({x_point:.2f}, {y_point:.2f})')
        
        self.ax.figure.canvas.draw_idle()

# Generate data
x_data = np.linspace(0, 4*np.pi, 200)
y_data = np.sin(x_data) * np.exp(-x_data/10)

# Create plot
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x_data, y_data, 'b-', linewidth=2, label='sin(x)·e^(-x/10)')

# Add cursor
cursor = CrosshairCursor(ax, x_data, y_data)
fig.canvas.mpl_connect('motion_notify_event', cursor.on_mouse_move)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Interactive Crosshair Cursor')
ax.legend()
ax.grid(True, alpha=0.3)

plt.show()

Key Features

Component Purpose Method
Vertical Line Shows x-position axvline()
Point Marker Highlights data point plot() with marker
Text Display Shows coordinates text() or annotate()
Mouse Event Detects movement motion_notify_event

Conclusion

Interactive cursors enhance data exploration by providing real-time coordinate feedback. Use axvline() for simple vertical cursors or combine with axhline() for crosshair effects. Connect mouse events using mpl_connect() for responsive interactivity.

Updated on: 2026-03-26T00:01:23+05:30

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements