Matplotlib 简明教程
Matplotlib - Viewlims
Viewlims 或 View limits 引用沿 x 和 y 坐标轴在一个图中显示的数据范围。Viewlims 对于交互式数据可视化非常有用,因为它们允许用户动态调整数据显示。
Matplotlib 提供了多种方法和工具,用于交互式设置和更新 viewlims,使用户能够有效地探索和分析数据。通常,视图限制会根据在 matplotlib 图中绘制的数据自动确定。
本教程将逐步实现使用 viewlims 在 Matplotlib 图中创建交互式缩放功能,以创建对应于用户交互的动态可视化。
Creating an Interactive Zoom Plot
创建一个类,在我们放大时重新生成一个分形集合(曼德尔布罗特集合是数学中一个著名的分形),从而使我们能够观察到越来越多的细节。此外,我们将在左面板中显示一个框,以显示我们缩放到的区域。
此类定义 compute_image 方法来根据提供的边界计算曼德尔布罗特集合。并且 axes_update 方法根据当前的视图限制更新图。它确保在视图限制改变时重新计算曼德尔布罗特集合并重新绘制。
class InteractiveFractal:
def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
self.height = h
self.width = w
self.niter = niter
self.radius = radius
self.power = power
def compute_image(self, xstart, xend, ystart, yend):
self.x = np.linspace(xstart, xend, self.width)
self.y = np.linspace(ystart, yend, self.height).reshape(-1, 1)
c = self.x + 1.0j * self.y
threshold_time = np.zeros((self.height, self.width))
z = np.zeros(threshold_time.shape, dtype=complex)
mask = np.ones(threshold_time.shape, dtype=bool)
for i in range(self.niter):
z[mask] = z[mask]**self.power + c[mask]
mask = (np.abs(z) < self.radius)
threshold_time += mask
return threshold_time
def axes_update(self, ax):
ax.set_autoscale_on(False)
self.width, self.height = \
np.round(ax.patch.get_window_extent().size).astype(int)
vl = ax.viewLim
extent = vl.x0, vl.x1, vl.y0, vl.y1
im = ax.images[-1]
im.set_data(self.compute_image(*extent))
im.set_extent(extent)
ax.figure.canvas.draw_idle()
Updating View Limits
我们创建一个类 UpdateRectangle 来创建一个矩形,它表示我们在曼德尔布罗特集中放大到的区域。此类扩展 Rectangle 类,用于在视图限制更改时更新表示缩放区域的矩形。当我们在左面板中放大时,矩形将根据坐标轴的边界更新其形状。
class UpdateRectangle(Rectangle):
def __call__(self, ax):
self.set_bounds(*ax.viewLim.bounds)
ax.figure.canvas.draw_idle()
Connecting Callbacks
回调连接到第二个子图 (ax2) 的 xlim_changed 和 ylim_changed 事件。这些回调在视图限制改变时触发矩形和曼德尔布罗特集合的更新。
# Connect for changing the view limits
ax2.callbacks.connect('xlim_changed', rect)
ax2.callbacks.connect('ylim_changed', rect)
ax2.callbacks.connect('xlim_changed', md.ax_update)
ax2.callbacks.connect('ylim_changed', md.ax_update)
Here is the complete code
曼德尔布罗特集合最初绘制在两个子图 (ax1 和 ax2) 中。表示缩放区域的矩形被添加到 ax1,并且回调连接到 ax2 以处理视图限制更改。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
class UpdateRectangle(Rectangle):
def __call__(self, ax):
self.set_bounds(*ax.viewLim.bounds)
ax.figure.canvas.draw_idle()
class InteractiveFractal:
def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
self.height = h
self.width = w
self.niter = niter
self.radius = radius
self.power = power
def compute_image(self, xstart, xend, ystart, yend):
self.x = np.linspace(xstart, xend, self.width)
self.y = np.linspace(ystart, yend, self.height).reshape(-1, 1)
c = self.x + 1.0j * self.y
threshold_time = np.zeros((self.height, self.width))
z = np.zeros(threshold_time.shape, dtype=complex)
mask = np.ones(threshold_time.shape, dtype=bool)
for i in range(self.niter):
z[mask] = z[mask]**self.power + c[mask]
mask = (np.abs(z) < self.radius)
threshold_time += mask
return threshold_time
def axes_update(self, ax):
ax.set_autoscale_on(False)
self.width, self.height = \
np.round(ax.patch.get_window_extent().size).astype(int)
vl = ax.viewLim
extent = vl.x0, vl.x1, vl.y0, vl.y1
im = ax.images[-1]
im.set_data(self.compute_image(*extent))
im.set_extent(extent)
ax.figure.canvas.draw_idle()
md = InteractiveFractal()
Z = md.compute_image(-2., 0.5, -1.25, 1.25)
fig1, (ax1, ax2) = plt.subplots(1, 2, figsize=(7, 4))
ax1.imshow(Z, origin='lower',
extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))
ax2.imshow(Z, origin='lower',
extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))
rect = UpdateRectangle(
[0, 0], 0, 0, facecolor='none', edgecolor='black', linewidth=1.0)
rect.set_bounds(*ax2.viewLim.bounds)
ax1.add_patch(rect)
# Connect for changing the view limits
ax2.callbacks.connect('xlim_changed', rect)
ax2.callbacks.connect('ylim_changed', rect)
ax2.callbacks.connect('xlim_changed', md.axes_update)
ax2.callbacks.connect('ylim_changed', md.axes_update)
ax2.set_title("Zoom here")
plt.show()
在执行上述程序后,你将获得以下输出 -