簡體   English   中英

使用 matplotlib 使用顏色條動畫散布 plot

[英]Animate scatter plot with colorbar using matplotlib

我花了很多時間嘗試為散點圖 plot 設置動畫,其中標記的顏色由數字定義。

以下是我的嘗試,雖然效果不錯,但並沒有按計划進行:

  • 在每個 animation 步驟之后,應刪除舊點。 相反,新點只是簡單地添加到 plot 上已有的點。
  • 顏色欄也應該根據值在每一步更新(就像時間文本一樣)。

但是,無論我做什么,都會產生一張空白圖表。 在動畫散布方面,這真的是我能用 python 做的最好的嗎?

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

time_steps = 50
N_nodes = 100

positions = []
solutions = []
for i in range(time_steps):
    positions.append(np.random.rand(2, N_nodes))
    solutions.append(np.random.random(N_nodes))

fig = plt.figure()
marker_size = 1
ax = fig.add_subplot(111, aspect='equal', autoscale_on=False, xlim=(0, 1), ylim=(0, 1))
time_text = ax.text(0.02, 0.95, '', transform=ax.transAxes)

def init():
    """ Initialize animation. """
    scat = ax.scatter(positions[0][0], positions[0][1], s = marker_size, c = solutions[0], cmap = "RdBu_r", marker = ".", edgecolor = None)
    fig.colorbar(scat)
    time_text.set_text('Time step = %d' % 0)

    return scat, time_text

def animate(i):
    """ Perform animation step. """
    scat = ax.scatter(positions[i][0], positions[i][1], s = marker_size, c = solutions[i], cmap = "RdBu_r", marker = ".", edgecolor = None)
    time_text.set_text('Time step = %d' % i)

    return scat, time_text

plt.xlabel('x [m]')
plt.ylabel('y [m]')
plt.grid(b=None)
plt.show()
ani = animation.FuncAnimation(fig, animate, interval=100, blit=True, repeat=True, init_func=init)

ani.save('animation.gif', writer='imagemagick', fps = 8)

我不確定您是否在帖子中指出了這一點,但我無法讓您的代碼按原樣運行。 但是,我認為主要問題與您提到的第一點有關:“在每個 animation 步驟之后,應刪除舊點。 ”在繪制 animation 時,您確實需要明確說明這一點。 目前,您的代碼正在重復為相同的Axes創建scatter 就像您要在 animation 之外執行此操作一樣,這將導致多組數據相互重疊。

我已經看到人們這樣做的兩種主要方式:要么使用 plot 的一些set_...方法來更新數據(參見此處的散點圖此處一般清除AxesFigure每次迭代以 plot 新數據. 我發現后者更容易/更普遍(如果更懶惰)。 這是您的示例的一種方法(我已編輯此代碼以刪除對plt.gridplt.label的調用,因為它們不起作用):

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

time_steps = 50
N_nodes = 100

positions = []
solutions = []
for i in range(time_steps):
    positions.append(np.random.rand(2, N_nodes))
    solutions.append(np.random.random(N_nodes))

fig, ax = plt.subplots()
marker_size = 5 #upped this to make points more visible

def animate(i):
    """ Perform animation step. """
    #important - the figure is cleared and new axes are added
    fig.clear()
    ax = fig.add_subplot(111, aspect='equal', autoscale_on=False, xlim=(0, 1), ylim=(0, 1))
    #the new axes must be re-formatted
    ax.set_xlim(0,1)
    ax.set_ylim(0,1)
    ax.grid(b=None)
    ax.set_xlabel('x [m]')
    ax.set_ylabel('y [m]')
    # and the elements for this frame are added
    ax.text(0.02, 0.95, 'Time step = %d' % i, transform=ax.transAxes)
    s = ax.scatter(positions[i][0], positions[i][1], s = marker_size, c = solutions[i], cmap = "RdBu_r", marker = ".", edgecolor = None)
    fig.colorbar(s)

ani = animation.FuncAnimation(fig, animate, interval=100, frames=range(time_steps))

ani.save('animation.gif', writer='pillow')

生成以下 GIF:

在此處輸入圖像描述

在這里,我使用fig.clear()來清除每一幀的colorbar條; 否則,其中許多將被繪制。 這意味着您每次都必須重新添加Axes和格式。 在其他情況下,使用ax.clear()可以很好並節省add_subplot的步驟。

然而,還有另一種方法可以做到這一點,如下此處 如果您有顏色條Axes的句柄,則可以清除它們(而不是清除整個Figure ),類似於分散 plot 軸:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

time_steps = 50
N_nodes = 100

positions = []
solutions = []
for i in range(time_steps):
    positions.append(np.random.rand(2, N_nodes))
    solutions.append(np.random.random(N_nodes))

# init the figure, so the colorbar can be initially placed somewhere
marker_size = 5
fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal', autoscale_on=False, xlim=(0, 1), ylim=(0, 1))
s = ax.scatter(positions[0][0], positions[0][1], s = marker_size, c = solutions[0], cmap = "RdBu_r", marker = ".", edgecolor = None)
cb = fig.colorbar(s)

# get the axis for the colobar
cax = cb.ax

def animate(i):
    """ Perform animation step. """
    # clear both plotting axis and colorbar axis
    ax.clear()
    cax.cla()
    #the new axes must be re-formatted
    ax.set_xlim(0,1)
    ax.set_ylim(0,1)
    ax.grid(b=None)
    ax.set_xlabel('x [m]')
    ax.set_ylabel('y [m]')
    # and the elements for this frame are added
    ax.text(0.02, 0.95, 'Time step = %d' % i, transform=ax.transAxes)
    s = ax.scatter(positions[i][0], positions[i][1], s = marker_size, c = solutions[i], cmap = "RdBu_r", marker = ".", edgecolor = None)
    fig.colorbar(s, cax=cax)

ani = animation.FuncAnimation(fig, animate, interval=100, frames=range(time_steps))

ani.save('animation2.gif', writer='pillow')

產生相同的圖形。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM