简介
在数据可视化中,放大图表的特定区域对于更好地理解和分析数据非常有用。Matplotlib 是一个广受欢迎的 Python 数据可视化库,它提供了一种方法来创建两个相同的面板,并在右侧面板中放大,以在第一个面板中显示一个矩形,表示缩放区域。在本实验中,我们将学习如何在 Matplotlib 中创建此交互式缩放功能。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。
导入必要的库
我们首先将导入必要的库,包括 Matplotlib 和 NumPy。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle
创建 UpdatingRect 类
我们将创建一个名为 UpdatingRect 的 Rectangle 子类。调用这个类时会传入一个 Axes 实例,使矩形更新其形状以匹配 Axes 的边界。
class UpdatingRect(Rectangle):
def __call__(self, ax):
self.set_bounds(*ax.viewLim.bounds)
ax.figure.canvas.draw_idle()
创建 MandelbrotDisplay 类
我们将创建一个名为 MandelbrotDisplay 的类,它会在我们放大时重新生成一个分形集,以便我们能够实际看到不断增加的细节。左侧面板中的一个框将显示我们所放大的区域。
class MandelbrotDisplay:
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 ax_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()
创建图表
我们将通过以下步骤创建图表:首先使用 MandelbrotDisplay 类计算图像,然后使用 subplots 创建两个相同的面板。我们将使用 imshow 把图像添加到两个面板中,并将 UpdatingRect 对象添加到左侧面板。
md = MandelbrotDisplay()
Z = md.compute_image(-2., 0.5, -1.25, 1.25)
fig1, (ax1, ax2) = plt.subplots(1, 2)
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 = UpdatingRect(
[0, 0], 0, 0, facecolor='none', edgecolor='black', linewidth=1.0)
rect.set_bounds(*ax2.viewLim.bounds)
ax1.add_patch(rect)
添加缩放功能
我们将通过把 xlim_changed 和 ylim_changed 事件连接到 UpdatingRect 和 MandelbrotDisplay 对象来添加缩放功能。
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)
ax2.set_title("Zoom here")
显示图表
我们将使用 show() 函数来显示图表。
plt.show()
总结
在本实验中,我们学习了如何使用两个相同的面板以及 UpdatingRect 和 MandelbrotDisplay 类在 Matplotlib 中创建交互式缩放功能。通过添加缩放功能,我们能够更好地理解和分析图表中的数据。