【问题标题】:Python - 3D gradient plot animation with control sliderPython - 带有控制滑块的 3D 渐变绘图动画
【发布时间】:2021-10-12 08:26:42
【问题描述】:

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

我正在考虑以下场景:

  1. 我有一个 x-y 网格,[1,2,...,20] X [1,2,...,20]
  2. 为每个点分配一个 z 值。
  3. 基于 1. 和 2.,我绘制了 3-D 梯度图,如下所示

假设我有 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()

如何修改代码以获得我想要的?请给个提示。谢谢!

【问题讨论】:

    标签: python matplotlib animation plot 3d


    【解决方案1】:

    如果您创建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)
    

    最后你需要将滑块链接到更新功能:

    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()
    

    (*) 你提到过:

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

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

    【讨论】:

      猜你喜欢
      • 2021-10-10
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      • 2016-05-10
      • 2011-02-25
      • 1970-01-01
      • 2012-07-12
      • 1970-01-01
      相关资源
      最近更新 更多