手记

python中plot实现即时数据动态显示方法

本人同类型博客(新鲜的哦!)matplotlib animation 绘制动画: 数据收集(产生)完成后,再生成动态显示。一般用于成果展示。生成各种格式的视频,gif动态图等。

本篇方法的特点:用于 实时 监测系统,实时 数据可视化,一般用于系统调试过程。因此,matplotlib animation 绘制动画不能完全取代本篇博客。


Matlab使用Plot函数实现数据动态显示方法总结中介绍了两种实现即时数据动态显示的方法。考虑到使用python的人群日益增多,再加上本人最近想使用python动态显示即时的数据,网上方法很少,故总结于此。本人主要在jupyter notebook作为交互式的python运行环境,但考虑不使用jupyter notebook的情况。所以下面主要分成针对jupyter notebook环境的增量式数据动态显示方法,与通用的(jupyter notebook 与非juypter notebook都适用)方法两大类。先介绍通用的方法,后介绍针对jupyter notebook的方法。接着给出一个更加实用的简单例子,希望可以给大家更多的启发。最后对博友运行本程序时遇到的问题做一个总结,并给出解决方法。

1. 通用的方法

1.1 需要保存历史数据


示例代码1-1

import matplotlib.pyplot as plt

import numpy as np

import time

from math import *


plt.ion() #开启interactive mode 成功的关键函数

plt.figure(1)

t = [0]

t_now = 0

m = [sin(t_now)]


for i in range(2000):

plt.clf() #清空画布上的所有内容

    t_now = i*0.1

    t.append(t_now)#模拟数据增量流入,保存历史数据

    m.append(sin(t_now))#模拟数据增量流入,保存历史数据

    plt.plot(t,m,'-r')

    plt.draw()#注意此函数需要调用

    time.sleep(0.01)

备注:此代码经过很多人测试发现不能呈现动态效果(我原本在ubuntu系统上是可以的,经验证在windows上也不行),特在此说明,如果出不了动态效果,就将

plt.draw()

time.sleep(0.01)

替换为:

plt.pause(0.01)


1.2 无需保存数据


示例代码1-2

import matplotlib.pyplot as plt

import numpy as np

import time

from math import *


plt.ion() #开启interactive mode 成功的关键函数

plt.figure(1)

t = [0]

t_now = 0

m = [sin(t_now)]


for i in range(2000):

# plt.clf() # 清空画布上的所有内容。此处不能调用此函数,不然之前画出的点,将会被清空。

    t_now = i*0.1

    """

    由于第次只画一个点,所以此处有两种方式,第一种plot函数中的样式选

    为点'.'、'o'、'*'都可以,就是不能为线段'-'。因为一条线段需要两

    个点才能确定。第二种方法是scatter函数,也即画点。

    """

    plt.plot(t_now,sin(t_now),'.') # 第次对画布添加一个点,覆盖式的。

    # plt.scatter(t_now, sin(t_now)) 


    plt.draw()#注意此函数需要调用

    time.sleep(0.01)

1.3 无需保存数据(进阶版)

以上是动态的显示一个函数,也即直观上一条轨迹不断的延伸。这是一种应用,另一种应用是在一张画布上增量式的画多条轨迹(函数)。


示例代码1-3

import matplotlib.pyplot as plt

import numpy as np

import time

from math import *

 

plt.ion() #开启interactive mode 成功的关键函数

plt.figure(1)

t = np.linspace(0, 20, 100)



 

for i in range(20):

# plt.clf() # 清空画布上的所有内容。此处不能调用此函数,不然之前画出的轨迹,将会被清空。

    y = np.sin(t*i/10.0)

    plt.plot(t, y) # 一条轨迹

    plt.draw()#注意此函数需要调用

    time.sleep(1)

2. Jupyter notebook版本

也对应三种应用:需要保存历史数据,无需保存历史数据,无需保存历史数据进阶版。

注意:在Jupyter notebook中显示python的画图程序时,需要添加%matplotlib inline,但是身边有人运行本博客中的程序时会出现无法正常显示动态图片的情况,并且本人在自己电脑windows 10环境下(python 3.6)运行本文中动态显示图片的程序时,也会出现上述情况。出现该情况,只需要将程序中出现的所有inline改为qt5,例如%matplotlib inline改为%matplotlib qt5,以及is_ipython = 'inline' in matplotlib.get_backend()改为is_ipython = 'qt5' in matplotlib.get_backend()即可。基于QT的图形显示界面会跳出jupyter notebook显示动态图,而且会多出许多可选的按钮。大家可以自行探索。建议大家,先运行本文的程序,如果不成功,再做此改变。因为,原本inline成功的,改为qt5后,可能反而不成功。

2.1 需要保存历史数据


示例代码2-1

