【问题标题】:3D scatter animation only animates first entry in tuple, matplotlib3D 散点动画仅对元组 matplotlib 中的第一个条目进行动画处理
【发布时间】:2020-03-24 23:05:26
【问题描述】:

我正在尝试设置 3D 散点图动画,如下所示:Matplotlib 3D scatter animations

我整理了以下代码:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D

def terminal_w(r):
    """calculation of droplet terminal fallspeed"""
    w=X1*r**2
    return(w)

class drop():
    """class of a drop"""
    def __init__(self,xpos,ypos,zpos,rad):
        self.x,self.y,self.z=xpos,ypos,zpos # position
        self.r=rad     # radius 
        self.w=terminal_w(rad) # velocity  


def main():
    # dimensions of the domain
    global xsize,ysize,zsize
    global X1,X2,X3
    global dt # timestep
    global rho_l

    xsize,ysize,zsize=1.,1.,100.    # domain size in meters
    X1,X2,X3=1.2e8,8e3,250. # terminal velocity coeffs
    dt=10.0
    rho_l=1000. # density of liquid water

    #
    # Student exercise 1: change radii and liquid water amount:
    #
    liq=1.e-3 # cloud liq water content in kg/m**3    
    rsmall=5.e-6 # microns
    rlarge=20.e-6

    # L=N*rho_l*4/3 pi r^3
    ndrop=10 # total number of drops
    # initial number of large drops with rlarge
    # not used if distrbution of drop sizes assumed
    nlarge=1  

    # initial random positions:
    # could use a dictionary, but don't want to lose numpy advantage?
    dropx=np.random.uniform(low=0,high=xsize,size=ndrop)
    dropy=np.random.uniform(low=0,high=ysize,size=ndrop)
    dropz=np.random.uniform(low=0,high=zsize,size=ndrop)

    # one large drop falling through a cloud of small drops
    dropr=np.full(ndrop,fill_value=rsmall)
    dropr[-nlarge:]=rlarge

    # Student exercise 2: change distribution: 
    # can insert code here to simply set a distribution of radii:
    # set arrange from lognormal distribution, 
    # dropr=np.random.DIST(moments)

    # initial drop conditions
    drops=drop(dropx,dropy,dropz,dropr)

    # set up plot window
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    ax.set_xlim(0,xsize)
    ax.set_ylim(0,ysize)
    ax.set_zlim(0,zsize)

    sc3d=ax.scatter(drops.x,drops.y,drops.z,c='blue',marker='o')
    title = ax.set_title('3D Test')

    def animate(i):
        timestep(drops)
        print(drops.z[0])
        sc3d._offsets3d=(drops.x,drops.y,drops.z)  # update the data
        title.set_text('3D Test, time={}'.format(i))

    ani = animation.FuncAnimation(fig, animate, 
                                  interval=25, 
                                  blit=False)

    plt.show()

def timestep(drops):
    #print(drops.w)
    drops.z-=dt*drops.w
    #print(drops.z)


main()

它产生一个 3D 散点图,但只对其中一个标记进行动画处理,即使所有条目的 z 坐标都已更新(当我取消选中打印语句时)。

更奇怪的是,如果我将声明注释掉

title.set_text('3D Test, time={}'.format(i))

在动画函数中,没有滴是动画的。我不明白为什么添加标题语句允许一个标记进行动画处理,而且我看不出我的代码与对我起作用并为所有点设置动画的示例有何不同......

【问题讨论】:

  • 当前的代码动画正确。我想您被以下事实欺骗了:其中一滴比其他滴快得多
  • 我不确定 - 当我将 return 语句放入时,我看到所有的水滴都在移动,尽管小半径的水滴要慢得多。我还没有完全理解,我是第一次使用这个动画功能。

标签: python matplotlib scatter-plot scatter3d


【解决方案1】:

根据docs,您的animate 函数签名应该是def func(frame, *fargs) -> iterable_of_artists。但是,您不会返回可迭代的艺术家。你什么都没退!

编辑:为了清楚起见,您的函数签名是func(frame) -> None。哦,不要使用globals,它们是邪恶的。

【讨论】:

  • 呵呵,当然,return(sc3d) 解决了!我不明白为什么该示例可以正常工作(也没有返回),但这对我来说很重要,谢谢! :-)
  • ps:我认为全局变量对于不能/不会在实验中更改的常量是可以的?
  • 其实只有当 blit 设置为 True 时才需要返回一些东西。既然是从这里出发的,你什么都不需要退货。
猜你喜欢
  • 2021-10-21
  • 2012-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
相关资源
最近更新 更多