Matplotlib 简明教程
Matplotlib - Viewlims
Viewlims 或 View limits 引用沿 x 和 y 坐标轴在一个图中显示的数据范围。Viewlims 对于交互式数据可视化非常有用,因为它们允许用户动态调整数据显示。
Viewlims or View limits, refer to the range of data that is displayed within a plot along the x and y axes. Viewlims are useful for interactive data visualization because they allow users to dynamically adjust the display of data.
Matplotlib 提供了多种方法和工具,用于交互式设置和更新 viewlims,使用户能够有效地探索和分析数据。通常,视图限制会根据在 matplotlib 图中绘制的数据自动确定。
Matplotlib provides various methods and tools for setting and updating viewlims interactively, enabling users to explore and analyze data effectively. In general, view limits are automatically determined based on the data being plotted in matplotlib plots.
本教程将逐步实现使用 viewlims 在 Matplotlib 图中创建交互式缩放功能,以创建对应于用户交互的动态可视化。
This tutorial will see step by setp implementation of creating interactive zoom functionality in a Matplotlib plot with viewlims to create dynamic visualizations coresponding to the user interactions.
Creating an Interactive Zoom Plot
创建一个类,在我们放大时重新生成一个分形集合(曼德尔布罗特集合是数学中一个著名的分形),从而使我们能够观察到越来越多的细节。此外,我们将在左面板中显示一个框,以显示我们缩放到的区域。
Create a class that regenerates a fractal set (the Mandelbrot set is a famous fractal in mathematics) as we zoom in, allowing us to observe increasing detail. Additionally, we’ll display a box in the left panel to show the area to which we are zoomed.
此类定义 compute_image 方法来根据提供的边界计算曼德尔布罗特集合。并且 axes_update 方法根据当前的视图限制更新图。它确保在视图限制改变时重新计算曼德尔布罗特集合并重新绘制。
This class defines the compute_image method to calculate the Mandelbrot set based on the provided bounds. And the axes_update method updates the plot based on the current view limits. It ensures that the Mandelbrot set is recalculated and redrawn whenever the view limits change.
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 类,用于在视图限制更改时更新表示缩放区域的矩形。当我们在左面板中放大时,矩形将根据坐标轴的边界更新其形状。
We’ll create a class UpdateRectangle to create a rectangle that represents the area to which we are zoomed in the Mandelbrot set. This class extends the Rectangle class and is used to update the rectangle representing the zoom area as the view limits change. As we zoom in on the left panel, the rectangle will update its shape to match the bounds of the axes.
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 事件。这些回调在视图限制改变时触发矩形和曼德尔布罗特集合的更新。
Callbacks are connected to the xlim_changed and ylim_changed events of the second subplot (ax2). These callbacks trigger the update of the rectangle and the Mandelbrot set whenever the view limits change.
# 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 以处理视图限制更改。
The Mandelbrot set is initially plotted in two subplots (ax1 and ax2). The rectangle representing the zoom area is added to ax1, and callbacks are connected to ax2 to handle view limit changes.
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()
在执行上述程序后,你将获得以下输出 -
On executing the above program you will get the following output −