上面的方式,可以在跳出的画图面板内动态显示,但是如果想在jupyter notebook中直接动态显示,上面的方法将无效。因此,补上在jupyter notebook中可行的动态显示示例程序。以供举一反三之用。

import math

import random

import numpy as np

import matplotlib

import matplotlib.pyplot as plt

%matplotlib inline


# set up matplotlib

is_ipython = 'inline' in matplotlib.get_backend()

if is_ipython:

    from IPython import display


plt.ion()


def plot_durations(y):

    plt.figure(2)

    plt.clf()

    plt.subplot(211)

    plt.plot(y[:,0])

    plt.subplot(212)

    plt.plot(y[:,1])


    plt.pause(0.001)  # pause a bit so that plots are updated

    if is_ipython:

        display.clear_output(wait=True)

        display.display(plt.gcf())

        

x = np.linspace(-10,10,500)

y = []

for i in range(len(x)):

    y1 = np.cos(i/(3*3.14))

    y2 = np.sin(i/(3*3.14))

    y.append(np.array([y1,y2])) #保存历史数据

    plot_durations(np.array(y))

2.2 无需保存历史数据


示例代码2-2

import math

import random

import numpy as np

import matplotlib

import matplotlib.pyplot as plt

%matplotlib inline


# set up matplotlib

is_ipython = 'inline' in matplotlib.get_backend()

if is_ipython:

    from IPython import display


plt.ion()


def plot_durations(i, y1, y2):

    plt.figure(2)

#     plt.clf() 此时不能调用此函数,不然之前的点将被清空。

    plt.subplot(211)

    plt.plot(i, y1, '.')

    plt.subplot(212)

    plt.plot(i, y2, '.')


    plt.pause(0.001)  # pause a bit so that plots are updated

    if is_ipython:

        display.clear_output(wait=True)

        display.display(plt.gcf())

        

x = np.linspace(-10,10,500)

y = []

for i in range(len(x)):

    y1 = np.cos(i/(3*3.14))

    y2 = np.sin(i/(3*3.14))

#     y.append(np.array([y1,y2])) #保存历史数据

    plot_durations(i, y1, y2)

2.3 无需保存历史数据(进阶版)


示例代码2-3

import math

import random

import numpy as np

import matplotlib

import matplotlib.pyplot as plt

%matplotlib inline


# set up matplotlib

is_ipython = 'inline' in matplotlib.get_backend()

if is_ipython:

    from IPython import display


plt.ion()


def plot_durations(y1, y2):

    plt.figure(2)

#     plt.clf()

    plt.subplot(211)

    plt.plot(x, y1)

    plt.subplot(212)

    plt.plot(x, y2)


    plt.pause(0.001)  # pause a bit so that plots are updated

    if is_ipython:

        display.clear_output(wait=True)

        display.display(plt.gcf())




x = np.linspace(-10,10,500)

for i in range(100):

    y1 = np.cos(x*i/(3*3.14))

    y2 = np.sin(x*i/(3*3.14))

    plot_durations(y1, y2)

3. 一个较为实际的应用示例——简单的机器人仿真环境

视频是由一系例图片按时间顺序排列组成的。即然能够基于以上程序实现简单的动态显示,进一步的,我们可以利用本文的代码片段构建自己的简易仿真环境,用于初步验证算法。下面的gif图就是利用本文的代码片验证了一个简单的机器人全局——局部两层路径规划算法。相信大家能够根据自己的应用背景,得到不同的有意思的动态显示结果。

其中,蓝色圆圈为机器人,黑色为障碍物(有动态与静态两种),红圏表示机器人要到达的目标点,绿色三角形表示机器人当前局部的目标点(由算法根据当前环境与机器人的状态计算得到),最终的运行轨迹会以红线显示。

4. 问题与解决

为了节省大家的时间,这部分主要收集大家运行以上程序时遇到的问题,并给出解决方案。如果运行以上程序发现运行异常,按以下两步修改

  1. plt.draw()  time.sleep(0.01)替换为plt.pause(0.01)运行,看是否正常。

  2. 如果还不行,就把plt.pause(0.01)也注释掉再运行。

博客中的示例程序都是本人在某些系统上运行成功的,如果某一行代码导致程序在你的系统上运行失败,并不是说这一行代码完全是多余的。经过我测试,示例程序2-1如果注释了plt.pause(0.01),以及%matplotlib inline(有时我们不小心用了这个程序,又想让动态图单独跳出一个窗口运行),我在ubuntu 14.04上的测试结果是显示不了图。但是,我重新用上暂停函数plt.pause(0.01),程序就能正常在跳出的窗口显示动态图了。建议先直接运行示例程序,如果错误再按要求修改,没有错误就不用修改。


作者:windSeS
链接:https://juejin.cn/post/6971312701041541150
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


0人推荐
随时随地看视频
慕课网APP