Python中的Matplotlib - 绘制形状及动画

5 投票
3 回答
4716 浏览
提问于 2025-04-15 18:18

我正在模拟一个令牌环网络(用SimPy进行模拟),对matplotlib完全是个新手,但有人告诉我,这个工具在可视化我的模拟方面非常好。

于是我在网上查了一下,发现可以通过add_patch和add_line来绘制形状和线条(我想是这样)。现在我得到了一个输出,效果还不错:

(还不能发图片!!)

http://img137.imageshack.us/img137/7822/screenshot20100121at120.png

但是我现在用pylab.show()这个函数得到的效果是这样的,而我想要的是用pylab.plot()这个函数来实现,这样在我的模拟进行时就可以用pylab.draw()来更新它。

我的代码如下:

plab.ion()

plab.axes()

for circ in self.circleList:
    plab.gca().add_patch(circ)

for line in self.lineList:
    plab.gca().add_line(line)

plab.axis('scaled')
plab.show()

其中circleList和lineList是包含图中圆和线的列表。

我可能在这里误解了一些简单的东西,但我找不到任何不是明显以图形为基础的例子来使用plot()函数。


补充说明:

我该如何用pylab.plot()来获得相同的输出,而不是用pylab.show()?

3 个回答

1

核心技巧是使用 set_data 来更新正在绘制的元素的数据。然后调用 draw()。看看你的圆形和线条元素是否有 set_data 函数。如果没有的话,你可以使用 pyvtk。另外一个选择是先绘制图形并保存为 png 文件,然后再从这些文件制作动画。

2

听起来Mark给出的答案正是你想要的,不过如果你决定采用whatnick的方法,从单独的png图片制作动画,这里有一段代码,可以用来实现Amit的建议,使用mencoder(来自http://en.wikibooks.org/wiki/Mplayer):

mencoder mf://*.png -mf w=400:h=400 -ovc lavc -lavcopts vcodec=xvid -of avi -o output.avi
4

使用绘图方法复制你的图像:

from pylab import *

points = []
points.append((-0.25, -1.0))
points.append((0.7, -0.7))
points.append((1,0))
points.append((0.7,1))
points.append((-0.25,1.2))
points.append((-1,0.5))
points.append((-1,-0.5))
points.append((-0.25, -1.0))

a_line = plot(*zip(*points))[0]
a_line.set_color('g')
a_line.set_marker('o')
a_line.set_markerfacecolor('b')
a_line.set_markersize(30)
axis([-1.5,1.5,-1.5,1.5])

show()

根据评论进行的编辑

这里使用了Python的多进程库,把matplotlib的动画放在一个单独的进程中运行。主进程通过一个队列把数据传递给它,然后更新绘图的图像。

# general imports
import random, time
from multiprocessing import Process, Queue

# for matplotlib
import random
import numpy as np
import matplotlib
matplotlib.use('GTKAgg') # do this before importing pylab

import matplotlib.pyplot as plt
from matplotlib.patches import Circle


def matplotLibAnimate(q,points):

    # set up initial plot
    fig = plt.figure()
    ax = fig.add_subplot(111)


    circles = []
    for point in points:
        ax.add_patch(Circle(point,0.1))

    a_line, = ax.plot(*zip(*points))
    a_line.set_color('g')
    a_line.set_lw(2)

    currentNode = None  
    def animate(currentNode = currentNode):
        while 1:
            newNode = q.get()
            if currentNode: currentNode.remove()
            circle = Circle(newNode,0.1)
            currentNode = ax.add_patch(circle)
            circle.set_fc('r')
            fig.canvas.draw()

    # start the animation
    import gobject
    gobject.idle_add(animate)
    plt.show()

#initial points
points = ((-0.25, -1.0),(0.7, -0.7),(1,0),(0.7,1),(-0.25,1.2),(-1,0.5),(-1,-0.5),(-0.25, -1.0))
q = Queue()
p = Process(target = matplotLibAnimate, args=(q,points,))
p.start()

# feed animation data
while 1:
    time.sleep(random.randrange(4))
    q.put(random.sample(points,1)[0])

当然,做完这些之后,我觉得你会更喜欢whatnick的图像解决方案。我会自己创建一个图形用户界面(GUI),而不是使用matplotlib自带的小部件。然后我会通过生成PNG图片并进行切换来“动画化”我的GUI。

撰写回答