需要帮助来解决Raspberry Pi上的matplotlib的性能问题

时间:2016-02-25 14:01:53

标签: python numpy matplotlib web2py

首先,抱歉这篇长篇文章。我是python和matplotlib的新手,所以请耐心等待。

作为对此question的后续跟踪,我发现使用web2py在Raspberry Pi上生成网格相当耗时。我有一个大约12k行的csv文件,如下所示:

1;1.0679759979248047;0.0;147.0;0.0;;{'FHR1': 'US', 'FHR2': 'INOP', 'MHR': 'INOP'};69;good;;;;1455891539.502167

问题是,用numpy.genfromtxt读取那些12k行已经需要30秒。然后填充图表(没有花哨的网格)又花了30秒,只使用那个csv的第1,3和7列。但加入解决方案后,时间爆炸到170秒。所以现在我必须弄清楚如何将时间消耗减少到不到一分钟的时间。

我的第一个想法是消除csv - 无论如何我都是读取数据的人,所以我可以通过将数据保存在内存中或者立即将其写入绘图来跳过它。这就是我所做的,用(在我看来)简单的测试布局和使用pdf后端。我选择在每次获取数据时将数据写入图表,并在传输完成后保存图表。我认为应该可以正常工作,而且它不会。我一直有可笑的错误:

  

RuntimeError:RRuleLocator估计从0001-01-01 15:20:31.883239 + 00:00到0001-04-17 20:52:39.779205 + 00:00:生成9178327刻度超过Locator.MAXTICKS * 2(6000000 )

并且相信我,我会在每次测试运行时不断增加这些maxticks,以达到错误消息所说的数字。这很荒谬,因为该消息只是60秒的数据,我想要在24 小时的数据附近。我要么想要RRuleLocator停止估计,要么只是闭嘴并等待数据结束。我真的不认为我可以用这个来制作MCVE,但是我可以把我最容易搞砸的细节弄清楚。

首先,我设置了一些类,所以没有全局变量。为了简化,我有一个通信类,它以一秒的间隔读取串行端口。这运行正常,直到昨天将串口上的任何内容写入csv。现在我想看看我是否可以在获取数据时填充图表,并在我完成后立即保存。因此,对于测试,我将其添加到我的.py

import matplotlib
matplotlib.use('PDF')    # I want a PDF in the end
from matplotlib import dates
import matplotlib.pyplot as plt
import numpy as np
from numpy import genfromtxt
然后一些成员来到通信类,即来自图表部分,主要是上面提到的解决方案。我在类 init

中初始化它们
    self.fig = None
    self.ctg = None
    self.toco = None

然后我调用了这个方法,一旦我觉得收到的数据的格式/状态正确,那么图表可能会准备填充数据

def prepchart(self):
    # how often to show xticklabels and repeat yticklabels:
    print('prepchart')
    xtickinterval = 5

    hfmt = dates.DateFormatter('%H:%M:%S')
    self.fig = plt.figure()

    self.ctg = self.fig.add_subplot(2, 1, 1)  # two rows, one column, first plot
    plt.ylim(50, 210)

    self.toco = self.fig.add_subplot(2, 1, 2)
    plt.ylim(0, 100)
    # Set the minor ticks to every 30 seconds
    minloc = dates.SecondLocator(bysecond=[0,30])
    minloc.MAXTICKS = 3000000 
    self.ctg.xaxis.set_minor_locator(minloc)
    # self.ctg.xaxis.set_minor_locator(dates.MinuteLocator())
    self.ctg.xaxis.set_major_formatter(hfmt)

    self.toco.xaxis.set_minor_locator(dates.MinuteLocator())
    self.toco.xaxis.set_major_formatter(hfmt)

    # actg.xaxis.set_ticks(rotation=45)
    plt.xticks(rotation=45)

然后,每当我想要绘制数据时,经常会在我的数据处理方法中执行此操作

 self.ctg.plot_date(timevalue, heartrate, '-')
 self.toco.plot_date(timevalue, toco, '-')

最后一旦不再发送数据(这可能是一分钟或24小时后),我会打电话

    def handleCTG(self):
        self.fig.savefig('/home/pi/test.pdf')

总结:我是否完全错误或者我的代码中只有错误?这是否真的可以减少生成图表的等待时间?

1 个答案:

答案 0 :(得分:1)

好的,所以这就是这笔交易。很明显,web2py运行起来非常紧张。这意味着没有那么多线程浮动,并且它肯定不会为我的小图表创建开始一个新线程。我有点注意到这一点,当我在Raspis任务管理器上跟踪CPU使用情况时,只看到了大约25%的东西。现在Raspberry Pi有4个内核......去做数学。首先,我在我的Raspi上运行web2py以外的脚本,并且,看,包括csv读取和图表渲染在内的整个过程只需要20秒。从那里开始(灵感来自How to run a task outside web2py and retrieve the output)它是一块蛋糕:使用记录良好的子流程用这个脚本调用一个新的python并完成。所以感谢任何想过这个想法的人。