【问题标题】:How to update pcolor in matplotlib?如何在 matplotlib 中更新 pcolor?
【发布时间】:2013-04-06 04:59:28
【问题描述】:

我用 pcolor 绘制二维数组中的信息。但是,数组中的信息在迭代过程中会发生变化,我想动态更新颜色图,以便实时可视化变化。我怎样才能以最简单的方式做到这一点?

编辑 - 示例:

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
  • 你能用imshow代替pcolor吗?
  • 您能否发布一个关于您正在做什么以及任何(部分)工作代码的最小示例?它可以更轻松地为您提供帮助。
  • 谢谢,但我想用“pcolor”命令来做。我也可以使用 imshow。
  • 为什么? imshow 有一个更新数据的简单方法,pcolor 返回一个 PolyCollection,这有点难以更新

标签: python matplotlib plot


【解决方案1】:

您可以将事件连接到您的图形并在该事件上调用特定函数。下面我以matplotlib 文档为例,并添加了一个函数ontype。当在键盘上按下1 时调用它。然后X * func3() 被调用。 Ontype 绑定到带有fig.canvas.mpl_connect('key_press_event',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()

【讨论】:

    【解决方案2】:

    我建议使用imshow (doc):

    # 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() 
    

    【讨论】:

    • 谢谢很好,点赞和接受更好;)(另见编辑重新颜色条)
    • 最后一个问题:如何限制 x 和 y 轴? imshow 不允许我写 imshow(X,Y,T) 而只能写 imshow(T)。
    • 你想使用extentkwarg
    • hmmm...你说 imshow 应该为我做颜色映射。然而它不会发生,颜色不会随着时间而改变。我应该写一些命令来更新它吗?
    • @user1767774 您可能需要在循环中使用plt.pause() 以确保画布实际更新。除此之外,使用您正在使用的代码发布一个新的。
    【解决方案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 ... 开头的行替换了它们。它只是更新数据而不计算新的 facecolors。最后一种方法更简单,也同样有效。不需要转置数据数组。

    【讨论】:

    • 您所需要的只是meshData.update({"array":C.ravel()})(以及某种绘图调用),但这应该是人们现在使用和参考的答案。 FWIW,我运行了一些基本的计时,更新功能比我简单的 100x100 测试用例的原始 pcolormesh 调用快约 50-100 倍。一个更好的答案可能会被简化以删除额外的电影相关代码工作(虽然我也从电影代码中学到了,所以谢谢。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-28
    • 1970-01-01
    • 2015-01-21
    • 2011-03-03
    • 1970-01-01
    • 2015-01-20
    相关资源
    最近更新 更多