首页 > 解决方案 > 如何在 matplotlib FuncAnimation 中有效地叠加散点图?

问题描述

我目前正在尝试制作一部显示散点图的电影,这些散点图叠加了从一系列图像派生的两个产品(如果相关,大约有 1000 张图像,其中每张图像都有 471x949 像素)。

对于FuncAnimation数组的每次交互,过滤以选择通常会在此类图中看到的最大值,并生成它们之间的散点图。这些像素中大约有 40k-50k 通常满足这个条件。

我们的想法是为每个交互绘制这些散点图,以显示这些点将如何随着时间的推移而分布。

虽然代码有效,但每次交互之间的时间正在增加,编译一部电影需要几个小时,我不知道如何优化这段代码以使其在合理的时间内制作一部电影。

代码如下:

def anim_scatter(harpnum):
    '''
    Description
    '''
    plt.style.use('dark_background')
    # Defining the top folder containing all the subfolders with the observations.
    path = f'mypath/{harpnum}/'

    # Defining the levels.
    levels=[-1e17,-5e16,-1e16,-5e15,0,5e15,1e16,5e16,1e17]

    # Taking the images paths and trimming the images that are too close to the limb.
    sn_files = sorted(glob(f'{path}Sn/*.npy'))[213:-213]
    bp_files = sorted(glob(f'{path}By/*.npy'))[213:-213]
    bt_files = sorted(glob(f'{path}Bx/*.npy'))[213:-213]
    vn_files = sorted(glob(f'{path}W0/*.npy'))[213:-213]

    # Saving the number of frames.
    n_frames = len(sn_files)

    # Loading the first data.
    s = np.load(sn_files[0])

    # Loading the images and filtering the values of interest based on Sn.
    # Note that the array is also flatenned in the proccess so we can produce 
    # a scatter plot between bt2 and vn.
    bt2 = np.multiply(np.sqrt(np.add(np.power(np.load(bp_files[0]),2),np.power(np.load(bt_files[0]),2))), np.add((s > 5e15).astype(int),(s < -5e15).astype(int))).flatten()
    bt2 = np.delete(bt2,np.argwhere(bt2 == 0))
    vn = np.multiply(np.load(vn_files[0]), np.add((s > 5e15).astype(int),(s < -5e15).astype(int))).flatten()
    vn = np.delete(vn,np.argwhere(vn == 0))

    # Creating the figure objects.
    fig, ax = plt.subplots(nrows=1,ncols=1,figsize=(14,8))

    # Setting the images
    ax.set_xlim(0,2000)
    ax.set_ylim(-1,1)
    ax.scatter([],[])

    plt.tight_layout()

    def refresher(frame_number):
        '''
        description
        '''
        print(f'Current frame: {frame_number}/{n_frames}')

        # Loading the new data.
        new_sn = np.load(sn_files[frame_number])

        new_bt2 = np.multiply(np.sqrt(np.add(np.power(np.load(bp_files[frame_number]),2),np.power(np.load(bt_files[frame_number]),2))), np.add((new_sn > 5e15).astype(int),(new_sn < -5e15).astype(int))).flatten()
        new_bt2 = np.delete(new_bt2,np.argwhere(new_bt2 == 0))

        new_vn = np.multiply(np.load(vn_files[frame_number]), np.add((new_sn > 5e15).astype(int),(new_sn < -5e15).astype(int))).flatten()
        new_vn = np.delete(new_vn,np.argwhere(new_vn == 0))

        # Creating the new colourmap.
        new_sn_map = np.multiply(new_sn, np.add((new_sn > 5e15).astype(int),(new_sn < -5e15).astype(int))).flatten()
        new_sn_map = np.delete(new_sn_map,np.argwhere(new_sn_map == 0))

        print(len(new_sn_map))

        # Setting the new data.
        ax.scatter(new_bt2,new_vn,s=2,c=new_sn_map,cmap='PRGn',vmin=levels[0],vmax=levels[-1])

        return(fig,)

    ani = FuncAnimation(fig, refresher, frames=range(n_frames), blit=True,)
    ani.save(f"mypath/{harpnum}_scatter_test.mp4",fps=10)
    plt.close()
    return

我错过了什么让处理每个循环的时间升级?它实际上可以优化还是只是积累了太多信息?

编辑:我一直在运行一些测试,虽然运行该refresher功能的时间在 0.33 秒左右保持稳定,但每次添加新帧所需的时间增加了大约 1 秒。

谢谢

标签: pythonmatplotlib

解决方案


推荐阅读