实时散点图每2秒从Firebase获取数据

时间:2019-03-22 06:49:05

标签: python firebase matplotlib scatter-plot

我有一个移动应用程序,该应用程序进行一些计算并抛出x,y坐标,并且每2秒在firebase上进行更新。

接下来,我希望将这些坐标实时绘制在平面图上。为此,我在平面图上使用了散点图。但是,一旦获取数据,我将无法立即启用它。

这是到目前为止的代码:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation

xs = []
ys = []
fig = plt.figure()
scat = plt.scatter(xs, ys, c='r', s=100)


def main():
    graph_data = open("testfile.txt","r").read()
    lines = graph_data.split("\n")


    for line in lines:
        if len(line)>1:
            x,y = line.split(",")
            xs.append(x)
            ys.append(y)

    plt.scatter(xs,ys)
    print(xs)
    print(ys)


ani = animation.FuncAnimation(fig,main(),fargs=(scat))
plt.show()

遇到animation.FuncAnimation TypeError: NoneType object argument after * must be an iterable, not PathCollection

错误

2 个答案:

答案 0 :(得分:0)

在更新主图中的图形时,您可以在单独的线程中获取数据。这是一个完整的工作示例:

#!/usr/bin/env python3
import time

from queue import Queue
from threading import Thread, Event

import numpy as np
import matplotlib.pyplot as plt


FETCH_DELAY = 2


def fetch_data(queue, stop):

    while not stop.is_set():
        x, y = np.random.randn(2)
        queue.put((x, y))
        time.sleep(FETCH_DELAY)


def limits(array, offset=1):
    return array.min() - offset, array.max() + offset


def main():
    stop = Event()
    queue = Queue()

    worker = Thread(target=fetch_data, args=(queue, stop))
    worker.start()

    plt.ion()
    fig, ax = plt.subplots()
    plot = ax.scatter([], [])

    try:

        while True:
            data = queue.get()

            data = np.array(data)
            plt_data = plot.get_offsets()
            plt_data = np.vstack((plt_data, data))
            plot.set_offsets(plt_data)
            fig.canvas.draw()

            xmin, xmax = limits(plt_data[:, 0])
            ymin, ymax = limits(plt_data[:, 1])

            ax.set_xlim(xmin, xmax)
            ax.set_ylim(ymin, ymax)

            queue.task_done()

    except KeyboardInterrupt:
        pass
    finally:
        stop.set()
        worker.join()


if __name__ == '__main__':
    main()

将其另存为plot_update.py文件并从命令行运行它:

python3 plot_update.py

答案 1 :(得分:0)

这是不使用线程的解决方案,它变得非常简单:

import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
from firebase import firebase

firebase = firebase.FirebaseApplication('Firebase url', None)

fig, ax = plt.subplots()
x, y = [],[]
sc = ax.scatter(x,y,c=np.random.rand(3,))
plt.xlim(12,13)
plt.ylim(77,78)

def animate(i):
    xs = firebase.get('/Lat',None)
    ys = firebase.get('/Long',None)
    xs = round(xs,2)
    ys = round(ys,2)
    file = open("testfile.txt","a+")
    file.write("{0},{1} \n".format(xs,ys))
    file.close()
    graph_data = open("testfile.txt","r").read()
    lines = graph_data.split("\n")
    for line in lines:
        if len(line)>1:
            xs,ys = line.split(",")
            x.append(xs)
            y.append(ys)
            sc.set_offsets(np.c_[x,y])

ani = matplotlib.animation.FuncAnimation(fig, animate, 
                frames=2, interval=500, repeat=True) 
plt.show()