Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
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.
