如何为Matplotlib中的颜色栏设置动画 [英] How to animate the colorbar in matplotlib

查看:107
本文介绍了如何为Matplotlib中的颜色栏设置动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动画,其中数据范围变化很​​大.我想有一个colorbar来跟踪数据的最大值和最小值(即我希望它不固定).问题是如何做到这一点.

I have an animation where the range of the data varies a lot. I would like to have a colorbar which tracks the max and the min of the data (i.e. I would like it not to be fixed). The question is how to do this.

理想情况下,我希望colorbar位于其自身的轴上.

Ideally I would like the colorbar to be on its own axis.

我尝试了以下四件事

问题:每帧都会绘制一个新的彩条

The problem: A new colorbar is plottet for each frame

#!/usr/bin/env python
"""
An animated image
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig = plt.figure()
ax = fig.add_subplot(111)


def f(x, y):
    return np.exp(x) + np.sin(y)

x = np.linspace(0, 1, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)

frames = []

for i in range(10):
    x       += 1
    curVals  = f(x, y)
    vmax     = np.max(curVals)
    vmin     = np.min(curVals)
    levels   = np.linspace(vmin, vmax, 200, endpoint = True)
    frame    = ax.contourf(curVals, vmax=vmax, vmin=vmin, levels=levels)
    cbar     = fig.colorbar(frame)
    frames.append(frame.collections)

ani = animation.ArtistAnimation(fig, frames, blit=False)

plt.show()

2.添加到图像

将上面的for循环更改为

2. Adding to the images

Changing the for loop above to

initFrame = ax.contourf(f(x,y)) 
cbar      = fig.colorbar(initFrame)
for i in range(10):
    x       += 1
    curVals  = f(x, y)
    vmax     = np.max(curVals)      
    vmin     = np.min(curVals)      
    levels   = np.linspace(vmin, vmax, 200, endpoint = True)
    frame    = ax.contourf(curVals, vmax=vmax, vmin=vmin, levels=levels)
    cbar.set_clim(vmin = vmin, vmax = vmax)
    cbar.draw_all()
    frames.append(frame.collections + [cbar])

问题:这引起了

AttributeError: 'Colorbar' object has no attribute 'set_visible'

3.在自己的轴上绘制

问题:colorbar未更新.

 #!/usr/bin/env python
 """
 An animated image
 """
 import numpy as np
 import matplotlib.pyplot as plt
 import matplotlib.animation as animation

 fig = plt.figure()
 ax1 = fig.add_subplot(121)
 ax2 = fig.add_subplot(122)


 def f(x, y):
     return np.exp(x) + np.sin(y)

 x = np.linspace(0, 1, 120)
 y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)

 frames = []

 for i in range(10):
     x       += 1
     curVals  = f(x, y)
     vmax     = np.max(curVals)
     vmin     = np.min(curVals)
     levels   = np.linspace(vmin, vmax, 200, endpoint = True)
     frame    = ax1.contourf(curVals, vmax=vmax, vmin=vmin, levels=levels)
     cbar     = fig.colorbar(frame, cax=ax2) # Colorbar does not update
     frames.append(frame.collections)

 ani = animation.ArtistAnimation(fig, frames, blit=False)

 plt.show()

2和4的组合.

问题:colorbar是常量.

此处,但OP似乎对固定的colorbar感到满意.

A similar question is posted here, but it looks like the OP is satisfied with a fixed colorbar.

推荐答案

虽然我不确定如何专门使用ArtistAnimation来做到这一点,但是使用FuncAnimation还是很简单的.如果我对您的原始"版本1进行了以下修改,则它可以正常工作.

While I'm not sure how to do this specifically using an ArtistAnimation, using a FuncAnimation is fairly straightforward. If I make the following modifications to your "naive" version 1 it works.

修改后的版本1

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.axes_grid1 import make_axes_locatable

fig = plt.figure()
ax = fig.add_subplot(111)

# I like to position my colorbars this way, but you don't have to
div = make_axes_locatable(ax)
cax = div.append_axes('right', '5%', '5%')

def f(x, y):
    return np.exp(x) + np.sin(y)

x = np.linspace(0, 1, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)

frames = []
for i in range(10):
    x       += 1
    curVals  = f(x, y)
    frames.append(curVals)

cv0 = frames[0]
cf = ax.contourf(cv0, 200)
cb = fig.colorbar(cf, cax=cax)
tx = ax.set_title('Frame 0')

def animate(i):
    arr = frames[i]
    vmax     = np.max(arr)
    vmin     = np.min(arr)
    levels   = np.linspace(vmin, vmax, 200, endpoint = True)
    cf = ax.contourf(arr, vmax=vmax, vmin=vmin, levels=levels)
    cax.cla()
    fig.colorbar(cf, cax=cax)
    tx.set_text('Frame {0}'.format(i))

ani = animation.FuncAnimation(fig, animate, frames=10)

plt.show()

主要区别在于,我在函数中执行关卡计算和轮廓绘制,而不是创建艺术家列表.颜色条之所以起作用,是因为您可以清除上一帧中的轴,并在每帧中重做.

The main difference is that I do the levels calculations and contouring in a function instead of creating a list of artists. The colorbar works because you can clear the axes from the previous frame and redo it every frame.

使用contourcontourf时,必须执行此重做,因为您不能只是动态地更改数据.但是,当您绘制了许多轮廓线并且结果看起来很平滑时,我认为使用imshow可能会更好-这意味着您实际上可以只使用同一位艺术家并更改数据,并且颜色栏会自动更新.它也快得多!

Doing this redo is necessary when using contour or contourf, because you can't just dynamically change the data. However, as you have plotted so many contour levels and the result looks smooth, I think you may be better off using imshow instead - it means you can actually just use the same artist and change the data, and the colorbar updates itself automatically. It's also much faster!

更好的版本

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.axes_grid1 import make_axes_locatable

fig = plt.figure()
ax = fig.add_subplot(111)

# I like to position my colorbars this way, but you don't have to
div = make_axes_locatable(ax)
cax = div.append_axes('right', '5%', '5%')

def f(x, y):
    return np.exp(x) + np.sin(y)

x = np.linspace(0, 1, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)

# This is now a list of arrays rather than a list of artists
frames = []
for i in range(10):
    x       += 1
    curVals  = f(x, y)
    frames.append(curVals)

cv0 = frames[0]
im = ax.imshow(cv0, origin='lower') # Here make an AxesImage rather than contour
cb = fig.colorbar(im, cax=cax)
tx = ax.set_title('Frame 0')

def animate(i):
    arr = frames[i]
    vmax     = np.max(arr)
    vmin     = np.min(arr)
    im.set_data(arr)
    im.set_clim(vmin, vmax)
    tx.set_text('Frame {0}'.format(i))
    # In this version you don't have to do anything to the colorbar,
    # it updates itself when the mappable it watches (im) changes

ani = animation.FuncAnimation(fig, animate, frames=10)

plt.show()

这篇关于如何为Matplotlib中的颜色栏设置动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