如何在matplotlib中更新pcolor?

3
我使用pcolor绘制2D数组中的信息。但是,数组中的信息在迭代过程中会发生变化,我希望动态更新颜色映射,以便实时可视化更改。最简单的方法是什么?
编辑-示例:
from __future__ import division
from pylab import *
import random

n = 50 # number of iterations
x = arange(0, 10, 0.1)
y = arange(0, 10, 0.1)
T = zeros([100,100]) # 10/0.1 = 100
X,Y = meshgrid(x, y)

"""initial conditions"""
for x in range(100):
 for y in range(100):
  T[x][y] = random.random()

pcolor(X, Y, T, cmap=cm.hot, vmax=abs(T).max(), vmin=0)
colorbar()
axis([0,10,0,10])
show() # colormap of the initial array

"""main loop"""

for i in range(n):
 for x in range(100):
  for y in range(100):
   T[x][y] += 0.1 # here i do some calculations, the details are not important

 # here I want to update the color map with the new array (T)

谢谢


可能有帮助的内容10944621 - behzad.nouri
你可以使用imshow代替pcolor吗? - tacaswell
谢谢,但我想用“pcolor”命令来实现。我也可以使用imshow。 - user1767774
1
为什么?imshow有一个几乎微不足道的方法来更新数据,而pcolor则返回一个相对较难更新的 PolyCollection - tacaswell
作为一个侧面说明,你可以用 T += .1 替换掉你嵌套的循环(关于 xy 的循环)。 - tacaswell
显示剩余2条评论
3个回答

3

我这里有一个简单的例子,演示如何在模拟过程中更新ax.pcolor(或者它更快的表亲ax.pcolormesh)。

def make_movie(fig, meshData, conc, fout='writer_test.mp4',
           dpi=150, metadata={}):
    '''
    Make a movie (on disk) starting from a first image generated with matplotlib,
    by updating only the values that were dispayed with ax.pcolormesh(...).

    Parameters
    ----------
    meshData: mesh as returned by ax.pcolormesh()
    conc: obj returned by readUCN
        computed concentrations
    fout: str
        name of output file, with or without '.mp4' extension.
    dpi: int
        dots per inch of output movie
    metadata: dict
        passed on to FFMpegWriter.savings(fout, ...)
    '''
    plt.rcParams['animation.ffmpeg_path'] = '/usr/local/bin/ffmpeg'

    from matplotlib.animation import FFMpegWriter

    writer = FFMpegWriter(fps=15, metadata=metadata)

    totims = conc.totim # get times of computed concentrations

    with writer.saving(fig, fout, dpi):
        for totim in totims:
            C = conc.at_t(totim)[:, 0, :] # 3D -->  2D Xsection concentrations
            #newcolors = cmap(norm(C.ravel()))
            #meshData.update({'facecolors': newcolors})
            meshData.update({'array': C.ravel()}) # reset array to new conc.
            fig.canvas.draw_idle()
            writer.grab_frame()

#newcolors和#meshData.update开头的这些行按照上面@tacaswell提出的建议编写。以meshdata.udate({array ...开头的这一行则取代了它们。它只更新数据而不计算新的面颜色。最后的方法更简单,效果同样好。转置数据数组是不必要的。


你只需要使用meshData.update({"array":C.ravel()})(以及某种绘制调用),这应该是人们现在使用和参考的答案。顺便说一下,我进行了一些基本的计时测试,对于我的简单100x100测试案例,更新函数的速度大约是原始pcolormesh调用的50-100倍。一个更好的答案可能会简化掉额外的与电影相关的代码工作(尽管我也从电影代码中学到了东西,所以感谢它)。 - Ethan Gutmann

2

我建议使用imshow文档):

# figure set up
fig, ax_lst = plt.subplots(2, 1)
ax_lst = ax_lst.ravel()

#fake data
data = rand(512, 512)
x = np.linspace(0, 5, 512)
X, Y = meshgrid(x, x)

data2 = np.sin(X ** 2 + Y **2)
# plot the first time#fake data

im = ax_lst[0].imshow(data, interpolation='nearest', 
                            origin='bottom', 
                            aspect='auto', # get rid of this to have equal aspect
                            vmin=np.min(data),
                            vmax=np.max(data), 
                            cmap='jet')

cb = plt.colorbar(im)

pc = ax_lst[1].pcolor(data)
cb2 = plt.colorbar(pc)

要使用imshow更新数据,只需设置数据数组,它会为您处理所有规范化和颜色映射:

# update_data (imshow)
im.set_data(data2) 
plt.draw()

要使用pcolor实现相同的功能,您需要自己进行归一化和颜色映射(并猜测行优先还是列优先):
my_cmap = plt.get_cmap('jet')
#my_nom = # you will need to scale your read data between [0, 1]
new_color = my_cmap(data2.T.ravel())
pc.update({'facecolors':new_color})

draw() 

1
谢谢是好的,点赞和接受更好;)(还请参见关于colorbar的编辑) - tacaswell
最后一个问题:我如何限制 x 轴和 y 轴?imshow 不允许我写 imshow(X, Y, T),只能写成 imshow(T)。 - user1767774
你想要使用extent关键字参数。 - tacaswell
嗯...你说imshow应该为我做颜色映射。然而实际上并没有发生,颜色在时间上没有变化。我应该写一些命令来更新它吗? - user1767774
@user1767774 你可能需要在循环中使用plt.pause()来确保画布实际更新。除此之外,请发布一段包含你所使用代码的新帖子。 - tacaswell
https://dev59.com/-WvXa4cB1Zd3GeqPImSo#13802936 - tacaswell

1
你可以将事件连接到图形上,并在该事件上调用特定的函数。以下是从matplotlib文档中选取的示例,我添加了一个名为ontype的函数。当键盘上按下1时,它会被调用,然后调用X * func3()。使用fig.canvas.mpl_connect('key_press_event',ontype)ontype绑定到图形上。以类似的方式,您可以定期触发事件。
#!/usr/bin/env python
"""
See pcolor_demo2 for an alternative way of generating pcolor plots
using imshow that is likely faster for large grids
"""
from __future__ import division
from matplotlib.patches import Patch
from pylab import *

def ontype(event):
    ''' function that is called on key event (press '1')'''
    if event.key == '1':
        print 'It is working'
        fig.gca().clear()
        # plot new function X * func3(X, Y) 
        Z = X * func3(X, Y) 
        pcolor(X, Y, Z, cmap=cm.RdBu, vmax=abs(Z).max(), vmin=-abs(Z).max())
        fig.canvas.draw()

def func3(x,y):
    return (1- x/2 + x**5 + y**3)*exp(-x**2-y**2)


# make these smaller to increase the resolution
dx, dy = 0.05, 0.05

x = arange(-3.0, 3.0001, dx)
y = arange(-3.0, 3.0001, dy)
X,Y = meshgrid(x, y)

Z = func3(X, Y)

fig=figure(figsize=(16,8))

# connect ontype to canvas
fig.canvas.mpl_connect('key_press_event',ontype)

pcolor(X, Y, Z, cmap=cm.RdBu, vmax=abs(Z).max(), vmin=-abs(Z).max())
colorbar()
axis([-3,3,-3,3])

show()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接