基于Matplotlib/Python的动画线图

2024-04-18 02:57:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我很难让我的线图动画。在

背景:我正在开发一个可以处理模拟网络延迟的程序,我正在尝试绘制延迟曲线图,这样我就可以看到我的程序能够很好地跟上来自控制器的命令负载。在

我已经确定了我的身材:

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0,2), ylim = (-2,2))
line, = ax.plot([], [], lw=2)

设置init()animate()函数

^{pr2}$

然后在我的DelayedTask.process()函数中(我测量预期执行和实际执行之间的时间),我将值和索引附加到x,y列表中。在

delta =  self.time - datetime.now()
lock = threading.Lock()
lock.acquire()
x.append(len(x))
y.append(delta.total_seconds())
lock.release()

最后在程序的底部,我创建了动画函数。在

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=True)

不幸的是,图表显示出来了,但数字无法绘制。我在animate()函数中设置了一个断点,并且在delta中填充了列表,但是它不会在图上显示任何行。在

以下是完整代码:

import multiprocessing, requests, threading
import decimal
import random
import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc

from queue import Queue
from multiprocessing.dummy import Pool as ThreadPool
from threading import Thread
from datetime import datetime, timedelta

class WorkQueue:
    def __init__(self, threads=6):
        self.threads = threads

    def process(self, work):
        pool = ThreadPool(self.threads)
        results = pool.map(DelayedTask.process, work)
        pool.close()
        pool.join()

class DelayedTask:
    def __init__(self, func, delay, message):
        print("DelayTask.__init__: {0}".format((func.__name__, delay, message)))
        self.func = func
        self.time = datetime.now() + timedelta(milliseconds=delay)
        self.message = message

    def process(self):
        delta =  self.time - datetime.now()
        lock = threading.Lock()
        lock.acquire()
        x.append(len(x))
        y.append(delta.total_seconds())
        lock.release()
        if delta.total_seconds() > 0.01:
            print('DelayTask.Process: Sleeping {0} milliseconds\n'.format(round(delta.total_seconds() * 1000)))
            time.sleep(delta.total_seconds())
            self.func(self.message)


        elif delta.total_seconds() < 0.01 and delta.total_seconds() > 0:
            print('DelayTask.Process: Processing with {0} milliseconds remaining\n'.format(round(delta.total_seconds() * 1000)))
            self.func(self.message)
        else:
            print("DelayTask.Process: Processing task: {0} milliseconds late\n".format(round(delta.total_seconds() * -1000)))
            self.func(self.message)
        return True

    def __str__(self):
        return str((self.func.__name__, self.time, self.message))

def get(url):

    print("Requesting {0}".format(url))

    r = requests.get(url=url)
    print("get(url): Received response for {0} with Status Code {1}".format(url, r.status_code))

aggregatorq = multiprocessing.Queue()

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(0,2), ylim = (-2,2))
line, = ax.plot([], [], lw=2)

x = []
y = []

# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

def animate(i):
    line.set_data(x[i], y[i])
    return line,

def collector():
    bucket = []
    while len(bucket) <= 10:
        task = aggregatorq.get()
        print("collector: aggregating Tasks\n")
        bucket.append(DelayedTask(task['func'], task['delay'], task['message']))

        if(len(bucket) == 10):
            bucket.sort(key=lambda x: x.time, reverse=False)
            firsttask = bucket[0]
            firsttime =  firsttask.time - datetime.now()
            if firsttime.total_seconds() >= 0:
                print('collector: Sleeping {0} seconds until first task in bucket\n'.format(firsttime.total_seconds()))
                time.sleep(firsttime.total_seconds())
            queue = WorkQueue(10)
            queue.process(bucket)
            bucket.clear()

def controller():
    print("Starting Controller\n")
    finishtime = datetime.now() + timedelta(seconds=5)
    print("controller: Will finish at {0}\n".format(finishtime))

    sites = ["att", "google", "hulu", "msn", "yahoo", "gmail"]
    while True:
        if datetime.now() > finishtime:
            print("Controller Finished")
            return;
        else:
            pass
            print("{0} remaining in controller..".format(finishtime - datetime.now()))

        requestdelay = random.randint(1, 20)
        randomsite = random.randint(0, len(sites)-1)
        aggregatorq.put({'func': get, 'delay': requestdelay, 'message': 'http://www.{0}.com'.format(sites[randomsite])})

t = threading.Thread(target=controller)
t2 = threading.Thread(target=collector)

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)

def main():
    t.start()
    t2.start()
    plt.show()

if __name__ == '__main__':
    try:
        main()
    except keyboardInterrupt:
        print('Interrupted')
        t.join()
        t2.join()
        try:
            sys.exit(0)
        except SystemExit:
            os._exit(0)

Tags: theimportselfformatmessagedatetimebuckettime
1条回答
网友
1楼 · 发布于 2024-04-18 02:57:04

{cd1>是你的问题。使用语句

line.set_data(x[i], y[i])

每次调用update时,只为行分配一个数据点。因此,您看不到任何线,因为线只在数据点之间绘制。要解决此问题,请省去索引:

^{pr2}$

这样,所有收集到的数据都将被绘制出来。在

相关问题 更多 >