Python - 带控制滑块的 3D 渐变绘图动画

Python - 3D gradient plot animation with control slider

我正在阅读以下文章 。它以 3D 形式显示动画。

我正在考虑以下情况:

  1. 我有一个 x-y 网格,[1,2,...,20] X [1,2,...,20]
  2. 为每个点分配一个 z 值。
  3. 根据1.和2.,我画出3维梯度图如下

假设我有 5 个 20X20 的 z 值数据 (.xlsx)。因此,我得到了 5 个不同的图表。

现在,我想在一张图中绘制所有 5 个图,但使用 滑块 这样当我将滑块从 1 移动到 5 时,我可以得到一个动画(变化) 的图表,但在同一个网格中。

这里只提供一张图(一个数据)的代码

fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
rm = pd.read_excel("test_3d.xlsx", header = None)
rec = np.shape(rm)
X = np.arange(1,rec[1]+1,1)
Y = np.arange(1,rec[0]+1,1)
x , y = np.meshgrid(X,Y)
# Plot the surface.

surf = ax.plot_surface(x, y, rm, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)

# Customize the z axis.
ax.set_zlim(-110, -80)
ax.zaxis.set_major_locator(LinearLocator(10))
# A StrMethodFormatter is used automatically
ax.zaxis.set_major_formatter('{x:.02f}')

# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()

如何修改代码得到我想要的?请提示。谢谢!

如果您创建一个 animation,情节将不会是交互式的:动画将重复,并且在每一帧中都会显示不同的表面,但您将无法与之互动。既然你提到了一个滑块,我想你想要一个交互式绘图,它会在用户更改滑块的值后更新。这与动画有很大不同。
在这里,我将介绍如何设置交互式滑块。
您应该为 3D 图创建一个轴,为滑块创建另一个轴:

ax1 = fig.add_axes([0, 0, 1, 0.8], projection = '3d')  # <-- 3D plot axis
ax2 = fig.add_axes([0.1, 0.85, 0.8, 0.1])              # <-- slider axis

然后您可以将 slider 装箱并放置在适当的轴中:

s = Slider(ax = ax2, label = 'value', valmin = 0, valmax = 5, valinit = 2)

此时有必要定义一个函数,当用户更改滑块的值时将调用该函数。在函数内部读取滑块的实际值,然后擦除之前的绘图,最后绘制新绘图。在更新函数中固定 x, y, z 轴的限制很方便,因此绘图的框架将保持不变,只有表面会发生变化。
在下面的例子中,我假设滑块中定义的值在表面上下移动,所以在 plot_surface 中我添加 z + value;您必须根据您的需要进行调整 (*)。

def update(val):
    value = s.val
    ax1.cla()
    ax1.plot_surface(x, y, z + value, cmap = cm.coolwarm, linewidth = 0, antialiased = False)
    ax1.set_zlim(-2, 7)

最后你需要link滑块到更新功能:

s.on_changed(update)

这一段不是必须的,但我建议在plt.show()之前调用update函数;这样,matplotlib 将显示的初始图将已经与滑块中表示的初始值一致。

完整代码

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.widgets import Slider

N = 100

X = np.linspace(0, 20, N)
Y = np.linspace(0, 20, N)
x, y = np.meshgrid(X, Y)
z = np.sin(x) + np.sin(y)


fig = plt.figure()

ax1 = fig.add_axes([0, 0, 1, 0.8], projection = '3d')
ax2 = fig.add_axes([0.1, 0.85, 0.8, 0.1])

s = Slider(ax = ax2, label = 'value', valmin = 0, valmax = 5, valinit = 2)

def update(val):
    value = s.val
    ax1.cla()
    ax1.plot_surface(x, y, z + value, cmap = cm.coolwarm, linewidth = 0, antialiased = False)
    ax1.set_zlim(-2, 7)

s.on_changed(update)
update(0)

plt.show()

(*) 您提到:

Suppose I have 5 20X20 data for z values (.xlsx). Therefore, I get 5 different graphs as above.

所以你有 5 个不同的 .xlsx 文件,每个表面一个?在这种情况下,您必须读取这些文件并将它们绘制在 update 函数中。